Skip to content

Commit df3262d

Browse files
feat: renders record their answers, so copier update can reach them (#21)
There was no answers file template under template/, so Copier wrote none: a render recorded neither its answers nor the template commit it came from, copier update refused to run, and every template fix had to be copied into each library by hand. template/{{_copier_conf.answers_file}}.jinja makes every render carry _src_path, _commit and the answers. The post-generation message now runs on a copy only, since copier update runs tasks too. CI gets an update job: a render of master, updated to the commit under test, has to come out exactly as a fresh render of it, so a change that does not travel through copier update fails its own pull request. The README says how to update a library and how to backfill the file in one rendered before it existed. Closes #14
1 parent 28d0825 commit df3262d

4 files changed

Lines changed: 73 additions & 11 deletions

File tree

‎.github/workflows/ci.yml‎

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,10 +67,49 @@ jobs:
6767
uv run ruff check tests/unit/test_probe.py
6868
rm demo_lib/probe.py tests/unit/test_probe.py
6969
70+
# A library takes template changes with `copier update`, so a change has to
71+
# arrive that way too: a render of master, updated to this commit, has to
72+
# come out exactly as a fresh render of this commit.
73+
update:
74+
name: copier update brings the change into a render of master
75+
runs-on: ubuntu-latest
76+
steps:
77+
- uses: actions/checkout@v7
78+
with:
79+
fetch-depth: 0
80+
- uses: astral-sh/setup-uv@v7
81+
82+
- name: Update a render of master to this commit
83+
run: |
84+
git fetch --no-tags origin master:refs/heads/ci-base
85+
git branch -f ci-head HEAD
86+
if ! git cat-file -e 'ci-base:template/{{_copier_conf.answers_file}}.jinja' 2>/dev/null; then
87+
echo "A render of master has no answers file to update from."
88+
exit 0
89+
fi
90+
render() {
91+
uvx --from copier==9.19.1 --with jinja2-time==0.2.0 copier copy --quiet --defaults --trust --vcs-ref "$1" \
92+
--data project_name=demo-lib \
93+
--data project_slug=demo-lib \
94+
--data package_name=demo_lib \
95+
--data project_description="Demo library rendered from the template" \
96+
--data author_name="Bedrock Python" \
97+
--data author_email="maintainers@example.com" \
98+
"$GITHUB_WORKSPACE" "$2"
99+
}
100+
render ci-base "$RUNNER_TEMP/updated"
101+
render ci-head "$RUNNER_TEMP/fresh"
102+
cd "$RUNNER_TEMP/updated"
103+
git init -q -b master
104+
git add -A
105+
git -c user.name=ci -c user.email=ci@example.com commit -q -m "render of master"
106+
uvx --from copier==9.19.1 --with jinja2-time==0.2.0 copier update --quiet --defaults --trust --vcs-ref ci-head
107+
diff -r --exclude=.git "$RUNNER_TEMP/fresh" "$RUNNER_TEMP/updated"
108+
70109
all-checks-passed:
71110
name: All checks passed
72111
if: always()
73-
needs: [render]
112+
needs: [render, update]
74113
runs-on: ubuntu-latest
75114
steps:
76115
- name: Every job above succeeded

‎README.md‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,24 @@ Then:
6060
4. Set up PyPI Trusted Publisher at pypi.org/manage/account/publishing/
6161
5. Add `CODECOV_TOKEN` secret in repo Settings → Secrets → Actions
6262

63+
## Pulling template changes into a library
64+
65+
A render records its answers and the template commit it came from in
66+
`.copier-answers.yml`. Commit that file and leave it to Copier. To bring a library up to
67+
the template's `master`, from the library's clean working tree:
68+
69+
```bash
70+
uvx --with jinja2-time copier update --trust --defaults
71+
```
72+
73+
Copier applies what changed in the template since the recorded commit as a three-way
74+
merge with the library's own edits, leaves conflicts as inline markers, and moves
75+
`_commit` forward. A file the library deleted, such as the checklist, stays deleted.
76+
77+
A library rendered before the answers file existed needs one written by hand first: the
78+
answers it was rendered with, `_src_path: gh:bedrock-python/python-library-template`,
79+
and as `_commit` the template commit it was rendered from, or the closest one.
80+
6381
## For AI Agents
6482

6583
See [`.claude/LIBRARY_CREATION.md`](.claude/LIBRARY_CREATION.md) for important rules:

‎copier.yml‎

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -45,13 +45,16 @@ _jinja_extensions:
4545
- jinja2_time.TimeExtension
4646

4747
_tasks:
48-
- >-
49-
echo "Template generated. Next steps:
50-
1. uv sync --group dev
51-
2. uv run pre-commit install --hook-type commit-msg
52-
3. Create the GitHub repo and push (branch: master)
53-
4. After the first CI pass, from the template repo:
54-
python scripts/setup_repo.py {{ github_org }}/{{ project_slug }}
55-
5. Configure the PyPI Trusted Publisher at pypi.org
56-
6. Add the CODECOV_TOKEN secret.
57-
See NEW_LIBRARY_CHECKLIST.md for full details."
48+
# On a copy only: `copier update` runs tasks too, and a library taking a
49+
# template update finished these steps long ago.
50+
- command: >-
51+
echo "Template generated. Next steps:
52+
1. uv sync --group dev
53+
2. uv run pre-commit install --hook-type commit-msg
54+
3. Create the GitHub repo and push (branch: master)
55+
4. After the first CI pass, from the template repo:
56+
python scripts/setup_repo.py {{ github_org }}/{{ project_slug }}
57+
5. Configure the PyPI Trusted Publisher at pypi.org
58+
6. Add the CODECOV_TOKEN secret.
59+
See NEW_LIBRARY_CHECKLIST.md for full details."
60+
when: "{{ _copier_operation == 'copy' }}"
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# Changes here will be overwritten by Copier; NEVER EDIT MANUALLY
2+
{{ _copier_answers|to_nice_yaml -}}

0 commit comments

Comments
 (0)