In my previous blog post I described the setup I am using for keeping my quarkus testing app up to date.

I also use Ansible quite heavily, and there, execution environments are being used. On a very very very high level: think of virtual environments that are put into a container. For me that’s great news. Perosnally, I find containers containing everything which I need for my automation much easier to use and more importantly, to lifecycle. Proper versioning, and you know exatcly what you use in which environment.

Naturally, after having started to use the renovate bot, I wanted to check how I could use the bot to keep my EEs up to date. the dependabot has a long-standing RFE to add Ansible Galaxy as manageable dependency. So, even if I wanted to, at least for galaxy collection I can’t use dependabot.

So, let’s see hwo far we get with renovate.

The Dependencies

An Execution Environment is defined via yaml, ansible-builder pretty much translates it into a Containerfile + necessary other bits. Sure, I could just use the Containerfile + X, but I find the yaml definition of the EE so much easier to read and maintain that I want to stick to it, unless not possible otherwise.

Let’s examine one of my EEs I use in my homelab for automating against OpenShift. Note: This is built from scratch, hence I actually install ansible-core and ansible-runner by myself. Usually this is already included in the base image.

---
version: 3

images:
  base_image:
    name: quay.io/fedora/fedora:39@sha256:6222a53d90adacd6985400a0309f9d104fd8e29761aede5cdd2278034156c047
dependencies:
  ansible_core:
    package_pip: ansible-core==2.15.1
  ansible_runner:
    package_pip: ansible-runner==2.3.3
  python_interpreter:
    python_path: "/usr/bin/python3.11"
  galaxy: requirements.yml
  python: requirements.txt

We can easily the few deps there:

  • the base image
  • ansible-core
  • ansible-runner

Moving on to the requirements.yml, containing the collections I need:

collections:
  - name: kubernetes.core
    version: 2.4.0
  - name: community.okd
    version: 2.3.0

As you can see, I pin versions here as well. I am a fan of reproducability, so I do not like to just specify >=someversion. However that also means, keeping it updated, testing etc. needs to be a non-issue.

The next is the python dependencies. Same here, version pinning:

kubernetes==26.1.0

Yes, then there’s also the github workflow, but we’ve seen that already.

Instructing Renovate to Update the Base Image

ansible-galaxy and pip are standard dependencies that the renovate bot will detect. That’s great news, nothing to do.

However, the renovate bot has no idea what execution environments are. But since it’s so customizable, we can instruct it how to update these dependencies.

That’s the relevant config bit:

{
  "$schema": "https://docs.renovatebot.com/renovate-schema.json",
  "extends": [
    "local>jeichler/renovate-bot",
  ],
  "regexManagers": [
    {
      "description": "Update base image version in execution-environment.yml",
      "fileMatch": [
        "(^|/)execution-environment\\.yml$"
      ],
      "matchStrings": [
        "base_image:\\n\\s+name:\\s+(?<depName>[^:]*):(?<currentValue>[^\\s@]*)(@(?<currentDigest>sha256:[0-9a-f]*))?"
      ],
      "datasourceTemplate": "docker"
    },
    {
      "description": "Update package_pip versions in execution-environment.yml",
      "fileMatch": [
        "(^|/)execution-environment\\.yml$"
      ],
      "matchStrings": [
        "package_pip:[\\W]*(?<depName>.*?)?(===|~=|==|!=|<=|>=|<|>)(?<currentValue>.*?)[\\W]*\\n"
      ],
      "datasourceTemplate": "pypi"
    }
  ],
  "packageRules": [
    {
      "matchDatasources": ["docker"],
      "matchPaths": ["**/execution-environment.yml"],
      "pinDigests": true
    }
  ]
}

It’s pretty much just me trying to use regex (yes, I’m not great at it as you can see). It’s capturing the respective “missing” dependencies in the execution-environment.yaml.

For the base image, we instruct it to treat it as docker depenency, the ansible-core and ansible-runner versions are captured by the super ugly regex to tell it to use the pypi datasource. And, finally, I also want digest pinning on the custom docker dependency (the base image), hence the package rule.

Did I do a lot of trial and error? No. The renovate repo itself with their configs as well as the forum are a great source of information. Once you know the basics, it’s not hard to find a solution.