workflow_dispatch와 workflow_call을 사용하지 않을 때 기본값 설정하기


환경

  • Github Actions


배경

  • Github Actions에서 workflow_dispatchworkflow_call에 정의된 inputs을 사용하는 부분이 있었는데 이 부분이 push와 같이 다른 이유로 호출될 때 사용하지 못하는 이슈가 발생하여 기본값을 설정해두면 대처가 가능할거 같아 찾아서 정리했다.


방법

  • push와 같이 workflow_dispatchworkflow_call이 아니라서 inputs을 사용할 수 없는 경우 기본값을 설정할 수 있다.
  • workflow_dispatch 또는 workflow_call을 통해 실행된 workflow의 경우 inputs에 명시된 값을 사용하고 그렇지 않다면 || 뒤에 나온 기본값을 사용하는 방식이다.
  • 기본값을 환경변수에 저장하고 그 환경변수를 가져오는 방식이다.

코드

name: Workflow Return Test
on:
  push:
    branches: [ main ]
  workflow_call:
    inputs:
      key:
        type: string
  workflow_dispatch:
    inputs:
      key:
        type: string
jobs:
  print_default_value_test:
    name: print value
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v4
      - name: Set default value
        run: |
          echo "VALUE_NAME=${{ inputs.key || "default value" }}" >> $GITHUB_ENV
      - name: Print value
        run: echo "${{ env.VALUE_NAME }}"

결과

  • push를 통해 실행된 경우
Run echo "default value"
  echo "default value"
  shell: /usr/bin/bash -e {0}
  env:
    VALUE_NAME: default value
default value
  • “test input value”라는 문자열 값을 전달해 workflow_dispatch 또는 workflow_call을 통해 실행된 경우
Run echo "test input value"
  echo "test input value"
  shell: /usr/bin/bash -e {0}
  env:
    VALUE_NAME: test input value
test input value


의견

이렇게 하는게 권장하는 방법인지는 모르겠으나 검색했더니 나온 결과가 있어서 사용했다.


참고자료

Setting default value when not using workflow_dispatch and workflow_call


Environment and Prerequisite

  • Github Actions


Background

  • In GitHub Actions, there was an issue where the inputs defined in workflow_dispatch and workflow_call could not be used when triggered by other events like push. To address this, it seems that setting default value could be a potential solution so I wrote this.


Solution

  • In cases when inputs cannot be used like push because it is not triggered by workflow_dispatch or workflow_call, you can set default values as shown below.
  • For workflows triggered by workflow_dispatch or workflow_call, the values specified in inputs are used. Otherwise the default value following || is used.
  • Save default value to environment variable and use it.

Code

name: Workflow Return Test
on:
  push:
    branches: [ main ]
  workflow_call:
    inputs:
      key:
        type: string
  workflow_dispatch:
    inputs:
      key:
        type: string
jobs:
  print_default_value_test:
    name: print value
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v4
      - name: Set default value
        run: |
          echo "VALUE_NAME=${{ inputs.key || "default value" }}" >> $GITHUB_ENV
      - name: Print value
        run: echo "${{ env.VALUE_NAME }}"

Result

  • Triggered by push
Run echo "default value"
  echo "default value"
  shell: /usr/bin/bash -e {0}
  env:
    VALUE_NAME: default value
default value
  • Triggered by workflow_dispatch or workflow_call with passing string value “test input value”
Run echo "test input value"
  echo "test input value"
  shell: /usr/bin/bash -e {0}
  env:
    VALUE_NAME: test input value
test input value


Opinion

I’m not sure if this is the recommended one but I used it because I found it by searching.


Reference

Github Actions Matrix 사용법과 예제


환경

  • Github Actions


배경


사용법

  • 문서에 나온대로 아래와 같은 방법으로 사용할 수 있다.
  • jobs.<job_id>.strategy.matrix에 행렬의 변수와 값을 정의해주면 된다.
  • 아래 예제의 경우 version에 해당하는 값들이 [10, 12, 14]이며 os도 마찬가지이다.
jobs:
  example_matrix:
    strategy:
      matrix:
        version: [10, 12, 14]
        os: [ubuntu-latest, windows-latest]


예시

Jekyll 빌드를 여러 OS에서 실행하고 싶은 경우 아래처럼 작성할 수 있다. 실제로 이 블로그에 사용하는 workflow 예제다.

코드

  • 문서에 나온대로 적용했으며 다른 부분들도 포함되어 있지만 jobs에 있는 build job의 strategy를 보면된다.
  • os: [ubuntu-22.04, ubuntu-20.04, macos-latest]를 통해 사용할 os를 목록으로 정의했고 runs-on: ${{ matrix.os }}에서 해당 os들을 사용하도록 작성했다.
  • jobs.<job_id>.strategy.fail-fast 설정이 true이거나 해당 식이 true로 평가되면, matrix의 어떤 job이라도 실패할 경우 matrix에서 진행 중인 job과 대기 중인 job을 모두 취소한다고 문서에 나와 있다. 여러개의 job에서 하나가 실패하더라도 나머지 job들은 계속 진행하도록 하고 싶어서 false로 적용했다.
name: Jekyll Build CI

on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]
  workflow_dispatch:
    inputs:
      ruby-version:
        required: true
        type: string
        default: "3.2.2"
        
jobs:
  build:
    name: jekyll build
    strategy:
      matrix:
        os: [ubuntu-22.04, ubuntu-20.04, macos-latest]
      fail-fast: false
    runs-on: ${{ matrix.os }}
    steps:
    - name: Checkout Repository
      uses: actions/checkout@v4
    - name: Setup Ruby
      uses: ruby/setup-ruby@v1
      with:
        ruby-version: ${{ github.event.inputs.ruby-version }}
    - name: Install Bundler
      run: |
        gem install bundler
    - name: Install Dependencies
      run: |
        bundle install
    - name: Build Jekyll Site
      run: |
        bundle exec jekyll build

