Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
106 changes: 106 additions & 0 deletions .github/workflows/auto-response.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
name: Issue Auto Responder

on:
issues:
types: [opened]

permissions:
issues: write
contents: read

jobs:
automove:
name: Move issue to swamp.club lab
runs-on: ubuntu-latest
steps:
- name: Move to lab and close GitHub issue
uses: actions/github-script@v7
env:
SWAMP_CLUB_API_KEY: ${{ secrets.SWAMP_CLUB_API_KEY }}
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const issue = context.payload.issue;
const repo = `${context.repo.owner}/${context.repo.repo}`;

const apiKey = process.env.SWAMP_CLUB_API_KEY;
if (!apiKey) {
core.setFailed("SWAMP_CLUB_API_KEY secret is not set");
return;
}

// Build the lab issue body: original body + auto-move footer.
const originalBody = (issue.body ?? "").trim();
const footer = `Automoved by swampadmin from GitHub issue #${issue.number}`;
const labBody = originalBody.length > 0
? `${originalBody}\n\n---\n${footer}`
: footer;

// Create (or fetch) the issue in the swamp.club lab.
const ensureRes = await fetch(
"https://swamp.club/api/v1/lab/issues/ensure",
{
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${apiKey}`,
},
body: JSON.stringify({
githubRepoFullName: repo,
githubIssueNumber: issue.number,
title: issue.title,
body: labBody,
type: "feature",
githubAuthorLogin: issue.user.login,
}),
signal: AbortSignal.timeout(15_000),
},
);

if (!ensureRes.ok) {
const text = await ensureRes.text().catch(() => "");
core.setFailed(
`swamp.club ensure failed: ${ensureRes.status} ${text}`,
);
return;
}

const data = await ensureRes.json();
// Lab issues use a sequential numeric id (LabIssueData.number) as
// the human-facing identifier — see swamp-club commit 9f12761c.
// The lab UI route and all API paths use /lab/{number} after #369.
// Mirror swamp-club's parseLabIssueNumberParam validator: require
// a safe positive integer.
const labIssueNumber = data?.issue?.number;
if (
typeof labIssueNumber !== "number" ||
!Number.isSafeInteger(labIssueNumber) ||
labIssueNumber <= 0
) {
core.setFailed(
`swamp.club ensure returned no lab issue number: ${
JSON.stringify(data)
}`,
);
return;
}

// We have a confirmed lab issue number — safe to comment and close.
const labUrl = `https://swamp.club/lab/${labIssueNumber}`;

// Post the auto-responder comment linking to the lab issue.
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issue.number,
body:
`Thank you for opening an issue. This issue is now managed in Swamp Club lab.\n\n${labUrl}`,
});

// Close the GitHub issue.
await github.rest.issues.update({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issue.number,
state: "closed",
});
Loading