step
이나 job
에서 사용할 수 있는 환경 변수를 key-value 쌍으로 넣을 수 있다.
환경 변수를 구성하는 방법은 두 가지가 있는데,
1. env
2. 미리 정리
env
방식은 workflow level, job level, step level에서 작성하면 된다.
name: env level
on:
workflow_dispatch
env:
level: workflow # workflow level
jobs:
get-env-1:
runs-on: ubuntu-latest
steps:
- name: check env
run: echo "LEVEL ${{ env.level }}"
name: env level
on:
workflow_dispatch
jobs:
get-env-2:
runs-on: ubuntu-latest
env:
level: job # job level
steps:
- name: check env
run: echo "LEVEL ${{ env.level }}"
name: env level
on:
workflow_dispatch
jobs:
get-env-3:
runs-on: ubuntu-latest
env:
level: job
steps:
- name: check env
run: echo "LEVEL ${{ env.level }}"
env:
level: step # step level
만약 중복해서 써있다면 step
level > job
level > workflow
level 순서이다.
참고로 env
사용 방법 이외에 다음과 같이 사용할 수도 있다.
...
jobs:
get-env-3:
runs-on: ubuntu-latest
env:
level: job
steps:
- name: create env
run: |
echo "level=job" >> $GITHUB_ENV
- name: check env
run: echo "LEVEL ${{ env.level }}"
echo "key=value" >> $GITHUB_ENV
형식으로 env값을 넣을 수 있다. 재밌는 것은 GITHUB_ENV.level
로 가져오는 것이 아니라, $GITHUB_ENV
에 값을 넣으면 env
로 가져올 수 있다는 것이다.
test를 위한 workflow를 만들어보도록 하자.
name: var-1
on: push
env:
level: workflow # workflow level
jobs:
get-env-1:
runs-on: ubuntu-latest
steps:
- name: check env
run: echo "LEVEL ${{ env.level }}" # workflow level
get-env-2:
runs-on: ubuntu-latest
env:
level: job # job level
steps:
- name: check env
run: echo "LEVEL ${{ env.level }}" # job level
get-env-3:
runs-on: ubuntu-latest
env:
level: step
steps:
- name: check env
run: echo "LEVEL ${{ env.level }}" # step level
env:
level: step # step level
echo-env-4:
runs-on: ubuntu-latest
steps:
- name: create env
run: echo "level=echo" >> $GITHUB_ENV
- name: check env
run: echo "LEVEL ${{ env.level }}" # step level
get-env-1
job은 workflow env 값을 가져온다. LEVEL workflow
가 결과로 나온다.get-env-2
job은 job env 값을 가져온다. LEVEL job
가 결과로 나온다.get-env-3
job은 step env 값을 가져온다. LEVEL step
가 결과로 나온다.get-env-4
job은 step env 값을 가져온다. LEVEL echo
가 결과로 나온다. 다음은 미리 환경변수를 설정하는 방법은 gitub에서 설정하는 방법도 있다.
github repo -> Settings -> Secrets and variables -> Actions -> Envrionment secrets -> Manage environments 로 설정해주면 된다.
민감한 데이터를 안전하게 저장해서 workflow에서 사용하는 것이다. 민감 정보를 코드와 분리하여 노출되는 것을 방지하는 것이다. 주로 암호, 인증 토큰 같은 것들이 있다.
github에서 안전하게 암호화하여 저장하며, 로그에 기록되지 않고 출력 시 마스킹된다. workflow 시에서만 접근할 수 있다.
secret을 사용하기 위해서는 secret을 정의해야하는데, github에서 설정이 가능하다.
github repo -> Settings -> Secrets and variables -> Actions -> New repository secret -> Name-Secret 설정 -> Add secret
Name은 level
, Secret은 secret
으로 저장해보도록 하자.
name: secrets
on: push
jobs:
get-secrets:
runs-on: ubuntu-latest
steps:
- name: get secrets
run: echo ${{ secrets.level }}
git push 후에 github에서 확인하면 echo ***
으로 출력된 것을 볼 수 있다.
특정 환경에서만 사용 가능한 환경변수와 secret 관리로 respository에서 정의할 수 있다.
env와 secret 모두 3가지 환경이 있다.
1. environment secrets/env
2. repository secrets/env
3. organization secretsenv
순서는 environment > repository > organization 이다.
environment의 경우 여러 environment들을 만들고, 이를 workflow에서 지정할 수 있다.
github -> Settings -> Code and automation -> Environments -> New environment -> Name: test 생성 -> Environment variables -> Add variable -> LEVEL=test 입력
workflow에서는 enviroment
라는 keyword를 사용하여 환경 변수 설정들을 가져올 수 있다.
name: environment
on: push
jobs:
get-env-dev:
runs-on: ubuntu-latest
environment: test
steps:
- name: check env & secret
run: |
echo ${{ vars.LEVEL }}
environment
로 test
환경을 가져오는 것이고, env값을 가져올 때는 vars.key
를 사용하고, secret값을 가져올 때는 secrets.key
를 사용한다.
결과로 test
가 나올 것이다.
변수 기반으로 여러 job을 실행하는 기능으로 matrix를 사용해 하나의 job을 구성하면 여러 개의 job을 실행하도록 할 수 있다.
가령, 변수로 window, linux, macOS를 설정하여 하나의 job을 구성해 runner가 다른 job을 3개 실행할 수 있다. 또한, python3.7~3.9 변수를 설정해 하나의 job을 python3.7, python3.8, python3.9에서 실행할 수 있도록 할 수 있다.
...
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
version: [3.7, 3.8, 3.9]
steps:
- name: checkout
uses: actions/checkout@v3
- name: setup python
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.version }}
- name: run python
run: python script.py
위의 경우 python 버전을 구성할 때, 버전 별로 구성이 가능하다.
strategy.matrix
아래의 key: []
값으로 여러 개의 값을 넣어 줄 수 있고, 이를 활용하여 정의한 하나의 job에 대해서 여러 환경에서의 실행이 가능하다.
...
jobs:
get-matrix:
strategy:
matrix:
os: [macos-latest, windows-latest, ubuntu-latest]
version: [12, 14, 16]
runs-on: ${{ matrix.os }}
steps:
- name: echo matrix value
run: |
echo ${{ matrix.os }}
echo ${{ matrix.version }}
이렇게 설정해두면, github action은 9개의 job을 실행하는데 다음과 같다.
1. macos-latest:12
2. macos-latest:14
3. macos-latest:16
4. windows-latest:12
5. windows-latest:14
6. windows-latest:16
7. ubuntu-latest:12
8. ubuntu-latest:14
9. ubuntu-latest:16
즉, matrix는 실행 가능한 모든 조합에 대해서 job으로 만들어 실행하는 것이다.
name: matrix
on: push
jobs:
get-matrix:
strategy:
matrix:
os: [windows-latest, ubuntu-latest]
version: [12, 14]
runs-on: ${{ matrix.os }}
steps:
- name: check matrix
run: |
echo ${{ matrix.os }}
echo ${{ matrix.version }}
총 4개의 job이 생성하게 될 것이다.
특정 조건이 충족될 때만 실행되도록 하는 데 사용한다. 사용 방법은 기존의 다른 언어와 별반 다를 바가 없다.
if condition의 실행은 다음의 level에서 가능하다.
1. job level: job 실행 여부
2. step level: step 실행 여부
name: if-condition
on:
push:
workflow_dispatch:
jobs:
job1:
runs-on: ubuntu-latest
if: github.event_name == 'push' # job level
steps:
- name: get event name
run: |
echo ${{ github.event_name }}
job2:
runs-on: ubuntu-latest
if: github.event_name != 'push' # job level
steps:
- name: get event name
run: |
echo ${{ github.event_name }}
위의 workflow에서는 push
와 workflow_dispatch
event일 때만 실행되는데, if
condition으로 해당 workflow의 event를 식별하여 job을 실행한다.
name: if-condition
on:
push:
workflow_dispatch:
jobs:
job1:
runs-on: ubuntu-latest
steps:
- name: get event name
if: github.event_name == 'push' # step-level
run: |
echo ${{ github.event_name }}
- name: get event name
if: github.event_name != 'push' # step-level
run: |
echo ${{ github.event_name }}
위는 이전에 있던 workflow에서 job level의 if condition을 step level로 바꾼 것 뿐이다.
참고로, fileter와 if condition이 약간 role이 겹치는데, 다음과 같다고 생각하면 된다.
가령 dev branch일 때만 workflow 실행은 filter가 하지만, dev branch에 대한 workflow가 실행되었을 때 특정 job만 실행은 if condition이 한다.
if condition에는 특정 job과 step을 강제로 실행 가능하도록 할 수 있다.
if: always()
위와 같이 설정 시 특정 job과 step을 강제로 실행할 수 있다.
name: if-condition
on:
push:
workflow_dispatch:
jobs:
job1:
runs-on: ubuntu-latest
steps:
- name: exit 1
run: exit 1 # 강제 종료
- name: echo
run: echo hello
job2:
needs: [job1]
runs-on: ubuntu-latest
steps:
- name: echo
run: echo hello
위와 같은 경우에는 job1에서 exit 1
을 호출하여 workflow 자체를 강제 종료하고 있다. 즉, job2
는 실행되지 않는다.
그런데 여기서 job2
에 if: always()
를 사용하면 job1
이 실패해도 job2
가 실행될 수 있다,.
name: if-condition
on:
push:
workflow_dispatch:
jobs:
job1:
runs-on: ubuntu-latest
steps:
- name: exit 1
run: exit 1 # 강제 종료
- name: echo
run: echo hello
job2:
needs: [job1]
runs-on: ubuntu-latest
if: always() # job-level
steps:
- name: echo
run: echo hello
job2
가 job1
에 대해서 needs
로 의존성을 가지고 있다하더라도 job2
가 if: always()
를 가지고 있어 반드시 실행된다.
job-level 뿐만 아니라 step-level도 가능하다.
name: if-condition
on:
push:
workflow_dispatch:
jobs:
job1:
runs-on: ubuntu-latest
steps:
- name: exit 1
run: exit 1 # 강제 종료
- name: echo
if: always() # step-level
run: echo hello
exit 1
step에서 workflow를 강제 종료 시키는 exit 1
을 실행시켜도 echo
step이 if: always()
이기 때문에 무조건 실행된다.
문자열에 대한 조건 검사를 수행하여 job 또는 step 실행 여부를 결정한다.
startsWith
은 첫번째 인자에 대해서 두번째 인자의 값이 앞부분에 있는 지 없는 지 검사한다.
endsWith
은 첫번째 인자에 대해서 두번째 인자의 값이 뒷부분으로 끝나는 지 검사한다.
contains
는 첫번째 인자인 문자열, 배열안에 두번째 인자의 값이 있는 지 없는 지 검사한다.
참고로 github action에서는 배열이 문자열에서 ,
로 구분한 것을 말한다.
name: string-function
on: push
jobs:
string-function:
runs-on: ubuntu-latest
steps:
- name: startswith
if: startsWith('github actions', 'git')
run: echo 'git'
- name: startsWith
if: startsWith('github actions', 'test')
run: echo 'test'
- name: endswith
if: endsWith('github actions', 'ions')
run: echo 'ions'
- name: endswith
if: endsWith('github actions', 'test')
run: echo 'test'
- name: contains
if: contains('github actions', 'act')
run: echo 'contains act'
- name: contains
if: contains('github, actions', 'git')
run: echo 'contains git'
git push
로 해당 workflow를 넣어보면 문제없이 실행되는 것을 볼 수 있을 것이다.