Sort issues, set a milestone on create, and add reactions, dependencies and tracked time #281

Merged
stephen merged 11 commits from feat/spec-parity-issues into main 2026-10-08 21:09:16 +00:00
Owner

Five issues requirements of the fjord-client-spec (#211).

fj issue list --sort takes Forgejo's own wire values (recentupdate,
leastupdate, latest, oldest, mostcomment, leastcomment, nearduedate,
farduedate). The server silently falls back to its default order on an
unknown value, so the flag is a closed enum.

fj issue create --milestone <TITLE|ID> resolves the milestone first
(title, then id; an ambiguous title errors naming the ids) and sends the
id in the create request. The confirmation line is read back from the
server's response.

fj issue reaction list|add|remove|toggle work on the issue body or,
with --comment, on one comment. The tally is re-read after every change.

fj issue dependency list|add|remove show "Depends on" and "Blocks" as
two lists and keep the direction through --blocks. A self reference is
refused with no request; a duplicate, a cycle and a removal from the
wrong list are refused after reading both lists and before any mutation.

fj issue time list|add|delete log and total tracked time. Durations
read as 1h30m, 45m, 90s or 1:30; a bare number is refused.

Dependencies and tracked time accept a pull request number too, since
the index is shared. Their "disabled on this repository" and "permission
denied" messages rest on a preflight of the repository's tracker
switches plus assumed status codes that have not been exercised against
a live forge.

fj issue view --json and the list JSON gain a milestone field.

Covered by unit and wiremock tests only. The status codes behind the dependency and tracked-time "disabled" and "permission denied" messages are the ones worth a live check before relying on the wording.

Part 4 of 8 in the spec-parity stack. Based on feat/spec-parity-admin-profile, so the diff here is this slice alone; it needs a rebase onto main once the PR below it is squash-merged.

Closes #211

Verified on macOS at this commit: cargo fmt --all clean, cargo clippy --all-targets --all-features -- -D warnings clean, cargo test --all green.

