GitHub Actions

GitHub Actions

1. GitHub Actionsλž€?

GitHub ActionsλŠ” CI/CD μžλ™ν™” ν”Œλž«νΌμž…λ‹ˆλ‹€. μ½”λ“œ ν‘Έμ‹œ, PR 생성 λ“±μ˜ μ΄λ²€νŠΈμ— 따라 μžλ™μœΌλ‘œ μ›Œν¬ν”Œλ‘œμš°λ₯Ό μ‹€ν–‰ν•©λ‹ˆλ‹€.

μ£Όμš” μš©λ„

μš©λ„ μ˜ˆμ‹œ
CI (Continuous Integration) ν…ŒμŠ€νŠΈ μžλ™ μ‹€ν–‰, 린트 검사
CD (Continuous Deployment) μžλ™ 배포, Docker 이미지 λΉŒλ“œ
μžλ™ν™” 이슈 라벨링, 릴리슀 λ…ΈνŠΈ 생성

핡심 κ°œλ…

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                   Workflow                          β”‚
β”‚   (.github/workflows/ci.yml)                        β”‚
β”‚                                                     β”‚
β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
β”‚   β”‚                  Job: build                  β”‚  β”‚
β”‚   β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”      β”‚  β”‚
β”‚   β”‚   β”‚ Step 1  β”‚β†’β”‚ Step 2  β”‚β†’β”‚ Step 3  β”‚      β”‚  β”‚
β”‚   β”‚   β”‚Checkout β”‚ β”‚ Install β”‚ β”‚  Test   β”‚      β”‚  β”‚
β”‚   β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜      β”‚  β”‚
β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β”‚                        ↓                            β”‚
β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
β”‚   β”‚                  Job: deploy                 β”‚  β”‚
β”‚   β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”                   β”‚  β”‚
β”‚   β”‚   β”‚ Build   β”‚β†’β”‚ Deploy  β”‚                   β”‚  β”‚
β”‚   β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                   β”‚  β”‚
β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
κ°œλ… μ„€λͺ…
Workflow μžλ™ν™” ν”„λ‘œμ„ΈμŠ€ 전체 (YAML 파일)
Event μ›Œν¬ν”Œλ‘œμš°λ₯Ό νŠΈλ¦¬κ±°ν•˜λŠ” 이벀트
Job 같은 λŸ¬λ„ˆμ—μ„œ μ‹€ν–‰λ˜λŠ” 단계 묢음
Step κ°œλ³„ μž‘μ—… λ‹¨μœ„
Action μž¬μ‚¬μš© κ°€λŠ₯ν•œ μž‘μ—… λ‹¨μœ„
Runner μ›Œν¬ν”Œλ‘œμš°λ₯Ό μ‹€ν–‰ν•˜λŠ” μ„œλ²„

2. μ›Œν¬ν”Œλ‘œμš° 파일 ꡬ쑰

μ›Œν¬ν”Œλ‘œμš°λŠ” .github/workflows/ 디렉토리에 YAML 파일둜 μ €μž₯ν•©λ‹ˆλ‹€.

기본 ꡬ쑰

# .github/workflows/ci.yml

name: CI Pipeline           # μ›Œν¬ν”Œλ‘œμš° 이름

on:                         # 트리거 이벀트
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:                       # μž‘μ—… μ •μ˜
  build:                    # Job 이름
    runs-on: ubuntu-latest  # μ‹€ν–‰ ν™˜κ²½

    steps:                  # 단계듀
      - name: Checkout      # Step 이름
        uses: actions/checkout@v4

      - name: Run tests
        run: npm test

3. 트리거 이벀트 (on)

push / pull_request

on:
  push:
    branches:
      - main
      - 'release/**'
    paths:
      - 'src/**'          # src 폴더 λ³€κ²½ μ‹œλ§Œ
    paths-ignore:
      - '**.md'           # md 파일 λ³€κ²½ λ¬΄μ‹œ

  pull_request:
    branches: [main]
    types: [opened, synchronize, reopened]

μˆ˜λ™ μ‹€ν–‰ (workflow_dispatch)

