A container image with CLI tools commonly used by Konflux Tasks. Released to quay.io/konflux-ci/task-runner.
This project implements ADR-0046: Common Task Runner Image.
The Task Runner image consolidates multiple CLI tools into a single container image, simplifying Task creation and reducing the maintenance overhead of managing multiple tool-specific images.
You can use it directly as the runtime image for Konflux Tasks or as a base image for more specialized runner images.
See Installed-Software.md for the complete list of tools and their versions.
Note
In main, this file is always up to date with the latest commit.
To see the software installed in a specific version of the runner image,
switch to the corresponding version tag.
Tools must meet the following requirements for inclusion:
- Must be a standalone CLI tool
- Language runtimes are also acceptable (e.g. Python)
- Must be installable hermetically
- Must follow a versioning scheme (preferably semantic versioning)
- Should have release notes or a changelog
Tools are organized by installation method:
RPM packages use a lockfile-based approach for hermeticity and reproducibility.
Process:
-
Add the package name to
deps/rpm/rpms.in.yamlunder either:packages- for new packagesreinstallPackages- for packages already in the base image (we want control over their versions)
-
Regenerate the lockfile:
make rpms.lock.yaml
-
Regenerate auto-generated files:
devtool gen --all
The install-rpms.sh script reads the infile and the lockfile and automatically
installs the exact package versions specified.
If the tool is installable via go install, prefer this approach. Compared to
the submodule approach, this results in more accurate SBOMs.
Each tool has its own directory with go.mod/go.sum, which is crucial for independent
version management. Go's MVS
ensures we get the same versions of dependencies used upstream. Combining multiple
tools in one go.mod file would break that.
Process:
-
Create a directory under
deps/go-tools/with the tool name -
Inside, create
go.modandgo.sumthat reference the tool's CLI package. Example:mkdir deps/go-tools/cosign cd deps/go-tools/cosign go mod init github.com/konflux-ci/task-runner/deps/go-tools/cosign go get -tool github.com/sigstore/cosign/v3/cmd/cosign@v3.0.2 go mod tidyNote: Use
go get -tool(not justgo get). Specify the package with the CLI binary, which is often a sub-package of the module (e.g.github.com/sigstore/cosign/v3/cmd/cosign, notgithub.com/sigstore/cosign/v3). -
Add the tool to
install-tools.sh:install_tool <name> [version_ldflags_attribute]
The
version_ldflags_attributeinjects the version into the binary and is required for tools that use this approach (otherwise tests will fail when checking version output). To find the correct attribute, inspect the tool's upstream build process (often found in the Makefile or build scripts). -
Regenerate auto-generated files:
devtool gen --all
If the tool is not installable with go install, e.g. due to the use of replace
directives in the tool's go.mod or due to incorrectly formatted semver tags,
fall back to git submodules.
Process:
-
Add the submodule and check out a semver(-ish) tag:
cd deps/go-submodules git submodule add <repository-url> <tool-name> cd <tool-name> git checkout v1.2.3
-
In
.gitmodules, set thebranchfield to the current tag (Renovate uses this for updates). If the submodule doesn't use correct semver tags (likeoc), add corresponding Renovate configuration indevtool/renovate.pywith a custom versioning regex. -
Add build commands to
install-submodules.sh -
Regenerate auto-generated files:
devtool gen --all
Pip packages use a lockfile-based approach similar to RPM packages.
Direct dependencies go in requirements.in, and resolved transitive dependencies
go in requirements.txt. Konflux's Hermeto can pre-fetch pip packages from
requirements.txt for hermetic builds.
Because we re-build the packages from source rather than using pre-built wheels,
we also need a requirements-build.txt file listing the build dependencies. Both
of the requirements*.txt files can be auto-generated with make pip-requirements.
Process:
-
Add the package name to
deps/pip/requirements.in:awscli -
Regenerate
requirements.txtandrequirements-build.txtmake pip-requirements
-
Regenerate auto-generated files:
devtool gen --all
Konflux Tasks have come to depend on two crucial scripts:
- select-oci-auth, a workaround for tools that
do not handle containers-auth.json correctly (such as
orasandcosign) - retry for retrying commands, especially those that interact
with quay.io as this interaction can be rather unreliable
- Note: the image sets
RETRY_STOP_IF_STDERR_MATCHES=unauthorizedfor backwards compatibility with the original retry script, which would abort on 'unauthorized'
- Note: the image sets
While including arbitrary Bash scripts goes against the Criteria for tool inclusion, these two are so ubiquitous that, for practicality, the runner image has to include them.
They have, at least, become more legitimate standalone tools:
- They each have their own version and CHANGELOG.md
- They will be following semantic versioning
- They have tests (in
tests/local-tools)
These two are an exception to the rule. We don't intend to add more local tools.
- Python 3.12+
- uv (Python package manager)
- Podman
Initialize/update git submodules:
make submodulesCreate a virtual environment and install dependencies:
make venv
source .venv/bin/activateThe devtool CLI assists with common development tasks:
devtool ls # List all tools to be installed
devtool gen --all # Generate files (e.g. Installed-Software.md)Locally:
podman build -t task-runner .For production: we use Konflux CI. See the pipelines in .tekton/.
There are two types of tests:
- Tests for the built task-runner image
- Tests for local tools (in
tests/local-tools)
Run them all at once with:
pytestpytest --ignore=tests/local-toolsBy default, tests build the image and tag it localhost/task-runner:test.
To skip rebuilding and test an existing image, set the TEST_IMAGE environment
variable:
# Build once
podman build -t localhost/task-runner:latest .
# Run tests against the existing image
TEST_IMAGE=localhost/task-runner:latest pytest
# Set it in .env for persistent use (if you use direnv or similar shell integration)
echo 'TEST_IMAGE=localhost/task-runner:latest' >> .envTests automatically discover packages and their expected versions using the
code in devtool/software_list.py. If a new package isn't detected properly,
you may need to update the discovery logic there. You may also need to update
test configuration (e.g. version_arg_overrides in tests/test_installed_packages.py
for tools that don't support the standard --version flag).
pytest tests/local-toolsThese are tests for the tools in local-tools/. They execute the tools directly
on your machine and verify the expected behavior.
After modifying deps/rpm/rpms.in.yaml:
make rpms.lock.yamlThis uses rpm-lockfile-prototype to resolve and lock package versions.
- The version of the runner image is tracked in the VERSION file
- The Konflux build pipeline automatically sets the
org.opencontainer.image.versionannotation (and label as well) on the built image using our custom.tekton/tasks/get-build-params.yamlTask
- The Konflux build pipeline automatically sets the
- All notable changes are tracked in the CHANGELOG.md file
When making a new release, bump the version according to the first matching rule:
- Removed a tool / updated the major version of any tool -> bump the major version
- Added a new tool / updated the minor version of any tool -> bump the minor version
- Otherwise -> bump the patch version
To bump the version automatically based on the changes in installed software, use:
devtool prep-releaseThe tool will automatically update the VERSION file and output a markdown list with the changes since the last release. Include this list when updating CHANGELOG.md.
If there are no relevant changes to the installed software (i.e. the Installed-Software.md
file did not change), the tool will abort without doing any changes. In that case,
if you do want to do a release, please update the VERSION file manually and write
the changelog content yourself.
- Determine what has changed since last release and update the VERSION and CHANGELOG.md files accordingly (see above).
- Send a PR to update the version and changelog.
- Once merged, create the GitHub release as
v{version}(e.g.v0.1.0). In the release notes, just link the relevant heading in CHANGELOG.md. - Merging the PR will have triggered a Konflux on-push pipeline, which will automatically trigger a release to https://quay.io/konflux-ci/task-runner upon success. Verify that the build and release succeed.