Skip to content

Support fetching tokens from an external command#469

Open
ammachado wants to merge 5 commits into
psss:mainfrom
ammachado:did-pwmgr
Open

Support fetching tokens from an external command#469
ammachado wants to merge 5 commits into
psss:mainfrom
ammachado:did-pwmgr

Conversation

@ammachado

@ammachado ammachado commented May 15, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Add token_command as a third token source alongside token / token_file, so plugins can pull secrets from password managers such as BitWarden (bw get password did-jira) or 1Password (op read op://Personal/Jira/token). The command is parsed with shlex (no shell) and its stripped stdout is used as the token; failures raise ConfigError. Results are memoized per process via functools.lru_cache so multiple config sections sharing a command only invoke the external tool once.
  • Breaking change: setting more than one of token, token_file, token_command in a section is now a hard ConfigError. Previously the lower-precedence keys were silently ignored.
  • Updated the jira and confluence plugin docstrings to document token_command and the mutual-exclusion rule. Other plugins automatically gain the feature through the shared did.base.get_token helper.
  • Added a CLAUDE.md with repo guidance (Makefile commands, three-layer architecture, plugin conventions, unit vs. FMF tests).

Test plan

  • pytest tests/unit/test_base.py::TestGetToken — 13/13 passing (5 new tests for the command source, mutual exclusion, failure modes, and memoization)
  • Full pytest tests/unit -n auto clean except for pre-existing failures unrelated to token handling (nitrate/psycopg2 build needs pg_config locally; one redmine live-data test)
  • CI runs the full suite with .[all] installed
  • Manual smoke: configure a plugin with token_command = printf %s ... and confirm the report runs

🤖 Generated with Claude Code

Add `token_command` as a third token source alongside `token` and
`token_file`, so secrets can be pulled from password managers such as
BitWarden (`bw get password ...`) or 1Password (`op read op://...`).
The command is parsed with shlex (no shell) and its stdout is used as
the token; failures raise `ConfigError`. Results are memoized per
process so multiple sections sharing a command only invoke the tool
once.

Setting more than one of `token`, `token_file`, `token_command` is now
a hard `ConfigError` (previously the lower-precedence keys were
silently ignored).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@ammachado ammachado marked this pull request as ready for review June 1, 2026 15:46
ammachado and others added 3 commits June 1, 2026 12:42
- Fix terminal color reset sequence (\033[1;m -> \033[0m) so
  background color does not bleed into subsequent output
- Extract the human-readable 'message' field from GitHub API JSON
  error responses instead of printing the raw JSON blob
- Drop the Future object reference from ReportError log lines so
  only the error text is shown

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Mirror the dependency list from the mypy hook so pylint can resolve
all project imports, substituting requests/python-dateutil for their
type-stub equivalents.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Adriano Machado <60320+ammachado@users.noreply.github.com>
Update expected ANSI escape sequences from \033[1;m to \033[0m
following the fix in cbef398.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

rh-pre-commit.version: 2.4.0
rh-pre-commit.check-secrets: ENABLED
@ammachado

Copy link
Copy Markdown
Contributor Author

Note on integration test count updates (tests/github/issues.sh, tests/github/pulls.sh)

@psss, while investigating CI failures in Testing Farm, I found that two items are no longer being returned by the GitHub Search API for the 2022 date range:

  • teemtee/fmf#149 — missing from all "issues created/closed" queries
  • teemtee/try#002 — missing from all "pull requests created" queries

Both items are still visible by direct URL, so they have not been deleted. The root cause is GitHub Search API inconsistency: the index is eventually consistent and does not guarantee that all matching items are returned, especially for older closed issues/PRs. I confirmed the failure also reproduces on main, so this is not a regression introduced by this PR. The same behavior is also observed in PRs #468 and #470.

As a short-term fix I updated the expected counts and dropped the specific rlAssertGrep assertions for the two missing items.

I'd like your advice on how to handle this long-term. A few options I can think of:

  1. Keep exact counts (current approach) — simple to read, but requires manual updates whenever the Search index drifts. Will happen again.
  2. Drop count assertions entirely — only assert that specific known items are present/absent. More resilient to index drift, but loses the sanity check that ensures we're not silently fetching zero results.
  3. Use a lower-bound check — e.g. assert the count is >= N rather than == N. Beakerlib doesn't support this natively but it could be done with a small shell snippet.
  4. Pin the test to a narrower, stable date range where the result set is small enough that index drift is unlikely to drop items.

What is the preferred approach for this project?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant