Skip to content

Anonymous GitHub release lookups exhaust a shared 60/hour and fail builds #62

Description

@catinspace-au

Every GitHub release lookup in the Ansible roles is anonymous -- 14 files hit api.github.com and a search for Authorization across ansible/ returns nothing. That is fine on a laptop and expensive anywhere the address is shared.

The anonymous limit is 60 requests an hour PER IP, and all HyperI on-prem infrastructure leaves through one public address. So an image build, a converge and CI all draw on the same 60, and a single run selecting infrastructure plus a couple of languages spends a good fraction of it by itself -- k8s.yml, cloud.yml, data_tools.yml, ghostty.yml, colima.yml, go.yml, the rust setup script.

It killed our desktop template build at task 90 with x_ratelimit_remaining: '0' and x_ratelimit_used: '60'. An earlier run the same morning got to task 280, so it is not deterministic -- it depends on what else in the estate has been talking to GitHub in the preceding hour.

Two things make it worse than the raw number suggests:

  • The diagnosis is buried. The uri module dumps the 403 response headers rather than saying "rate limited", and the shell call sites that do curl ... | grep tag_name end up with an empty version and fail later on a 404 or a tar error that names nothing.
  • Anonymous quota is consumed by whoever gets there first, so the run that fails is rarely the run that spent it.

What would fix it for us: read a token from the environment (GITHUB_TOKEN or GH_TOKEN) and set the Authorization header when one is present, staying anonymous when it is not. Then an unattended build can pass one and a laptop run is unchanged.

DONE WHEN an image build can make its release lookups without competing for anonymous quota.

Activity

  1. catinspace-au commented on Aug 30, 2026

    @catinspace-au
    ContributorAuthor

    Went through this one call site at a time before changing anything, and most of it is already done.

    All 14 Ansible call sites carry hyperi_github_headers -- counts match 1:1 per file (utilities 3/3, k8s 7/7, cloud 2/2, and ten singles). Nothing to do there.

    The one real gap was hyperi-rust-setup, which does its own sccache release lookup and had no token handling at all. It runs during the converge, so it burned anonymous quota on the shared egress address every time.

    Worth recording why the fix is two halves, because the script change alone does nothing on a fleet box: an exported token survives become to the SAME user, but is stripped becoming a DIFFERENT one. Measured it -- token=[] becoming root, the value intact becoming yourself. hyperi-infra connects as ubuntu and becomes the desktop user, so the task has to hand the token over explicitly. hyperi_github_env is the process-environment twin of hyperi_github_headers, empty when no token is set.

    STILL OPEN after #70, and why we stopped: hyperi-update-linux.sh:389,465 make the same unauthenticated lookups, but hyperi-update.service runs as actual_user with no Environment=. Patching the script changes nothing until we decide where a fleet box gets a token from, and a token in a unit file is not it for a classification 4 repo. That is a decision, not a code change, so it is left here rather than half-fixed.

    Fix for the converge path is in #70.

  2. github-actions commented on Oct 7, 2026

    @github-actions
    Contributor
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions