最近为了批量修改 GitHub Actions Secrets,研究了下如何使用 GitHub REST API 修改 GitHub Actions Secrets,现记录一下。
没代码没真相,直接上代码,后面再解释怎么回事。
import { Octokit } from '@octokit/core'
import sodium from 'libsodium-wrappers'
// Octokit.js
// https://github.com/octokit/core.js#readme
const octokit = new Octokit({
auth: 'ghp_xxxxxxxxxxxxxxxxxx', // 替换为你的 GitHub token,参考 https://github.com/settings/tokens ,其中至少要有 repo 或 public_repo 权限才能修改 Actions Secrets
request: {
timeout: 10 * 1000, // 记得设置超时,不然会无限等待
},
})
type GetARepositoryPublicKeyRequest = {
owner: string
repo: string
}
/**
* 获取 存储库 公共密钥
文档:https://docs.github.com/en/rest/actions/secrets?apiVersion=2022-11-28#get-a-repository-public-key
*/
async function getARepositoryPublicKey(data: GetARepositoryPublicKeyRequest) {
return (await octokit.request('GET /repos/{owner}/{repo}/actions/secrets/public-key', data)).data
}
type CreateOrUpdateARepositorySecretRequest = {
owner: string
repo: string
/**
* 要更改的 secret
*/
secret_name: string
/**
* 更改后的值
*/
secret_value: string
}
/**
* 创建或更新 Repository Secret
文档:https://docs.github.com/en/rest/actions/secrets?apiVersion=2022-11-28#create-or-update-a-repository-secret
*/
async function createOrUpdateARepositorySecret(data: CreateOrUpdateARepositorySecretRequest) {
const { secret_value, owner, repo, ...other } = data
// Convert Secret & Base64 key to Uint8Array.
const { key, key_id } = await getARepositoryPublicKey({ owner, repo }) // 获取公钥
const binkey = sodium.from_base64(key, sodium.base64_variants.ORIGINAL)
const binsec = sodium.from_string(secret_value)
// Encrypt the secret using LibSodium
const encBytes = sodium.crypto_box_seal(binsec, binkey)
// Convert encrypted Uint8Array to Base64
const encrypted_value = sodium.to_base64(encBytes, sodium.base64_variants.ORIGINAL) // 根据公钥计算加密后的值
const newData = {
...other,
owner,
repo,
encrypted_value,
key_id,
}
return (await octokit.request('PUT /repos/{owner}/{repo}/actions/secrets/{secret_name}', newData)).data
}
async function start() {
await createOrUpdateARepositorySecret({
owner: 'OWNER', // 你的 GitHub 用户名
repo: 'REPO', // 仓库的名称
secret_name: 'SECRET_NAME', // 要更改的 secret
secret_value: 'xxxxxxxxxxxxxx', // 这里是 secret 的原始值
})
}
start()
在更新 secret 前,需要先获取公钥,然后用公钥加密 secret,最后再 PUT
我之前搜索了一下这方面的内容,发现基本上没什么人提过这事,故特此记录一下。
本文作者:草梅友仁
本文地址: blog.cmyr.ltd/archives/2a…
版权声明:转载请注明出处!