Oore CI
Build and shipConfigure pipelines

Use secrets in a pipeline

Store credentials as encrypted, write-only secrets and reference them from commands and env values.

Store tokens, API keys and store credentials as secrets instead of pipeline env values. Oore encrypts each value with the instance encryption key, never returns it from the API, and masks it as *** in build logs.

What you need

  • Project developer, maintainer, instance admin, or instance owner access for project and pipeline secrets.
  • Instance admin or owner access for instance secrets.

Scopes

A secret belongs to one scope. A build sees the secrets of its pipeline, its project and the instance. When two scopes define the same name, the narrower scope wins: pipeline over project, project over instance.

ScopeAPI baseWho can write
Instance/v1/secretsInstance admin or owner
Project/v1/projects/{project_id}/secretsProject developer or above
Pipeline/v1/pipelines/{pipeline_id}/secretsProject developer or above

Listing returns names and timestamps only. Anyone who can read the project can see which names exist; nobody can read a value back, including the person who wrote it.

1. Create a secret

Add the secret in the scope that matches who should use it:

  • For every pipeline on the instance, open Settings > Secrets.
  • For every pipeline in one project, open the project’s Settings tab.
  • For one pipeline, open the pipeline’s Secrets tab.

Select Add secret, enter the Name and Value, and save. To change a value later, use Replace value. The next build uses the new value. Builds already running keep the old one.

Names follow environment variable rules ([A-Za-z_][A-Za-z0-9_]*, at most 128 characters). Values can be up to 64 KiB, which fits a Google Play service account JSON file.

From the API, send the secret to the scope’s base path:

curl -X POST "$OORE_URL/v1/projects/$PROJECT_ID/secrets" \
  -H "Authorization: Bearer $OORE_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"name": "SENTRY_AUTH_TOKEN", "value": "sntrys_..."}'

To rotate, send PUT .../secrets/{name} with {"value": "..."}. To remove, send DELETE .../secrets/{name}. Each change is written to the audit log. Deleting a secret that a pipeline uses as its Google Play service account returns 409 secret_in_use and names those pipelines. Point them at another secret first, or add ?force=true to delete it anyway. A pipeline that would fall back to a secret of the same name in a wider scope, such as an instance PLAY_SERVICE_ACCOUNT, does not block the delete.

2. Reference it

Use ${{ secrets.NAME }} in an env value or in any command:

env:
  - key: SENTRY_AUTH_TOKEN
    value: ${{ secrets.SENTRY_AUTH_TOKEN }}
commands:
  post_build:
    - ./scripts/upload-symbols.sh --token "${{ secrets.SENTRY_AUTH_TOKEN }}"
  • In an env value, the reference is replaced with the secret value before the step starts.
  • In a command, the reference becomes the shell variable ${OORE_SECRET_NAME}, which the runner sets for that build. Quote it as you would any shell variable. The value is never pasted into the command text.
  • Env values that come from a secret are left out of the --dart-define-from-file file, so they are not compiled into the app. Pass one explicitly with --dart-define if the app really needs it.
  • Only ${{ secrets.NAME }} is supported inside ${{ }}. Any other expression, or a reference to a secret that does not exist in any visible scope, fails the build before a step runs.

Verify the result

Any line a step prints that contains a secret value shows *** in its place. For multi-line values such as JSON keys, each longer line of the value is masked as well. Masking matches exact text, so a value that a step transforms (for example, base64-encodes) is not recognised; avoid printing derived forms.

Run a build that uses the secret. The step that reads it succeeds, and the log shows *** wherever the value would appear.

Troubleshooting

The build fails before its first step with an unknown secret

No visible scope defines that name. Check the spelling, and add the secret to the pipeline, its project, or the instance.

The value appears in the log

The step printed a transformed form of the value, such as base64. Masking matches exact text only. Stop printing the value, then rotate it.

Next step

Set triggers, timeouts, and approvals for the pipeline.