Sync Repository, Dependabot and Codespaces secrets + variables between GitHub repositories
APACHE-2.0 License
Sync Repository, Dependabot and Codespaces secrets + variables between GitHub repositories
github-token
: Required - The GitHub token to use. Use GitHub secrets for security.target
: Optional - The repository to sync secrets and variables to. Either target
or query
must be set, but not both.secrets
: Optional - Secrets to sync. Formatted as a string of newline-separated KEY=VALUE
pairs.variables
: Optional - Variables to sync. Formatted as a string of newline-separated KEY=VALUE
pairs.rate-limit
: Optional - Enables rate limit checking. Set to true
to enable. Default is false
.max-retries
: Optional - Maximum number of retries for operations. Must not be smaller than zero. Default is 3
.dry-run
: Optional - Dry run mode. If true, no changes will be made. Useful for testing. Default is false
.prune
: Optional - Prunes all existing secrets and variables not in the subset of those defined. Default is false
.environment
: Optional - The GitHub environment to sync variables or secrets to. Use when targeting environment-specific secrets or variables.type
: Optional - Type of the secrets to manage: actions
, dependabot
, or codespaces
. Default is actions
.query
: Optional - GitHub search query to find repositories for batch processing. Either query
or target
must be set, but not both.Note: To use Sync Secrets Action, you need a GitHub Token with the right permissions. The default
GITHUB_TOKEN
won't work.
For a Personal Access Token (PAT), create one in your GitHub settings with repo
and, if needed, admin:org
permissions.
For a GitHub App token, create an app in GitHub settings, set necessary permissions, install it to target repositories, and use the private key for authentication.
Store your token in GitHub secrets and use it in the github-token
input of the action.
This action can be executed independently from workflows within a container. To do so, use the following command:
podman run --rm -it ghcr.io/cbrgm/sync-secrets-action:v1 --help
Here are some usage examples to help you getting started! Feel free to contribute more.
name: Sync Repository Secrets and Variables
on:
workflow_dispatch:
jobs:
sync-repo-secrets-and-vars:
runs-on: ubuntu-latest
steps:
- name: Sync Secrets and Variables
uses: cbrgm/sync-secrets-action@v1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
target: 'user/repository'
secrets: |
SECRET_KEY=${{ secrets.SOME_SECRET }}
ANOTHER_SECRET=${{ secrets.ANOTHER_SECRET }}
variables: |
VAR_KEY=varvalue
ANOTHER_VAR=${{ secrets.A_VARIABLE }}
name: Sync Secrets Across Repositories
on:
workflow_dispatch:
jobs:
sync-secrets-across-repos:
runs-on: ubuntu-latest
strategy:
matrix:
target: ['user/repo1', 'user/repo2', 'user/repo3']
steps:
- name: Sync Secrets to ${{ matrix.target }}
uses: cbrgm/sync-secrets-action@v1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
target: ${{ matrix.target }}
secrets: |
GLOBAL_SECRET=${{ secrets.GLOBAL_SECRET }}
variables: |
GLOBAL_VAR=globalvarvalue
name: Sync Secrets to Repositories by Query
on:
workflow_dispatch:
jobs:
sync-secrets-by-query:
runs-on: ubuntu-latest
steps:
- name: Sync Secrets to Repositories Matching Query
uses: cbrgm/sync-secrets-action@v1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
query: 'org:myorganization topic:mytopic'
secrets: |
GLOBAL_SECRET=${{ secrets.GLOBAL_SECRET }}
variables: |
GLOBAL_VAR=globalvarvalue
This workflow uses the query argument to target repositories within
myorganization
that are tagged with the topicmytopic
. It syncs the specified secrets and variables to all matching repositories.
See GitHub Queries.
Tip: Make sure these environments exist before distributing secrets!
name: Sync Environment Secrets
on:
push:
branches:
- main
jobs:
sync-env-secrets:
runs-on: ubuntu-latest
steps:
- name: Sync Environment Secrets
uses: cbrgm/sync-secrets-action@v1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
target: 'user/repository'
environment: 'production'
secrets: |
PROD_DB_PASSWORD=${{ secrets.PROD_DB_PASSWORD }}
dry-run: 'false'
prune: 'true'
name: Sync Secrets Across Repositories and Environments
on:
workflow_dispatch:
jobs:
sync-secrets:
runs-on: ubuntu-latest
strategy:
matrix:
repo: ['org/repo1', 'org/repo2', 'org/repo3'] # Target repositories
environment: ['development', 'staging', 'production'] # Target environments
steps:
- name: Sync Secrets to ${{ matrix.repo }} for ${{ matrix.environment }} Environment
uses: cbrgm/sync-secrets-action@v1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
target: ${{ matrix.repo }}
environment: ${{ matrix.environment }}
secrets: |
DATABASE_URL=${{ secrets['DB_URL_' + matrix.environment] }}
API_KEY=${{ secrets['API_KEY_' + matrix.environment] }}
type: 'actions'
dry-run: 'false'
prune: 'true'
The secrets input dynamically references secrets based on the environment. For example,
DB_URL_development
,DB_URL_staging
, andDB_URL_production
should be defined in your repository's secrets. This approach allows each job to use environment-specific secret values.
name: Sync Codespaces Secrets
on:
workflow_dispatch:
jobs:
sync-codespaces-secrets:
runs-on: ubuntu-latest
steps:
- name: Sync Codespaces Secrets
uses: cbrgm/sync-secrets-action@v1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
target: 'user/repository'
secrets: |
CODESPACE_SECRET=${{ secrets.CODESPACE_SECRET }}
type: 'codespaces'
name: Sync Dependabot Secrets
on:
workflow_dispatch:
jobs:
sync-dependabot-secrets:
runs-on: ubuntu-latest
steps:
- name: Sync Dependabot Secrets
uses: cbrgm/sync-secrets-action@v1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
target: 'user/repository'
secrets: |
DEPENDABOT_SECRET=${{ secrets.DEPENDABOT_SECRET }}
type: 'dependabot'
You can build this action from source using Go
:
make build
sequenceDiagram
participant CronUser as Cron / User
participant GitHubAction
participant GitHubAPI
participant Repository
CronUser->>+GitHubAction: Execute Action
GitHubAction->>+GitHubAPI: Create API Client
GitHubAPI->>-GitHubAction: Client Created
GitHubAction->>GitHubAction: Parse Secrets & Variables
GitHubAction->>+GitHubAPI: Search Repositories (if query provided)
GitHubAPI->>-GitHubAction: Return Repositories
GitHubAction->>GitHubAction: Process Each Repository
GitHubAction->>+Repository: Process Repository
alt Environment Specific
Repository->>+GitHubAPI: List Environment Secrets & Variables Names
GitHubAPI->>-Repository: Update Secrets & Variables
else Repository Specific
Repository->>+GitHubAPI: List Repository Secrets & Variables Names
GitHubAPI->>-Repository: Update Secrets & Variables
else Dependabot
Repository->>+GitHubAPI: List Dependabot Secrets Names
GitHubAPI->>-Repository: Update Secrets
else Codespaces
Repository->>+GitHubAPI: List Codespaces Secrets Names
GitHubAPI->>-Repository: Update Secrets
end
Repository->>-GitHubAction: Processing Complete
GitHubAction->>-CronUser: Execution Finished`
Yes, it is designed with safety in mind. However, like any tool, the security level depends on proper usage and configuration. Ensure your GitHub token has the minimum required permissions.
No, secrets are encrypted and handled within GitHub's secure environment. Yet, be cautious with the output logs and error messages to avoid accidental exposure.
Yes, they are protected using GitHub's security mechanisms. Nonetheless, the security is also contingent on how well access controls and permissions are managed in your GitHub repository settings.
Yes, secrets are not exposed in code or logs, ensuring they remain secure. However, the inherent risk of public repositories means you should be extra vigilant in monitoring access and usage patterns.
Using this action does not inherently increase risk if followed by GitHub's security guidelines and best practices. Risks mainly arise from misconfigurations or improper handling of secrets on the user's part. Regular audits and updates are recommended to maintain security.
While building my GitHub Action for secret synchronization, I drew inspiration from existing solutions, focusing on addressing specific challenges and enhancing user experience:
Key design principles guiding this action development include: