Reusable workflowのすすめ (GitHub Actions)

# ワークフローの再利用

GitHub Actionsのワークフローで、よく使う内容をreusable workflowとしてまとめて再利用することができる。  
https://docs.github.com/en/actions/using-workflows/reusing-workflows

コピペを減らし、ワークフローのメンテナンス性を向上させることができる。
使用方法についてまとめた。

## 基本

ワークフローのトリガーに**workflow_call**を定義する。これによって、別のワークフローから呼び出されたことをトリガーとして実行される。

```yml
on:
  workflow_call:
```

### レポジトリの設定

ワークフローを持つレポジトリの設定（Access）を変更しておく。  
Setting -> Code and automation -> Actions -> General と辿り、 一番下の「Access」で「Accessible from repositories owned by...」を選択してSave。

## inputsとsecrets

ワークフローに**inputs**と**secrets**をパラメータとして渡すことができる。

```yml
on:
  workflow_call:
    inputs:
      hoge:
        required: true
        type: string
    secrets:
      fuga:
        required: true
```

シークレットは直接参照することができず、必ず呼び出し元から渡す。（次項参照）

## 呼び出し元の記述

jobs.<job_id>.usesにワークフローへの参照を指定する。
- {owner}/{repo}/.github/workflows/{filename}@{ref}の形式
- 同一レポジトリの場合、{owner}/{repo}/の代わりに./を指定
- secretsには呼び出し元で設定されているsecretsを指定

```yml
jobs:
  workflow-call-job1:
    uses: owner/repo/.github/workflows/sample1.yml@main # 別レポジトリ
      with:
        hoge: hogehoge
      secrets:
        fuga: ${{ secrets.PERSONAL_ACCESS_TOKEN }}
  workflow-call-job2:
    uses: ./.github/workflows/sample2.yml@main # 同一レポジトリ
```

## サンプル（AWS S3へのアップロード）

AWS S3にアップロード（sync）するサンプル。CLIを実行するためのAWSの設定については割愛する。

- 呼び出し元で作成された何か（ビルドされたアプリなど）をS3にアップロードする
- データの受け渡しはuplaod-artifact, download-artifactを使用する

### sync-s3.yml（呼ばれる側）

```yml
name: Sync S3

on:
  workflow_call:
    inputs:
      region: # S3リージョン
        required: true
        type: string
      bucket-name: # S3バケット名
        required: true
        type: string
      target-path: # S3バケット内のパス
        required: true
        type: string
      artifact-name: # アップロードする内容
        required: true
        type: string
    secrets: # S3へのアクセス可能なユーザーのアクセスキー、シークレット
      aws-access-key-id:
        required: true
      aws-secret-access-key:
        required: true

env:
  TARGET_PATH: ${{ inputs.target-path}}
  BUCKET: ${{ inputs.bucket-name}}
  AWS_DEFAULT_REGION: ${{ inputs.region }}
  AWS_ACCESS_KEY_ID: ${{ secrets.aws-access-key-id }}
  AWS_SECRET_ACCESS_KEY: ${{ secrets.aws-secret-access-key }}

jobs:
  sync:
    runs-on: ubuntu-latest
    steps:

    - name: Download a single artifact
      uses: actions/download-artifact@v4
      with:
        name: ${{ inputs.artifact-name}}
        path: app

    - name: Sync s3
      run: aws s3 sync app s3://$BUCKET/$TARGET_PATH
```

### call-sync-s3.yml（呼び出し元）

この例ではworkflow_dispatchでマニュアル実行する。

```yml
name: Testing s3 sync

on:
  workflow_dispatch:

jobs:
  # 何かを行い、artifactとしてアップロードするジョブ
  build:
    runs-on: ubuntu-latest
    steps:
    - name: Checkout
      uses: actions/checkout@v4
    - name: Create files
      run: |
        mkdir app
        echo Hello! > app/hoge
        echo Goodbye! > app/fuga
    - name: upload
      uses: actions/upload-artifact@v4
      with:
        name: myapp
        path: app/
  # 呼び出し用ジョブ
  call-sync-s3:
    needs: build
    uses: owner/repo/.github/workflows/sync-s3.yml@main
    with:
      artifact-name: myapp
      bucket-name: mybucket
      target-path: path/to/content
    secrets:
      aws-access-key-id: ${{secrets.AWS_ACCESS_KEY_ID}}
      aws-secret-access-key: ${{secrets.AWS_SECRET_ACCESS_KEY}}
```

## 参照

https://docs.github.com/en/actions/using-workflows/reusing-workflows