Skip to content

Makefile entrypoints

The platform build, test, audit, and publishing entrypoints live in the root Makefile. The workflows call these targets instead of repeating logic in YAML. Workflow triggers and gates are in Continuous integration and Releases.

Makefile entrypoints used by workflows

The workflows intentionally reuse a small set of Makefile targets:

make init-workspace
make hub-assets
make test
make fuzz-go [FUZZTIME=<duration>]
make dependency-audit
make dependency-audit-python
make dependency-audit-go
make dependency-audit-npm
make dependency-audit-fix
make dependency-update-check [-python|-go|-npm]
make dependency-update [-python|-go|-npm]
make check-lockstep-version
make print-version
make publish-images IMAGE_TAG=<tag>
make publish-helm CHART_VERSION=<semver> [IMAGE_TAG=<tag>]
make publish IMAGE_TAG=<tag> [CHART_VERSION=<semver>]
make publish-develop
make release
make release-notes
make build-docs
make publish-docs
make check-docs-nav

Their roles are:

Target Purpose
make init-workspace Set up the uv workspace and install test requirements. If npm is installed, also run make hub-assets.
make hub-assets Install the Hub frontend packages with npm ci --ignore-scripts from hub/frontend/package-lock.json, then copy the files in hub/frontend/vendor-files.json to the Hub static/vendor directory (git-ignored). Requires Node.js 24 and network access to the npm registry.
make test Run the Python test suites for core, hub, operator, and site, including Lua-backed tests, and run the Go API tests.
make fuzz-go [FUZZTIME=<duration>] Run each Go fuzz target of the Site API (FuzzParseContentRange, FuzzResolveRootPath) with generated inputs for FUZZTIME. A failing input fails the target and is written to api/testdata/fuzz/. make test runs only the seed inputs.
make dependency-audit Run the Python, Go, and Hub frontend dependency audits in this order. Report findings as warnings. Fail if a scan cannot run.
make dependency-audit-python Export the frozen workspace lockfile and run pip-audit==2.10.1 with --disable-pip --no-deps --strict. Findings are warnings.
make dependency-audit-go Run govulncheck@v1.9.0 on the Go API module. Findings are warnings.
make dependency-audit-npm Run npm audit --package-lock-only on hub/frontend/package-lock.json. Findings are warnings.
make dependency-audit-fix Apply targeted Python, Go module, and Go toolchain fixes, then run the Python and Go audits. Local use only; the workflows do not call it.
make dependency-update-check Run the Python, Go, and Hub frontend update checks in this order. List the newer packages. Change nothing. A package with an update is not a failure; only a tool that cannot run is, and one such tool does not hide the report of the other two. Local use only; the workflows do not call it.
make dependency-update-check-python List each exact pyproject.toml pin with a newer release within the cooldown, naming the file that holds it. Then run uv lock --upgrade --dry-run --exclude-newer <cutoff> and list the lockfile changes it reports.
make dependency-update-check-go Run go list -m -u -json all and list each module that go.mod requires with a newer version within the cooldown. List the modules that wait for the cooldown or need a manual change separately.
make dependency-update-check-npm Run npm outdated --json --before <cutoff> in hub/frontend and list each package with a newer version.
make dependency-update Run the three update targets in order. Local use only; the workflows do not call it.
make dependency-update-python Rewrite each pin that has a newer release within the cooldown with uv add --frozen, then apply the checked lockfile changes with uv lock --upgrade and a plain uv lock. Run make init-workspace to install the result.
make dependency-update-go Apply the checked module updates with go get and go mod tidy. Never changes the go or toolchain directives.
make dependency-update-npm Rewrite each exact pin in hub/frontend/package.json with npm install --save-exact --ignore-scripts, then run make hub-assets. Review hub/frontend/vendor-files.json when a copied file name changes.
make check-lockstep-version Verify that the Python packages, the Helm chart version and appVersion, and the chart images.tag match VERSION.
make print-version Print the version read from VERSION. publish-develop, release, and release.yml use it.
make publish-images IMAGE_TAG=<tag> Build and push all container images with the provided tag.
make publish-helm CHART_VERSION=<semver> [IMAGE_TAG=<tag>] Copy the chart to a local build directory, set images.tag in the copy to IMAGE_TAG (default: CHART_VERSION), lint, package, and push the chart to oci://$(SITES_PRIVATE_REGISTRY)/$(SITES_PRIVATE_REGISTRY_PROJECT).
make publish IMAGE_TAG=<tag> [CHART_VERSION=<semver>] Run publish-images and publish-helm. CHART_VERSION defaults to IMAGE_TAG.
make publish-develop Publish develop images and the <VERSION>-develop chart. The chart copy is set to use the develop images (images.tag is rewritten by publish-helm).
make release Verify lockstep versioning, read VERSION, then publish all release images and the chart with that version.
make release-notes Print the CHANGELOG.md section for the version in VERSION. Fails if the section is missing or empty.
make build-docs Check the documentation navigation (check-docs-nav), then stage the docs/ pages and build them as HTML with the locked docs dependency group (Zensical). Links to repository files outside docs/ point to the source at DOCS_SOURCE_REF (default main). Needs no credentials.
make check-docs-nav Fail when a page under docs/ is missing from the nav list in utilities/release/docs/zensical.toml, or a nav entry has no file on disk. Runs first in make build-docs and make publish-docs.
make publish-docs Check the documentation navigation (check-docs-nav), then build the site and upload the generated HTML with sitesctl to the sites site in the docs space, at /. Needs DOCS_BASE_URL (https:// URL) and DOCS_TOKEN. It uses separate CLI settings, passes the token in the environment, overwrites files, and deletes nothing. DOCS_SPACE and DOCS_SITE change the destination.

Helm chart versions must be SemVer. The develop image tag is not a valid chart version, thus the develop chart uses the <VERSION>-develop pre-release version.

Makefile variables

These variables tune the targets. The workflow jobs set some of them; the rest are local overrides.

Variable Default Used by
VERSION_FILE VERSION print-version, release, check-lockstep-version
UV_PYTHON 3.13 init-workspace
SITES_PRIVATE_REGISTRY eccr.ecmwf.int image and chart publishing
SITES_PRIVATE_REGISTRY_PROJECT sites-oss image and chart publishing
IMAGE_PLATFORM linux/amd64 publish-images — build platform for the images
HELM_CHART_DIR helm/ecmwf-sites publish-helm
HELM_BUILD_DIR dist/helm publish-helm — chart copy destination
AUDIT_RUNNER uv run --no-project --python $(UV_PYTHON) python dependency-audit targets — command that runs audit tools
AUDIT_FIX_RUNNER same as AUDIT_RUNNER dependency-audit-fix
UPDATE_RUNNER same as AUDIT_RUNNER dependency-update targets — command that runs utilities/release/dependency_updates.py
DEPENDENCY_COOLDOWN_DAYS 7 dependency-update targets — newest release an update may select, counted back from now. Passed to the helper in the environment. 0 allows every current release.
FUZZTIME 30s fuzz-go — time for each fuzz target (a Go duration, or <n>x for a number of inputs)

Dependency updates

Dependabot updates the uv, Go module, npm, GitHub Actions, and Docker ecosystems, and Renovate updates site/proxy.Dockerfile. Both run weekly with a seven-day cooldown. The dependency-update targets cover the same ground on demand, for example before a release. They use the same cooldown, so they do not select a release that Dependabot would still hold back.

utilities/release/dependency_updates.py implements both actions for one ecosystem:

uv run --no-project --python 3.13 python utilities/release/dependency_updates.py {check|update} {python|go|npm}

The check action runs the tool in report mode and writes nothing. The update action runs the same tool again to apply what the report lists, so it applies no surprise. Both actions print the release cutoff they used.

A Python dependency lives in two places. Each member pyproject.toml file pins its direct dependencies with ==, and uv lock --upgrade cannot move such a pin. The tool therefore reads every pin, asks uv pip compile for the newest release that the cooldown allows, rewrites the pin in place with uv add --frozen, and then re-locks uv.lock. The final plain uv lock removes the cutoff that a bounded lock records in uv.lock; it changes no version, so a later uv sync leaves the file alone. A pin that already holds the newest allowed release is not rewritten, and a requirement with a range keeps its range. uv add needs a package name to select a manifest, so the tool lists a pin of the workspace file for a manual change.

An update covers dependency files only. It does not run the tests, the audits, or the license checks, and it does not open a pull request. Docker image pins, the declared Go go and toolchain directives, and the pinned audit tool versions are out of scope. The Go part covers the modules that go.mod requires. go list -m -u all also reports a module that only the module graph needs, with no line in go.mod; an update would add such a line, and go mod tidy would remove it again, so the tool leaves that module to the one that asks for it. Review the diff, run make test and make dependency-audit, then commit the result on a branch.

Release-note extraction (make release-notes → utilities/release/changelog-notes.sh) prints the CHANGELOG.md section for the version in VERSION. Pass a version argument to select another section, and set CHANGELOG_FILE to read another changelog:

./utilities/release/changelog-notes.sh 2.6.0
CHANGELOG_FILE=/tmp/CHANGELOG.md ./utilities/release/changelog-notes.sh