Five issues requirements of the fjord-client-spec (#211). `fj issue list --sort` takes Forgejo's own wire values (recentupdate, leastupdate, latest, oldest, mostcomment, leastcomment, nearduedate, farduedate). The server silently falls back to its default order on an unknown value, so the flag is a closed enum. `fj issue create --milestone <TITLE|ID>` resolves the milestone first (title, then id; an ambiguous title errors naming the ids) and sends the id in the create request. The confirmation line is read back from the server's response. `fj issue reaction list|add|remove|toggle` work on the issue body or, with --comment, on one comment. The tally is re-read after every change. `fj issue dependency list|add|remove` show "Depends on" and "Blocks" as two lists and keep the direction through --blocks. A self reference is refused with no request; a duplicate, a cycle and a removal from the wrong list are refused after reading both lists and before any mutation. `fj issue time list|add|delete` log and total tracked time. Durations read as 1h30m, 45m, 90s or 1:30; a bare number is refused. Dependencies and tracked time accept a pull request number too, since the index is shared. Their "disabled on this repository" and "permission denied" messages rest on a preflight of the repository's tracker switches plus assumed status codes that have not been exercised against a live forge. `fj issue view --json` and the list JSON gain a `milestone` field. Covered by unit and wiremock tests only. The status codes behind the dependency and tracked-time "disabled" and "permission denied" messages are the ones worth a live check before relying on the wording. Part 4 of 8 in the spec-parity stack. Based on `feat/spec-parity-admin-profile`, so the diff here is this slice alone; it needs a rebase onto main once the PR below it is squash-merged. Closes #211 Verified on macOS at this commit: `cargo fmt --all` clean, `cargo clippy --all-targets --all-features -- -D warnings` clean, `cargo test --all` green.
Five issues requirements of the fjord-client-spec (#211).

`fj issue list --sort` takes Forgejo's own wire values (recentupdate,
leastupdate, latest, oldest, mostcomment, leastcomment, nearduedate,
farduedate). The server silently falls back to its default order on an
unknown value, so the flag is a closed enum.

`fj issue create --milestone <TITLE|ID>` resolves the milestone first
(title, then id; an ambiguous title errors naming the ids) and sends the
id in the create request. The confirmation line is read back from the
server's response.

`fj issue reaction list|add|remove|toggle` work on the issue body or,
with --comment, on one comment. The tally is re-read after every change.

`fj issue dependency list|add|remove` show "Depends on" and "Blocks" as
two lists and keep the direction through --blocks. A self reference is
refused with no request; a duplicate, a cycle and a removal from the
wrong list are refused after reading both lists and before any mutation.

`fj issue time list|add|delete` log and total tracked time. Durations
read as 1h30m, 45m, 90s or 1:30; a bare number is refused.

Dependencies and tracked time accept a pull request number too, since
the index is shared. Their "disabled on this repository" and "permission
denied" messages rest on a preflight of the repository's tracker
switches plus assumed status codes that have not been exercised against
a live forge.

`fj issue view --json` and the list JSON gain a `milestone` field.

Closes #211
stephen changed target branch from feat/spec-parity-admin-profile to feat/spec-parity-fjord 2026-10-08 19:42:38 +00:00
Four forge-organization-management requirements and one repositories
requirement of the fjord-client-spec.

`fj org create` validates the name and fields locally, then prints the
organization the server returned. A permission denial and a name
conflict get different headlines.

`fj org team create|members|add-member|remove-member|repos|add-repo|
remove-repo`. Every mutation is followed by a read, and the command
errors if that read contradicts the change. Team creation and member
changes are refused before sending when the account is neither an org
owner nor a site admin; add-repo and remove-repo have no local preflight
and rely on the server's 403.

`fj repo collaborator list` reported every permission as none: the list
endpoint sends `permissions: null` and the field defaulted to all-false.
It is now optional, and the list resolves each row through the
per-collaborator permission endpoint. A 403 on a row leaves it "unknown",
never "none". `add` and `remove` now confirm against the server.

`fj repo transfer request` inspects before it asks: it resolves the new
owner, refuses an unknown owner, the current owner and an already
pending transfer, and prints who has to accept. `fj repo transfer
list|view|accept|reject` review incoming transfers. Forgejo has no
incoming-transfer endpoint, so `list` scans the caller's repository
listings and can miss a transfer addressed to one of their orgs;
`view -R` always works. The help text says so.

`fj repo topics add|remove` use the single-topic routes and print the
list the server confirms. `--set` now reads back too instead of echoing
its own input, and validates topic names locally.

Covered by unit and wiremock tests only; nothing here was run against a live forge. `repo transfer list` is knowingly partial, for the reason above.

Part 5 of 8 in the spec-parity stack. Based on `feat/spec-parity-issues`, so the diff here is this slice alone; it needs a rebase onto main once the PR below it is squash-merged.

Fixes #276

Verified on macOS at this commit: `cargo fmt --all` clean, `cargo clippy --all-targets --all-features -- -D warnings` clean, `cargo test --all` green.

Reviewed-on: #282
stephen changed target branch from feat/spec-parity-fjord to main 2026-10-08 20:22:15 +00:00
Review on diff lines and explain merge blockers before merging (#283)
Some checks failed
ci / coverage (pull_request) Has been cancelled
ci / live-e2e (pull_request) Has been cancelled
ci / check (pull_request) Has been cancelled
75f5ac557a
Two pull-requests requirements of the fjord-client-spec (#213).

Inline review comments. `fj pr review N --line-comment <PATH> <LINE>
<BODY>` is repeatable, and `--line-comments-file` takes the same as a
JSON array. LINE is `N` or `new:N` for the PR's version of the file and
`old:N` for a removed line. Comments given with --event are batched into
that review in one request; without --event they post as a plain comment
review. Each anchor is checked against the PR diff first, so a line that
is not commentable is refused locally with the commentable lines named.
Only single-line anchors are supported: range fields are rejected, which
is also what Gitea needs.

`--event comment` with nothing to say and `--event request-changes` with
no body now fail locally instead of as a server 422.

Merge preflight. `fj pr merge` used to explain a blocked merge only
after the server refused it, and through the admin-only branch
protection endpoint. It now reads the base branch's effective protection
from GET /branches/{branch}, which needs read access only, before the
POST. A certain blocker (a required check failing, pending or not
reported, a missing required approval, no merge permission) stops the
merge with the reason and, for checks still running, a pointer to
--auto. Evidence that could not be read stays "unknown": it never blocks
and never reads as passing, and the server decides.

`fj pr checks` shows the same verdict, gains a REQUIRED column, and
lists required checks that have not reported. Its --json is additive:
`required` per status, `statuses_complete` and `merge_preflight`.

Covered by unit and wiremock tests only; the preflight was not run against a live protected branch. `fj pr checks` gains a `REQUIRED` column, which shifts the table for anything parsing it.

Part 6 of 8 in the spec-parity stack. Based on `feat/spec-parity-org`, so the diff here is this slice alone; it needs a rebase onto main once the PR below it is squash-merged.

Closes #213

Verified on macOS at this commit: `cargo fmt --all` clean, `cargo clippy --all-targets --all-features -- -D warnings` clean, `cargo test --all` green.

Reviewed-on: #283
Merge main into feat/spec-parity-issues
Some checks failed
ci / check (pull_request) Successful in 12m43s
ci / live-e2e (pull_request) Failing after 2m27s
ci / coverage (pull_request) Successful in 2m47s
ddab638a1a
Restore the executable bit on scripts/e2e-smoke.sh
All checks were successful
ci / check (pull_request) Successful in 13m31s
ci / coverage (pull_request) Successful in 2m38s
ci / live-e2e (pull_request) Successful in 2m43s
fc27b705a2
The pull request slice rewrote the smoke script as 100644, so the CI
live-e2e job failed with "Permission denied" before running a single
check.
stephen deleted branch feat/spec-parity-issues 2026-10-08 21:09:16 +00:00
Sign in to join this conversation.
No description provided.