Base container recipes and automated build infrastructure for UFS Chemistry (UFS-Chem).
ufs-chem-container provides the authoritative, decoupled base environment container images used across the Unified Forecast System (UFS) Chemistry ecosystem. Container recipes and automated build workflows are maintained centrally to ensure cross-platform reproducibility, streamline dependency management, and eliminate redundant Spack build pipelines across downstream atmospheric and chemistry modeling workflows.
docker/Dockerfile.ufschem-spack-base-ubuntu-gcc-13: Ubuntu 24.04 base container environment built with the GCC 13 toolchain, Rust, and a pre-configured spack-stack environment for UFS Chemistry modeling applications.
Images are hosted on Docker Hub under the noaaepic organization at noaaepic/ufschem-spack-base-ubuntu-gcc-13-dev. The organization namespace is configured via repository secret DOCKER_ORG:
| Branch / Context | Image Name | Tags | Purpose |
|---|---|---|---|
main |
ufschem-spack-base-ubuntu-gcc-13 |
<version> (e.g. 0.2.0), latest |
Stable production base image |
develop |
ufschem-spack-base-ubuntu-gcc-13-dev |
<version>-rc.X (e.g. 0.2.0-rc.2), latest |
Prerelease release candidate |
PR with sandbox-build |
ufschem-spack-base-ubuntu-gcc-13-sandbox |
<sandbox-version> (e.g. 7.7.7-rc.1) |
Temporary sandbox image for external application testing prior to merge |
Note: Prerelease builds on
developupdate the:latesttag on the-devrepository (<image>-dev:latest). Production builds onmainupdate:lateston the production repository. Sandbox builds on PRs omit the:latesttag to prevent collisions across concurrent pull requests.
To pull pre-built images for downstream modeling or integration testing:
-
Production release:
docker pull noaaepic/ufschem-spack-base-ubuntu-gcc-13:latest # or specific version: docker pull noaaepic/ufschem-spack-base-ubuntu-gcc-13:0.2.0 -
Prerelease candidate:
docker pull noaaepic/ufschem-spack-base-ubuntu-gcc-13-dev:0.2.0-rc.2
-
Sandbox test build:
docker pull noaaepic/ufschem-spack-base-ubuntu-gcc-13-sandbox:7.7.7-rc.1
Recipe changes may need to be tested by an external application (such as downstream UFS modeling workflows or integration test suites) before merging into develop. Pull requests can trigger temporary sandbox builds published to Docker Hub:
- Apply Label: Add the
sandbox-buildlabel to the Pull Request. - Specify Version Tag: Include
sandbox-version=<version>on its own line in the Pull Request description (body). For example:sandbox-version=7.7.7-rc.1
- Validation: If a PR is labeled with
sandbox-buildbut does not include a validsandbox-version=on its own line in the PR description, the CI workflow will raise an error and abort immediately. - Repository Destination & Caching: The image is published strictly to
${DOCKER_ORG}/<image-name>-sandbox:<sandbox-version>. Sandbox builds do not push a:latesttag to eliminate collisions across concurrent pull requests; subsequent builds on the same PR reuse layer cache directly from<image-name>-sandbox:<sandbox-version>. - Branch Isolation: Sandbox images are never built or pushed on
developormainbranches. They exist solely for pre-merge testing during PR review. - Pulling the Sandbox Image: External applications can pull and execute the sandbox image using:
docker pull noaaepic/ufschem-spack-base-ubuntu-gcc-13-sandbox:7.7.7-rc.1
The GitHub Actions workflows require the following repository-level secrets when publishing images (all Docker configuration is managed via repository secrets with no defaults):
- Repository Secrets:
DOCKER_ORG: Docker Hub organization / namespace (noaaepic).DOCKER_USERNAME: Docker Hub account username with write permissions tonoaaepic.DOCKERHUB_TOKEN: Docker Hub Personal Access Token (PAT) with read/write permissions fornoaaepic.SEMVER_APP_ID: GitHub App Client ID (or App ID) for automated semantic release. Requires branch ruleset bypass permissions (bypass_actors) for protected branches (develop,main).SEMVER_APP_PRIVATE_KEY: GitHub App private key (.pem) for automated semantic release and branch protection bypass.
Pull requests originating from external forks run in GitHub's restricted security context where repository secrets are withheld:
- Credential Verification Isolation: Credential verification jobs across workflows are automatically skipped when running outside
ufs-community/ufs-chem-container, preventing false failures and eliminating runner resource consumption on forks. - Local Container Build Verification: The
build-testjob runs cleanly on fork PRs. If the Dockerfile changed, it builds with Docker Buildx and verifies local registry push (localhost:5000) with public layer cache fallbacks. - Semantic Release Preview: The preview workflow evaluates the PR title and generates projected release diffs using
github.tokenfallback, gracefully skipping App token verification. - Sandbox Builds: Publishing sandbox test containers to Docker Hub requires write secrets and must be triggered from internal branches within
ufs-community/ufs-chem-container.
A dedicated verification workflow (.github/workflows/verify-secrets.yml) runs on a daily cron schedule (0 6 * * * at 06:00 UTC) and can be triggered on demand via workflow_dispatch in the authoritative upstream repository. It continuously verifies:
- Docker Hub login and registry push permissions for all target repositories (
ufschem-spack-base-ubuntu-gcc-13,ufschem-spack-base-ubuntu-gcc-13-dev, andufschem-spack-base-ubuntu-gcc-13-sandbox). - GitHub App token acquisition, repository write permissions, Git ref operations, and branch ruleset bypass permissions on
developandmain.
Compiling the Spack-based container environment requires 35–45 minutes of runner execution. To maximize developer velocity and minimize compute consumption, workflows incorporate intelligent change detection:
- Workflows evaluate Git diffs (
origin/<base>...HEAD) for each Dockerfile defined in the build matrix. - Dockerfile Unchanged: Container compilation in
build-testis short-circuited entirely. An informational optimization report is published to$GITHUB_STEP_SUMMARYand the check completes in under 30 seconds. - Dockerfile Changed: The container image is compiled and verified against the runner's ephemeral local registry.
- If a pull request requests a sandbox build (
sandbox-buildlabel andsandbox-version=...), but the Dockerfile has not changed, the existing upstream image is re-tagged directly to${DOCKER_ORG}/${IMAGE_NAME}-sandbox:${SANDBOX_VERSION}usingdocker buildx imagetools create. - This publishes the sandbox test artifact in ~15 seconds without rebuilding. If the source image manifest is unavailable, the workflow automatically falls back to full compilation.
- When releases or prereleases are triggered upon merge to
developormain, the workflow inspects whether the Dockerfile changed since the preceding release tag (git describe --tags --abbrev=0 HEAD~1). - Dockerfile Unchanged: Avoids re-compilation. Existing OCI image manifests on Docker Hub are re-tagged directly in ~2–5 seconds with bit-for-bit cryptographic reproducibility (promoting
dev:latestto production or updating prerelease candidate tags). - Dockerfile Changed: Compiles the new container recipe and pushes updated tags via Docker Buildx. If registry manifest re-tagging encounters any errors, the workflow automatically falls back to full compilation.
This repository uses pre-commit orchestrated through uv for code hygiene, formatting, type checking, and conventional commit message validation.
uv sync --all-groups
uv run pre-commit install --hook-type pre-commit --hook-type commit-msguv run pre-commit run --all-filesSee .pre-commit-config.yaml for the list of configured checks.
Releases are fully automated via python-semantic-release (PSR) v10:
- Commits and PR titles must follow the Conventional Commits specification:
feat: ...→ bumps minor version (e.g.,0.1.0→0.2.0).fix: ...→ bumps patch version (e.g.,0.1.0→0.1.1).chore: ...,docs: ...,refactor: ...→ no version bump unless breaking change specified.feat!: ...orBREAKING CHANGE:→ bumps major version.
- Merges into
developpublish prerelease versions (0.1.0-rc.X) and push dev candidate container images. - Merges into
mainpublish formal releases (0.1.0), tag the Git commit, updateCHANGELOG.md, and push production images tagged with the release version andlatest.
Portions of this code were generated/augmented using agentic SI models and has been reviewed and validated consistent with NOAA's SI Statement.