Pre-release (base) - Release 3.1.2 #75
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: Pre-release (base) | |
run-name: Pre-release (base) - ${{ github.event.pull_request.title }} | |
on: | |
pull_request: | |
branches: [main] | |
paths-ignore: # not always respected. See https://github.com/actions/runner/issues/2324#issuecomment-1703345084 | |
- ".github/**" | |
- "**.md" | |
# cf https://github.com/actions/runner/issues/2324, paths-ignore will only be respected at PR creation | |
# all new commits then added in the PR will trigger the workflow | |
env: | |
# intermediate registry in which architecture-specific images and base images must be pushed | |
INTERMEDIATE_IMAGES_BUILDS_REGISTRY: "nwodtuhs/exegol-builds" | |
# base image is used as initial layer when building the final image | |
IMAGE_TARGET_REGISTRY: "nwodtuhs/exegol-misc-preprod" | |
IMAGE_TAG: "base" | |
DOCKERFILE: "./sources/dockerfiles/base.dockerfile" | |
jobs: | |
# https://github.com/orgs/community/discussions/26671, "can’t pass ENV variables to the reusable workflow" | |
init: | |
if: ${{ startsWith(github.event.pull_request.title, 'Release') }} | |
name: Initialize | |
runs-on: self-hosted | |
outputs: | |
INTERMEDIATE_IMAGES_BUILDS_REGISTRY: ${{ steps.varset.outputs.INTERMEDIATE_IMAGES_BUILDS_REGISTRY }} | |
IMAGE_TARGET_REGISTRY: ${{ steps.varset.outputs.IMAGE_TARGET_REGISTRY }} | |
IMAGE_TAG: ${{ steps.varset.outputs.IMAGE_TAG }} | |
IMAGE_VERSION: ${{ steps.varset.outputs.IMAGE_VERSION }} | |
DOCKERFILE: ${{ steps.varset.outputs.DOCKERFILE }} | |
image_exists: ${{ steps.check_remote_image.outputs.image_exists }} | |
steps: | |
- name: Checkout | |
uses: actions/checkout@v3 | |
with: | |
fetch-depth: 2 | |
- name: Setting variables | |
id: varset | |
run: | | |
echo "INTERMEDIATE_IMAGES_BUILDS_REGISTRY=${{ env.INTERMEDIATE_IMAGES_BUILDS_REGISTRY }}" >> $GITHUB_OUTPUT | |
echo "IMAGE_TARGET_REGISTRY=${{ env.IMAGE_TARGET_REGISTRY }}" >> $GITHUB_OUTPUT | |
echo "IMAGE_TAG=${{ env.IMAGE_TAG }}" >> $GITHUB_OUTPUT | |
echo "IMAGE_VERSION=$(echo ${{ github.event.pull_request.title }} | cut -d ' ' -f 2)" >> $GITHUB_OUTPUT | |
echo "DOCKERFILE=${{ env.DOCKERFILE }}" >> $GITHUB_OUTPUT | |
cat $GITHUB_OUTPUT | |
- name: Checking if remote image exists | |
id: check_remote_image | |
run: | | |
echo "docker manifest inspect ${{ env.IMAGE_TARGET_REGISTRY }}:${{ env.IMAGE_TAG }}-${{ steps.varset.outputs.IMAGE_VERSION }}" | |
if docker manifest inspect ${{ env.IMAGE_TARGET_REGISTRY }}:${{ env.IMAGE_TAG }}-${{ steps.varset.outputs.IMAGE_VERSION }}; then | |
echo "Image exists" | |
echo "image_exists=true" >> $GITHUB_OUTPUT | |
else | |
echo "Image does not exist" | |
echo "image_exists=false" >> $GITHUB_OUTPUT | |
fi | |
cat $GITHUB_OUTPUT | |
- name: Check changes | |
id: check_changes | |
run: | | |
# we get all changes in the PR, need only the most recent | |
file_list=$(git diff --name-only HEAD HEAD~1) | |
files_to_check=( | |
"sources/install/package_base.sh" | |
"sources/install/entrypoint.sh" | |
"sources/install/package_desktop.sh" | |
"sources/install/post_install.sh" | |
) | |
for file_to_check in "${files_to_check[@]}"; do | |
if [[ $file_list =~ $file_to_check ]]; then | |
echo "Base layer must be compiled" | |
echo "base_changed=true" >> $GITHUB_OUTPUT | |
break | |
fi | |
done | |
- name: (dbg) print changes | |
run: git diff --name-only HEAD^1 HEAD | |
- name: (dbg) print result | |
run: echo ${{ steps.check_changes.outputs.base_changed }} | |
code_check: | |
if: ${{ startsWith(github.event.pull_request.title, 'Release') }} | |
name: Code compliance check | |
uses: ./.github/workflows/sub_code_check.yml | |
build: | |
name: Image build | |
needs: [ init, code_check ] | |
# only building base if ccc was a success and image doesn't already exist | |
if: needs.code_check.result == 'success' && needs.init.outputs.image_exists == 'false' | |
strategy: | |
fail-fast: false | |
matrix: | |
arch: [ arm64, amd64 ] | |
uses: ./.github/workflows/sub_build_belt.yml | |
with: | |
# ex: nwodtuhs/exegol-builds | |
IMAGE_REGISTRY: ${{ needs.init.outputs.INTERMEDIATE_IMAGES_BUILDS_REGISTRY }} | |
# ex: base | |
IMAGE_TAG: ${{ needs.init.outputs.IMAGE_TAG }} | |
# ex: base-1.2.3-arm64 | |
IMAGE_NAME: ${{ needs.init.outputs.IMAGE_TAG }}-${{ needs.init.outputs.IMAGE_VERSION }}-${{ matrix.arch }} | |
# ex: 1.2.3 | |
IMAGE_VERSION: ${{ needs.init.outputs.IMAGE_VERSION }} | |
# ex: base.dockerfile | |
DOCKERFILE: ${{ needs.init.outputs.DOCKERFILE }} | |
# ex: arm64 | |
ARCH: ${{ matrix.arch }} | |
EXPORT_TOOLS: false | |
PUSH_IMAGE: true | |
secrets: | |
DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }} | |
DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }} | |
publish: | |
name: Publish image | |
needs: [ init, build ] | |
# only publishing if the tests were a success (implicit by the success of build). | |
if: needs.build.result == 'success' | |
timeout-minutes: 60 | |
runs-on: self-hosted | |
strategy: | |
fail-fast: false | |
matrix: | |
image: [ "${{ needs.init.outputs.IMAGE_TAG }}", "${{ needs.init.outputs.IMAGE_TAG }}-${{ needs.init.outputs.IMAGE_VERSION }}" ] | |
steps: | |
- name: Login to Dockerhub | |
if: success() | |
uses: docker/login-action@v2 | |
with: | |
username: ${{ secrets.DOCKER_USERNAME }} | |
password: ${{ secrets.DOCKER_PASSWORD }} | |
- name: Create manifest | |
id: create_manifest | |
if: success() | |
# ex: docker manifest create nwodtuhs/exegol-misc-preprod:base nwodtuhs/exegol-builds:base-1.2.3-arm64 nwodtuhs/exegol-builds:base-1.2.3-amd64 | |
# ex: docker manifest create nwodtuhs/exegol-misc-preprod:base-1.2.3 nwodtuhs/exegol-builds:base-1.2.3-arm64 nwodtuhs/exegol-builds:base-1.2.3-amd64 | |
run: docker manifest create ${{ env.IMAGE_TARGET_REGISTRY }}:${{ matrix.image }} ${{ env.INTERMEDIATE_IMAGES_BUILDS_REGISTRY }}:${{ env.IMAGE_TAG }}-${{ needs.init.outputs.IMAGE_VERSION }}-arm64 ${{ env.INTERMEDIATE_IMAGES_BUILDS_REGISTRY }}:${{ env.IMAGE_TAG }}-${{ needs.init.outputs.IMAGE_VERSION }}-amd64 | |
- name: Push manifest to remote | |
if: success() | |
# ex: docker manifest push nwodtuhs/exegol-misc-preprod:base | |
# ex: docker manifest push nwodtuhs/exegol-misc-preprod:base-1.2.3 | |
run: docker manifest push ${{ env.IMAGE_TARGET_REGISTRY }}:${{ matrix.image }} | |
- name: Remove manifest locally | |
if: always() && steps.create_manifest.outcome == 'success' | |
# ex: docker manifest rm nwodtuhs/exegol-misc-preprod:base | |
# ex: docker manifest rm nwodtuhs/exegol-misc-preprod:base-1.2.3 | |
run: docker manifest rm ${{ env.IMAGE_TARGET_REGISTRY }}:${{ matrix.image }} | |
clean_runners: | |
name: Clean runner | |
needs: [ init, publish ] | |
if: always() && ${{ startsWith(github.event.pull_request.title, 'Release') }} | |
# even if this job fails, it won't affect the success/fail status of the whole workflow | |
continue-on-error: true | |
strategy: | |
fail-fast: false | |
matrix: | |
arch: [ arm64, amd64 ] | |
runs-on: | |
- self-hosted | |
- builder | |
- ${{ matrix.arch }} | |
steps: | |
- name: List docker images | |
run: docker image ls | |
- name: Remove local image | |
# always removing image, no need to keep it on the runner | |
if: always() | |
# ex: docker rmi nwodtuhs/exegol-builds:base-1.2.3-arm64 | |
run: docker rmi ${{ env.INTERMEDIATE_IMAGES_BUILDS_REGISTRY }}:${{ env.IMAGE_TAG }}-${{ needs.init.outputs.IMAGE_VERSION }}-${{ matrix.arch }} | |
clean_registries: | |
name: Clean registries | |
needs: [ init, publish ] | |
if: always() && needs.publish.result == 'success' | |
runs-on: self-hosted | |
# only cleaning if publish was a success. And publish requires that tests were a success. | |
# If tests were a success, there's no need for debugging the images, they can be removed from the exegol-builds registry | |
strategy: | |
fail-fast: false | |
matrix: | |
arch: [ arm64, amd64 ] | |
steps: | |
- name: Remove remote arch-specific images in ${{ env.INTERMEDIATE_IMAGES_BUILDS_REGISTRY }} | |
# ex: curl [...] --request DELETE [...]exegol-builds/tags/base-1.2.3-arm64 | |
run: | | |
HUB_TOKEN=$(curl --silent --header "Content-Type: application/json" --request POST --data "{\"username\": \"${{ secrets.DOCKER_USERNAME }}\", \"password\": \"${{ secrets.DOCKER_PASSWORD }}\"}" https://hub.docker.com/v2/users/login/ | jq -r .token) | |
curl --fail-with-body --include --request DELETE -H "Accept: application/json" --header "Authorization: JWT $HUB_TOKEN" https://hub.docker.com/v2/repositories/${{ env.INTERMEDIATE_IMAGES_BUILDS_REGISTRY }}/tags/${{ env.IMAGE_TAG }}-${{ needs.init.outputs.IMAGE_VERSION }}-${{ matrix.arch }}/ | |
add_label: | |
name: Trigger image builds | |
needs: [ init, clean_registries ] | |
# running either if publish and clean_registries were a success, or if the image already existed on remote | |
if: always() && ${{ startsWith(github.event.pull_request.title, 'Release') }} && ( needs.clean_registries.result == 'success' || needs.init.outputs.image_exists == 'true' ) | |
runs-on: ubuntu-latest | |
# Cannot use secrets.GITHUB_TOKEN as it is the default "github-actions bot" token, and "An action in a workflow run can’t trigger a new workflow run." | |
# https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#about-workflow-events | |
# https://github.com/orgs/community/discussions/25565 | |
env: | |
GITHUB_TOKEN: ${{ secrets.GH_PAT_BASE_TRIGGER }} | |
steps: | |
- name: Checkout | |
uses: actions/checkout@v3 | |
- name: List labels | |
run: gh pr view --json labels ${{ github.event.number }} -q '.labels[].name' | |
- name: Label "base success" already set? | |
id: already_labeled | |
run: | | |
if gh pr view --json labels ${{ github.event.number }} -q '.labels[].name' | grep -q "base success" | |
then | |
echo "PR already labeled" | |
echo "already_labeled=true" >> $GITHUB_OUTPUT | |
else | |
echo "PR not already labeled" | |
echo "already_labeled=false" >> $GITHUB_OUTPUT | |
fi | |
cat $GITHUB_OUTPUT | |
- name: Remove label | |
# removing and re-adding label in order to re-trigger next preprod workflows | |
if: steps.already_labeled.outputs.already_labeled == 'true' | |
run: gh pr edit --remove-label "base success" ${{ github.event.number }} | |
- name: Add label | |
if: always() | |
run: gh pr edit --add-label "base success" ${{ github.event.number }} |