Dosu LogoDosu Logo
Ask
Join our Discord
opentelemetry-collector-releasesPublic
OpenTelemetry
Documentsopentelemetry-collector-releases
CI/CD Workflow Authentication
CI/CD Workflow Authentication
Type
Topic
Status
Published
Created
Sep 8, 2026
Updated
Sep 8, 2026

CI/CD Workflow Authentication#

Overview#

Authentication in this repo's CI/CD pipelines is split across three credential types — a GitHub App token (otelbot), the built-in GITHUB_TOKEN, and a DockerHub access token — with strict boundaries on which token is used for which operation. Understanding these boundaries is critical because the wrong token at the wrong step will silently produce a permission error.


Token Reference#

CredentialSecret/VarUsed For
otelbot GitHub AppOTELBOT_COLLECTOR_RELEASES_CLIENT_ID (var) + OTELBOT_COLLECTOR_RELEASES_PRIVATE_KEY (secret)Git push, tag creation/deletion
GITHUB_TOKENsecrets.GITHUB_TOKENGHCR login (push images), GHCR package version deletion
DockerHub tokenvars.DOCKER_USERNAME + secrets.DOCKER_TOKEN_COLLECTOR_RELEASESDocker Hub image push and nightly tag deletion

otelbot App Token vs. GITHUB_TOKEN#

The otelbot GitHub App token is used only for Git operations — checkout, tag creation, and tag deletion. It is explicitly not used for container registry operations because the otelbot installation is not granted the packages permission; attempting to request it causes the token creation step to fail with:

The permissions requested are not granted to this installation

This is documented in a comment in cleanup-nightly.yaml and was the root cause of failures addressed in PR #1614.

Split in practice:

  • Git tag deletion in cleanup-nightly-git-tags.sh runs via a git push origin --delete authenticated with the otelbot token (checked out with token: ${{ steps.otelbot-token.outputs.token }}).
  • GHCR package version deletion in cleanup-nightly-ghcr.sh uses GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} with packages: write granted at the job level.

GHCR Package Deletion Authorization#

Deleting GHCR package versions requires packages: write in both the calling workflow and any workflow_call child. In nightly-release.yaml, the cleanup-nightly job explicitly re-grants this permission when invoking the reusable workflow — without it, the permission would be capped away:

permissions:
  contents: read
  packages: write

The reusable cleanup-nightly.yaml also declares packages: write at the job level . If either declaration is missing, the gh api DELETE call in the cleanup script will fail with a 403.

The GHCR cleanup script authenticates via GH_TOKEN and calls the GitHub Packages API (/orgs/{ORG}/packages/container/{PACKAGE}/versions), filtering to versions whose tags all match the vX.Y.Z-nightly.<ts> pattern and whose updated_at is older than 2 weeks.

For image push during a release, GHCR login uses secrets.GITHUB_TOKEN wrapped in a retry action (5 attempts, 15 s delay) to guard against transient registry errors.


DockerHub Token History#

DockerHub authentication went through a turbulent cycle:

  1. Legacy: workflows used secrets.DOCKER_USERNAME + secrets.DOCKER_PASSWORD.
  2. PR #1031 re-enabled a new token (DOCKER_TOKEN_COLLECTOR_RELEASES) with vars.DOCKER_USERNAME.
  3. PR #1050 reverted — the new token lacked sufficient DockerHub permissions at that time.
  4. PR #1057 re-introduced the new token after the necessary DockerHub permissions were added.

Current state: all release workflows (base-release.yaml, release-builder.yaml, release-opampsupervisor.yaml) and the nightly cleanup authenticate to Docker Hub with vars.DOCKER_USERNAME + secrets.DOCKER_TOKEN_COLLECTOR_RELEASES.

The DockerHub cleanup script exchanges these credentials for a short-lived Hub JWT via POST /v2/users/login/ and fails fast if the response token is empty or null.


Workflow Permission Propagation#

A subtle GitHub Actions rule: when a top-level workflow calls a reusable workflow with uses:, the child's GITHUB_TOKEN is capped by the permissions declared in the calling job block. nightly-release.yaml must therefore explicitly grant packages: write when invoking cleanup-nightly.yaml, or GHCR deletion will be denied — even though the child workflow also declares packages: write internally. The same applies to secrets: inherit for DockerHub credentials.


Key Files#

FilePurpose
.github/workflows/cleanup-nightly.yamlReusable cleanup workflow; defines per-job token strategy
.github/workflows/nightly-release.yamlNightly trigger; must re-grant packages: write to child
.github/workflows/scripts/cleanup-nightly-ghcr.shGHCR package version deletion via GitHub API
.github/workflows/scripts/cleanup-nightly-dockerhub.shDockerHub tag deletion via Hub API + JWT
.github/workflows/scripts/cleanup-nightly-git-tags.shGit tag deletion via otelbot-authenticated push
Documents
CI/CD Workflow Authentication