Skip to content
Merged
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
83 changes: 83 additions & 0 deletions .github/workflows/docker.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
name: Build and Push Docker Image to GHCR

on: push
Copy link

@psafont psafont Sep 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does the workflow do anything if it's not on master branch? I would rather limit the branches where it's run here rather than doing it per-step, now there are 4 places where this branch limitation needs to be placed (6 when the 9.0 is enabled, which is ripe for errors)

Copy link
Member Author

@glehmann glehmann Sep 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It builds the image on all the branches, but only uploads when on master


permissions:
contents: read # Required to checkout the repo code
packages: write # Required to push packages to GHCR

jobs:
xcp-ng-build-env-82:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: docker/setup-buildx-action@v3
with:
driver: docker-container
- uses: docker/login-action@v3
if: github.ref == 'refs/heads/master'
with:
registry: ghcr.io
username: ${{ github.actor }} # Uses the GitHub user/org name that triggered the workflow
password: ${{ secrets.GITHUB_TOKEN }} # Automatically provided by GitHub
- uses: docker/build-push-action@v5 # Using v5 for latest features
with:
context: ./src/xcp_ng_dev/
file: ./src/xcp_ng_dev/files/Dockerfile-8.x
push: ${{ github.ref == 'refs/heads/master' }}
tags: ghcr.io/${{ github.repository }}:8.2
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We likely want those official floating tags to be set only when run on master, maybe we set particular tags for PRs?
Also, timestamped tags as is common may be interesting to have.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The workflow is only configured on master.
Other tags may be useful, as well as building for PRs, but we must consider cleaning up the old images.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The workflow is only configured on master.

Actually it seems to be configured for main instead :)

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, there would be a reason for allowing it to run not just on master: detecting pipeline errors before they reach master

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, that would be nice. Maybe push to the registry when on the master branch then.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, there would be a reason for allowing it to run not just on master: detecting pipeline errors before they reach master

This comes at the cost of extra complexity: all steps now have a branch check.

I'm surprised that the push action doesn't support logging in, or use protected deployments

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a bit more complex not to upload, but we spare the complexity to clean up temporary images.
It seems like a good compromise to me—your opinion may vary, of course

cache-from: type=gha,scope=${{ github.ref_name }}-82 # Cache layers to speed up builds
cache-to: type=gha,mode=max,scope=${{ github.ref_name }}-82 # Store layers in cache for future builds
build-args: |
XCP_NG_BRANCH=8.2
platforms: |
linux/amd64
xcp-ng-build-env-83:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: docker/setup-buildx-action@v3
with:
driver: docker-container
- uses: docker/login-action@v3
if: github.ref == 'refs/heads/master'
with:
registry: ghcr.io
username: ${{ github.actor }} # Uses the GitHub user/org name that triggered the workflow
password: ${{ secrets.GITHUB_TOKEN }} # Automatically provided by GitHub
- uses: docker/build-push-action@v5 # Using v5 for latest features
with:
context: ./src/xcp_ng_dev/
file: ./src/xcp_ng_dev/files/Dockerfile-8.x
push: ${{ github.ref == 'refs/heads/master' }}
tags: ghcr.io/${{ github.repository }}:8.3
cache-from: type=gha,scope=${{ github.ref_name }}-83 # Cache layers to speed up builds
cache-to: type=gha,mode=max,scope=${{ github.ref_name }}-83 # Store layers in cache for future builds
platforms: |
linux/amd64
# TODO: uncomment once we have a public xcp-ng 9.0 repository
# xcp-ng-build-env-90:
# runs-on: ubuntu-latest
# steps:
# - uses: actions/checkout@v4
# - uses: docker/setup-buildx-action@v3
# with:
# driver: docker-container
# - uses: docker/login-action@v3
# if: github.ref == 'refs/heads/master'
# with:
# registry: ghcr.io
# username: ${{ github.actor }} # Uses the GitHub user/org name that triggered the workflow
# password: ${{ secrets.GITHUB_TOKEN }} # Automatically provided by GitHub
# - uses: docker/build-push-action@v5 # Using v5 for latest features
# with:
# context: ./src/xcp_ng_dev/
# file: ./src/xcp_ng_dev/files/Dockerfile-9.x
# platforms: |
# linux/amd64/v2
# push: ${{ github.ref == 'refs/heads/master' }}
# tags: ghcr.io/${{ github.repository }}:9.0
# cache-from: type=gha,scope=${{ github.ref_name }}-90 # Cache layers to speed up builds
# cache-to: type=gha,mode=max,scope=${{ github.ref_name }}-90 # Store layers in cache for future builds
26 changes: 0 additions & 26 deletions src/xcp_ng_dev/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,6 @@ fi

