Secrets and variables¶
Workflows often need credentials, e.g. to publish packages or sign artifacts, and configuration values. GitHub Actions provides secrets for sensitive values and variables for other values. Otterdog manages both on organization, repository and environment level.
| Scope | Properties | Available to |
|---|---|---|
| Organization | secrets, variables |
the repositories selected by visibility |
| Repository | secrets, variables |
all workflows of the repository |
| Environment | secrets, variables |
jobs that use the environment, once its protection rules pass |
The visibility of organization secrets and variables can be:
public: all repositories of the organizationprivate: private and internal repositories, not available for organizations on thefreeplanselected: only the repositories listed inselected_repositories
Reference secret values, never write them¶
Secret values must not be written in the configuration, which is stored in a repository. Instead, reference
them in a credential provider with the format <provider>:<data>, e.g. pass:path/to/secret. Otterdog resolves
the reference when it applies the configuration. The supported providers and their formats are listed in
SecretValue, and validate reports secret values that do not use
a credential provider as warning.
orgs.newOrg('my-project', 'my-org') {
secrets+: [
orgs.newOrgSecret('SIGNING_KEY') {
value: "pass:path/to/signing-key",
visibility: "selected",
selected_repositories+: [
"my-library",
],
},
],
variables+: [
orgs.newOrgVariable('REGISTRY_URL') {
value: "https://registry.example.org",
},
],
_repositories+:: [
orgs.newRepo('my-library') {
secrets+: [
orgs.newRepoSecret('DOCS_DEPLOY_TOKEN') {
value: "pass:path/to/docs-deploy-token",
},
],
environments+: [
orgs.newEnvironment('publish') {
deployment_branch_policy: "selected",
branch_policies+: [
"tag:v*",
],
secrets+: [
orgs.newEnvSecret('REGISTRY_TOKEN') {
value: "pass:path/to/registry-token",
},
],
},
],
},
],
}
Recommendation
Give each secret the narrowest scope that works: an environment secret for deployment credentials, protected
by the rules of the environment (see Deployment environments), a repository secret for a
single repository, and an organization secret with selected visibility for credentials that several
repositories share. A secret with public visibility is available to every repository, including
repositories created later.
Override a value for a repository or an environment¶
When secrets or variables with the same name are defined on several levels, the most specific one is used: an environment value takes precedence over a repository value, which takes precedence over an organization value, see Using secrets in GitHub Actions. This allows defining a value for most repositories and overriding it where needed:
orgs.newOrg('my-project', 'my-org') {
variables+: [
orgs.newOrgVariable('REGISTRY_URL') {
value: "https://registry.example.org", // (1)!
},
],
_repositories+:: [
orgs.newRepo('my-library') {
variables+: [
orgs.newRepoVariable('REGISTRY_URL') {
value: "https://staging.registry.example.org", // (2)!
},
],
environments+: [
orgs.newEnvironment('release') {
variables+: [
orgs.newEnvVariable('REGISTRY_URL') {
value: "https://registry.example.org", // (3)!
},
],
},
],
},
],
}
- Used by all repositories,
publicbeing the default visibility of organization variables in the example default configuration. - Used by the workflows of
my-library, e.g. to publish snapshots to a staging registry. - Used by the jobs of
my-librarythat run in thereleaseenvironment.
Recommendation
Overriding a secret hides which value a workflow actually uses. Prefer distinct names, e.g. STAGING_TOKEN and
RELEASE_TOKEN, for secrets that grant different permissions, and keep overrides for configuration values.
Dependabot and Codespaces secrets¶
Dependabot and Codespaces use their own secrets, which GitHub manages independently of the secrets of GitHub Actions:
- Dependabot secrets are used by Dependabot, e.g. to access private registries, and are the only secrets available to workflows triggered by Dependabot, e.g. a workflow running for a pull request opened by Dependabot.
- Codespaces secrets are available as environment variables in the codespaces created for a repository.
They are defined in the dependabot_secrets and codespaces_secrets properties of an organization or a repository,
see Organization Dependabot Secret,
Organization Codespaces Secret,
Repository Dependabot Secret and
Repository Codespaces Secret. A secret with the same
name can be defined for GitHub Actions and for Dependabot, e.g. when a workflow needs the same credential whether it is
triggered by Dependabot or not:
orgs.newOrg('my-project', 'my-org') {
secrets+: [
orgs.newOrgSecret('REGISTRY_TOKEN') {
value: "pass:path/to/registry-token",
},
],
dependabot_secrets+: [
orgs.newOrgDependabotSecret('REGISTRY_TOKEN') {
value: "pass:path/to/registry-token",
},
],
}
Note
Otterdog only reads the Dependabot and Codespaces secrets when the default configuration defines the
corresponding function, e.g. newOrgDependabotSecret for the Dependabot secrets of an organization and
newRepoDependabotSecret for those of its repositories. The credentials used by otterdog then need access to
these secrets, see Create a GitHub App.
Secrets managed outside otterdog¶
A secret with the redacted value ********, which import writes as GitHub never discloses secret values, is
skipped by otterdog, see Redacted values. Such a
secret can be maintained in the GitHub web interface.
Organization policy
Managing secrets with otterdog makes them visible in the configuration and centralizes their rotation, but only
people with access to the credential provider can change them. Keeping a secret as ******** lets maintainers
of a repository manage it themselves, but it is not visible which value is used and when it was rotated.
Updating secret values¶
Otterdog cannot detect that the value of a secret changed in the credential provider. After rotating a credential, update the secret explicitly, see Updating values.
Avoid long-lived secrets¶
Many cloud providers and package registries accept short-lived tokens that a workflow obtains with OpenID Connect, without storing any secret in GitHub, see OpenID Connect. Combined with a protected environment, this is usually safer than a long-lived token stored as secret.
Limits¶
- Secret names must not start with
GITHUB_, and must be uppercase as GitHub normalizes them to uppercase. - Secrets and variables of Copilot agents cannot be managed with otterdog, see
Unsupported Features. GitHub moved the secrets of the Copilot cloud agent from an
environment named
copilotto dedicated agent secrets, see the GitHub changelog.