The wizard's eval / bench harnesses and production runs in CI need a live
Amplitude OAuth bearer (WIZARD_OAUTH_TOKEN) to talk to the gateway.
Access tokens issued by Hydra typically expire in ~1 hour, so we keep
them fresh with a scheduled GitHub Actions workflow that calls the
/oauth2/token refresh endpoint and rotates the corresponding repo
secrets in place.
| Piece | Role |
|---|---|
scripts/refresh-wizard-oauth-token.mjs |
Calls Hydra /oauth2/token with grant_type=refresh_token, writes new credential triple to GITHUB_OUTPUT. Zero deps. |
.github/workflows/refresh-wizard-oauth-token.yml |
Hourly cron at :23. Runs the script, then gh secret sets WIZARD_OAUTH_TOKEN / WIZARD_REFRESH_TOKEN / WIZARD_EXPIRES_AT. |
amplitude-wizard ci-bootstrap |
One-time setup: pushes the four secrets from your local OAuth session. |
WIZARD_SECRET_REFRESH_PAT |
Fine-grained PAT with secrets:write on this repo. The default GITHUB_TOKEN cannot write secrets. |
-
Install the GitHub CLI and authenticate:
gh auth login
-
Sign in to the wizard locally so a fresh OAuth session lands on disk:
npx @amplitude/wizard login
-
Create a fine-grained PAT in GitHub with
secrets:writescope onamplitude/wizard. Save it as theWIZARD_SECRET_REFRESH_PATsecret in the same repo. Without this PAT the refresh workflow has no way to rotate the secrets —GITHUB_TOKENcannot. -
Run
ci-bootstrap:amplitude-wizard ci-bootstrap
This pushes four values to repo secrets:
WIZARD_OAUTH_TOKEN← current access tokenWIZARD_REFRESH_TOKEN← current refresh tokenWIZARD_EXPIRES_AT← ISO 8601 expiryWIZARD_ZONE←usoreu
Pass
--yesto skip the confirmation prompt, or--repo <owner/name>to target a fork.
The workflow runs hourly at :23 (off the top of the hour to avoid
GitHub's cron thundering-herd) plus on workflow_dispatch. Each run:
- Reads
secrets.WIZARD_REFRESH_TOKEN+vars.WIZARD_ZONE. - Calls Hydra
/oauth2/tokenwithgrant_type=refresh_token. - Writes the new triple to
GITHUB_OUTPUT. - Calls
gh secret set(usingWIZARD_SECRET_REFRESH_PAT) to overwriteWIZARD_OAUTH_TOKEN,WIZARD_REFRESH_TOKEN, andWIZARD_EXPIRES_AT.
If Hydra rotates the refresh token (it does, on every exchange when the client is configured for rotation), the new one replaces the stored value — the workflow never reuses a stale refresh token.
The workflow surfaces ::error::OAuth refresh failed. and exits
non-zero. Common causes:
- Refresh token revoked. Most likely after a long inactivity period
or a deliberate
wizard logout. Re-bootstrap (next section). - Hydra 5xx / network blip. The next scheduled run will retry; no action needed unless multiple consecutive runs fail.
- PAT expired.
gh secret setreturns 401. Mint a newWIZARD_SECRET_REFRESH_PATand update the secret.
amplitude-wizard logout # clear the stale session
npx @amplitude/wizard login # mint a new refresh token
amplitude-wizard ci-bootstrap --yesgh secret list --repo amplitude/wizard shows the names and last-updated
timestamps but not the values (by design). The WIZARD_EXPIRES_AT secret
is a useful sanity-check: it should advance by ~1 hour every cron tick.