Skip to content

feat(env): register GITHUB_TOKEN for .env and keychain end-to-end support#793

Open
23241a6749 wants to merge 2 commits into
mvanhorn:mainfrom
23241a6749:feat/github-token-env-keychain
Open

feat(env): register GITHUB_TOKEN for .env and keychain end-to-end support#793
23241a6749 wants to merge 2 commits into
mvanhorn:mainfrom
23241a6749:feat/github-token-env-keychain

Conversation

@23241a6749

Copy link
Copy Markdown
Contributor

Problem

GITHUB_TOKEN is missing from env.py's keys tuple and KEYCHAIN_KEYS. Users who set GITHUB_TOKEN in their .env file find it silently ignored — config.get("GITHUB_TOKEN") always returns None because unregistered keys are never loaded from .env into the config dict.

This was partially addressed by:

The maintainer's feedback on PR #724:

"What your PR is really pointing at, first-class GITHUB_TOKEN support via .env and keychain end-to-end, is a feature I'd take. If you want it, file the issue and it's yours; your setup-script additions would carry straight over."

Changes

  1. env.py: Added "GITHUB_TOKEN" to both:

    • KEYCHAIN_KEYS tuple — enables macOS Keychain / pass(1) store support
    • get_config keys tuple — so .env values are loaded into config
  2. setup-keychain.sh: Added GITHUB_TOKEN to ALL_KEYS array

  3. setup-pass.sh: Added GITHUB_TOKEN to ALL_KEYS array

Why this is sufficient

lib/github.py's _resolve_token already checks the token argument first before falling back to os.environ and gh auth token. pipeline.py already passes config.get("GITHUB_TOKEN") as that argument. Once the key is registered, config.get("GITHUB_TOKEN") returns the .env value, and it flows through to the GitHub API client end-to-end.

Both doctor.py and pipeline.py also use config.get("GITHUB_TOKEN") for the has_github check — they'll now accurately reflect .env-configured tokens.

Verification

All 77 tests pass across keychain, pass, env-doc-contract, doctor, and no-bare-open-read test suites.

…port

GITHUB_TOKEN was missing from env.py's CONFIGURATION_KEYS and
KEYCHAIN_KEYS, so .env and keychain-stored tokens were silently
ignored. Pipeline.py already passes config.get(GITHUB_TOKEN) to
github._resolve_token, so registration alone completes the end-to-end.

Closes mvanhorn#792
References mvanhorn#724 (closed), mvanhorn#782 (merged)
@greptile-apps

greptile-apps Bot commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR registers GITHUB_TOKEN as a first-class credential in env.py (KEYCHAIN_KEYS tuple and get_config keys list), mirrors the addition in both setup-keychain.sh and setup-pass.sh, and updates doctor.py's _github_record to prefer config.get("GITHUB_TOKEN") so .env- and keychain-sourced tokens are reflected in the diagnostics output.

  • env.py: GITHUB_TOKEN is appended to KEYCHAIN_KEYS and to the keys list in get_config, so tokens stored via .env, macOS Keychain, or pass(1) are loaded into the config dict and flow downstream to pipeline.py.
  • doctor.py: _github_record now checks config.get(\"GITHUB_TOKEN\") first, fixing the previously-reported gap where a .env-sourced token was invisible to the auth-tier display.
  • setup-keychain.sh / setup-pass.sh: GITHUB_TOKEN is added to ALL_KEYS to keep the setup helpers in sync with KEYCHAIN_KEYS (enforced by the env-doc-contract test suite).

Confidence Score: 5/5

Safe to merge — changes are additive registrations with no behavioral side-effects on existing code paths.

All four changes are purely additive: appending a string to a tuple/array and a key-default pair to a list. The doctor.py update correctly promotes config.get() as the primary check. No existing behavior is altered, no migration or data-path change is introduced, and the PR description confirms all 77 tests pass.

No files require special attention.

Important Files Changed

Filename Overview
skills/last30days/scripts/lib/env.py Adds GITHUB_TOKEN to KEYCHAIN_KEYS tuple and to the get_config keys list; straightforward registration with no logic changes.
skills/last30days/scripts/lib/doctor.py _github_record now checks config.get("GITHUB_TOKEN") first; the redundant env.read_secret_env fallback is fully covered by config already.
skills/last30days/scripts/setup-keychain.sh GITHUB_TOKEN appended to ALL_KEYS array to keep keychain setup script in sync with KEYCHAIN_KEYS.
skills/last30days/scripts/setup-pass.sh GITHUB_TOKEN appended to ALL_KEYS array to keep pass(1) setup script in sync with KEYCHAIN_KEYS.

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
    participant User as User (.env / Keychain / pass)
    participant getConfig as env.get_config()
    participant config as config dict
    participant pipeline as pipeline.py
    participant github as lib/github.py _resolve_token()
    participant doctor as doctor.py _github_record()

    User->>getConfig: GITHUB_TOKEN in .env / Keychain / pass
    getConfig->>config: "config[GITHUB_TOKEN] = os.environ OR merged_env value"
    config->>pipeline: config.get(GITHUB_TOKEN)
    pipeline->>github: "_resolve_token(token=config.get(GITHUB_TOKEN))"
    github-->>pipeline: resolved token (API calls authenticated)

    config->>doctor: config.get(GITHUB_TOKEN)
    doctor-->>doctor: "authed = True, authenticated tier"
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
    participant User as User (.env / Keychain / pass)
    participant getConfig as env.get_config()
    participant config as config dict
    participant pipeline as pipeline.py
    participant github as lib/github.py _resolve_token()
    participant doctor as doctor.py _github_record()

    User->>getConfig: GITHUB_TOKEN in .env / Keychain / pass
    getConfig->>config: "config[GITHUB_TOKEN] = os.environ OR merged_env value"
    config->>pipeline: config.get(GITHUB_TOKEN)
    pipeline->>github: "_resolve_token(token=config.get(GITHUB_TOKEN))"
    github-->>pipeline: resolved token (API calls authenticated)

    config->>doctor: config.get(GITHUB_TOKEN)
    doctor-->>doctor: "authed = True, authenticated tier"
Loading

Reviews (2): Last reviewed commit: "fix(doc): make _github_record read confi..." | Re-trigger Greptile

Comment thread skills/last30days/scripts/lib/env.py
…N shows in doctor

_github_record now checks config.get("GITHUB_TOKEN") first (covering
.env and keychain sources), falling back to os.environ (for process-env-only
cases), before trying gh CLI. This mirrors _resolve_token's same two-source
pattern and ensures doctor's auth display matches real token availability.
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