Skip to content

A.4 - Required Secrets and Variables

Context: Section 7, Credential Storage: GitHub Secrets Architecture; the authentication action that consumes the JWT secrets and variables is in A.3.2.

Secret / Variable Scope Description
SF_JWT_KEY_PROD Environment The private key of the JWT bearer flow for the production org, in PEM format; its certificate is uploaded to the org's External Client App. Consumed by pr-prod.yml (validation) and the scheduled workflows (org scan, tests).
SF_CLIENT_ID_PROD Environment The client ID (consumer key) of the External Client App in the production org. Consumed by pr-prod.yml (validation) and the scheduled workflows (org scan, tests).
SF_USERNAME_PROD Environment A variable, not a secret. The username of the integration user that the workflows log in to the production org as. Consumed by pr-prod.yml (validation) and the scheduled workflows (org scan, tests).
SF_INSTANCE_URL_PROD Environment A variable, not a secret. The URL that the JWT login uses for the production org, such as its My Domain URL. Consumed by pr-prod.yml (validation) and the scheduled workflows (org scan, tests).
SF_JWT_KEY_STAGING Environment The private key of the JWT bearer flow for the staging sandbox, in PEM format; its certificate is uploaded to the org's External Client App. Consumed by pr-pipeline.yml for a pull request to staging, and by the scheduled test runner.
SF_CLIENT_ID_STAGING Environment The client ID (consumer key) of the External Client App in the staging sandbox. Consumed by pr-pipeline.yml for a pull request to staging, and by the scheduled test runner.
SF_USERNAME_STAGING Environment A variable, not a secret. The username of the integration user that the workflows log in to the staging sandbox as. Consumed by pr-pipeline.yml for a pull request to staging, and by the scheduled test runner.
SF_INSTANCE_URL_STAGING Environment A variable, not a secret. The URL that the JWT login uses for the staging sandbox, such as its My Domain URL. Consumed by pr-pipeline.yml for a pull request to staging, and by the scheduled test runner.
SF_JWT_KEY_QA Environment The private key of the JWT bearer flow for the QA sandbox, in PEM format; its certificate is uploaded to the org's External Client App. Consumed by pr-pipeline.yml for a pull request to qa.
SF_CLIENT_ID_QA Environment The client ID (consumer key) of the External Client App in the QA sandbox. Consumed by pr-pipeline.yml for a pull request to qa.
SF_USERNAME_QA Environment A variable, not a secret. The username of the integration user that the workflows log in to the QA sandbox as. Consumed by pr-pipeline.yml for a pull request to qa.
SF_INSTANCE_URL_QA Environment A variable, not a secret. The URL that the JWT login uses for the QA sandbox, such as its My Domain URL. Consumed by pr-pipeline.yml for a pull request to qa.
SF_JWT_KEY_INT Environment The private key of the JWT bearer flow for the int sandbox, in PEM format; its certificate is uploaded to the org's External Client App. Consumed by pr-pipeline.yml for a pull request to int.
SF_CLIENT_ID_INT Environment The client ID (consumer key) of the External Client App in the int sandbox. Consumed by pr-pipeline.yml for a pull request to int.
SF_USERNAME_INT Environment A variable, not a secret. The username of the integration user that the workflows log in to the int sandbox as. Consumed by pr-pipeline.yml for a pull request to int.
SF_INSTANCE_URL_INT Environment A variable, not a secret. The URL that the JWT login uses for the int sandbox, such as its My Domain URL. Consumed by pr-pipeline.yml for a pull request to int.
CODECOV_TOKEN Repository Codecov upload token (required for private repositories). Consumed by the full-org Apex test workflow and the Jest tests.
APEX_RUN_RELEVANT_TESTS_ORGANIZATION Organization A variable, not a secret. true or false decides the test level for every repository, and the repository's variable is then not read. With no value, each repository decides (A.2.11).
APEX_RUN_RELEVANT_TESTS Repository A variable, not a secret. Read only when the organization's variable has no value. true makes the pull request validation use RunRelevantTests; any other value, or none, uses the computed RunSpecifiedTests list (A.2.11).
SF_METADATA_DIR Repository or organization A variable, not a secret. The project metadata directories, as a comma-separated list, such as force-app, service-cloud. Read when the caller passes no folder: by the delta package (A.2.8), which without it uses force-app, and by the push scan of Code Analyzer (A.2.9), which without it uses the whole repository.
SLACK_WEBHOOK_URL Repository Slack incoming webhook URL for the drift report and for failure/release notifications. Consumed by all scheduled workflows and the release-please workflow.
SLACK_SECURITY_WEBHOOK Repository or organization Slack incoming webhook URL of the security channel. Consumed by the secret scan (A.2.3), which posts a finding there; without it, a finding fails the job and nothing is posted.
RELEASE_PLEASE_TOKEN Repository PAT or GitHub App token with contents:write and pull-requests:write. Required for Release Please to open PRs that trigger CI runs.
GITHUB_TOKEN Automatic Provided automatically by GitHub. Used for PR comments, label assignment, and issue creation.

An organisation that adds an org to the pipeline creates an External Client App in that org, uploads the certificate of the org's key pair to it, and adds the org's four values: the secrets SF_JWT_KEY_<ORG> and SF_CLIENT_ID_<ORG>, and the variables SF_USERNAME_<ORG> and SF_INSTANCE_URL_<ORG>. It keeps those values in a GitHub Environment named for the org, and not in repository secrets. Only a workflow that names that environment in its environment: key can read them, and the production environment requires an approval before a job can use its key (Section 7). Each org has a key pair of its own, so a leaked key reaches one org only. A Dev Hub from which a pipeline creates scratch orgs is the exception, and still needs a Connected App (Section 7).

SF_METADATA_DIR can be set at the repository level or at the organisation level. When both have a value, the repository's value overrides the organisation's.

The severity threshold and the coverage threshold are not variables of the repository or the organisation. Each caller sets them at the top of its own file, and a first job passes them to the workflows it calls (A.1).