프론트엔드 릴리즈 워크플로우 및 Vercel 배포 자동화#516
Conversation
- Add a preview deployment workflow for pull requests and main updates. - Add a tag-based production release workflow. - Generate GitHub Releases from the production workflow. - Closes #514.
Walkthrough이 PR은 프론트엔드 배포 자동화를 위한 두 개의 GitHub Actions 워크플로를 추가합니다. Possibly related issues
🚥 Pre-merge checks | ✅ 4✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ 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: 2
🧹 Nitpick comments (2)
.github/workflows/cd.yml (1)
33-34: ⚡ Quick win체크아웃 자격증명 영속화 비활성화 권장.
이후 단계에서 git push를 하지 않으므로
actions/checkout가 워크플로 전체에 토큰을 영속화할 필요가 없습니다.persist-credentials: false로 노출 표면을 줄이는 것을 권장합니다. 더불어actions/checkout@v4,pnpm/action-setup@v4,actions/setup-node@v4,actions/github-script@v7등 외부 액션을 커밋 SHA로 고정하면 공급망 공격 표면을 추가로 줄일 수 있습니다.🔒 persist-credentials 비활성화
- name: Checkout repository uses: actions/checkout@v4 + with: + persist-credentials: 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/cd.yml around lines 33 - 34, Update the Checkout step (named "Checkout repository") to set persist-credentials: false so the workflow does not persist the GITHUB_TOKEN unnecessarily; also pin third‑party actions used in the workflow (actions/checkout, pnpm/action-setup, actions/setup-node, actions/github-script) to specific commit SHAs instead of loose tags (e.g., replace `@v4/`@v7 with the corresponding commit SHA) to reduce supply‑chain risk and exposure..github/workflows/release.yml (1)
24-25: ⚡ Quick win체크아웃 자격증명 영속화 비활성화 권장.
릴리스 단계는
GITHUB_TOKEN/시크릿으로 동작하며 git push가 없으므로persist-credentials: false를 설정하는 것을 권장합니다. 또한actions/checkout@v4,pnpm/action-setup@v4,actions/setup-node@v4,softprops/action-gh-release@v2를 커밋 SHA로 고정하면 공급망 보안을 강화할 수 있습니다.🔒 persist-credentials 비활성화
- name: Checkout repository uses: actions/checkout@v4 + with: + persist-credentials: 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/release.yml around lines 24 - 25, The checkout step currently uses actions/checkout@v4 without disabling credential persistence; update the Checkout repository step (actions/checkout@v4) to include persist-credentials: false to avoid persisting GITHUB_TOKEN credentials during the release workflow, and also pin third-party actions used in the workflow (pnpm/action-setup@v4, actions/setup-node@v4, softprops/action-gh-release@v2) to specific commit SHAs instead of floating tags to improve supply-chain security; ensure the changes are applied in the release workflow file where the Checkout repository step and those action usages are defined.
🤖 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/cd.yml:
- Around line 53-64: The Vercel steps ("Pull Vercel preview environment", "Build
Vercel artifacts", and "Deploy preview to Vercel") assume secrets and PR write
permissions and will fail for forked PRs; update the workflow so these steps run
only for non-forked PRs by adding a conditional (e.g., check head.repo.fork ==
false) to each step or move only the secret/permission-requiring parts into a
separate pull_request_target job, keeping the deploy/comment logic guarded from
untrusted fork runs and referencing the step names above to locate where to add
the condition or extraction.
In @.github/workflows/release.yml:
- Around line 53-61: The step is vulnerable because echo "- Tag: ${{
github.ref_name }}" expands the GitHub expression directly into the shell
(possible code injection); instead pass the tag through the environment and
reference that env var in the run block. Update the job to set an env variable
(e.g., TAG) to ${{ github.ref_name }} and then in the run section write the
summary using that env var (e.g., echo "- Tag: $TAG" >> "$GITHUB_STEP_SUMMARY"),
keeping deployment_url handling unchanged.
---
Nitpick comments:
In @.github/workflows/cd.yml:
- Around line 33-34: Update the Checkout step (named "Checkout repository") to
set persist-credentials: false so the workflow does not persist the GITHUB_TOKEN
unnecessarily; also pin third‑party actions used in the workflow
(actions/checkout, pnpm/action-setup, actions/setup-node, actions/github-script)
to specific commit SHAs instead of loose tags (e.g., replace `@v4/`@v7 with the
corresponding commit SHA) to reduce supply‑chain risk and exposure.
In @.github/workflows/release.yml:
- Around line 24-25: The checkout step currently uses actions/checkout@v4
without disabling credential persistence; update the Checkout repository step
(actions/checkout@v4) to include persist-credentials: false to avoid persisting
GITHUB_TOKEN credentials during the release workflow, and also pin third-party
actions used in the workflow (pnpm/action-setup@v4, actions/setup-node@v4,
softprops/action-gh-release@v2) to specific commit SHAs instead of floating tags
to improve supply-chain security; ensure the changes are applied in the release
workflow file where the Checkout repository step and those action usages are
defined.
🪄 Autofix (Beta)
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: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: bce9260c-e265-4a50-aa5e-04e038825c87
📒 Files selected for processing (2)
.github/workflows/cd.yml.github/workflows/release.yml
| - name: Pull Vercel preview environment | ||
| run: vercel pull --yes --environment=preview --token=${{ secrets.VERCEL_TOKEN }} | ||
|
|
||
| - name: Build Vercel artifacts | ||
| run: vercel build --token=${{ secrets.VERCEL_TOKEN }} | ||
|
|
||
| - name: Deploy preview to Vercel | ||
| id: deploy | ||
| shell: bash | ||
| run: | | ||
| deployment_url="$(vercel deploy --prebuilt --archive=tgz --token=${{ secrets.VERCEL_TOKEN }})" | ||
| echo "deployment_url=${deployment_url}" >> "$GITHUB_OUTPUT" |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# 포크 PR 허용 여부 및 다른 워크플로의 트리거 패턴 확인
fd -e yml -e yaml . .github/workflows --exec rg -n 'pull_request|fork|secrets\.' {} \;Repository: Team-SoFa/linkiving
Length of output: 1346
🏁 Script executed:
#!/bin/bash
set -euo pipefail
FILE=".github/workflows/cd.yml"
if [ ! -f "$FILE" ]; then
echo "Missing $FILE" >&2
exit 1
fi
echo "=== on: section (first 120 lines) ==="
nl -ba "$FILE" | sed -n '1,120p'
echo "=== workflow/jobs/steps around Vercel deploy (40-120 lines) ==="
nl -ba "$FILE" | sed -n '35,120p'Repository: Team-SoFa/linkiving
Length of output: 163
🏁 Script executed:
#!/bin/bash
set -euo pipefail
FILE=".github/workflows/cd.yml"
wc -l "$FILE"
echo "=== cd.yml: 1-120 ==="
sed -n '1,120p' "$FILE"
echo "=== cd.yml: 120-end ==="
sed -n '121,$p' "$FILE"Repository: Team-SoFa/linkiving
Length of output: 2996
🌐 Web query:
GitHub Actions pull_request events from fork secrets.VERCEL_TOKEN not available GITHUB_TOKEN read-only even if permissions specified pull-requests: write
💡 Result:
In GitHub Actions, when a workflow is triggered by the pull_request event for a pull request coming from a fork, secrets (including your secrets.VERCEL_TOKEN) are not passed to the workflow, and GitHub also applies a security model that can make the GITHUB_TOKEN effectively read-only for that run even if you set permissions in the workflow YAML. 1) Why secrets.VERCEL_TOKEN is “not available” - GitHub documents that secrets are not passed to workflows that are triggered by a pull request from a fork. This means ${{ secrets.VERCEL_TOKEN }} will be unset/empty in that fork PR run (by design/security restriction). [1] 2) Why GITHUB_TOKEN becomes read-only and ignores “pull-requests: write” - GitHub applies a read-only permissions adjustment for pull-request runs triggered from forked repositories (the docs clarification indicates write permissions are changed to read-only except for pull_request_target). [2][3] - Therefore, on pull_request from forks, you should not expect permissions: pull-requests: write to grant write access in the way it does for same-repo pull requests. [3] 3) The supported workaround (use pull_request_target with caution) - If you need a workflow to run with access to secrets (and generally with broader token permissions) for PRs originating from forks, GitHub’s guidance is to use the pull_request_target event so the workflow runs in the context of the base repository and can access secrets/tokens. [4] - Note: pull_request_target runs against the base context rather than the PR head context; GitHub explicitly warns to avoid running unsafe code from the pull request because that could alter the repository or steal secrets. [5][4] 4) Practical guidance for your case (Vercel deploy on fork PRs) - For fork-origin PRs on pull_request, plan for VERCEL_TOKEN to be unavailable and therefore disable/skip any steps that require it. - If you truly must deploy preview from fork PRs, switch to pull_request_target and only check out the PR code after you have appropriate review/guardrails (the security risk is real, which is why many actions default to not deploying fork PRs). [6][5] If you paste your workflow YAML (especially the on: trigger, permissions:, and where you use secrets.VERCEL_TOKEN), I can suggest an exact conditional structure to prevent the token from being required on fork PRs while still allowing the behavior you want on internal PRs.
Citations:
- 1: https://github.com/github/docs/blob/main/content/code-security/reference/secret-security/understanding-github-secret-types.md
- 2: Misleading wording regarding permissions and access to secrets in
pull_requestworkflows github/docs#25117 - 3: Clarify
How the permissions are calculated for a workflow jobgithub/docs#32398 - 4: https://github.com/github/docs/blob/main/content/actions/reference/workflows-and-actions/events-that-trigger-workflows.md
- 5: https://raw.githubusercontent.com/github/docs/refs/heads/main/content/actions/reference/workflows-and-actions/events-that-trigger-workflows.md
- 6: https://github.com/marketplace/actions/vercel-deployment-for-github-actions
🌐 Web query:
GitHub Actions pull_request events from fork secrets not passed GITHUB_TOKEN read-only even if permissions pull-requests: write
💡 Result:
For pull requests from forks using the pull_request event, GitHub intentionally prevents your workflow from getting write-capable GITHUB_TOKEN or any repository secrets beyond the default token’s limited access: repository secrets are not passed to workflows triggered by a pull request from a fork, and any “write” token permissions are adjusted down to read-only unless you use pull_request_target [1][2][3]. As a result, setting pull-requests: write (or broader write scopes) won’t be honored for the forked-PR workflow context; GitHub changes those permissions to read-only for security [1][4][3]. What you can do instead 1) If you need secrets and write access for forked PRs, the supported mechanism is pull_request_target (it runs in the base repository context and can access secrets; by default it grants read/write token permissions unless you restrict them) [5][3]. But you must not check out or execute untrusted code from the fork in that workflow; only do trusted actions like labeling/commenting/triage [5]. 2) Keep pull_request for untrusted code execution and move any secret-dependent or write-permission steps behind a trusted workflow (commonly by splitting workflows, or using pull_request_target only for metadata/reporting) [5]. 3) Use least-privilege permissions anyway: the GITHUB_TOKEN’s granted scopes are controlled via the permissions key, but for forked pull_request triggers GitHub still applies the fork-related read-only/secret-withholding restrictions [6][1][3]. Bottom line answer to your query - Yes: for fork PRs triggered with pull_request, GitHub will withhold secrets and downgrade any requested token write permissions (including pull-requests: write) to read-only for that workflow run [1][3]. - There is no way to “force” pull_request fork runs to get pull-requests: write with repository secrets; the security restriction is intentional [1][3]. - The practical option is to use pull_request_target for the privileged portion, with the critical rule that you do not execute fork code in that context [5].
Citations:
- 1: https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/enabling-features-for-your-repository/managing-github-actions-settings-for-a-repository
- 2: https://github.com/github/docs/blob/main/content/code-security/reference/secret-security/understanding-github-secret-types.md
- 3: Clarify Permissions Calculation for Workflow Jobs in Documentation github/docs#33566
- 4: Clarify
How the permissions are calculated for a workflow jobgithub/docs#32398 - 5: https://stackoverflow.com/questions/75744849/permission-to-repo-denied-to-github-actions-for-pr-coming-from-a-fork-only
- 6: https://docs.github.com/actions/reference/authentication-in-a-workflow
포크 PR에서 Vercel 토큰/PR 코멘트 권한이 막혀 워크플로가 실패할 수 있어요.
- 현재
.github/workflows/cd.yml의pull_request트리거에서는secrets.VERCEL_TOKEN을 전제로vercel pull/build/deploy를 항상 실행하는데, 포크 PR의pull_request에서는 시크릿이 전달되지 않아 이 단계가 실패할 수 있습니다. - 또한
permissions: pull-requests: write를 설정해도 포크 PRpull_request실행에서는GITHUB_TOKEN이 write로 동작하지 않을 수 있어 코멘트 작성 단계(createComment/updateComment)도 실패할 수 있습니다. - 대응: 포크 PR이면 해당 단계들을
if: ...head.repo.fork == false로 스킵하거나, 권한/시크릿이 필요한 부분만pull_request_target로 분리(비신뢰 코드 실행 주의)하세요.
🤖 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/cd.yml around lines 53 - 64, The Vercel steps ("Pull
Vercel preview environment", "Build Vercel artifacts", and "Deploy preview to
Vercel") assume secrets and PR write permissions and will fail for forked PRs;
update the workflow so these steps run only for non-forked PRs by adding a
conditional (e.g., check head.repo.fork == false) to each step or move only the
secret/permission-requiring parts into a separate pull_request_target job,
keeping the deploy/comment logic guarded from untrusted fork runs and
referencing the step names above to locate where to add the condition or
extraction.
| run: | | ||
| deployment_url="$(vercel deploy --prebuilt --archive=tgz --prod --token=${{ secrets.VERCEL_TOKEN }})" | ||
| echo "deployment_url=${deployment_url}" >> "$GITHUB_OUTPUT" | ||
| { | ||
| echo "Production release deployed." | ||
| echo | ||
| echo "- Tag: ${{ github.ref_name }}" | ||
| echo "- URL: ${deployment_url}" | ||
| } >> "$GITHUB_STEP_SUMMARY" |
There was a problem hiding this comment.
스텝 요약에서 github.ref_name을 직접 셸로 확장하지 마세요 (코드 인젝션).
echo "- Tag: ${{ github.ref_name }}"는 표현식을 셸 스크립트로 직접 전개합니다. git 태그 이름에는 $, (, ), 백틱 등 셸 메타문자가 포함될 수 있어, 태그를 푸시할 수 있는 권한자가 임의 명령을 실행할 수 있는 인젝션 경로가 됩니다(이 잡은 VERCEL_TOKEN 시크릿에 접근). env로 전달해 안전하게 참조하세요.
🛡️ env 변수로 전달
- name: Deploy production to Vercel
id: deploy
shell: bash
+ env:
+ REF_NAME: ${{ github.ref_name }}
run: |
deployment_url="$(vercel deploy --prebuilt --archive=tgz --prod --token=${{ secrets.VERCEL_TOKEN }})"
echo "deployment_url=${deployment_url}" >> "$GITHUB_OUTPUT"
{
echo "Production release deployed."
echo
- echo "- Tag: ${{ github.ref_name }}"
+ echo "- Tag: ${REF_NAME}"
echo "- URL: ${deployment_url}"
} >> "$GITHUB_STEP_SUMMARY"🧰 Tools
🪛 zizmor (1.25.2)
[error] 59-59: 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/release.yml around lines 53 - 61, The step is vulnerable
because echo "- Tag: ${{ github.ref_name }}" expands the GitHub expression
directly into the shell (possible code injection); instead pass the tag through
the environment and reference that env var in the run block. Update the job to
set an env variable (e.g., TAG) to ${{ github.ref_name }} and then in the run
section write the summary using that env var (e.g., echo "- Tag: $TAG" >>
"$GITHUB_STEP_SUMMARY"), keeping deployment_url handling unchanged.
관련 이슈
PR 설명
ci.yml은 유지하고, PR /main기준 Vercel Preview 배포를 담당하는cd.yml을 추가했습니다.v*) 기준으로만 Vercel Production 배포와 GitHub Release 생성을 수행하는release.yml을 추가했습니다.비고
CI / CD / release로 분리했습니다.