Daemon Responder: guide contributors in no-reply repos
Ubiquity OS · 2024 · Auto-reply to common mistakes in designated repositories using pattern-based config and Worker-deployed plugin with tests and CI.
So what?
pattern-based repos response coverage
pattern-based repos response coverage
Problem
Contributors occasionally tried to self-assign or ask questions in no-reply repositories. Maintainers needed an automated way to redirect them to the correct flow.
Approach
- Configuration maps of
owner/repo
,owner
, andrepo
keys → message - Listen to
issue_comment.created
; match in order of specificity - Post the configured guidance comment
- Tests for schema defaults and handler behavior
- CI deploy via Wrangler with pinned version
System diagram
flowchart LR IssueComment[GitHub Issue Comment] --> Router[Kernel Event Router] Router --> Plugin[Daemon-Responder Plugin] Plugin --> Matcher[Config Pattern Matcher] Matcher --> Handler[Auto-Response Handler] Handler --> API[Comment API] API --> Posted[Response Posted]
Outcome
- Common missteps get a helpful automated response
- Maintainers spend less time on repetitive redirection
- Pattern can be extended to other repos quickly
Constraints
- Keep latency low; avoid heavy processing in request cycle
- Store all secrets in CI; do not log sensitive config
Design choices
- Pattern precedence:
owner/repo
→owner
→repo
- TypeBox schema provides defaults for well-known repos
Proof
Code excerpt — auto-response handler
export async function handleAutoResponse(context: Context) {
const { logger, payload: { repository }, config: { automatedResponses }, commentHandler } = context;
const repo = repository.name;
const owner = repository.owner.login;
const autoResponse = automatedResponses[`${owner}/${repo}`] || automatedResponses[owner] || automatedResponses[repo];
if (autoResponse) {
await commentHandler.postComment(context, logger.warn(autoResponse, { owner, repo }));
}
}
Code excerpt — settings schema default
export const pluginSettingsSchema = T.Object({
/** key → message; supports `owner/repo`, `repo`, `owner` */
automatedResponses: T.Record(T.String(), T.String(), {
default: {
"devpool-directory": "This is a no-reply repository, please visit the task using the link in the description.",
},
}),
});
CI evidence — deploy + tests (trimmed)
- name: Deploy with Wrangler
uses: cloudflare/wrangler-action@v3
with:
wranglerVersion: "3.79.0"
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
References
- Issue — #44 - Autoresponder for DevPool Directory
- PR — #1 - daemon-responder v1
- Files — handler, schema, tests, workflows (see PR diff)