Skip to content

Commit f461005

Browse files
Update template_update.yml
1 parent 9799c0b commit f461005

1 file changed

Lines changed: 104 additions & 87 deletions

File tree

Lines changed: 104 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
name: template_update
22

3+
permissions:
4+
contents: write
5+
pull-requests: write
6+
37
on:
48
workflow_call:
59
inputs:
@@ -13,146 +17,159 @@ on:
1317
type: string
1418

1519
jobs:
16-
validate-inputs:
20+
template-update:
1721
runs-on: ubuntu-latest
18-
outputs:
19-
repo: ${{ inputs.template_repo }}
20-
branch: ${{ inputs.repo_branch }}
2122
steps:
22-
- name: Checkout caller repo
23-
uses: actions/checkout@v4
24-
with:
25-
fetch-depth: 0
26-
27-
- name: Fetch all remote branches
28-
run: |
29-
git fetch origin '+refs/heads/*:refs/remotes/origin/*'
30-
31-
- name: Validate repo_branch exists
32-
run: |
33-
if ! git show-ref --verify --quiet "refs/remotes/origin/${{ inputs.repo_branch }}"; then
34-
echo "::error ::Branch '${{ inputs.repo_branch }}' not found!"
35-
exit 1
36-
fi
3723

38-
update-template:
39-
needs: validate-inputs
40-
runs-on: ubuntu-latest
41-
steps:
42-
# 1. Check out the target branch
43-
- name: Checkout project at ${{ needs.validate-inputs.outputs.branch }}
24+
# 1. Checkout target branch (full history, can push)
25+
- name: Checkout project repo
4426
uses: actions/checkout@v4
4527
with:
28+
repository: ${{ github.repository }}
29+
ref: ${{ inputs.repo_branch }}
4630
fetch-depth: 0
47-
ref: ${{ needs.validate-inputs.outputs.branch }}
4831

49-
# 2. Set up Python & Cookiecutter
32+
# 2. Set up Python & install deps
5033
- name: Set up Python
5134
uses: actions/setup-python@v5
5235
with:
5336
python-version: '3.x'
54-
- run: pip install cookiecutter jq
55-
56-
# this section checks if the template has had updates
57-
58-
# 3. Grab old & new template SHAs checks template changes
37+
- name: Install dependencies
38+
run: pip install cookiecutter jq
39+
40+
# 3. Read old SHA
5941
- name: Read old template SHA
6042
id: get_old_sha
6143
run: |
62-
OLD_SHA=$(jq -r '.template_sha' .cookiecutter.json)
44+
OLD_SHA=$(jq -r '.cookiecutter.template_sha // empty' .cookiecutter.json)
45+
if [ -z "$OLD_SHA" ]; then
46+
echo "::error ::.cookiecutter.json is missing cookiecutter.template_sha"
47+
exit 1
48+
fi
6349
echo "old_sha=$OLD_SHA" >> $GITHUB_OUTPUT
50+
51+
# 4. Fetch new SHA
6452
- name: Fetch new template SHA
6553
id: get_new_sha
6654
run: |
67-
NEW_SHA=$(git ls-remote "${{ needs.validate-inputs.outputs.repo }}" HEAD | cut -f1)
55+
NEW_SHA=$(git ls-remote "${{ inputs.template_repo }}" HEAD | cut -f1)
6856
echo "new_sha=$NEW_SHA" >> $GITHUB_OUTPUT
6957
70-
# 4. Clone base & new template repos
71-
- name: Clone base template at old SHA
58+
# 5. Determine if SHA changed
59+
- name: Determine if SHA changed
60+
id: sha_check
61+
run: |
62+
if [ "${{ steps.get_old_sha.outputs.old_sha }}" != "${{ steps.get_new_sha.outputs.new_sha }}" ]; then
63+
echo "SHA_CHANGED=true" >> $GITHUB_ENV
64+
else
65+
echo "SHA_CHANGED=false" >> $GITHUB_ENV
66+
fi
67+
68+
# 6. Exit early if SHA unchanged
69+
- name: Exit if SHA unchanged
70+
if: env.SHA_CHANGED == 'false'
71+
run: |
72+
echo "✂️ SHA unchanged; nothing to update."
73+
exit 0
74+
75+
# 7. Clone both template versions
76+
- name: Clone base template at OLD SHA
77+
if: env.SHA_CHANGED == 'true'
7278
run: |
73-
git clone "${{ needs.validate-inputs.outputs.repo }}" base-template
79+
git clone "${{ inputs.template_repo }}" base-template
7480
pushd base-template
7581
git checkout "${{ steps.get_old_sha.outputs.old_sha }}"
7682
popd
7783
7884
- name: Clone new template at HEAD
79-
run: git clone "${{ needs.validate-inputs.outputs.repo }}" template-source
85+
if: env.SHA_CHANGED == 'true'
86+
run: git clone "${{ inputs.template_repo }}" template-source
8087

