fj secret/variable --org scope for shared CI credentials #137

Closed
opened 2026-06-11 00:57:41 +00:00 by stephen · 0 comments
Owner

Task

Add an org (and optionally user) scope to fj secret and fj variable:

  • Add a mutually-exclusive scope selector --org <name> (consider --user for user-level secrets, which Forgejo also supports). Default remains repo scope inferred from the remote.
  • Route the four verbs (list/set/delete, for both secrets and variables) to /orgs/{org}/actions/secrets and /orgs/{org}/actions/variables when --org is set; request/response shapes match the repo endpoints already implemented in src/api/workflow_secrets.rs.

Source: rasterstate/fj#127.

Priority

p3. Org-level secrets are how teams avoid copy-pasting the same REGISTRY_TOKEN/DEPLOY_KEY into many repos, so this is real provisioning value, but the audience is narrower (org admins, one-time setup) than the per-run scripting primitives, and the fj api -X PUT /orgs/.../actions/secrets/... escape hatch works today.

Reason

Every secret/variable call is hard-wired to the repo path: list_secrets/set_secret/list_variables/set_variable/delete_variable all build crate::api::repo_path(owner, name) + /actions/... (src/api/workflow_secrets.rs). The CLI args carry only RepoFlag with no scope selector (src/cli/workflow_secret.rs:29-61), and var/secret share those args via workflow_variable.rs. Forgejo exposes the org surface at the mirror paths, so the gap is purely on the fj side; no new verbs, no new auth, rendering unchanged.

Acceptance

  • fj secret list/set/delete --org <name> and fj variable list/set/delete --org <name> target /orgs/{org}/actions/....
  • --org is mutually exclusive with repo scope; default stays repo scope inferred from the remote.
  • (Optional) --user scope for user-level secrets/variables.
  • Table and JSON rendering unchanged across scopes.
  • Wiremock coverage in src/client/integration_tests.rs for the org-scoped paths.
  • cargo fmt --check, cargo clippy --all-targets --all-features -- -D warnings, and cargo test --all pass.

Dependencies

None. The hand-rolled fj api workaround for this also re-exposes the stdin gap in rasterstate/fj#126.

Size

M

## Task Add an org (and optionally user) scope to `fj secret` and `fj variable`: - Add a mutually-exclusive scope selector `--org <name>` (consider `--user` for user-level secrets, which Forgejo also supports). Default remains repo scope inferred from the remote. - Route the four verbs (list/set/delete, for both secrets and variables) to `/orgs/{org}/actions/secrets` and `/orgs/{org}/actions/variables` when `--org` is set; request/response shapes match the repo endpoints already implemented in `src/api/workflow_secrets.rs`. Source: rasterstate/fj#127. ## Priority p3. Org-level secrets are how teams avoid copy-pasting the same `REGISTRY_TOKEN`/`DEPLOY_KEY` into many repos, so this is real provisioning value, but the audience is narrower (org admins, one-time setup) than the per-run scripting primitives, and the `fj api -X PUT /orgs/.../actions/secrets/...` escape hatch works today. ## Reason Every secret/variable call is hard-wired to the repo path: `list_secrets`/`set_secret`/`list_variables`/`set_variable`/`delete_variable` all build `crate::api::repo_path(owner, name)` + `/actions/...` (`src/api/workflow_secrets.rs`). The CLI args carry only `RepoFlag` with no scope selector (`src/cli/workflow_secret.rs:29-61`), and `var`/`secret` share those args via `workflow_variable.rs`. Forgejo exposes the org surface at the mirror paths, so the gap is purely on the fj side; no new verbs, no new auth, rendering unchanged. ## Acceptance - [ ] `fj secret list/set/delete --org <name>` and `fj variable list/set/delete --org <name>` target `/orgs/{org}/actions/...`. - [ ] `--org` is mutually exclusive with repo scope; default stays repo scope inferred from the remote. - [ ] (Optional) `--user` scope for user-level secrets/variables. - [ ] Table and JSON rendering unchanged across scopes. - [ ] Wiremock coverage in `src/client/integration_tests.rs` for the org-scoped paths. - [ ] `cargo fmt --check`, `cargo clippy --all-targets --all-features -- -D warnings`, and `cargo test --all` pass. ## Dependencies None. The hand-rolled `fj api` workaround for this also re-exposes the stdin gap in rasterstate/fj#126. ## Size M
Sign in to join this conversation.
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
rasterstate/fj#137
No description provided.