GitHub Actionsでビルドが終了時に DiscordでartifactのダウンロードページURLを受け取る【GitHub Actions,Discord,Python】

はじめに

GitHub ActionでCI/CD環境を組んでいて、ビルドができても完了通知やビルドデータのダウンロードをするためには毎回 GitHubを開く必要があります。

かなり手間になっていたので、ビルドが環境するとアーティファクトがあるページのURLをDiscordに送信するシステムを作りました。

(デモリポジトリはUnity用に作成していますが、ほかのものでも代用できると思います)

public Repositoryではないと動かないことが判明したため、調査中です

成果物

以下のように Discordにビルドで作成されたアーティファクトがあるページのURLが、 discordでビルド環境時にメッセージとして送られてきます。

Repository

github.com

動作環境

使い方

1. Actions secretsの登録

まずは今回は GitHub APIと discordのwebHookを使っているため、以下の画像のように GitHub環境変数WebHookURLGitHub Personal Token 登録をします。

tokenは最低限のものを許可していれば大丈夫です。

この際に GitHub上の設定で、Setting → Actions → General → Workflow permissionsRead and write permissions になっていることを確認してください。 動かない可能性があります。

2. GitHub Actionのymlの作成

ymlの実行したい箇所に以下を追加します

      - name: Set up Python 3.9
        uses: actions/setup-python@v3.1.2
        with:
          python-version: 3.9
      - name: Install dependencies
        run: |
          pip install -r .github/send_download_artifact_url/requirements.txt
      - name: send download artifact page url
        env:
          GITHUB_REPOSITORY: ${{ github.repository }}
        run: |
          python .github/send_download_artifact_url/send-download-artifact-page-url.py

3. スクリプトの作成と配置

実行するスクリプト( send-download-artifact-page.py ) と requirements.txt を以下のように .github/send_download_artifact_url 以下に配置します。

ファイル名や配置パスは、ymlを書き換えれば任意のものに変更しても大丈夫です。

discordに送信するスクリプトは以下になっています。

import os
import requests

from dotenv import load_dotenv

load_dotenv()

headers = {
    "Accept": "application/vnd.github.v3+json",
    "Authorization": os.getenv("PERSONAL_ACCESS_TOKEN"),
}

req = requests.get(f" https://api.github.com/repos/{os.getenv('GITHUB_REPOSITORY')}/actions/artifacts",
                   headers=headers).json()


def get_download_url(content):
    for artifact in content["artifacts"]:
        if artifact["name"] == "Build-StandaloneWindows64":
            run_id = artifact["workflow_run"]["id"]
            url = f"https://github.com/{os.getenv('GITHUB_REPOSITORY')}/actions/runs/{run_id}"
            return url
    return None


def message(url):
    content = {
        "username": "ビルドダウンロードページ",
        "content": "ビルドが終了しました。"
                   + f"\nダウンロードページ: {url}"
    }
    return content


requests.post(os.getenv("DISCORD_WEBHOOK_URL"), message(get_download_url(req)))

実装の詳細

最新のビルドデータを取得

https://api.github.com/repos/OWNER/REPO/actions/artifacts を使い、Repositoryのartifactのリストを取得しています。その中から ビルドデータ (今回の場合は、Build-StandaloneWindows64 ) に一致するもので最新のものを取得しています。

https://docs.github.com/ja/rest/actions/artifacts#list-artifacts-for-a-repository

実際にAPIを叩いてみると、以下のようなデータが返ってくることが分かります。

artifactのあるページのURL作成

GitHub上でartifactがあるページは https://github.com/owner_name/repository_name/actions/runs/run_id となっています。こちらは直接取得できないため、↑のでビルドデータの中に run_id が含まれているので、そこからidを取得して URLを生成しています。

(ブックマークは気にしないでください)

リポジトリのownerとRepositoryNameを取得

Repositoryに依存しない実装にしたかったので、Repository名やowner名をスクリプト上に記載したくはなかったので この二つを 環境変数として取得しています。

${{ github.repository }} で取得できるため、 ymlファイルでは以下のように設定をして Python上で環境変数を読んでいます。

        env:
          GITHUB_REPOSITORY: ${{ github.repository }}

参考サイト

zenn.dev

終わりに

本来は直接artifactをダウンロードできるURLが欲しかったのですが、以下のようにダウンロードURLは発行できるものの1分しか持たないみたいです。

github.com

そのため、今回は妥協してダウンロードできるページのURLを送信するようにしました。