cd $(dirname "$0")

CUSTOM_ARGS=()

ALMA_VERSION=
CENTOS_VERSION=
case "$1" in
Expand All @@ -81,38 +79,14 @@ case "$1" in
DOCKERFILE=files/Dockerfile-8.x
: ${PLATFORM:=linux/amd64}
;;
7.*)
DOCKERFILE=Dockerfile-7.x
: ${PLATFORM:=linux/amd64}
;;
*)
echo >&2 "Unsupported release '$1'"
exit 1
;;
esac

CUSTOM_UID="$(id -u)"
CUSTOM_GID="$(id -g)"

if [ "${CUSTOM_UID}" -eq 0 ] || [ "${CUSTOM_GID}" -eq 0 ]; then
if [ -z "${SUDO_GID}" ] || [ -z "${SUDO_UID}" ] || [ -z "${SUDO_USER}" ] || \
[ -z "${SUDO_COMMAND}" ] || [ "${SUDO_GID}" -eq 0 ] || [ "${SUDO_UID}" -eq 0 ]; then
echo -e "[ERROR] This operation cannot be performed by the 'root' user directly:"
echo -e "\tplease use an unprivileged user (eventually with 'sudo')"
exit 1
fi
CUSTOM_UID="${SUDO_UID}"
CUSTOM_GID="${SUDO_GID}"
fi

# Support for seamless use of current host user
# and Docker user "builder" inside the image
CUSTOM_ARGS+=( "--build-arg" "CUSTOM_BUILDER_UID=${CUSTOM_UID}" )
CUSTOM_ARGS+=( "--build-arg" "CUSTOM_BUILDER_GID=${CUSTOM_GID}" )

"$RUNNER" build \
--platform "$PLATFORM" \
"${CUSTOM_ARGS[@]}" \
-t ghcr.io/xcp-ng/xcp-ng-build-env:${1} \
--build-arg XCP_NG_BRANCH=${1} \
--ulimit nofile=1024 \
Expand Down
14 changes: 10 additions & 4 deletions src/xcp_ng_dev/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,11 +144,17 @@ def buildparser():
return parser

def container(args):
docker_args = [RUNNER, "run", "-i", "-t",
"-u", "builder",
]
docker_args = [RUNNER, "run", "-i", "-t"]

if is_podman(RUNNER):
docker_args += ["--userns=keep-id", "--security-opt", "label=disable"]
# With podman we use the `--userns` option to map the builder user to the user on the system.
# The container will start with that user and not as root as with docker
docker_args += ["--userns=keep-id:uid=1000,gid=1000", "--security-opt", "label=disable"]
else:
# With docker, the container starts as root and modify the builder user in the entrypoint to
# match the uid:gid of the user launching the container, and then continue with the builder
# user thanks to gosu.
docker_args += ["-e", f'BUILDER_UID={os.getuid()}', "-e", f'BUILDER_GID={os.getgid()}']

# common args
if args.no_exit:
Expand Down
78 changes: 0 additions & 78 deletions src/xcp_ng_dev/files/Dockerfile-7.x

This file was deleted.

65 changes: 26 additions & 39 deletions src/xcp_ng_dev/files/Dockerfile-8.x
Original file line number Diff line number Diff line change
Expand Up @@ -2,38 +2,32 @@ ARG CENTOS_VERSION=7.5.1804

FROM centos:${CENTOS_VERSION}

ARG CUSTOM_BUILDER_UID=""
ARG CUSTOM_BUILDER_GID=""

