[OSSCA] Challengers 3주차 Github Actions

뚜비·2022년 7월 30일
0

2022 OSSCA

목록 보기
6/14
post-thumbnail

2022 오픈소스 컨트리뷰션 아카데미 "NHN Toast Power Platform Connector" 프로젝트에 참여하면서 Challengers 기간 동안 배운 내용을 기록하였습니다.
github-actions-from-scratch를 추가로 공부하면서 기록하였습니다.
Github actions를 추가로 공부하면서 기록하였습니다.



✅ Github Actions?

CI/CD

DevOps 방법론에서 나온 말임!!

코드 작성, test, 빌드, 사용자에게 배포, 버그를 고치는 모든 과정에서는 cycle이 존재한다!(버그 고치려면 코드 작성 다시 해야 하니까!) -> 그러나 이런 과정은 자주 발생한다.

CI (지속적인 통합, Continuous Integration)

❗ 코드, 빌드, test 부분을 자동화(workflow Automation)해서 cycle이 좀 더 짧은 주기를 갖게 하는 것! ❗

  • 소프트웨어 개발 process는 위의 full cycle을 도는데, 이때 cycle의 주기를 짧게 하여 빠르게 자동화시키는 것
  • 새롭게 급부상하고 있는 컨셉

CD (지속적인 제공 / 배포, Continuous Delivery/Deployment)

코드, 빌드, 테스트, 배포 과정이 있는데 이때 배포가 개발환경에 배포되는 것일 수도 있고, 운영 환경에 배포되는 것일 수도 있다. 보통 개발환경에서 먼저 배포가 이루어진 다음에 운영환경에 배포한다.

  • Continuous delivery(지속적인 제공) : 코드부터 개발환경 까지는 자동으로 Full Cycle로 가게 한다. 이때 운영환경으로 가기 전에 수동으로 한다.

  • Continuous deployment(지속적인 배포) : 코드부터 운영환경까지 한번에 자동화한다.


결론

코드, 테스트, 빌드, 배포, 버그 이렇게 Full cycle을 도는 것에 있어서 무엇인가 이 주기의 생명주기를 짧게 하는 것이 CI / CD이다!

pr을 날렸을 때 자동으로 뭘 체크하거나 이슈 생성 했을 때,, 코멘트 남겼을 때 뭐가 되는 경우가 있음!

흠 깃헙 액션 사전 지식 배워야 할 듯..



Github action을 이해하기 위해 꼭 알아야 하는 용어

Github action을 이해하기 위해 꼭 알아야 하는 용어로 먼저 Workflowsaction이 있다.
workflows는 조금 더 큰 개념이라면 Actions는 작은 개념이다. 예를 들어 비유를 하자면 Workflow는 스탠드, 나무, 다이닝 세트라면 Actions는 전구, 잎, 포크 인 것! 즉 actions는 workflows에 속하는 개념이다.


이때 컴포넌트에는 네 개의 단계가 있다. Workflow -> Job -> Step -> Action로 점점 작아진다.



✅ 실습

환경설정

VsCode extension에서 위의 두 extensions을 설치하면 된다!



Basic Syntax

main.yaml

name : 'My First GitHub Actions Workflow' 

on: push 
# on은 깃허브 액션이 작동하게 하는 trigger 같은 것 
jobs: 
  fist-job: 
    name: 'first Job'
    runs-on : 'ubuntu-latest'
    # ['windows-latest', 'ubuntu-latest','macos-latest'] # 어떤 운영체제에서 실행시킬 것인지 설정!! 이건 3개의 OS에서 동시에 실행 가능! 
    
    steps:
    - name: 'Say Hello World on step 1'
      shell: bash
      run: |
        echo "Hello World from Step 1"

    - name: 'Say Lorem Ipsum on step 2'
      shell: pwsh
      run: |
        echo "Lorem Ipsum on step 2"

