github action을 배워보자 1일차 - 개요

0

github action

목록 보기
1/3

Github action component

github action 주요 component로는 다음이 있다.

  1. workflow: 하나 이상의 작업을 실행하는 구성 가능한 자동화 프로세스로 .github/workflows 경로에 파일이 있어야하고, 여러 개의 workflow들이 있을 수 있다.
  2. event: workflow를 실행을 트리거하는 github repo 내의 특정 활동으로 push, pull 등이 있고, 시간, 외부 요청으로도 가능하다.
  3. runner: job을 실행할 수 있는 서버로 각 runner는 하나의 job을 실행할 수 있다.
  4. job: job은 동일한 runner에서 실행될 수 있는 각 step들의 집합이다. workflow안에 job들은 여러 개가 있을 수 있는데, 병렬 실행, 순차 실행(needs)이 가능하다.
  5. step: job이 실행하는 개별 명령, 순차적으로 실행되며 한 step이 실패하면, 그 다음 step은 실행되지 않는다.
  6. action: 특정 작업을 수행하는 코드 조각, uses 라는 키워드를 이용해서 action을 로드한다. 하나의 step에서 하나의 action만 사용할 수 있다.

action에는 github에서 공식 제공 action과 community에서 만든 action, 사용자가 직접 만든 action들도 있다.

Event ---> -------Runner:unbuntu-latest--------
           | job: check-bats-version--------- |
           | | step1: check out repo        | |
           | | - uses: actions/checkout@v3  | |
           | |                              | |
           | | step2: install Node.js       | |
           | | - uses: actions/setup-node@v3| |
           | -------------------------------- |
           ------------------------------------ 

setup-node라는 action으로 nodejs를 쉽게 설치할 수 있는 것이다.

github marketplace는 action의 저장소로 직접 만든 custom action을 publish할 수 있다. 필요한 기능이 있다면 사용하는 게 편리하다.

checkout이라는 github action을 사용할 수 있느데, 여기서 사용 방법들 나열된 것을 볼 수 있다.

- uses: actions/checkout@v4
  with:
    # Repository name with owner. For example, actions/checkout
    # Default: ${{ github.repository }}
    repository: ''

    # The branch, tag or SHA to checkout. When checking out the repository that
    # triggered a workflow, this defaults to the reference or SHA for that event.
    # Otherwise, uses the default branch.
    ref: ''
    ...

with은 하나의 parameter를 받는 것으로 repositoryref라는 parameter를 받는다는 것이다. 이는 다른 repo의 특정 code나 다른 branch의 code를 사용하고 싶다면 여기에 입력해주면 된다.

github action의 핵심은 event에 따른 action인 것이다. 따라서, 어떠한 event들이 먼저 알아보고, 이에 따른 action들에 대한 example들을 살펴보자

push event

git push event가 발생하면 github action이 발생하도록 하는 것이다. 자신의 github repo에 .github/workflows 디렉터리를 만들고 다음의 파일을 만들도록 하자.

  • .github/workflows/push.yaml
name: push-workflow
on: push # event

jobs:
  push-job:
    runs-on: ubuntu-latest # runner
    steps: # job이 실행할 step들을 순차적으로 적는다.
    - name: step1
      run: echo hello world
    - name: step2
      run: |
        echo hello world
        echo githu action

다른 github action을 실행시키기 위해서 .github/workflows/push.yaml.github/workflows/push/push.yaml에 저장시키도록 하자. 이렇게두면 push.yaml이 실행되지 않는다.

pull request event

pull request가 실행되면 발생하는 event를 만들어보도록 하자.

  • .github/workflows/pull_request.yaml
name: pull-request-workflow
on: pull_request

jobs:
  pull-request-job:
    runs-on: ubuntu-latest # runner
    steps: # job이 실행할 step들을 순차적으로 적는다.
    - name: step1
      run: echo hello world
    - name: step2
      run: |
        echo hello world
        echo github action

다른 branch를 하나 만들고 commit을 올려주도록 하자.

git switch -c test1
echo "h" >> ./README.md 
git add ./README.md
git commit -m "add2"
git push origin test1

이제 github로 가서 pull request를 만들어주도록 하자, 단 'Merge pull request' 버튼은 누르지 않도록 하자. pull request가 올라간 것 만으로도 github action이 실행될 것이다.

한번 더 commit을 만들어주면 이전에 만들었던 pull request에 commit이 추가될 것이다.

git switch -c test1
echo "h" >> ./README.md 
git add ./README.md
git commit -m "add2"
git push origin test1

그런데, 이상한 것이 있다. github action을 보면 action이 두 번 실행되었을 것이다. 즉, 새로 올린 commit에 대해서 pull request를 만들지 않고, 기존 pull request에 포함된 것임에도 불구하고 github action이 또 실행되는 것이다.

왜 이렇게 되었냐면, pull_requeston에 설정할 때 default activity 때문에 그렇다. 만약 pull request를 open시킬 때만 github action을 실행시키고 싶었다면 다음과 같이 정의하면 된다.

  • .github/workflows/pull_request.yaml