# Remove all repositories
RUN rm /etc/yum.repos.d/*

# Add only the specific CentOS 7.5 repositories, because that's what XS used for the majority of packages
ARG CENTOS_VERSION
COPY files/CentOS-Vault.repo.in /etc/yum.repos.d/CentOS-Vault-7.5.repo
RUN sed -e "s/@CENTOS_VERSION@/${CENTOS_VERSION}/g" -i /etc/yum.repos.d/CentOS-Vault-7.5.repo
RUN sed -i -e "s/@CENTOS_VERSION@/${CENTOS_VERSION}/g" /etc/yum.repos.d/CentOS-Vault-7.5.repo

# Add our repositories
# Repository file depends on the target version of XCP-ng, and is pre-processed by build.sh
ARG XCP_NG_BRANCH=8.3
COPY files/xcp-ng.repo.8.x.in /etc/yum.repos.d/xcp-ng.repo
RUN sed -e "s/@XCP_NG_BRANCH@/${XCP_NG_BRANCH}/g" -i /etc/yum.repos.d/xcp-ng.repo
RUN sed -i -e "s/@XCP_NG_BRANCH@/${XCP_NG_BRANCH}/g" /etc/yum.repos.d/xcp-ng.repo

# Install GPG key
RUN curl -sSf https://xcp-ng.org/RPM-GPG-KEY-xcpng -o /etc/pki/rpm-gpg/RPM-GPG-KEY-xcpng

# Fix invalid rpmdb checksum error with overlayfs, see https://github.com/docker/docker/issues/10180
# (still needed?)
RUN yum install -y yum-plugin-ovl

# Use priorities so that packages from our repositories are preferred over those from CentOS repositories
RUN yum install -y yum-plugin-priorities

# Update
RUN yum update -y

# Common build requirements
RUN yum install -y \
RUN yum update -y \
# Fix invalid rpmdb checksum error with overlayfs, see https://github.com/docker/docker/issues/10180
# (still needed?)
&& yum install -y yum-plugin-ovl \
# Use priorities so that packages from our repositories are preferred over those from CentOS repositories
&& yum install -y yum-plugin-priorities \
# Common build requirements
&& yum install -y \
gcc \
gcc-c++ \
git \
Expand All @@ -44,37 +38,30 @@ RUN yum install -y \
sudo \
yum-utils \
epel-release \
epel-rpm-macros

# Niceties
RUN yum install -y \
epel-rpm-macros \
# Niceties
&& yum install -y \
vim \
wget \
which

# clean package cache to avoid download errors
RUN yum clean all
which \
# clean package cache to avoid download errors
&& yum clean all

# OCaml in XS may be older than in CentOS
RUN sed -i "/gpgkey/a exclude=ocaml*" /etc/yum.repos.d/Cent* /etc/yum.repos.d/epel*

# Set up the builder user
RUN bash -c ' \
OPTS=(); \
if [ -n "${CUSTOM_BUILDER_UID}" ]; then \
OPTS+=("-u" "${CUSTOM_BUILDER_UID}"); \
fi; \
if [ -n "${CUSTOM_BUILDER_GID}" ]; then \
OPTS+=("-g" "${CUSTOM_BUILDER_GID}"); \
if ! getent group "${CUSTOM_BUILDER_GID}" >/dev/null; then \
groupadd -g "${CUSTOM_BUILDER_GID}" builder; \
fi; \
fi; \
useradd "${OPTS[@]}" builder; \
' \
# create the builder user
RUN groupadd -g 1000 builder \
&& useradd -u 1000 -g 1000 builder \
&& echo "builder:builder" | chpasswd \
&& echo "builder ALL=(ALL:ALL) NOPASSWD: ALL" >> /etc/sudoers

RUN mkdir -p /usr/local/bin
RUN curl -fsSL "https://github.com/tianon/gosu/releases/download/1.17/gosu-amd64" -o /usr/local/bin/gosu \
&& chmod +x /usr/local/bin/gosu
COPY files/init-container.sh /usr/local/bin/init-container.sh
COPY files/rpmmacros /home/builder/.rpmmacros
COPY files/entrypoint.sh /usr/local/bin/entrypoint.sh
COPY --chown=builder:builder files/rpmmacros /home/builder/.rpmmacros

ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]
CMD ["bash"]
Loading