Conversation
EC2에 프론트엔드 정적 파일을 자동 배포하는 GitHub Actions 워크플로우를 추가합니다. main, dev 브랜치 push 시 pnpm 빌드 후 SCP로 EC2에 배포합니다.
워크스루PR이 main 또는 dev 브랜치로 머지(닫힌 PR에서 merged)될 때 트리거되는 새 GitHub Actions 워크플로우( 변경 사항
Sequence Diagram(s)sequenceDiagram
participant GH as GitHub Actions
participant Runner as Runner (ubuntu-latest)
participant Secrets as GitHub Secrets
participant EC2 as EC2 Host
GH->>Runner: 워크플로우 트리거 (PR merged to main/dev)
Runner->>Runner: checkout
Runner->>Runner: setup pnpm (v10.28.0) & Node.js (v20)
Runner->>Secrets: 접근(SSH key, HOST, USER, VITE_*)
Runner->>Runner: pnpm install --frozen-lockfile (pnpm cache)
Runner->>Runner: pnpm build (env from Secrets)
Runner->>EC2: scp dist/* (credentials from Secrets)
Runner->>EC2: ssh -> mkdir /tmp/fe-deploy, mv, chown www-data, chmod, backup /var/www/dokdok -> /var/www/dokdok-old
EC2-->>Runner: deploy result
Runner-->>GH: workflow 완료/실패
문제 → 영향 → 대안:
평가 항목🎯 2 (Simple) | ⏱️ ~12분 🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 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: 3
🤖 Fix all issues with AI agents
In @.github/workflows/deploy.yml:
- Around line 3-6: CI currently deploys both branches listed in on.push.branches
(main and dev) to the same target, causing dev to overwrite production; update
the workflow by making the deploy job conditional on the branch (use github.ref
or if: startsWith(github.ref, 'refs/heads/dev') / 'refs/heads/main') and set
branch-specific deploy destinations (e.g., use a different target for dev versus
main) or attach an environment with required reviewers for the main branch;
modify the deploy job (the job named "deploy" or the steps that perform the
rsync/ssh copy) to select the destination path and/or environment based on the
branch to prevent accidental overwrites.
- Around line 51-55: Current approach removes /var/www/dokdok with rm -rf then
moves /tmp/fe-deploy into place, risking downtime or partial deploys; instead
implement an atomic swap: copy or move the contents of /tmp/fe-deploy into a new
sibling directory (e.g. /var/www/dokdok_new), set ownership/permissions there
(chown/chmod), then use a single rename (mv) to atomically replace
/var/www/dokdok with the new directory and finally remove the old backup
directory; update the workflow steps that currently run sudo rm -rf
/var/www/dokdok, sudo mv /tmp/fe-deploy/* /var/www/dokdok/, sudo chown -R
www-data:www-data /var/www/dokdok and rm -rf /tmp/fe-deploy to follow this
create-set-permissions-atomic-rename-remove-old pattern.
- Around line 34-49: Add SSH host key verification to both the
appleboy/scp-action@v0.1.7 and appleboy/ssh-action@v1.2.0 steps by passing a
fingerprint input (e.g., fingerprint: ${{ secrets.SSH_HOST_FINGERPRINT }});
compute the server's SSH host key fingerprint (SHA256) and store it in the
secret, then add the fingerprint input to the scp step and the ssh step so the
actions verify the host key before connecting.
| on: | ||
| push: | ||
| branches: [main, dev] | ||
|
|
There was a problem hiding this comment.
dev/main 동일 경로 배포 위험
문제: main과 dev가 모두 /var/www/dokdok로 배포됩니다.
영향: dev 푸시가 운영을 덮어써 예기치 않은 서비스 변경이 발생할 수 있습니다.
대안: 브랜치별 배포 경로 분리(예: /var/www/dokdok-dev) 또는 환경 보호/승인 게이트를 적용하세요.
Also applies to: 51-54
🤖 Prompt for AI Agents
In @.github/workflows/deploy.yml around lines 3 - 6, CI currently deploys both
branches listed in on.push.branches (main and dev) to the same target, causing
dev to overwrite production; update the workflow by making the deploy job
conditional on the branch (use github.ref or if: startsWith(github.ref,
'refs/heads/dev') / 'refs/heads/main') and set branch-specific deploy
destinations (e.g., use a different target for dev versus main) or attach an
environment with required reviewers for the main branch; modify the deploy job
(the job named "deploy" or the steps that perform the rsync/ssh copy) to select
the destination path and/or environment based on the branch to prevent
accidental overwrites.
| - name: Deploy to EC2 | ||
| uses: appleboy/scp-action@v0.1.7 | ||
| with: | ||
| host: ${{ secrets.EC2_HOST }} | ||
| username: ${{ secrets.EC2_USER }} | ||
| key: ${{ secrets.EC2_SSH_KEY }} | ||
| source: "dist/*" | ||
| target: "/tmp/fe-deploy" | ||
| strip_components: 1 | ||
|
|
||
| - name: Move files and set permissions | ||
| uses: appleboy/ssh-action@v1.2.0 | ||
| with: | ||
| host: ${{ secrets.EC2_HOST }} | ||
| username: ${{ secrets.EC2_USER }} | ||
| key: ${{ secrets.EC2_SSH_KEY }} |
There was a problem hiding this comment.
🧩 Analysis chain
🌐 Web query:
appleboy scp-action ssh-action host key verification fingerprint known_hosts
💡 Result:
appleboy/ssh-action and appleboy/scp-action don’t use a known_hosts input; instead, they support SSH host key verification via a SHA256 host fingerprint (and proxy_fingerprint for jump hosts). [1][2]
How to do host key verification (recommended):
-
Get the server’s host-key fingerprint (SHA256) on the server (example for ed25519):
ssh-keygen -l -f /etc/ssh/ssh_host_ed25519_key.pub | cut -d ' ' -f2
(Use the matching host key type your server actually uses.) [1]
-
Store that output as a GitHub Secret, e.g.
SSH_FINGERPRINT. -
Pass it to the action:
ssh-action
- uses: appleboy/ssh-action@v1 with: host: ${{ secrets.HOST }} username: ${{ secrets.USERNAME }} key: ${{ secrets.KEY }} fingerprint: ${{ secrets.SSH_FINGERPRINT }} script: whoami
[1]
scp-action
- uses: appleboy/scp-action@v1 with: host: ${{ secrets.HOST }} username: ${{ secrets.USERNAME }} key: ${{ secrets.KEY }} fingerprint: ${{ secrets.SSH_FINGERPRINT }} source: dist/* target: /var/www/app
[2]
If you specifically need known_hosts-style pinning, you’d typically do that with OpenSSH directly (e.g., ssh-keyscan to write ~/.ssh/known_hosts) and then run scp/ssh yourself—but for these appleboy/* actions, the built-in mechanism is the fingerprint input. [1][2]
SSH 호스트 키 검증 누락
문제: SCP/SSH 단계에서 호스트 키 검증이 설정되지 않았습니다.
영향: 중간자 공격(MITM)에 취약합니다.
대안: 서버의 SSH 호스트 키 지문(SHA256)을 구한 후 fingerprint 입력값으로 전달하세요.
- uses: appleboy/scp-action@v0.1.7
with:
host: ${{ secrets.EC2_HOST }}
username: ${{ secrets.EC2_USER }}
key: ${{ secrets.EC2_SSH_KEY }}
fingerprint: ${{ secrets.SSH_HOST_FINGERPRINT }}
source: "dist/*"
target: "/tmp/fe-deploy"
strip_components: 1SSH 호스트 지문 확인: ssh-keygen -l -f /etc/ssh/ssh_host_ed25519_key.pub | cut -d ' ' -f2
🤖 Prompt for AI Agents
In @.github/workflows/deploy.yml around lines 34 - 49, Add SSH host key
verification to both the appleboy/scp-action@v0.1.7 and
appleboy/ssh-action@v1.2.0 steps by passing a fingerprint input (e.g.,
fingerprint: ${{ secrets.SSH_HOST_FINGERPRINT }}); compute the server's SSH host
key fingerprint (SHA256) and store it in the secret, then add the fingerprint
input to the scp step and the ssh step so the actions verify the host key before
connecting.
push 트리거 대신 pull_request closed + merged 조건으로 변경하여 main, dev 브랜치에 PR이 merge될 때만 배포가 실행되도록 수정합니다.
rm -rf 후 mv 방식 대신 디렉터리 rename 스왑으로 변경하여 배포 중 다운타임 및 부분 배포 문제를 방지합니다.
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In @.github/workflows/deploy.yml:
- Around line 52-59: The deploy script can fail on first run because the sudo mv
/var/www/dokdok /var/www/dokdok-old command will error if /var/www/dokdok
doesn't exist; modify the script to tolerate a missing source by either
appending a no-op-on-failure operator (i.e., make the mv resilient) or by
wrapping that mv in a conditional existence check that only runs the move when
/var/www/dokdok is present, and keep the subsequent sudo mv /tmp/fe-deploy
/var/www/dokdok and cleanup steps unchanged so the rest of the deployment
proceeds.
| script: | | ||
| sudo mkdir -p /tmp/fe-deploy | ||
| sudo chown -R www-data:www-data /tmp/fe-deploy | ||
| sudo chmod -R 755 /tmp/fe-deploy | ||
| sudo rm -rf /var/www/dokdok-old | ||
| sudo mv /var/www/dokdok /var/www/dokdok-old | ||
| sudo mv /tmp/fe-deploy /var/www/dokdok | ||
| sudo rm -rf /var/www/dokdok-old No newline at end of file |
There was a problem hiding this comment.
첫 배포 시 스크립트 실패 가능
문제: Line 57에서 /var/www/dokdok가 존재하지 않으면 mv 명령이 실패합니다.
영향: 첫 배포 또는 디렉터리가 없는 환경에서 전체 배포가 중단됩니다.
대안: || true 추가 또는 조건부 체크를 적용하세요.
🔧 수정 제안
sudo mkdir -p /tmp/fe-deploy
sudo chown -R www-data:www-data /tmp/fe-deploy
sudo chmod -R 755 /tmp/fe-deploy
sudo rm -rf /var/www/dokdok-old
- sudo mv /var/www/dokdok /var/www/dokdok-old
+ sudo mv /var/www/dokdok /var/www/dokdok-old || true
sudo mv /tmp/fe-deploy /var/www/dokdok
sudo rm -rf /var/www/dokdok-old🤖 Prompt for AI Agents
In @.github/workflows/deploy.yml around lines 52 - 59, The deploy script can
fail on first run because the sudo mv /var/www/dokdok /var/www/dokdok-old
command will error if /var/www/dokdok doesn't exist; modify the script to
tolerate a missing source by either appending a no-op-on-failure operator (i.e.,
make the mv resilient) or by wrapping that mv in a conditional existence check
that only runs the move when /var/www/dokdok is present, and keep the subsequent
sudo mv /tmp/fe-deploy /var/www/dokdok and cleanup steps unchanged so the rest
of the deployment proceeds.
Summary
main,dev브랜치에 PR이 merge될 때 자동으로 EC2에 정적 파일 배포작업 내용
.github/workflows/deploy.yml추가pull_requestclosed + merged 조건으로 merge 시에만 배포 실행pnpm/action-setup@v4를 사용한 안정적인 pnpm 설치cache: 'pnpm')으로 빌드 속도 최적화VITE_API_URL,VITE_APP_URL)를 GitHub Secrets에서 주입appleboy/scp-action으로 빌드 결과물 EC2 전송배포 흐름
main또는dev브랜치에 PR mergepnpm builddist/*를 EC2/tmp/fe-deploy로 SCP 전송/tmp/fe-deploy권한 설정 → 기존 디렉터리를dokdok-old로 이동 → 신규 디렉터리를dokdok으로 원자적 스왑 → 이전 버전 삭제사전 설정 필요 (GitHub Secrets)
EC2_HOSTEC2_USEREC2_SSH_KEYVITE_API_URLVITE_APP_URLTest plan
/var/www/dokdok/에 빌드 파일 배포 확인https://dokdok.site접속 시 프론트엔드 정상 렌더링 확인Summary by CodeRabbit
✏️ Tip: You can customize this high-level summary in your review settings.