GitHub Actions の Repository Secrets を登録する Python スクリプトを書いてみた

GitHub Actions の Repository Secrets を登録する Python スクリプトを書いてみた

GitHub Actionsを利用する上で、1つの Organization に複数のチームで利用していて、 Organization Secret を登録しにくい場合に、自分たちで管理する各 Repository Secret に登録・更新するスクリプトを書きました。
Clock Icon2022.07.07 10:17

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

サーモン大好き横山です。

GitHub Actions を利用する上で、1つの Organization に複数のチームで利用していて、 Organization Secret を登録しにくい場合に、自分たちで管理する各 Repository Secret に登録・更新する作業が面倒になることがありますよね。……はい、うちは面倒になりました。

ということで Python コードを書きました。

事前準備

Python バージョン

$ python3 -V
Python 3.10.4

パッケージインストール

$ pip install requests pynacl

コード

GitHub の REST API の Doc に書いてある方法を一部そのまま使いました。 ORG_NAMEREPO_NAMESGITHUB_TOKENACTIONS_SECRETS の値は適宜書き換えて実行してください。

from base64 import b64encode
from typing import Dict, List

import requests
from nacl import encoding, public

ORG_NAME = "OWNER"
REPO_NAMES = ["repo-name1", "repo-name2", "repo-name3"]
GITHUB_TOKEN = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"

ACTIONS_SECRETS: List[Dict[str, str]] = [
    {
        "name": "SECRET_VALUE1",
        "value": "hoge",
    },
    {
        "name": "SECRET_VALUE2",
        "value": "fuga",
    },
    {
        "name": "SECRET_VALUE3",
        "value": "foo",
    },
]


def encrypt(public_key: str, secret_value: str) -> str:
    """Encrypt a Unicode string using the public key."""
    public_key = public.PublicKey(public_key.encode("utf-8"), encoding.Base64Encoder())
    sealed_box = public.SealedBox(public_key)
    encrypted = sealed_box.encrypt(secret_value.encode("utf-8"))
    return b64encode(encrypted).decode("utf-8")


def get_repository_public_key(
    session: requests.Session, org_name: str, repo_name: str
) -> Dict[str, str]:
    resp = session.get(
        f"https://api.github.com/repos/{org_name}/{repo_name}/actions/secrets/public-key"
    )
    return resp.json()


def main() -> None:
    session = requests.Session()

    session.headers.update(
        {
            "Accept": "application/vnd.github+json",
            "Authorization": f"token {GITHUB_TOKEN}",
        }
    )

    for repo_name in REPO_NAMES:
        public_key_dict = get_repository_public_key(session, ORG_NAME, repo_name)
        key_id = public_key_dict["key_id"]
        public_key = public_key_dict["key"]

        for secret in ACTIONS_SECRETS:
            url = f"https://api.github.com/repos/{ORG_NAME}/{repo_name}/actions/secrets/{secret['name']}"
            params = {
                "key_id": key_id,
                "encrypted_value": encrypt(public_key, secret["value"]),
            }
            resp = session.put(url, json=params)
            print(f"{repo_name}, {secret['name']}: {resp.status_code}")

        print("-" * 40)


if __name__ == "__main__":
    main()

実行結果例

$ python3 main.py
repo-name1, SECRET_VALUE1: 201
repo-name1, SECRET_VALUE2: 201
repo-name1, SECRET_VALUE3: 201
----------------------------------------
repo-name2, SECRET_VALUE1: 201
repo-name2, SECRET_VALUE2: 201
repo-name2, SECRET_VALUE3: 201
----------------------------------------
repo-name3, SECRET_VALUE1: 201
repo-name3, SECRET_VALUE2: 201
repo-name3, SECRET_VALUE3: 201
----------------------------------------

まとめ

GitHub Actions の設定に関して、同じ境遇の人の助力になれば幸いです。

この記事をシェアする

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.