# on에 대해 어떤 일을 하게 하는지 정의
# 각각의 job은 독립적인 서버(머신)라고 생각!! 그래서 서로 관여 못하고 데이터를 받을 수 없음
# 기본적으로 job 하나당 서버 하나!

해당 코드를 깃허브에 push 해보자!

깃허브 Actions에 보면 First Job이 잘 실행된 것을 볼 수 있다.



Environment Variables

name : 'My First GitHub Actions Workflow' 

on: push 
# on은 깃허브 액션이 작동하게 하는 trigger 같은 것 

env:
  WORKFLOW_LEVEL: 'This value comes fom the workflow level'

jobs: 
  fist-job: 
    name: 'first Job'
    runs-on : 'ubuntu-latest'
   
    env:
      JOB_LEVEL_1: 'This value comes fom the job level 1'
    steps:
    - name: 'Say Hello World on step 1'
      shell: bash
      env:
       STEP_LEVEL_1: 'This value comes fom the step 1'
      run: |
        echo "Hello World from Step 1"
        echo "workflow level : $WORKFLOW_LEVEL"
        echo "job level 1 : $JOB_LEVEL_1"
        echo "job level 2 : $JOB_LEVEL_2"
        echo "step level 1 : $STEP_LEVEL_1"
        echo "step level 2 : $STEP_LEVEL_2"
    # step1에서 $로 접근

    - name: 'Say Lorem Ipsum on step 2'
      shell: pwsh
      env:
       STEP_LEVEL_2: 'This value comes fom the step 2'
      run: |
        echo "Lorem Ipsum on step 2"
        echo "workflow level: $env:WORKFLOW_LEVEL"
        echo "job level 1 : $env:JOB_LEVEL_1"
        echo "job level 2 : $env:JOB_LEVEL_2"
        echo "step level 1 : $env:STEP_LEVEL_1"
        echo "step level 2 : $env:STEP_LEVEL_2"
    # step2에서 환경 변수로 접근, 이때 STEP 간에 변수 공유가 되는지 확인 

#power shell은 변수 가져오는 방식이 다르다!(bash랑 다름 주의)
#job이 다른 경우에도 변수간에 접근이 가능한지 확인해보기 위해 
  second-job:
      name: 'second Job'
      runs-on : 'ubuntu-latest'
      env:
        JOB_LEVEL_2: 'This value comes fom the job level 2'
      steps:
        - name: 'Say Hello World on step 1'
          shell: bash
          env:
            STEP_LEVEL_1: 'This value comes fom the step 1'
          run: |
            echo "Hello World from Step 1"
            echo "workflow level: $WORKFLOW_LEVEL"
            echo "job level 1 : $JOB_LEVEL_1"
            echo "job level 2 : $JOB_LEVEL_2"
            echo "step level 1 : $STEP_LEVEL_1"
            echo "step level 2 : $STEP_LEVEL_2"

        - name: 'Say Lorem Ipsum on step 2'
          shell: pwsh
          env:
            STEP_LEVEL_2: 'This value comes fom the step 2'
          run: |
            echo "Lorem Ipsum on step 2"
            echo "workflow level: $env:WORKFLOW_LEVEL"
            echo "job level 1 : $env:JOB_LEVEL_1"
            echo "job level 2 : $env:JOB_LEVEL_2"
            echo "step level 1 : $env:STEP_LEVEL_1"
            echo "step level 2 : $env:STEP_LEVEL_2"

위의 결과는 Fist Job의 결과인데 STEP 1에서는 Second Job의 값과 STEP2의 값이 안 나온다. 또한 STEP 2에서는 Second Job의 값과 STEP1의 값이 안 나온다.


위의 결과는 Second Job의 결과인데 STEP 1에서는 First Job의 값과 STEP2의 값이 안 나온다. 또한 STEP 2에서는 First Job의 값과 STEP1의 값이 안 나온다.

어느 레벨에서 환경변수 값을 놓을 것이냐에 따라, 참조 가능한 위치가 달라진다. 그래서 scope를 잘 해둬야 한다.

