Skip to content

Commit bd8565f

Browse files
sbglasiusclaude
andcommitted
Add template sync workflow, TEMPLATE_README, and warning comments
- Add .github/workflows/files-sync.yml: syncs infrastructure files to registered plugin repos on release, using a GitHub App for cross-org write access (gpc + grails-plugins) - Add .github/scripts/prepare-sync-matrix.groovy: builds GH Actions matrix from .github/projects.yml - Add .github/projects.yml: registry of target repos for the sync - Add TEMPLATE_README.md: guide for new plugins and migration path - Prepend "do not edit" warning comments to all synced files (workflows, scripts, build-logic convention plugins) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 886878f commit bd8565f

21 files changed

Lines changed: 540 additions & 0 deletions

.github/projects.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
projects:
2+
gpc:
3+
- export
4+
- grails-cookie
5+
grails-plugins:
6+
- grails-shiro
7+
- grails-elasticsearch
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#!/usr/bin/env groovy
2+
@Grab('org.apache.groovy:groovy-yaml')
3+
import groovy.json.JsonOutput
4+
import groovy.yaml.YamlSlurper
5+
6+
def projectsYml = new YamlSlurper().parse(new File('.github/projects.yml')) as Map
7+
def filterProject = System.getenv('FILTER_PROJECT') ?: ''
8+
9+
def repos = []
10+
(projectsYml.projects as Map<String, List<String>>).each { org, repoList ->
11+
repoList.each { repo ->
12+
if (!filterProject || filterProject == "${org}/${repo}") {
13+
repos << [org: org, repo: repo]
14+
}
15+
}
16+
}
17+
18+
def line = "repos=${JsonOutput.toJson(repos)}"
19+
def outputFile = System.getenv('GITHUB_OUTPUT')
20+
if (outputFile) {
21+
new File(outputFile) << "${line}\n"
22+
} else {
23+
System.err.println "GITHUB_OUTPUT not set — would output: ${line}"
24+
}
25+
println "Matrix: ${repos.size()} repo(s)"

.github/scripts/update-contributors.groovy

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
#!/usr/bin/env groovy
2+
// WARNING: Do not edit this file directly in your own repository.
3+
// It is maintained in the grails-plugin-template repository.
4+
// https://github.com/grails-plugins/grails-plugin-template/tree/main/.github/scripts
25
@Grab('org.apache.groovy:groovy-yaml')
36
import groovy.json.JsonOutput
47
import groovy.json.JsonSlurper

.github/scripts/update-versions.groovy

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
#!/usr/bin/env groovy
2+
// WARNING: Do not edit this file directly in your own repository.
3+
// It is maintained in the grails-plugin-template repository.
4+
// https://github.com/grails-plugins/grails-plugin-template/tree/main/.github/scripts
25
@Grab('org.apache.groovy:groovy-yaml')
36
import groovy.json.JsonSlurper
47
import groovy.yaml.YamlBuilder

.github/workflows/ci.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
# WARNING: Do not edit this file directly in your own repository.
2+
# It is maintained in the grails-plugin-template repository.
3+
# To make changes, edit it there and they will be synced automatically:
4+
# https://github.com/grails-plugins/grails-plugin-template/tree/main/.github/workflows
15
name: "CI"
26
on:
37
push:

