container-images/.github/workflows/build-test-push.yml
Yuriy Kohut 077ca2b38d Implement root file-system extracting from images.
Remove "Collect and save changed Containerfile(s) used by Docker Official Library" job from the "Build, test and push to the Client Library" workflow.
It is now part of the "Deploy version_major images_type images" job.

Update README.md.
2024-04-10 18:45:37 +03:00

368 lines
13 KiB
YAML

name: Build, test and push to the Client Library
on:
workflow_dispatch:
inputs:
production:
description: |
'Push to production registries'
'not checked - to testing'
required: true
type: boolean
default: false
version_major:
description: 'AlmaLinux major version'
required: true
default: '9'
type: choice
options:
- 9
- 8
type_default:
description: 'default'
required: true
type: boolean
default: true
type_minimal:
description: 'minimal'
required: true
type: boolean
default: true
type_micro:
description: 'micro'
required: true
type: boolean
default: true
type_base:
description: 'base'
required: true
type: boolean
default: true
type_init:
description: 'init'
required: true
type: boolean
default: true
env:
# Latest version
version_latest: 9
# Platforms list: linux/amd64, linux/ppc64le, linux/s390x, linux/arm64
platforms: 'linux/amd64, linux/ppc64le, linux/s390x, linux/arm64'
# Registries list:
# for production: docker.io/almalinux, quay.io/almalinuxorg, ghcr.io/almalinux
# for testing: quay.io/almalinuxautobot
registries: ${{ inputs.production && 'docker.io/almalinux, quay.io/almalinuxorg, ghcr.io/almalinux' || 'quay.io/almalinuxautobot, ghcr.io/almalinux' }}
jobs:
build-test-push:
name: Deploy ${{ inputs.version_major }} ${{ matrix.image_types }} images
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
# Set image types matrix based on boolean inputs.type_* with true value
image_types: ${{ fromJSON(format('["{0}", "{1}", "{2}", "{3}", "{4}"]', ( inputs.type_default && 'default' ), ( inputs.type_minimal && 'minimal' ), ( inputs.type_micro && 'micro' ), ( inputs.type_base && 'base' ), ( inputs.type_init && 'init' ) )) }}
exclude:
- image_types: 'false'
steps:
-
name: Prepare AlmaLinux Minor version number
run: |
case ${{ inputs.version_major }} in
8)
version_minor="9" ;;
9)
version_minor="3" ;;
10)
version_minor="0" ;;
*)
echo "Almalinux ${{ inputs.version_major }} is not supported!" && false
esac
echo "version_minor=${version_minor}" >> $GITHUB_ENV
# [Debug]
echo "version_minor=${version_minor}"
-
name: Prepare date stamp
id: date_stamp
run: |
# date stamp
date_stamp=$(date -u '+%Y%m%d')
echo "date_stamp=${date_stamp}" >> $GITHUB_ENV
echo "date_stamp=${date_stamp}" >> "$GITHUB_OUTPUT"
[ -z "$date_stamp-x" ] && false
# [Debug]
echo "date_stamp=${date_stamp}"
-
name: Generate list of images to use as base name for tags
run: |
# list of registries to push to
REGISTRIES="${{ env.registries }}"
IMAGE_NAMES=
# generate image names in format $REGISTRY/almalinux or $REGISTRY/${{ inputs.version_major }}-${{ matrix.image_types }}
# image names are used by docker/metadata-action to set 'images'
for REGISTRY in ${REGISTRIES//,/ }; do
# 'default' images should not go to docker.io
[ "${{ matrix.image_types }}" = "default" ] && [[ $REGISTRY = *'docker.io'* ]] && continue
# 'default' images goes to $REGISTRY/almalinux
[ "${{ matrix.image_types }}" = "default" ] \
&& IMAGE_NAME="$REGISTRY/almalinux" \
|| IMAGE_NAME="$REGISTRY/${{ inputs.version_major }}-${{ matrix.image_types }}"
IMAGE_NAMES="${IMAGE_NAMES} ${IMAGE_NAME}"
unset IMAGE_NAME
done
# remove space at the beginning of string
IMAGE_NAMES=${IMAGE_NAMES# }
# separate with comma instead of space and export to the action
echo "IMAGE_NAMES=${IMAGE_NAMES// /,}" >> $GITHUB_ENV
# [Debug]
echo $IMAGE_NAMES
-
name: Enable containerd image store on Docker Engine
run: |
# Use containerd image store
sudo jq '.features |= . + { "containerd-snapshotter": true }' /etc/docker/daemon.json > ./daemon.json.${{ env.date_stamp }} && \
sudo mv -f ./daemon.json.${{ env.date_stamp }} /etc/docker/daemon.json
sudo systemctl restart docker
docker info -f '{{ .DriverStatus }}'
-
name: Checkout ${{ github.repository }}, branch 'main'
uses: actions/checkout@v4
-
name: Checkout ${{ github.repository }}, branch 'docker-library', path '${{ inputs.version_major }}'
uses: actions/checkout@v4
with:
ref: ${{ inputs.version_major }}
path: ${{ inputs.version_major }}
-
name: Set up QEMU
uses: docker/setup-qemu-action@v3
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
-
name: Login to Docker.io
if: contains(env.registries, 'docker.io')
uses: docker/login-action@v3
with:
registry: docker.io
username: ${{ inputs.production && secrets.DOCKERHUB_USERNAME || secrets.TEST_DOCKERHUB_USERNAME }}
password: ${{ inputs.production && secrets.DOCKERHUB_TOKEN || secrets.TEST_DOCKERHUB_TOKEN }}
-
name: Login to Quay.io
if: contains(env.registries, 'quay.io')
uses: docker/login-action@v3
with:
registry: quay.io
username: ${{ inputs.production && secrets.QUAY_IO_USERNAME || secrets.TEST_QUAY_IO_USERNAME }}
password: ${{ inputs.production && secrets.QUAY_IO_CLI_PASSWORD || secrets.TEST_QUAY_IO_CLI_PASSWORD }}
-
name: Login to Ghcr.io
if: contains(env.registries, 'ghcr.io')
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ inputs.production && secrets.GIT_HUB_USERNAME || secrets.TEST_GITHUB_USERNAME }}
password: ${{ inputs.production && secrets.GIT_HUB_TOKEN || secrets.TEST_GITHUB_TOKEN }}
-
name: Generate tags and prepare metadata to build and push
id: meta
uses: docker/metadata-action@v5
with:
# list of Docker images to use as base names for tags
images: ${{ env.IMAGE_NAMES }}
# list of tags
tags: |
type=raw,value=latest,enable=${{ matrix.image_types != 'default' || ( matrix.image_types == 'default' && inputs.version_major == env.version_latest ) }}
type=raw,value=${{ inputs.version_major }},enable=true
type=raw,value=${{ inputs.version_major }}.${{ env.version_minor }},enable=true
type=raw,value=${{ inputs.version_major }}.${{ env.version_minor }}-${{ env.date_stamp }},enable=true
-
name: Build images
id: build-images
uses: docker/build-push-action@v5
with:
provenance: false
context: "{{defaultContext}}:Containerfiles/${{ inputs.version_major }}"
file: ./Containerfile.${{ matrix.image_types }}
platforms: ${{ env.platforms }}
push: false
load: true
tags: ${{ steps.meta.outputs.tags }}
-
name: Test images
id: test-images
run: |
# [Test]
platforms="${{ env.platforms }}"
for platform in ${platforms//,/ }; do
echo "Testing AlmaLinux ${{ inputs.version_major }} ${{ matrix.image_types }} for ${platform} image:"
docker run --platform=${platform} ${{ steps.build-images.outputs.digest }} /bin/bash -c " \
uname -m \
&& cat /etc/almalinux-release \
&& ( test "${{ matrix.image_types }}" != "micro" && rpm -q gpg-pubkey) || true "
done
-
name: Push images to Client Library
id: push-images
uses: docker/build-push-action@v5
with:
provenance: false
context: "{{defaultContext}}:Containerfiles/${{ inputs.version_major }}"
file: ./Containerfile.${{ matrix.image_types }}
platforms: ${{ env.platforms }}
push: true
tags: ${{ steps.meta.outputs.tags }}
-
name: Extract RootFS (default and minimal only)
id: extract-rootfs
# 'default' or 'minimal' images only go to Docker Official Library
if: matrix.image_types == 'default' || matrix.image_types == 'minimal'
run: |
# [RootFS]
# File name for RootFS file (packed with tag + Xz)
name=almalinux-${{ inputs.version_major }}-${{ matrix.image_types }}
pwd=$( pwd )
path=${pwd}/${name}
# The "tar file" for 'docker save' to write to
tar_name=${pwd}/${name}.tar
mkdir ${path}
cd ${path}
# Produce a tarred repository and save it to the "tar file".
docker save ${{ steps.build-images.outputs.digest }} -o ${tar_name}
# Extract the "tar file"
tar xf ${tar_name}
cd blobs/sha256
# The "temporary Dockerfile" to build image based on RootFS
cat <<EOF > Dockerfile
FROM scratch
ADD rootfs.tar.gz /
CMD ["/bin/bash"]
EOF
# Loop blobs to find all zipped files that are RootFS for a particular architecture
for file in `find . -type f`; do
if file --brief ${file} | grep -i gzip >/dev/null; then
# Make a copy of "taken RootFS"
cp -av ${file} rootfs.tar.gz
# Build an image from the "temporary Dockerfile"
docker build -t rootfs .
# Run the image and query almalinux-release package's architecture
arch=$( docker run --rm rootfs /bin/bash -c "rpm -q --qf=%{ARCH} almalinux-release" )
# Map found architecture to the corresponding platform
platform=
docker rmi rootfs
case ${arch} in
x86_64)
platform=amd64;;
ppc64le)
platform=ppc64le;;
s390x)
platform=s390x;;
aarch64)
platform=arm64;;
*)
echo "The '$arch' is incorrect or failed to determine architecture." && false;;
esac
# Delete copy of the "taken RootFS"
rm -f rootfs.tar.gz
# Copy the "taken RootFS" into corresponded .tar.xz
cp -av ${file} ${name}-${platform}.tar.gz
zcat ${name}-${platform}.tar.gz | xz -9 -e -T0 > ${pwd}/${{ inputs.version_major }}/${{ matrix.image_types }}/${platform}/${name}-${platform}.tar.xz
fi
done
# Clean up
rm -rf ${path}
echo "[Debug]"
ls -1 ${pwd}/${{ inputs.version_major }}/${{ matrix.image_types }}/*/*.tar.xz
# Change date stamp in '${version_major}/${image_types}/${arch}/Dockerfile'
-
name: Change date stamp in Dockerfile (default and minimal only)
# 'default' or 'minimal' images only go to Docker Official Library
if: matrix.image_types == 'default' || matrix.image_types == 'minimal'
run: |
# [Dockerfile]
platforms="${{ env.platforms }}"
for platform in ${platforms//,/ }; do
arch=${platform#linux/}
dockerfile=${{ inputs.version_major }}/${{ matrix.image_types }}/${arch}/Dockerfile
case ${{ matrix.image_types }} in
default)
tags="${{ inputs.version_major }}, ${{ inputs.version_major }}.${{ env.version_minor }}, ${{ inputs.version_major }}.${{ env.version_minor }}-${{ env.date_stamp }}"
[ "${{ inputs.version_major }}" = "9" ] && tags="latest, ${tags}" ;;
minimal)
tags="${{ inputs.version_major }}-${{ matrix.image_types }}, ${{ inputs.version_major }}.${{ env.version_minor }}-${{ matrix.image_types }}, ${{ inputs.version_major }}.${{ env.version_minor }}-${{ matrix.image_types }}-${{ env.date_stamp }}"
[ "${{ inputs.version_major }}" = "9" ] && tags="minimal, ${tags}" ;;
*)
esac
# Tags: 8, 8.9, 8.9-20231124
sed -i "/^\([[:space:]]*#[[:space:]]*Tags: \).*/s//\1${tags}/" ${dockerfile}
echo "[Debug] ${dockerfile}"
cat ${dockerfile}
done
# Commit '${version_major}/${image_types}/${arch}/*'
-
name: "Commit and push ${{ matrix.image_types }}/*/* Dockerfile and RootFS (branch ${{ inputs.version_major }})"
# 'default' or 'minimal' images only and 'Push to production' is checked
if: ( matrix.image_types == 'default' || matrix.image_types == 'minimal' ) && inputs.production
uses: EndBug/add-and-commit@v9
with:
default_author: user_info
new_branch: ${{ inputs.version_major }}
cwd: ${{ inputs.version_major }}
pull: '--rebase --autostash'
message: "AlmaLinux ${{ inputs.version_major }} ${{ matrix.image_types }} image built as of ${{ env.date_stamp }} (generated on ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})."
push: true