fix(hive-forge): tolerate an empty CI state in pr-status + pr-merge
Forgejo reports `"state": ""` in the combined-status response for a commit that has no CI contexts at all. The typed `forgejo-api` client models that field as an enum with no empty variant, so deserialization failed and both verbs died outright — on exactly the pull requests where "no CI ran here" is the useful answer. `pr-merge` was the worse of the two: the crash sat in its pre-merge readiness check, blocking a merge it should have waved through. Route both call sites through the existing raw-JSON escape hatch (`Client::get_api_json`), which exists for this failure mode: the crate pins one schema while the server tracks the latest release line. A lenient local `CombinedStatus` keeps `state` a plain `String` and the per-context statuses as opaque values, so an empty or unknown state is reported rather than fatal. `status_state_str` and its enum mapping go away with it. Closes #2735
This commit is contained in:
parent
fd40138f5a
commit
1219f31c2f
2 changed files with 57 additions and 50 deletions
|
|
@ -15,10 +15,10 @@
|
|||
use anyhow::{Result, bail};
|
||||
use clap::{Args as ClapArgs, ValueEnum};
|
||||
use forgejo_api::structs::{
|
||||
CommitStatusState, MergePullRequestOption, MergePullRequestOptionDo, PullRequest, StateType,
|
||||
MergePullRequestOption, MergePullRequestOptionDo, PullRequest, StateType,
|
||||
};
|
||||
|
||||
use crate::client::{Client, index, split_repo};
|
||||
use crate::client::{Client, index};
|
||||
|
||||
/// Merge strategy. Squash is deliberately omitted (hive convention: keep the
|
||||
/// per-commit history, so a squash option isn't exposed).
|
||||
|
|
@ -136,17 +136,11 @@ fn check_ready(client: &Client, repo: &str, number: u64, pull: &PullRequest) ->
|
|||
}
|
||||
|
||||
if let Some(sha) = pull.head.as_ref().and_then(|h| h.sha.as_deref()) {
|
||||
let (owner, name) = split_repo(repo)?;
|
||||
let (_, combined) = client
|
||||
.api()
|
||||
.repo_get_combined_status_by_ref(owner, name, sha)
|
||||
.send()?;
|
||||
let state = combined.state;
|
||||
let has_statuses = combined.statuses.as_ref().is_some_and(|a| !a.is_empty());
|
||||
let combined = super::pr_status::fetch_combined_in(client, repo, sha)?;
|
||||
// An empty status set means no CI is configured — not a blocker.
|
||||
// Anything other than success once CI exists blocks the merge.
|
||||
if has_statuses && state != Some(CommitStatusState::Success) {
|
||||
let state = super::pr_status::status_state_str(state);
|
||||
if !combined.statuses.is_empty() && combined.state != "success" {
|
||||
let state = &combined.state;
|
||||
bail!(
|
||||
"pr-merge: PR #{number} CI is not green (state: {state}). Wait for green, or pass --force."
|
||||
);
|
||||
|
|
|
|||
Loading…
Reference in a new issue