この記事は公開されてから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_NAME
、 REPO_NAMES
、 GITHUB_TOKEN
、 ACTIONS_SECRETS
の値は適宜書き換えて実行してください。
main.py
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 の設定に関して、同じ境遇の人の助力になれば幸いです。