Job 1.: Docker 빌드 + E2E 테스트
Job 2.: GHCR에 이미지 등록
Job 3.: GitHub Pages 배포
코드 push → 도커 이미지를 빌드해서 E2E 통과
→ 컨테이너 레지스트리 (GHCR)에 이미지 올리기
→ 정적 파일은 GitHub Pages로 웹 배포
GitHub Pages: GitHub에서 제공하는 웹 서버

name: CD
on:
push:
branches: [main]
name: 워크플로우 이름. GitHub Actions 탭에 그대로 노출on: 트리거를 정의하는 키워드push: push 이벤트 발생 시 실행branches: main 브랜치에 push될 때만 실행permissions:
contents: read
packages: write
pages: write
id-token: write
필요한 권한만 명시적으로 부여
contents: read: 저장소 코드를 읽기만 함 (체크아웃에 필요)packages: write: GHCR에 도커 이미지를 업로드하므로 쓰기 권한 필요pages: write: GitHub Pages 배포에 필요한 쓰기 권한id-token: write: OIDC 토큰 발급용. 비밀번호 없이 신원을 증명env:
IMAGE_NAME: ghcr.io/${{ github.repository }}
워크플로우 전체에서 쓸 환경 변수
IMAGE_NAME: 도커 이미지의 풀네임${{ github.repository }}: GitHub이 자동으로 채워주는 사용자명/저장소jobs:
build-and-e2e:
name: 1) Docker + E2E
runs-on: ubuntulatest
outpits:
image-tag: ${{ steps.meta.outputs.tag }}
build-and-e2e: 이 job의 고유 IDsteps:
- uses: actions/checkout@v4
- id: meta
run: echo "tag=sha-${GITHUB_SHA::7}" >> "$GITHUB_OUTPUT"
${GITHUB_SHA::7}: 현재 커밋 해시의 앞 7자리만 잘라냄- run: docker build -t calculator:test .
- run: docker run -d --rm --name calc -p 8080:80 calculator:test
-d: detached 백그라운드 모드로 실행-rm: 컨테이너가 멈추면 자동 삭제--name calc: 컨테이너 이름을 calc로 지정p 8080:80: 호스트 8080 포트를 컨테이너 80포트에 연결- name:
run: |
for i in {1..20}; do
if curl -sf http://localhost:8080 >dev/null; then echo OK; exit 0; fi
sleep 1
done
exit 1
- uses: actions/setup-node@v4
with:
node-version: "20"
cache: "npm"
- run: npm ci
- run: npx playwright install --with-deps chromium
- env:
BASE_URL: http://localhost:8080
run: npm run test:e2e
- if: always()
run: docker stop calc || true
BASE_URL: 코드가 어디로 접속할지 알려주는 환경 변수if: always(): 이전 step의 성공/실패와 무관하게 무조건 실행||true: stop이 실패해도 워크플로우 전체를 실패시키지 않도록 무시push-image:
name: 2) GHCR
runs-on: ubuntu-latest
needs: build-and-e2e
...
- uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
needs: bulid-and-e2e: 이전의 job이 성공해야만 실행 (안전장치)secrets.GITHUB_TOKEN: 매 실행마다 만들어지는 일회용 토큰... 등