on:
  workflow_dispatch:
    inputs:
      environment:
        description: '배포 ν™˜κ²½'
        required: true
        default: 'staging'
        type: choice
        options:
          - staging
          - production

μŠ€μΌ€μ€„ (cron)

on:
  schedule:
    - cron: '0 9 * * 1-5'  # 평일 μ˜€μ „ 9μ‹œ (UTC)

# cron ν˜•μ‹: λΆ„ μ‹œ 일 μ›” μš”μΌ
# 0 9 * * 1-5 = λ§€μ£Ό μ›”-금 09:00

λ‹€λ₯Έ μ›Œν¬ν”Œλ‘œμš° μ™„λ£Œ μ‹œ

on:
  workflow_run:
    workflows: ["Build"]
    types: [completed]

4. Jobs μ„€μ •

κΈ°λ³Έ Job

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm install
      - run: npm test

μ‹€ν–‰ ν™˜κ²½ (runs-on)

jobs:
  build:
    runs-on: ubuntu-latest      # Ubuntu μ΅œμ‹ 
    # runs-on: ubuntu-22.04     # νŠΉμ • 버전
    # runs-on: macos-latest     # macOS
    # runs-on: windows-latest   # Windows

Job μ˜μ‘΄μ„± (needs)

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - run: npm run build

  test:
    needs: build              # build μ™„λ£Œ ν›„ μ‹€ν–‰
    runs-on: ubuntu-latest
    steps:
      - run: npm test

  deploy:
    needs: [build, test]      # λ‘˜ λ‹€ μ™„λ£Œ ν›„ μ‹€ν–‰
    runs-on: ubuntu-latest
    steps:
      - run: ./deploy.sh

병렬 μ‹€ν–‰

jobs:
  test-node-16:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/setup-node@v4
        with:
          node-version: '16'
      - run: npm test

  test-node-18:               # 병렬 μ‹€ν–‰
    runs-on: ubuntu-latest
    steps:
      - uses: actions/setup-node@v4
        with:
          node-version: '18'
      - run: npm test

맀트릭슀 μ „λž΅(Matrix Strategy)

맀트릭슀 λΉŒλ“œλ₯Ό μ‚¬μš©ν•˜λ©΄ μ—¬λŸ¬ κ΅¬μ„±μ—μ„œ μžλ™μœΌλ‘œ μž‘μ—…μ„ μ‹€ν–‰ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

jobs:
  test:
    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        node-version: [18, 20, 22]
        os: [ubuntu-latest, macos-latest, windows-latest]
        # 9개의 μž‘μ—… 생성 (3개 버전 Γ— 3개 OS)

    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: ${{ matrix.node-version }}
      - run: npm test

κ³ κΈ‰ 맀트릭슀 μ˜΅μ…˜

jobs:
  test:
    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        os: [ubuntu-latest, macos-latest]
        node-version: [18, 20]
        include:
          # νŠΉμ • μ‘°ν•© μΆ”κ°€
          - os: windows-latest
            node-version: 20
        exclude:
          # νŠΉμ • μ‘°ν•© μ œμ™Έ
          - os: macos-latest
            node-version: 18
      fail-fast: false  # ν•˜λ‚˜κ°€ μ‹€νŒ¨ν•΄λ„ λ‹€λ₯Έ μž‘μ—… 계속 μ‹€ν–‰

    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: ${{ matrix.node-version }}
      - run: npm test

Python 맀트릭슀 예제

jobs:
  test:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        python-version: ['3.9', '3.10', '3.11', '3.12']

    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: ${{ matrix.python-version }}
      - run: |
          pip install -r requirements.txt
          pytest

쑰건뢀 μ‹€ν–‰ (if)

jobs:
  deploy:
    if: github.ref == 'refs/heads/main'
    runs-on: ubuntu-latest
    steps:
      - run: ./deploy.sh

  notify:
    if: failure()             # μ‹€νŒ¨ μ‹œμ—λ§Œ
    runs-on: ubuntu-latest
    steps:
      - run: echo "Build failed!"

5. Steps μ„€μ •

Action μ‚¬μš© (uses)

