โ˜๏ธ DevOps ๐ŸŒฟ ์ค‘๊ธ‰

GitHub Actions CI/CD

GitHub Actions๋กœ ์ž๋™ ๋ฐฐํฌ ํŒŒ์ดํ”„๋ผ์ธ ๊ตฌ์ถ•

โฑ๏ธ 5์‹œ๊ฐ„ ๐Ÿ‘๏ธ 21 ์กฐํšŒ
๐Ÿ“– ๊ฐ•์ขŒ ๋‚ด์šฉ
# GitHub Actions CI/CD ๊ฐ€์ด๋“œ

## ํ•™์Šต ๋ชฉํ‘œ
GitHub Actions๋กœ ์ž๋™ํ™”๋œ CI/CD ํŒŒ์ดํ”„๋ผ์ธ์„ ๊ตฌ์ถ•ํ•ฉ๋‹ˆ๋‹ค.

## 1. GitHub Actions๋ž€?
GitHub์—์„œ ์ œ๊ณตํ•˜๋Š” ์ž๋™ํ™” CI/CD ํ”Œ๋žซํผ์ž…๋‹ˆ๋‹ค.
- ์ฝ”๋“œ ํ‘ธ์‹œ ์‹œ ์ž๋™ ๋นŒ๋“œ/ํ…Œ์ŠคํŠธ
- PR ์ž๋™ ๊ฒ€์ฆ
- ์ž๋™ ๋ฐฐํฌ
- ๋ฌด๋ฃŒ ์‚ฌ์šฉ๋Ÿ‰ ์ œ๊ณต

## 2. Workflow ํŒŒ์ผ ์œ„์น˜
ํ”„๋กœ์ ํŠธ ๋ฃจํŠธ์— .github/workflows/ ๋””๋ ‰ํ† ๋ฆฌ ์ƒ์„ฑ
YAML ํŒŒ์ผ๋กœ ์›Œํฌํ”Œ๋กœ์šฐ ์ •์˜
์˜ˆ: .github/workflows/ci.yml

## 3. ๊ธฐ๋ณธ ๊ตฌ์กฐ
name: CI
on: [push, pull_request]

jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: 20
- run: npm install
- run: npm test

## 4. ํŠธ๋ฆฌ๊ฑฐ ์ด๋ฒคํŠธ
Push:
on:
push:
branches: [main, develop]
paths:
- "src/**"

Pull Request:
on:
pull_request:
branches: [main]

์Šค์ผ€์ค„:
on:
schedule:
- cron: "0 9 * * 1-5"

์ˆ˜๋™ ์‹คํ–‰:
on: workflow_dispatch

## 5. ํ™˜๊ฒฝ๋ณ€์ˆ˜์™€ ์‹œํฌ๋ฆฟ
ํ™˜๊ฒฝ๋ณ€์ˆ˜:
env:
NODE_ENV: production

jobs:
build:
env:
DATABASE_URL: postgres://localhost/test

์‹œํฌ๋ฆฟ ์‚ฌ์šฉ:
steps:
- name: Deploy
env:
API_KEY: ${{ secrets.API_KEY }}
run: ./deploy.sh

## 6. ๋งคํŠธ๋ฆญ์Šค ๋นŒ๋“œ
strategy:
matrix:
node: [18, 20, 22]
os: [ubuntu-latest, windows-latest]

runs-on: ${{ matrix.os }}
steps:
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node }}

## 7. ์บ์‹ฑ
- name: Cache node modules
uses: actions/cache@v4
with:
path: ~/.npm
key: ${{ runner.os }}-node-${{ hashFiles("**/package-lock.json") }}
restore-keys: |
${{ runner.os }}-node-

## 8. ์•„ํ‹ฐํŒฉํŠธ
์—…๋กœ๋“œ:
- uses: actions/upload-artifact@v4
with:
name: build
path: dist/

๋‹ค์šด๋กœ๋“œ:
- uses: actions/download-artifact@v4
with:
name: build

## 9. ์กฐ๊ฑด๋ถ€ ์‹คํ–‰
if: github.event_name == "push"
if: github.ref == "refs/heads/main"
if: contains(github.event.head_commit.message, "[skip ci]") == false
if: success()
if: failure()
if: always()

## 10. Docker ๋นŒ๋“œ ๋ฐ ํ‘ธ์‹œ
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}

- name: Build and push
uses: docker/build-push-action@v5
with:
push: true
tags: user/app:latest

## 11. ๋ฐฐํฌ ์˜ˆ์‹œ
Vercel:
- uses: amondnet/vercel-action@v25
with:
vercel-token: ${{ secrets.VERCEL_TOKEN }}
vercel-org-id: ${{ secrets.ORG_ID }}
vercel-project-id: ${{ secrets.PROJECT_ID }}
vercel-args: "--prod"

SSH ๋ฐฐํฌ:
- name: Deploy via SSH
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.HOST }}
username: ${{ secrets.USERNAME }}
key: ${{ secrets.SSH_KEY }}
script: |
cd /var/www/app
git pull
npm install
pm2 restart all

## 12. ์žฌ์‚ฌ์šฉ ๊ฐ€๋Šฅ ์›Œํฌํ”Œ๋กœ์šฐ
.github/workflows/reusable.yml:
on:
workflow_call:
inputs:
environment:
required: true
type: string

ํ˜ธ์ถœ:
jobs:
deploy:
uses: ./.github/workflows/reusable.yml
with:
environment: production

## ์ถ”์ฒœ ํ•™์Šต ์ˆœ์„œ
1. ๊ธฐ๋ณธ ์›Œํฌํ”Œ๋กœ์šฐ ์ž‘์„ฑ
2. ํŠธ๋ฆฌ๊ฑฐ์™€ ์กฐ๊ฑด ์ดํ•ด
3. ์บ์‹ฑ์œผ๋กœ ์†๋„ ๊ฐœ์„ 
4. ๋ฐฐํฌ ์ž๋™ํ™”
5. ์žฌ์‚ฌ์šฉ ์›Œํฌํ”Œ๋กœ์šฐ