.github/workflows/files-sync.yml

Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
name: "Files Sync"
2+
3+
on:
4+
release:
5+
types: [published]
6+
workflow_dispatch:
7+
inputs:
8+
project:
9+
description: 'Specific project to sync (org/repo, e.g. gpc/export). Leave empty to sync all.'
10+
required: false
11+
type: string
12+
13+
env:
14+
JAVA_DISTRIBUTION: 'liberica'
15+
16+
jobs:
17+
prepare-matrix:
18+
if: github.repository == 'grails-plugins/grails-plugin-template'
19+
runs-on: ubuntu-24.04
20+
outputs:
21+
repos: ${{ steps.prepare.outputs.repos }}
22+
steps:
23+
- name: "📥 Checkout repository"
24+
uses: actions/checkout@v6
25+
26+
- name: "Export .sdkmanrc properties"
27+
uses: apache/grails-github-actions/export-gradle-properties@asf
28+
with:
29+
file: ".sdkmanrc"
30+
prefix: "SDKMANRC_"
31+
32+
- name: "Determine Java Version"
33+
run: echo "SDKMANRC_java=${{ env.SDKMANRC_java }}" | sed 's/-.*//' >> $GITHUB_ENV
34+
35+
- name: "☕️ Setup JDK"
36+
uses: actions/setup-java@v5
37+
with:
38+
distribution: ${{ env.JAVA_DISTRIBUTION }}
39+
java-version: ${{ env.SDKMANRC_java }}
40+
41+
- name: "🦊 Install Groovy ${{ env.SDKMANRC_groovy }}"
42+
run: |
43+
curl -s "https://get.sdkman.io" | bash
44+
source "$HOME/.sdkman/bin/sdkman-init.sh"
45+
sdk install groovy ${{ env.SDKMANRC_groovy }} < /dev/null
46+
echo "$HOME/.sdkman/candidates/groovy/current/bin" >> $GITHUB_PATH
47+
48+
- name: "🗂️ Prepare sync matrix"
49+
id: prepare
50+
env:
51+
FILTER_PROJECT: ${{ inputs.project }}
52+
run: groovy .github/scripts/prepare-sync-matrix.groovy
53+
54+
sync-files:
55+
needs: prepare-matrix
56+
if: github.repository == 'grails-plugins/grails-plugin-template'
57+
runs-on: ubuntu-24.04
58+
permissions:
59+
contents: read
60+
strategy:
61+
fail-fast: false
62+
max-parallel: 3
63+
matrix:
64+
include: ${{ fromJson(needs.prepare-matrix.outputs.repos) }}
65+
steps:
66+
- name: "🔑 Mint org-scoped app token for ${{ matrix.org }}"
67+
uses: actions/create-github-app-token@v1
68+
id: app-token
69+
with:
70+
app-id: ${{ secrets.APP_ID }}
71+
private-key: ${{ secrets.APP_PRIVATE_KEY }}
72+
owner: ${{ matrix.org }}
73+
74+
- name: "📥 Checkout source (template)"
75+
uses: actions/checkout@v6
76+
with:
77+
path: source
78+
79+
- name: "📥 Checkout target (${{ matrix.org }}/${{ matrix.repo }})"
80+
uses: actions/checkout@v6
81+
with:
82+
repository: ${{ matrix.org }}/${{ matrix.repo }}
83+
path: target
84+
token: ${{ steps.app-token.outputs.token }}
85+
fetch-depth: 0
86+
87+
- name: "🌿 Detect default branch"
88+
id: branch
89+
env:
90+
GH_TOKEN: ${{ steps.app-token.outputs.token }}
91+
run: |
92+
branch=$(gh api repos/${{ matrix.org }}/${{ matrix.repo }} --jq '.default_branch')
93+
echo "branch=${branch}" >> $GITHUB_OUTPUT
94+
95+
- name: "🔄 Sync files from template"
96+
run: |
97+
set -euo pipefail
98+
99+
maybe_copy() {
100+
local src="$1" dst="$2"
101+
if [ -f "target/${dst}.lock" ]; then
102+
echo "Skipping locked: ${dst}"
103+
return
104+
fi
105+
mkdir -p "target/$(dirname "${dst}")"
106+
cp "source/${src}" "target/${dst}"
107+
}
108+
109+
# Workflow files — exclude files-sync.yml (template-only)
110+
mkdir -p target/.github/workflows/
111+
rsync -a --delete --exclude='files-sync.yml' \
112+
source/.github/workflows/ target/.github/workflows/
113+
114+
# Scripts — exclude prepare-sync-matrix.groovy (template-only)
115+
mkdir -p target/.github/scripts/
116+
rsync -a --exclude='prepare-sync-matrix.groovy' \
117+
source/.github/scripts/ target/.github/scripts/
118+
119+
# GitHub config singles (lock-aware)
120+
maybe_copy .github/dependabot.yml .github/dependabot.yml
121+
maybe_copy .github/renovate.json .github/renovate.json
122+
maybe_copy .github/release-drafter.yml .github/release-drafter.yml
123+
124+
# Directories
125+
mkdir -p target/.github/dependency-graph/
126+
rsync -a source/.github/dependency-graph/ target/.github/dependency-graph/
127+
mkdir -p target/.skills/
128+
rsync -a --delete source/.skills/ target/.skills/
129+
mkdir -p target/build-logic/
130+
rsync -a source/build-logic/ target/build-logic/
131+
mkdir -p target/gradle/
132+
rsync -a source/gradle/ target/gradle/
133+
134+
# Root files (lock-aware)
135+
maybe_copy .editorconfig .editorconfig
136+
maybe_copy .sdkmanrc .sdkmanrc
137+
maybe_copy CONTRIBUTING.md CONTRIBUTING.md
138+
maybe_copy LICENSE.txt LICENSE.txt
139+
maybe_copy gradlew.bat gradlew.bat
140+
141+
# gradlew needs +x
142+
if [ ! -f "target/gradlew.lock" ]; then
143+
cp source/gradlew target/gradlew
144+
chmod +x target/gradlew
145+
fi
146+
147+
- name: "📤 Create Pull Request"
148+
id: create-pr
149+
uses: peter-evans/create-pull-request@v7
150+
with:
151+
path: target
152+
token: ${{ steps.app-token.outputs.token }}
153+
commit-message: "chore: sync files from grails-plugin-template"
154+
title: "Sync common files from grails-plugin-template"
155+
body: |
156+
Syncs common infrastructure files from [grails-plugin-template](https://github.com/grails-plugins/grails-plugin-template).
157+
158+
**Files updated:**
159+
- `.github/workflows/` (CI, release, release-notes, update-contributors, update-versions)
160+
- `.github/scripts/` (update-contributors, update-versions)
161+
- `.github/dependabot.yml`, `renovate.json`, `release-drafter.yml`
162+
- `.skills/`
163+
- `build-logic/`
164+
- `gradle/` (wrapper)
165+
- `.editorconfig`, `.sdkmanrc`, `CONTRIBUTING.md`, `gradlew`, `gradlew.bat`, `LICENSE.txt`
166+
167+
> To lock a file and prevent future syncs, create a `<filename>.lock` file next to it.
168+
branch: sync-files-from-template
169+
base: ${{ steps.branch.outputs.branch }}
170+
labels: "maintenance"
171+
172+
- name: "🔀 Enable auto-merge"
173+
if: steps.create-pr.outputs.pull-request-number != ''
174+
env:
175+
GH_TOKEN: ${{ steps.app-token.outputs.token }}
176+
run: |
177+
gh pr merge "${{ steps.create-pr.outputs.pull-request-url }}" \
178+
--squash \
179+
--auto \
180+
--delete-branch

.github/workflows/release-notes.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
# WARNING: Do not edit this file directly in your own repository.
2+
# It is maintained in the grails-plugin-template repository.
3+
# To make changes, edit it there and they will be synced automatically:
4+
# https://github.com/grails-plugins/grails-plugin-template/tree/main/.github/workflows
15
name: "Release - Drafter"
26
on:
37
issues:

.github/workflows/release.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
# WARNING: Do not edit this file directly in your own repository.
2+
# It is maintained in the grails-plugin-template repository.
3+
# To make changes, edit it there and they will be synced automatically:
4+
# https://github.com/grails-plugins/grails-plugin-template/tree/main/.github/workflows
15
name: "Release"
26
on:
37
release:

.github/workflows/update-contributors.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
# WARNING: Do not edit this file directly in your own repository.
2+
# It is maintained in the grails-plugin-template repository.
3+
# To make changes, edit it there and they will be synced automatically:
4+
# https://github.com/grails-plugins/grails-plugin-template/tree/main/.github/workflows
15
name: Update Contributors
26

37
on:

.github/workflows/update-versions.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
# WARNING: Do not edit this file directly in your own repository.
2+
# It is maintained in the grails-plugin-template repository.
3+
# To make changes, edit it there and they will be synced automatically:
4+
# https://github.com/grails-plugins/grails-plugin-template/tree/main/.github/workflows
15
name: Update GitHub Index Page
26

37
on:

0 commit comments

Comments
 (0)