-
Notifications
You must be signed in to change notification settings - Fork 0
프론트엔드 릴리즈 워크플로우 및 Vercel 배포 자동화 #516
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,101 @@ | ||
| name: Linkiving frontend CD | ||
|
|
||
| on: | ||
| workflow_dispatch: | ||
| push: | ||
| branches: | ||
| - main | ||
| pull_request: | ||
| branches: | ||
| - main | ||
| types: | ||
| - opened | ||
| - synchronize | ||
| - reopened | ||
|
|
||
| permissions: | ||
| contents: read | ||
| pull-requests: write | ||
|
|
||
| concurrency: | ||
| group: frontend-cd-${{ github.event.pull_request.number || github.ref }} | ||
| cancel-in-progress: true | ||
|
|
||
| env: | ||
| VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }} | ||
| VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }} | ||
|
|
||
| jobs: | ||
| deploy-preview: | ||
| runs-on: ubuntu-latest | ||
|
|
||
| steps: | ||
| - name: Checkout repository | ||
| uses: actions/checkout@v4 | ||
|
|
||
| - name: Setup pnpm | ||
| uses: pnpm/action-setup@v4 | ||
| with: | ||
| version: 10.19.0 | ||
|
|
||
| - name: Setup Node.js | ||
| uses: actions/setup-node@v4 | ||
| with: | ||
| node-version: '22.x' | ||
| cache: 'pnpm' | ||
|
|
||
| - name: Install dependencies | ||
| run: pnpm install --frozen-lockfile | ||
|
|
||
| - name: Install Vercel CLI | ||
| run: npm install --global vercel@latest | ||
|
|
||
| - 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" | ||
| echo "Preview deployment: ${deployment_url}" >> "$GITHUB_STEP_SUMMARY" | ||
|
|
||
| - name: Add PR preview comment | ||
| if: github.event_name == 'pull_request' | ||
| uses: actions/github-script@v7 | ||
| env: | ||
| DEPLOYMENT_URL: ${{ steps.deploy.outputs.deployment_url }} | ||
| with: | ||
| script: | | ||
| const marker = '<!-- vercel-preview-deployment -->'; | ||
| const body = `${marker}\nPreview deployment is ready.\n\n- URL: ${process.env.DEPLOYMENT_URL}\n- Commit: ${context.sha}`; | ||
| const { owner, repo } = context.repo; | ||
| const issue_number = context.issue.number; | ||
| const comments = await github.paginate(github.rest.issues.listComments, { | ||
| owner, | ||
| repo, | ||
| issue_number, | ||
| per_page: 100, | ||
| }); | ||
| const existing = comments.find((comment) => comment.user?.type === 'Bot' && comment.body?.includes(marker)); | ||
|
|
||
| if (existing) { | ||
| await github.rest.issues.updateComment({ | ||
| owner, | ||
| repo, | ||
| comment_id: existing.id, | ||
| body, | ||
| }); | ||
| return; | ||
| } | ||
|
|
||
| await github.rest.issues.createComment({ | ||
| owner, | ||
| repo, | ||
| issue_number, | ||
| body, | ||
| }); | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,66 @@ | ||
| name: Vercel Production Release | ||
|
|
||
| on: | ||
| push: | ||
| tags: | ||
| - 'v*' | ||
|
|
||
| permissions: | ||
| contents: write | ||
|
|
||
| concurrency: | ||
| group: vercel-release-${{ github.ref }} | ||
| cancel-in-progress: false | ||
|
|
||
| env: | ||
| VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }} | ||
| VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }} | ||
|
|
||
| jobs: | ||
| deploy-production: | ||
| runs-on: ubuntu-latest | ||
|
|
||
| steps: | ||
| - name: Checkout repository | ||
| uses: actions/checkout@v4 | ||
|
|
||
| - name: Setup pnpm | ||
| uses: pnpm/action-setup@v4 | ||
| with: | ||
| version: 10.19.0 | ||
|
|
||
| - name: Setup Node.js | ||
| uses: actions/setup-node@v4 | ||
| with: | ||
| node-version: '22.x' | ||
| cache: 'pnpm' | ||
|
|
||
| - name: Install dependencies | ||
| run: pnpm install --frozen-lockfile | ||
|
|
||
| - name: Install Vercel CLI | ||
| run: npm install --global vercel@latest | ||
|
|
||
| - name: Pull Vercel production environment | ||
| run: vercel pull --yes --environment=production --token=${{ secrets.VERCEL_TOKEN }} | ||
|
|
||
| - name: Build production artifacts | ||
| run: vercel build --prod --token=${{ secrets.VERCEL_TOKEN }} | ||
|
|
||
| - name: Deploy production to Vercel | ||
| id: deploy | ||
| shell: bash | ||
| 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" | ||
|
Comment on lines
+53
to
+61
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 스텝 요약에서
🛡️ 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 |
||
|
|
||
| - name: Create GitHub release | ||
| uses: softprops/action-gh-release@v2 | ||
| with: | ||
| generate_release_notes: true | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
Repository: Team-SoFa/linkiving
Length of output: 1346
🏁 Script executed:
Repository: Team-SoFa/linkiving
Length of output: 163
🏁 Script executed:
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, onpull_requestfrom forks, you should not expectpermissions: pull-requests: writeto 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 thepull_request_targetevent so the workflow runs in the context of the base repository and can access secrets/tokens. [4] - Note:pull_request_targetruns 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 onpull_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 topull_request_targetand 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 theon:trigger,permissions:, and where you usesecrets.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:
pull_requestworkflows github/docs#25117How the permissions are calculated for a workflow jobgithub/docs#32398🌐 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:
How the permissions are calculated for a workflow jobgithub/docs#32398포크 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)도 실패할 수 있습니다.if: ...head.repo.fork == false로 스킵하거나, 권한/시크릿이 필요한 부분만pull_request_target로 분리(비신뢰 코드 실행 주의)하세요.🤖 Prompt for AI Agents