$ vs $env. vs ${{ }} 차이?

  • run 키로 읽혀지는 환경 변수는 runner 운영체제에서 읽혀진다. job이 runner로 보내진 뒤 변수들이 대체된다.
  • env.으로 표현하면 workflow가 runner로 보내기 전 처리해야 할 때 대체되어 사용할 수 있다.
  • ${{ }} 의 경우 환경 변수를 setting하고 context나 function에 접근하기 위한 표현식이라고 한다.


Runtime Environment Variables

name : 'My First GitHub Actions Workflow' 

on: push 
# on은 깃허브 액션이 작동하게 하는 trigger 같은 것 

env:
  WORKFLOW_LEVEL: 'This value comes fom the workflow level'

jobs: 
  fist-job: 
    name: 'first Job'
    runs-on : 'ubuntu-latest'
    # ['windows-latest', 'ubuntu-latest','macos-latest'] # 어떤 운영체제에서 실행시킬 것인지 설정!! ㅣ건 3개의 OSd에서 동시에 실행 가능! 
  
    steps:
    - name: 'Set environment variable 1'
      shell: bash
      run: |
        echo "STEP_1 ='This value comes from the step 1'" >> $GITHUB_ENV
    # GITHUB_ENV에 "STEP1~"을 저장해라!
    - name: 'Set environment variable 2'
      shell: pwsh
      run : |
        echo "STEP_2 ='This value comes from the step 2'" | Out-File -FilePath $env:GITHUB_ENV -Encoing utf-8 -Append

    - name : 'Get environment variables'
      shell: bash
      run: |
        echo "WORKFLOW: ${{ env.WORKFLOW_LEVEL }}"
        echo "STEP 1: ${{ env.STEP_1 }}"   
        echo "STEP 2: ${{ env.STEP_2 }}"

이렇게 깃허브 환경변수에 값을 runtime 중에 추가해줄 수도 있다! 이때 주의할 점은 var_name = 'expession' 이렇게 변수명과 변수값과 '=' 사이에 공백이 있으면 값이 할당이 안 될 수도 있다. 꼭 붙여주자.



Output Values Reference와 Output Values Mask

name : 'My First GitHub Actions Workflow' 

on: push 

env:
  WORKFLOW_LEVEL: 'This value comes fom the workflow level'

jobs: 
  fist-job: 
    name: 'first Job'
    runs-on : 'ubuntu-latest'
  
    steps:
    - name: 'Set output value 1'
      id: step1
      shell: bash
      run: |
        STEP_1='This value comes from the step 1'
        echo "::add-mask::$STEP_1" 
        echo "::set-output name=value1::$STEP_1"
# bash에서 변수 값을 할당할 때 그냥 변수명='값'만 써줘도 된다.
    - name: 'Set output value 2'
      id: step2
      shell: pwsh
      run : |
        $STEP_2='This value comes from the step 2'
# pwsh에서 변수 값을 할당하려면 $를 써줘야 한다. 
        echo "::set-output name=value2::$STEP_2"

    - name : 'Get values'
      shell: bash
      run: |
        echo "STEP 1: ${{ steps.step1.outputs.value1 }}"
        echo "STEP 2: ${{ steps.step2.outputs.value2 }}"
# STEP1 output은 마스크 처리 됨. 

먼저 STEP1이라는 변수에 값을 할당해준다. 그 다음에 output 변수 이름을 value1 이라 하고 STEP1을 할당해준다. 이때 set-ouput은 다른 step에서 참조해줄 수 있게 한다.
위의 사진처럼 add-mask하면 민감 정보를 ***으로 표시하게 한다.



GitHub Secrets

Settings에 들어가서 Secrets을 선택하고 New repository secret을 선택해보장


이런식으로 값을 입력해주었다!

name : 'My First GitHub Actions Workflow' 

on: push  

