FJ-37: org scope and get for fj actions variables #45

Merged
nrupard merged 2 commits from feat/actions-variables-org-get-FJ-37 into main 2026-06-08 03:32:19 +02:00
Member

What

Extends fj actions variables to organization scope and adds a get subcommand (FJ-37), so org-level CI variables can be listed and verified from the CLI without hitting the REST API or web UI.

  • fj actions variables list --org <ORG> lists org-level actions variables.
  • fj actions variables get [--org <ORG> | -r <OWNER>/<NAME>] <NAME> reads a single variable's value. Plain output prints the value (scriptable); --json emits {name,value,owner_id,repo_id}.
  • create and delete accept --org <ORG> and target the org endpoints.
  • --org is mutually exclusive with --repo/--remote (clear error when combined) and does not require a resolvable repo, so it works outside a git checkout with just --host.
  • A missing organization read scope (HTTP 403) maps to an actionable message pointing at fj auth add-key with read:organization, instead of a bare 403 Forbidden.

How

All endpoints exist in forgejo-api 0.10.0 (/api/v1/orgs/{org}/actions/variables... and the single-variable GETs), so no web-route handling is needed (unlike FJ-36 logs). New thin wrappers live in fj_core::actions (list_org_variables, get_variable, get_org_variable, create_org_variable, update_org_variable, delete_org_variable). The binary resolves a VarScope (Repo vs Org) once per variables invocation and routes each subcommand accordingly; the repo name is resolved lazily so non-org subcommands behave exactly as before.

Verification

Built, clippy (-D warnings), fmt, tests pass in the builder image. Exercised against dev.a8n.run:

  • repo list regression: -r a8n-tools/rusty-links returns [] (the var is org-scoped, the original symptom).
  • repo get nonexistent var: clean not found: variable not found (no panic).
  • --org + -r together: clear mutual-exclusion error.
  • org list/get (incl. --json): return the clear read:organization scope error, since the test token lacks that scope.
  • help text lists get and documents --org on variables and each subcommand.

Note: the org success path and create/delete mutation are not live-verified here because the available token lacks read:organization (and to avoid mutating org state). The 403-mapping path confirms the org requests reach the correct endpoints; a token re-issued with org read scope will exercise the success path.

## What Extends `fj actions variables` to organization scope and adds a `get` subcommand (FJ-37), so org-level CI variables can be listed and verified from the CLI without hitting the REST API or web UI. - `fj actions variables list --org <ORG>` lists org-level actions variables. - `fj actions variables get [--org <ORG> | -r <OWNER>/<NAME>] <NAME>` reads a single variable's value. Plain output prints the value (scriptable); `--json` emits `{name,value,owner_id,repo_id}`. - `create` and `delete` accept `--org <ORG>` and target the org endpoints. - `--org` is mutually exclusive with `--repo`/`--remote` (clear error when combined) and does not require a resolvable repo, so it works outside a git checkout with just `--host`. - A missing organization read scope (HTTP 403) maps to an actionable message pointing at `fj auth add-key` with `read:organization`, instead of a bare `403 Forbidden`. ## How All endpoints exist in forgejo-api 0.10.0 (`/api/v1/orgs/{org}/actions/variables...` and the single-variable GETs), so no web-route handling is needed (unlike FJ-36 logs). New thin wrappers live in `fj_core::actions` (`list_org_variables`, `get_variable`, `get_org_variable`, `create_org_variable`, `update_org_variable`, `delete_org_variable`). The binary resolves a `VarScope` (Repo vs Org) once per `variables` invocation and routes each subcommand accordingly; the repo name is resolved lazily so non-org subcommands behave exactly as before. ## Verification Built, clippy (`-D warnings`), fmt, tests pass in the builder image. Exercised against dev.a8n.run: - repo `list` regression: `-r a8n-tools/rusty-links` returns `[]` (the var is org-scoped, the original symptom). - repo `get` nonexistent var: clean `not found: variable not found` (no panic). - `--org` + `-r` together: clear mutual-exclusion error. - org `list`/`get` (incl. `--json`): return the clear `read:organization` scope error, since the test token lacks that scope. - help text lists `get` and documents `--org` on `variables` and each subcommand. Note: the org success path and `create`/`delete` mutation are not live-verified here because the available token lacks `read:organization` (and to avoid mutating org state). The 403-mapping path confirms the org requests reach the correct endpoints; a token re-issued with org read scope will exercise the success path.
feat(actions): org scope and get for actions variables
All checks were successful
Check / fmt + clippy + build + tests (pull_request) Successful in 37s
a26aad3cc8
`fj actions variables` could only target a repository and had no way to read a single variable's value, so org-level CI variables (e.g. A8N_TOOLS_PRIVATE_PACKAGE_OWNER on a8n-tools) could not be listed or verified from the CLI. This adds a global `--org <ORG>` flag to the `variables` subcommands and a new `get` subcommand.

- `--org <ORG>` targets the org-level endpoints (`/api/v1/orgs/{org}/actions/variables...`) for list/create/delete/get; it is mutually exclusive with `--repo`/`--remote` and errors clearly when combined.
- `get <NAME>` reads a single variable's value for both repo and org scope; plain output prints the value, `--json` emits `{name,value,owner_id,repo_id}`.
- `--org` operations no longer require a resolvable repo, so the repo name is resolved lazily per subcommand instead of up front.
- A missing organization read scope (HTTP 403) is mapped to an actionable message pointing at `fj auth add-key` with `read:organization`, instead of a bare `403 Forbidden`.

All endpoints exist in forgejo-api 0.10.0 (pure /api/v1), so no web-route handling is needed. New thin wrappers live in fj_core::actions; the binary resolves scope via a VarScope enum.

#FJ-37

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
fix(actions): detect 409 conflict and dedup variable JSON
All checks were successful
Check / fmt + clippy + build + tests (pull_request) Successful in 38s
Create release / Create release from merged PR (pull_request) Has been skipped
add026e79d
Review follow-ups on the variables work.

create-variable conflict detection matched only `ApiErrorKind::Other(CONFLICT)`, but forgejo-api 0.10.0's create endpoints do not model 409, so a duplicate surfaces as `UnexpectedStatusCode(409)`. The match never fired, so `create --force` reported a raw 409 instead of updating the existing variable, for both repo and org scope. An `is_conflict` helper now matches both representations.

Also hoists the duplicated `--json` variable view into one shared `VariableJson` (with `From<DisplayActionVariable>`) used by `list` and `get`, so their JSON shapes can't drift, and adds the German strings for the two new `--org` messages.

#FJ-37

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
nrupard deleted branch feat/actions-variables-org-get-FJ-37 2026-06-08 03:32:19 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
pandoras-box/forgejo-cli!45
No description provided.