ci: auto-move new GitHub issues to swamp.club lab#54
Conversation
Adds the same Issue Auto Responder action that systeminit/swamp ships in PR #1134. Every new issue filed against systeminit/swamp-extensions is mirrored to the swamp.club lab via POST /api/v1/lab/issues/ensure, the GitHub issue receives an auto-responder comment linking to the new lab home, and the GitHub issue is closed. The close is gated on a confirmed lab issue number — if the swamp.club call fails or returns a non-safe-integer number, the action fails and the GitHub issue stays open. No failure mode closes a GitHub issue without confirming the lab counterpart exists. Requires the SWAMP_CLUB_API_KEY repo secret to be set with an admin-role swamp.club API key (the /ensure endpoint is still admin-gated; PR systeminit/swamp-club#370 only opened up /issues). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Code Review
Blocking Issues
None.
Suggestions
-
Hardcoded
type: "feature"— all issues (including bug reports) will be created withtype: "feature"in the lab. If the lab's API supports other types (e.g."bug"), you might want to map GitHub labels or leave this as a follow-up. -
Error response body logged to CI —
core.setFailed(swamp.club ensure failed: ${ensureRes.status} ${text})logs the raw response text to the CI log. If the server ever reflects authentication details in error bodies, those would appear in CI output. Low risk (CI logs are restricted), but worth keeping in mind. -
No
label: "closed-moved"on close — The swamp counterpart (systeminit/swamp#1134) may add a label when closing. Not required, but could help distinguish auto-closed issues from organically closed ones.
The sequential gating (POST → validate lab issue number → comment → close) is correctly implemented and matches the stated safety property. Permissions are scoped minimally (issues: write, contents: read). Secret is injected via env var, not hardcoded. Timeout and error handling look solid.
There was a problem hiding this comment.
CI Security Review
Critical / High
None.
Medium
.github/workflows/auto-response.yml:9—contents: readpermission is unnecessary. The workflow never checks out code or reads repo contents; it only interacts with issues and an external API. Removingcontents: readwould tighten the permission set. Not exploitable — the defaultGITHUB_TOKENalready has this permission in public repos.
Low
None.
Verdict
PASS — Clean workflow. Issue data is handled safely via JavaScript objects and JSON.stringify() (no shell interpolation). The labIssueNumber from the external API response is validated as a safe positive integer before use in URL construction. Secrets are passed via environment variables, not string interpolation. The actions/github-script action is GitHub-owned and acceptable with tag pins.
Summary
Adds the same Issue Auto Responder action that
systeminit/swampships in systeminit/swamp#1134. Every new issue filed againstsysteminit/swamp-extensionsis mirrored to the swamp.club lab viaPOST /api/v1/lab/issues/ensure, the GitHub issue receives an auto-responder comment linking to the new lab home, and the GitHub issue is closed.The workflow is byte-identical to swamp's because it derives the repo from
context.repoand posts that to swamp.club'sensureendpoint — the lab will seegithubRepoFullName: "systeminit/swamp-extensions"automatically. No code changes were required to copy it across.Verified compatibility
/ensurevalidatesgithubRepoFullNameagainst^[\w.-]+\/[\w.-]+$(swamp-club/routes/api/v1/lab/issues/ensure.ts:86).systeminit/swamp-extensionsmatches.owner/reposhape is accepted.user.role !== "admin"→ 403). systeminit/swamp-club#370 only opened up/api/v1/lab/issues(the public submission endpoint), not/ensure. So this PR needs an admin-role API key in the secret.Why the close is gated
Same safety property as the swamp action: a GitHub issue must never be closed unless its lab counterpart exists. The flow short-circuits on every error:
/api/v1/lab/issues/ensure. If non-2xx →core.setFailed+return(issue stays open).data.issue.numberis a safe positive integer. If not →core.setFailed+return(issue stays open).Required before merge
SWAMP_CLUB_API_KEYrepo secret with an admin-role swamp.club API key. Reusing the sameswampadminkey that's configured onsysteminit/swampis the cleanest path.Test plan
After merge:
systeminit/swamp-extensions. Expect:https://swamp.club/lab/<n>link.Automoved by swampadmin from GitHub issue #<n>footer.SWAMP_CLUB_API_KEYsecret value (or point at an unreachable host) and file a throwaway issue. Expect:core.setFailedmessage.Related
/api/v1/lab/issues(not used here — the auto-mover uses/ensurefor idempotency and structured GitHub linkage).🤖 Generated with Claude Code