κ°œμΈκ³΅λΆ€/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ν‚€μ›Œλ“œλŠ” 이미 λ‹€λ₯Έ νšŒμ‚¬λ‚˜ μ‚¬λžŒλ“€μ΄ λ§Œλ“€μ–΄μ„œ μ˜¬λ €λ‘” μ•‘μ…˜μ„ 섀정을 톡해 μ‚¬μš©ν•  수 μžˆλ‹€. μ΄λ ‡κ²Œ λ§Œλ“€μ–΄μ§„ μ•‘μ…˜λ“€μ€ λ§ˆμΌ“ν”Œλ ˆμ΄μŠ€μ—μ„œ μ‰½κ²Œ κ³΅μœ ν•  수 μžˆλ‹€.


λ‚΄μš©μ΄ 길어진 κ΄€κ³„λ‘œ λ‹€μŒ κΈ€μ—μ„œ 직접 μ›Œν¬ν”Œλ‘œμš°λ₯Ό μž‘μ„±ν•΄λ³΄κ² λ‹€!😎

πŸ™ μ°Έκ³