name: pull-request-workflow
on:
  pull_request:
    types: [opened]

jobs:
  pull-request-job:
    runs-on: ubuntu-latest # runner
    steps: # job이 실행할 step들을 순차적으로 적는다.
    - name: step1
      run: echo hello world
    - name: step2
      run: |
        echo hello world
        echo github action

이런식으로 정의하면 pull request가 생성된 시점에만 실행된다. 모든 event들이 activity type이 있는 것은 아니고, event마다 activity type이 다르다.

issue event

issue event는 bug, 기능 요청, 질문, 논의 등 추적 및 관리하기 위해서 사용하는데, project의 버그나 기능 개발 등의 진행 상황을 한눈에 파악할 수 있다. issue를 생성할 때 trigger되는 github action을 만들어보도록 하자. 단, issue event는 오직 default branch에 workflow가 있어야만 동작한다는 특징이 있다.

issue event도 activity가 있는데, default로 모든 issue에 대해서 trigger된다는 특징이 있다.

  • .github/workflows/issue.yaml
name: issue-workflow
on:
  issues:
    types: [opened]

jobs:
  push-job:
    runs-on: ubuntu-latest # runner
    steps: # job이 실행할 step들을 순차적으로 적는다.
    - name: step1
      run: echo hello world

issue가 open될 때에만 해당 github action이 실행된다.

issue comment event

issue comment는 issue에 comment를 생성하거나, pull request에 comment를 생성할 때 실행되는 action을 말한다. activity로 default는 모든 type들이고, type으로는 created, edited, deleted 3개가 있다.

  • .github/workflows/issue_comment.yaml
name: issue-comment-workflow
on: issue_comment

jobs:
  pr-comment:
    if: ${{ github.event.issue.pull_request }}
    runs-on: ubuntu-latest
    steps:
    - name: pr comment
      run: echo ${{ github.event.issue.pull_request }}

  issue-comment:
    if: ${{ !github.event.issue.pull_request }}
    runs-on: ubuntu-latest
    steps:
    - name: issue comment
      run: echo ${{ github.event.issue.pull_request }}

두 가지 job인 pr-commentissue-comment가 있는데, pr-comment는 pull request에 comment가 생기면 job을 실행하도록 하기위해서 if문을 ${{ github.event.issue.pull_request }}으로 써주었다. issue-comment는 issue에 comment가 추가될 때 실생되도록 if문에 ${{ !github.event.issue.pull_request }}을 넣어주었다.

이러한 코드를 context라고 한다. context를 넣어주면 유연한 동작이 가능하다.

schedule event

cron으로 특정 시간마다 github action을 실행시켜주는 것이다. default branch에 github workflow가 있어야 동작한다. 그러나, schedule은 부하가 많기 때문에 실행에 있어서 누락이 있을 가능성이 높다. 그래서 정확한 시간에 정확하게 실행되어야 하는 app에 대해서는 schedule을 쓰지 않도록 하자. 특히, 5분 30분 간격의 cron job들에 대해서는 누락이 많이 된다.

  • .github/workflows/schedule.yaml
name: schedule-workflow
on:
  schedule:
  - cron: '15 * * * *'

jobs:
  schedule-job:
    runs-on: ubuntu-latest
    steps:
    - name: schedule test
      run: echo hello world

workflow dispatch event

사용자가 원할 때 수동으로 trigger할 수 있는 event가 있는데, default branch에서만 동작한다. 또한, input 값을 넣을 수 있다는 특징이 있는데, input 데이터의 type으로는 다음과 같다.

  • string
  • number
  • boolean
  • choice

choice는 미리 옵션으로 지정한 것들을 넣을 수 있다.

  • .github/workflows/workflow_dispatch.yaml
name: workflow-dispatch
on:
  workflow_dispatch:
    inputs:
      name:
        description: 'set name'
        required: true
        default: 'github-actions'
        type: string
      environment:
        description: 'set env'
        required: true
        default: 'dev'
        type: choice
        options:
          - dev
          - prod

inputs이라는 keyword를 통해서 값을 받을 수 있는데, nameenvironment input을 파라미터로 받는다. 각 파라미터는 description, required, default, type을 설정해주어야 한다.

choice의 경우는 options를 통해서 설정이 가능하다.

이 input값들은 workflow의 job에서 다음과 같이 사용이 가능하다.

  • .github/workflows/workflow_dispatch.yaml
jobs:
  workflow-dispatch-job:
    runs-on: ubuntu-lates
    steps:
      - name: step1 echo hello world
        run: echo Hello, world!
      - name: step2 echo github action
        run: |
          echo hello, world!
          echo github action!
      - name: echo inputs
        run: |
          echo "NAME: ${{ inputs.name }}"
          echo "NAME: ${{ inputs.environment }}"

inputs.name, inputs.environment로 접근 가능한 것을 볼 수 있다.

  • .github/workflows/workflow_dispatch.yaml