steps:
  # 곡식 Action
  - uses: actions/checkout@v4

  # νŠΉμ • 버전
  - uses: actions/setup-node@v4
    with:
      node-version: '18'

  # λ§ˆμΌ“ν”Œλ ˆμ΄μŠ€ Action
  - uses: docker/build-push-action@v5

λͺ…λ Ήμ–΄ μ‹€ν–‰ (run)

steps:
  # 단일 λͺ…λ Ή
  - run: npm install

  # μ—¬λŸ¬ λͺ…λ Ή
  - run: |
      npm install
      npm run build
      npm test

  # μž‘μ—… 디렉토리 μ§€μ •
  - run: npm install
    working-directory: ./frontend

  # μ‰˜ μ§€μ •
  - run: echo "Hello"
    shell: bash

ν™˜κ²½ λ³€μˆ˜

steps:
  - run: echo $MY_VAR
    env:
      MY_VAR: "Hello"

  - run: echo ${{ env.MY_VAR }}

Secrets μ‚¬μš©

steps:
  - run: echo ${{ secrets.API_KEY }}
    env:
      API_KEY: ${{ secrets.API_KEY }}

Secrets μ„€μ •: Repository β†’ Settings β†’ Secrets and variables β†’ Actions


6. κ³ κΈ‰ κΈ°λŠ₯

μ˜μ‘΄μ„± 캐싱(Dependency Caching)

캐싱을 톡해 μ‹€ν–‰ κ°„ μ˜μ‘΄μ„±μ„ μ €μž₯ν•˜μ—¬ μ›Œν¬ν”Œλ‘œμš° 속도λ₯Ό λ†’μž…λ‹ˆλ‹€.

actions/cache μ‚¬μš©

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4

      # npm μΊμ‹œ
      - uses: actions/cache@v4
        with:
          path: ~/.npm
          key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
          restore-keys: |
            ${{ runner.os }}-node-

      - run: npm ci
      - run: npm test

Python pip μΊμ‹œ

steps:
  - uses: actions/checkout@v4

  - uses: actions/setup-python@v5
    with:
      python-version: '3.11'
      cache: 'pip'  # λ‚΄μž₯ 캐싱 지원

  - run: pip install -r requirements.txt

Go λͺ¨λ“ˆ μΊμ‹œ

steps:
  - uses: actions/checkout@v4

  - uses: actions/setup-go@v5
    with:
      go-version: '1.21'
      cache: true  # Go λͺ¨λ“ˆ μžλ™ 캐싱

  - run: go build

μ—¬λŸ¬ μΊμ‹œ 경둜

- uses: actions/cache@v4
  with:
    path: |
      ~/.npm
      ~/.cache
      node_modules
    key: ${{ runner.os }}-deps-${{ hashFiles('**/package-lock.json') }}
    restore-keys: |
      ${{ runner.os }}-deps-

μž¬μ‚¬μš© κ°€λŠ₯ν•œ μ›Œν¬ν”Œλ‘œ(Reusable Workflows)

λ‹€λ₯Έ μ›Œν¬ν”Œλ‘œμ—μ„œ ν˜ΈμΆœν•  수 μžˆλŠ” μ›Œν¬ν”Œλ‘œλ₯Ό μƒμ„±ν•©λ‹ˆλ‹€.

호좜 κ°€λŠ₯ν•œ μ›Œν¬ν”Œλ‘œ

# .github/workflows/reusable-deploy.yml

name: Reusable Deploy

on:
  workflow_call:
    inputs:
      environment:
        required: true
        type: string
      version:
        required: false
        type: string
        default: 'latest'
    secrets:
      deploy-token:
        required: true
    outputs:
      deployment-url:
        description: "Deployed application URL"
        value: ${{ jobs.deploy.outputs.url }}

jobs:
  deploy:
    runs-on: ubuntu-latest
    outputs:
      url: ${{ steps.deploy.outputs.url }}

    steps:
      - uses: actions/checkout@v4

      - name: Deploy to ${{ inputs.environment }}
        id: deploy
        run: |
          echo "Deploying version ${{ inputs.version }} to ${{ inputs.environment }}"
          # Deployment logic here
          echo "url=https://${{ inputs.environment }}.example.com" >> $GITHUB_OUTPUT
        env:
          DEPLOY_TOKEN: ${{ secrets.deploy-token }}

