Skip to content

Instantly share code, notes, and snippets.

@Atsumi3
Created February 25, 2025 07:05
Show Gist options
  • Save Atsumi3/468f2bbfe3e62d25fbbe21e09899d0ad to your computer and use it in GitHub Desktop.
Save Atsumi3/468f2bbfe3e62d25fbbe21e09899d0ad to your computer and use it in GitHub Desktop.
GithubのSecretsをスプシから更新するためのGAS
/// 例: https://github.com/Atsumi3/AppManager
/// const _GITHUB_OWNER = "Atsumi3";
/// const _GITHUB_REPOSITORY = "AppManager";
const _GITHUB_OWNER = "";
const _GITHUB_REPOSITORY = "";
/// Permission: Read and Write -> actions variables and secrets
const _GITHUB_PAT = "";
/// Secretsの値更新のために LibSodium 相当でハッシュ化出来る関数が必要
/// このGASでは外のAPIで変換する
/// サーバ側のサンプル https://github.com/Atsumi3/nk-sodium-api
const _SODIUM_ENCRYPT_API_ENDPOINT = "";
const _SHEET_NAME = "Secrets";
const _SECRET_API_BASE = `https://api.github.com/repos/${_GITHUB_OWNER}/${_GITHUB_REPOSITORY}/actions/secrets`;
function updateGithubSecrets() {
const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(_SHEET_NAME);
const data = sheet.getDataRange().getValues();
const secrets = {};
/// 2行目から
for (let i = 1; i < data.length; i++) {
/// 1列目
const secretKey = data[i][0];
/// 2列目
const secretValue = data[i][1];
if (secretKey && secretValue) {
secrets[secretKey] = secretValue;
}
}
const headerAuthValue = `token ${_GITHUB_PAT}`;
const options = {
method: "get",
headers: {
"Authorization": headerAuthValue,
"Accept": "application/vnd.github+json"
}
};
const response = UrlFetchApp.fetch(`${_SECRET_API_BASE}/public-key`, options);
const publicKeyData = JSON.parse(response.getContentText());
const keyId = publicKeyData.key_id;
const publicKey = publicKeyData.key;
for (const secretName in secrets) {
const plainValue = secrets[secretName];
const payload = {
"encrypted_value": _encryptSecret(plainValue, publicKey),
"key_id": keyId
};
const putOptions = {
method: "put",
headers: {
"Authorization": headerAuthValue,
"Accept": "application/vnd.github+json",
"Content-Type": "application/json"
},
payload: JSON.stringify(payload),
muteHttpExceptions: true
};
const putResponse = UrlFetchApp.fetch(`${_SECRET_API_BASE}/${secretName}`, putOptions);
Logger.log(`Secret ${secretName} 更新: HTTPステータス ${putResponse.getResponseCode()}`);
}
}
/**
* GitHubのSecret値を暗号化する関数
* 外部で作成したLibSodium相当のAPI を呼び出します。
*
* @param {string} plainText - 暗号化する平文(例:"123" や "あいうえお")
* @param {string} base64PublicKey - GitHubから取得した公開鍵(base64エンコード済み)
* @return {string} - 暗号化後の値(base64エンコード済みの文字列)
*/
function _encryptSecret(plainText, base64PublicKey) {
var payload = {
text: plainText,
publicKey: base64PublicKey
};
var options = {
method: 'post',
contentType: 'application/json',
payload: JSON.stringify(payload),
muteHttpExceptions: true
};
var response = UrlFetchApp.fetch(_SODIUM_ENCRYPT_API_ENDPOINT, options);
if (response.getResponseCode() !== 200) {
throw new Error('Encryption API returned error: ' + response.getContentText());
}
var result = JSON.parse(response.getContentText());
return result.encrypted;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment