Uh oh!
There was an error while loading. Please reload this page.
ci: 상용 배포용 태그 자동 생성 워크플로 추가 (Promote to Production) - #241
Conversation
git tag를 로컬에서 직접 만들고 push하는 게 번거롭다는 피드백에 따라, GitHub Actions workflow_dispatch로 버튼 한 번(또는 gh workflow run)에 다음 semver 태그를 계산해 생성/push하는 워크플로를 추가했다. 이 태그 push가 prod-cd.yml의 트리거(on.push.tags)를 실행시켜 상용 배포로 이어진다.
📝 WalkthroughWalkthroughThe PR adds a manually triggered production-promotion workflow. The workflow calculates and pushes the next semantic version tag. The README now documents workflow-based production promotion and the resulting ChangesProduction promotion
Estimated code review effort: 3 (Moderate) | ~20 minutes Sequence Diagram(s)sequenceDiagram
participant Operator
participant PromoteWorkflow
participant Repository
participant ProdCD
Operator->>PromoteWorkflow: Select version bump
PromoteWorkflow->>Repository: Read existing semantic version tags
Repository-->>PromoteWorkflow: Return latest tag
PromoteWorkflow->>Repository: Create and push next tag
Repository-->>ProdCD: Trigger production deployment
PromoteWorkflow-->>Operator: Record completion summary
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 5
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.github/workflows/promote-to-prod.yml:
- Around line 22-24: Add workflow-level concurrency configuration to
promote-to-prod.yml, using a shared group for production promotion runs and
setting cancel-in-progress to false so queued manual runs execute sequentially.
Keep the existing tag job unchanged.
- Around line 61-66: Update the checkout configuration used by the promote
workflow to set persist-credentials to false, then authenticate the git push in
the tag-generation step with a PAT or GitHub App token rather than GITHUB_TOKEN.
Ensure the tag push still targets the version from steps.version.outputs.new_tag
so the prod-cd.yml tag trigger runs.
- Around line 34-43: Validate LATEST against strict stable semver immediately
after selecting the latest tag and before assigning VERSION or parsing MAJOR,
MINOR, and PATCH. Reject non-matching tags, including values with build metadata
or other arithmetic-sensitive characters, while preserving the v0.0.0 fallback
for no matching tag.
- Around line 26-28: Update the actions/checkout step in the promote-to-prod
workflow from v3 to v7.0.1, ensuring it runs only on runners at v2.327.1 or
later. Preserve fetch-depth: 0 and pin the reviewed commit instead of the tag if
repository policy requires SHA-pinned actions.
- Around line 26-28: Update the workflow’s checkout step to explicitly use the
main ref and add a guard that stops promotion unless the selected ref is main.
Preserve fetch-depth: 0 and ensure the subsequent tagging and push steps only
run after this main-branch validation.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: ce2739db-48e6-4819-92cc-cb3b3b253e1b
📒 Files selected for processing (2)
.github/workflows/promote-to-prod.ymlREADME.md
| jobs: | ||
| tag: | ||
| runs-on: ubuntu-latest |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bashset -eu
file=".github/workflows/promote-to-prod.yml"printf'%s\n''--- workflow ---'
cat -n "$file"printf'%s\n''--- related workflow concurrency and tag references ---'
rg -n --glob '.github/workflows/**''concurrency:|cancel-in-progress|promote-to-prod|git tag|GITHUB_REF|github\.ref' .github/workflows ||trueRepository: Runnect/Runnect-Spring-Boot-Server
Length of output: 2847
🏁 Script executed:
#!/bin/bashset -eu
python3 - <<'PY'from pathlib import Pathimport retext = Path(".github/workflows/promote-to-prod.yml").read_text()assert re.search(r"(?m)^on:\s*$", text)assert re.search(r"(?m)^\s+workflow_dispatch:\s*$", text)assert not re.search(r"(?m)^concurrency:", text)tag_lines = re.search( r"(?ms)^\s+LATEST=\$\(git tag --list 'v\*'.*?^\s+NEW_TAG=\"v\$\{MAJOR\}\.\$\{MINOR\}\.\$\{PATCH\}\"", text,)assert tag_lines, "expected latest-tag and NEW_TAG logic was not found"def next_tag(latest, bump): major, minor, patch = map(int, latest.removeprefix("v").split(".")) if bump == "major": major, minor, patch = major + 1, 0, 0 elif bump == "minor": minor, patch = minor + 1, 0 elif bump == "patch": patch += 1 else: raise ValueError(bump) return f"v{major}.{minor}.{patch}"for bump in ("major", "minor", "patch"): latest = "v1.2.3" first_read = next_tag(latest, bump) second_read = next_tag(latest, bump) assert first_read == second_read print(f"{bump}: both runs read {latest!r} -> {first_read!r}; the second push targets the same tag")PYRepository: Runnect/Runnect-Spring-Boot-Server
Length of output: 415
Serialize production promotion runs.
Two manual runs can calculate the same next tag. The second git push then fails because the tag already exists. Add a workflow-level concurrency group with cancel-in-progress: false.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.github/workflows/promote-to-prod.yml around lines 22 - 24, Add
workflow-level concurrency configuration to promote-to-prod.yml, using a shared
group for production promotion runs and setting cancel-in-progress to false so
queued manual runs execute sequentially. Keep the existing tag job unchanged.
| - uses: actions/checkout@v3 | ||
| with: | ||
| fetch-depth: 0 |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bashset -e
printf'%s\n''--- workflow ---'
cat -n .github/workflows/promote-to-prod.yml
printf'%s\n''--- repository action references and runner versions ---'
rg -n --glob '*.yml' --glob '*.yaml''actions/checkout@|runs-on:|actionlint'.printf'%s\n''--- available actionlint ---'ifcommand -v actionlint >/dev/null 2>&1;then actionlint -version;elseecho'actionlint not installed';fiRepository: Runnect/Runnect-Spring-Boot-Server
Length of output: 2640
🌐 Web query:
GitHub actions/checkout latest release v6.0.2 runner requirements Node.js 24
💡 Result:
The actions/checkout version 6.0.2 uses the Node.js 24 runtime [1][2]. To support this runtime, a minimum GitHub Actions Runner version of v2.327.1 or later is required [1][2]. Additionally, if you use the persist-credentials feature in workflows involving Docker container actions, a minimum runner version of v2.329.0 or later is required to properly access the credentials stored in the runner's temporary directory [3][1][2].
Citations:
- 1: https://github.com/actions/checkout
- 2: https://git.liteyuki.org/actions/checkout/raw/branch/releases/v6/README.md
- 3: https://github.com/actions/checkout/tree/v6.0.2
🏁 Script executed:
#!/bin/bashset -u
printf'%s\n''--- checkout releases ---'
curl -fsSL https://api.github.com/repos/actions/checkout/releases/latest |
jq '{tag_name, name, published_at, html_url}'printf'%s\n''--- checkout v3 and v6 metadata ---'fortagin v3 v6;doprintf'%s\n'"[$tag]"
curl -fsSL "https://api.github.com/repos/actions/checkout/git/ref/tags/$tag"|
jq '{ref, object}'doneprintf'%s\n''--- repository policy files mentioning action pinning ---'
rg -n -i 'pin(ned|ning)?|commit sha|full[- ]length sha|actions/checkout|github actions' \
.github README.md CONTRIBUTING.md SECURITY.md 2>/dev/null ||trueprintf'%s\n''--- actionlint availability ---'ifcommand -v actionlint >/dev/null 2>&1;then
actionlint -version
elseecho'actionlint not installed'fiRepository: Runnect/Runnect-Spring-Boot-Server
Length of output: 1137
🏁 Script executed:
#!/bin/bashset +e
printf'%s\n''--- actionlint target workflow ---'
actionlint .github/workflows/promote-to-prod.yml
printf'%s\n''--- actionlint all workflows ---'
actionlint .github/workflows
printf'%s\n''--- checkout tags from the upstream repository ---'
git ls-remote --tags --refs https://github.com/actions/checkout.git 'v[0-9]*'|
tail -n 20Repository: Runnect/Runnect-Spring-Boot-Server
Length of output: 1778
🌐 Web query:
official actions/checkout v7.0.1 README runner requirements Node.js 24 GitHub Actions
💡 Result:
The official actions/checkout v7.0.1 action requires the GitHub Actions runner to be at version v2.327.1 or later to support the Node.js 24 runtime [1][2][3]. This requirement is explicitly stated in the action's documentation as a result of its migration to Node.js 24 [1][2]. While the action utilizes Node.js 24 for execution, the runner-level requirement ensures that the underlying infrastructure is compatible with this runtime version [4].
Citations:
- 1: https://github.com/actions/checkout/?tab=readme-ov-file
- 2: https://github.com/actions/checkout
- 3: https://git.lightless-sync.org/actions/checkout/raw/tag/v7.0.1/README.md
- 4: Update actions checkout to use node 24 actions/checkout#2226
Update actions/checkout@v3 to a supported major.
Use v7.0.1 only when the runner is version v2.327.1 or later. Pin the reviewed commit if repository policy requires SHA pins.
🧰 Tools
🪛 actionlint (1.7.12)
[error] 26-26: the runner of "actions/checkout@v3" action is too old to run on GitHub Actions. update the action's version to fix this issue
(action)
🪛 zizmor (1.29.0)
[warning] 26-28: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false
(artipacked)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.github/workflows/promote-to-prod.yml around lines 26 - 28, Update the
actions/checkout step in the promote-to-prod workflow from v3 to v7.0.1,
ensuring it runs only on runners at v2.327.1 or later. Preserve fetch-depth: 0
and pin the reviewed commit instead of the tag if repository policy requires
SHA-pinned actions.
Source: Linters/SAST tools
🔒 Security & Privacy | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bashset -eu
printf'%s\n''--- workflow ---'
cat -n .github/workflows/promote-to-prod.yml
printf'%s\n''--- related workflow references ---'
rg -n --hidden --glob '!node_modules''promote-to-prod|workflow_dispatch|actions/checkout@' .github README.md 2>/dev/null ||trueRepository: Runnect/Runnect-Spring-Boot-Server
Length of output: 3222
🌐 Web query:
GitHub Actions workflow_dispatch selected branch workflow file permissions github.ref actions/checkout default ref documentation
💡 Result:
To trigger a workflow using the workflow_dispatch event, the workflow file must exist on the repository's default branch [1][2][3]. However, once triggered, you can select any branch or tag to run the workflow against via the GitHub UI, CLI, or API [1][4][5]. Key points regarding branch selection and permissions: 1. Workflow File Availability: The workflow file itself must be present in the default branch to be discoverable and triggerable [1][2]. If you want to run a version of a workflow that exists only on a feature branch, it must first be merged into the default branch [6]. 2. Selecting the Ref: - GitHub UI: When manually triggering the workflow, a dropdown menu allows you to select the desired branch or tag [1][4]. - GitHub CLI: Use the --ref flag (e.g., gh workflow run WORKFLOW --ref BRANCH) [1][4]. - API: Provide the ref parameter in the request body [5]. 3. github.ref Context: The github.ref context variable represents the branch or tag that was selected and triggered the run [7][8]. For a branch, it is returned in the format refs/heads/<branch_name>, and for a tag, it is refs/tags/<tag_name> [7][8]. 4. actions/checkout Behavior: When using the actions/checkout action, if you do not specify a ref, it defaults to the branch or tag that triggered the workflow run (the value of github.ref) [9][10]. This ensures that the code checked out matches the branch/tag you selected in the UI/CLI/API [9][10]. 5. Permissions: Users must have write access to the repository to trigger a workflow_dispatch event [1]. No additional special permissions are required for the workflow itself to access different branches, provided the user has sufficient repository access to trigger it [1]. In summary, while the workflow definition is pinned to the default branch, the execution context (code version) is determined by the ref you select at runtime, which is automatically respected by the default behavior of actions/checkout [1][9].
Citations:
- 1: https://docs.github.com/actions/managing-workflow-runs/manually-running-a-workflow
- 2: https://docs.github.com/en/actions/how-tos/write-workflows/choose-when-workflows-run/trigger-a-workflow
- 3: https://docs.github.com/en/actions/reference/workflows-and-actions/workflow-syntax?use_case=
- 4: https://docs.github.com/en/actions/how-tos/manage-workflow-runs/manually-run-a-workflow?tool=webui
- 5: https://docs.github.com/en/rest/actions/workflows
- 6: https://stackoverflow.com/questions/72037313/use-selected-branch-on-workflow-dispatch-in-github-actions
- 7: https://docs.github.com/en/actions/reference/workflows-and-actions/variables
- 8: https://docs.github.com/en/actions/reference/workflows-and-actions/contexts
- 9: https://github.com/actions/checkout
- 10: https://github.com/actions/checkout/blob/cbb722410c2e876e24abbe8de2cc27693e501dcb/action.yml
🏁 Script executed:
#!/bin/bashset -eu
printf'%s\n''--- production workflow ---'
cat -n .github/workflows/prod-cd.yml
printf'%s\n''--- deployment documentation ---'
sed -n '160,195p' README.mdRepository: Runnect/Runnect-Spring-Boot-Server
Length of output: 5298
Restrict promotion to main.
workflow_dispatch allows a branch or tag selection. Without ref, actions/checkout checks out that selected ref. The subsequent git tag and push can therefore trigger production deployment from a non-main commit. Add a main guard and check out main explicitly.
Suggested fix
jobs:
tag:
+ if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
@@
with:
fetch-depth: 0
+ ref: main🧰 Tools
🪛 actionlint (1.7.12)
[error] 26-26: the runner of "actions/checkout@v3" action is too old to run on GitHub Actions. update the action's version to fix this issue
(action)
🪛 zizmor (1.29.0)
[warning] 26-28: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false
(artipacked)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.github/workflows/promote-to-prod.yml around lines 26 - 28, Update the
workflow’s checkout step to explicitly use the main ref and add a guard that
stops promotion unless the selected ref is main. Preserve fetch-depth: 0 and
ensure the subsequent tagging and push steps only run after this main-branch
validation.
| LATEST=$(git tag --list 'v*' --sort=-v:refname | head -n1) | ||
| if [ -z "$LATEST" ]; then | ||
| LATEST="v0.0.0" | ||
| fi | ||
| echo "현재 최신 태그: $LATEST" | ||
| VERSION=${LATEST#v} | ||
| MAJOR=$(echo "$VERSION" | cut -d. -f1) | ||
| MINOR=$(echo "$VERSION" | cut -d. -f2) | ||
| PATCH=$(echo "$VERSION" | cut -d. -f3) |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bashset -eu
printf'%s\n''--- workflow context ---'
sed -n '1,90p' .github/workflows/promote-to-prod.yml
printf'%s\n''--- arithmetic assignments and shell context ---'
rg -n -C 3 'MAJOR|MINOR|PATCH|VERSION|LATEST|shell:' .github/workflows/promote-to-prod.yml
printf'%s\n''--- standalone Bash behavior probe ---'
bash -c 'set -uprobe() { local version=$1 local major printf "VERSION=%q: " "$version" MAJOR=$(echo "$version" | cut -d. -f1) if MAJOR=$((MAJOR)); then printf "MAJOR=%s\n" "$MAJOR" else printf "arithmetic_status=%s\n" "$?" fi}probe "1.2.3"probe "08.2.3"probe "1+2.3.4"probe "1\$(printf injected).2.3"'Repository: Runnect/Runnect-Spring-Boot-Server
Length of output: 3433
🏁 Script executed:
#!/bin/bashset +e
printf'%s\n''--- Bash version ---'
bash --version | head -n 1
printf'%s\n''--- arithmetic-value probes ---'forvaluein \
'1+2' \
'1+$(printf COMMAND_SUBSTITUTION >&2)' \
'$(printf COMMAND_SUBSTITUTION >&2)' \
'1#$(printf COMMAND_SUBSTITUTION >&2)' \
'1;$(printf COMMAND_SUBSTITUTION >&2)' \
'1));$(printf COMMAND_SUBSTITUTION >&2);((0' \
'1[$(printf ARRAY_SUBSCRIPT >&2)]'doprintf'value=%q -> '"$value"
VALUE=$value bash -c ' set +e RESULT=$((VALUE + 1)) STATUS=$? printf "result=%q status=%s\n" "$RESULT" "$STATUS"'2>&1doneprintf'%s\n''--- candidate tag ref validation ---'forrefin \
'refs/tags/v1+2.3.4' \
'refs/tags/v1.2.3-100' \
'refs/tags/v1$(printf injected).2.3' \
'refs/tags/v1.2.3/extra' \
'refs/tags/v01.2.3'do
git check-ref-format "$ref">/dev/null 2>&1printf'%s: status=%s\n'"$ref""$?"doneRepository: Runnect/Runnect-Spring-Boot-Server
Length of output: 1734
Reject non-semver tags before Bash arithmetic.
git tag --list 'v*' accepts valid Git tags that are not stable semver. Values such as 1+2 are evaluated as arithmetic expressions, which can generate an incorrect tag or fail the release step. Validate LATEST against strict stable semver before parsing its components.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.github/workflows/promote-to-prod.yml around lines 34 - 43, Validate LATEST
against strict stable semver immediately after selecting the latest tag and
before assigning VERSION or parsing MAJOR, MINOR, and PATCH. Reject non-matching
tags, including values with build metadata or other arithmetic-sensitive
characters, while preserving the v0.0.0 fallback for no matching tag.
Source: Linters/SAST tools
| - name: 태그 생성 및 push (→ prod-cd.yml 트리거) | ||
| run: | | ||
| git config user.name "github-actions[bot]" | ||
| git config user.email "github-actions[bot]@users.noreply.github.com" | ||
| git tag "${{ steps.version.outputs.new_tag }}" | ||
| git push origin "${{ steps.version.outputs.new_tag }}" |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🔴 Critical | 🏗️ Heavy lift
🧩 Analysis chain
🏁 Script executed:
#!/bin/bashset -eu
printf'%s\n''--- workflow files ---'
git ls-files '.github/workflows/*''README.md'printf'%s\n''--- promote-to-prod.yml ---'
cat -n .github/workflows/promote-to-prod.yml
printf'%s\n''--- prod-cd.yml ---'
cat -n .github/workflows/prod-cd.yml
printf'%s\n''--- references to promote/prod-cd/tag push/token ---'
rg -n -i 'promote-to-prod|prod-cd|GITHUB_TOKEN|persist-credentials|tag push|tag 생성|workflow_dispatch|on:' .github README.mdRepository: Runnect/Runnect-Spring-Boot-Server
Length of output: 8403
🏁 Script executed:
#!/bin/bashset -eu
printf'%s\n''--- workflow files ---'
git ls-files '.github/workflows/*''README.md'printf'%s\n''--- promote-to-prod.yml ---'
cat -n .github/workflows/promote-to-prod.yml
printf'%s\n''--- prod-cd.yml ---'
cat -n .github/workflows/prod-cd.yml
printf'%s\n''--- related references ---'
rg -n -i 'promote-to-prod|prod-cd|GITHUB_TOKEN|persist-credentials|workflow_dispatch|tag 생성|tag push' .github README.mdRepository: Runnect/Runnect-Spring-Boot-Server
Length of output: 7506
🌐 Web query:
GitHub Actions documentation events triggered by GITHUB_TOKEN do not create new workflow runs actions/checkout persist-credentials default
💡 Result:
GitHub Actions is designed to prevent recursive workflow loops when using the default GITHUB_TOKEN. In general, events triggered by the GITHUB_TOKEN do not create new workflow runs [1][2][3]. There are a few key exceptions to this behavior: 1. Workflow Dispatch and Repository Dispatch: These events always trigger new workflow runs, even when initiated by the GITHUB_TOKEN [1][4]. 2. Pull Request Events (Opened, Synchronize, Reopened): When a workflow uses the GITHUB_TOKEN to create or update a pull request, the resulting event triggers workflow runs in an approval-required state [1][5]. These runs will not execute until a user with write access to the repository manually approves them [3][6]. Regarding the actions/checkout action, the persist-credentials input, which determines whether to configure the authentication token or SSH key in the local git configuration, has a default value of true [7][8][9]. While there have been community discussions and pull requests proposing to change this default to false to improve security, the official default remains true [7][10][11]. When set to true, the token is persisted in the local git config to enable authenticated git commands for that job, and it is removed during post-job cleanup [7][9].
Citations:
- 1: https://docs.github.com/en/actions/concepts/security/github_token
- 2: https://docs.github.com/en/actions/how-tos/write-workflows/choose-when-workflows-run/trigger-a-workflow
- 3: https://docs.github.com/actions/using-workflows/triggering-a-workflow
- 4: https://github.blog/changelog/2022-09-08-github-actions-use-github_token-with-workflow_dispatch-and-repository_dispatch/
- 5: https://docs.github.com/en/actions/reference/workflows-and-actions/events-that-trigger-workflows
- 6: https://docs.github.com/actions/using-workflows/events-that-trigger-workflows
- 7: https://github.com/actions/checkout
- 8: https://github.com/actions/checkout/blob/cbb722410c2e876e24abbe8de2cc27693e501dcb/action.yml
- 9: https://github.com/actions/checkout/tree/v6.0.2?tab=readme-ov-file
- 10: Change the default value of persist-credentials to false actions/checkout#1687
- 11: https://github.com/actions/checkout/blob/34e114876b0b11c390a56381ad16ebd13914f8d5/action.yml
🏁 Script executed:
#!/bin/bashset -eu
python3 - <<'PY'from pathlib import Pathimport repromote = Path(".github/workflows/promote-to-prod.yml").read_text()prod_cd = Path(".github/workflows/prod-cd.yml").read_text()checks = { "promote workflow_dispatch": bool(re.search(r"(?m)^\s+workflow_dispatch:\s*$", promote)), "contents write": bool(re.search(r"(?m)^\s+contents:\s*write\s*$", promote)), "checkout persist-credentials false": bool( re.search(r"(?m)^\s+persist-credentials:\s*false\s*$", promote) ), "checkout token override": bool( re.search(r"(?m)^\s+token:\s*(?!\$\{\{\s*github\.token\s*\}\})\S+", promote) ), "git tag command": bool(re.search(r"(?m)^\s*git tag ", promote)), "git push command": bool(re.search(r"(?m)^\s*git push ", promote)), "prod push tag trigger": bool(re.search(r"(?m)^\s+push:\s*$", prod_cd)), "prod v-star tag filter": bool(re.search(r"(?m)^\s+tags:\s*\[\s*['\"]v\*['\"]\s*\]", prod_cd)), "prod workflow_dispatch": bool(re.search(r"(?m)^\s+workflow_dispatch:\s*$", prod_cd)), "prod repository_dispatch": bool(re.search(r"(?m)^\s+repository_dispatch:\s*$", prod_cd)),}for name, result in checks.items(): print(f"{name}: {result}")PYRepository: Runnect/Runnect-Spring-Boot-Server
Length of output: 439
Authenticate the tag push with a non-GITHUB_TOKEN credential.
actions/checkout@v3 persists GITHUB_TOKEN by default. GitHub does not trigger push workflows from events created by GITHUB_TOKEN. Since prod-cd.yml listens only for push tags matching v*, the tag is created but production deployment does not start. Set persist-credentials: false and authenticate the push with a PAT or GitHub App token, or invoke an explicit dispatch contract.
🧰 Tools
🪛 zizmor (1.29.0)
[info] 65-65: code injection via template expansion (template-injection): may expand into attacker-controllable code
(template-injection)
[info] 66-66: code injection via template expansion (template-injection): may expand into attacker-controllable code
(template-injection)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.github/workflows/promote-to-prod.yml around lines 61 - 66, Update the
checkout configuration used by the promote workflow to set persist-credentials
to false, then authenticate the git push in the tag-generation step with a PAT
or GitHub App token rather than GITHUB_TOKEN. Ensure the tag push still targets
the version from steps.version.outputs.new_tag so the prod-cd.yml tag trigger
runs.
Source: Linters/SAST tools
작업 배경
#240에서 상용 배포를
git tag v1.x.x && git push origin v1.x.x로 수동 트리거하도록 분리했는데, 매번 로컬에서 이 커맨드를 직접 입력하는 게 번거롭다는 피드백을 받았다. GitHub Actions 버튼(또는 CLI 한 줄)으로 대체한다.변경 사항
.github/workflows/promote-to-prod.yml(신규)workflow_dispatch(bump: patch/minor/major 선택) — 최신v*태그를 조회해 다음 semver를 계산하고 태그 생성/push까지 자동 수행README.mdgh workflow run promote-to-prod.yml -f bump=patch사용법 추가영향 범위
prod-cd.yml의 트리거를 실행시켜 상용 배포로 이어짐 — 즉 이 워크플로를 실행하면 실제로 상용에 배포됨permissions: contents: write로 GITHUB_TOKEN에 태그 push 권한 부여 (다른 권한 확장 없음)Test Plan
python3 -c "import yaml; yaml.safe_load(...)")🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Documentation