Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
182 changes: 182 additions & 0 deletions .github/workflows/images.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
name: Build ROOT Images

on:
workflow_dispatch:
inputs:
dry_run:
description: "Discover and update metadata without pushing images or committing README changes"
required: false
type: boolean
default: false
force_rebuild:
description: "Rebuild release images even when the GHCR tag already exists"
required: false
type: boolean
default: false
schedule:
- cron: "37 2 * * *"
pull_request:
paths:
- ".github/workflows/images.yml"
- "README.md"
- "scripts/**"
- "tests/**"

permissions:
contents: read

env:
REGISTRY: ghcr.io
IMAGE_NAMESPACE: root-project
IMAGE_NAME: root

jobs:
validate:
name: Validate automation
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v6

- name: Run actionlint
uses: rhysd/actionlint@v1.7.12

- name: Run unit tests
run: python -m unittest discover -s tests -v

discover:
name: Discover images
runs-on: ubuntu-latest
needs: validate
permissions:
contents: read
packages: read
outputs:
release_matrix: ${{ steps.plan.outputs.release_matrix }}
release_count: ${{ steps.plan.outputs.release_count }}
steps:
- name: Checkout repository
uses: actions/checkout@v6

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4

- name: Log in to GHCR
if: ${{ github.event_name != 'pull_request' && inputs.dry_run != true && github.ref_name == github.event.repository.default_branch }}
uses: docker/login-action@v4
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Discover release matrix
id: plan
env:
IMAGE: ${{ env.REGISTRY }}/${{ env.IMAGE_NAMESPACE }}/${{ env.IMAGE_NAME }}
run: |
args=(--image "$IMAGE" --plan-json build-plan.json --github-output "$GITHUB_OUTPUT")
if [[ "${{ github.event_name }}" != "pull_request" && "${{ inputs.dry_run }}" != "true" && "${{ inputs.force_rebuild }}" != "true" && "${{ github.ref_name }}" == "${{ github.event.repository.default_branch }}" ]]; then
args+=(--skip-existing)
fi
python scripts/root_images.py plan "${args[@]}"

- name: Print discovery summary
run: |
python - <<'PY'
import json
from pathlib import Path

plan = json.loads(Path("build-plan.json").read_text())
print(f"Image: {plan['image']}")
print(f"Release images to build: {len(plan['release_images'])}")
PY

build-release:
name: Build release image
runs-on: ubuntu-latest
needs: discover
if: ${{ github.event_name != 'pull_request' && inputs.dry_run != true && github.ref_name == github.event.repository.default_branch && needs.discover.outputs.release_count != '0' }}
timeout-minutes: 120
permissions:
contents: read
packages: write
strategy:
fail-fast: false
max-parallel: 3
matrix: ${{ fromJSON(needs.discover.outputs.release_matrix) }}
steps:
- name: Checkout repository
uses: actions/checkout@v6

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4

- name: Log in to GHCR
uses: docker/login-action@v4
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Build and push release image
uses: docker/build-push-action@v7
with:
context: ${{ matrix.context }}
file: ${{ matrix.dockerfile }}
pull: true
push: true
tags: ${{ join(matrix.tags, ',') }}
build-args: ${{ join(matrix.build_args, ',') }}
labels: |
org.opencontainers.image.source=https://github.com/${{ github.repository }}
org.opencontainers.image.revision=${{ github.sha }}
org.opencontainers.image.version=${{ matrix.root_version }}

- name: Smoke test release image
run: docker run --rm "${{ matrix.primary_tag }}" root-config --version

publish-metadata:
name: Publish README metadata
runs-on: ubuntu-latest
needs:
- discover
- build-release
if: >-
${{
always() &&
github.event_name != 'pull_request' &&
inputs.dry_run != true &&
github.ref_name == github.event.repository.default_branch &&
needs.discover.result == 'success' &&
(needs.build-release.result == 'success' || needs.build-release.result == 'skipped')
}}
permissions:
contents: write
steps:
- name: Checkout repository
uses: actions/checkout@v6
with:
ref: ${{ github.ref_name }}

