fix(e2e): scope screenshot posting to named journey (bookshelf-2hoy) #795
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "bd-bookshelf-2hoy"
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
e2e/browser/gated onFORGEJO_TOKEN + PULL_REQUEST_NUMBERonly. Running the full suite withPULL_REQUEST_NUMBERset caused every journey to post to that PR — PR #776 got 38 stray screenshots from unrelated beads.SCREENSHOT_JOURNEYenv var required.e2e/screenshotscope.ShouldPost()requires token + prNum + targetJourney all set AND matching the journey's slug. WhenSCREENSHOT_JOURNEYis unset, nothing posts — the full suite is safe to run withPULL_REQUEST_NUMBERset.shouldPostJourneyScreenshot("slug")via a shared wrapper inscreenshot_scope_test.go.e2e/screenshotscopepackage (no e2e build tag) has 100% unit test coverage and is inUNIT_PKGSformake test+make coverage.Capture pattern (documented in scope.go)
Never run the full suite with only
PULL_REQUEST_NUMBERset.Compatibility with bookshelf-qy9b
bookshelf-qy9b wires
PULL_REQUEST_NUMBERinto the CI browser job. This fix is additive: CI will also need to setSCREENSHOT_JOURNEY=<slug>alongsidePULL_REQUEST_NUMBERfor the specific journey being captured. The two env vars are independent — setting both allows the correct single screenshot to post.Test plan
make testpasses (includese2e/screenshotscopeunit tests)make coveragepasses (100% one2e/screenshotscope, gate is clean)go test -run='^$' -tags e2e ./e2e/browser/compiles without errorgo vet -tags e2e ./e2e/browser/cleanPULL_REQUEST_NUMBERset but noSCREENSHOT_JOURNEY→ no screenshots posted (verified by logic:ShouldPost("any-slug", tok, pr, "") == false)SCREENSHOT_JOURNEY=create-shelf, onlyuploadCreateShelfScreenshotToPRpostsCloses bead bookshelf-2hoy on merge.
Security Review — PR #795 (bookshelf-2hoy)
Branch:
bd-bookshelf-2hoy· HEAD:16d295fbReviewed per
.claude/rules/review-standard.md. Diff scope: newe2e/screenshotscope/package,e2e/browser/screenshot_scope_test.go, 26 test-file one-liners replacing the guard,Makefile+scripts/check-coverage.shpackage-list additions.1. TOKEN HANDLING
FORGEJO_TOKENis read fromos.Getenv("FORGEJO_TOKEN")in two places after this change: in the existing caller function (unchanged) and insidescreenshotscope.ShouldPost(new). InShouldPostthe token is only checked for emptiness (token == ""); it is never logged, never written to a file, never embedded in a string that reaches test output, and not committed anywhere. The actual POST to the Forgejo API still uses thetokenlocal variable in the caller, unchanged. The double-read is harmless.CONFIRMED: token is not logged, not written to a file, not embedded in a fixture, not exposed in test output.
2. NO SECRET COMMITTED
Scanned all new/modified files (
e2e/screenshotscope/scope.go,scope_test.go,suite_test.go,e2e/browser/screenshot_scope_test.go, all 26 updated test helpers,Makefile,scripts/check-coverage.sh). The only new constant isEnvScreenshotJourney = "SCREENSHOT_JOURNEY"— the env var name, not a value. No token, credential, or secret value is hardcoded anywhere in the diff.CONFIRMED: no secret committed.
3. NO NEW NETWORK SURFACE
The change only tightens the gating:
ShouldPostrequires three conditions (token + prNum + targetJourney all non-empty, and targetJourney == slug) vs. the old two (token + prNum). The actual Forgejo API POST call is unchanged and only reached when the guard passes. No new HTTP endpoint is opened; no new outbound destination is introduced.CONFIRMED: strictly narrower network surface than before.
4. MAKEFILE + CHECK-COVERAGE.SH
Both changes append
./e2e/screenshotscope/...to theUNIT_PKGSstring literal. This string is passed as plain positional arguments togo test— noeval, no shell variable expansion of untrusted input, no command substitution. The./e2e/screenshotscope/...glob is resolved by the Go toolchain, not by the shell. No injection vector.CONFIRMED: no shell-injection, no eval of untrusted input.
REVIEW VERDICT: 0 blocker, 0 major, 0 minor
CODE REVIEW: APPROVED
Phase 0: DEMO Verification
No explicit
DEMO:block exists in the bead description or comments. The user dispatcher noted "CI green" and instructed not to re-run tests; CI serves as behavioral verification for this infrastructure fix. Flagged below as MINOR.Phase 1: Spec Compliance — PASS
All requirements from bookshelf-2hoy met:
e2e/screenshotscopepackage withShouldPost(journeySlug, token, prNum, targetJourney)— present ate2e/screenshotscope/scope.go.targetJourney == ""short-circuit inShouldPost.origin/bd-bookshelf-2hoy(26shouldPostJourneyScreenshotcalls, 0 remainingtoken == "" || prNum == ""patterns).scope.gopackage doc andscreenshot_scope_test.goheader comment.ShouldPostonly inspects it for emptiness; posting code remains in the individual helpers.Phase 2: Code Quality — PASS
Core logic (
e2e/screenshotscope/scope.go:50-55)ShouldPostreturns true only when all three oftoken,prNum,targetJourneyare non-empty ANDtargetJourney == journeySlug(exact string match). No prefix/partial match gap. WhenSCREENSHOT_JOURNEYis unset the third condition short-circuits immediately — the full suite is safe to run withPULL_REQUEST_NUMBERset alone.All 26 guards
Every call site uses
shouldPostJourneyScreenshot("<slug>")through the shared wrapper ine2e/browser/screenshot_scope_test.go. Slugs are unique per journey. The tworeader-fit-modeguards injourney_reader_peripherals_test.go:47and:99are intentional — both helpers belong to the same journey, so sharing the slug is correct.Build-tag boundary
e2e/screenshotscope/scope.go— no//go:buildtag (correct: pure decision function, no Chromium/Docker dep, unit-testable).e2e/screenshotscope/scope_test.go/suite_test.go— no//go:buildtag (correct: plain unit tests).e2e/browser/screenshot_scope_test.go—//go:build e2e(correct: lives in the e2e browser package).**Coverage gate (
Makefileline 70,scripts/check-coverage.shline 50)**./e2e/screenshotscope/...is an INCLUSION intoUNIT_PKGS— the new package is now coverage-gated at 100%. This is not an exclusion. BothMakefileandscripts/check-coverage.shupdated in sync. Perno-coverage-exclusions`, this is correct.Branch coverage of
ShouldPostAll branches exercised by
scope_test.go:token == ""→ false: Entry("no token") + Entry("all empty")prNum == ""(token set) → false: Entry("no prNum")targetJourney == ""(token + prNum set) → false: Entry("no targetJourney")targetJourney != journeySlug→ false: four entries (different, prefix, suffix, case)Secret/token safety
Token is received as a parameter and passed only to a boolean comparison (
token == ""). No logging, no serialisation.[MINOR] e2e/screenshotscope — no DEMO block in bead
The bead has no
DEMO:block showing a command + expected output. For future bead authors: add aDEMO: go test -run TestScreenshotScope ./e2e/screenshotscope/with expected pass output so reviewers can reproduce independently. Does not block this PR.REVIEW VERDICT: 0 blocker, 0 major, 1 minor
16d295fbf3b0d4855f33