๊ฐœ์ธ๊ณต๋ถ€/CI&CD

Github actions: Basic (with YAML)

soon327 2021. 12. 1. 23:56


๐Ÿง Github actions?

Github actions๋Š” Github์—์„œ ์ œ๊ณตํ•˜๋Š” workflow๋ฅผ ์ž๋™ํ™”ํ•  ์ˆ˜ ์žˆ๋Š” ๋„๊ตฌ์ด๋‹ค. ์ฆ‰, Github์—์„œ ์ง์ ‘ ์ œ๊ณตํ•˜๋Š” CI/CD ๋„๊ตฌ๋ผ๊ณ  ํ•  ์ˆ˜ ์žˆ๋‹ค.
CI๋กœ ์“ด๋‹ค๋Š” ์˜๋ฏธ๋Š” ํ…Œ์ŠคํŠธ ์‹คํ–‰์ด๋‚˜ ๋นŒ๋“œ ๊ฒ€์‚ฌ, ์ปจ๋ฒค์…˜ ๊ฒ€์‚ฌ๋ฅผ ํ†ตํ•ด ์ฝ”๋“œ๊ฐ€ ์˜๋„๋Œ€๋กœ ๋™์ž‘ํ•˜๊ณ  ์ž˜ ์ž‘์„ฑ๋˜์—ˆ๋Š”์ง€๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์˜๋ฏธ์ด๊ณ  CD๋Š” ์„œ๋ฒ„์— ๋ฐฐํฌํ•˜๊ฑฐ๋‚˜ ๋ ˆ์ง€์ŠคํŠธ๋ฆฌ์— ๋ฐœํ–‰ํ•˜๋Š” ๋“ฑ์˜ ํ–‰์œ„๋ฅผ ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์˜๋ฏธ์ด๋‹ค.
์ด๋Ÿฌํ•œ CI/CD ๋„๊ตฌ์—๋Š” Travis CI, CircleCI ๋“ฑ์ด ์žˆ์ง€๋งŒ Github actions๋Š” ์ž‘์„ฑ์ด ์‰ฌ์šฐ๋ฉด์„œ๋„ ํ™•์žฅ์„ฑ์ด ์ข‹๊ณ , Github ๋งˆ์ผ“ ํ”Œ๋ ˆ์ด์Šค์—์„œ ์—ฌ๋Ÿฌ ์‚ฌ๋žŒ์ด ๊ณต์œ ํ•œ Workflow๋ฅผ ์ฐพ์„ ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์ž์‹ ์ด ์ง์ ‘ ๋งŒ๋“ค์–ด์„œ ๊ณต์œ ํ•  ์ˆ˜๋„ ์žˆ๋‹ค๋Š” ์žฅ์ ์ด ์žˆ๋‹ค.


