Skip to content

ci: 상용 배포용 태그 자동 생성 워크플로 추가 (Promote to Production) - #241

Merged
unam98 merged 1 commit into
mainfrom
ci/promote-to-prod-workflow
Aug 11, 2026
Merged

ci: 상용 배포용 태그 자동 생성 워크플로 추가 (Promote to Production)#241
unam98 merged 1 commit into
mainfrom
ci/promote-to-prod-workflow

Conversation

@unam98

@unam98unam98 commented Aug 11, 2026

Copy link
Copy Markdown
Collaborator

작업 배경

#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.md배포 전략 섹션에 gh workflow run promote-to-prod.yml -f bump=patch 사용법 추가

영향 범위

  • 이 워크플로가 push하는 태그가 prod-cd.yml의 트리거를 실행시켜 상용 배포로 이어짐 — 즉 이 워크플로를 실행하면 실제로 상용에 배포됨
  • permissions: contents: write로 GITHUB_TOKEN에 태그 push 권한 부여 (다른 권한 확장 없음)

Test Plan

  • YAML 문법 검증 (python3 -c "import yaml; yaml.safe_load(...)")
  • 실제 Actions 탭에서 실행해 태그 생성 → prod-cd.yml 트리거까지 확인 필요 (다음 릴리즈 때)

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added a manually triggered production promotion workflow with patch, minor, and major version options.
    • Automatically creates the next version tag and initiates production deployment.
  • Documentation

    • Updated deployment instructions with workflow usage through the command line and web interface.
    • Removed outdated manual tag creation steps.

git tag를 로컬에서 직접 만들고 push하는 게 번거롭다는 피드백에 따라,
GitHub Actions workflow_dispatch로 버튼 한 번(또는 gh workflow run)에
다음 semver 태그를 계산해 생성/push하는 워크플로를 추가했다.
이 태그 push가 prod-cd.yml의 트리거(on.push.tags)를 실행시켜
상용 배포로 이어진다.
@unam98unam98 self-assigned this Aug 11, 2026
@coderabbitai

coderabbitaiBot commented Aug 11, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The 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 prod-cd.yml trigger.

Changes

Production promotion

Layer / File(s)Summary
Version input and tag calculation
.github/workflows/promote-to-prod.yml
The workflow accepts patch, minor, or major, reads existing tags, calculates the next semantic version, and exposes the tag as a step output.
Tag push and deployment instructions
.github/workflows/promote-to-prod.yml, README.md
The workflow pushes the calculated tag and records completion details. The README documents CLI and UI usage and the prod-cd.yml deployment trigger.

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
Loading
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check nameStatusExplanation
Description Check✅ PassedCheck skipped - CodeRabbit’s high-level summary is enabled.
Title check✅ PassedThe title clearly describes the added workflow that automatically generates production deployment tags.
Docstring Coverage✅ PassedNo functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check✅ PassedCheck skipped because no linked issues were found for this pull request.
Out of Scope Changes check✅ PassedCheck skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch ci/promote-to-prod-workflow

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

📥 Commits

Reviewing files that changed from the base of the PR and between 24ed6ba and f5d033f.

📒 Files selected for processing (2)
  • .github/workflows/promote-to-prod.yml
  • README.md

Comment on lines +22 to +24
jobs:
tag:
runs-on: ubuntu-latest

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 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 ||true

Repository: 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")PY

Repository: 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.

Comment on lines +26 to +28
- uses: actions/checkout@v3
with:
fetch-depth: 0

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 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';fi

Repository: 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:


🏁 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'fi

Repository: 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 20

Repository: 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:


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 ||true

Repository: 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:


🏁 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.md

Repository: 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.

Comment on lines +34 to +43
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)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 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""$?"done

Repository: 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

Comment on lines +61 to +66
- 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 }}"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ 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.md

Repository: 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.md

Repository: 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:


🏁 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}")PY

Repository: 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

@unam98
unam98 merged commit c4b1f6a into mainAug 11, 2026
2 checks passed
@unam98
unam98 deleted the ci/promote-to-prod-workflow branch August 11, 2026 08:32
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@unam98@alh0409