Skip to content

Commit 8dbbad8

Browse files
committed
fix: Check renovate ignores template-managed Dockerfile base images
Add a test that the renovate config shipped to downstream projects disables updates for every base image in the generated Dockerfile, and clarify this in the renovate how-to.
1 parent c35e85e commit 8dbbad8

2 files changed

Lines changed: 38 additions & 2 deletions

File tree

‎docs/how-to/renovate.md‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22

33
[Renovate](https://github.com/apps/renovate) is a tool for automating dependency updates. It is used to:
44
- Automatically update the [uv lock file](./lock-requirements.md) and automerge if tests pass
5-
- Update any dependencies in the Dockerfile
6-
- Update the versions of any GitHub actions not manager by the python-copier-template
5+
- Update any dependencies in the Dockerfile, apart from the base images managed by the python-copier-template
6+
- Update the versions of any GitHub actions not managed by the python-copier-template
77

88
## Install the Renovate GitHub app
99

‎tests/test_example.py‎

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,42 @@ def test_renovate_actions_match_what_is_shipped(override: dict, tmp_path: Path):
370370
assert used_github_actions == config_github_actions
371371

372372

373+
@pytest.mark.parametrize("docker", [False, True])
374+
def test_renovate_dockerfile_base_images_match_what_is_shipped(
375+
docker: bool, tmp_path: Path
376+
):
377+
# Generate a project with the given answers
378+
copy_project(tmp_path, docker=docker)
379+
# Find the Dockerfile base images ignored by renovate
380+
renovate_config_path = tmp_path / "renovate.json"
381+
renovate_config = json.loads(renovate_config_path.read_text())
382+
dockerfile_rules = [
383+
rule
384+
for rule in renovate_config["packageRules"]
385+
if rule.get("matchManagers") == ["dockerfile"]
386+
]
387+
assert len(dockerfile_rules) == 1
388+
rule = dockerfile_rules[0]
389+
# The rule must disable every update type (tags and digests), not just one
390+
assert rule["enabled"] is False
391+
assert "matchUpdateTypes" not in rule
392+
config_base_images = set(rule["matchDepNames"])
393+
# Find the base images actually used in the Dockerfile
394+
stages = set[str]()
395+
used_base_images = set[str]()
396+
for line in (tmp_path / "Dockerfile").read_text().splitlines():
397+
words = line.split()
398+
if words and words[0] == "FROM":
399+
image = words[1]
400+
if image not in stages:
401+
used_base_images.add(image.split("@")[0].split(":")[0])
402+
if len(words) > 3 and words[2] == "AS":
403+
stages.add(words[3])
404+
# Check every base image in the Dockerfile is covered by the rule
405+
assert used_base_images
406+
assert used_base_images <= config_base_images
407+
408+
373409
def test_python_versions_match(tmp_path: Path):
374410
copy_project(tmp_path)
375411
# Grab the python versions from ci.yml

0 commit comments

Comments
 (0)