Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e5e62ad2e6 | ||
|
|
d5a27a5823 | ||
|
|
224cb06004 | ||
|
|
a97d159009 |
6 changed files with 64 additions and 11 deletions
|
|
@ -55,6 +55,9 @@ hive-forge pr-reviews 42 # list reviews; inline comments incl
|
||||||
hive-forge pr-reviews 42 --approve # submit APPROVED 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 --request-changes -m "msg" # submit REQUEST_CHANGES review
|
||||||
hive-forge pr-reviews 42 --comment -m "msg" # submit COMMENT 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 # unified diff (lockfile hunks collapsed by default)
|
||||||
hive-forge diff 42 --full # include unfiltered lockfile hunks
|
hive-forge diff 42 --full # include unfiltered lockfile hunks
|
||||||
hive-forge list # open issues/PRs
|
hive-forge list # open issues/PRs
|
||||||
|
|
|
||||||
|
|
@ -145,7 +145,7 @@ nodes are skipped. A `select all / select none`
|
||||||
control sits above the tree. Checking inputs + submitting bumps
|
control sits above the tree. Checking inputs + submitting bumps
|
||||||
the lock in `/meta/` and rebuilds the selected agents in
|
the lock in `/meta/` and rebuilds the selected agents in
|
||||||
sequence; each outcome reaches the root agent as a `rebuilt`
|
sequence; each outcome reaches the root agent as a `rebuilt`
|
||||||
system event. `POST /meta-update`. While a lock-bump ripple runs,
|
system event. `POST /api/meta-update`. While a lock-bump ripple runs,
|
||||||
the panel shows a pulsing "⏳ meta-update running" banner and the
|
the panel shows a pulsing "⏳ meta-update running" banner and the
|
||||||
update button is disabled (snapshot field `meta_update_running`,
|
update button is disabled (snapshot field `meta_update_running`,
|
||||||
live event `meta_update_running`).
|
live event `meta_update_running`).
|
||||||
|
|
@ -430,9 +430,9 @@ Refreshed on tab activation and after each submit/cancel. Backed by
|
||||||
**QU3U3D R3M1ND3RS** — reminders agents have scheduled for
|
**QU3U3D R3M1ND3RS** — reminders agents have scheduled for
|
||||||
themselves (via the `remind` tool) but not yet delivered.
|
themselves (via the `remind` tool) but not yet delivered.
|
||||||
Each row shows the owner, due time, and message; a `CANC3L`
|
Each row shows the owner, due time, and message; a `CANC3L`
|
||||||
button hard-deletes (`POST /cancel-reminder/{id}`) and a
|
button hard-deletes (`POST /api/cancel-reminder/{id}`) and a
|
||||||
`R3TRY` button re-arms one whose delivery failed
|
`R3TRY` button re-arms one whose delivery failed
|
||||||
(`POST /retry-reminder/{id}`). Backed by `GET /api/reminders`.
|
(`POST /api/retry-reminder/{id}`). Backed by `GET /api/reminders`.
|
||||||
Lives in the SCH3DUL3S tab alongside operator schedules so the
|
Lives in the SCH3DUL3S tab alongside operator schedules so the
|
||||||
operator has one place for everything time-fired. The due-time
|
operator has one place for everything time-fired. The due-time
|
||||||
label (`.reminder-due`) carries a `data-due-at` Unix timestamp
|
label (`.reminder-due`) carries a `data-due-at` Unix timestamp
|
||||||
|
|
@ -1124,8 +1124,8 @@ that's a browser-level decision, not ours.
|
||||||
a background `du -sxb` of the agent's state dir + container writable
|
a background `du -sxb` of the agent's state dir + container writable
|
||||||
rootfs every ~5 min, `-x` excluding the shared read-only nix store.
|
rootfs every ~5 min, `-x` excluding the shared read-only nix store.
|
||||||
`null` until the first sample lands.
|
`null` until the first sample lands.
|
||||||
- `POST /cancel-reminder/{id}` — hard-delete a pending reminder.
|
- `POST /api/cancel-reminder/{id}` — hard-delete a pending reminder.
|
||||||
- `POST /retry-reminder/{id}` — re-arm a reminder whose delivery
|
- `POST /api/retry-reminder/{id}` — re-arm a reminder whose delivery
|
||||||
failed (clears the failure state so the scheduler retries).
|
failed (clears the failure state so the scheduler retries).
|
||||||
- `GET /api/tool-groups` — returns `{ groups: Vec<String>,
|
- `GET /api/tool-groups` — returns `{ groups: Vec<String>,
|
||||||
assignments: BTreeMap<String, Vec<String>>,
|
assignments: BTreeMap<String, Vec<String>>,
|
||||||
|
|
@ -1197,7 +1197,7 @@ that's a browser-level decision, not ours.
|
||||||
Per-target `last_result` is annotated as a manual fire so
|
Per-target `last_result` is annotated as a manual fire so
|
||||||
the audit trail distinguishes scheduled fires from operator-
|
the audit trail distinguishes scheduled fires from operator-
|
||||||
triggered ones.
|
triggered ones.
|
||||||
- `POST /meta-update` — `nix flake update` the selected
|
- `POST /api/meta-update` — `nix flake update` the selected
|
||||||
`meta/flake.lock` inputs, then rebuild the affected agents.
|
`meta/flake.lock` inputs, then rebuild the affected agents.
|
||||||
- `GET /dashboard/stream` — unified live event channel:
|
- `GET /dashboard/stream` — unified live event channel:
|
||||||
broker `sent` / `delivered`, plus the mutation events listed
|
broker `sent` / `delivered`, plus the mutation events listed
|
||||||
|
|
|
||||||
|
|
@ -63,7 +63,7 @@ enum Verb {
|
||||||
/// Edit an issue's title, body, state, or milestone.
|
/// Edit an issue's title, body, state, or milestone.
|
||||||
#[command(hide = true)]
|
#[command(hide = true)]
|
||||||
IssueEdit(verbs::issue_edit::Args),
|
IssueEdit(verbs::issue_edit::Args),
|
||||||
/// PR-scoped commands: `pr <show|status|create|merge|reviews|commits|diff|view|comment|comments|close|reopen|labels|assign|timeline> …`.
|
/// PR-scoped commands: `pr <show|status|create|merge|reviews|assign-reviewer|commits|diff|view|comment|comments|close|reopen|labels|assign-committer|timeline> …`.
|
||||||
Pr(verbs::pr_cmd::Args),
|
Pr(verbs::pr_cmd::Args),
|
||||||
/// List a PR's commits as JSON (sha, message, author date, author).
|
/// List a PR's commits as JSON (sha, message, author date, author).
|
||||||
/// Survives rebase-rewritten shas — message + author date let a
|
/// Survives rebase-rewritten shas — message + author date let a
|
||||||
|
|
@ -135,6 +135,9 @@ enum Verb {
|
||||||
/// `--request-changes` / `--comment` (with `-m` for the body).
|
/// `--request-changes` / `--comment` (with `-m` for the body).
|
||||||
#[command(hide = true)]
|
#[command(hide = true)]
|
||||||
PrReviews(verbs::pr_reviews::Args),
|
PrReviews(verbs::pr_reviews::Args),
|
||||||
|
/// Request (or withdraw with `--remove`) a review from a user on a PR.
|
||||||
|
#[command(hide = true)]
|
||||||
|
PrAssignReviewer(verbs::pr_assign_reviewer::Args),
|
||||||
/// List branches, optionally filtered.
|
/// List branches, optionally filtered.
|
||||||
Branches(verbs::branches::Args),
|
Branches(verbs::branches::Args),
|
||||||
/// Print the tree SHA at a branch or commit.
|
/// Print the tree SHA at a branch or commit.
|
||||||
|
|
@ -200,6 +203,7 @@ fn main() -> Result<()> {
|
||||||
Verb::Milestone(a) => verbs::milestone::run(&client, a),
|
Verb::Milestone(a) => verbs::milestone::run(&client, a),
|
||||||
Verb::PrMerge(a) => verbs::pr_merge::run(&client, a),
|
Verb::PrMerge(a) => verbs::pr_merge::run(&client, a),
|
||||||
Verb::PrReviews(a) => verbs::pr_reviews::run(&client, a),
|
Verb::PrReviews(a) => verbs::pr_reviews::run(&client, a),
|
||||||
|
Verb::PrAssignReviewer(a) => verbs::pr_assign_reviewer::run(&client, a),
|
||||||
Verb::Branches(a) => verbs::branches::run(&client, a),
|
Verb::Branches(a) => verbs::branches::run(&client, a),
|
||||||
Verb::TreeSha(a) => verbs::tree_sha::run(&client, a),
|
Verb::TreeSha(a) => verbs::tree_sha::run(&client, a),
|
||||||
Verb::Diff(a) => verbs::diff::run(&client, a),
|
Verb::Diff(a) => verbs::diff::run(&client, a),
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@ pub mod lint;
|
||||||
pub mod list;
|
pub mod list;
|
||||||
pub mod milestone;
|
pub mod milestone;
|
||||||
pub mod pr;
|
pub mod pr;
|
||||||
|
pub mod pr_assign_reviewer;
|
||||||
pub mod pr_cmd;
|
pub mod pr_cmd;
|
||||||
pub mod pr_commits;
|
pub mod pr_commits;
|
||||||
pub mod pr_create;
|
pub mod pr_create;
|
||||||
|
|
|
||||||
41
hive-forge/src/verbs/pr_assign_reviewer.rs
Normal file
41
hive-forge/src/verbs/pr_assign_reviewer.rs
Normal file
|
|
@ -0,0 +1,41 @@
|
||||||
|
//! `pr assign-reviewer <number> <user> [--remove]` — add or remove a
|
||||||
|
//! requested reviewer on a PR. Unlike `pr assign-committer` (assignees,
|
||||||
|
//! mutate + PATCH the issue) Forgejo has a dedicated endpoint pair for review
|
||||||
|
//! requests: `POST /repos/{repo}/pulls/{index}/requested_reviewers`
|
||||||
|
//! adds, `DELETE` (same path + body) removes. Requesting a review from
|
||||||
|
//! a user who is already requested is a Forgejo-side no-op, so the verb
|
||||||
|
//! is idempotent in both directions.
|
||||||
|
|
||||||
|
use anyhow::Result;
|
||||||
|
use clap::Args as ClapArgs;
|
||||||
|
use serde_json::json;
|
||||||
|
|
||||||
|
use crate::client::Client;
|
||||||
|
|
||||||
|
#[derive(ClapArgs)]
|
||||||
|
pub struct Args {
|
||||||
|
/// PR number.
|
||||||
|
number: u64,
|
||||||
|
/// User login to request a review from (or withdraw with `--remove`).
|
||||||
|
user: String,
|
||||||
|
/// Withdraw the review request instead of adding it.
|
||||||
|
#[arg(long)]
|
||||||
|
remove: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn run(client: &Client, args: Args) -> Result<()> {
|
||||||
|
let repo = client.repo();
|
||||||
|
let path = format!("/repos/{repo}/pulls/{}/requested_reviewers", args.number);
|
||||||
|
let body = json!({ "reviewers": [args.user] });
|
||||||
|
if args.remove {
|
||||||
|
client.delete(&path, Some(&body))?;
|
||||||
|
println!(
|
||||||
|
"review request withdrawn: {} on #{}",
|
||||||
|
args.user, args.number
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
client.post_json(&path, &body)?;
|
||||||
|
println!("review requested: {} on #{}", args.user, args.number);
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
//! `pr <verb>` — PR-scoped sub-commands. Wraps the per-verb modules under a
|
//! `pr <verb>` — PR-scoped sub-commands. Wraps the per-verb modules under a
|
||||||
//! `pr` parent so `hive-forge pr close 42`, `pr status --pr 42`, etc. read as
|
//! `pr` parent so `hive-forge pr close 42`, `pr status --pr 42`, etc. read as
|
||||||
//! kind-namespaced commands. The generic verbs that also work on issues
|
//! kind-namespaced commands. The generic verbs that also work on issues
|
||||||
//! (view/comment/comments/close/reopen/labels/assign/timeline) kind-check the number
|
//! (view/comment/comments/close/reopen/labels/assign-committer/timeline) kind-check the number
|
||||||
//! is a PR first (`assert_kind`); the PR-only verbs hit `/pulls/…` and are
|
//! is a PR first (`assert_kind`); the PR-only verbs hit `/pulls/…` and are
|
||||||
//! kind-correct by construction. The flat `pr-*` + bare generic verbs stay as
|
//! kind-correct by construction. The flat `pr-*` + bare generic verbs stay as
|
||||||
//! hidden back-compat aliases (see `main.rs`).
|
//! hidden back-compat aliases (see `main.rs`).
|
||||||
|
|
@ -32,6 +32,8 @@ enum Cmd {
|
||||||
Merge(verbs::pr_merge::Args),
|
Merge(verbs::pr_merge::Args),
|
||||||
/// List a PR's reviews, or submit one.
|
/// List a PR's reviews, or submit one.
|
||||||
Reviews(verbs::pr_reviews::Args),
|
Reviews(verbs::pr_reviews::Args),
|
||||||
|
/// Request (or withdraw with `--remove`) a review from a user.
|
||||||
|
AssignReviewer(verbs::pr_assign_reviewer::Args),
|
||||||
/// Print the PR's unified diff.
|
/// Print the PR's unified diff.
|
||||||
Diff(verbs::diff::Args),
|
Diff(verbs::diff::Args),
|
||||||
/// Show title + body + comments.
|
/// Show title + body + comments.
|
||||||
|
|
@ -46,8 +48,9 @@ enum Cmd {
|
||||||
Reopen(verbs::reopen::Args),
|
Reopen(verbs::reopen::Args),
|
||||||
/// List / add / remove labels.
|
/// List / add / remove labels.
|
||||||
Labels(verbs::labels::Args),
|
Labels(verbs::labels::Args),
|
||||||
/// Assign or unassign a user.
|
/// Assign or unassign a user (the PR's assignee list).
|
||||||
Assign(verbs::assign::Args),
|
#[command(alias = "assign")]
|
||||||
|
AssignCommitter(verbs::assign::Args),
|
||||||
/// List timeline events.
|
/// List timeline events.
|
||||||
Timeline(verbs::timeline::Args),
|
Timeline(verbs::timeline::Args),
|
||||||
}
|
}
|
||||||
|
|
@ -61,6 +64,7 @@ pub fn run(client: &Client, args: Args) -> Result<()> {
|
||||||
Cmd::Status(a) => verbs::pr_status::run(client, a),
|
Cmd::Status(a) => verbs::pr_status::run(client, a),
|
||||||
Cmd::Merge(a) => verbs::pr_merge::run(client, a),
|
Cmd::Merge(a) => verbs::pr_merge::run(client, a),
|
||||||
Cmd::Reviews(a) => verbs::pr_reviews::run(client, a),
|
Cmd::Reviews(a) => verbs::pr_reviews::run(client, a),
|
||||||
|
Cmd::AssignReviewer(a) => verbs::pr_assign_reviewer::run(client, a),
|
||||||
Cmd::Diff(a) => verbs::diff::run(client, a),
|
Cmd::Diff(a) => verbs::diff::run(client, a),
|
||||||
// Generics shared with `issue` — verify the number is a PR first.
|
// Generics shared with `issue` — verify the number is a PR first.
|
||||||
Cmd::View(a) => {
|
Cmd::View(a) => {
|
||||||
|
|
@ -87,7 +91,7 @@ pub fn run(client: &Client, args: Args) -> Result<()> {
|
||||||
assert_kind(client, a.number, Kind::Pr)?;
|
assert_kind(client, a.number, Kind::Pr)?;
|
||||||
verbs::labels::run(client, a)
|
verbs::labels::run(client, a)
|
||||||
}
|
}
|
||||||
Cmd::Assign(a) => {
|
Cmd::AssignCommitter(a) => {
|
||||||
assert_kind(client, a.number, Kind::Pr)?;
|
assert_kind(client, a.number, Kind::Pr)?;
|
||||||
verbs::assign::run(client, a)
|
verbs::assign::run(client, a)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue