iTranslated by AI
The content below is an AI-generated translation. This is an experimental feature, and may contain errors. View original article
🔑
How to Share GitHub Secrets and Variables across Multiple Repositories
You often want to configure things like Slack Webhook URLs or S3 access keys to upload or notify CI/CD results.
However, when you own multiple repositories, managing these values becomes a hassle.
GitHub Organization paid plans feature "Organization secrets & variables," and you can solve this tedious problem by using this feature to set cross-repository secrets and variables.
While this is the standard approach, it costs money, so it's a solution individual developers might want to avoid to keep expenses down.
I have built a reasonably satisfactory workflow by creating a GitHub Action to sync Secrets and Variables, which I will introduce here.
GitHub Actions
Create a workflow like the following:
name: Sync Secrets and Variables
on:
workflow_dispatch:
defaults:
run:
shell: bash
jobs:
sync_secrets:
runs-on: ubuntu-latest
timeout-minutes: 1
strategy:
fail-fast: false
matrix:
include:
- repo: repo-aaa
secrets:
- "R2_ACCOUNT_ID"
- "R2_BUCKET_NAME"
- "R2_ACCESS_KEY_ID"
- "R2_SECRET_ACCESS_KEY"
- "SLACK_WEBHOOK"
- repo: repo-bbb
secrets:
- "R2_ACCOUNT_ID"
- "R2_BUCKET_NAME"
- "R2_ACCESS_KEY_ID"
- "R2_SECRET_ACCESS_KEY"
- "SLACK_WEBHOOK"
steps:
- name: Set secrets
run: |
for secret_name in ${{ join(matrix.secrets, ' ') }}; do
secret_value="${!secret_name}"
echo "Setting $secret_name for ${{ matrix.repo }}"
echo "$secret_value" | gh secret set "$secret_name" \
--repo="${{ github.repository_owner }}/${{ matrix.repo }}"
done
env:
GH_TOKEN: ${{ secrets.TOKEN_RW_SECRETS_VARIABLES }} # needed to use gh cli to set secrets on other repos
R2_ACCOUNT_ID: ${{ secrets.R2_ACCOUNT_ID }}
R2_BUCKET_NAME: ${{ secrets.R2_BUCKET_NAME }}
R2_ACCESS_KEY_ID: ${{ secrets.R2_ACCESS_KEY_ID }}
R2_SECRET_ACCESS_KEY: ${{ secrets.R2_SECRET_ACCESS_KEY }}
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }}
sync_vars:
runs-on: ubuntu-latest
timeout-minutes: 1
strategy:
fail-fast: false
matrix:
include:
- repo: repo-aaa
vars:
- "R2_PUBLIC_DEV_URL"
- repo: repo-bbb
vars:
- "R2_PUBLIC_DEV_URL"
steps:
- name: Set vars
run: |
for var_name in ${{ join(matrix.vars, ' ') }}; do
var_value="${!var_name}"
echo "Setting $var_name for ${{ matrix.repo }}"
gh variable set "$var_name" \
--repo="${{ github.repository_owner }}/${{ matrix.repo }}" \
--body="$var_value"
done
env:
GH_TOKEN: ${{ secrets.TOKEN_RW_SECRETS_VARIABLES }} # needed to use gh cli to set vars on other repos
R2_PUBLIC_DEV_URL: ${{ vars.R2_PUBLIC_DEV_URL }}
Notes and Explanation
- It is a very simple workflow.
- It sends the Secrets & Variables from the repository running this workflow to other repositories.
- It achieves setting Secrets & Variables in other repositories by using
gh secret setandgh variable set. - To do this, a Personal Access Token (PAT) with appropriate permissions is required. That is
TOKEN_RW_SECRETS_VARIABLES. Please create a PAT and grant itRead and Write access to actions variables and secretspermissions. - The
envandmatrix.includesections are designed to allow for detailed mapping. Please customize them according to your specific needs.- The description can become redundant as the number of repositories and variables increases. While there is room for further optimization, I like the current method because it is explicit and easy to understand.
- (*Added 2025-11-03) It seems YAML anchor syntax was supported a few months ago, so you can write it more concisely using that. I tried it out and it worked well. However, it does cause a syntax error false positive in the VS Code extension...
Operation Method
Initial Setup
- Please create and configure a PAT as described above.
Regular Operation
- When you have repositories or Secrets & Variables you want to share, edit this workflow.
- Commit and push.
- Run this workflow on the pushed branch.
- Verify the results in the target repository. There is a
Last updatedcolumn in theRepository secretslist, which is useful to check.
- Sharing secrets carries security risks, so please carefully consider which values to share and which repositories to send them to.
Discussion