결과

  • 실행한 결과를 이미지로 보여주는게 이해하기 편해 이미지를 첨부한다


참고자료

Usage and example of github actions matrix


Environment and Prerequisite

  • Github Actions


Background


Usage

  • According to the document, you can use it as shown below.
  • jobs.<job_id>.strategy.matrix is where you define the variables and values for the matrix.
  • In the example below, the values corresponding to version are [10, 12, 14] and the same applies to os.
jobs:
  example_matrix:
    strategy:
      matrix:
        version: [10, 12, 14]
        os: [ubuntu-latest, windows-latest]


Example

If you want to run Jekyll builds on multiple OS, you can write it as shown below. This is a workflow example actually used in this blog.

Code

  • This include other steps but just look on strategy in jobs’s build.
  • Define os on statement os: [ubuntu-22.04, ubuntu-20.04, macos-latest] and use it on runs-on: ${{ matrix.os }}.
  • The documentation states that if jobs.<job_id>.strategy.fail-fast is set to true or its expression evaluates to true, GitHub will cancel all in-progress and queued jobs in the matrix if any job in the matrix fails. To allow remaining jobs to continue even if one job fails, I’ve set this to false.
name: Jekyll Build CI

on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]
  workflow_dispatch:
    inputs:
      ruby-version:
        required: true
        type: string
        default: "3.2.2"
        
jobs:
  build:
    name: jekyll build
    strategy:
      matrix:
        os: [ubuntu-22.04, ubuntu-20.04, macos-latest]
      fail-fast: false
    runs-on: ${{ matrix.os }}
    steps:
    - name: Checkout Repository
      uses: actions/checkout@v4
    - name: Setup Ruby
      uses: ruby/setup-ruby@v1
      with:
        ruby-version: ${{ github.event.inputs.ruby-version }}
    - name: Install Bundler
      run: |
        gem install bundler
    - name: Install Dependencies
      run: |
        bundle install
    - name: Build Jekyll Site
      run: |
        bundle exec jekyll build

Result

  • To make it easier to understand, I’m attaching an image that shows the results of the execution.


Reference

PyYAML 사용 시 키 이름 “on”이 True로 바뀌는 사례


환경

  • Github Actions
  • Python
  • PyYAML


배경

  • Github Actions Workflow 파일을 동적으로 Python을 통해 수정하는데 YAML 파일 파싱시 on이라는 키가 True로 바뀌는 상황이 발생해서 정리.


예시

아래와 같이 Python에서 yaml을 통해 파일을 읽어서 출력하면 on이 사라지고 True가 들어가 있는걸 볼 수 있다.

코드

import io
import yaml

file_content = """
name: Workflow Complete Event Test

on:
  workflow_run:
    workflows: [ "Push Main Branch" ]
    types:
      - completed
"""

file_like_object = io.StringIO(file_content)
yaml_content = yaml.safe_load(file_like_object)

print(yaml_content)

결과

{'name': 'Workflow Complete Event Test', True: {'workflow_run': {'workflows': ['Push Main Branch'], 'types': ['completed']}}}


이유

검색해보니 PyYAML의 경우 YAML 1.1 버전을 지원하고 있으며 1.1 버전의경우 "on"은 boolean으로 간주되며 그렇기에 True로 바뀌는게 맞다고 한다. YAML 1.2를 아직 지원하지 않다고 하기에 의도된 동작이며 방법을 따로 찾아야한다.


해결 방법

여러가지 방식이 있다.

  • Loader의 코드를 변경해서 설정
  • Key에 따옴표("" 또는 '')를 사용
  • 다른 Python 모듈 사용

따옴표가 눈에 띄어서 없애고 싶은 마음이 들지만 두번째 방식이 가장 간단해보이고 기존 yaml 모듈 변경이 없어서 해당 방식을 적용했다.

코드

import io
import yaml

file_content = """
name: Workflow Complete Event Test

'on':
  workflow_run:
    workflows: [ "Push Main Branch" ]
    types:
      - completed
"""

file_like_object = io.StringIO(file_content)
yaml_content = yaml.safe_load(file_like_object)

print(yaml_content)

결과

{'name': 'Workflow Complete Event Test', 'on': {'workflow_run': {'workflows': ['Push Main Branch'], 'types': ['completed']}}}


기타

True를 키 이름으로 사용

  • 키가 True로 잡히는데 Python에서 True를 사용하니 접근이 가능했다.

코드

import io
import yaml

file_content = """
name: Workflow Complete Event Test

on:
  workflow_run:
    workflows: [ "Push Main Branch" ]
    types:
      - completed
key:
  on: "test"
"""

file_like_object = io.StringIO(file_content)
yaml_content = yaml.safe_load(file_like_object)

print(yaml_content[True])

결과

{'workflow_run': {'workflows': ['Push Main Branch'], 'types': ['completed']}}


YAML 파일 생성 시 생성되는 키 이름

  • 여기서 yaml.dump를 통해 파일을 만들면 키는 true로 들어간다.

코드

import io
import yaml

file_content = """
name: Workflow Complete Event Test

on:
  workflow_run:
    workflows: [ "Push Main Branch" ]
    types:
      - completed
key:
  on: "test"
"""

file_like_object = io.StringIO(file_content)
yaml_content = yaml.safe_load(file_like_object)

with open('example.yaml', 'w') as file:
    yaml.dump(yaml_content, file)

결과

$ cat example.yaml
name: Workflow Complete Event Test
true:
  workflow_run:
    types:
    - completed
    workflows:
    - Push Main Branch
key:
  true: test


참고자료