name: workflow-dispatch
on: 
  workflow_dispatch:
    inputs:
      name:
        description: 'set name' 
        required: true
        default: 'github-actions'
        type: string
      environment:
        description: 'set env' 
        required: true
        default: 'dev'
        type: choice
        options:
          - dev
          - qa
          - prod

jobs:
  workflow-dispatch-job:
    runs-on: ubuntu-latest
    steps:
      - name: step1
        run: echo hello world
      - name: step2
        run: |
          echo hello world
          echo github action
      - name: echo inputs
        run: |
          echo ${{ inputs.name }}
          echo ${{ inputs.environment }}

github에 넣어준 다음에 github actions tab으로 가면 Run workflow라는 버튼이 있다. 이 버튼을 누르면 수동으로 실행시켜줄 수 있는 버튼들이 나온다.

다양한 event로 하나의 workflow trigger

on event에 여러 개의 event를 주도록 하여, 하나의 workflow를 실행시킬 수 있다.

  • .github/workflows/multiple-event-workflow.yaml
name: multiple-event-workflow
on:
  push:
  issues:
    types: [opened]
  workflow_dispatch:

jobs:
  multiple-event-job:
    runs-on: ubuntu-latest # runner
    steps: # job이 실행할 step들을 순차적으로 적는다.
    - name: step1
      run: echo hello world
    - name: step2
      run: |
        echo hello world
        echo github action

위의 코드는 push, issue가 열릴 때, 수동으로 workflow를 실행시킬 때 해당 job들이 실행된다는 것을 나타낸다. 따라서 여러 개의 event에 대해서 하나의 workflow를 실행시킬 수 있는 것이다.

needs

하나의 workflow에서 여러 개의 job을 정의해서 사용하는 경우가 많다.

jobs:
  pr-comment:
    if: ${{ github.event.issue.pull_request }}
    runs-on: ubuntu-latest
    steps:
    - name: pr comment
      run: echo ${{ github.event.issue.pull_request }}
  
  issue-comment:
    if: ${{ !github.event.issue.pull_request }}
    runs-on: ubuntu-latest
    steps:
    - name: issue comment
      run: echo ${{ github.event.issue.pull_request }}

이렇게 하나의 workflow에 여러 개의 job이 있는 경우, 병렬로 실행된다는 특징을 갖는다.

그런데, 순차적으로 실행이 필요한 경우가 있는데 이렇게 의존 관계가 있는 경우에는 needs를 사용한다.

needs는 하나의 job이 다른 job 또는 여러 job이 완료될 때, 실행되도록 할 수 있다. 이를 통해서 여러 job의 실행 순서를 조절할 수 있는 것이다.

가장 대표적인 경우가 test job이 실행되고 나서 배포 job이 실행되도록 할 수 있다.

  • .github/workflows/needs.yaml
name: needs
on: push

jobs:
  job1:
    runs-on: ubuntu-latest
    steps:
    - name: echo
      run: echo "job1 done"
  job2:
    runs-on: ubuntu-latest
    needs: [job1]
    steps:
    - name: echo
      run: echo "job2 done"
  job3:
    runs-on: ubuntu-latest
    steps:
    - name: echo
      run: |
        echo "job3 failed"
        exit 1
  job4:
    runs-on: ubuntu-latest
    needs: [job3]
    steps:
    - name: echo
      run: echo "job4 done"

job1이 실행되어 성공해야 job2가 실행되고, job3이 실행되어야 job4가 실행된다. 단, job3의 경우 exit 1을 주었는데, github action은 exit 1을 실행하면 실패로 여기기 때문에 job4는 실행되지 않을 것이다.

이제 code를 push해보고 결과를 확인해보도록 하자.

job1 o---------o job2
job3 o---------o iob4

이렇게 나오고 job1, job2는 실행되었지만, job3는 실행되지 않아 job4도 실행되지 않는 것을 볼 수 있다.

job3가 실패했으므로 re-run을 트리거할 수 있다. re-run은 과거에 실행된 workflow를 재실행하는 것으로, 성공과 실패의 상관없이 재실행이 가능하다. 단, trigger된 그 시점을 다시 실행하는 것이다.

즉, 특정 workflow를 re-run 시켜도 해당 workflow 이후의 commit들에 대해서 반영되지 않은, 딱 그 workflow가 실행된 처음 시점의 commit을 기준으로만 re-run되는 것이다. 따라서, 과거에 실행된 workflow를 re-run해도 수정한 내용은 반영되지 않는다. 수정한 파일이 포함된 commit을 만들고, 새로운 workflow가 실행되어야 반영되는 것이다.

+ commit1
workflow#1 --- commit1
+ commit2
workflow#2 --- commit2

commit1이 들어온 후에 workflow#1이 실행되었다고 하자. 이 다음 commit2가 들어와서 workflow#2가 실행되었는데, workflow#1을 re-run시켜버리면 commit2까지 반영된 코드가 아니라 commit만 반영된 code로 실행된다는 것이다.

0개의 댓글