Skip to content

Commit bd9a31d

Browse files
Update template_update.yml
1 parent 56e2404 commit bd9a31d

1 file changed

Lines changed: 144 additions & 159 deletions

File tree

.github/workflows/template_update.yml

Lines changed: 144 additions & 159 deletions
Original file line numberDiff line numberDiff line change
@@ -21,167 +21,152 @@ jobs:
2121
runs-on: ubuntu-latest
2222

2323
steps:
24-
- name: Checkout project repo
25-
uses: actions/checkout@v4
26-
with:
27-
repository: ${{ github.repository }}
28-
ref: ${{ inputs.repo_branch }}
29-
fetch-depth: 0
30-
submodules: false
31-
32-
- name: Set up Python
33-
uses: actions/setup-python@v5
34-
with:
35-
python-version: '3.x'
36-
37-
- name: Install dependencies
38-
run: pip install cookiecutter jq
39-
40-
- name: Read old template SHA
41-
id: old_sha
42-
run: |
43-
SHA=$(jq -r '.cookiecutter.template_sha // empty' .cookiecutter.json)
44-
if [ -z "$SHA" ]; then
45-
echo "::error ::.cookiecutter.json is missing cookiecutter.template_sha"
46-
exit 1
47-
fi
48-
echo "sha=$SHA" >> "$GITHUB_OUTPUT"
49-
50-
- name: Fetch new template SHA
51-
id: new_sha
52-
run: |
53-
echo "sha=$(git ls-remote '${{ inputs.template_repo }}' HEAD | cut -f1)" >> "$GITHUB_OUTPUT"
54-
55-
- name: Determine if Template was updated
56-
run: |
57-
if [ "${{ steps.old_sha.outputs.sha }}" = "${{ steps.new_sha.outputs.sha }}" ]; then
58-
echo "SHA_CHANGED=false" >> "$GITHUB_ENV"
59-
else
60-
echo "SHA_CHANGED=true" >> "$GITHUB_ENV"
61-
fi
62-
63-
- name: Exit if SHA unchanged
64-
if: env.SHA_CHANGED == 'false'
65-
run: echo "✂️ SHA unchanged; nothing to update."
66-
67-
- name: Clone template at OLD SHA
68-
if: env.SHA_CHANGED == 'true'
69-
run: |
70-
git clone '${{ inputs.template_repo }}' base-template
71-
git -C base-template checkout '${{ steps.old_sha.outputs.sha }}'
72-
73-
- name: Clone template at NEW SHA
74-
if: env.SHA_CHANGED == 'true'
75-
run: git clone '${{ inputs.template_repo }}' template-source
76-
77-
- name: Render OLD template (base-template → template-base)
78-
if: env.SHA_CHANGED == 'true'
79-
run: |
80-
rm -rf ~/.cookiecutters/*
81-
mkdir -p template-base
82-
cookiecutter base-template \
83-
--replay-file .cookiecutter.json \
84-
--overwrite-if-exists \
85-
--output-dir template-base
86-
87-
- name: Render NEW template (template-source → template-new)
88-
if: env.SHA_CHANGED == 'true'
89-
run: |
90-
rm -rf ~/.cookiecutters/*
91-
mkdir -p template-new
92-
cookiecutter template-source \
93-
--replay-file .cookiecutter.json \
94-
--overwrite-if-exists \
95-
--output-dir template-new
96-
97-
- name: Apply patch & raise PR
98-
if: env.SHA_CHANGED == 'true'
99-
shell: bash
100-
run: |
101-
diff -ruN template-base template-new > update.patch || true
102-
103-
if [ ! -s update.patch ]; then
104-
echo "ℹ️ No template diffs; only SHA bump will occur."
105-
else
106-
# 1) Pre-create target directories for NEW files (paths normalized for -p1)
107-
awk '
108-
/^\+\+\+ / {
109-
f=$2
110-
if (f == "/dev/null") next
111-
# Normalize path for -p1:
112-
if (f ~ /^[ab]\//) { sub(/^[ab]\//, "", f) } # git-style (a/ or b/)
113-
else { sub(/^[^/]+\//, "", f) } # strip "template-new/" (or "template-base/")
114-
if (match(f, /(.+)\//, m)) print m[1]
115-
}
116-
' update.patch | sort -u | xargs -r mkdir -p
117-
118-
# 2) Seed missing files from template-base so patch has a base to modify
119-
# (If a file exists in template-base but not in the repo, copy it over.)
120-
while IFS= read -r OLD; do
121-
[ "$OLD" = "/dev/null" ] && continue
122-
TGT="$OLD"
123-
if [[ "$TGT" =~ ^[ab]/ ]]; then
124-
TGT="${TGT#*/}"
125-
else
126-
TGT="${TGT#*/}"
127-
fi
128-
mkdir -p "$(dirname "$TGT")"
129-
if [ ! -e "$TGT" ] && [ -f "$OLD" ]; then
130-
cp -a "$OLD" "$TGT"
131-
fi
132-
done < <(awk '/^--- /{print $2}' update.patch)
133-
134-
# 3) Apply patch non-interactively; fail on conflicts
135-
if ! patch --batch -p1 < update.patch; then
136-
echo "::error ::Patch could not be applied; possible conflict or missing files."
24+
- name: Checkout project repo
25+
uses: actions/checkout@v4
26+
with:
27+
repository: ${{ github.repository }}
28+
ref: ${{ inputs.repo_branch }}
29+
fetch-depth: 0
30+
submodules: false
31+
32+
- name: Set up Python
33+
uses: actions/setup-python@v5
34+
with:
35+
python-version: '3.x'
36+
37+
- name: Install dependencies
38+
shell: bash
39+
run: |
40+
sudo apt-get update
41+
sudo apt-get install -y jq
42+
pip install cookiecutter
43+
44+
- name: Read old template SHA
45+
id: old_sha
46+
shell: bash
47+
run: |
48+
SHA=$(jq -r '.cookiecutter.template_sha // empty' .cookiecutter.json)
49+
if [ -z "$SHA" ]; then
50+
echo "::error ::.cookiecutter.json is missing cookiecutter.template_sha"
13751
exit 1
13852
fi
53+
echo "sha=$SHA" >> "$GITHUB_OUTPUT"
54+
55+
- name: Fetch new template SHA
56+
id: new_sha
57+
shell: bash
58+
run: |
59+
echo "sha=$(git ls-remote '${{ inputs.template_repo }}' HEAD | cut -f1)" >> "$GITHUB_OUTPUT"
60+
61+
- name: Determine if Template was updated
62+
shell: bash
63+
run: |
64+
if [ "${{ steps.old_sha.outputs.sha }}" = "${{ steps.new_sha.outputs.sha }}" ]; then
65+
echo "SHA_CHANGED=false" >> "$GITHUB_ENV"
66+
else
67+
echo "SHA_CHANGED=true" >> "$GITHUB_ENV"
68+
fi
13969
140-
git add -A
141-
echo "✅ Applied template changes"
142-
fi
143-
144-
jq ".cookiecutter.template_sha = \"${{ steps.new_sha.outputs.sha }}\"" \
145-
.cookiecutter.json > tmp && mv tmp .cookiecutter.json
146-
git add .cookiecutter.json
147-
148-
BRANCH="template-update-${{ steps.new_sha.outputs.sha }}"
149-
git checkout -b "$BRANCH"
150-
git config user.name "GitHub Actions Bot"
151-
git config user.email "actions@github.com"
152-
git commit -am "chore: merge template updates ${{ steps.old_sha.outputs.sha }} → ${{ steps.new_sha.outputs.sha }}"
153-
git push origin "$BRANCH"
154-
155-
- name: Create pull request
156-
if: env.SHA_CHANGED == 'true'
157-
env:
158-
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
159-
run: |
160-
gh pr create \
161-
--title "chore: merge template updates ${{ steps.old_sha.outputs.sha }} → ${{ steps.new_sha.outputs.sha }}" \
162-
--body "Updates cookiecutter.template_sha from ${{ steps.old_sha.outputs.sha }} to ${{ steps.new_sha.outputs.sha }}" \
163-
--base '${{ inputs.repo_branch }}' \
164-
--head "$BRANCH"
165-
- name: Final cleanup (remove temp dirs & neutralize bad .gitmodules)
166-
if: always()
167-
shell: bash
168-
run: |
169-
set -euo pipefail
170-
171-
# Remove temporary working folders & patch file
172-
rm -rf base-template template-source template-base template-new update.patch
173-
174-
# Defensive: if a stray/invalid .gitmodules exists (missing URL entries),
175-
# delete it so actions/checkout post-job doesn't crash on submodule foreach.
176-
if [ -f .gitmodules ]; then
177-
if ! git config -f .gitmodules --get-regexp '^submodule\..*\.url$' >/dev/null 2>&1; then
178-
echo "Removing invalid .gitmodules (no submodule URLs found)."
179-
rm -f .gitmodules
180-
# Purge any lingering local submodule config and modules dir
181-
git config --local --name-only --get-regexp '^submodule\.' \
182-
| xargs -r -n1 -I {} git config --local --unset-all "{}"
183-
rm -rf .git/modules || true
70+
- name: Exit if SHA unchanged
71+
if: env.SHA_CHANGED == 'false'
72+
run: echo "✂️ SHA unchanged; nothing to update."
73+
74+
- name: Render templates + apply patch (temp work OUTSIDE repo) + commit branch
75+
if: env.SHA_CHANGED == 'true'
76+
shell: bash
77+
run: |
78+
set -euo pipefail
79+
80+
WORKDIR="${RUNNER_TEMP}/cc-template-update"
81+
BASE_REPO="${WORKDIR}/base-template"
82+
NEW_REPO="${WORKDIR}/template-source"
83+
OUT_BASE="${WORKDIR}/template-base"
84+
OUT_NEW="${WORKDIR}/template-new"
85+
PATCHFILE="${WORKDIR}/update.patch"
86+
87+
rm -rf "$WORKDIR"
88+
mkdir -p "$WORKDIR" "$OUT_BASE" "$OUT_NEW"
89+
90+
echo "Cloning OLD template SHA..."
91+
git clone '${{ inputs.template_repo }}' "$BASE_REPO"
92+
git -C "$BASE_REPO" checkout '${{ steps.old_sha.outputs.sha }}'
93+
94+
echo "Cloning NEW template SHA..."
95+
git clone '${{ inputs.template_repo }}' "$NEW_REPO"
96+
97+
echo "Rendering OLD template..."
98+
rm -rf ~/.cookiecutters/*
99+
cookiecutter "$BASE_REPO" \
100+
--replay-file .cookiecutter.json \
101+
--overwrite-if-exists \
102+
--output-dir "$OUT_BASE"
103+
104+
echo "Rendering NEW template..."
105+
rm -rf ~/.cookiecutters/*
106+
cookiecutter "$NEW_REPO" \
107+
--replay-file .cookiecutter.json \
108+
--overwrite-if-exists \
109+
--output-dir "$OUT_NEW"
110+
111+
echo "Diffing renders..."
112+
diff -ruN "$OUT_BASE" "$OUT_NEW" > "$PATCHFILE" || true
113+
114+
if [ ! -s "$PATCHFILE" ]; then
115+
echo "ℹ️ No template diffs; only SHA bump will occur."
116+
else
117+
echo "Pre-creating dirs for new files..."
118+
awk '
119+
/^\+\+\+ / {
120+
f=$2
121+
if (f == "/dev/null") next
122+
# remove leading directory (template-new/ or template-base/)
123+
sub(/^[^/]+\//, "", f)
124+
if (match(f, /(.+)\//, m)) print m[1]
125+
}
126+
' "$PATCHFILE" | sort -u | xargs -r mkdir -p
127+
128+
echo "Seeding missing base files so patch can modify them..."
129+
awk '/^--- /{print $2}' "$PATCHFILE" | while read -r OLD; do
130+
[ "$OLD" = "/dev/null" ] && continue
131+
# strip leading dir from diff path
132+
REL="${OLD#*/}"
133+
SRC="$OUT_BASE/${REL}"
134+
TGT="${REL}"
135+
mkdir -p "$(dirname "$TGT")"
136+
if [ ! -e "$TGT" ] && [ -f "$SRC" ]; then
137+
cp -a "$SRC" "$TGT"
138+
fi
139+
done
140+
141+
echo "Applying patch..."
142+
patch --batch -p1 < "$PATCHFILE"
143+
echo "✅ Applied template changes"
184144
fi
185-
fi
186145
187-
echo "Cleanup complete."
146+
echo "Updating template SHA in .cookiecutter.json..."
147+
jq ".cookiecutter.template_sha = \"${{ steps.new_sha.outputs.sha }}\"" \
148+
.cookiecutter.json > tmp && mv tmp .cookiecutter.json
149+
150+
BRANCH="template-update-${{ steps.new_sha.outputs.sha }}"
151+
echo "BRANCH=$BRANCH" >> "$GITHUB_ENV"
152+
153+
git checkout -b "$BRANCH"
154+
git config user.name "GitHub Actions Bot"
155+
git config user.email "actions@github.com"
156+
157+
git add -A
158+
git commit -m "chore: merge template updates ${{ steps.old_sha.outputs.sha }} → ${{ steps.new_sha.outputs.sha }}"
159+
git push origin "$BRANCH"
160+
161+
- name: Create pull request
162+
if: env.SHA_CHANGED == 'true'
163+
env:
164+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
165+
shell: bash
166+
run: |
167+
gh pr create \
168+
--title "chore: merge template updates ${{ steps.old_sha.outputs.sha }} → ${{ steps.new_sha.outputs.sha }}" \
169+
--body "Updates cookiecutter.template_sha from ${{ steps.old_sha.outputs.sha }} to ${{ steps.new_sha.outputs.sha }}" \
170+
--base '${{ inputs.repo_branch }}' \
171+
--head "${{ env.BRANCH }}"
172+

0 commit comments

Comments
 (0)