env:
  WORKFLOW_LEVEL: 'This value comes fom the workflow level'

jobs: 
  fist-job: 
    name: 'first Job'
    runs-on : 'ubuntu-latest'
  
    steps:
    - name: 'Set output value 1'
      id: step1
      shell: bash
      run: |
        STEP_1='This value comes from the step 1'

        echo "::add-mask::$STEP_1"
        echo "::set-output name=value1::$STEP_1"

    - name: 'Set output value 2'
      id: step2
      shell: pwsh
      run : |
        $STEP_2='This value comes from the step 2'

        echo "::set-output name=value2::$STEP_2"

    - name : 'Get values'
      shell: pwsh
      run: |
        echo "STEP 1: ${{ steps.step1.outputs.value1 }}"
        echo "STEP 2: ${{ steps.step2.outputs.value2 }}"
        echo "SECRET 1: ${{ secrets.SECRET_1 }}"

        if ("${{ secrets.SECRET_1 }}" -eq "Hello World") { # SECRET_1은 Hello임
           echo "TRUE"
        } else {
          echo "FALSE"
        }


이렇게 Secret은 자동으로 *** 표시가 된다는 것을 알 수 있고 기댓값 FALSE도 잘 나왔다.



Matrix & Conditions

Matrix 1 : 운영체제 다르게

name : 'My First GitHub Actions Workflow' 

on: push 

env:
  WORKFLOW_LEVEL: 'This value comes fom the workflow level'

jobs: 
  fist-job: 
    name: 'first Job'

    strategy:
      matrix:
        os: ['windows-latest', 'ubuntu-latest','macos-latest']

    runs-on : ${{ matrix.os }}
    # 즉 first job이 각 os에서 총 3번 돈다! 
  
    steps:
    - name: 'Say Hello on ${{ matrix.os }}'
      shell: bash
      run: |
        echo "Hello from ${{ matrix.os }}"

strategy, matrix, runs-on keyword를 통해 각 os에서 setp이 실행될 수 있도록 한다.



Matrix #2 : 운영체제와 nodejs 버전 다르게

name : 'My First GitHub Actions Workflow' 

on: push 

env:
  WORKFLOW_LEVEL: 'This value comes fom the workflow level'

jobs: 
  fist-job: 
    name: 'first Job'

    strategy:
      matrix:
        os: ['windows-latest', 'ubuntu-latest','macos-latest']
        nodejs : ['14.x', '16.x']

    runs-on : ${{ matrix.os }}
    # 즉 first job이 각 os에서 3번 돈다! 
  
    steps:
      - name: 'Setup node.js version'
        uses: actions/setup-node@v3
        with:
          node-version: ${{ matrix.nodejs }}

      - name: 'Check node.js version on ${{ matrix.os }}'
        shell: bash
        run: |
          echo "nodejs version: $(node --version)"

## 즉 총 6번 돈다 os버전 * nodejs 버전 == 6

matrix의 os와 nodejs에 각각 접근한다.



Conditions on Jobs

name : 'My First GitHub Actions Workflow' 

on: push 

env:
  WORKFLOW_LEVEL: 'This value comes fom the workflow level'

jobs: 
  fist-job: 
    name: 'first Job'
    if: github.event_name == 'pull_request'

    strategy:
      matrix:
        os: ['windows-latest', 'ubuntu-latest','macos-latest']
        nodejs : ['14.x', '16.x']

    runs-on : ${{ matrix.os }}
  
    steps:
      - name: 'Setup node.js version'
        uses: actions/setup-node@v3
        with:
          node-version: ${{ matrix.nodejs }}

      - name: 'Run only on Windows'
        if: matrix.os == 'windows-latest'
        shell: bash
        run: |
          echo "Windows Only"

      - name: 'Run not on Windows'
        if: matrix.os != 'windows-latest'
        shell: bash
        run: |
          echo "Not Windows"


      - name: 'Check node.js version on ${{ matrix.os }}'
        shell: bash
        run: |
          echo "nodejs version: $(node --version)"

