🚀

GitHub Actionsのワークフロー 一覧を自動出力する

2025/01/05に公開

はじめに

GitHub Actions は CI/CD ワークフローを簡単に管理・実行できる強力なツールです。しかし、プロジェクトが大規模になると、ワークフローの整理やドキュメント化が課題になります。
この記事では、シェルスクリプトを用いてワークフロー一覧を自動生成し、プロジェクトの効率的な運用を実現する方法を解説します。

こんな感じです

以下のGitHub Actionsがあったとして
GitHub Actionsの説明文は、---の上にコメントアウトして記載します

.github/workflows/assign_pr_creator.yml
# このワークフローは、新しいプルリクエストが開かれたときに自動的に PR 作成者を assignee として割り当てます。
# ボットによって作成された PR や、既に assignee が設定されている PR には適用されません。
# 参考:https://zenn.dev/yumemi_inc/articles/b3e11b50869c1a
---
name: Assign PR Creator
run-name: Run by @${{ github.actor }} - ${{ github.workflow }}

on:
  pull_request:
    types:
      - opened

jobs:
  assign_pr_creator:
    name: Assign
    if: endsWith(github.actor, '[bot]') == false && github.event.pull_request.assignee == null
    runs-on: ubuntu-latest
    permissions:
      pull-requests: write
      repository-projects: read
    steps:
      - name: Add event actor to assignees
        env:
          GH_TOKEN: ${{ github.token }}
          GH_REPO: ${{ github.repository }}
        run: gh pr edit ${{ github.event.number }} --add-assignee ${{ github.actor }}

↓生成↓:今回紹介するスクリプトで下記のmarkdownは生成できます。

.github/WORKFLOWS.md
# GitHub Actions ワークフロー 一覧

## Assign PR Creator
  このワークフローは、新しいプルリクエストが開かれたときに自動的に PR 作成者を assignee として割り当てます。  
  ボットによって作成された PR や、既に assignee が設定されている PR には適用されません。  
  参考:https://zenn.dev/yumemi_inc/articles/b3e11b50869c1a  
####  **ファイル名:** [`assign_pr_creator.yml`](workflows/assign_pr_creator.yml)
- **トリガー:**
  ```yaml
  pull_request:
    types:
      - opened
  ```
- **環境変数(vars):** -
- **環境変数(secrets):** -
- **参照スクリプト:** -

スクリプトの仕組み

以下のシェルスクリプトは、.github/workflows/ ディレクトリにある YAML ファイルから情報を抽出し、一覧形式で .github/WORKFLOWS.md に出力します。

.github/script/generate_workflows_readme.sh
#!/bin/bash

# ワークフロー一覧を生成
echo "# GitHub Actions ワークフロー 一覧" > .github/WORKFLOWS.md
echo "" >> .github/WORKFLOWS.md