μž¬μ‚¬μš© κ°€λŠ₯ν•œ μ›Œν¬ν”Œλ‘œ 호좜

# .github/workflows/main.yml

name: Main Pipeline

on: push

jobs:
  deploy-staging:
    uses: ./.github/workflows/reusable-deploy.yml
    with:
      environment: staging
      version: ${{ github.sha }}
    secrets:
      deploy-token: ${{ secrets.DEPLOY_TOKEN }}

  deploy-production:
    needs: deploy-staging
    if: github.ref == 'refs/heads/main'
    uses: ./.github/workflows/reusable-deploy.yml
    with:
      environment: production
      version: ${{ github.sha }}
    secrets:
      deploy-token: ${{ secrets.DEPLOY_TOKEN }}

  notify:
    needs: deploy-production
    runs-on: ubuntu-latest
    steps:
      - run: echo "Deployed to ${{ needs.deploy-production.outputs.deployment-url }}"

볡합 μ•‘μ…˜(Composite Actions)

μ—¬λŸ¬ λ‹¨κ³„λ‘œ κ΅¬μ„±λœ μ‚¬μš©μž μ •μ˜ μ•‘μ…˜μ„ μƒμ„±ν•©λ‹ˆλ‹€.

# .github/actions/setup-app/action.yml

name: 'Setup Application'
description: 'Install and configure application'

inputs:
  node-version:
    description: 'Node.js version'
    required: false
    default: '20'
  install-deps:
    description: 'Install dependencies'
    required: false
    default: 'true'

outputs:
  cache-hit:
    description: 'Whether cache was restored'
    value: ${{ steps.cache.outputs.cache-hit }}

runs:
  using: 'composite'
  steps:
    - name: Setup Node.js
      uses: actions/setup-node@v4
      with:
        node-version: ${{ inputs.node-version }}

    - name: Cache dependencies
      id: cache
      uses: actions/cache@v4
      with:
        path: node_modules
        key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}

    - name: Install dependencies
      if: inputs.install-deps == 'true' && steps.cache.outputs.cache-hit != 'true'
      shell: bash
      run: npm ci

    - name: Display info
      shell: bash
      run: |
        echo "Node version: $(node --version)"
        echo "npm version: $(npm --version)"

볡합 μ•‘μ…˜ μ‚¬μš©

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4

      - name: Setup application
        uses: ./.github/actions/setup-app
        with:
          node-version: '20'
          install-deps: 'true'

      - run: npm test
      - run: npm run build

ν΄λΌμš°λ“œ 제곡자 OIDC 인증

OpenID Connect(OIDC)λ₯Ό μ‚¬μš©ν•˜λ©΄ 자격 증λͺ…을 μ €μž₯ν•˜μ§€ μ•Šκ³ λ„ ν΄λΌμš°λ“œ μ œκ³΅μžμ— ν‚€ 없이 인증할 수 μžˆμŠ΅λ‹ˆλ‹€.

AWS OIDC

jobs:
  deploy-to-aws:
    runs-on: ubuntu-latest
    permissions:
      id-token: write
      contents: read

    steps:
      - uses: actions/checkout@v4

      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: arn:aws:iam::123456789012:role/GitHubActionsRole
          aws-region: us-east-1

      - name: Deploy to S3
        run: |
          aws s3 sync ./build s3://my-bucket

GCP OIDC

jobs:
  deploy-to-gcp:
    runs-on: ubuntu-latest
    permissions:
      id-token: write
      contents: read

    steps:
      - uses: actions/checkout@v4

      - name: Authenticate to Google Cloud
        uses: google-github-actions/auth@v2
        with:
          workload_identity_provider: 'projects/123456789/locations/global/workloadIdentityPools/github/providers/github-provider'
          service_account: 'github-actions@my-project.iam.gserviceaccount.com'

      - name: Deploy to Cloud Run
        run: |
          gcloud run deploy my-service --image gcr.io/my-project/my-image

Azure OIDC

