Commit Graph

16 Commits

Author SHA1 Message Date
benvin 68805a8cde Merge pull request 'Add agentvault with a seed-outpost subcommand' (#7) from benvin/agentvault-seed-outpost into main
ci/woodpecker/tag/release Pipeline was successful
Reviewed-on: #7
v0.3.0
2026-08-29 21:58:01 +10:00
unkin-agent 61bb464e32 Add agentvault with a seed-outpost subcommand
ci/woodpecker/pr/build Pipeline was successful
ci/woodpecker/pr/test Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
Interactive agents are classifier-blocked from plumbing credentials through
a shell, so seeding an Authentik outpost token into Vault KV needs to happen
inside one binary invocation that never exposes the secret.

- Add cmd/agentvault, a fourth CLI sharing the agentpr Vault AppRole login
  (role_id only, VAULT_ADDR/AGENT_APPROLE_ROLE_ID defaults unchanged).
- Add `agentvault seed-outpost`: read the Authentik API token from
  kv/service/authentik/agent-api-token (field `token`, falling back to
  `api_token`), exact-match the outpost by name via the instances search,
  fetch its key from /api/v3/core/tokens/<identifier>/view_key/ and write it
  to --dest-path under --dest-key.
- Print only the outpost name, token identifier, dest path and new KV
  version; keep secret material out of results, errors and logs.
- Distinguish the failure stages (login, KV read denied, outpost missing,
  view_key, KV write denied) with ErrVaultDenied/ErrVaultNotFound/
  ErrOutpostNotFound sentinels and actionable messages.
- Add internal/agent vaultkv.go (AppRole-authenticated KV-v2 client) and
  authentik.go (outpost search + view_key) for reuse by future flows.
- Cover the happy path, idempotent re-run, field fallback and every failure
  mode with httptest servers, including a leak check on error strings.
- Wire agentvault into the Makefile, build-rpm.sh, nfpm contents, release
  cross-builds/assets, README and AGENTS.md.
2026-08-29 21:03:31 +10:00
benvin 60b08f1198 Merge pull request 'watchpr: fix watch mode never detecting changes' (#5) from benvin/watchpr-watchloop-fix into main
ci/woodpecker/tag/release Pipeline was successful
Reviewed-on: #5
v0.2.1
2026-08-15 15:00:01 +10:00
unkin-agent fda3761ead watchpr: fix watch mode hanging when a merged PR's head commit is gone
ci/woodpecker/pr/build Pipeline was successful
ci/woodpecker/pr/test Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
FetchState fetched the PR (merged=true) but then failed the whole state
fetch when CommitStatus 404'd for a head commit that no longer existed
(the branch was deleted after a squash/rebase merge). The merge signal was
discarded, so the watch loop treated every post-merge poll as a transient
error and never exited -- the 37-minute hang seen in production.

- Add a typed APIError carrying the HTTP status so callers can detect a 404
  without parsing error strings.
- FetchState now tolerates a 404 from CommitStatus (commit gone => no CI
  status) and returns the authoritative merged/closed PR state.
- Regression tests: FetchState survives a 404 status; the full watch loop,
  driven through a real client, detects a merge whose head commit is gone
  (both fail/hang before the fix).
2026-08-15 13:23:25 +10:00
benvin 05cc0874d6 Merge pull request 'Add agentws worktree-management binary' (#4) from benvin/agentws into main
ci/woodpecker/tag/release Pipeline was successful
Reviewed-on: #4
v0.2.0
2026-08-15 13:13:06 +10:00
unkin-agent 61e73ada51 agentws: fix golangci-lint findings
ci/woodpecker/pr/build Pipeline was successful
ci/woodpecker/pr/test Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
2026-08-15 12:54:22 +10:00
unkin-agent 6a82b88947 Add agentws worktree-management binary
ci/woodpecker/pr/build Pipeline was successful
ci/woodpecker/pr/test Pipeline failed
ci/woodpecker/pr/pre-commit Pipeline was successful
agentws manages per-branch git worktrees for the unkin-agent user: it clones
repos into the source root (~/src/prodenv/<repo>) so branches are visible in
Ben's main checkout, and creates isolated worktrees under the worktree root
(~/.cache/agentws/<repo>__<branch>).

- New internal/agent/git.go: small, testable git helpers shelling out to the
  git binary (clone/fetch/worktree add/remove/list/prune, branch + config ops,
  porcelain parsing, path sanitizing). No go-git dependency.
- New cmd/agentws: new / list / rm / clean / token / credential subcommands.
  Auth uses an ephemeral git credential helper (agentws credential get) so the
  ~1h Gitea token is never persisted in a remote URL or config; per-worktree
  config keeps the shared checkout's identity untouched.
- Wire agentws into Makefile, scripts/build-rpm.sh, packaging/nfpm.yaml (binary
  + bash/zsh/fish completions), .woodpecker/release.yaml (cross-compile + assets)
  and .gitignore.
- Tests: table tests for parsing/sanitizing/dir-naming, a real temp-git repo for
  the worktree lifecycle, and hermetic cmd tests (bad input + credential-helper
  host guard) that never touch the network.
- Document agentws in README.md and AGENTS.md.
2026-08-15 12:21:08 +10:00
benvin c6712063bc Merge pull request 'watchpr: detect merge/close in poll loop (was hanging after baseline)' (#3) from benvin/watchpr-poll-loop-fix into main
ci/woodpecker/tag/release Pipeline was successful
Reviewed-on: #3
v0.1.2
2026-08-12 23:40:50 +10:00
unkin-agent f915b5ba3b watchpr: detect merge/close in poll loop (was hanging after baseline)
ci/woodpecker/pr/build Pipeline was successful
ci/woodpecker/pr/test Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
watchpr only reported meaningful changes as transitions from the poll
baseline. A PR already merged or closed when the watch started was
captured as the baseline and never produced a transition, so the loop
polled the dead PR forever (process alive, never exiting) -- the
single-PR --interval case observed in production.

Add a terminal-state check applied to the baseline snapshot: a PR that
is already merged or closed the moment watchpr starts is reported and
exits immediately, since it can never change again. Extract the
baseline+poll loop into agent.Watch behind a StateFetcher interface so
the loop, its open->merged/close detection, and its poll-error
resilience are unit-testable with a fake client.
2026-08-12 23:32:28 +10:00
benvin 7d9ae0fcc6 Merge pull request 'Fix non-zero exit on error and debounce transient mergeable=false' (#2) from benvin/followup-fixes into main
ci/woodpecker/tag/release Pipeline was successful
Reviewed-on: #2
v0.1.1
2026-08-12 22:22:58 +10:00
unkin-agent 05594113a2 Fix non-zero exit on error and debounce transient mergeable=false
ci/woodpecker/pr/build Pipeline was successful
ci/woodpecker/pr/test Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
agentpr/watchpr already propagated command errors to a non-zero exit, but
that behaviour had no regression coverage and the root command was not
constructible outside main(). watchpr also fired a spurious conflict alert
because Gitea computes mergeability asynchronously and can briefly report
mergeable=false right after a push. The docs additionally printed the
AppRole role_id literal UUID.

- Extract newRootCmd() in both cmd/agentpr and cmd/watchpr so main() only
  runs Execute and exits non-zero on error; add tests asserting Execute
  returns an error for a bad PR ref / malformed --repo / no args.
- Debounce mergeability loss in MeaningfulChange: only alert when
  mergeable=false persists across two consecutive polls (both prev and cur
  false, still open); update the table test for one-poll-false (benign),
  false-persisting (alert), and recovered false->true (benign).
- Refer to AGENT_APPROLE_ROLE_ID by env var in README.md/AGENTS.md without
  printing the literal role_id; keep the code default and env override.
2026-08-12 22:17:10 +10:00
benvin 3f03e0d84f Merge pull request 'Add agentpr and watchpr CLI tools' (#1) from benvin/init into main
ci/woodpecker/tag/release Pipeline was successful
Reviewed-on: #1
v0.1.0
2026-08-12 21:51:27 +10:00
unkin-agent 8403741902 lint: check deferred resp.Body.Close error returns
ci/woodpecker/pr/build Pipeline was successful
ci/woodpecker/pr/test Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
golangci-lint v2 (errcheck) flagged three unchecked resp.Body.Close()
returns in gitea.go and vault.go. Wrap each deferred Close in a closure
discarding the return, the idiomatic form for a deferred Close whose
error is intentionally ignored.
2026-08-12 21:46:40 +10:00
unkin-agent fa8ccac0dd ci: pin go 1.25.7 and use module-level go vet
ci/woodpecker/pr/build Pipeline was successful
ci/woodpecker/pr/test Pipeline failed
ci/woodpecker/pr/pre-commit Pipeline was successful
- go.mod: go 1.26.5 -> 1.25.7 to match the golang:1.25 CI image (node-lookup convention)
- .pre-commit-config: dnephin go-vet runs at repo root (no .go files here since both
  tools live under cmd/); replace with a local 'go vet ./...' hook (CI pre-commit
  image has go)
2026-08-12 21:41:34 +10:00
unkin-agent d78644d173 Add agentpr and watchpr CLI tools
ci/woodpecker/pr/build Pipeline failed
ci/woodpecker/pr/test Pipeline failed
ci/woodpecker/pr/pre-commit Pipeline failed
agentpr manages PRs/comments/whoami as unkin-agent (Vault AppRole -> gitea creds
-> Gitea API), fixing tea's post-as-Ben default. watchpr polls PRs and alerts
only on merge/close, human comment, CI failure, or lost mergeability.

- cobra multi-binary layout mirroring node-lookup (cmd/ + internal/)
- Makefile (build, patch|minor|major, completions, rpm), nfpm RPM with both
  binaries + bash/zsh/fish completions, woodpecker CI publishing to rpm-internal
- unit tests for parsing, meaningful-change detection, and the Vault+Gitea client
2026-08-12 21:37:09 +10:00
gitadmin 1c42974b74 Initial commit 2026-08-12 21:33:07 +10:00