AlmaLinux 8 and 9, Container/Docker Images builder and uploader #333
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: AlmaLinux 8 and 9, Container/Docker Images builder and uploader | |
on: | |
workflow_dispatch: | |
inputs: | |
major_version: | |
description: 'AlmaLinux major version' | |
required: true | |
default: '9' | |
type: choice | |
options: | |
- 10 | |
- 9 | |
- 8 | |
platform: | |
description: 'Comma-separated list of platforms: linux/amd64, linux/ppc64le, linux/s390x, linux/arm64' | |
required: true | |
default: 'linux/amd64, linux/arm64' | |
type_default: | |
description: 'default' | |
required: true | |
type: boolean | |
type_minimal: | |
description: 'minimal' | |
required: true | |
type: boolean | |
type_micro: | |
description: 'micro' | |
required: true | |
type: boolean | |
type_base: | |
description: 'base' | |
required: true | |
type: boolean | |
type_init: | |
description: 'init' | |
required: true | |
type: boolean | |
# image_types: | |
# description: 'Comma-separated list of image types (put each type in quotes): "default", "minimal", "micro", "base", "init"' | |
# required: true | |
# default: '"micro"' | |
# registry: | |
# description: 'Registry to push' | |
# required: true | |
# default: 'docker.io/ykohut' | |
# type: choice | |
# options: | |
# - docker.io/ykohut | |
# - quay.io/ykohut | |
# - ghcr.io/yuravk | |
registry: | |
description: 'Comma-separated list of registries: docker.io/ykohut, quay.io/ykohut, ghcr.io/yuravk' | |
required: true | |
default: 'docker.io/ykohut, quay.io/ykohut, ghcr.io/yuravk' | |
push: | |
description: 'Push to registries' | |
required: true | |
type: boolean | |
pr: | |
description: 'Create PR to Docker official' | |
required: true | |
type: boolean | |
env: | |
# VERSION_MINOR: ${{ inputs.major_version == '9' && '3' || '9' }} | |
REGISTRY_IMAGE: ykohut/almalinux | |
# docker-library/official-images | |
DOCKER_LIBRARY_OFFICIAL: LKHN/official-images | |
LOCAL_LIBRARY_OFFICIAL: ${{ github.actor }}/official-images | |
jobs: | |
build: | |
name: "Build ${{ inputs.major_version }} ${{ matrix.image_types }} for ${{ inputs.platform }} and push to all registries" | |
runs-on: ubuntu-latest | |
strategy: | |
fail-fast: false | |
matrix: | |
# platform: ${{ fromJSON(format('[{0}]', inputs.platform || '"linux/amd64", "linux/ppc64le", "linux/s390x", "linux/arm64"')) }} | |
# - linux/amd64 | |
# - linux/ppc64le | |
# - linux/s390x | |
# - linux/arm64 | |
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: "Set environment variables" | |
run: | | |
platform="$( echo '${{ inputs.platform }}' | sed 's/\//_/g' )" | |
echo "PLATFORM_PAIR=${platform//,/}" >> $GITHUB_ENV | |
- | |
name: "Prepare version minor number" | |
run: | | |
# set minor version | |
case ${{ inputs.major_version }} in | |
8) | |
VERSION_MINOR="9" ;; | |
9) | |
VERSION_MINOR="3" ;; | |
10) | |
VERSION_MINOR="0" ;; | |
esac | |
echo "VERSION_MINOR=${VERSION_MINOR}" >> $GITHUB_ENV | |
- | |
name: "Prepare date stamp" | |
id: date_stamp | |
run: | | |
# date stamp | |
STAMP=$(date '+%Y%m%d') | |
echo "STAMP=${STAMP}" >> $GITHUB_ENV | |
echo "::set-output name=date_stamp::${STAMP}" | |
- | |
name: "Prepare image names" | |
run: | | |
# list of registries to push to | |
REGISTRIES="${{ inputs.registry }}" | |
IMAGE_NAMES= | |
# generate image names in format $REGISTRY/almalinux or $REGISTRY/${{ inputs.major_version }}-${{ 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'* ]] && continue | |
# 'default' images goes to $REGISTRY/almalinux | |
[ "${{ matrix.image_types }}" = "default" ] \ | |
&& IMAGE_NAME="$REGISTRY/almalinux" \ | |
|| IMAGE_NAME="$REGISTRY/${{ inputs.major_version }}-${{ 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 | |
echo | |
echo $IMAGE_NAMES | |
# - | |
# name: "Prepare tags" | |
# run: | | |
# # list of repositories to push | |
# REPOS=$( echo '${{ inputs.image_types }}' | tr -d '"') | |
# # list of registries to push to | |
# REGISTRIES="${{ inputs.registry }}" | |
# TAGS= | |
# # generate tags list in format $REGISTRY/${{ inputs.major_version }}-${REPO}:$TAG | |
# for REPO in ${REPOS//,/ }; do | |
# for REGISTRY in ${REGISTRIES//,/ }; do | |
# case ${{ matrix.image_types }} in | |
# default ) | |
# # tags: MAJOR, MAJOR.MINOR | |
# TAGS="${TAGS} $REGISTRY/${{ inputs.major_version }}-${REPO}:${{ inputs.major_version }} $REGISTRY/${{ inputs.major_version }}-${REPO}:${{ inputs.major_version }}.${VERSION_MINOR}" | |
# # tags: MAJOR.MINOR-STAMP | |
# TAGS="${TAGS} $REGISTRY/${{ inputs.major_version }}-${REPO}:${{ inputs.major_version }}.${VERSION_MINOR}-${STAMP}" | |
# # tags: latest | |
# [ "${{ inputs.major_version }}" = "9" ] && TAGS="${TAGS} $REGISTRY/${{ inputs.major_version }}-${REPO}:latest" | |
# ;; | |
# * ) | |
# # tags: MAJOR-TYPE, MAJOR.MINOR-TYPE | |
# TAGS="${TAGS} $REGISTRY/${{ inputs.major_version }}-${REPO}:${{ inputs.major_version }}-${{ matrix.image_types }} $REGISTRY/${{ inputs.major_version }}-${REPO}:${{ inputs.major_version }}.${VERSION_MINOR}-${{ matrix.image_types }}" | |
# # tags: MAJOR.MINOR-TYPE-STAMP | |
# TAGS="${TAGS} $REGISTRY/${{ inputs.major_version }}-${REPO}:${{ inputs.major_version }}.${VERSION_MINOR}-${{ matrix.image_types }}-${STAMP}" | |
# ;; | |
# esac | |
# done | |
# done | |
# # remove space at the beginning of string | |
# TAGS=${TAGS# } | |
# # separate with comma instead of space and export to the action | |
# echo "TAGS=${TAGS// /,}" >> $GITHUB_ENV | |
# echo | |
# echo $TAGS | |
- | |
name: "Switch into containerd image store" | |
run: | | |
# Use containerd image store | |
sudo sed -i '$s/}/, "features": { "containerd-snapshotter": true } }/' /etc/docker/daemon.json | |
sudo systemctl restart docker | |
docker info -f '{{ .DriverStatus }}' | |
- | |
name: Checkout | |
uses: actions/checkout@v4 | |
with: | |
ref: official | |
- | |
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(inputs.registry, 'docker.io') && inputs.push | |
uses: docker/login-action@v3 | |
with: | |
registry: docker.io | |
username: ${{ secrets.DOCKERHUB_USERNAME }} | |
password: ${{ secrets.DOCKERHUB_TOKEN }} | |
- | |
name: Login to Quay.io | |
if: contains(inputs.registry, 'quay.io') && inputs.push | |
uses: docker/login-action@v3 | |
with: | |
registry: quay.io | |
username: ${{ secrets.QUAY_IO_USERNAME }} | |
password: ${{ secrets.QUAY_IO_CLI_PASSWORD }} | |
- | |
name: Login to Ghcr.io | |
if: contains(inputs.registry, 'ghcr.io') && inputs.push | |
uses: docker/login-action@v3 | |
with: | |
registry: ghcr.io | |
username: ${{ secrets.GIT_HUB_USERNAME }} | |
password: ${{ secrets.GIT_HUB_TOKEN }} | |
- | |
name: Docker meta | |
id: meta | |
uses: docker/metadata-action@v5 | |
with: | |
# list of Docker images to use as base name for tags | |
images: ${{ env.IMAGE_NAMES }} | |
# images: ${{ inputs.registry }}/${{ inputs.major_version }}-${{ matrix.image_types }} | |
# images: | | |
# docker.io/ykohut/${{ inputs.major_version }}-${{ matrix.image_types }} | |
# quay.io/ykohut/${{ inputs.major_version }}-${{ matrix.image_types }} | |
# ghcr.io/yuravk/${{ inputs.major_version }}-${{ matrix.image_types }} | |
# generate Docker tags | |
tags: | | |
type=raw,priority=500,value=latest,enable=${{ matrix.image_types != 'default' || ( matrix.image_types == 'default' && inputs.major_version == '9' ) }} | |
type=raw,priority=400,value=${{ inputs.major_version }},enable=true | |
type=raw,priority=300,value=${{ inputs.major_version }}.${{ env.VERSION_MINOR }},enable=true | |
type=raw,priority=200,value=${{ inputs.major_version }}.${{ env.VERSION_MINOR }}-${{ env.STAMP }},enable=true | |
# labels: | | |
# maintainer=Yuriy Kohut <[email protected]> | |
# org.opencontainers.image.title=${{ inputs.major_version }}-${{ matrix.image_types }} | |
# org.opencontainers.image.description=Almalinux ${{ inputs.major_version }}.${{ env.VERSION_MINOR }} ${{ matrix.image_types }} images. | |
# org.opencontainers.image.vendor=AlmaLinux.org | |
- | |
name: Build images | |
# if 'Push to registries' is checked | |
if: inputs.push | |
id: build-images | |
uses: docker/build-push-action@v5 | |
with: | |
provenance: false | |
context: "{{defaultContext}}:dockerfiles/al${{ inputs.major_version }}" | |
file: ./Dockerfile.${{ matrix.image_types }} | |
platforms: ${{ inputs.platform }} | |
push: false | |
load: true | |
# tags: ${{ env.TAGS }} | |
tags: ${{ steps.meta.outputs.tags }} | |
# labels: ${{ steps.meta.outputs.labels }} | |
- | |
name: "[Debug] Test images" | |
# if 'Push to registries' is checked | |
if: inputs.push | |
id: test-images | |
run: | | |
archs="${{ inputs.platform }}" | |
for arch in ${archs//,/ }; do | |
# docker run --platform=${arch} ${{ steps.build-images.outputs.imageid }} /bin/bash -c " \ | |
docker run --platform=${arch} ${{ 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 to registry | |
# if 'Push to registries' is checked | |
if: inputs.push | |
id: push-images | |
uses: docker/build-push-action@v5 | |
with: | |
provenance: false | |
context: "{{defaultContext}}:dockerfiles/al${{ inputs.major_version }}" | |
file: ./Dockerfile.${{ matrix.image_types }} | |
platforms: ${{ inputs.platform }} | |
push: ${{ inputs.push }} | |
# tags: ${{ env.TAGS }} | |
tags: ${{ steps.meta.outputs.tags }} | |
# labels: ${{ steps.meta.outputs.labels }} | |
# Change 'tag:' in the 'dockerfiles/official/al*/Dockerfile.*' | |
- | |
name: "Set tag into official Dockerfile" | |
# if 'Push to registries' is checked and 'default' or 'minimal' image | |
if: matrix.image_types == 'default' || matrix.image_types == 'minimal' | |
run: | | |
case ${{ matrix.image_types }} in | |
default) | |
tags="${{ inputs.major_version }}, ${{ inputs.major_version }}.${{ env.VERSION_MINOR }}, ${{ inputs.major_version }}.${{ env.VERSION_MINOR }}-${{ env.STAMP }}" | |
[ "${{ inputs.major_version }}" = "9" ] && tags="latest, ${tags}" ;; | |
minimal) | |
tags="${{ inputs.major_version }}-${{ matrix.image_types }}, ${{ inputs.major_version }}.${{ env.VERSION_MINOR }}-${{ matrix.image_types }}, ${{ inputs.major_version }}.${{ env.VERSION_MINOR }}-${{ matrix.image_types }}-${{ env.STAMP }}" | |
[ "${{ inputs.major_version }}" = "9" ] && tags="minimal, ${tags}" ;; | |
*) | |
esac | |
# # the data for tag in MAJOR.MINOR-TYPE-DATE format | |
# tag="${{ inputs.major_version }}.${{ env.VERSION_MINOR }}-${{ matrix.image_types }}-${{ env.STAMP}}" | |
# # if 'default' image, the data for tag in MAJOR.MINOR-DATE format | |
# [ "${{ matrix.image_types }}" = "default" ] && tag="${{ inputs.major_version }}.${{ env.VERSION_MINOR }}-${{ env.STAMP}}" | |
sed -i "/^\([[:space:]]*#[[:space:]]*tag: \).*/s//\1${tags}/" dockerfiles/official/al${{ inputs.major_version }}/Dockerfile.${{ matrix.image_types }} | |
sed -i 's/^\([[:space:]]*FROM[[:space:]]\+.\+:\).\+$/\1${{ inputs.major_version }}.${{ env.VERSION_MINOR }}-${{ env.STAMP}}/' dockerfiles/official/al${{ inputs.major_version }}/Dockerfile.${{ matrix.image_types }} | |
cat dockerfiles/official/al${{ inputs.major_version }}/Dockerfile.${{ matrix.image_types }} | |
# Upload changed 'dockerfiles/official/al*/Dockerfile.*' | |
- uses: actions/upload-artifact@v4 | |
# if 'Push to registries' is checked and 'default' or 'minimal' image | |
if: matrix.image_types == 'default' || matrix.image_types == 'minimal' | |
with: | |
name: dockerfiles-${{ matrix.image_types }} | |
path: dockerfiles/official/al${{ inputs.major_version }}/Dockerfile.${{ matrix.image_types }} | |
outputs: | |
date_stamp: ${{ steps.date_stamp.outputs.date_stamp }} | |
commit: | |
if: contains(inputs.image_types, 'default') || contains(inputs.image_types, 'minimal') | |
name: "Commit official Dockerfile for ${{ inputs.major_version }}" | |
runs-on: ubuntu-latest | |
needs: | |
- build | |
steps: | |
- | |
name: Checkout | |
uses: actions/checkout@v4 | |
with: | |
ref: official | |
# Download uploaded above 'dockerfiles/official/al*/Dockerfile.*' | |
- uses: actions/download-artifact@v4 | |
with: | |
merge-multiple: true | |
path: dockerfiles/official/al${{ inputs.major_version }} | |
- | |
name: "[Debug] Print dockerfiles/official/al${{ inputs.major_version }}/Dockerfile.*" | |
run: | | |
echo "Date stamp: ${{ needs.build.outputs.date_stamp }}" | |
cat dockerfiles/official/al${{ inputs.major_version }}/Dockerfile.* | |
# Commit 'dockerfiles/official/al*/Dockerfile.*' | |
# TODO: does this run only if files changed ... ? | |
- | |
name: "Commit tag for dockerfiles/official/al${{ inputs.major_version }}" | |
# if 'Push to registries' is checked | |
# if: inputs.push | |
uses: EndBug/add-and-commit@v9 | |
with: | |
default_author: user_info | |
new_branch: official | |
message: "Almalinux ${{ inputs.major_version }} image build as of ${{ needs.build.outputs.date_stamp }} (with ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})." | |
# push: true | |
push: ${{ inputs.push }} | |
prepare-manifest: | |
if: inputs.pr && ( contains(inputs.image_types, 'default') || contains(inputs.image_types, 'minimal') ) | |
name: "Generate manifest for ${{ matrix.major_version }} ${{ matrix.image_types }}" | |
runs-on: ubuntu-latest | |
needs: | |
- commit | |
strategy: | |
fail-fast: false | |
matrix: | |
image_types: | |
- default | |
- minimal | |
major_version: | |
- 8 | |
- 9 | |
steps: | |
- | |
name: Checkout ${{ github.repository }} | |
uses: actions/checkout@v4 | |
with: | |
ref: official | |
fetch-depth: 0 | |
- | |
name: Checkout ${{ env.LOCAL_LIBRARY_OFFICIAL }} | |
uses: actions/checkout@v4 | |
with: | |
repository: ${{ env.LOCAL_LIBRARY_OFFICIAL }} | |
path: official-images | |
- | |
name: "Get data to prepare manifest for ${{ matrix.major_version }} ${{ matrix.image_types }}" | |
run: | | |
to_manifest=true | |
echo "to_manifest=${to_manifest}" >> $GITHUB_ENV | |
dockerfile="dockerfiles/official/al${{ matrix.major_version }}/Dockerfile.${{ matrix.image_types }}" | |
# The recent commit of Dockerfile for specific version and image type | |
last_commit=$( git log -1 --format='%H' -- ${dockerfile} ) | |
echo "commit_hash=${last_commit}" >> $GITHUB_ENV | |
echo "commit_hash=${last_commit}" | |
# Get tags from the Dockerfile | |
tag=$( grep 'tag:' ${dockerfile} | sed "s/^[[:space:]]*#[[:space:]]*tag: \(.*\)$/\1/" ) | |
echo "tag=${tag}" >> $GITHUB_ENV | |
echo "tag=${tag}" | |
- | |
name: "Render manifest for ${{ matrix.major_version }} ${{ matrix.image_types }}" | |
if: env.to_manifest == 'true' | |
id: minifest | |
uses: chuhlomin/render-template@v1 | |
with: | |
template: official-manifest.tmpl | |
result_path: official-images/library/almalinux.${{ matrix.major_version }}.${{ matrix.image_types }} | |
vars: | | |
tags: ${{ env.tag }} | |
commit_hash: ${{ env.commit_hash}} | |
version_major: ${{ matrix.major_version }} | |
image_type: ${{ matrix.image_types }} | |
- | |
name: "[Debug] Check manifest for ${{ matrix.major_version }} ${{ matrix.image_types }}" | |
if: env.to_manifest == 'true' | |
run: | | |
cat official-images/library/almalinux.${{ matrix.major_version }}.${{ matrix.image_types }} | |
# Upload changed 'official-images/library/almalinux.*' | |
- uses: actions/upload-artifact@v4 | |
if: env.to_manifest == 'true' | |
with: | |
name: manifest-${{ matrix.major_version }}.${{ matrix.image_types }} | |
path: official-images/library/almalinux.${{ matrix.major_version }}.${{ matrix.image_types }} | |
push-pr: | |
if: inputs.pr && ( contains(inputs.image_types, 'default') || contains(inputs.image_types, 'minimal') ) | |
name: "Create pull request for the new manifest" | |
runs-on: ubuntu-latest | |
needs: | |
- prepare-manifest | |
steps: | |
- | |
name: Checkout ${{ env.LOCAL_LIBRARY_OFFICIAL }} | |
uses: actions/checkout@v4 | |
with: | |
repository: ${{ env.LOCAL_LIBRARY_OFFICIAL }} | |
path: official-images | |
token: ${{ secrets.GIT_HUB_TOKEN }} | |
# - | |
# name: Sync upstream changes for ${{ env.LOCAL_LIBRARY_OFFICIAL }} | |
# id: sync | |
# uses: aormsby/[email protected] | |
# with: | |
# target_sync_branch: master | |
# # REQUIRED 'target_repo_token' exactly like this! | |
# target_repo_token: ${{ secrets.GIT_HUB_TOKEN }} | |
# upstream_sync_branch: master | |
# upstream_sync_repo: ${{ env.DOCKER_LIBRARY_OFFICIAL }} | |
# upstream_repo_access_token: ${{ secrets.GIT_HUB_TOKEN }} | |
- | |
name: "Sync ${{ env.LOCAL_LIBRARY_OFFICIAL }} with upstream" | |
run: | | |
cd official-images | |
# gh repo sync ${{ env.DOCKER_LIBRARY_OFFICIAL }} -b master --force | |
git remote add upstream https://github.com/${{ env.DOCKER_LIBRARY_OFFICIAL }}.git | |
git fetch upstream | |
git checkout master | |
# rebase or merge or merge --no-ff ... | |
git rebase upstream/master | |
# Download uploaded above 'official-images/library/almalinux.*' | |
- uses: actions/download-artifact@v4 | |
with: | |
pattern: manifest-* | |
merge-multiple: true | |
path: official-images/library/ | |
- | |
name: "Create head of official-images/library/almalinux" | |
run: | | |
echo "# This file is generated using ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} | |
Maintainers: The AlmaLinux OS Foundation <[email protected]> (@AlmaLinux) | |
GitRepo: ${{ github.server_url }}/${{ github.repository }}.git" > official-images/library/almalinux | |
- | |
name: "[Debug] Squash manifests into official-images/library/almalinux" | |
run: | | |
for file in $( ls -1 official-images/library/almalinux.*.* ); do | |
echo "" >> official-images/library/almalinux | |
cat $file >> official-images/library/almalinux | |
done | |
rm -f official-images/library/almalinux.*.* | |
cat official-images/library/almalinux | |
- | |
name: "Prepare date stamp" | |
run: | | |
# date stamp | |
STAMP=$(date '+%Y%m%d') | |
echo "STAMP=${STAMP}" >> $GITHUB_ENV | |
- | |
name: "Commit and push official-images/library/almalinux" | |
uses: EndBug/add-and-commit@v9 | |
with: | |
cwd: official-images | |
default_author: user_info | |
message: "Almalinux auto-update - ${{ env.STAMP }}" | |
# push: false | |
push: ${{ inputs.pr }} | |
- | |
name: Create Pull Request [commendline] | |
run: | | |
cd official-images | |
gh auth login --with-token < <(echo ${{ secrets.GIT_HUB_TOKEN }}) | |
gh pr create \ | |
--title "Almalinux auto-update - ${{ env.STAMP }}" \ | |
--body "This is an auto-generated commit. Any concern or issues, please contact or email AlmaLinux OS Foundation [email protected] (@AlmaLinux)" \ | |
--repo ${{ env.DOCKER_LIBRARY_OFFICIAL }} \ | |
--base master \ | |
--draft | |
# - | |
# name: Create Pull Request | |
# uses: peter-evans/create-pull-request@v6 | |
# with: | |
# path: official-images | |
# add-paths: library | |
# # branch: master | |
# # base: master | |
# # committer: ${{ github.actor }} <${{ github.actor_id }}+${{ github.actor }}@users.noreply.github.com> | |
# commit-message: "Almalinux auto-update - ${{ env.STAMP }}" | |
# title: "Almalinux auto-update - ${{ env.STAMP }}" | |
# body: "This is an auto-generated commit. Any concern or issues, please contact or email AlmaLinux OS Foundation [email protected] (@AlmaLinux)" | |
# push-to-fork: ${{ env.DOCKER_LIBRARY_OFFICIAL }} | |
# draft: true | |
# token: ${{ secrets.GIT_HUB_TOKEN }} |