I’m building a simple automated deploy pipeline for learning purposes. One of the steps I’d like to implement would be setting the GitHub Actions secrets in bulk.
One of the possibilities I thought about would be to create a node script (javascript) and run before deploy. Something like: set-secrets.js
Example: I’d like to start the script with something like:
// Replace these values with your own.
const REPO_OWNER = 'your-username';
const REPO_NAME = 'your-repo';
const GITHUB_TOKEN = 'your-personal-access-token';
And the data structure would be like:
// Data structure for setting the secrets.
const arrSecrets = [];
arrSecrets.push(['KEY_NAME1', 'secretValue1']);
arrSecrets.push(['KEY_NAME2', 'secretValue2']);
// I will have more values here, but I just want an example.
Then loop through the arrSecrets array and set/update the GitHub Actions secrets through GitHub API.
Would that be possible? If so, anyone has an example of how I could accomplish it? I tried already with a bash .sh but got stuck.
Constraints:
I managed to land on a satisfying solution. It sets the github actions repo secrets key/value in bulk. Very useful for project with tons of environment variables.
const { Octokit } = require("@octokit/rest");
const sodium = require('libsodium-wrappers');
Replace these values with your own.
const GITHUB_USER = 'your-username';
const GITHUB_REPO_NAME = 'your-repo';
const GITHUB_TOKEN = 'your-personal-access-token';
// Secrets.
const arrSecrets = [];
arrSecrets.push(['KEY_NAME1', 'secretValue1']);
arrSecrets.push(['KEY_NAME2', 'secretValue2']);
// Add more.
// Oktakit.
const octokit = new Octokit({
auth: GITHUB_TOKEN
});
(async () => {
const { data: { key, key_id } } = await octokit.actions.getRepoPublicKey({
owner: GITHUB_USER,
repo: GITHUB_REPO_NAME
});
// Loop through the key/value arrays.
arrSecrets.forEach(async ([secretKey, secretValue]) => {
// Encrypt secret value.
await sodium.ready;
// Convert the secret and key to a Uint8Array.
const binkey = sodium.from_base64(key, sodium.base64_variants.ORIGINAL);
const binsec = sodium.from_string(secretValue);
// Encrypt the secret using libsodium.
const encBytes = sodium.crypto_box_seal(binsec, binkey);
// Convert the encrypted Uint8Array to Base64.
secretValueEncrypted = sodium.to_base64(encBytes, sodium.base64_variants.ORIGINAL);
// Set secret.
await octokit.request(`PUT /repos/${ GITHUB_USER}/${ GITHUB_REPO_NAME}/actions/secrets/${secretKey}`, {
owner: GITHUB_USER,
repo: GITHUB_REPO_NAME,
secret_name: secretKey,
encrypted_value: secretValueEncrypted,
key_id: key_id,
headers: {
'X-GitHub-Api-Version': '2022-11-28'
}
});
});
})();
References:
There’s even room to load your local file .env
variables and set them all in bulk at once.