Skip to content

9.15.2 appears to have breaking change #2723

Description

@oc-ben-ellis

Describe the problem

Copier 9.15.2 renders a non-root {{ _copier_conf.answers_file }}.jinja template to the destination root as .copier-answers.yml.

Copier 9.15.1 rendered the same answers-file template into the same nested destination directory where the template file lived. This changes the generated output path for existing templates that include .copier-answers.yml.jinja below the template root.

Template

This minimal template can be created locally with:

rm -rf /tmp/copier-answers-repro
mkdir -p /tmp/copier-answers-repro/template/nested/{{ project_name }}
cd /tmp/copier-answers-repro

cat > template/copier.yml <<'YAML'
project_name:
  type: str
  default: example-project
YAML

cat > 'template/nested/{{ project_name }}/.copier-answers.yml.jinja' <<'JINJA'
_commit: ''
_src_path: template
project_name: {{ project_name }}
JINJA

cat > 'template/nested/{{ project_name }}/README.md.jinja' <<'JINJA'
# {{ project_name }}
JINJA

To Reproduce

  1. Create the template above.
  2. Run Copier 9.15.1:
rm -rf /tmp/copier-answers-repro/output-9151
mkdir -p /tmp/copier-answers-repro/output-9151
cd /tmp/copier-answers-repro/output-9151
git init -q

uvx --from "copier==9.15.1" copier copy --trust --defaults --force \
  --data project_name=example-project \
  ../template .
  1. Check where the answers file was created:
test -f nested/example-project/.copier-answers.yml && echo "nested answers exists"
test ! -f .copier-answers.yml && echo "root answers absent"

Observed with 9.15.1:

nested answers exists
root answers absent
  1. Run Copier 9.15.2:
rm -rf /tmp/copier-answers-repro/output-9152
mkdir -p /tmp/copier-answers-repro/output-9152
cd /tmp/copier-answers-repro/output-9152
git init -q

uvx --from "copier==9.15.2" copier copy --trust --defaults --force \
  --data project_name=example-project \
  ../template .
  1. Check where the answers file was created:
test ! -f nested/example-project/.copier-answers.yml && echo "nested answers missing"
test -f .copier-answers.yml && echo "root answers exists"

Observed with 9.15.2:

nested answers missing
root answers exists

Logs

Expected behavior

The answers file should be rendered consistently with the previous Copier behavior, or the new behavior should require an explicit opt-in.

For the template above, I expected:

nested/example-project/.copier-answers.yml

I did not expect:

.copier-answers.yml

Screenshots/screencasts/logs

No response

Operating system

Linux

Operating system distribution and version

linux 6.12.91-1-MANJARO

Copier version

copier 9.15.2

Python version

Python 3.14.5

Installation method

uvx+pypi

Additional context

This appears related to the 9.15.2 answers-file path changes. The same template behaves differently across Copier versions:

  • Copier 9.15.1 renders the nested .copier-answers.yml.jinja file into the nested destination directory.
  • Copier 9.15.2 renders .copier-answers.yml at the destination root instead.

The exact behavioral change
Removed _adjust_rendered_part(), which used to turn a full rendered answers path into just the filename so the file could land in the template’s subdirectory:

[Commit d76195a — deletion of _adjust_rendered_part](d76195a#diff-8b8e8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8The breaking change is in copier-org/copier#2186, specifically commit d76195a in copier/_main.py.

The exact behavioral change
Removed _adjust_rendered_part(), which used to strip a full rendered answers path down to just the filename so nested templates could place the file under a subdirectory:

commit d76195a — deletion of _adjust_rendered_part

The diff hunk is around lines 1040–1057 in that commit view.

Replaced with an early yield of self.answers_relpath (default .copier-answers.yml at repo root) whenever the rendered path matches the answers file:

if str(self.answers_relpath) == rendered_part:
yield self.answers_relpath, new_context
continue
and:

if str(self.answers_relpath) == rendered_part:
yield (self.answers_relpath, extra_context)
return

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugtriageTrying to make sure if this is valid or not

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions