Skip to content

Commit 0964f11

Browse files
authored
Add agentic workflows for community catalog submissions (#2655)
* Add agentic workflows for community catalog submissions Add GitHub Agentic Workflows that automatically process community extension and preset submission issues: - add-community-extension.md: triggered by extension-submission issues, validates the submission, updates extensions/catalog.community.json and docs/community/extensions.md, then opens a draft PR - add-community-preset.md: parallel workflow for preset-submission issues, updates presets/catalog.community.json and docs/community/presets.md Both workflows: - Trigger on opened, edited, or labeled events (maintainers can retroactively label pre-existing issues) - Validate ID format, semver, repo existence, required files, release, and submission checklists - Label issues with validation-passed or validation-failed - Create draft PRs with Closes #N for maintainer review Also includes gh-aw scaffolding (.github/aw/, .gitattributes lock file rule, dependabot ignore for gh-aw-actions). * Suppress whitespace checks on generated .lock.yml files These files are auto-generated by gh aw compile and contain trailing whitespace in the ASCII art header and indented YAML blocks that we cannot control. Add -whitespace attribute to skip git whitespace checks on them.
1 parent b4b83be commit 0964f11

7 files changed

Lines changed: 3755 additions & 10 deletions

.gitattributes

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
11
* text=auto eol=lf
2+
3+
.github/workflows/*.lock.yml linguist-generated=true merge=ours -whitespace

.github/aw/actions-lock.json

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"entries": {
3+
"actions/github-script@v9.0.0": {
4+
"repo": "actions/github-script",
5+
"version": "v9.0.0",
6+
"sha": "3a2844b7e9c422d3c10d287c895573f7108da1b3"
7+
},
8+
"github/gh-aw-actions/setup@v0.74.8": {
9+
"repo": "github/gh-aw-actions/setup",
10+
"version": "v0.74.8",
11+
"sha": "efa55847f72aadb03490d955263ff911bf758700"
12+
}
13+
}
14+
}

.github/dependabot.yml

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
1-
version: 2
21
updates:
3-
- package-ecosystem: "pip"
4-
directory: "/"
5-
schedule:
6-
interval: "weekly"
7-
8-
- package-ecosystem: "github-actions"
9-
directory: "/"
10-
schedule:
11-
interval: "weekly"
2+
- directory: /
3+
package-ecosystem: pip
4+
schedule:
5+
interval: weekly
6+
- directory: /
7+
ignore:
8+
- dependency-name: "github/gh-aw-actions/**" # Managed by gh aw compile. Version-locked to the gh-aw compiler; do not bump.
9+
package-ecosystem: github-actions
10+
schedule:
11+
interval: weekly
12+
version: 2

.github/workflows/add-community-extension.lock.yml

Lines changed: 1579 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 288 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,288 @@
1+
---
2+
description: "Process community extension submission issues — validate, add to catalog, and open a PR for maintainer review"
3+
emoji: "🧩"
4+
5+
on:
6+
issues:
7+
types: [opened, edited, labeled]
8+
skip-bots: [github-actions, copilot, dependabot]
9+
10+
tools:
11+
edit:
12+
bash: ["echo", "cat", "head", "tail", "grep", "wc", "sort", "python3", "jq", "date"]
13+
github:
14+
toolsets: [issues, repos]
15+
web-fetch:
16+
17+
permissions:
18+
contents: read
19+
issues: read
20+
21+
checkout:
22+
fetch-depth: 0
23+
24+
safe-outputs:
25+
create-pull-request:
26+
title-prefix: "[extension] "
27+
labels: [extension-submission, automated]
28+
draft: true
29+
max: 1
30+
protected-files:
31+
policy: blocked
32+
exclude:
33+
- README.md
34+
- CHANGELOG.md
35+
add-comment:
36+
max: 2
37+
add-labels:
38+
allowed: [extension-submission, validation-passed, validation-failed, needs-info]
39+
max: 3
40+
---
41+
42+
# Add Community Extension from Issue Submission
43+
44+
You are a catalog maintenance agent for the Spec Kit project. Your job is to
45+
process community extension submission issues and create pull requests that add
46+
or update entries in the community extension catalog.
47+
48+
## Triggering Conditions
49+
50+
This workflow triggers on issue events. **Only process the issue if ALL of these
51+
conditions are met:**
52+
53+
1. The issue has the `extension-submission` label
54+
2. The issue title starts with `[Extension]:`
55+
56+
If the issue does not meet these conditions, add a brief comment explaining that
57+
this workflow only processes extension submission issues, then stop.
58+
59+
## Step 1 — Read and Parse the Issue
60+
61+
Read issue #${{ github.event.issue.number }}.
62+
63+
Extract the following fields from the structured issue body (GitHub issue form
64+
fields):
65+
66+
| Field | Issue Form ID | Required |
67+
|-------|--------------|----------|
68+
| Extension ID | `extension-id` | Yes |
69+
| Extension Name | `extension-name` | Yes |
70+
| Version | `version` | Yes |
71+
| Description | `description` | Yes |
72+
| Author | `author` | Yes |
73+
| Repository URL | `repository` | Yes |
74+
| Download URL | `download-url` | Yes |
75+
| License | `license` | Yes |
76+
| Homepage | `homepage` | No |
77+
| Documentation URL | `documentation` | No |
78+
| Changelog URL | `changelog` | No |
79+
| Required Spec Kit Version | `speckit-version` | Yes |
80+
| Required Tools | `required-tools` | No |
81+
| Number of Commands | `commands-count` | Yes |
82+
| Number of Hooks | `hooks-count` | No (default 0) |
83+
| Tags | `tags` | Yes |
84+
| Proposed Catalog Entry | `catalog-entry` | Yes |
85+
86+
The issue body uses GitHub's issue form format. Each field appears under a
87+
heading matching the field label (e.g., `### Extension ID` followed by the
88+
value). Parse accordingly.
89+
90+
## Step 2 — Validate the Submission
91+
92+
Run **all** of the following validation checks. Collect all results before
93+
deciding pass/fail:
94+
95+
### 2a. Extension ID format
96+
- Must match regex: `^[a-z][a-z0-9-]*$`
97+
- Must be lowercase with hyphens only
98+
99+
### 2b. Version format
100+
- Must follow semver: `X.Y.Z` (digits only, no `v` prefix)
101+
102+
### 2c. Repository validation
103+
- Fetch the repository URL — confirm it exists and is publicly accessible
104+
- Confirm the repository contains an `extension.yml` file
105+
- Confirm the repository contains a `README.md` file
106+
- Confirm the repository contains a `LICENSE` file
107+
108+
### 2d. Release and download URL validation
109+
- The download URL should follow the pattern
110+
`https://github.com/<owner>/<repo>/archive/refs/tags/v<version>.zip`
111+
or
112+
`https://github.com/<owner>/<repo>/releases/download/<tag>/<asset>.zip`
113+
- Verify a GitHub release exists matching the submitted version
114+
115+
### 2e. Submission checklists
116+
- Confirm that all required checkboxes in the Testing Checklist and Submission
117+
Requirements sections are checked (`[x]`)
118+
119+
### Validation outcome
120+
121+
If **any** validation fails:
122+
1. Add a comment on the issue listing each failed check with a clear explanation
123+
of what's wrong and how to fix it
124+
2. Add the `validation-failed` label
125+
3. **Stop — do not proceed further**
126+
127+
If all validations pass:
128+
1. Add the `validation-passed` label
129+
2. Continue to Step 3
130+
131+
## Step 3 — Determine Add vs Update
132+
133+
Search `extensions/catalog.community.json` for the extension ID.
134+
135+
- **Not found** → this is a **new addition**
136+
- **Found** → this is an **update** — replace the existing entry in-place;
137+
preserve `created_at`, `downloads`, and `stars` from the existing entry
138+
139+
## Step 4 — Update `extensions/catalog.community.json`
140+
141+
Edit `extensions/catalog.community.json` to add or update the extension entry.
142+
143+
### For a new extension
144+
145+
Insert the entry in **alphabetical order by extension ID** within the
146+
`"extensions"` object. Use this structure:
147+
148+
```json
149+
{
150+
"<id>": {
151+
"name": "<name>",
152+
"id": "<id>",
153+
"description": "<description>",
154+
"author": "<author>",
155+
"version": "<version>",
156+
"download_url": "<download_url>",
157+
"repository": "<repository>",
158+
"homepage": "<homepage or repository>",
159+
"documentation": "<documentation or repository README>",
160+
"changelog": "<changelog or empty string>",
161+
"license": "<license>",
162+
"requires": {
163+
"speckit_version": "<speckit_version>"
164+
},
165+
"provides": {
166+
"commands": <N>,
167+
"hooks": <N>
168+
},
169+
"tags": ["<tag1>", "<tag2>"],
170+
"verified": false,
171+
"downloads": 0,
172+
"stars": 0,
173+
"created_at": "<today>T00:00:00Z",
174+
"updated_at": "<today>T00:00:00Z"
175+
}
176+
}
177+
```
178+
179+
If the extension has optional tool dependencies, add a `"tools"` array inside
180+
`"requires"`:
181+
182+
```json
183+
"tools": [{ "name": "<tool>", "required": false }]
184+
```
185+
186+
### For an update
187+
188+
Replace only the changed fields (typically `version`, `download_url`,
189+
`description`, `provides`, `requires`, `tags`, `updated_at`). **Preserve**
190+
`created_at`, `downloads`, and `stars` from the existing entry.
191+
192+
### After editing
193+
194+
Update the **top-level `"updated_at"` timestamp** in the catalog to today's date
195+
in ISO 8601 format.
196+
197+
Validate the JSON by running:
198+
199+
```bash
200+
python3 -c "import json; json.load(open('extensions/catalog.community.json')); print('Valid JSON')"
201+
```
202+
203+
If validation fails, fix the JSON and re-validate before continuing.
204+
205+
## Step 5 — Update `docs/community/extensions.md`
206+
207+
Edit `docs/community/extensions.md` to add or update a row in the Community
208+
Extensions table.
209+
210+
### For a new extension
211+
212+
Insert a new row in **alphabetical order by extension name**:
213+
214+
```
215+
| <Name> | <Description> | `<category>` | <Effect> | [<repo-name>](<repository-url>) |
216+
```
217+
218+
Determine the category from the extension's behavior:
219+
- `docs` — reads, validates, or generates spec artifacts
220+
- `code` — reviews, validates, or modifies source code
221+
- `process` — orchestrates workflow across phases
222+
- `integration` — syncs with external platforms
223+
- `visibility` — reports on project health or progress
224+
225+
Determine the effect:
226+
- `Read-only` — produces reports only
227+
- `Read+Write` — modifies project files
228+
229+
### For an update
230+
231+
Find the existing row and update any changed fields in-place.
232+
233+
## Step 6 — Create Pull Request
234+
235+
Create a pull request with the changes. Use this branch naming convention:
236+
237+
- **New extension:** `add-<extension-id>-extension`
238+
- **Update:** `update-<extension-id>-extension`
239+
240+
### Commit message
241+
242+
For a new extension:
243+
```
244+
Add <Name> extension to community catalog
245+
246+
Add <id> extension submitted by @<issue-author> to:
247+
- extensions/catalog.community.json (alphabetical order)
248+
- docs/community/extensions.md community extensions table
249+
250+
Closes #<issue-number>
251+
```
252+
253+
For an update:
254+
```
255+
Update <Name> extension to v<version>
256+
257+
Update <id> extension submitted by @<issue-author>:
258+
- extensions/catalog.community.json (version, download_url, etc.)
259+
- docs/community/extensions.md community extensions table
260+
261+
Closes #<issue-number>
262+
```
263+
264+
### PR description
265+
266+
Include:
267+
- A summary of what changed
268+
- Validation results (all checks passed)
269+
- `Closes #${{ github.event.issue.number }}`
270+
- `cc @<issue-author>` — mention the submitter
271+
272+
## Important Rules
273+
274+
- **Alphabetical order matters** — entries must be sorted by ID in the JSON and
275+
by name in the docs table
276+
- **Always validate JSON** after editing — a trailing comma or missing brace
277+
will break the catalog
278+
- **Use `Closes` not `Fixes`**`Closes #N` is the correct keyword for
279+
submission issues
280+
- **Match the proposed entry but verify** — the issue may include a proposed
281+
JSON block, but always validate field values against the actual repository
282+
state rather than blindly trusting the submitter's JSON
283+
- **Preserve `created_at` on updates** — keep the original value; only update
284+
`updated_at`
285+
- **Preserve `downloads` and `stars` on updates** — these reflect usage metrics
286+
and must not be reset
287+
- **Do not modify any other files** — only `extensions/catalog.community.json`
288+
and `docs/community/extensions.md`

0 commit comments

Comments
 (0)