Hive Hive
Sign in

fix(infra): stop mise hitting the GitHub API in CI (install via mise.lock with –locked)

GitHub issue · Closed

Metadata
Source
tuist/tuist #11347
Updated
Jun 25, 2026
Domains
Compute
Details

What

Make every meaningful mise install in CI use the pre-resolved mise.lock URLs instead of resolving/downloading through api.github.com, eliminating the recurring GitHub rate limit exceeded / 403 Forbidden failures (e.g. run 27743340122, server Test job on github:ClickHouse/ClickHouse).

Why it was happening

  • The lockfile records both a direct CDN url (github.com/.../releases/download/..., not rate-limited) and a url_api (api.github.com/.../releases/assets/<id>, rate-limited). Without --locked, mise downloads github-backend assets through url_api.
  • The repo’s shared GITHUB_TOKEN is ~1k req/hr; dozens of concurrent CI jobs each making GitHub API calls via mise exhaust it → 403.
  • mise only keeps off the GitHub/aqua API when installing with --locked (its own help: “This prevents API calls to GitHub, aqua registry, etc.”). Only 4 of ~48 mise workflows set it.
  • Several workflows passed no install_args, so mise installed the entire merged root toolset (~30 tools, building erlang from source) and resolved all of it through the API. Worse, mise run and mise x auto-install the full merged config, so scoping install_args alone doesn’t help those — they need MISE_AUTO_INSTALL=0.

Constraints (verified empirically)

  • --locked hard-fails for source-built / non-URL backends (erlang, elixir, ruby, rust, npm:, gem:, asdf:) — mise lock writes no URL for them.
  • A scoped mise install --locked <lockable tools> only enforces the named tools and just warns (exit 0) about unlockable ones in the merged config.
  • MISE_AUTO_INSTALL=0 stops mise run/mise x/shims from installing the full config, while pre-installed tools still work. MISE_CEILING_PATHS does not stop the project-tree merge. A subdir --locked install resolves root-tier tools from the root lockfile.

Changes

  • New .github/actions/mise-install — splits requested tools: source-built/registry backends install normally, everything else installs with --locked (direct CDN URL, zero GitHub API calls). Used by setup-server-mix and the mixed-install workflows.
  • Mixed erlang/rust + lockable PR-CI installs routed through the action: noora (aube), kura (bazel/shellspec/buck2), gradle-cache-acceptance (ClickHouse), blick, and server.yml (ClickHouse — the original failure).
  • Pure-lockable release/deploy installs get --locked prepended (git-cliff, jq, helm, kubectl, tuist, 1password-cli, bats).
  • No-install_args workflows scoped to their real tools + MISE_AUTO_INSTALL=0 where they use mise run/mise x: app.yml (tuist / tuist+1password-cli), grafana-datasource (go node), status/status-deploy (node aube wrangler), search/search-deploy (ruby kamal).
  • Lockfiles regenerated for all common platforms (root, server, cache, noora, handbook) and created for kura, grafana-datasource, status.

Erlang/elixir-only jobs (slack, tuist-ops, l10n, cache) are unchanged — they install only source-built backends, which never touch the rate-limited API.

Validation

  • actionlint on all changed workflows: no new errors (only pre-existing custom-runner-label noise).
  • Split logic unit-tested in bash for every install string in use; MISE_AUTO_INSTALL/--locked/cross-dir-lock behaviors verified in isolated runs.
  • Verified every locked tool has a linux-x64 entry in its applicable lockfile; lockfile diffs are additive (no tool version changes except an intended cache erlang/elixir sync).

Behavior when a tool isn’t locked

If a tool is added to mise.toml but mise.lock isn’t updated (e.g. forgetting to commit the lock), the --locked install fails fast with a clear “…is not in the lockfile” error and makes zero GitHub API calls — it’s a pre-flight check, like npm ci refusing a stale lockfile, not a silent fallback to API resolution. So a stale lock is a loud, cheap CI failure rather than a quiet regression back into rate-limit territory. (Source-built / npm: / gem: / asdf: backends are installed unlocked by design and need no lock entry; they don’t hit the rate-limited API anyway.)

The contributor workflow stays: add the tool → run mise install (or mise lock) locally → commit the updated mise.lock.

Deliberately left unchanged

  • The SLSA-tuned mise -C infra run platform-install in server-deployment (resolves the full infra toolset; rescoping a prod-deploy path is high-risk for low marginal gain).
  • The rust-only install in server-production-deployment (rust is source-built and uses no rate-limited GitHub API).
  • The image-build workflows (*-image) — they don’t use jdx/mise-action (they use actions/setup-go, or invoke oras/packer directly).

🤖 Generated with Claude Code

Comments
TA
tuist-atlas[bot] Jun 19, 2026

The fix to stop mise hitting the GitHub API in CI (install via mise.lock with –locked) is now available in grafana-datasource@0.1.3. Please update to this version to get the changes.