즉 pull request라는 trigger가 발생해야만 job이 실행되므로
아예 실행이 안 된다.



Conditions on Steps

name : 'My First GitHub Actions Workflow' 

on: push 
# on은 깃허브 액션이 작동하게 하는 trigger 같은 것 

env:
  WORKFLOW_LEVEL: 'This value comes fom the workflow level'

jobs: 
  fist-job: 
    name: 'first Job'

    strategy:
      matrix:
        os: ['windows-latest', 'ubuntu-latest','macos-latest']
        nodejs : ['14.x', '16.x']

    runs-on : ${{ matrix.os }}
    # 즉 first job이 각 os에서 3번 돈다! 
  
    steps:
      - name: 'Setup node.js version'
        uses: actions/setup-node@v3
        with:
          node-version: ${{ matrix.nodejs }}

      - name: 'Run only on Windows'
        if: matrix.os == 'windows-latest'
        shell: bash
        run: |
          echo "Windows Only"

      - name: 'Run not on Windows'
        if: matrix.os != 'windows-latest'
        shell: bash
        run: |
          echo "Not Windows"


      - name: 'Check node.js version on ${{ matrix.os }}'
        shell: bash
        run: |
          echo "nodejs version: $(node --version)"

즉 os가 Window인 경우와 아닌 경우로 조건을 나누어 각각 처리를 다르게 해주었는데 ubuntu는 window가 아니니 Run only on Winodw라는 step은 실행되지 못한 것을 확인할 수 있다.



Job Chaining

작업 순서가 정해진 경우! needs를 쓰면 된다.

name : 'My First GitHub Actions Workflow' 

on: push  

env:
  WORKFLOW_LEVEL: 'This value comes fom the workflow level'

jobs: 
  build-job: 
    name: 'build Job'

    runs-on : ubuntu-latest

    steps:
      - name: 'Say Hello'
        shell: bash
        run: |
          echo "Hello World"

  deploy-to-dev-job:
    name: 'Deployment Job to DEV'
    needs:
    - build-job
# build-job이 실행된 후에 실행해줘! 
    runs-on: ubuntu-latest

    steps:
      - name: 'Say DEV'
        shell: bash
        run: |
          echo "DEVELOPERS"

  deploy-to-prod-job:
    name: 'Deployment Job to PROD'
    needs:
    - build-job
# build-job이 실행된 후에 실행해줘! 
    runs-on: ubuntu-latest

    steps:
      - name: 'Say PROD'
        shell: bash
        run: |
          echo "PRODUCTION"
    
# 반드시 작업 순서가 정해진 채로 실행되어야 하는 경우

즉 build가 끝나야 다른 task가 실행되는 것을 확인할 수 있습니다. 이때 task 2개는 어떤 task가 먼저 실행해도 상관없다.



####
name: 'My First GitHub Actions Workflow'

on: push

jobs:
  build-job:
    name: 'Build Job'
    runs-on: ubuntu-latest

    steps:
      - name: 'Say Hello'
        shell: bash
        run: |
          echo "Hello World"

  deploy-to-dev-job:
    name: 'Deployment Job to DEV'
    runs-on: ubuntu-latest

    steps:
      - name: 'Say DEV'
        shell: bash
        run: |
          echo "DEVELOPERS"
          
  deploy-to-prod-job:
    name: 'Deployment Job to PROD'
    needs:
    - build-job
    - deploy-to-dev-job
# build랑 deploy 끝나면 실행 
    runs-on: ubuntu-latest

    steps:
      - name: 'Say PROD'
        shell: bash
        run: |
          echo "PRODUCTION"

이 경우는 먼저 두 task를 실행한 후에 다음 task가 실행되어야 한다. 이때 두 task의 실행 순서는 상관없다.



이어서 계속...

profile
SW Engineer 꿈나무 / 자의식이 있는 컴퓨터

0개의 댓글