Container images built from upstream sources or custom Dockerfiles, published to GitHub Container Registry with automated security scanning and SLSA provenance.
See DEVELOPMENT.md for development environment setup.
Pull an image:
docker pull ghcr.io/anthony-spruyt/chrony:latestVersions are owned by release-please. See docs/releases.md.
-
Create a directory named after the image, containing a
Dockerfile. -
Register the image in
release-please-config.jsonand.release-please-manifest.json. -
Add a build job to
.github/workflows/release-please.yamland add the image to theimagechoice list in.github/workflows/rebuild-release.yaml.
Merging a conventional commit that touches the directory then opens a release PR; merging that cuts the tag and publishes the image.
To share another image's sources but use your own Dockerfile, add a metadata.yaml setting build_context:
build_context: llm-guardCustom MegaLinter flavors extend official flavors with additional linters. The megalinter-factory/ directory contains tooling to generate flavor files from a simple configuration.
The /create-megalinter-flavor command automates flavor creation with automatic base flavor selection:
# With specific linters
/create-megalinter-flavor my-ci ACTION_ACTIONLINT,MARKDOWN_MARKDOWNLINT,BASH_SHELLCHECK
# Interactive mode (prompts for linter selection)
/create-megalinter-flavor my-ciThe command will:
- Validate the flavor name and check for conflicts
- Look up linter configurations from the catalog
- Auto-select the optimal base flavor (minimizing custom installs)
- Generate
megalinter-<name>/flavor.yamlwith Renovate annotations
-
Create a directory for your flavor:
mkdir megalinter-<name>/
-
Create
flavor.yamlwith your configuration:name: my-flavor description: "MegaLinter for my use case" # renovate: datasource=docker depName=oxsecurity/megalinter-ci_light upstream_image: "oxsecurity/megalinter-ci_light:v9.3.0@sha256:..." custom_linters: - ACTION_ACTIONLINT - MARKDOWN_MARKDOWNLINT - PYTHON_BANDIT
-
Commit
flavor.yaml- CI generates Dockerfile and test.sh, then builds automatically
Linter information is extracted directly from MegaLinter's descriptors at build time. The generator automatically fetches the latest versions from https://github.com/oxsecurity/megalinter/tree/main/megalinter/descriptors.
Linter versions are automatically extracted from MegaLinter at build time - no manual tracking needed. The weekly scheduled rebuild workflow picks up any new linter versions.
For the base image, Renovate tracks the upstream MegaLinter version:
# renovate: datasource=docker depName=oxsecurity/megalinter-ci_light
upstream_image: "oxsecurity/megalinter-ci_light:v9.3.0@sha256:..."When Renovate creates a PR updating flavor.yaml, CI regenerates the Dockerfile and builds.
To test locally, generate files first:
pip install pyyaml jinja2
python megalinter-factory/generate.py megalinter-<name>/Generated files (Dockerfile, test.sh) are regenerated by CI at build time.
CI builds but never pushes. Every publish goes through release-please — see docs/releases.md.
Pushing changes to Dockerfile, flavor.yaml, assets/, metadata.yaml, or .rebuild-stamp builds the affected images. Changes to megalinter-factory/ build all flavors. Publishing happens when the resulting release PR merges.
Trigger a build with no push via workflow_dispatch:
curl -X POST \
-H "Authorization: token $GITHUB_TOKEN" \
-H "Accept: application/vnd.github.v3+json" \
https://api.github.com/repos/anthony-spruyt/container-images/actions/workflows/ci.yaml/dispatches \
-d '{"ref":"main","inputs":{"image":"chrony"}}'To republish a release whose build failed after tagging, use the Rebuild Release workflow instead.
Renovate updates dependencies inside an image (base images, packages). The resulting commit lands on main and release-please cuts a patch release for that image.
Image versions themselves are never set by Renovate; they live in .release-please-manifest.json.
For upstream sources Renovate cannot monitor, an n8n workflow can watch the source and open an issue. See chrony/n8n-release-watcher.json, which tracks the Alpine chrony package.
See SECURITY.md for security policy and controls.