Skip to content

Contributing to ECMWF Sites

This page is the path for a new contributor: set up the workspace, make a change that passes the gates, and land it. Platform architecture is in the other design documents; start with 01-overview.

Development environment

Requirements: uv, Python 3.13, Go (the toolchain pinned in site/src/ecmwf/sites/website/applications/api/go.mod), lua 5.4 (the proxy Lua modules are unit-tested), Bash 5 for the shell helper tests, and git. Docker and Helm are needed only for the local-dev deployment path (18-local-development).

uv venv --python 3.13
uv sync --all-packages --all-groups   # or: make init-workspace
make test                             # Python + Go + Lua suites

Run a single layer with unittest discover or go test, as mapped in 20-testing. make test refuses to run without lua on PATH.

Dependabot and Renovate open weekly update pull requests, each held back by a seven-day cooldown. Use make dependency-update-check to list newer Python, Go, and Hub frontend packages, and make dependency-update to apply the ones older than that cooldown. A Python update also rewrites the exact pins of the member pyproject.toml files, so its diff touches those files. Review the diff, then run make test and make dependency-audit in the same pull request. See 15 — Makefile entrypoints.

Licensing and file headers

The project is Apache-2.0 (LICENSE, NOTICE). Every tracked file carries the SPDX header block:

# SPDX-FileCopyrightText: 2019-2026 European Centre for Medium-Range Weather Forecasts (ECMWF)
# SPDX-License-Identifier: Apache-2.0

Markdown and HTML use the comment form of the same two lines. REUSE.toml lists the files that cannot carry a header (generated data, binary assets). Keep the years of existing files unchanged; new files use the current year. Copied code from other projects must keep its upstream licence and be recorded in NOTICE. The dockerfile-policy helper test enforces licence collection in images (see 20-testing); make dependency-audit reports licence-relevant advisories as warnings.

Making a change

  1. Branch from main (features destined for the release) or the current develop branch. One change per pull request; keep the commit subject in the feat: / fix: / docs: / chore: style used in the history.
  2. Code style: Python follows the repository ruff configuration; JavaScript in the Hub and proxy pages follows the surrounding file's style; Go follows gofmt (enforced by the Go toolchain).
  3. Write or update tests. Every behaviour table in the design documents lists a Verified by column; when you change a requirement, update the row and its test in the same pull request. New requirements get a new, never-reused ID in the owning document's prefix family.
  4. Update the documentation in the same pull request. The table "Where to look when changing behaviour" in the design README maps code areas to documents. When you change a Hub or Site route, update the matching OpenAPI spec file; hub/tests/test_api_spec_coverage.py fails otherwise.
  5. Changelog: add your change under a ## Version <next> section of CHANGELOG.md when the release notes should mention it. The section becomes the GitHub release text (15 — Releases).

Automated coding agents that work in this repository read AGENTS.md at the repository root. That file sets their documentation language and edit rules. It does not replace this guide.

Pull requests and CI

  • Pull requests run the CI workflow (make test) and the advisory Security workflow. See 15 — Continuous integration.
  • Pull requests from forks do not run until a maintainer adds the approved-for-ci label; this is a safety gate, not a review gate (15 — Fork pull request policy).
  • Merge into develop for integration; develop images publish after CI passes (15 — develop.yml). main is the release line.
  • Version bumps are a release activity, not a per-PR rule: the release manager sets VERSION with make set-version (01-overview).

Documentation rules

  • Audience split: docs/end-user/ (no Kubernetes detail), docs/sys-admin/ (operators), docs/design/ (implemented behaviour only, with requirement tables).
  • Infrastructure that the cluster provides (DNS records, TLS certificates, storage classes, the Ingress or Gateway data plane) is written as a choice: the cluster integration or the operator's manual process. Never write it as a bare instruction that assumes manual work. The chart creates no DNS records and no TLS Secret.
  • Write in ASD-STE100 Simplified Technical English: short sentences, one instruction per step, present tense, no idioms.
  • Pages above roughly 350 lines are split into a directory with an index.md plus sub-pages; the index.md carries the behaviour requirements table for the set. Add every new page to the nav list in utilities/release/docs/zensical.toml.
  • Broken internal links and anchors fail the strict Zensical build, a page missing from the navigation fails check-docs-nav (run first by make build-docs), and docs_stage.py fails the build when a repository link is broken (15 — Documentation site).

Reporting problems

  • Bugs and feature requests: GitHub issues on ecmwf/ecmwf-sites.
  • Security vulnerabilities: report privately per SECURITY.md at the repository root — never open a public issue. Supported versions: the latest release only.
  • Citing the platform: use the metadata in CITATION.cff.
  • Support scope: ECMWF supports the ECMWF production Sites service only. An operator that installs the platform on its own infrastructure supports its own users.