๐Ÿ“š YAML (YAML Ain't Markup Language)

Github actions์˜ workflow๋“ค์€ yaml(์•ผ๋ฏˆ)๋ฌธ๋ฒ•์œผ๋กœ ์ž‘์„ฑ๋˜์–ด /.github/workflows์— xxx.ymlํ˜•ํƒœ๋กœ ์ €์žฅ๋œ๋‹ค.
๋”ฐ๋ผ์„œ YAML์— ๋Œ€ํ•ด ์ต์ˆ™ํ• ์ˆ˜๋ก ์›Œํฌํ”Œ๋กœ์šฐ๋ฅผ ์ž‘์„ฑํ•˜๊ธฐ ์ˆ˜์›”ํ•ด์ง€๊ธฐ๋•Œ๋ฌธ์— YAML์— ๋Œ€ํ•ด ๊ฐ„๋‹จํ•˜๊ฒŒ ์ •๋ฆฌํ•˜๊ณ  ๋„˜์–ด๊ฐ€๋ณด๋ ค ํ•œ๋‹ค.

YAML ์ด๋ž€? (vs JSON)

YAML์˜ ์˜๋ฏธ๋Š” "๋˜ ๋‹ค๋ฅธ ๋งˆํฌ์—… ์–ธ์–ด (Yet Another Markup Language)"์˜€์œผ๋‚˜, ๋ฌธ์„œ ๋งˆํฌ์—… ํ˜•์‹์ด ์•„๋‹ˆ๊ณ  ๋ฐ์ดํ„ฐ ์ค‘์‹ฌ์— ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ๋ณด์—ฌ์ฃผ๊ธฐ ์œ„ํ•˜์—ฌ "YAML์€ ๋งˆํฌ์—… ์–ธ์–ด๊ฐ€ ์•„๋‹ˆ๋‹ค (YAML Ain't Markup Language)"๋ผ๋Š” ์ด๋ฆ„์„ ์ฑ„ํƒํ•˜์˜€๋‹ค๊ณ  ํ•œ๋‹ค.

YAML์€ JSON๊ณผ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ์‚ฌ๋žŒ์ด ์ฝ๊ธฐ ์‰ฝ๊ฒŒ ๊ฐ€๋…์„ฑ์„ ๊ณ ๋ คํ•˜์—ฌ ์„ค๊ฒŒ๋œ ๋ฐ์ดํ„ฐ ๊ตํ™˜ํฌ๋งท์ด๋‹ค. JSON์€ ๋‹จ์ˆœํ™”์™€ ๋ฒ”์šฉ์„ฑ์— ์ค‘์ ์„ ๋‘” ๋ฐ˜๋ฉด, YAML์€ ๊ฐ€๋…์„ฑ์— ์ค‘์ ์„ ๋‘์—ˆ๋‹ค๋Š” ์ ์—์„œ ์ฐจ์ด๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค. ๋”ฐ๋ผ์„œ JSON์— ๋น„ํ•˜์—ฌ YAMLํŒŒ์ผ์€ ์ƒ์„ฑ๊ณผ ํ•ด์„์ด ๋น„๊ต์  ๋ณต์žกํ•œ ํŽธ์ด๋‹ค.

YAML ๋ฌธ๋ฒ•

์ด๋ฒˆ ๊ธ€์—์„œ๋Š” YAML์˜ ๋ชจ๋“  ๋ฌธ๋ฒ•์„ ์•Œ์•„๋ณธ๋‹ค๊ธฐ ๋ณด๋‹ค๋Š” workflow ์ž‘์„ฑ์— ํ•„์š”ํ•œ ๋ฌธ๋ฒ•๋“ค๋งŒ ๊ฐ„๋žตํžˆ ์ •๋ฆฌํ•ด๋ณด๋ คํ•œ๋‹ค.

๋ฐ์ดํ„ฐ ์ •์˜ (map)

๋ฐ์ดํ„ฐ๋Š” ๋“ค์—ฌ์“ฐ๊ธฐ ๋ฐ key: value ํ˜•ํƒœ๋กœ ์ •์˜ํ•œ๋‹ค.

// YAML
apiVersion: v1
kind: Pod
metadata:
  name: echo
  labels:
    type: app
// JSON
{
  "apiVersion": "v1",
  "kind": "Pod",
  "metadata": {
    "name": "echo",
    "labels": {
      "type": "app"
    }
  }
}

์ด๋•Œ key์™€ value์‚ฌ์ด์—๋Š” ๋ฐ˜๋“œ์‹œ ๋นˆ์นธ์ด ์กด์žฌํ•ด์•ผํ•œ๋‹ค.

# error (not key-value, string)
key:value

# ok
key: value

๋ฐฐ์—ด ์ •์˜ (array)

๋ฐฐ์—ด์€ ํ•˜์ดํ”ˆ(-) ํ˜•ํƒœ๋กœ ์ •์˜ํ•œ๋‹ค.

// YAML
person:
  name: Chungsub Kim
  job: Developer
  skills: 
    - docker
    - kubernetes
// JSON
{
  "person": {
    "name": "Chungsub Kim",
    "job": "Developer",
    "skills": [
      "docker", "kubernetes"
    ]
  }
}

์ฃผ์„

์ฃผ์„์€ #์œผ๋กœ ํ‘œ์‹œํ•œ๋‹ค.

# ์ฃผ์„์ฃผ์„์ฃผ์„

์ค„๋ฐ”๊ฟˆ

|์ง€์‹œ์–ด๋Š” ๋งˆ์ง€๋ง‰ ์ค„๋ฐ”๊ฟˆ ํฌํ•จ, |-์ง€์‹œ์–ด๋Š” ๋งˆ์ง€๋ง‰ ์ค„๋ฐ”๊ฟˆ ์ œ์™ธ, >์ง€์‹œ์–ด๋Š” ์ค‘๊ฐ„์— ๋“ค์–ด๊ฐ„ ๋นˆ์ค„์„ ์ œ์™ธํ•œ๋‹ค.

// YAML
newlines_sample: |
            number one line

            second line

            last line
// JSON
{
  "newlines_sample": "number one line\n\nsecond line\n\nlast line\n"
}

YAML ๋ณ€ํ™˜ ์‚ฌ์ดํŠธ

json2yaml
์œ„ ์‚ฌ์ดํŠธ์—์„œ JSON์„ YAML ๋ณ€ํ™˜ํ•  ์ˆ˜ ์žˆ๋‹ค.


๐Ÿƒ๐Ÿปโ€โ™‚๏ธ workflow ๊ตฌ์„ฑ ์‚ดํŽด๋ณด๊ธฐ

repository์˜ Actions ํƒญ์—์„œ workflow๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค.

์ง์ ‘ ์ฒ˜์Œ๋ถ€ํ„ฐ ์ž‘์„ฑํ•  ์ˆ˜๋„ ์žˆ์ง€๋งŒ, ์ฒ˜์Œ์—๋Š” ์•„๋ž˜์˜ ์ถ”์ฒœ ํ…œํ”Œ๋ฆฟ์—์„œ ์ˆ˜์ •ํ•˜๋ฉด์„œ ์ž‘์„ฑํ•˜๋Š” ๊ฒƒ์„ ์ถ”์ฒœํ•œ๋‹ค.

name: CI

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

jobs:
  build:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        node: [ 12,14,16 ]

    steps:
      - name: checkout to repository
        uses: actions/checkout@v2

      - name: Run a one-line script
        run: echo Hello, world!
      - run: npm test

์œ„์˜ ๊ธฐ๋ณธ ํ…œํ”Œ๋ฆฟ์„ ์˜ˆ์‹œ๋กœ ์›Œํฌํ”Œ๋กœ์šฐ์˜ ๊ตฌ์„ฑ์„ ๊ฐ„๋‹จํžˆ ์ •๋ฆฌํ•ด๋ณด๋„๋ก ํ•˜๊ฒ ๋‹ค.๐Ÿ˜Ž

name

name: CI

name์€ ์ด ์›Œํฌํ”Œ๋กœ์šฐ์˜ ์ด๋ฆ„์ด๋‹ค. GitHub Actions์—์„œ๋Š” ๋‹ค์ˆ˜์˜ ์›Œํฌํ”Œ๋กœ์šฐ๋ฅผ ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋Š”๋ฐ ํŒŒ์ผ๋งˆ๋‹ค ํ•˜๋‚˜์”ฉ ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.
์ด๋ ‡๊ฒŒ ์ž‘์„ฑํ•œ ์ด๋ฆ„์€ repository์˜ Actionsํƒญ์—์„œ ์•„๋ž˜์ฒ˜๋Ÿผ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค. (name: PR Test)

on

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

on์€ ํ•„์ˆ˜๊ฐ’์œผ๋กœ ์›Œํฌํ”Œ๋กœ์šฐ์— ์ด๋ฒคํŠธ๋ฅผ ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋‹ค. ์œ„์—์„œ๋Š” push์™€ pull_reqeust์˜ main ๋ธŒ๋žœ์น˜์— ๋Œ€ํ•ด์„œ ์„ค์ •ํ•œ ๊ฒƒ์ธ๋ฐ ๊ฐ„๋‹จํ•˜๊ฒŒ

on: [push, pull_request]

๋กœ ์„ค์ •ํ•˜๋Š” ๊ฒƒ๋„ ๊ฐ€๋Šฅํ•˜๋‹ค.
๋‹ค์–‘ํ•œ ์ด๋ฒคํŠธ๊ฐ€ ์žˆ์œผ๋ฉฐ ์ด๋Š” ์ด๊ณณ์—์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.
repository_dispatch๋ฅผ ์„ค์ •ํ•˜๋ฉด Github ์™ธ๋ถ€์—์„œ ๋ฐœ์ƒํ•˜๋Š” ํ™œ๋™์œผ๋กœ๋„ ์ด๋ฒคํŠธ๋ฅผ ๋ฐœ์ƒ์‹œํ‚ฌ ์ˆ˜ ์žˆ์œผ๋ฉฐ,
schedule ์ด๋ฒคํŠธ๋ฅผ ์„ค์ •ํ•˜๋ฉด POSIX cron ๋ฌธ๋ฒ•์œผ๋กœ ์•„๋ž˜์ฒ˜๋Ÿผ ํŠน์ • ์‹œ๊ฐ„์— ์ด๋ฒคํŠธ๋ฅผ ๋ฐœ์ƒ์‹œํ‚ฌ ์ˆ˜ ์žˆ๋‹ค.

on:
  schedule:
    # KST ๊ธฐ์ค€, ์›”-๊ธˆ 06์‹œ
    - cron: "0 21 * * 0-4"

jobs

jobs:
  build:

jobs๋Š” ์›Œํฌํ”Œ๋กœ์šฐ์˜ ๊ธฐ๋ณธ ๋‹จ์œ„๋ผ๊ณ  ๋ณด๋ฉด ๋˜๋ฉฐ ๋‹ค์‹œ ๋” ์ž‘์€ ๋‹จ์œ„์ธ ์Šคํ…(step)์œผ๋กœ ์ด๋ฃจ์–ด์ ธ ์žˆ๋‹ค.
์œ„์—์„œ๋Š” jobs.build๋กœ ๋˜์–ด ์žˆ๋Š”๋ฐ ์‹ค์ œ ๋ฌธ๋ฒ•์€ jobs.<job_id>๊ฐ€ ๋œ๋‹ค. build๋Š” ์ž„์˜๋กœ ์ง€์ •ํ•œ ์ด๋ฆ„์ด๊ณ  ์•„๋ฌด ์ด๋ฆ„์ด๋‚˜ ์ง€์ •ํ•  ์ˆ˜ ์žˆ๋‹ค. ์—ฌ๊ธฐ์„œ๋Š” build๋ผ๋Š” ์žก ํ•˜๋‚˜๋งŒ ์žˆ์ง€๋งŒ ์ด๋ฆ„์ฒ˜๋Ÿผ ์—ฌ๋Ÿฌ ๊ฐœ์˜ ์žก์„ ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.

jobs๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ๋ณ‘๋ ฌ์ ์œผ๋กœ ์‹คํ–‰๋˜์ง€๋งŒ needsํ‚ค์›Œ๋“œ๋ฅผ ํ†ตํ•ด ์˜์กด์„ฑ์„ ๊ฐ–๋„๋ก ์„ค์ •ํ•  ์ˆ˜๋„ ์žˆ๋‹ค.
์•„๋ž˜๋Š” needsํ‚ค์›Œ๋“œ๋ฅผ ์ถ”๊ฐ€ํ•˜์—ฌ test์ž‘์—…์ด build์ž‘์—… ์ดํ›„์— ์‹คํ–‰๋˜๋„๋ก ์„ค์ •ํ•œ ๊ฒƒ์ด๋‹ค.

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - run: ./build_server.sh
  test:
    needs: build
    runs-on: ubuntu-latest
    steps:
      - run: ./test_server.sh

runs-on

    runs-on: ubuntu-latest

runs-on์€ ์žก์„ ์‹คํ–‰ํ•  ์šด์˜์ฒด์ œ๋กœ Windows, Linux, macOS๋ฅผ ์ง€์ •ํ•  ์ˆ˜ ์žˆ๊ณ  ๋…ธ๋“œ๋ฅผ ์ง์ ‘ ์šด์˜ํ•˜๋Š” ๊ฒฝ์šฐ์—๋Š” self-hosted๋ฅผ ์ง€์ •ํ•  ์ˆ˜๋„ ์žˆ๋‹ค.

strategy

    strategy:
      matrix:
        node: [ 12,14,16 ]

strategy๋Š” ์œ„ ์„ค์ •์ฒ˜๋Ÿผ ๊ฐ™์€ ์žก์„ ์—ฌ๋Ÿฌ ๋ฒ„์ „์˜ ํ™˜๊ฒฝ์—์„œ ์‹คํ–‰ํ•˜๊ณ  ์‹ถ์„ ๋•Œ ํ–‰๋ ฌ์„ ๊ตฌ์„ฑํ•œ๋‹ค. ์œ„์—์„œ๋Š” Node.js 12, 14, 16๋ฒ„์ „์—์„œ๋งŒ ์‹คํ–‰ํ–ˆ์ง€๋งŒ os๊นŒ์ง€ ์ง€์ •ํ•˜๋ฉด ๋” ๋ณต์žกํ•œ ํ–‰๋ ฌ์„ ๊ตฌ์„ฑํ•  ์ˆ˜๋„ ์žˆ๋‹ค.

steps

    steps:
      - name: checkout to repository
          uses: actions/checkout@v2

      - name: Run a one-line script
        run: echo Hello, world!
      - run: npm test

steps๋Š” ์žก์˜ ์‹ค์ œ ๋™์ž‘์„ ์ •์˜ํ•˜๋Š” ๋ถ€๋ถ„์ด๋ฉฐ yaml๋ฌธ๋ฒ•์ƒ ํ•˜์ดํ”ˆ(-)์œผ๋กœ ๋ถ„๋ฅ˜๋˜์–ด ํ•˜๋‚˜์˜ step์ด ๊ตฌ์„ฑ๋œ๋‹ค.
name์€ ํ•„์ˆ˜๊ฐ’์ด ์•„๋‹ˆ์ง€๋งŒ, ํ•˜๋‚˜์˜ step์€ ํ•˜๋‚˜์˜ uses ๋˜๋Š” run ํ‚ค์›Œ๋“œ๊ฐ€ ์กด์žฌํ•ด์•ผ ํ•œ๋‹ค.
run ํ‚ค์›Œ๋“œ๋Š” ์‹œ์Šคํ…œ์˜ shell์— ์‹คํ–‰๋  ๋ช…๋ น์–ด๋ฅผ ์ง์ ‘ ์ž‘์„ฑํ•ด์ฃผ์–ด์•ผ ํ•˜์ง€๋งŒ,
usesํ‚ค์›Œ๋“œ๋Š” ์ด๋ฏธ ๋‹ค๋ฅธ ํšŒ์‚ฌ๋‚˜ ์‚ฌ๋žŒ๋“ค์ด ๋งŒ๋“ค์–ด์„œ ์˜ฌ๋ ค๋‘” ์•ก์…˜์„ ์„ค์ •์„ ํ†ตํ•ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด๋ ‡๊ฒŒ ๋งŒ๋“ค์–ด์ง„ ์•ก์…˜๋“ค์€ ๋งˆ์ผ“ํ”Œ๋ ˆ์ด์Šค์—์„œ ์‰ฝ๊ฒŒ ๊ณต์œ ํ•  ์ˆ˜ ์žˆ๋‹ค.


๋‚ด์šฉ์ด ๊ธธ์–ด์ง„ ๊ด€๊ณ„๋กœ ๋‹ค์Œ ๊ธ€์—์„œ ์ง์ ‘ ์›Œํฌํ”Œ๋กœ์šฐ๋ฅผ ์ž‘์„ฑํ•ด๋ณด๊ฒ ๋‹ค!๐Ÿ˜Ž

๐Ÿ™ ์ฐธ๊ณ 

'๊ฐœ์ธ๊ณต๋ถ€ > CI&CD' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

Github actions: ํ…Œ์ŠคํŠธ ์ž๋™ํ™” (with Slack)  (0) 2021.12.04