jobs:
  deploy-to-azure:
    runs-on: ubuntu-latest
    permissions:
      id-token: write
      contents: read

    steps:
      - uses: actions/checkout@v4

      - name: Azure Login
        uses: azure/login@v2
        with:
          client-id: ${{ secrets.AZURE_CLIENT_ID }}
          tenant-id: ${{ secrets.AZURE_TENANT_ID }}
          subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}

      - name: Deploy to Azure
        run: |
          az webapp deploy --resource-group myRG --name myApp

λ™μ‹œμ„± μ œμ–΄(Concurrency Control)

μ—¬λŸ¬ μ›Œν¬ν”Œλ‘œ 싀행이 μ„œλ‘œ κ°„μ„­ν•˜λŠ” 것을 λ°©μ§€ν•©λ‹ˆλ‹€.

name: Deploy

on:
  push:
    branches: [main]

# ν•œ λ²ˆμ— ν•˜λ‚˜μ˜ 배포만
concurrency:
  group: production-deploy
  cancel-in-progress: false  # ν˜„μž¬ 배포가 μ™„λ£Œλ  λ•ŒκΉŒμ§€ λŒ€κΈ°

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: ./deploy.sh

λΈŒλžœμΉ˜λ³„ λ™μ‹œμ„±

concurrency:
  group: deploy-${{ github.ref }}
  cancel-in-progress: true  # μƒˆ ν‘Έμ‹œκ°€ λ„μ°©ν•˜λ©΄ 이전 μ‹€ν–‰ μ·¨μ†Œ

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: ./deploy.sh

PR별 λ™μ‹œμ„±

name: CI

on:
  pull_request:

concurrency:
  group: ci-${{ github.event.pull_request.number }}
  cancel-in-progress: true  # 였래된 PR λΉŒλ“œ μ·¨μ†Œ

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm test

7. μ‹€μŠ΅ 예제

예제 1: Node.js ν…ŒμŠ€νŠΈ μžλ™ν™” (μ΅œμ‹  버전)

# .github/workflows/node-ci.yml

name: Node.js CI

on:
  push:
    branches: [main, develop]
  pull_request:
    branches: [main]

concurrency:
  group: ci-${{ github.ref }}
  cancel-in-progress: true

jobs:
  test:
    runs-on: ubuntu-latest

    strategy:
      matrix:
        node-version: [18, 20, 22]

    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Setup Node.js ${{ matrix.node-version }}
        uses: actions/setup-node@v4
        with:
          node-version: ${{ matrix.node-version }}
          cache: 'npm'

      - name: Install dependencies
        run: npm ci

      - name: Run linter
        run: npm run lint

      - name: Run tests
        run: npm test

      - name: Build
        run: npm run build

예제 2: Docker 이미지 λΉŒλ“œ & ν‘Έμ‹œ (μ΅œμ‹  버전)

# .github/workflows/docker.yml

name: Docker Build & Push

on:
  push:
    branches: [main]
    tags: ['v*']

env:
  REGISTRY: ghcr.io
  IMAGE_NAME: ${{ github.repository }}

jobs:
  build-and-push:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: write

    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3

      - name: Login to Container Registry
        uses: docker/login-action@v3
        with:
          registry: ${{ env.REGISTRY }}
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: Extract metadata
        id: meta
        uses: docker/metadata-action@v5
        with:
          images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
          tags: |
            type=ref,event=branch
            type=semver,pattern={{version}}
            type=sha

      - name: Build and push
        uses: docker/build-push-action@v6
        with:
          context: .
          push: true
          tags: ${{ steps.meta.outputs.tags }}
          labels: ${{ steps.meta.outputs.labels }}
          cache-from: type=gha
          cache-to: type=gha,mode=max

예제 3: PR μžλ™ 라벨링

# .github/workflows/labeler.yml

name: PR Labeler

on:
  pull_request:
    types: [opened, synchronize]

jobs:
  label:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      pull-requests: write

    steps:
      - uses: actions/labeler@v5
        with:
          repo-token: ${{ secrets.GITHUB_TOKEN }}
# .github/labeler.yml (라벨 κ·œμΉ™)

frontend:
  - 'src/frontend/**'
  - '*.css'
  - '*.html'

backend:
  - 'src/backend/**'
  - 'api/**'

documentation:
  - '**/*.md'
  - 'docs/**'

