Add local staging environment for PR testing #32
Reference in New Issue
Block a user
Delete Branch "staging-setup"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Local staging environment on code-server for testing PRs before merge. Enables:
./test-pr.sh <pr-number>Changes
Infrastructure
NANOBOT_CONFIGenvironment variable support — specify custom config file pathapi_keyfromoauthCredentials.access_tokenstructuretest-pr.shhelper script — automate PR checkout, install, and testStaging Setup
/config/workspace/.nanobot-staging/{workspace}/sessions/)Testing
All components tested:
Usage
Files Changed
nanobot/config/loader.py— NANOBOT_CONFIG support + OAuth migrationtest-pr.sh— PR testing automation script🤖 Generated via staging environment implementation plan
PR Review: Add local staging environment for PR testing
Overview
Clean, focused PR with three logical changes:
NANOBOT_CONFIGenv var for custom config path_migrate_configtest-pr.shhelper scriptFindings
1.
NANOBOT_CONFIGenv var support — looks goodThe implementation is clean and minimal. Both
load_configandsave_configuseget_config_path()so they stay consistent. One note:_get_oauth_store_dir()still hardcodesPath.home() / ".nanobot"regardless ofNANOBOT_CONFIG. This means OAuth creds are always read from~/.nanobot/even with a custom config path. The PR description says "shared OAuth with production" so this seems intentional, but it's an implicit coupling worth being aware of.2. OAuth credentials migration — functional, but has a gap
The migration extracts
access_tokenfromoauthCredentialsintoapi_key, but leaves theoauthCredentialsdict in place. After migration, the token exists in two locations in the config dict. Consider cleaning up the source:Also,
provider_nameis unused in the loop — should be_per convention.3.
test-pr.sh— works but has rough edgesgit fetch wylab "pull/$PR_NUM/head:pr-$PR_NUM"will fail ifpr-$PR_NUMalready exists from a previous test. Addgit branch -D "pr-$PR_NUM" 2>/dev/nullbefore fetch, or use+refspec (+pull/$PR_NUM/head:pr-$PR_NUM)/config/workspace/...— not portable, but clearly a dev-only tool4. No tests added
Neither the env var support nor the migration logic have test coverage.
_migrate_confighas zero test coverage in the existing test suite. At minimum:get_config_path()with/withoutNANOBOT_CONFIGset_migrate_configwithoauthCredentialspresent/absent/already-migratedSummary
Recommendation: Mergeable as-is for a dev tooling PR, but the branch collision in
test-pr.shwill bite on second use. The missing tests are a risk for the migration logic inloader.py.🤖 Review by Claude Code
PR Review (Round 2): Post-feedback assessment
The previous review identified 4 issues. All have been addressed in follow-up commits:
oauthCredentialsleft after migration153b08f—del provider_config["oauthCredentials"]provider_nameunused variable153b08f— changed to_test-pr.sh1b920d7—+refspec for force-updatea3fe901— 7 tests addedRemaining Findings
1. Edge case in migration:
oauthCredentialspersists whenapi_keyalready setWhen both
api_keyandoauthCredentialsexist (the "already migrated" case),oauthCredentialsis intentionally kept (line 104: migration only fires whenapi_keyis absent). This means staleoauthCredentialsdata lingers in the config dict.If the Pydantic schema ever switches to
extra='forbid', this leftover field would cause a validation error. Currently harmless, but worth noting. Consider always cleaning upoauthCredentialsregardless:Severity: Low — current schema allows extra fields.
2. Test env var isolation uses manual try/finally instead of
monkeypatchTests manipulate
os.environdirectly with try/finally cleanup. Using pytest'smonkeypatchfixture would be more idiomatic and automatically cleaned up:Severity: Minor — current approach works, just less idiomatic.
3.
save_configwrites migrated-away fields backsave_configcallsconfig.model_dump(by_alias=True)which serializes the Pydantic model — this is fine. But if a config was loaded (triggering migration), then saved, theoauthCredentialsfield is gone from the on-disk config permanently. This is the correct behavior (migration is intentionally one-way), but worth being explicit that running nanobot withNANOBOT_CONFIGpointing to a production config will permanently modify it on save. The staging setup avoids this by using a separate config file.Severity: Informational — by design, just worth documenting.
Verified
NANOBOT_CONFIGrespected by bothload_configandsave_configvia sharedget_config_path()_get_oauth_store_dir()intentionally hardcoded to~/.nanobot— staging shares production OAuth credstest-pr.sh+refspec handles re-runs correctlyoauthCredentialsafter extractionapi_keywhen already set (no overwrite)Verdict
Ready to merge. All review feedback addressed. Remaining items are minor/informational and don't block.
🤖 Review by Claude Code
Pull request closed