for file in .github/workflows/*.yml; do
  echo "Processing file: $file"
  
  # ファイル名とワークフロー名を取得
  name=$(basename "$file" .yml)
  workflow_name=$(grep '^name:' "$file" | sed 's/name: *//g')

  # コメント部分(説明)を抽出
  if grep -q '^---' "$file"; then
    description=$(awk '/^---/ {exit} {print}' "$file" | sed 's/^# //')
  else
    description=""
  fi
  
  # onセクションを抽出
  triggers=$(awk '/^on:/ {flag=1; next} /^[^ ]/ {flag=0} flag {print}' "$file")

  # 変数とシークレットの設定文字列を抽出する
  vars=$(grep -oP "\\\${{ *vars\.[A-Za-z0-9_-]+[ ]*}}" "$file" | sort | uniq)
  secrets=$(grep -oP "\\\${{ *secrets\.[A-Za-z0-9_-]+[ ]*}}" "$file" | sort | uniq)

  # ワークフロー内で参照されている `.py` ファイルを検出
  script_files=$(grep -oP '\.github/script/[^\s]+\.[a-zA-Z]+' "$file" | sort | uniq)

  # Markdown 形式で出力
  echo "## $workflow_name" >> .github/WORKFLOWS.md

  if [[ -n "$description" ]]; then
    while IFS= read -r script; do
      echo "  $script  " >> .github/WORKFLOWS.md
    done <<< "$description"
  else
    echo "**説明:** -  " >> .github/WORKFLOWS.md
  fi

  echo "####  **ファイル名:** [\`$name.yml\`](workflows/$name.yml)" >> .github/WORKFLOWS.md

  echo "- **トリガー:**" >> .github/WORKFLOWS.md
  echo '  ```yaml' >> .github/WORKFLOWS.md
  echo "$triggers" >> .github/WORKFLOWS.md
  echo '  ```' >> .github/WORKFLOWS.md

  if [[ -n "$vars" ]]; then
    echo "- **環境変数(vars):**" >> .github/WORKFLOWS.md
    while IFS= read -r script; do
      echo "  - $script" >> .github/WORKFLOWS.md
    done <<< "$vars"
  else
    echo "- **環境変数(vars):** -" >> .github/WORKFLOWS.md
  fi

  if [[ -n "$secrets" ]]; then
    echo "- **環境変数(secrets):**" >> .github/WORKFLOWS.md
    while IFS= read -r script; do
      echo "  - $script" >> .github/WORKFLOWS.md
    done <<< "$secrets"
  else
    echo "- **環境変数(secrets):** -" >> .github/WORKFLOWS.md
  fi
  
  if [[ -n "$script_files" ]]; then
    echo "- **参照スクリプト:**" >> .github/WORKFLOWS.md
    while IFS= read -r script; do
      # .github/ を削除
      cleaned_script=$(echo "$script" | sed 's/^\.github\///')
      echo "  - [$script]($cleaned_script)" >> .github/WORKFLOWS.md
    done <<< "$script_files"
  else
    echo "- **参照スクリプト:** -" >> .github/WORKFLOWS.md
  fi

  echo "" >> .github/WORKFLOWS.md
  echo "" >> .github/WORKFLOWS.md
done

echo ".github/WORKFLOWS.md が生成されました。"

このスクリプトは以下の機能を備えています

  • ワークフロー名の取得
  • 説明文の抽出
  • Markdown形式での出力

自動化の設定

GitHub Actions のワークフローで、上記スクリプトを実行する設定を作成します。

.github/workflows/generate_workflows_readme.yml
# このワークフローは、リポジトリ内の GitHub Actions ワークフロー一覧を .github/WORKFLOWS.md ファイルに生成・更新する自動化処理です。
---
name: Generate Workflow README

on:
  push:
    branches:
      - main
    paths:
      - '.github/workflows/*.yml'
  workflow_dispatch:

jobs:
  generate-readme:
    runs-on: ubuntu-latest
    steps:
      # リポジトリのコードを取得
      - name: Checkout Repository
        uses: actions/checkout@v4

      # 外部シェルスクリプトを実行してワークフロー一覧を生成
      - name: Generate Workflows README
        run: |
          set -e
          chmod +x .github/script/generate_workflows_readme.sh
          .github/script/generate_workflows_readme.sh

      # 現在の日付を取得
      - name: Get Current Date
        id: current_date
        run: echo "current_date=$(date '+%Y-%m-%d')" >> $GITHUB_ENV

      # プルリクエストの作成
      - name: Create Pull Request
        uses: peter-evans/create-pull-request@v5
        with:
          commit-message: "Update .github/WORKFLOWS.md"
          branch: update-workflows-readme
          title: "GitHub Actions ワークフロー一覧の更新 (${{ env.current_date }})"
          body: |
            このプルリクエストは、最新の GitHub Actions ワークフロー構成を反映するために `.github/WORKFLOWS.md` を更新します。

2025/01/06追記

.github/README.mdだとリポジトリのトップに表示されてしまう問題があったので
.github/README.md.github/WORKFLOWS.mdに変更しました
https://docs.github.com/ja/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-readmes

README ファイルをリポジトリの隠れ .github ルートまたは docs ディレクトリに置けば、GitHub はそれを認識して自動的に README をリポジトリへの訪問者に提示します。
リポジトリに複数の README ファイルが含まれている場合、表示されるファイルは、.github ディレクトリ、リポジトリのルート ディレクトリ、最後に docs ディレクトリの順に選択されます。

この情報は知らなかった、、、

おわりに

この手法を導入することで、ワークフローの管理が簡素化され、ドキュメントを常に最新状態に保つことができます。自動化を活用して、開発チームの生産性向上に役立ててください。

参考

https://zenn.dev/yumemi_inc/articles/b3e11b50869c1a
https://gihyo.jp/article/2024/10/good-practices-for-github-actions

Discussion