Files
Joseph SpikerandClaude Opus 4.8 a67d0cf3f3 fix(bao-secrets): retry login+fetch with backoff on 429/504/non-JSON (#545/#590-adjacent)
Under a CI burst (a batch merge fires ~13 workflows x ~4 jobs, each doing an
AppRole login = a raft write), the vault nodes return nginx 504s and the
rate-limit quota returns 429s. Both are non-JSON, which crashed jq and
hard-failed the job with a misleading "parse error". Add a bao_req helper that
retries connect-failures/429/5xx with backoff+jitter (~60s over 6 tries) and
surfaces real 4xx bodies unchanged. Transient throttling no longer fails CI.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-15 16:57:25 +00:00
..

bao-secrets — fetch OpenBao secrets in one step

Composite action for Gitea Actions (spikersoft-issues#545). AppRole-logs in to OpenBao, reads the KV v2 paths you list, and exports them as masked env vars for the rest of the job — so workflows stop carrying a pile of per-repo Actions secrets.

One-time setup per repo

  1. Provision the repo's AppRole (once, by an admin):
    export BAO_ADDR=https://bao.spikersoft.com BAO_TOKEN=<admin token>
    cd /mnt/infrastructure/openbao && bash provision-ci-approles.sh
    
    It prints a role_id and secret_id per repo.
  2. In the repo's Settings → Actions → Secrets, set exactly two: BAO_ROLE_ID and BAO_SECRET_ID. These replace DOCKER_PASSWORD, *_S3_SECRET_KEY, ACCESS_TOKEN_GITEA, DISCORD_*, HF_TOKEN, … — delete those once the workflow is migrated.

Use it in a workflow

    steps:
      - uses: spikerj/spikersoft-infrastructure/.gitea/actions/bao-secrets@master
        with:
          role-id:   ${{ secrets.BAO_ROLE_ID }}
          secret-id: ${{ secrets.BAO_SECRET_ID }}
          secrets: |
            DOCKER_PASSWORD  secret/ci/shared/registry       password
            VIDEOS_S3_KEY    secret/ci/backend/minio/videos   secret_key

      # DOCKER_PASSWORD and VIDEOS_S3_KEY are now normal (masked) env vars:
      - run: echo "$DOCKER_PASSWORD" | docker login git.spikersoft.com -u ci --password-stdin

secrets format

One mapping per line: ENV_NAME <kv-v2-path> <field>, whitespace-separated. The path is exactly what you'd pass to bao kv get. Blank lines and # comments are ignored. Multiline values (PEM keys, etc.) are handled.

Inputs

input required default notes
role-id yes ${{ secrets.BAO_ROLE_ID }}
secret-id yes ${{ secrets.BAO_SECRET_ID }}
secrets yes the mapping block above
bao-addr no https://bao.spikersoft.com override for testing

Notes

  • Tokens issued to CI are short-lived (15m) and read-only, scoped to the repo's own tree + secret/ci/shared/* by its policy. The action revokes its token when done.
  • If a path is outside the role's policy the step fails loudly (permission denied) rather than exporting an empty value — verified in provision-ci-approles.sh's policy scoping.
  • Runner needs curl and jq (present on the standard act_runner images).
  • Rotation: secret_ids expire in 90 days — re-run provision-ci-approles.sh and update the two Actions secrets; nothing else changes.