Skip to content

Mirror to Git Forges: 3 of 7 forges broken — Gitea's host variable expands to EMPTY, Disroot/Bitbucket keys rejected #845

Description

@hyperpolymath

Summary

Mirror to Git Forges has failed on every recent run of main, and 3 of
its 7 forge jobs are broken for three different reasons. One of them is a
silent empty-variable expansion, not an auth problem — which matters, because
the three look identical from the workflow list.

This is pre-existing and unrelated to #842: red at 450734e, 4fa2e39,
c18608e, 1b2e66e5 and 0aa89724.

Measured — run 35772116797 @ 450734ea021167b2d9c2a85e9976bc6708deb379

Job Result
mirror-gitlab ✅ success
mirror-codeberg ✅ success
mirror-radicle ✅ success
mirror-sourcehut ✅ success
mirror-gitea empty host variable
mirror-disroot Permission denied (publickey)
mirror-bitbucket Could not read from remote repository

Fault 1 — mirror-gitea: the host expands to the empty string

Step 4 Mirror to Gitea runs:

ssh-keyscan -t ed25519  >> ~/.ssh/known_hosts
                       ^^ two spaces -- the host argument is MISSING

ssh-keyscan then prints its usage line ([-t type] [host | addrlist namelist]) and exits non-zero. Compare the sibling jobs, where the host is
present and correct:

ssh-keyscan -t ed25519 git.disroot.org >> ~/.ssh/known_hosts
ssh-keyscan -t ed25519 bitbucket.org   >> ~/.ssh/known_hosts

So the secret or variable supplying the Gitea host does not exist, and
GitHub expanded it to empty rather than failing. This is not an authentication
fault and will not be fixed by rotating a key — the job never learned which
host to contact.

A nonexistent secret resolves EMPTY and silently. The job name says
"Gitea", the log says ssh-keyscan failed, and neither says "your variable is
undefined". Any ${{ secrets.X }} / ${{ vars.X }} used as a command
argument
needs an explicit non-empty assertion before use.

Faults 2 and 3 — mirror-disroot and mirror-bitbucket: the key is not authorized

disroot:   git@git.disroot.org: Permission denied (publickey).
bitbucket: fatal: Could not read from remote repository.

Host resolution is fine (both keyscans carry a real hostname). The deploy key
presented is not accepted by the remote. Either the public key is not
registered on that forge, the wrong private key is in the secret, or the remote
repository does not exist under the configured path.

These two need an owner action (registering a public key on those forges);
fault 1 does not — it is a workflow/config fix.

Acceptance criteria

  1. Every host-valued secret/var is asserted non-empty before use. Add a
    guard step per forge that fails with a named message
    (GITEA_HOST is unset or empty) rather than passing an empty argument to
    ssh-keyscan. Applies to all 7 jobs, not just Gitea.
  2. Mutant: blank one forge's host variable deliberately; the job must fail
    at the assertion naming that variable, not at ssh-keyscan usage.
    Restore it; green returns.
  3. The workflow reports a denominator: mirrored N of 7 forges. A run where
    some forges are deliberately unconfigured must state which were skipped and
    why — a skip must never read as a mirror.
  4. Decide per forge: configure or remove. A permanently-failing mirror job
    trains everyone to ignore a red workflow. If Disroot/Bitbucket/Gitea are not
    wanted, delete those jobs; if they are, register the keys and prove a push
    lands by checking the mirrored ref's SHA equals main.
  5. Verify by state, not exit code: after a green run, fetch each mirror's
    default-branch SHA and assert it equals hypatia main. A mirror job that
    pushes nothing can still exit 0.

Context

Found while accounting for every red on main after #842 (450734e). The
other three reds are tracked: #843 (E2E), #844 (Security), #520 (Governance
baseline). This was the only untracked one.

Activity

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

    bugSomething is broken or behaves incorrectly

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions