From d7c8dc5d42ba2780f772607fd48eddcf2a7b27c9 Mon Sep 17 00:00:00 2001 From: David Davis Date: Fri, 12 Jun 2026 13:23:07 -0400 Subject: [PATCH] Fix missing cookiecutter bootstrap error Also add a cookiecutter bootstrap test. Assisted-By: GitHub Copilot (Claude) Closes #1428 --- .github/workflows/pr.yml | 22 ++++++++++++++++++++++ CHANGES/1428.bugfix | 1 + cookiecutter/ci/hooks/post_gen_project.py | 11 ++++++++--- 3 files changed, 31 insertions(+), 3 deletions(-) create mode 100644 CHANGES/1428.bugfix diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 742e2457f..3cd588c00 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -30,6 +30,27 @@ jobs: needs: - "lint" uses: "./.github/workflows/codeql.yml" + cookiecutter-bootstrap-check: + runs-on: "ubuntu-latest" + steps: + - name: "Checkout" + uses: "actions/checkout@v6" + with: + fetch-depth: 0 + - name: "Set up Python" + uses: "actions/setup-python@v6" + with: + python-version: "3.14" + allow-prereleases: true + - name: "Install uv" + uses: "astral-sh/setup-uv@v7" + with: + enable-cache: true + - name: "Bootstrap template sanity check" + run: | + tmpdir="$(mktemp -d)" + pushd "$tmpdir" + yes "" | uv run "$GITHUB_WORKSPACE/cookiecutter/apply_templates.py" --bootstrap check-commits: runs-on: "ubuntu-latest" steps: @@ -69,6 +90,7 @@ jobs: - "test" - "docs" - "codeql" + - "cookiecutter-bootstrap-check" if: "always()" steps: - name: "Collect needed jobs results" diff --git a/CHANGES/1428.bugfix b/CHANGES/1428.bugfix new file mode 100644 index 000000000..ac4388416 --- /dev/null +++ b/CHANGES/1428.bugfix @@ -0,0 +1 @@ +Fixed cookiecutter bootstrap error caused by a missing [tool] section in pyproject.toml.update during template merge. \ No newline at end of file diff --git a/cookiecutter/ci/hooks/post_gen_project.py b/cookiecutter/ci/hooks/post_gen_project.py index 75f845b09..791aaf4ea 100644 --- a/cookiecutter/ci/hooks/post_gen_project.py +++ b/cookiecutter/ci/hooks/post_gen_project.py @@ -17,7 +17,11 @@ # TODO How deep is your merge? # Is merging on the tool level appropriate? - pyproject_toml["tool"].update(pyproject_toml_update["tool"]) + if "tool" in pyproject_toml_update: + if "tool" not in pyproject_toml: + pyproject_toml["tool"] = pyproject_toml_update["tool"] + else: + pyproject_toml["tool"].update(pyproject_toml_update["tool"]) if "dependency-groups" in pyproject_toml_update: if "dependency-groups" not in pyproject_toml: @@ -26,8 +30,9 @@ pyproject_toml["dependency-groups"].update(pyproject_toml_update["dependency-groups"]) # Remove legacy tools. - for tool in ["flake8", "black", "isort"]: - pyproject_toml["tool"].pop(tool, None) + if "tool" in pyproject_toml: + for tool in ["flake8", "black", "isort"]: + pyproject_toml["tool"].pop(tool, None) with open(os.path.join(base_path, "pyproject.toml"), "w") as fp: tomlkit.dump(pyproject_toml, fp)