- name: Regenerate README image metadata
id: plan
env:
IMAGE: ${{ env.REGISTRY }}/${{ env.IMAGE_NAMESPACE }}/${{ env.IMAGE_NAME }}
run: |
python scripts/root_images.py plan \
--image "$IMAGE" \
--plan-json build-plan.json
python scripts/root_images.py update-readme --plan-json build-plan.json

- name: Commit README update
run: |
if git diff --quiet README.md; then
echo "README image metadata is already up to date"
exit 0
fi

git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git add README.md
git commit -m "Update ROOT image metadata"
git push
91 changes: 82 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,82 @@ Maintained by: [the ROOT team](https://root.cern/) and collaborators

Where to get help: [the ROOT forum](https://root-forum.cern.ch/)

## Supported tags and respective Dockerfile links

### Latest images
## GHCR images

<!-- BEGIN ROOT-GHCR-IMAGES -->

Images built by the GitHub Actions automation are published to GHCR.

Pull the latest supported stable release with:

```
docker pull ghcr.io/root-project/root:latest
```

### Active release images

| Image tag | ROOT tag | Dockerfile |
| --- | --- | --- |
| `ghcr.io/root-project/root:6.38.04-ubuntu24.04` | `v6-38-04` | [ubuntu2404/Dockerfile](https://github.com/root-project/root-docker/blob/master/ubuntu2404/Dockerfile) |
| `ghcr.io/root-project/root:6.38.02-ubuntu24.04` | `v6-38-02` | [ubuntu2404/Dockerfile](https://github.com/root-project/root-docker/blob/master/ubuntu2404/Dockerfile) |
| `ghcr.io/root-project/root:6.38.00-ubuntu24.04` | `v6-38-00` | [ubuntu2404/Dockerfile](https://github.com/root-project/root-docker/blob/master/ubuntu2404/Dockerfile) |
| `ghcr.io/root-project/root:6.36.12-ubuntu24.04` | `v6-36-12` | [ubuntu2404/Dockerfile](https://github.com/root-project/root-docker/blob/master/ubuntu2404/Dockerfile) |
| `ghcr.io/root-project/root:6.36.10-ubuntu24.04` | `v6-36-10` | [ubuntu2404/Dockerfile](https://github.com/root-project/root-docker/blob/master/ubuntu2404/Dockerfile) |
| `ghcr.io/root-project/root:6.36.08-ubuntu24.04` | `v6-36-08` | [ubuntu2404/Dockerfile](https://github.com/root-project/root-docker/blob/master/ubuntu2404/Dockerfile) |
| `ghcr.io/root-project/root:6.36.06-ubuntu24.04` | `v6-36-06` | [ubuntu2404/Dockerfile](https://github.com/root-project/root-docker/blob/master/ubuntu2404/Dockerfile) |
| `ghcr.io/root-project/root:6.36.04-ubuntu24.04` | `v6-36-04` | [ubuntu2404/Dockerfile](https://github.com/root-project/root-docker/blob/master/ubuntu2404/Dockerfile) |
| `ghcr.io/root-project/root:6.36.02-ubuntu24.04` | `v6-36-02` | [ubuntu2404/Dockerfile](https://github.com/root-project/root-docker/blob/master/ubuntu2404/Dockerfile) |
| `ghcr.io/root-project/root:6.36.00-ubuntu24.04` | `v6-36-00` | [ubuntu2404/Dockerfile](https://github.com/root-project/root-docker/blob/master/ubuntu2404/Dockerfile) |
| `ghcr.io/root-project/root:6.34.10-ubuntu24.04` | `v6-34-10` | [ubuntu2404/Dockerfile](https://github.com/root-project/root-docker/blob/master/ubuntu2404/Dockerfile) |
| `ghcr.io/root-project/root:6.34.08-ubuntu24.04` | `v6-34-08` | [ubuntu2404/Dockerfile](https://github.com/root-project/root-docker/blob/master/ubuntu2404/Dockerfile) |
| `ghcr.io/root-project/root:6.34.06-ubuntu24.04` | `v6-34-06` | [ubuntu2404/Dockerfile](https://github.com/root-project/root-docker/blob/master/ubuntu2404/Dockerfile) |
| `ghcr.io/root-project/root:6.34.04-ubuntu24.04` | `v6-34-04` | [ubuntu2404/Dockerfile](https://github.com/root-project/root-docker/blob/master/ubuntu2404/Dockerfile) |
| `ghcr.io/root-project/root:6.34.02-ubuntu24.04` | `v6-34-02` | [ubuntu2404/Dockerfile](https://github.com/root-project/root-docker/blob/master/ubuntu2404/Dockerfile) |
| `ghcr.io/root-project/root:6.34.00-ubuntu24.04` | `v6-34-00` | [ubuntu2404/Dockerfile](https://github.com/root-project/root-docker/blob/master/ubuntu2404/Dockerfile) |
| `ghcr.io/root-project/root:6.32.22-ubuntu24.04` | `v6-32-22` | [ubuntu2404/Dockerfile](https://github.com/root-project/root-docker/blob/master/ubuntu2404/Dockerfile) |
| `ghcr.io/root-project/root:6.32.20-ubuntu24.04` | `v6-32-20` | [ubuntu2404/Dockerfile](https://github.com/root-project/root-docker/blob/master/ubuntu2404/Dockerfile) |
| `ghcr.io/root-project/root:6.32.18-ubuntu24.04` | `v6-32-18` | [ubuntu2404/Dockerfile](https://github.com/root-project/root-docker/blob/master/ubuntu2404/Dockerfile) |
| `ghcr.io/root-project/root:6.32.16-ubuntu24.04` | `v6-32-16` | [ubuntu2404/Dockerfile](https://github.com/root-project/root-docker/blob/master/ubuntu2404/Dockerfile) |
| `ghcr.io/root-project/root:6.32.14-ubuntu24.04` | `v6-32-14` | [ubuntu2404/Dockerfile](https://github.com/root-project/root-docker/blob/master/ubuntu2404/Dockerfile) |
| `ghcr.io/root-project/root:6.32.12-ubuntu24.04` | `v6-32-12` | [ubuntu2404/Dockerfile](https://github.com/root-project/root-docker/blob/master/ubuntu2404/Dockerfile) |
| `ghcr.io/root-project/root:6.32.10-ubuntu24.04` | `v6-32-10` | [ubuntu2404/Dockerfile](https://github.com/root-project/root-docker/blob/master/ubuntu2404/Dockerfile) |
| `ghcr.io/root-project/root:6.32.08-ubuntu24.04` | `v6-32-08` | [ubuntu2404/Dockerfile](https://github.com/root-project/root-docker/blob/master/ubuntu2404/Dockerfile) |
| `ghcr.io/root-project/root:6.32.06-ubuntu24.04` | `v6-32-06` | [ubuntu2404/Dockerfile](https://github.com/root-project/root-docker/blob/master/ubuntu2404/Dockerfile) |
| `ghcr.io/root-project/root:6.32.04-ubuntu24.04` | `v6-32-04` | [ubuntu2404/Dockerfile](https://github.com/root-project/root-docker/blob/master/ubuntu2404/Dockerfile) |
| `ghcr.io/root-project/root:6.32.02-ubuntu24.04` | `v6-32-02` | [ubuntu2404/Dockerfile](https://github.com/root-project/root-docker/blob/master/ubuntu2404/Dockerfile) |
| `ghcr.io/root-project/root:6.32.00-ubuntu24.04` | `v6-32-00` | [ubuntu2404/Dockerfile](https://github.com/root-project/root-docker/blob/master/ubuntu2404/Dockerfile) |
| `ghcr.io/root-project/root:6.30.10-ubuntu24.04` | `v6-30-10` | [ubuntu2404/Dockerfile](https://github.com/root-project/root-docker/blob/master/ubuntu2404/Dockerfile) |
| `ghcr.io/root-project/root:6.30.08-ubuntu22.04` | `v6-30-08` | [ubuntu2204/Dockerfile](https://github.com/root-project/root-docker/blob/master/ubuntu2204/Dockerfile) |
| `ghcr.io/root-project/root:6.30.06-ubuntu22.04` | `v6-30-06` | [ubuntu2204/Dockerfile](https://github.com/root-project/root-docker/blob/master/ubuntu2204/Dockerfile) |
| `ghcr.io/root-project/root:6.30.04-ubuntu22.04` | `v6-30-04` | [ubuntu2204/Dockerfile](https://github.com/root-project/root-docker/blob/master/ubuntu2204/Dockerfile) |
| `ghcr.io/root-project/root:6.30.02-ubuntu22.04` | `v6-30-02` | [ubuntu2204/Dockerfile](https://github.com/root-project/root-docker/blob/master/ubuntu2204/Dockerfile) |
| `ghcr.io/root-project/root:6.28.14-ubuntu24.04` | `v6-28-14` | [ubuntu2404/Dockerfile](https://github.com/root-project/root-docker/blob/master/ubuntu2404/Dockerfile) |
| `ghcr.io/root-project/root:6.28.12-ubuntu22.04` | `v6-28-12` | [ubuntu2204/Dockerfile](https://github.com/root-project/root-docker/blob/master/ubuntu2204/Dockerfile) |
| `ghcr.io/root-project/root:6.28.10-ubuntu22.04` | `v6-28-10` | [ubuntu2204/Dockerfile](https://github.com/root-project/root-docker/blob/master/ubuntu2204/Dockerfile) |
| `ghcr.io/root-project/root:6.26.18-ubuntu22.04` | `v6-26-18` | [ubuntu2204/Dockerfile](https://github.com/root-project/root-docker/blob/master/ubuntu2204/Dockerfile) |
| `ghcr.io/root-project/root:6.26.16-ubuntu22.04` | `v6-26-16` | [ubuntu2204/Dockerfile](https://github.com/root-project/root-docker/blob/master/ubuntu2204/Dockerfile) |
| `ghcr.io/root-project/root:6.26.14-ubuntu22.04` | `v6-26-14` | [ubuntu2204/Dockerfile](https://github.com/root-project/root-docker/blob/master/ubuntu2204/Dockerfile) |
| `ghcr.io/root-project/root:6.25.01-ubuntu20.04` | `v6-25-01` | [ubuntu20/Dockerfile](https://github.com/root-project/root-docker/blob/master/ubuntu20/Dockerfile) |
| `ghcr.io/root-project/root:6.24.08-ubuntu20.04` | `v6-24-08` | [ubuntu20/Dockerfile](https://github.com/root-project/root-docker/blob/master/ubuntu20/Dockerfile) |
| `ghcr.io/root-project/root:6.24.06-ubuntu20.04` | `v6-24-06` | [ubuntu20/Dockerfile](https://github.com/root-project/root-docker/blob/master/ubuntu20/Dockerfile) |
| `ghcr.io/root-project/root:6.24.04-ubuntu20.04` | `v6-24-04` | [ubuntu20/Dockerfile](https://github.com/root-project/root-docker/blob/master/ubuntu20/Dockerfile) |
| `ghcr.io/root-project/root:6.24.02-ubuntu20.04` | `v6-24-02` | [ubuntu20/Dockerfile](https://github.com/root-project/root-docker/blob/master/ubuntu20/Dockerfile) |
| `ghcr.io/root-project/root:6.24.00-ubuntu20.04` | `v6-24-00` | [ubuntu20/Dockerfile](https://github.com/root-project/root-docker/blob/master/ubuntu20/Dockerfile) |
| `ghcr.io/root-project/root:6.23.01-ubuntu20.04` | `v6-23-01` | [ubuntu20/Dockerfile](https://github.com/root-project/root-docker/blob/master/ubuntu20/Dockerfile) |
| `ghcr.io/root-project/root:6.22.08-ubuntu20.04` | `v6-22-08` | [ubuntu20/Dockerfile](https://github.com/root-project/root-docker/blob/master/ubuntu20/Dockerfile) |
| `ghcr.io/root-project/root:6.22.06-ubuntu20.04` | `v6-22-06` | [ubuntu20/Dockerfile](https://github.com/root-project/root-docker/blob/master/ubuntu20/Dockerfile) |
| `ghcr.io/root-project/root:6.22.02-ubuntu20.04` | `v6-22-02` | [ubuntu20/Dockerfile](https://github.com/root-project/root-docker/blob/master/ubuntu20/Dockerfile) |
| `ghcr.io/root-project/root:6.22.00-ubuntu20.04` | `v6-22-00` | [ubuntu20/Dockerfile](https://github.com/root-project/root-docker/blob/master/ubuntu20/Dockerfile) |
| `ghcr.io/root-project/root:6.20.08-ubuntu20.04` | `v6-20-08` | [ubuntu20/Dockerfile](https://github.com/root-project/root-docker/blob/master/ubuntu20/Dockerfile) |
| `ghcr.io/root-project/root:6.20.06-ubuntu20.04` | `v6-20-06` | [ubuntu20/Dockerfile](https://github.com/root-project/root-docker/blob/master/ubuntu20/Dockerfile) |

`ghcr.io/root-project/root:latest` points to `6.38.04-ubuntu24.04`.

<!-- END ROOT-GHCR-IMAGES -->

## Legacy Docker Hub tags and Dockerfile links

### Latest legacy image

* [`latest`](https://github.com/root-project/root-docker/blob/6.38.00-ubuntu25.10/ubuntu2510/Dockerfile) -> [`6.38.00-ubuntu25.10`](https://github.com/root-project/root-docker/blob/6.38.00-ubuntu25.10/ubuntu2510/Dockerfile)

Expand Down Expand Up @@ -45,15 +118,15 @@ Different images provide ROOT installations built with different C++ standards.
The ROOT team provides several Docker images. In order to run containers, you must [have Docker installed](https://www.docker.com/community-edition#/download).
You can start a container by running the following command in your terminal which will start the latest stable release of ROOT:
```
docker run --rm -it rootproject/root
docker run --rm -it ghcr.io/root-project/root:latest
```
Note that the `--rm` flag tells Docker to remove the container, together with its data, once it is shut down. In order to persist data, it is recommended to mount a directory on the container. For example, to mount your home directory on Linux and Mac, run:
```
docker run --rm -it -v ~:/userhome --user $(id -u) rootproject/root
docker run --rm -it -v ~:/userhome --user $(id -u) ghcr.io/root-project/root:latest
```
On Windows, you have to specify the full path to your user directory:
```
docker run --rm -it -v C:\\Users\\Username:/userhome rootproject/root
docker run --rm -it -v C:\\Users\\Username:/userhome ghcr.io/root-project/root:latest
```

The `-v` option tells Docker to mount the home directory (`~`) to `/userhome` in the container. `--user $(id -u)` signs us in with the same userid as in the host in order to allow reading/writing to the mounted directory. This is not necessary on Windows. Mac and Windows users does however have to mark the drives or areas they want to mount as shared in the Docker application under settings.
Expand All @@ -67,7 +140,7 @@ The `-v` option tells Docker to mount the home directory (`~`) to `/userhome` in
To use graphics, make sure you are in an X11 session and run the following command:

```
docker run -e DISPLAY=$DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix --rm -it --user $(id -u) rootproject/root root
docker run -e DISPLAY=$DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix --rm -it --user $(id -u) ghcr.io/root-project/root:latest root
```

On some platforms (e.g., Arch Linux) connections to the X server must be allowed explicitly by executing `xhost local:root` or an equivalent command (see e.g. [this page](https://wiki.archlinux.org/index.php/Xhost) for more information on `xhost` and its possible security implications).
Expand All @@ -83,15 +156,15 @@ xhost + $ip
```
This will start XQuartz and whitelist your local IP address. Finally, you can start up ROOT with the following command:
```
docker run --rm -it -v /tmp/.X11-unix:/tmp/.X11-unix -e DISPLAY=$ip:0 rootproject/root root
docker run --rm -it -v /tmp/.X11-unix:/tmp/.X11-unix -e DISPLAY=$ip:0 ghcr.io/root-project/root:latest root
```

##### Windows
To enable graphics, you must have [Xming](https://sourceforge.net/projects/xming/) installed. Make sure Xming is whitelisted in the Windows firewall when prompted. After installing Xming, white-list the IP-address of the Docker containers in Xming by running the following command in PowerShell as administrator:
``Add-Content 'C:\Program Files (x86)\Xming\X0.hosts' "`r`n10.0.75.2"``
Restart Xming and start the container with the following command:
```
docker run --rm -it -e DISPLAY=10.0.75.1:0 rootproject/root
docker run --rm -it -e DISPLAY=10.0.75.1:0 ghcr.io/root-project/root:latest
```

## Examples
Expand Down
1 change: 1 addition & 0 deletions scripts/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"""Project-local automation scripts."""
Loading