diff --git a/.gitea/workflows/ci.yml b/.gitea/workflows/ci.yml index ca2b95d..cd989f4 100644 --- a/.gitea/workflows/ci.yml +++ b/.gitea/workflows/ci.yml @@ -72,7 +72,7 @@ jobs: - name: Build production binary run: | make build - echo "Binary built at: $(pwd)/bin/fj" + echo "Binary built at: $(pwd)/bin/fgj" - name: Run functional tests run: go test -v -race -tags=functional ./tests/functional/... diff --git a/.gitea/workflows/nightly.yml b/.gitea/workflows/nightly.yml index ef53290..d335132 100644 --- a/.gitea/workflows/nightly.yml +++ b/.gitea/workflows/nightly.yml @@ -24,7 +24,7 @@ jobs: - name: Build production binary run: | make build - echo "Binary built at: $(pwd)/bin/fj" + echo "Binary built at: $(pwd)/bin/fgj" - name: Run functional tests run: go test -v -race -tags=functional ./tests/functional/... diff --git a/.gitignore b/.gitignore index 58e31fb..ec3f87e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,5 @@ # Binaries -fj -bin/ +fgj *.exe *.exe~ *.dll @@ -32,5 +31,3 @@ config.yaml # Git worktrees .worktrees/ -# Workspace (scratch data, cloned repos, analysis) -.workspace/ diff --git a/CHANGELOG.md b/CHANGELOG.md index 170c5ec..4a61045 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,151 +5,50 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [0.4.0] - 2026-05-02 - -Audit-driven hardening pass. Three reviewers (Codex + two Claude agents -with non-overlapping focuses) found 13 issues across cmd/ and internal/; -this release ships fixes for all 13. - -### BREAKING - -- `--json=fields` syntax removed. The flag was a string with - `NoOptDefVal=" "` sentinel — `--json` alone meant "everything", - `--json=fields` projected. That produced `--json string[=" "]` in - `--help` and required a literal `=` because `--json fields` was parsed - as the bare flag plus a positional. **Migration**: `--json=fields` → - `--json-fields fields`. Bare `--json` still means "all fields as JSON". - `--json` and `--json-fields` are mutually exclusive; `--jq` composes - with either. - -### Added - -- `fj api --json` / `--json-fields` / `--jq` — projection and jq filtering - for raw API responses. Routes through the same `addJSONFlags` helpers - as the other list commands. Closes the inconsistency where `fj api` - was the only command returning raw JSON without these knobs. -- `fj api --paginate` — follows RFC 5988 `Link: rel="next"` headers and - concatenates JSON array pages, gh-compatible. Validates same-origin - before forwarding the bearer token to the next URL. -- `cmd/paginate.go` — generic `paginateGitea[T any]` helper. Applied to - `repo list`, `pr list`, `issue list`. Previously only `release list` - walked pages; the others passed `PageSize: limit` directly to the - gitea SDK, which silently caps PageSize at 50, so `--limit > 50` was - truncated without warning. -- `CLAUDE.md` — guide for Claude Code sessions: layout, codex review - pattern, release process, homebrew tap update steps. - -### Changed - -- `--json` flag rebuilt as a plain `Bool`. `--json-fields` keeps - comma-separated projection. Both registered via `addJSONFlags` and - marked `MutuallyExclusive`. -- `cmd/actions.go` — `run` and `workflow` subtrees converted from - package-level `var`s to factory functions (`newRunCmd`, - `newWorkflowCmd`, ...). `cmd/aliases.go` shrank from 142 → 17 lines - and now calls those same factories with a `parentLabel` parameter that - disambiguates the alias variant. Result: `diff` of `fj run list - --help` flags vs `fj actions run list --help` flags is now empty. - Drift between the two paths is structurally impossible. -- `fj api` now uses `internal/api.SharedHTTPClient` (30s timeout, pooled - connections) instead of a zero-value `&http.Client{}` with no timeout. - A hung Forgejo no longer pins the CLI indefinitely. -- `fj api` response body bounded by `io.LimitReader` at 64 MB to prevent - OOM-on-self. -- `cmd/auth.go` removed redundant local `--hostname` declarations on - three subcommands. The persistent flag on rootCmd is now the only - declaration; previously local declarations shadowed it, so - `fj --hostname=X auth login` and `fj auth login --hostname=X` went - through different code paths. -- `--token` on `auth login` emits a stderr warning when used (visible - in `ps auxe` and shell history). Flag not removed; just discoverable. -- Error handling: `Hint` is now a structured field on `CLIError`. - JSON-error consumers get clean structure; the human renderer still - appends `\nHint: ...`. Dropped substring matching of `"401"`/`"403"` - against rendered error strings (would match issue #403); now relies - exclusively on typed `*api.APIError`. -- Network errors (`no such host`, `connection refused`, `i/o timeout`) - return a structured `CLIError` with code `ErrNetworkError` and a hint. -- Config dir created with mode 0700 instead of 0755. - -### Fixed - -- `--config ` now actually honored. Previously fed only into - Viper; every command that touched config went through - `internal/config.Load()` / `Save()` which always read the default - path. So `fj --config other.yaml auth login` writes to other.yaml now. -- `fj run list --json`, `fj workflow list --json`, `fj wiki view --json` - now produce JSON. `cmd/aliases.go` registered `--json` as `Bool` but - handlers called `wantJSON()` which does `GetString("json")` — pflag - returned a type-error that `wantJSON` silently swallowed. - `cmd/wiki.go` had the inverse bug (`GetBool` against an - `addJSONFlags`-registered string flag). Both routed through - `addJSONFlags`/`wantJSON`/`outputJSON` consistently now. -- `migrateConfigDir` opens dst with `O_TRUNC`. Previously a partially- - pre-existing dst file would have legacy contents overwrite a prefix - and leave stale tail bytes — silent YAML/token corruption. Refactored - close handling into `copyOneConfigFile`. - -### Security - -- `fj api` endpoint path traversal closed. `fj api '/../admin/users'` - previously normalized through `http.NewRequest` to - `https://host/admin/users` — silently sending authenticated traffic - to non-API paths. Endpoint is now parsed via `url.Parse`, `..` - segments rejected, then `JoinPath` onto the `/api/v1` base. - URL-encoded `%2E%2E` is also caught because Go decodes before our - split. -- `fj api --paginate` validates same-origin before forwarding the - bearer token to a `Link: rel="next"` URL. Refuses to reattach - `Authorization` if the next URL's scheme isn't `https` or its host - doesn't match the configured one. -- `initConfig` warns on stderr if the resolved config file is world or - group readable (`mode & 0o077 != 0`). - ## [0.3.0c] - 2026-03-21 ### Added #### Label Management -- `fj label list` - List repository labels -- `fj label create` - Create a label with color and description -- `fj label edit` - Edit label name, color, or description -- `fj label delete` - Delete a label +- `fgj label list` - List repository labels +- `fgj label create` - Create a label with color and description +- `fgj label edit` - Edit label name, color, or description +- `fgj label delete` - Delete a label #### Milestone Management -- `fj milestone list` - List milestones with state filtering -- `fj milestone view` - View milestone details -- `fj milestone create` - Create a milestone with description and due date -- `fj milestone edit` - Edit milestone title, description, due date, or state -- `fj milestone delete` - Delete a milestone +- `fgj milestone list` - List milestones with state filtering +- `fgj milestone view` - View milestone details +- `fgj milestone create` - Create a milestone with description and due date +- `fgj milestone edit` - Edit milestone title, description, due date, or state +- `fgj milestone delete` - Delete a milestone #### Wiki Management -- `fj wiki list` - List wiki pages -- `fj wiki view` - View wiki page content -- `fj wiki create` - Create a wiki page from flag or file -- `fj wiki edit` - Edit a wiki page -- `fj wiki delete` - Delete a wiki page +- `fgj wiki list` - List wiki pages +- `fgj wiki view` - View wiki page content +- `fgj wiki create` - Create a wiki page from flag or file +- `fgj wiki edit` - Edit a wiki page +- `fgj wiki delete` - Delete a wiki page #### Issue Dependencies -- `fj issue edit --add-dependency ` - Add issue dependency -- `fj issue edit --remove-dependency ` - Remove issue dependency +- `fgj issue edit --add-dependency ` - Add issue dependency +- `fgj issue edit --remove-dependency ` - Remove issue dependency ## [0.3.0b] - 2026-03-21 ### Added #### Repository Management -- `fj repo edit` - Edit repository settings (visibility, description, homepage, default branch) +- `fgj repo edit` - Edit repository settings (visibility, description, homepage, default branch) ### Fixed -- `fj repo create --public` flag was defined but never read; now properly wired up +- `fgj repo create --public` flag was defined but never read; now properly wired up ## [0.3.0a] - 2026-03-21 ### Added #### Raw API Access -- `fj api ` - Make authenticated REST API requests to any Forgejo/Gitea endpoint +- `fgj api ` - Make authenticated REST API requests to any Forgejo/Gitea endpoint - HTTP method selection (`--method`/`-X`), auto-switches to POST when fields are provided - JSON field assembly (`--field`/`-f`) with type inference (bool, int, float, null, string) - Raw string fields (`--raw-field`/`-F`) @@ -159,14 +58,14 @@ this release ships fixes for all 13. - Response header display (`--include`/`-i`) #### Pull Request Management -- `fj pr diff ` - View the diff for a pull request +- `fgj pr diff ` - View the diff for a pull request - Colorized output (`--color auto/always/never`) - Changed file names only (`--name-only`) - Diffstat summary (`--stat`) -- `fj pr comment ` - Add a comment to a pull request +- `fgj pr comment ` - Add a comment to a pull request - Body from flag (`--body`/`-b`) or file (`--body-file`, `-` for stdin) - JSON output (`--json`) -- `fj pr review ` - Submit a review on a pull request +- `fgj pr review ` - Submit a review on a pull request - Approve (`--approve`/`-a`), request changes (`--request-changes`/`-r`), or comment (`--comment`/`-c`) - Body from flag or file - JSON output (`--json`) @@ -182,30 +81,30 @@ this release ships fixes for all 13. ### Added #### Forgejo Actions -- `fj actions run watch ` - Poll a run until completion -- `fj actions run rerun ` - Trigger a rerun of a workflow run -- `fj actions run cancel ` - Cancel an in-progress workflow run -- `fj actions workflow enable ` - Enable a workflow -- `fj actions workflow disable ` - Disable a workflow +- `fgj actions run watch ` - Poll a run until completion +- `fgj actions run rerun ` - Trigger a rerun of a workflow run +- `fgj actions run cancel ` - Cancel an in-progress workflow run +- `fgj actions workflow enable ` - Enable a workflow +- `fgj actions workflow disable ` - Disable a workflow #### Repository Management -- `fj repo create ` - Create a new repository with full option set: `--private`/`--public`, `--description`, `--add-readme`, `--gitignore`, `--license`, `--homepage`, `--clone`, `--team` +- `fgj repo create ` - Create a new repository with full option set: `--private`/`--public`, `--description`, `--add-readme`, `--gitignore`, `--license`, `--homepage`, `--clone`, `--team` #### Issue Management -- `fj issue create -l