Skip to content

Commit 0b9d273

Browse files
committed
Require tags for new patterns
Validate content generation on pull requests, reject missing or unregistered pattern tags, and limit PR proof runs to changed scenarios. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: b54d1b0e-e0a6-47d0-bc1d-017139d2c390
1 parent 4d194cf commit 0b9d273

4 files changed

Lines changed: 60 additions & 8 deletions

File tree

.github/copilot-instructions.md

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ Content files are YAML (preferred) or JSON under `content/{category}/{slug}.yaml
4848
| `category` | Must match parent folder name |
4949
| `whyModernWins` | Exactly **3** entries, each with `icon`, `title`, `desc` |
5050
| `related` | Exactly **3** entries as `category/slug` paths (cross-category OK) |
51+
| `tags` | Non-empty list of slugs registered in `html-generators/tags.properties` |
5152
| `docs` | At least **1** entry with `title` and `href` |
5253
| `prev` / `next` | `category/slug` path or `null` for first/last in the global chain |
5354
| `jdkVersion` | The JDK version where the feature became **final** (not preview) |
@@ -57,10 +58,11 @@ Content files are YAML (preferred) or JSON under `content/{category}/{slug}.yaml
5758
### Adding a new pattern
5859

5960
1. Create `content/{category}/new-slug.yaml` with all required fields (use `content/template.json` as reference).
60-
2. Update `prev`/`next` in the adjacent patterns to maintain the navigation chain.
61-
3. Create `proof/{category}/{PascalCaseSlug}.java` — JBang script wrapping the modern code.
62-
4. Run `jbang html-generators/generate.java` and verify it completes.
63-
5. Translations are optional — the AI translation workflow handles them, or create partial files under `translations/content/{locale}/`.
61+
2. Add a non-empty `tags` list. Every tag slug must already exist in `html-generators/tags.properties`; add new `slug=Display Name` entries there in the same change.
62+
3. Update `prev`/`next` in the adjacent patterns to maintain the navigation chain.
63+
4. Create `proof/{category}/{PascalCaseSlug}.java` — JBang script wrapping the modern code.
64+
5. Run `jbang html-generators/generate.java` and verify it completes. The generator rejects missing, empty, malformed, and unregistered tags.
65+
6. Translations are optional — the AI translation workflow handles them, or create partial files under `translations/content/{locale}/`.
6466

6567
### Removing or reordering a pattern
6668

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
name: Content Validation
2+
3+
on:
4+
pull_request:
5+
paths:
6+
- '.github/workflows/content-validation.yml'
7+
- 'content/**'
8+
- 'translations/**'
9+
- 'templates/**'
10+
- 'html-generators/generate.java'
11+
- 'html-generators/tags.properties'
12+
- 'html-generators/categories.properties'
13+
- 'html-generators/locales.properties'
14+
workflow_dispatch:
15+
16+
permissions:
17+
contents: read
18+
19+
jobs:
20+
validate:
21+
runs-on: ubuntu-latest
22+
steps:
23+
- uses: actions/checkout@v7
24+
25+
- uses: actions/setup-java@v6
26+
with:
27+
distribution: 'temurin'
28+
java-version: '25'
29+
30+
- uses: jbangdev/setup-jbang@main
31+
32+
- name: Validate content and generate site
33+
run: jbang html-generators/generate.java

.github/workflows/proof.yml

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ jobs:
1818
runs-on: ubuntu-latest
1919
steps:
2020
- uses: actions/checkout@v7
21+
with:
22+
fetch-depth: 0
2123

2224
- uses: actions/setup-java@v6
2325
with:
@@ -26,14 +28,27 @@ jobs:
2628

2729
- uses: jbangdev/setup-jbang@main
2830

29-
- name: Run all proof scripts
31+
- name: Run proof scripts
3032
shell: bash
3133
run: |
3234
passed=0
3335
failed=0
3436
failures=()
37+
scripts=()
38+
39+
if [[ "${{ github.event_name }}" == "pull_request" ]]; then
40+
while IFS= read -r -d '' script; do
41+
[[ "$script" == *.java ]] && scripts+=("$script")
42+
done < <(git diff --name-only --diff-filter=ACMR -z \
43+
"${{ github.event.pull_request.base.sha }}" \
44+
"${{ github.event.pull_request.head.sha }}" -- proof/)
45+
else
46+
while IFS= read -r -d '' script; do
47+
scripts+=("$script")
48+
done < <(find proof -name '*.java' -print0 | sort -z)
49+
fi
3550
36-
while IFS= read -r -d '' script; do
51+
for script in "${scripts[@]}"; do
3752
name="${script#proof/}"
3853
if jbang "$script" > /dev/null 2>&1; then
3954
echo "✅ $name"
@@ -43,7 +58,7 @@ jobs:
4358
failures+=("$name")
4459
failed=$((failed + 1))
4560
fi
46-
done < <(find proof -name '*.java' -print0 | sort -z)
61+
done
4762
4863
echo ""
4964
echo "Results: $passed passed, $failed failed out of $((passed + failed)) scripts"

html-generators/generate.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,9 @@ List<String> related() {
179179

180180
List<String> tags() {
181181
var t = node.get("tags");
182-
if (t == null || !t.isArray()) return List.of();
182+
if (t == null || !t.isArray() || t.isEmpty()) {
183+
throw new IllegalArgumentException("Missing or empty tags array in " + key());
184+
}
183185
var tagList = new ArrayList<String>();
184186
t.forEach(n -> {
185187
var tag = n.asText().strip();

0 commit comments

Comments
 (0)