hive-forge: ci-rerun dispatches a fresh run via workflow-dispatch API

The previous implementation POSTed Forgejo's run-page rerun web route,
which is CSRF-gated and answers a bare token POST with 404 — so the verb
never actually re-ran anything against the agent token.

Rework it to dispatch a fresh run of the workflow via the
GitHub-compatible workflow-dispatch API
(POST /repos/<o>/<r>/actions/workflows/<workflow>/dispatches {"ref":<branch>}),
which accepts a plain agent token (verified end-to-end on Forgejo 15.0.3).
A dispatched run is equivalent to the old empty-commit retrigger, minus
the commit.

The branch is resolved from exactly one of --pr (the PR head branch),
--run (branch + workflow looked up from that run in the Actions runs
list), or --branch (directly); --workflow picks the workflow file for
--pr/--branch (default ci.yml). Dispatch re-runs the whole workflow, so
the old --job single-job variant is dropped.

Also add workflow_dispatch to .forgejo/workflows/ci.yml for explicitness
(Forgejo 15.0.3 dispatches the pull_request workflow without it, but the
trigger makes the API path intent-clear and cross-version robust), remove
the now-unused Client::post_web_no_content, and update docs/tools/forge.md.
This commit is contained in:
atlas 2026-06-23 11:25:33 +02:00 committed by mara
commit c9c59c2a1d
4 changed files with 175 additions and 118 deletions

View file

@ -321,26 +321,6 @@ impl Client {
decode_json(resp, &format!("POST {url}"))
}
/// POST to a base-relative *web* path (NOT under `/api/v1/`) whose
/// response carries no useful body — e.g. the Actions run rerun
/// endpoints (`<base>/<owner>/<repo>/actions/runs/<run>/rerun`), which
/// answer with a redirect to the run page rather than JSON. Same
/// token-auth path as `post_json_web` (the web router accepts a
/// token-authed doer and skips CSRF for non-session auth); the bodyless
/// POST mirrors the form-handler's expectations (run/job come from the
/// URL). reqwest follows the redirect, so a 2xx on the final hop is
/// success. `path` should start with `/`.
///
/// # Errors
/// Returns an error on a transport failure or a non-2xx final status
/// (e.g. `404` for an unknown run).
pub fn post_web_no_content(&self, path: &str) -> Result<()> {
let url = self.web_url(path);
let resp = self.http.post(&url).send().context("POST")?;
check_status(resp, &format!("POST {url}"))?;
Ok(())
}
/// GET a raw (non-API) URL and return the response body as bytes.
/// The client's auth headers are still sent — Forgejo requires them
/// for private attachment downloads. Uses the full URL as-is; the