fix(ci): route scanner-comment API calls via internal Forgejo URL (#104) #107

Merged
james merged 1 commit from 99-forgejo-api-url-override into main 2026-06-18 12:34:09 +00:00
Owner

Closes #104.

What happened

OSV scanner's Post sticky PR comment step timed out on the first PR run after #68 landed:

ConnectTimeoutError: Connect Timeout Error
  attempted addresses: 104.21.38.184:443, 2606:4700:3032::ac43:895b:443, 172.67.137.91:443
  timeout: 10000ms

The three addresses are Cloudflare anycast IPs. The runner is inside the same network the Forgejo server lives in, and can't hairpin back through CF to its own public hostname — exact same network-topology issue that drove #76 to use forge.int.wynning.tech for the container push.

Fix

  • scripts/ci/post-pr-comment.mjs now reads FORGEJO_API_URL and prefers it over the auto-injected GITHUB_SERVER_URL. Falls back to GITHUB_SERVER_URL so a self-hoster forking this workflow into a non-CF deployment doesn't need to set anything.
  • .forgejo/workflows/pr.yml — each of the three scanner Post sticky PR comment steps (npm/osv/trivy) sets FORGEJO_API_URL: https://forge.int.wynning.tech in its env block.
  • .forgejo/workflows/secrets.yml — same for the gitleaks scanner's post step.
  • .forgejo/workflows/release.ymlCreate Forgejo release step swapped from ${{ github.server_url }} to a step-local API_URL: https://forge.int.wynning.tech, preemptive (that call had been working but the root cause is identical and worth fixing before it does fail).
  • docs/ci.md — new "Forgejo API URL (FORGEJO_API_URL)" subsection under "Sticky PR comments" explaining when a self-hoster would set / unset it.

Test plan

  • actionlint .forgejo/workflows/*.yml — clean.
  • node --check scripts/ci/post-pr-comment.mjs — clean.
  • Next PR run's Post sticky PR comment steps complete without a connect timeout. (CI on this PR is the test — the script runs against this PR's own scanner output.)
  • Next tag push's Create Forgejo release step still creates the release page, now via the internal API endpoint.

Why not just retry on timeout?

A retry loop would buy us a few extra seconds of "maybe CF is having a moment" — but the root cause is reachability, not transient flakiness. The runner physically cannot establish TLS to the CF edge from inside the network. A retry would always fail. The internal URL is the only durable fix.

Closes #104. ## What happened OSV scanner's `Post sticky PR comment` step timed out on the first PR run after #68 landed: ``` ConnectTimeoutError: Connect Timeout Error attempted addresses: 104.21.38.184:443, 2606:4700:3032::ac43:895b:443, 172.67.137.91:443 timeout: 10000ms ``` The three addresses are Cloudflare anycast IPs. The runner is inside the same network the Forgejo server lives in, and can't hairpin back through CF to its own public hostname — exact same network-topology issue that drove #76 to use `forge.int.wynning.tech` for the container push. ## Fix - **`scripts/ci/post-pr-comment.mjs`** now reads `FORGEJO_API_URL` and prefers it over the auto-injected `GITHUB_SERVER_URL`. Falls back to `GITHUB_SERVER_URL` so a self-hoster forking this workflow into a non-CF deployment doesn't need to set anything. - **`.forgejo/workflows/pr.yml`** — each of the three scanner `Post sticky PR comment` steps (npm/osv/trivy) sets `FORGEJO_API_URL: https://forge.int.wynning.tech` in its env block. - **`.forgejo/workflows/secrets.yml`** — same for the gitleaks scanner's post step. - **`.forgejo/workflows/release.yml`** — `Create Forgejo release` step swapped from `${{ github.server_url }}` to a step-local `API_URL: https://forge.int.wynning.tech`, preemptive (that call had been working but the root cause is identical and worth fixing before it does fail). - **`docs/ci.md`** — new "Forgejo API URL (`FORGEJO_API_URL`)" subsection under "Sticky PR comments" explaining when a self-hoster would set / unset it. ## Test plan - [x] `actionlint .forgejo/workflows/*.yml` — clean. - [x] `node --check scripts/ci/post-pr-comment.mjs` — clean. - [ ] Next PR run's `Post sticky PR comment` steps complete without a connect timeout. *(CI on this PR is the test — the script runs against this PR's own scanner output.)* - [ ] Next tag push's `Create Forgejo release` step still creates the release page, now via the internal API endpoint. ## Why not just retry on timeout? A retry loop would buy us a few extra seconds of "maybe CF is having a moment" — but the root cause is **reachability**, not transient flakiness. The runner physically cannot establish TLS to the CF edge from inside the network. A retry would always fail. The internal URL is the only durable fix.
fix(ci): route scanner-comment API calls via internal Forgejo URL (#104)
All checks were successful
Commits / Conventional Commits (pull_request) Successful in 7s
PR / OSV-Scanner (pull_request) Successful in 30s
Secrets / gitleaks (pull_request) Successful in 37s
PR / Static analysis (pull_request) Successful in 50s
PR / Lint (pull_request) Successful in 53s
PR / npm audit (pull_request) Successful in 57s
PR / Typecheck (pull_request) Successful in 1m1s
PR / Test (sqlite) (pull_request) Successful in 1m13s
PR / Test (postgres) (pull_request) Successful in 1m15s
PR / Build (pull_request) Successful in 1m18s
PR / Trivy (image) (pull_request) Successful in 1m30s
0c0174ea5c
OSV scanner's `Post sticky PR comment` step timed out on the first
post-#68 PR run with `UND_ERR_CONNECT_TIMEOUT` against three
Cloudflare anycast IPs. The runner can't hairpin back through CF to
its own public hostname (`forge.wynning.tech`) — same network-topology
issue that #76 fixed for the registry push.

Add a `FORGEJO_API_URL` env var that `post-pr-comment.mjs` prefers
over `GITHUB_SERVER_URL`, with `GITHUB_SERVER_URL` retained as the
fallback so a self-hoster forking this workflow into a non-CF
environment doesn't need to set anything. Each scanner's post step
in pr.yml (npm/osv/trivy) and secrets.yml (gitleaks) sets the env
to the internal hostname.

release.yml's "Create Forgejo release" step gets the same treatment
preemptively. That step has been working under the public URL until
now, probably by route luck — same root cause, same fix shape.

Docs/ci.md picks up a `FORGEJO_API_URL` subsection under "Sticky PR
comments" explaining when a self-hoster would unset / override it.

Closes #104.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
james merged commit b19de99b78 into main 2026-06-18 12:34:09 +00:00
james deleted branch 99-forgejo-api-url-override 2026-06-18 12:34:09 +00:00
Sign in to join this conversation.
No description provided.