81-
# 5. Determine which sub-template to use
88+
# 8. Determine sub-template path
8289
- name: Determine sub-template path
8390
id: template_path
91+
if: env.SHA_CHANGED == 'true'
8492
run: |
85-
if grep -q '"is_aspire": *"yes"' .cookiecutter.json; then
93+
ASP=$(jq -r '.cookiecutter.is_aspire // "no"' .cookiecutter.json)
94+
DOC=$(jq -r '.cookiecutter.is_docker // "no"' .cookiecutter.json)
95+
if [ "$ASP" = "yes" ]; then
8696
echo "path=aspire-project" >> $GITHUB_OUTPUT
87-
elif grep -q '"is_docker": *"yes"' .cookiecutter.json; then
97+
elif [ "$DOC" = "yes" ]; then
8898
echo "path=docker-project" >> $GITHUB_OUTPUT
8999
else
90-
echo "::error ::No valid sub-template selected!" && exit 1
100+
echo "::error ::No valid sub-template in .cookiecutter.json" && exit 1
91101
fi
92102
93-
# 6. Regenerate base & new outputs
103+
# 9. Render base & new template outputs
94104
- name: Generate base template output
105+
if: env.SHA_CHANGED == 'true'
95106
run: |
107+
rm -rf ~/.cookiecutters/*
96108
mkdir -p template-base
97-
cookiecutter "base-template/${{ steps.template_path.outputs.path }}" \
98-
--no-input --replay-file .cookiecutter.json \
109+
cookiecutter ./base-template \
110+
--directory "${{ steps.template_path.outputs.path }}" \
111+
--replay-file .cookiecutter.json \
112+
--overwrite-if-exists \
99113
--output-dir template-base
100114
101115
- name: Generate new template output
116+
if: env.SHA_CHANGED == 'true'
102117
run: |
118+
rm -rf ~/.cookiecutters/*
103119
mkdir -p template-new
104-
cookiecutter "template-source/${{ steps.template_path.outputs.path }}" \
105-
--no-input --replay-file .cookiecutter.json \
120+
cookiecutter ./template-source \
121+
--directory "${{ steps.template_path.outputs.path }}" \
122+
--replay-file .cookiecutter.json \
123+
--overwrite-if-exists \
106124
--output-dir template-new
107125
108-
# 7. Create a unified patch
109-
- name: Create update.patch
126+
# 10. Diff + merge + bump + branch + commit + push
127+
- name: Apply patch if changes
128+
if: env.SHA_CHANGED == 'true'
129+
shell: bash
110130
run: |
131+
# create patch
111132
diff -ruN \
112133
template-base/${{ steps.template_path.outputs.path }} \
113134
template-new/${{ steps.template_path.outputs.path }} \
114135
> update.patch || true
115136
116-
# 8. Apply it with three-way merge
117-
- name: Apply three-way merge
118-
run: |
119-
if ! git apply --index --3way update.patch; then
120-
echo "::error ::Merge conflicts detected in template updates – exiting."
121-
exit 1
137+
# abort if no patch
138+
if [ ! -s update.patch ]; then
139+
echo "ℹ️ No template diffs; only SHA bump will occur."
140+
else
141+
# apply 3-way merge or abort
142+
if ! git apply --index --3way update.patch; then
143+
echo "::error ::Merge conflicts detected; aborting."
144+
exit 1
145+
fi
146+
echo "✅ Applied template changes"
122147
fi
123148
124-
# 9. Update the SHA in .cookiecutter.json
125-
- name: Write new SHA back to .cookiecutter.json
126-
run: |
127-
jq --arg sha "${{ steps.get_new_sha.outputs.new_sha }}" \
128-
'.template_sha = $sha' .cookiecutter.json > tmp.json
129-
mv tmp.json .cookiecutter.json
149+
# bump the SHA
150+
jq ".cookiecutter.template_sha = \"${{ steps.get_new_sha.outputs.new_sha }}\"" \
151+
.cookiecutter.json > tmp.json && mv tmp.json .cookiecutter.json
130152
git add .cookiecutter.json
131153
132-
# 10. Clean up temp dirs
133-
- name: Cleanup
134-
run: rm -rf base-template template-source template-base template-new update.patch
135-
136-
# 11. Commit & push merged result on a new branch
137-
- name: Commit & push
138-
id: commit
154+
# create branch, commit & push
155+
UPDATE_BRANCH="template-update-${{ steps.get_new_sha.outputs.new_sha }}"
156+
echo "UPDATE_BRANCH=${UPDATE_BRANCH}" >> $GITHUB_ENV
157+
git checkout -b "${UPDATE_BRANCH}"
158+
git config user.name "GitHub Actions Bot"
159+
git config user.email "actions@github.com"
160+
git commit -m "chore: merge template updates ${{ steps.get_old_sha.outputs.old_sha }} → ${{ steps.get_new_sha.outputs.new_sha }}"
161+
git push origin "${UPDATE_BRANCH}"
162+
163+
# 11. Create Pull Request (even if only .cookiecutter.json changed)
164+
# After your commit & push step…
165+
- name: Create Pull Request via GitHub CLI
166+
if: env.SHA_CHANGED == 'true'
167+
env:
168+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
139169
run: |
140-
BRANCH="template-update-${{ steps.get_new_sha.outputs.new_sha }}"
141-
echo "UPDATE_BRANCH=$BRANCH" >> $GITHUB_ENV
142-
git checkout -b "$BRANCH"
143-
git commit -m "chore: merge template ${ steps.get_old_sha.outputs.old_sha } → ${ steps.get_new_sha.outputs.new_sha }"
144-
git push origin "$BRANCH"
145-
146-
# 12. Open a single draft PR
147-
- name: Create draft Pull Request
148-
uses: peter-evans/create-pull-request@v5
149-
with:
150-
token: ${{ secrets.GITHUB_TOKEN }}
151-
branch: ${{ env.UPDATE_BRANCH }}
152-
base: ${{ needs.validate-inputs.outputs.branch }}
153-
draft: true
154-
title: "chore: merge cookiecutter template updates"
155-
body: |
156-
**Template Repo:** ${{ needs.validate-inputs.outputs.repo }}
157-
**Base SHA:** ${{ steps.get_old_sha.outputs.old_sha }}
158-
**New SHA:** ${{ steps.get_new_sha.outputs.new_sha }}
170+
gh auth setup-git
171+
gh pr create \
172+
--title "chore: merge template updates ${{ steps.get_old_sha.outputs.old_sha }} → ${{ steps.get_new_sha.outputs.new_sha }}" \
173+
--body "Updates cookiecutter.template_sha from ${{ steps.get_old_sha.outputs.old_sha }} to ${{ steps.get_new_sha.outputs.new_sha }}" \
174+
--base "${{ inputs.repo_branch }}" \
175+
--head "${{ env.UPDATE_BRANCH }}"

0 commit comments

Comments
 (0)