예제 4: μžλ™ 배포 (Vercel)

# .github/workflows/deploy.yml

name: Deploy to Vercel

on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '18'

      - name: Install Vercel CLI
        run: npm install -g vercel

      - name: Deploy to Vercel
        run: vercel --prod --token=${{ secrets.VERCEL_TOKEN }}
        env:
          VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
          VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }}

예제 5: 릴리슀 μžλ™ν™”

# .github/workflows/release.yml

name: Release

on:
  push:
    tags: ['v*']

jobs:
  release:
    runs-on: ubuntu-latest
    permissions:
      contents: write

    steps:
      - name: Checkout
        uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: Generate changelog
        id: changelog
        uses: orhun/git-cliff-action@v3
        with:
          args: --latest --strip header

      - name: Create Release
        uses: softprops/action-gh-release@v1
        with:
          body: ${{ steps.changelog.outputs.content }}
          draft: false
          prerelease: ${{ contains(github.ref, 'beta') }}

8. μœ μš©ν•œ Actions (μ΅œμ‹  버전)

Action μš©λ„ μ΅œμ‹  버전
actions/checkout@v4 μ½”λ“œ 체크아웃 v4
actions/setup-node@v4 Node.js μ„€μ • v4
actions/setup-python@v5 Python μ„€μ • v5
actions/setup-go@v5 Go μ„€μ • v5
actions/cache@v4 μ˜μ‘΄μ„± 캐싱 v4
docker/setup-buildx-action@v3 Docker Buildx μ„€μ • v3
docker/build-push-action@v6 Docker λΉŒλ“œ/ν‘Έμ‹œ v6
docker/login-action@v3 Docker λ ˆμ§€μŠ€νŠΈλ¦¬ 둜그인 v3
aws-actions/configure-aws-credentials@v4 AWS 인증 (OIDC) v4
google-github-actions/auth@v2 GCP 인증 (OIDC) v2
azure/login@v2 Azure 인증 (OIDC) v2

μΊμ‹±μœΌλ‘œ 속도 ν–₯상

steps:
  - uses: actions/checkout@v4

  - uses: actions/setup-node@v4
    with:
      node-version: '20'
      cache: 'npm'           # npm μΊμ‹œ μžλ™ 처리

  - run: npm ci

9. 디버깅

둜그 확인

  • Actions νƒ­μ—μ„œ μ›Œν¬ν”Œλ‘œμš° μ‹€ν–‰ 기둝 확인
  • 각 Step의 둜그 펼쳐보기

디버그 λͺ¨λ“œ

steps:
  - run: echo "Debug info"
    env:
      ACTIONS_RUNNER_DEBUG: true

둜컬 ν…ŒμŠ€νŠΈ (act)

# act μ„€μΉ˜ (macOS)
brew install act

# μ›Œν¬ν”Œλ‘œμš° μ‹€ν–‰
act push

# νŠΉμ • Job만 μ‹€ν–‰
act -j build

λͺ…λ Ήμ–΄/문법 μš”μ•½

ν‚€μ›Œλ“œ μ„€λͺ…
name μ›Œν¬ν”Œλ‘œμš°/μŠ€ν… 이름
on 트리거 이벀트
jobs μž‘μ—… μ •μ˜
runs-on μ‹€ν–‰ ν™˜κ²½
steps 단계 μ •μ˜
uses Action μ‚¬μš©
run λͺ…λ Ήμ–΄ μ‹€ν–‰
with Action νŒŒλΌλ―Έν„°
env ν™˜κ²½ λ³€μˆ˜
if 쑰건뢀 μ‹€ν–‰
needs Job μ˜μ‘΄μ„±
strategy.matrix 맀트릭슀 λΉŒλ“œ

λ‹€μŒ 단계

Kubernetesλ₯Ό λ°°μ›Œμ„œ μ»¨ν…Œμ΄λ„ˆ μ˜€μΌ€μŠ€νŠΈλ ˆμ΄μ…˜μ„ μ΄ν•΄ν•΄λ΄…μ‹œλ‹€! β†’ Docker/06_Kubernetes_μž…λ¬Έ.md

to navigate between lessons