Release 3.1.0 #22
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 (web) | |
on: | |
pull_request: | |
title: | |
- "Release *.*.*" | |
- "Release *.*.*b*" | |
branches: main | |
paths-ignore: | |
- ".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: | |
# intermediary registry in which architecture-specific images must be pushed | |
DOCKER_BUILD_REPO: "nwodtuhs/exegol-builds" | |
# final registry target, in which arch-specific images must be aggregated | |
DOCKER_TARGET_REPO: "nwodtuhs/exegol-preprod" | |
IMAGE_BASE_NAME: "web" | |
DOCKERFILE: "web.dockerfile" | |
jobs: | |
# https://github.com/orgs/community/discussions/26671, "can’t pass ENV variables to the reusable workflow" | |
varset: | |
name: Initialize variables | |
runs-on: self-hosted | |
outputs: | |
DOCKER_BUILD_REPO: ${{ steps.varset.outputs.DOCKER_BUILD_REPO }} | |
DOCKER_TARGET_REPO: ${{ steps.varset.outputs.DOCKER_TARGET_REPO }} | |
IMAGE_BASE_NAME: ${{ steps.varset.outputs.IMAGE_BASE_NAME }} | |
DOCKERFILE: ${{ steps.varset.outputs.DOCKERFILE }} | |
IMAGE_VERSION: ${{ steps.varset.outputs.IMAGE_VERSION }} | |
steps: | |
- name: Passing workflow env vars to reusable workflows | |
id: varset | |
run: | | |
echo "DOCKER_BUILD_REPO=${DOCKER_BUILD_REPO}" >> $GITHUB_OUTPUT | |
echo "DOCKER_TARGET_REPO=${DOCKER_TARGET_REPO}" >> $GITHUB_OUTPUT | |
echo "IMAGE_BASE_NAME=${IMAGE_BASE_NAME}" >> $GITHUB_OUTPUT | |
echo "DOCKERFILE=${DOCKERFILE}" >> $GITHUB_OUTPUT | |
echo "IMAGE_VERSION=$(echo ${{ github.event.pull_request.title }} | cut -d ' ' -f 2)" | |
echo "IMAGE_VERSION=$(echo ${{ github.event.pull_request.title }} | cut -d ' ' -f 2)" >> $GITHUB_OUTPUT | |
build_belt: | |
name: Build belt | |
needs: varset | |
strategy: | |
fail-fast: false | |
matrix: | |
arch: [arm64, amd64] | |
uses: ./.github/workflows/sub_build_belt.yml | |
with: | |
DOCKER_BUILD_REPO: ${{ needs.varset.outputs.DOCKER_BUILD_REPO }} | |
DOCKER_TARGET_REPO: ${{ needs.varset.outputs.DOCKER_TARGET_REPO }} | |
IMAGE_BASE_NAME: ${{ needs.varset.outputs.IMAGE_BASE_NAME }} | |
DOCKERFILE: ${{ needs.varset.outputs.DOCKERFILE }} | |
IMAGE_VERSION: ${{ needs.varset.outputs.IMAGE_VERSION }} | |
ARCH: ${{ matrix.arch }} | |
secrets: | |
DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }} | |
DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }} | |
publish: | |
name: Publish | |
timeout-minutes: 60 | |
needs: | |
- varset | |
- build_belt | |
runs-on: self-hosted | |
# only publishing if the tests were a success (implicit by the success of build_belt). | |
if: needs.build_belt.result == 'success' | |
steps: | |
- name: Login to Dockerhub | |
uses: docker/login-action@v2 | |
with: | |
username: ${{ secrets.DOCKER_USERNAME }} | |
password: ${{ secrets.DOCKER_PASSWORD }} | |
- name: Create and push manifest | |
if: success() | |
run: | | |
echo "Create manifest" | |
docker manifest create ${DOCKER_TARGET_REPO}:${IMAGE_BASE_NAME} ${DOCKER_BUILD_REPO}:${IMAGE_BASE_NAME}-arm64 ${DOCKER_BUILD_REPO}:${IMAGE_BASE_NAME}-amd64 | |
docker manifest push ${DOCKER_TARGET_REPO}:${IMAGE_BASE_NAME} | |
docker manifest rm ${DOCKER_TARGET_REPO}:${IMAGE_BASE_NAME} | |
- name: Create and push version manifest | |
env: | |
IMAGE_VERSION: ${{ needs.varset.outputs.IMAGE_VERSION }} | |
if: success() && env.IMAGE_VERSION != '' | |
run: | | |
echo "Create version manifest" | |
docker manifest create ${DOCKER_TARGET_REPO}:${IMAGE_BASE_NAME}-${IMAGE_VERSION} ${DOCKER_BUILD_REPO}:${IMAGE_BASE_NAME}-arm64 ${DOCKER_BUILD_REPO}:${IMAGE_BASE_NAME}-amd64 | |
docker manifest push ${DOCKER_TARGET_REPO}:${IMAGE_BASE_NAME}-${IMAGE_VERSION} | |
docker manifest rm ${DOCKER_TARGET_REPO}:${IMAGE_BASE_NAME}-${IMAGE_VERSION} | |
tools_list: | |
name: Export tools list | |
needs: | |
- varset | |
- publish | |
- build_belt | |
# only exporting tools list if publish was a success AND the tests were a success | |
if: always() && ( needs.publish.result == 'success' && !contains(needs.build_belt.outputs.build, 'failure')) | |
strategy: | |
fail-fast: false | |
# only 1 job at a time, else there will be a conflict. Runner 2 will pull exegol-docs before runner 1 pushes changes. | |
max-parallel: 1 | |
matrix: | |
arch: [ arm64, amd64 ] | |
runs-on: | |
- self-hosted | |
- builder | |
- ${{ matrix.arch }} | |
steps: | |
- name: Checkout Exegol-images | |
uses: actions/checkout@v3 | |
- name: Prepare image version | |
id: prepare | |
run: | | |
COMMIT_ID=$(git rev-parse "$GITHUB_SHA") | |
if [ "$IMAGE_VERSION" == "" ]; then | |
IMAGE_VERSION=${COMMIT_ID:0:8} | |
fi | |
echo "image_version=${IMAGE_VERSION}" | |
echo "image_version=${IMAGE_VERSION}" >> $GITHUB_OUTPUT | |
- name: Checkout Exegol-docs | |
uses: actions/checkout@v3 | |
with: | |
repository: 'ThePorgs/Exegol-docs' | |
ref: 'dev-images' | |
- name: Inspect the built image | |
run: docker inspect ${{ needs.varset.outputs.DOCKER_BUILD_REPO }}:${{ needs.varset.outputs.IMAGE_BASE_NAME }}-${{ matrix.arch }} | |
- name: Create a container from the built image | |
run: | | |
docker run --name exegol-${{ needs.varset.outputs.IMAGE_BASE_NAME }}-${{ matrix.arch }} --rm -t -d ${{ needs.varset.outputs.DOCKER_BUILD_REPO }}:${{ needs.varset.outputs.IMAGE_BASE_NAME }}-${{ matrix.arch }} endless | |
- name: Export the tools list | |
if: success() | |
run: | | |
docker cp exegol-${{ needs.varset.outputs.IMAGE_BASE_NAME }}-${{ matrix.arch }}:/.exegol/installed_tools.csv installed_tools.csv | |
- name: Debug print installed_tools.csv | |
id: list_exists | |
run: cat installed_tools.csv | |
- name: Sanity check for installed_tools.csv | |
if: success() | |
run: | | |
grep -qE '([^,]*,[^,]*){3,}' installed_tools.csv \ | |
&& (echo '[-] Wrong number of columns on the following lines' \ | |
&& grep -oE '([^,]*,[^,]*){3,}' installed_tools.csv || exit 1) \ | |
|| (echo '[+] List contains right number of columns' && exit 0) | |
- name: Stop the container | |
if: always() | |
run: docker stop exegol-${{ needs.varset.outputs.IMAGE_BASE_NAME }}-${{ matrix.arch }} | |
- name: Adding list to repo and tables | |
if: always() && steps.list_exists.outcome == 'success' | |
run: | | |
mkdir -p source/assets/installed_tools/lists | |
echo '[*] Moving tools list to imagetag_version_arch.csv' | |
mv installed_tools.csv source/assets/installed_tools/lists/${{ needs.varset.outputs.IMAGE_BASE_NAME }}_${{ steps.prepare.outputs.image_version }}_${{ matrix.arch }}.csv | |
echo '[*] Changing lists.csv so that new tools list appears' | |
echo '[*] [SHOULD BE RELEASES ONLY] Removing occurences of image,version,arch. This is because this workflow runs in the prerelease pipeline, meaning that there's a possibility tools list is pushed to exegol-docs even if the images are not released for some reasons (e.g. imageA prerelease works but not for imageB). Doing this grep -v will ensure that lists.csv doesn't have duplicates to the same tag, same version and same arch' | |
(head -n 1 source/assets/installed_tools/lists.csv; \ | |
echo "${{ needs.varset.outputs.IMAGE_BASE_NAME }},${{ steps.prepare.outputs.image_version }},${{ matrix.arch }},$(date -u +"%Y-%m-%dT%H:%M:%SZ"),:download:\`${{ needs.varset.outputs.IMAGE_BASE_NAME }}_${{ steps.prepare.outputs.image_version }}_${{ matrix.arch }}.csv \ | |
</assets/installed_tools/lists/${{ needs.varset.outputs.IMAGE_BASE_NAME }}_${{ steps.prepare.outputs.image_version }}_${{ matrix.arch }}.csv>\`"; \ | |
( \ | |
tail -n +2 source/assets/installed_tools/lists.csv | grep -Ev "${{ needs.varset.outputs.IMAGE_BASE_NAME }},${{ steps.prepare.outputs.image_version }},${{ matrix.arch }}" \ | |
) \ | |
) | tee source/assets/installed_tools/new_lists.csv | |
mv source/assets/installed_tools/new_lists.csv source/assets/installed_tools/lists.csv | |
- name: Debug print lists.csv | |
if: always() | |
id: final_list_exists | |
run: cat source/assets/installed_tools/lists.csv | |
- name: Push Exegol-docs | |
if: always() && steps.final_list_exists.outcome == 'success' | |
env: | |
SSH_DEPLOY_KEY: ${{ secrets.EXEGOL_DOCS_SSH_DEPLOY_KEY }} | |
run: | | |
echo '[*] Setting up git env for SSH use' | |
mkdir -p "$HOME/.ssh" | |
DEPLOY_KEY_FILE="$HOME/.ssh/deploy_key" | |
echo "${SSH_DEPLOY_KEY}" > "$DEPLOY_KEY_FILE" | |
chmod 600 "$DEPLOY_KEY_FILE" | |
SSH_KNOWN_HOSTS_FILE="$HOME/.ssh/known_hosts" | |
ssh-keyscan -H github.com > "$SSH_KNOWN_HOSTS_FILE" | |
export GIT_SSH_COMMAND="ssh -i "$DEPLOY_KEY_FILE" -o UserKnownHostsFile=$SSH_KNOWN_HOSTS_FILE" | |
GIT_CMD_REPOSITORY="[email protected]:ThePorgs/Exegol-docs.git" | |
echo '[*] Setting git config' | |
git config --global user.name "exegol-images[pipeline]" | |
git config --global user.email "[email protected]" | |
echo '[*] Staging changes' | |
git add --verbose source/assets/installed_tools/lists/${{ needs.varset.outputs.IMAGE_BASE_NAME }}_${{ steps.prepare.outputs.image_version }}_${{ matrix.arch }}.csv | |
git add --verbose source/assets/installed_tools/lists.csv | |
echo '[*] Commiting changes' | |
git commit --verbose -m "PIPELINE: tools list for ${{ needs.varset.outputs.IMAGE_BASE_NAME }}_${{ steps.prepare.outputs.image_version }}_${{ matrix.arch }}" | |
echo '[*] Pushing changes' | |
git push --verbose "$GIT_CMD_REPOSITORY" | |
clean_runners: | |
name: Clean runner | |
needs: | |
- tools_list | |
- publish | |
- build_belt | |
# clean runners, if publish was a success, or at least if build succeeded | |
if: always() && ( needs.publish.result == 'success' || !contains(needs.build_belt.outputs.build, 'failure')) | |
strategy: | |
fail-fast: false | |
matrix: | |
arch: [ arm64, amd64 ] | |
runs-on: | |
- self-hosted | |
- builder | |
- ${{ matrix.arch }} | |
steps: | |
- name: Remove image built for ${{ matrix.arch }} | |
run: | | |
image_name=${DOCKER_BUILD_REPO}:${IMAGE_BASE_NAME}-${{ matrix.arch }} | |
echo "Removing $image_name" | |
docker image inspect $image_name || exit 0 && docker rmi $image_name | |
clean_registry: | |
name: Clean intermediate registry | |
needs: publish | |
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 | |
if: needs.publish.result == 'success' | |
steps: | |
- name: Remove arch-specific images on intermediate registry | |
run: | | |
HUB_TOKEN=$(curl -s -H "Content-Type: application/json" -X POST -d "{\"username\": \"${{ secrets.DOCKER_USERNAME }}\", \"password\": \"${{ secrets.DOCKER_PASSWORD }}\"}" https://hub.docker.com/v2/users/login/ | jq -r .token) | |
curl -i -X DELETE -H "Accept: application/json" -H "Authorization: JWT $HUB_TOKEN" https://hub.docker.com/v2/repositories/${DOCKER_BUILD_REPO}/tags/${IMAGE_BASE_NAME}-arm64/ | |
curl -i -X DELETE -H "Accept: application/json" -H "Authorization: JWT $HUB_TOKEN" https://hub.docker.com/v2/repositories/${DOCKER_BUILD_REPO}/tags/${IMAGE_BASE_NAME}-amd64/ | |