docs, prompts, hive-forge: stop handing readers the renamed verbs
docs/tools/forge.md already listed the nine renamed verbs as removed, then used them ~30 more times in pasteable blocks. Sweeps every occurrence a reader would type, including three runtime messages that told the user to run a verb the same binary rejects. The renamed-verb list itself keeps the old names; it is what documents them. Refs #4155
This commit is contained in:
parent
d2175c84b3
commit
55f01942a2
23 changed files with 73 additions and 73 deletions
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
name: forge-issue-filing
|
||||
description: How to file a well-formed forge issue through the hive-forge CLI - check for an existing duplicate first (title-only grepping misses it, use server-side --search), pick a title that states the problem not the symptom, write a body that's the *problem*, and put any proposed fix in a follow-up comment rather than the issue description. Use this whenever you're about to run `hive-forge issue-create`, whenever you hit a bug/gap/usability problem and are about to file it rather than silently work around it, or whenever asked to write up a finding as an issue.
|
||||
description: How to file a well-formed forge issue through the hive-forge CLI - check for an existing duplicate first (title-only grepping misses it, use server-side --search), pick a title that states the problem not the symptom, write a body that's the *problem*, and put any proposed fix in a follow-up comment rather than the issue description. Use this whenever you're about to run `hive-forge issue create`, whenever you hit a bug/gap/usability problem and are about to file it rather than silently work around it, or whenever asked to write up a finding as an issue.
|
||||
---
|
||||
|
||||
# Forge Issue Filing
|
||||
|
|
@ -55,7 +55,7 @@ proposed implementation - post that as a **follow-up comment**, not baked
|
|||
into the description:
|
||||
|
||||
```sh
|
||||
hive-forge issue-create --title "..." --body "..." --label ... --assignee ...
|
||||
hive-forge issue create --title "..." --body "..." --label ... --assignee ...
|
||||
hive-forge comment <number> --body "proposed fix: ..."
|
||||
```
|
||||
|
||||
|
|
@ -74,7 +74,7 @@ separate from the problem statement.
|
|||
|
||||
## 4. Labels: check the taxonomy, don't guess
|
||||
|
||||
Label names are repo-specific and an unresolved name in `issue-create
|
||||
Label names are repo-specific and an unresolved name in `issue create
|
||||
--label` errors out before the issue is even created (better than the
|
||||
alternative, but still wasted effort if you guess wrong). If you don't
|
||||
already know the repo's label scopes, list them first:
|
||||
|
|
@ -107,7 +107,7 @@ unassigned and let it surface through the normal triage sweep (see the
|
|||
```sh
|
||||
hive-forge list --search "thing you think is broken" --state all # 1: dedup
|
||||
hive-forge repo-labels # 4: taxonomy
|
||||
hive-forge issue-create \
|
||||
hive-forge issue create \
|
||||
--title "the problem, stated durably" \
|
||||
--body "what's wrong, how to reproduce, where it bites" \
|
||||
--label area/whatever --label type/bug
|
||||
|
|
|
|||
|
|
@ -120,7 +120,7 @@ required.
|
|||
though you can't push a branch:
|
||||
|
||||
```sh
|
||||
hive-forge -r internal/knowledge pr-create --agit \
|
||||
hive-forge -r internal/knowledge pr create --agit \
|
||||
--title "docs: add the X runbook" \
|
||||
--topic add-x-runbook \
|
||||
--body-file - <<'EOF'
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ is someone else's call.
|
|||
|
||||
## Reviewers: submit the verdict, don't gate it on CI
|
||||
|
||||
Submit `hive-forge pr-reviews <pr> --approve` or `--request-changes`
|
||||
Submit `hive-forge pr reviews <pr> --approve` or `--request-changes`
|
||||
as soon as you've finished checking the diff — don't hold it back
|
||||
waiting for CI to go green first. Mention CI's current state in the
|
||||
review body if it's relevant (for example "approving; `nix flake check` is
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ Forgejo's PR commit-status tracking appears scoped to `pull_request`-event
|
|||
runs specifically, so a dispatched run — even a genuinely successful one —
|
||||
never writes to that status slot. Reproduced with three dispatches on one
|
||||
PR over 20+ minutes, all genuinely green, the PR's own status unmoved
|
||||
throughout. **Always re-check `pr-status` after a dispatch and believe
|
||||
throughout. **Always re-check `pr status` after a dispatch and believe
|
||||
what it says — don't push a commit just to unwedge it, that's the
|
||||
empty-commit anti-pattern this verb exists to avoid.** If `hive-forge
|
||||
ci-log --run <n> --job 0` shows the code green (verdict is the
|
||||
|
|
|
|||
|
|
@ -75,22 +75,22 @@ hive-forge issue reaction 42 add heart # react to issue 42 with :heart:
|
|||
hive-forge issue reaction 42 --comment 18042 add +1 # react to a specific comment instead
|
||||
hive-forge issue reaction 42 remove heart # remove your own :heart: reaction
|
||||
hive-forge issue reaction 1 --list-allowed # this instance's actual configured shortcodes
|
||||
hive-forge issue-create --title "..." --body "..."
|
||||
hive-forge issue-create --title "..." --body "..." --label area/ops --label type/bug # repeatable
|
||||
hive-forge issue-edit 42 --title "new title"
|
||||
hive-forge issue create --title "..." --body "..."
|
||||
hive-forge issue create --title "..." --body "..." --label area/ops --label type/bug # repeatable
|
||||
hive-forge issue edit 42 --title "new title"
|
||||
hive-forge pr edit 42 --title "new title" # same edit, PR-kind-validated
|
||||
hive-forge pr 42 # PR metadata as JSON
|
||||
hive-forge pr-create --title "..." --head my-branch --push # also `git push forge my-branch`
|
||||
hive-forge pr-create --title "..." --head my-branch --label area/ops # repeatable, same as issue-create
|
||||
hive-forge pr-reviews 42 # list reviews; inline comments included per review
|
||||
hive-forge pr-reviews 42 --approve # submit APPROVED review
|
||||
hive-forge pr-reviews 42 --request-changes -m "msg" # submit REQUEST_CHANGES review
|
||||
hive-forge pr-reviews 42 --comment -m "msg" # submit COMMENT review
|
||||
hive-forge pr create --title "..." --head my-branch --push # also `git push forge my-branch`
|
||||
hive-forge pr create --title "..." --head my-branch --label area/ops # repeatable, same as issue create
|
||||
hive-forge pr reviews 42 # list reviews; inline comments included per review
|
||||
hive-forge pr reviews 42 --approve # submit APPROVED review
|
||||
hive-forge pr reviews 42 --request-changes -m "msg" # submit REQUEST_CHANGES review
|
||||
hive-forge pr reviews 42 --comment -m "msg" # submit COMMENT review
|
||||
hive-forge pr assign-reviewer 42 argus # set argus as a requested reviewer on the PR
|
||||
hive-forge pr assign-reviewer 42 argus --remove # withdraw the request
|
||||
hive-forge pr assign-committer 42 damocles # add damocles to the PR's assignee list
|
||||
hive-forge diff 42 # unified diff (lockfile hunks collapsed by default)
|
||||
hive-forge diff 42 --full # include unfiltered lockfile hunks
|
||||
hive-forge pr diff 42 # unified diff (lockfile hunks collapsed by default)
|
||||
hive-forge pr diff 42 --full # include unfiltered lockfile hunks
|
||||
hive-forge list # open issues/PRs
|
||||
hive-forge list --kind pr --state all --page 2 # page 2 of all PRs (walk --page 1,2,… with --limit as page size for a repo-wide sweep)
|
||||
hive-forge list --search "trust bundle" --state all # full-text over title AND body — the duplicate check
|
||||
|
|
@ -105,11 +105,11 @@ hive-forge lint no-reviewer --reviewer argus # PRs where argus specifically isn
|
|||
hive-forge lint stale-branches --days 14 # branches with no recent activity, each with its merge outcome (PR #n merged / closed unmerged / no PR)
|
||||
hive-forge lint assignments # per-assignee open item count
|
||||
hive-forge lint unlabeled --scope type # open issues/PRs with no exclusive type/* label (any scope works, e.g. --scope area)
|
||||
hive-forge pr-status --pr 42 # PR health: mergeable, CI, reviews, last comment (exit 0 = ready)
|
||||
hive-forge pr-status --sha <sha> # CI-only fast path for an explicit commit sha
|
||||
hive-forge pr-merge 42 # merge (refuses unless mergeable + CI not red + no changes-requested); deletes head branch
|
||||
hive-forge pr-merge 42 --method rebase # rebase-merge instead of a merge commit (no squash option)
|
||||
hive-forge pr-merge 42 --keep-branch --force # keep the head branch; override the readiness gate
|
||||
hive-forge pr status --pr 42 # PR health: mergeable, CI, reviews, last comment (exit 0 = ready)
|
||||
hive-forge pr status --sha <sha> # CI-only fast path for an explicit commit sha
|
||||
hive-forge pr merge 42 # merge (refuses unless mergeable + CI not red + no changes-requested); deletes head branch
|
||||
hive-forge pr merge 42 --method rebase # rebase-merge instead of a merge commit (no squash option)
|
||||
hive-forge pr merge 42 --keep-branch --force # keep the head branch; override the readiness gate
|
||||
hive-forge timeline 42 # audit trail: closes, label changes, assignments, commit refs
|
||||
hive-forge attach-issue 42 /path/to/file # upload a file attachment to an issue; prints download URL
|
||||
hive-forge attach-comment 18042 /path/to/file # upload a file attachment to a comment; prints download URL
|
||||
|
|
@ -121,7 +121,7 @@ hive-forge subscription --watch # subscribe to repo notifications
|
|||
hive-forge subscription --unwatch # unsubscribe
|
||||
hive-forge subscription --list # list every repo you watch (audit the notification firehose)
|
||||
hive-forge -r internal/knowledge clone # clone with creds auto-injected
|
||||
hive-forge -r internal/knowledge pr-create --agit --topic foo --title "..." # open PR via AGit (no fork)
|
||||
hive-forge -r internal/knowledge pr create --agit --topic foo --title "..." # open PR via AGit (no fork)
|
||||
# --- repo management ---
|
||||
hive-forge repo-create my-repo # create under authenticated user; prints URL
|
||||
hive-forge repo-create my-repo --org myorg --private --auto-init # under an org, private, with initial commit
|
||||
|
|
@ -144,16 +144,16 @@ distinct output shape — pick by what you need:
|
|||
| Only the comments (skip the body), for example to catch up a long thread; for PRs, review bodies (approve/request-changes/comment summaries) are merged in too | `comments <n>` [`--tail N`] | comment + review-body list; **marks read** |
|
||||
| One specific comment by its id | `comment-show <id>` | single comment |
|
||||
| The audit trail — closes, label/assignee changes, commit refs, merges (no comment bodies) | `timeline <n>` | event list |
|
||||
| The code change | `diff <n>` | unified diff |
|
||||
| Is this PR ready to merge — mergeable + CI + reviews | `pr-status --pr <n>` | health view; exit code = merge-readiness |
|
||||
| The review verdicts + inline review comments | `pr-reviews <n>` | review list |
|
||||
| The code change | `pr diff <n>` | unified diff |
|
||||
| Is this PR ready to merge — mergeable + CI + reviews | `pr status --pr <n>` | health view; exit code = merge-readiness |
|
||||
| The review verdicts + inline review comments | `pr reviews <n>` | review list |
|
||||
|
||||
Rule of thumb: **`view` first** when you're about to act on a thread (it
|
||||
shows everything and clears the unread guard so your follow-up `comment`
|
||||
isn't rejected); the JSON verbs (`issue`/`pr`) when a script needs one
|
||||
field; `pr-status` when the only question is "can I merge it."
|
||||
field; `pr status` when the only question is "can I merge it."
|
||||
|
||||
### Contributing to a read-only repo (`clone` + `pr-create --agit`)
|
||||
### Contributing to a read-only repo (`clone` + `pr create --agit`)
|
||||
|
||||
Agents are read-only collaborators on some repos (e.g.
|
||||
`internal/knowledge`) and so can't push branches. Forgejo's AGit flow
|
||||
|
|
@ -165,7 +165,7 @@ hive-forge -r internal/knowledge clone # clone, auth handled for you
|
|||
cd knowledge
|
||||
# add / edit / delete any files, then commit normally
|
||||
git add -A && git commit -m "add foo runbook"
|
||||
hive-forge -r internal/knowledge pr-create --agit \
|
||||
hive-forge -r internal/knowledge pr create --agit \
|
||||
--topic foo-runbook \ # groups pushes into ONE PR; reuse to update it
|
||||
--title "add foo runbook" \
|
||||
[--body "details"] # PR description (also accepts --body-file)
|
||||
|
|
@ -177,17 +177,17 @@ URL and the `origin` remote it leaves behind carry no credentials —
|
|||
`clone` instead configures `origin`'s `credential.helper` to invoke
|
||||
`hive-forge credential-helper` (a hidden verb, not meant to be run by
|
||||
hand), which git calls fresh on every fetch/push. That's what lets
|
||||
`pr-create --agit` (default remote `origin`) push without re-auth,
|
||||
`pr create --agit` (default remote `origin`) push without re-auth,
|
||||
without a durable token sitting in the checkout's `.git/config`.
|
||||
|
||||
`pr-create --agit` prints the PR URL. Re-running with the same
|
||||
`pr create --agit` prints the PR URL. Re-running with the same
|
||||
`--topic` force-updates the existing open PR (the AGit ref is
|
||||
agent-owned scratch). Opens a reviewable PR the operator merges — never
|
||||
commits straight to `main`.
|
||||
|
||||
`hive-forge <verb> --help` prints the full signature for any verb.
|
||||
|
||||
### `pr-status`
|
||||
### `pr status`
|
||||
|
||||
One-stop PR health view (`--pr <n>`): mergeable state, CI checks,
|
||||
requested reviewers + review verdicts, and the last-comment timestamp —
|
||||
|
|
@ -197,11 +197,11 @@ before merge). `--sha <sha>` is a CI-only fast path for a raw commit.
|
|||
A failing/erroring CI context prints its job link. The process exit code
|
||||
is a **merge-readiness** verdict for `--pr` (0 only when CI is green AND
|
||||
the PR is mergeable AND no review requests changes), so it composes:
|
||||
`hive-forge pr-status --pr 42 && echo ready`. `--sha` mirrors the CI
|
||||
`hive-forge pr status --pr 42 && echo ready`. `--sha` mirrors the CI
|
||||
verdict alone.
|
||||
|
||||
```
|
||||
hive-forge pr-status --pr 42
|
||||
hive-forge pr status --pr 42
|
||||
# PR #42: feat(...): ... # lint:allow: sample CLI output, not a real tag
|
||||
# state: open (mergeable: yes)
|
||||
# CI: e39a87ea3949: ✅ success (1 context(s))
|
||||
|
|
@ -264,21 +264,21 @@ to discover valid label names before triaging or to audit the label set.
|
|||
block), or pass `--force` to skip the guard.
|
||||
- `comment --body "..."` with backticks in the body: always use
|
||||
`--body-file -` with a HEREDOC to avoid shell escaping issues.
|
||||
- `pr-create --push` also runs `git push forge <head>` and suppresses
|
||||
- `pr create --push` also runs `git push forge <head>` and suppresses
|
||||
the post-push "Create a pull request" hint (hive-forge prints the
|
||||
canonical URL itself).
|
||||
- `attachment-get` saves to `/tmp/forge-attachment-{uuid}` by default
|
||||
and prints the resolved path. Pass `-o -` to stream to stdout.
|
||||
- `artifact-get <name> --run <n>` downloads a CI Actions artifact. `<n>`
|
||||
is the run number from the run-page URL (`/actions/runs/<n>`, which
|
||||
`pr-status` surfaces as a CI context's target_url). Forgejo 15 serves
|
||||
`pr status` surfaces as a CI context's target_url). Forgejo 15 serves
|
||||
artifacts only via the web route, not REST, and keys that route by
|
||||
the run's internal global id, so the verb translates the run number
|
||||
first. Saves a zip to `/tmp/forge-artifact-<name>.zip` by default; pass
|
||||
`-o -` to stream to stdout.
|
||||
- `ci-log --run <n> [--job i] [--step i] [--attempt n]` prints a CI
|
||||
run's job step logs. `<n>` is the run number from the run-page URL
|
||||
(same value `artifact-get` takes; `pr-status` surfaces it as a CI
|
||||
(same value `artifact-get` takes; `pr status` surfaces it as a CI
|
||||
context's target_url). Two log sources, tried in **completeness
|
||||
order**: the verb tries the **durable persisted-log download** the run page's "view
|
||||
raw logs" link uses (`…/runs/<n>/jobs/<job>/attempt/<a>/logs`, a flat
|
||||
|
|
@ -327,12 +327,12 @@ to discover valid label names before triaging or to audit the label set.
|
|||
instance-global, this path ignores `<n>`/`--comment`.
|
||||
- **Don't** use raw `curl` for forge access -- the CLI handles auth,
|
||||
error checking, and output formatting.
|
||||
- `issue-create --label <name>` / `pr-create --label <name>` are
|
||||
- `issue create --label <name>` / `pr create --label <name>` are
|
||||
repeatable and take the same spelling `labels <n> add` does. **An
|
||||
unknown name is an error, not a silent drop** — the command fails
|
||||
listing the names that didn't resolve plus every label the repo has,
|
||||
so it's fixable from the message without a second call. On
|
||||
`pr-create --agit`, hive-forge applies labels as a follow-up call once
|
||||
`pr create --agit`, hive-forge applies labels as a follow-up call once
|
||||
it parses the PR number back out of the push output (the AGit push
|
||||
itself has no label field), so they're silently skipped if that
|
||||
parse fails — same fallback as the deferred multi-line body.
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ Claude session (OAuth credentials) lives at `/root/.claude/` and persists across
|
|||
|
||||
**Code forge**: a private Forgejo (base URL in `$HIVE_FORGE_URL`) is available when `/agents/{label}/state/forge-token` exists. You have your own user account (named `{label}`). Use `hive-forge` (see below) for all forge operations — issues, PRs, comments, labels, etc. For git operations use plain `git` directly against `$HIVE_FORGE_URL/<org>/<repo>.git` (credentials are pre-configured).
|
||||
|
||||
The `hive-forge` CLI is the supported interface to the Forgejo — issues, PRs, comments, labels, reviews, CI status, attachments, triage (`lint`). **Discover the verb list and each verb's full signature with `hive-forge --help` and `hive-forge <verb> --help`** rather than memorising them. The active repo is whichever git checkout you're standing in (inferred from the `origin` remote), or pass `-r <repo>` (global flag, works before or after the verb) to target a different one explicitly — there's no single hardcoded default repo, so don't assume one. A few conventions `--help` won't surface: **never `curl` the forge** — the CLI handles auth and is the only supported path; to check a PR's CI + mergeability use `hive-forge pr-status --pr <n>` (or `--sha <commit>` for a CI-only fast path; exit code is a merge-readiness verdict), not curl. `--body-file -` reads the body from stdin, so a HEREDOC works for multi-line comments/issues: `hive-forge comment <num> --body-file - <<EOF ... EOF`. `hive-forge pr-create --title "..." --head <branch> [--push]` opens a PR and prints its URL; `--push` `git push`es the head branch first (default remote `forge`). Forge notifications are delivered via the internal message daemon (sender `forge`), not polling. A `forge` notification stays unread **on the forge** until you actually read its thread — viewing the referenced issue/PR with `hive-forge comments <n>` or `view <n>` marks that notification read (it's the forge's own read-state, not a local mirror). So when a `forge` message points you at a thread, read the thread to clear the notification instead of letting the same one linger and re-surface. (`hive-forge comment` does the opposite — it _refuses_ to post to a thread with unread activity until you've read it, so read first, then comment.)
|
||||
The `hive-forge` CLI is the supported interface to the Forgejo — issues, PRs, comments, labels, reviews, CI status, attachments, triage (`lint`). **Discover the verb list and each verb's full signature with `hive-forge --help` and `hive-forge <verb> --help`** rather than memorising them. The active repo is whichever git checkout you're standing in (inferred from the `origin` remote), or pass `-r <repo>` (global flag, works before or after the verb) to target a different one explicitly — there's no single hardcoded default repo, so don't assume one. A few conventions `--help` won't surface: **never `curl` the forge** — the CLI handles auth and is the only supported path; to check a PR's CI + mergeability use `hive-forge pr status --pr <n>` (or `--sha <commit>` for a CI-only fast path; exit code is a merge-readiness verdict), not curl. `--body-file -` reads the body from stdin, so a HEREDOC works for multi-line comments/issues: `hive-forge comment <num> --body-file - <<EOF ... EOF`. `hive-forge pr create --title "..." --head <branch> [--push]` opens a PR and prints its URL; `--push` `git push`es the head branch first (default remote `forge`). Forge notifications are delivered via the internal message daemon (sender `forge`), not polling. A `forge` notification stays unread **on the forge** until you actually read its thread — viewing the referenced issue/PR with `hive-forge comments <n>` or `view <n>` marks that notification read (it's the forge's own read-state, not a local mirror). So when a `forge` message points you at a thread, read the thread to clear the notification instead of letting the same one linger and re-surface. (`hive-forge comment` does the opposite — it _refuses_ to post to a thread with unread activity until you've read it, so read first, then comment.)
|
||||
|
||||
Keep messages short — a few sentences each. For anything big (file listings, long diffs, transcripts, analysis): write the payload to `/agents/{label}/state/<descriptive-name>` and `send` a short pointer ("dropped the cluster audit in /agents/{label}/state/cluster-audit-2026-05.md, headline: 3 nodes over 80% mem"). The operator can read your state from the host as `/agents/{label}/state/`. Sub-agent peers can't read each other's state directly — coordinate through shared space or a common parent.
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ use anyhow::{Context, Result, bail};
|
|||
/// Resolve the body to send, given the user's explicit flags and the
|
||||
/// current stdin state. Returns `None` when none of the sources are
|
||||
/// available (the caller decides whether that's allowed — e.g.
|
||||
/// `issue-edit` treats absent body as "leave unchanged", while
|
||||
/// `issue edit` treats absent body as "leave unchanged", while
|
||||
/// `comment` treats absent body as a hard error).
|
||||
pub fn resolve(body: Option<&str>, file: Option<&str>) -> Result<Option<String>> {
|
||||
if body.is_some() && file.is_some() {
|
||||
|
|
|
|||
|
|
@ -124,7 +124,7 @@ enum Verb {
|
|||
#[command(hide = true)]
|
||||
PrStatus(verbs::pr_status::Args),
|
||||
/// Clone a forge repo (default `-r`/`HIVE_FORGE_REPO`) with
|
||||
/// credentials autoinjected. Pairs with `pr-create --agit`.
|
||||
/// credentials autoinjected. Pairs with `pr create --agit`.
|
||||
Clone(verbs::clone::Args),
|
||||
/// Create a forge repo under the current user (or `--org`). Prints
|
||||
/// the repo URL.
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
//! the only path is the web UI's download route,
|
||||
//! `<base>/<owner>/<repo>/actions/runs/<run-id>/artifacts/<name>`. That
|
||||
//! route is keyed by the run's GLOBAL id, **not** the per-repo run number
|
||||
//! the UI shows in run-page URLs (`/actions/runs/51`) and that `pr-status`
|
||||
//! the UI shows in run-page URLs (`/actions/runs/51`) and that `pr status`
|
||||
//! surfaces as a CI context's `target_url`. The REST artifacts *list*
|
||||
//! route, confusingly, keys off the run number instead — so the two can't
|
||||
//! be chained directly. We therefore translate the caller's run number
|
||||
|
|
@ -32,7 +32,7 @@ pub struct Args {
|
|||
/// Artifact name, as shown on the run page (for example `pr1ma-paper-pdf`).
|
||||
name: String,
|
||||
/// Workflow run number — the `runs/<n>` in the run-page URL, which
|
||||
/// `pr-status` surfaces as a CI context's `target_url`. (This is the
|
||||
/// `pr status` surfaces as a CI context's `target_url`. (This is the
|
||||
/// per-repo run number, not the global run id; the verb translates.)
|
||||
#[arg(long)]
|
||||
run: u64,
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ use forgejo_api::structs::{ActionRun, ListActionRunsQuery};
|
|||
use crate::client::Client;
|
||||
|
||||
/// The per-repo run NUMBER from a run object's `html_url` (`…/runs/<n>`
|
||||
/// tail) — the number the UI shows, `pr-status` surfaces, and every
|
||||
/// tail) — the number the UI shows, `pr status` surfaces, and every
|
||||
/// `--run <n>` flag takes.
|
||||
///
|
||||
/// ⚠️ NOT [`ActionRun::id`]: Forgejo's `GET
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ use crate::client::Client;
|
|||
#[derive(ClapArgs)]
|
||||
pub struct Args {
|
||||
/// Workflow run number — the `runs/<n>` in the run-page URL (shown
|
||||
/// by `pr-status`).
|
||||
/// by `pr status`).
|
||||
#[arg(long)]
|
||||
run: u64,
|
||||
/// Job index within the run (0-based, default 0).
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@
|
|||
//!
|
||||
//! Dispatch re-runs the whole workflow (no single-job variant). ⚠️ `--pr`
|
||||
//! verifies the code but doesn't reliably move the PR's own status
|
||||
//! checks — see `docs/scheduler/ci.md`'s "CI checks" for why; re-check `pr-status`.
|
||||
//! checks — see `docs/scheduler/ci.md`'s "CI checks" for why; re-check `pr status`.
|
||||
|
||||
use anyhow::{Context as _, Result, bail};
|
||||
use clap::Args as ClapArgs;
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
//! with credentials auto-injected, so agents don't hand-assemble
|
||||
//! token-bearing URLs. The repo is the standard `-r/--repo` (see
|
||||
//! `client::Client::from_env` for the full resolution chain). Pairs
|
||||
//! with `pr-create --agit`: clone, edit + commit normally, then open a
|
||||
//! with `pr create --agit`: clone, edit + commit normally, then open a
|
||||
//! PR via the `AGit` ref.
|
||||
//!
|
||||
//! The clone URL itself carries no credentials, and the resulting
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
//! `issue-create --title <t> [body sources] [--assignee <u>]
|
||||
//! `issue create --title <t> [body sources] [--assignee <u>]
|
||||
//! [--label <name>]... [repo]` — create an issue. Prints the issue URL.
|
||||
|
||||
use anyhow::Result;
|
||||
|
|
@ -46,7 +46,7 @@ pub fn run(client: &Client, args: Args) -> Result<()> {
|
|||
let body = body::resolve_required(
|
||||
args.body.as_deref(),
|
||||
args.body_file.as_deref(),
|
||||
"issue-create",
|
||||
"issue create",
|
||||
)?;
|
||||
let (owner, name) = client.owner_repo()?;
|
||||
let label_ids = if args.labels.is_empty() {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
//! `issue-edit <number> [--title <t>] [body sources] [--state s]
|
||||
//! `issue edit <number> [--title <t>] [body sources] [--state s]
|
||||
//! [--milestone id] [repo]` — partial update of an issue. Fields not
|
||||
//! provided are left unchanged. Also backs `pr edit`: Forgejo serves
|
||||
//! both kinds off the same `/issues/<n>` endpoint, so this is shared
|
||||
|
|
|
|||
|
|
@ -91,7 +91,7 @@ pub fn run(client: &Client, args: Args) -> Result<()> {
|
|||
}
|
||||
|
||||
/// The repo's whole label set, for name → id resolution. `pub(crate)` so
|
||||
/// other verbs (`issue-create`, `pr-create`, `list`) can resolve a label
|
||||
/// other verbs (`issue create`, `pr create`, `list`) can resolve a label
|
||||
/// name without duplicating the lookup.
|
||||
///
|
||||
/// Paginated, where this used to ask for one page of 100 — **a page size
|
||||
|
|
@ -127,7 +127,7 @@ pub(crate) fn repo_labels(client: &Client) -> Result<Vec<Label>> {
|
|||
/// Resolve label names to ids, hard-erroring if any name doesn't match an
|
||||
/// existing repo label. A typo used to silently produce fewer labels than
|
||||
/// intended with no signal — not even a nonzero exit code — so callers
|
||||
/// (`labels add`, `issue-create --label`, `pr-create --label`) had no way
|
||||
/// (`labels add`, `issue create --label`, `pr create --label`) had no way
|
||||
/// to notice without manually diffing what they asked for against what
|
||||
/// landed. The error lists both the exact names that didn't resolve and
|
||||
/// every label actually available on the repo, so it's fixable from the
|
||||
|
|
|
|||
|
|
@ -299,8 +299,8 @@ fn reviewed_older_head(reviewed_sha: Option<&str>, head_sha: Option<&str>) -> bo
|
|||
/// Latest non-comment review per reviewer on a PR. Reviews come
|
||||
/// oldest-first, so a later verdict from the same user supersedes an
|
||||
/// earlier one; `COMMENT` / `PENDING` reviews carry no verdict and are
|
||||
/// skipped. Shared by `pr-status` (health view + readiness verdict) and
|
||||
/// `pr-merge` (pre-merge changes-requested gate) so the verdict semantics
|
||||
/// skipped. Shared by `pr status` (health view + readiness verdict) and
|
||||
/// `pr merge` (pre-merge changes-requested gate) so the verdict semantics
|
||||
/// stay in one place.
|
||||
///
|
||||
/// # Errors
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
//! `pr-commits <number> [repo]` — list a PR's commits as JSON
|
||||
//! `pr commits <number> [repo]` — list a PR's commits as JSON
|
||||
//! (sha, message, author date, author login), paginated.
|
||||
//!
|
||||
//! The forge stores a PR's commits against its branch ref, so this
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
//! `pr-create --title <t> --head <branch> [--base <b>] [body sources]
|
||||
//! `pr create --title <t> --head <branch> [--base <b>] [body sources]
|
||||
//! [--draft] [--push] [--remote <name>] [repo]` — create a PR. Prints
|
||||
//! the PR URL.
|
||||
//!
|
||||
|
|
@ -71,7 +71,7 @@ pub struct Args {
|
|||
/// Label name to attach, repeatable (for example `--label area/ops --label
|
||||
/// type/bug`). Same spelling `labels add` accepts — an unresolved name
|
||||
/// errors out rather than silently attaching fewer labels than asked
|
||||
/// for. In `--agit` mode `pr-create` applies this as a follow-up call
|
||||
/// for. In `--agit` mode `pr create` applies this as a follow-up call
|
||||
/// once it learns the PR number (the `AGit` push itself has no label
|
||||
/// field), so it silently skips them (not a label-resolution error) if
|
||||
/// it couldn't parse the PR URL back out of the push output — same
|
||||
|
|
@ -146,7 +146,7 @@ pub fn run(client: &Client, args: Args) -> Result<()> {
|
|||
/// single-line body still rides along as a push option (it's guaranteed
|
||||
/// to land even if we can't parse the PR URL back out); a multi-line
|
||||
/// body is pushed title-only and then set on the resulting PR via a REST
|
||||
/// PATCH, mirroring the manual `pr-create --title …` + `issue-edit
|
||||
/// PATCH, mirroring the manual `pr create --title …` + `issue edit
|
||||
/// --body-file` two-step.
|
||||
fn agit_create(client: &Client, args: &Args, body: &str) -> Result<()> {
|
||||
let remote = args.remote.as_deref().unwrap_or("origin");
|
||||
|
|
@ -192,7 +192,7 @@ fn agit_create(client: &Client, args: &Args, body: &str) -> Result<()> {
|
|||
if deferred_body {
|
||||
eprintln!(
|
||||
"warning: multi-line body NOT set — PR URL not parsed, so it could \
|
||||
not be PATCHed. Set it manually: hive-forge issue-edit <pr#> --body-file -"
|
||||
not be PATCHed. Set it manually: hive-forge issue edit <pr#> --body-file -"
|
||||
);
|
||||
}
|
||||
println!(
|
||||
|
|
@ -224,7 +224,7 @@ fn agit_create(client: &Client, args: &Args, body: &str) -> Result<()> {
|
|||
} else {
|
||||
eprintln!(
|
||||
"warning: multi-line body NOT set — could not parse PR number from {url}. \
|
||||
Set it manually: hive-forge issue-edit <pr#> --body-file -"
|
||||
Set it manually: hive-forge issue edit <pr#> --body-file -"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
//! `pr-merge <number> [--method merge|rebase] [--keep-branch] [--force]`
|
||||
//! `pr merge <number> [--method merge|rebase] [--keep-branch] [--force]`
|
||||
//! — merge a pull request.
|
||||
//!
|
||||
//! Wraps `POST /api/v1/repos/{owner}/{repo}/pulls/{n}/merge` so agents on a
|
||||
//! peer-review-and-merge workflow (e.g. the paper repo, where agents merge
|
||||
//! each other's PRs without an operator approval) have a CLI path instead of
|
||||
//! reaching for the raw API. Pairs with `pr-status` (the merge-readiness
|
||||
//! verdict this verb pre-checks) and `pr-create`.
|
||||
//! reaching for the raw API. Pairs with `pr status` (the merge-readiness
|
||||
//! verdict this verb pre-checks) and `pr create`.
|
||||
//!
|
||||
//! Safe by default: refuses unless the PR is mergeable, CI is not red, and no
|
||||
//! review requests changes — pass `--force` to override (which also sets
|
||||
|
|
@ -120,7 +120,7 @@ pub fn run(client: &Client, args: Args) -> Result<()> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
/// Pre-merge readiness gate, mirroring `pr-status`'s verdict: the PR must be
|
||||
/// Pre-merge readiness gate, mirroring `pr status`'s verdict: the PR must be
|
||||
/// mergeable, CI must not be red/pending, and no review may request changes.
|
||||
/// Bails with an actionable message (pointing at `--force`) on the first
|
||||
/// failure.
|
||||
|
|
@ -133,7 +133,7 @@ fn check_ready(client: &Client, repo: &str, number: u64, pull: &PullRequest) ->
|
|||
// correct for one of those causes and actively wrong advice for the
|
||||
// others (rebasing a draft does nothing). Only name the
|
||||
// cause when the API actually confirms it (draft); otherwise report
|
||||
// the bare observation and let `pr-status` be consulted for detail.
|
||||
// the bare observation and let `pr status` be consulted for detail.
|
||||
// Report the confirmed cause without prescribing the fix — a draft
|
||||
// can be a deliberate signal (from the author, or the operator)
|
||||
// rather than an oversight, so don't tell the caller to just
|
||||
|
|
@ -142,7 +142,7 @@ fn check_ready(client: &Client, repo: &str, number: u64, pull: &PullRequest) ->
|
|||
"pr-merge: PR #{number} is a draft, not mergeable. Pass --force, or check with whoever set draft before un-drafting it."
|
||||
),
|
||||
Some(false) => bail!(
|
||||
"pr-merge: PR #{number} is not mergeable. Check `pr-status --pr {number}` for detail, or pass --force."
|
||||
"pr-merge: PR #{number} is not mergeable. Check `pr status --pr {number}` for detail, or pass --force."
|
||||
),
|
||||
None => bail!(
|
||||
"pr-merge: PR #{number} mergeability is still being computed. Retry shortly, or pass --force."
|
||||
|
|
@ -165,7 +165,7 @@ fn check_ready(client: &Client, repo: &str, number: u64, pull: &PullRequest) ->
|
|||
// (latest-per-reviewer, so a later APPROVED clears an earlier
|
||||
// REQUEST_CHANGES). A superseded REQUEST_CHANGES — stale (older head) or
|
||||
// dismissed — no longer applies, so it doesn't block. Shares the verdict
|
||||
// logic with `pr-status`.
|
||||
// logic with `pr status`.
|
||||
let blockers: Vec<String> = super::latest_reviews(client, repo, number)?
|
||||
.into_iter()
|
||||
.filter(|r| r.state == "REQUEST_CHANGES" && !r.superseded())
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
//! `pr-reviews <number>` — list reviews, or submit one via `--approve` /
|
||||
//! `pr reviews <number>` — list reviews, or submit one via `--approve` /
|
||||
//! `--request-changes` / `--comment`.
|
||||
|
||||
use anyhow::{Result, bail};
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
//! `pr-status --pr <n>` — one-stop PR health view: mergeable state, CI
|
||||
//! `pr status --pr <n>` — one-stop PR health view: mergeable state, CI
|
||||
//! checks, requested reviewers + review verdicts, and the last-comment
|
||||
//! timestamp. `--sha <sha>` is a CI-only fast path for a raw commit.
|
||||
//! Removes the need for raw `curl` to the statuses / reviews endpoints,
|
||||
|
|
@ -6,7 +6,7 @@
|
|||
//!
|
||||
//! Exit code is a merge-readiness verdict for `--pr`: 0 only when CI is
|
||||
//! green AND the PR is mergeable AND no review requests changes — so it
|
||||
//! composes (`hive-forge pr-status --pr 42 && …`). `--sha` mirrors the
|
||||
//! composes (`hive-forge pr status --pr 42 && …`). `--sha` mirrors the
|
||||
//! CI verdict alone (0 = success).
|
||||
|
||||
use anyhow::{Context, Result, bail};
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ pub fn run(client: &Client, args: Args) -> Result<()> {
|
|||
if client.json_mode() {
|
||||
return print_json(&serde_json::to_value(&resp)?);
|
||||
}
|
||||
// Default human path: print the web URL, like issue-create / pr-create.
|
||||
// Default human path: print the web URL, like issue create / pr create.
|
||||
if let Some(url) = resp.html_url {
|
||||
println!("{url}");
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue