From 583e5c0f16c4293e7a28cef3f7cdd6ebccb03f94 Mon Sep 17 00:00:00 2001 From: aptalca <541623+aptalca@users.noreply.github.com> Date: Thu, 8 Oct 2026 21:59:39 -0400 Subject: [PATCH 1/4] add bash function for retrying ghcr operations --- .../roles/repository/templates/Jenkinsfile.j2 | 281 +++++++++++++----- 1 file changed, 211 insertions(+), 70 deletions(-) diff --git a/ansible/roles/repository/templates/Jenkinsfile.j2 b/ansible/roles/repository/templates/Jenkinsfile.j2 index e384036a..98121bd7 100644 --- a/ansible/roles/repository/templates/Jenkinsfile.j2 +++ b/ansible/roles/repository/templates/Jenkinsfile.j2 @@ -109,6 +109,54 @@ pipeline { } } } + /* ############################ + Bash Function For GHCR Retry + ############################ */ + // Create a reusable script for a ghcr retry bash function + stage("Create Bash Function"){ + steps{ + sh '''#! /bin/bash + # create our retry function + retry_ghcr() { + local max_attempts=5 + local base_delay=1 + local max_delay=30 + local attempt=1 + + while true; do + rm -rf /tmp/cmdstderr + "$@" 2> >(tee /tmp/cmdstderr) + local exit_code="$?" + if [[ "${exit_code}" = "0" ]]; then + rm -rf /tmp/cmdstderr + return 0 + elif cat /tmp/cmdstderr | grep -q -v "retry-after:"; then + rm -rf /tmp/cmdstderr + return "$exit_code" + elif (( attempt >= max_attempts )); then + rm -rf /tmp/cmdstderr + echo "retry: $* failed after $attempt attempts (exit $exit_code)" >&2 + return "$exit_code" + else + # Calculate exponential delay: base * 2^(attempt-1), capped at max_delay + local delay=$(( base_delay * 2 ** (attempt - 1) )) + (( delay > max_delay )) && delay="$max_delay" + + # Apply full jitter (random delay between 0 and calculated delay) + local wait=$(( RANDOM % (delay + 1) )) + + rm -rf /tmp/cmdstderr + + echo "retry: attempt $attempt/$max_attempts failed (exit $exit_code); waiting ${wait}s..." >&2 + sleep "$wait" + ((attempt++)) + fi + done + } + declare -f retry_ghcr > /tmp/retry_ghcr.sh + ''' + } + } /* ####################### Package Version Tagging ####################### */ @@ -459,6 +507,8 @@ pipeline { } sh '''curl -sL https://raw.githubusercontent.com/linuxserver/docker-jenkins-builder/master/checkrun.sh | /bin/bash''' sh '''#! /bin/bash + source /tmp/retry_ghcr.sh + retry_ghcr docker pull ghcr.io/linuxserver/baseimage-alpine:3.23 docker run --rm \ -v ${WORKSPACE}:/mnt \ -e AWS_ACCESS_KEY_ID=\"${S3_KEY}\" \ @@ -485,8 +535,9 @@ pipeline { sh '''#! /bin/bash set -e TEMPDIR=$(mktemp -d) + source /tmp/retry_ghcr.sh {% if project_repo_name != "docker-jenkins-builder" %} - docker pull ghcr.io/linuxserver/jenkins-builder:latest + retry_ghcr docker pull ghcr.io/linuxserver/jenkins-builder:latest {% endif %} # Cloned repo paths for templating: # ${TEMPDIR}/docker-${CONTAINER_NAME}: Cloned branch {{ ls_branch }} of ${LS_USER}/${LS_REPO} for running the jenkins builder on @@ -550,6 +601,7 @@ pipeline { sed -i 's|^changelogs:|# init diagram\\ninit_diagram:\\n\\n# changelog\\nchangelogs:|' readme-vars.yml fi mkdir -p ${TEMPDIR}/d2 + retry_ghcr docker pull ghcr.io/linuxserver/d2-builder:latest docker run --rm -v ${TEMPDIR}/d2:/output -e PUID=$(id -u) -e PGID=$(id -g) -e RAW="true" ghcr.io/linuxserver/d2-builder:latest ${CONTAINER_NAME}:{{ release_tag }} ls -al ${TEMPDIR}/d2 yq -ei ".init_diagram |= load_str(\\"${TEMPDIR}/d2/${CONTAINER_NAME}-{{ release_tag }}.d2\\")" readme-vars.yml @@ -798,22 +850,25 @@ pipeline { {% if "docker-baseimage" not in project_repo_name %} sh "sed -r -i 's|(^FROM .*)|\\1\\n\\nENV LSIO_FIRST_PARTY=true|g' Dockerfile" {% endif %} - sh "docker buildx build \ - --label \"org.opencontainers.image.created=${GITHUB_DATE}\" \ - --label \"org.opencontainers.image.authors={{ lsio_project_name }}\" \ - --label \"org.opencontainers.image.url={{ project_github_repo_url }}/packages\" \ - --label \"org.opencontainers.image.documentation={{ lsio_docs_url }}/images/docker-{{ project_name }}\" \ - --label \"org.opencontainers.image.source={{ project_github_repo_url }}\" \ - --label \"org.opencontainers.image.version=${EXT_RELEASE_CLEAN}-ls${LS_TAG_NUMBER}\" \ - --label \"org.opencontainers.image.revision=${COMMIT_SHA}\" \ - --label \"org.opencontainers.image.vendor={{ lsio_project_name }}\" \ - --label \"org.opencontainers.image.licenses=GPL-3.0-only\" \ - --label \"org.opencontainers.image.ref.name=${COMMIT_SHA}\" \ - --label \"org.opencontainers.image.title={{ project_name|capitalize }}\" \ - --label \"org.opencontainers.image.description={% if project_blurb is defined %}{{ project_blurb | replace('"', '') | replace('\n', ' ') }}{% else %}{{ project_name }} image by {{ lsio_project_name }}{% endif %}\" \ - --no-cache --pull -t ${IMAGE}:${META_TAG} --platform=linux/amd64 \ - --provenance={{ image_provenance | lower }} --sbom={{ image_sbom | lower }} --builder={{ image_builder }} --load \ - --build-arg ${BUILD_VERSION_ARG}=${EXT_RELEASE} --build-arg VERSION=\"${VERSION_TAG}\" --build-arg BUILD_DATE=${GITHUB_DATE} ." + sh '''#! /bin/bash + source /tmp/retry_ghcr.sh + retry_ghcr docker buildx build \ + --label "org.opencontainers.image.created=${GITHUB_DATE}" \ + --label "org.opencontainers.image.authors={{ lsio_project_name }}" \ + --label "org.opencontainers.image.url={{ project_github_repo_url }}/packages" \ + --label "org.opencontainers.image.documentation={{ lsio_docs_url }}/images/docker-{{ project_name }}" \ + --label "org.opencontainers.image.source={{ project_github_repo_url }}" \ + --label "org.opencontainers.image.version=${EXT_RELEASE_CLEAN}-ls${LS_TAG_NUMBER}" \ + --label "org.opencontainers.image.revision=${COMMIT_SHA}" \ + --label "org.opencontainers.image.vendor={{ lsio_project_name }}" \ + --label "org.opencontainers.image.licenses=GPL-3.0-only" \ + --label "org.opencontainers.image.ref.name=${COMMIT_SHA}" \ + --label "org.opencontainers.image.title={{ project_name|capitalize }}" \ + --label "org.opencontainers.image.description={% if project_blurb is defined %}{{ project_blurb | replace('"', '') | replace('\n', ' ') }}{% else %}{{ project_name }} image by {{ lsio_project_name }}{% endif %}" \ + --no-cache --pull -t ${IMAGE}:${META_TAG} --platform=linux/amd64 \ + --provenance={{ image_provenance | lower }} --sbom={{ image_sbom | lower }} --builder={{ image_builder }} --load \ + --build-arg ${BUILD_VERSION_ARG}=${EXT_RELEASE} --build-arg VERSION="${VERSION_TAG}" --build-arg BUILD_DATE=${GITHUB_DATE} . + ''' sh '''#! /bin/bash set -e IFS=',' read -ra CACHE <<< "$BUILDCACHE" @@ -871,22 +926,25 @@ pipeline { {% if "docker-baseimage" not in project_repo_name %} sh "sed -r -i 's|(^FROM .*)|\\1\\n\\nENV LSIO_FIRST_PARTY=true|g' Dockerfile" {% endif %} - sh "docker buildx build \ - --label \"org.opencontainers.image.created=${GITHUB_DATE}\" \ - --label \"org.opencontainers.image.authors={{ lsio_project_name }}\" \ - --label \"org.opencontainers.image.url={{ project_github_repo_url }}/packages\" \ - --label \"org.opencontainers.image.documentation={{ lsio_docs_url }}/images/docker-{{ project_name }}\" \ - --label \"org.opencontainers.image.source={{ project_github_repo_url }}\" \ - --label \"org.opencontainers.image.version=${EXT_RELEASE_CLEAN}-ls${LS_TAG_NUMBER}\" \ - --label \"org.opencontainers.image.revision=${COMMIT_SHA}\" \ - --label \"org.opencontainers.image.vendor={{ lsio_project_name }}\" \ - --label \"org.opencontainers.image.licenses=GPL-3.0-only\" \ - --label \"org.opencontainers.image.ref.name=${COMMIT_SHA}\" \ - --label \"org.opencontainers.image.title={{ project_name|capitalize }}\" \ - --label \"org.opencontainers.image.description={% if project_blurb is defined %}{{ project_blurb | replace('"', '') | replace('\n', ' ') }}{% else %}{{ project_name }} image by {{ lsio_project_name }}{% endif %}\" \ - --no-cache --pull -t ${IMAGE}:amd64-${META_TAG} --platform=linux/amd64 \ - --provenance={{ image_provenance | lower }} --sbom={{ image_sbom | lower }} --builder={{ image_builder }} --load \ - --build-arg ${BUILD_VERSION_ARG}=${EXT_RELEASE} --build-arg VERSION=\"${VERSION_TAG}\" --build-arg BUILD_DATE=${GITHUB_DATE} ." + sh '''#! /bin/bash + source /tmp/retry_ghcr.sh + retry_ghcr docker buildx build \ + --label "org.opencontainers.image.created=${GITHUB_DATE}" \ + --label "org.opencontainers.image.authors={{ lsio_project_name }}" \ + --label "org.opencontainers.image.url={{ project_github_repo_url }}/packages" \ + --label "org.opencontainers.image.documentation={{ lsio_docs_url }}/images/docker-{{ project_name }}" \ + --label "org.opencontainers.image.source={{ project_github_repo_url }}" \ + --label "org.opencontainers.image.version=${EXT_RELEASE_CLEAN}-ls${LS_TAG_NUMBER}" \ + --label "org.opencontainers.image.revision=${COMMIT_SHA}" \ + --label "org.opencontainers.image.vendor={{ lsio_project_name }}" \ + --label "org.opencontainers.image.licenses=GPL-3.0-only" \ + --label "org.opencontainers.image.ref.name=${COMMIT_SHA}" \ + --label "org.opencontainers.image.title={{ project_name|capitalize }}" \ + --label "org.opencontainers.image.description={% if project_blurb is defined %}{{ project_blurb | replace('"', '') | replace('\n', ' ') }}{% else %}{{ project_name }} image by {{ lsio_project_name }}{% endif %}" \ + --no-cache --pull -t ${IMAGE}:amd64-${META_TAG} --platform=linux/amd64 \ + --provenance={{ image_provenance | lower }} --sbom={{ image_sbom | lower }} --builder={{ image_builder }} --load \ + --build-arg ${BUILD_VERSION_ARG}=${EXT_RELEASE} --build-arg VERSION="${VERSION_TAG}" --build-arg BUILD_DATE=${GITHUB_DATE} . + ''' sh '''#! /bin/bash set -e IFS=',' read -ra CACHE <<< "$BUILDCACHE" @@ -939,22 +997,62 @@ pipeline { {% if "docker-baseimage" not in project_repo_name %} sh "sed -r -i 's|(^FROM .*)|\\1\\n\\nENV LSIO_FIRST_PARTY=true|g' Dockerfile.aarch64" {% endif %} - sh "docker buildx build \ - --label \"org.opencontainers.image.created=${GITHUB_DATE}\" \ - --label \"org.opencontainers.image.authors={{ lsio_project_name }}\" \ - --label \"org.opencontainers.image.url={{ project_github_repo_url }}/packages\" \ - --label \"org.opencontainers.image.documentation={{ lsio_docs_url }}/images/docker-{{ project_name }}\" \ - --label \"org.opencontainers.image.source={{ project_github_repo_url }}\" \ - --label \"org.opencontainers.image.version=${EXT_RELEASE_CLEAN}-ls${LS_TAG_NUMBER}\" \ - --label \"org.opencontainers.image.revision=${COMMIT_SHA}\" \ - --label \"org.opencontainers.image.vendor={{ lsio_project_name }}\" \ - --label \"org.opencontainers.image.licenses=GPL-3.0-only\" \ - --label \"org.opencontainers.image.ref.name=${COMMIT_SHA}\" \ - --label \"org.opencontainers.image.title={{ project_name|capitalize }}\" \ - --label \"org.opencontainers.image.description={% if project_blurb is defined %}{{ project_blurb | replace('"', '') | replace('\n', ' ') }}{% else %}{{ project_name }} image by {{ lsio_project_name }}{% endif %}\" \ - --no-cache --pull -f Dockerfile.aarch64 -t ${IMAGE}:arm64v8-${META_TAG} --platform=linux/arm64 \ - --provenance={{ image_provenance | lower }} --sbom={{ image_sbom | lower }} --builder={{ image_builder }} --load \ - --build-arg ${BUILD_VERSION_ARG}=${EXT_RELEASE} --build-arg VERSION=\"${VERSION_TAG}\" --build-arg BUILD_DATE=${GITHUB_DATE} ." + sh '''#! /bin/bash + # create our retry function + retry_ghcr() { + local max_attempts=5 + local base_delay=1 + local max_delay=30 + local attempt=1 + + while true; do + rm -rf /tmp/cmdstderr + "$@" 2> >(tee /tmp/cmdstderr) + local exit_code="$?" + if [[ "${exit_code}" = "0" ]]; then + rm -rf /tmp/cmdstderr + return 0 + elif cat /tmp/cmdstderr | grep -q -v "retry-after:"; then + rm -rf /tmp/cmdstderr + return "$exit_code" + elif (( attempt >= max_attempts )); then + rm -rf /tmp/cmdstderr + echo "retry: $* failed after $attempt attempts (exit $exit_code)" >&2 + return "$exit_code" + else + # Calculate exponential delay: base * 2^(attempt-1), capped at max_delay + local delay=$(( base_delay * 2 ** (attempt - 1) )) + (( delay > max_delay )) && delay="$max_delay" + + # Apply full jitter (random delay between 0 and calculated delay) + local wait=$(( RANDOM % (delay + 1) )) + + rm -rf /tmp/cmdstderr + + echo "retry: attempt $attempt/$max_attempts failed (exit $exit_code); waiting ${wait}s..." >&2 + sleep "$wait" + ((attempt++)) + fi + done + } + declare -f retry_ghcr > /tmp/retry_ghcr.sh + retry_ghcr docker buildx build \ + --label "org.opencontainers.image.created=${GITHUB_DATE}" \ + --label "org.opencontainers.image.authors={{ lsio_project_name }}" \ + --label "org.opencontainers.image.url={{ project_github_repo_url }}/packages" \ + --label "org.opencontainers.image.documentation={{ lsio_docs_url }}/images/docker-{{ project_name }}" \ + --label "org.opencontainers.image.source={{ project_github_repo_url }}" \ + --label "org.opencontainers.image.version=${EXT_RELEASE_CLEAN}-ls${LS_TAG_NUMBER}" \ + --label "org.opencontainers.image.revision=${COMMIT_SHA}" \ + --label "org.opencontainers.image.vendor={{ lsio_project_name }}" \ + --label "org.opencontainers.image.licenses=GPL-3.0-only" \ + --label "org.opencontainers.image.ref.name=${COMMIT_SHA}" \ + --label "org.opencontainers.image.title={{ project_name|capitalize }}" \ + --label "org.opencontainers.image.description={% if project_blurb is defined %}{{ project_blurb | replace('"', '') | replace('\n', ' ') }}{% else %}{{ project_name }} image by {{ lsio_project_name }}{% endif %}" \ + --no-cache --pull -f Dockerfile.aarch64 -t ${IMAGE}:arm64v8-${META_TAG} --platform=linux/arm64 \ + --provenance={{ image_provenance | lower }} --sbom={{ image_sbom | lower }} --builder={{ image_builder }} --load \ + --build-arg ${BUILD_VERSION_ARG}=${EXT_RELEASE} --build-arg VERSION="${VERSION_TAG}" --build-arg BUILD_DATE=${GITHUB_DATE} . + ''' sh '''#! /bin/bash set -e IFS=',' read -ra CACHE <<< "$BUILDCACHE" @@ -1015,22 +1113,62 @@ pipeline { {% if "docker-baseimage" not in project_repo_name %} sh "sed -r -i 's|(^FROM .*)|\\1\\n\\nENV LSIO_FIRST_PARTY=true|g' Dockerfile.riscv64" {% endif %} - sh "docker buildx build \ - --label \"org.opencontainers.image.created=${GITHUB_DATE}\" \ - --label \"org.opencontainers.image.authors={{ lsio_project_name }}\" \ - --label \"org.opencontainers.image.url={{ project_github_repo_url }}/packages\" \ - --label \"org.opencontainers.image.documentation={{ lsio_docs_url }}/images/docker-{{ project_name }}\" \ - --label \"org.opencontainers.image.source={{ project_github_repo_url }}\" \ - --label \"org.opencontainers.image.version=${EXT_RELEASE_CLEAN}-ls${LS_TAG_NUMBER}\" \ - --label \"org.opencontainers.image.revision=${COMMIT_SHA}\" \ - --label \"org.opencontainers.image.vendor={{ lsio_project_name }}\" \ - --label \"org.opencontainers.image.licenses=GPL-3.0-only\" \ - --label \"org.opencontainers.image.ref.name=${COMMIT_SHA}\" \ - --label \"org.opencontainers.image.title={{ project_name|capitalize }}\" \ - --label \"org.opencontainers.image.description={% if project_blurb is defined %}{{ project_blurb | replace('"', '') | replace('\n', ' ') }}{% else %}{{ project_name }} image by {{ lsio_project_name }}{% endif %}\" \ - --no-cache --pull -f Dockerfile.riscv64 -t ${IMAGE}:riscv64-${META_TAG} --platform=linux/riscv64 \ - --provenance={{ image_provenance | lower }} --sbom={{ image_sbom | lower }} --builder={{ image_builder }} --load \ - --build-arg ${BUILD_VERSION_ARG}=${EXT_RELEASE} --build-arg VERSION=\"${VERSION_TAG}\" --build-arg BUILD_DATE=${GITHUB_DATE} ." + sh '''#! /bin/bash + # create our retry function + retry_ghcr() { + local max_attempts=5 + local base_delay=1 + local max_delay=30 + local attempt=1 + + while true; do + rm -rf /tmp/cmdstderr + "$@" 2> >(tee /tmp/cmdstderr) + local exit_code="$?" + if [[ "${exit_code}" = "0" ]]; then + rm -rf /tmp/cmdstderr + return 0 + elif cat /tmp/cmdstderr | grep -q -v "retry-after:"; then + rm -rf /tmp/cmdstderr + return "$exit_code" + elif (( attempt >= max_attempts )); then + rm -rf /tmp/cmdstderr + echo "retry: $* failed after $attempt attempts (exit $exit_code)" >&2 + return "$exit_code" + else + # Calculate exponential delay: base * 2^(attempt-1), capped at max_delay + local delay=$(( base_delay * 2 ** (attempt - 1) )) + (( delay > max_delay )) && delay="$max_delay" + + # Apply full jitter (random delay between 0 and calculated delay) + local wait=$(( RANDOM % (delay + 1) )) + + rm -rf /tmp/cmdstderr + + echo "retry: attempt $attempt/$max_attempts failed (exit $exit_code); waiting ${wait}s..." >&2 + sleep "$wait" + ((attempt++)) + fi + done + } + declare -f retry_ghcr > /tmp/retry_ghcr.sh + retry_ghcr docker buildx build \ + --label "org.opencontainers.image.created=${GITHUB_DATE}" \ + --label "org.opencontainers.image.authors={{ lsio_project_name }}" \ + --label "org.opencontainers.image.url={{ project_github_repo_url }}/packages" \ + --label "org.opencontainers.image.documentation={{ lsio_docs_url }}/images/docker-{{ project_name }}\" \ + --label "org.opencontainers.image.source={{ project_github_repo_url }}" \ + --label "org.opencontainers.image.version=${EXT_RELEASE_CLEAN}-ls${LS_TAG_NUMBER}" \ + --label "org.opencontainers.image.revision=${COMMIT_SHA}" \ + --label "org.opencontainers.image.vendor={{ lsio_project_name }}" \ + --label "org.opencontainers.image.licenses=GPL-3.0-only" \ + --label "org.opencontainers.image.ref.name=${COMMIT_SHA}" \ + --label "org.opencontainers.image.title={{ project_name|capitalize }}" \ + --label "org.opencontainers.image.description={% if project_blurb is defined %}{{ project_blurb | replace('"', '') | replace('\n', ' ') }}{% else %}{{ project_name }} image by {{ lsio_project_name }}{% endif %}" \ + --no-cache --pull -f Dockerfile.riscv64 -t ${IMAGE}:riscv64-${META_TAG} --platform=linux/riscv64 \ + --provenance={{ image_provenance | lower }} --sbom={{ image_sbom | lower }} --builder={{ image_builder }} --load \ + --build-arg ${BUILD_VERSION_ARG}=${EXT_RELEASE} --build-arg VERSION="${VERSION_TAG}" --build-arg BUILD_DATE=${GITHUB_DATE} . + ''' sh '''#! /bin/bash set -e IFS=',' read -ra CACHE <<< "$BUILDCACHE" @@ -1099,6 +1237,8 @@ pipeline { LOCAL_CONTAINER=${IMAGE}:${META_TAG} fi touch ${TEMPDIR}/package_versions.txt + source /tmp/retry_ghcr.sh + retry_ghcr docker pull ghcr.io/anchore/syft:${SYFT_IMAGE_TAG} docker run --rm \ -v /var/run/docker.sock:/var/run/docker.sock:ro \ -v ${TEMPDIR}:/tmp \ @@ -1191,13 +1331,14 @@ pipeline { CI_DOCKERENV="LSIO_FIRST_PARTY=true" fi fi - docker pull ghcr.io/linuxserver/ci:${CITEST_IMAGETAG} + source /tmp/retry_ghcr.sh + retry_ghcr docker pull ghcr.io/linuxserver/ci:${CITEST_IMAGETAG} if [ "${MULTIARCH}" == "true" ]; then - docker pull ghcr.io/linuxserver/lsiodev-buildcache:arm64v8-${COMMIT_SHA}-${BUILD_NUMBER} --platform=arm64 - docker tag ghcr.io/linuxserver/lsiodev-buildcache:arm64v8-${COMMIT_SHA}-${BUILD_NUMBER} ${IMAGE}:arm64v8-${META_TAG} + retry_ghcr docker pull ghcr.io/linuxserver/lsiodev-buildcache:arm64v8-${COMMIT_SHA}-${BUILD_NUMBER} --platform=arm64 + retry_ghcr docker tag ghcr.io/linuxserver/lsiodev-buildcache:arm64v8-${COMMIT_SHA}-${BUILD_NUMBER} ${IMAGE}:arm64v8-${META_TAG} {% if build_riscv64 %} - docker pull ghcr.io/linuxserver/lsiodev-buildcache:riscv64-${COMMIT_SHA}-${BUILD_NUMBER} --platform=riscv64 - docker tag ghcr.io/linuxserver/lsiodev-buildcache:riscv64-${COMMIT_SHA}-${BUILD_NUMBER} ${IMAGE}:riscv64-${META_TAG} + retry_ghcr docker pull ghcr.io/linuxserver/lsiodev-buildcache:riscv64-${COMMIT_SHA}-${BUILD_NUMBER} --platform=riscv64 + retry_ghcr docker tag ghcr.io/linuxserver/lsiodev-buildcache:riscv64-${COMMIT_SHA}-${BUILD_NUMBER} ${IMAGE}:riscv64-${META_TAG} {% endif %} fi docker run --rm \ From 1160202577dfce8968cdf4b7c40ab79159a486ee Mon Sep 17 00:00:00 2001 From: aptalca <541623+aptalca@users.noreply.github.com> Date: Fri, 9 Oct 2026 13:15:03 -0400 Subject: [PATCH 2/4] no need for the wrapper in tagging --- ansible/roles/repository/templates/Jenkinsfile.j2 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ansible/roles/repository/templates/Jenkinsfile.j2 b/ansible/roles/repository/templates/Jenkinsfile.j2 index 98121bd7..09dd6163 100644 --- a/ansible/roles/repository/templates/Jenkinsfile.j2 +++ b/ansible/roles/repository/templates/Jenkinsfile.j2 @@ -1335,10 +1335,10 @@ pipeline { retry_ghcr docker pull ghcr.io/linuxserver/ci:${CITEST_IMAGETAG} if [ "${MULTIARCH}" == "true" ]; then retry_ghcr docker pull ghcr.io/linuxserver/lsiodev-buildcache:arm64v8-${COMMIT_SHA}-${BUILD_NUMBER} --platform=arm64 - retry_ghcr docker tag ghcr.io/linuxserver/lsiodev-buildcache:arm64v8-${COMMIT_SHA}-${BUILD_NUMBER} ${IMAGE}:arm64v8-${META_TAG} + docker tag ghcr.io/linuxserver/lsiodev-buildcache:arm64v8-${COMMIT_SHA}-${BUILD_NUMBER} ${IMAGE}:arm64v8-${META_TAG} {% if build_riscv64 %} retry_ghcr docker pull ghcr.io/linuxserver/lsiodev-buildcache:riscv64-${COMMIT_SHA}-${BUILD_NUMBER} --platform=riscv64 - retry_ghcr docker tag ghcr.io/linuxserver/lsiodev-buildcache:riscv64-${COMMIT_SHA}-${BUILD_NUMBER} ${IMAGE}:riscv64-${META_TAG} + docker tag ghcr.io/linuxserver/lsiodev-buildcache:riscv64-${COMMIT_SHA}-${BUILD_NUMBER} ${IMAGE}:riscv64-${META_TAG} {% endif %} fi docker run --rm \ From 4f80589abb465287c1d5980be72e0dcebbed75cb Mon Sep 17 00:00:00 2001 From: thelamer Date: Fri, 9 Oct 2026 15:05:01 -0400 Subject: [PATCH 3/4] add gitlab_timeout env var rework retry loop a bit and catch two more cases --- .../roles/repository/templates/Jenkinsfile.j2 | 318 +++++++++--------- 1 file changed, 155 insertions(+), 163 deletions(-) diff --git a/ansible/roles/repository/templates/Jenkinsfile.j2 b/ansible/roles/repository/templates/Jenkinsfile.j2 index 09dd6163..4cf3f7ad 100644 --- a/ansible/roles/repository/templates/Jenkinsfile.j2 +++ b/ansible/roles/repository/templates/Jenkinsfile.j2 @@ -1,3 +1,46 @@ +{# optional gitlab_timeout from jenkins-vars.yml wraps registry.gitlab.com calls in timeout #} +{% set gitlab_timeout_cmd = '${TIMEOUT_CMD} ' if gitlab_timeout is defined else '' %} +{# bash function retrying ghcr pulls and builds on rate limit, written to the workspace once and inlined on remote nodes #} +{% set retry_ghcr_fn %} +retry_ghcr() { + local max_attempts=7 + local base_delay=10 + local max_delay=90 + local attempt=1 + local errfile exit_code delay pause + errfile=$(mktemp) + while true; do + # run inside an if so a caller's set -e cannot abort before we get to retry + if "$@" 2> >(tee "${errfile}" >&2); then + exit_code=0 + else + exit_code=$? + fi + # make sure tee has finished writing before we read the file + wait $! 2>/dev/null || true + if [[ "${exit_code}" == "0" ]]; then + rm -f "${errfile}" + return 0 + elif ! grep -q -i -E "retry-after:|toomanyrequests|too many requests" "${errfile}"; then + rm -f "${errfile}" + return "${exit_code}" + elif (( attempt >= max_attempts )); then + rm -f "${errfile}" + echo "retry: $* failed after ${attempt} attempts (exit ${exit_code})" >&2 + return "${exit_code}" + else + # exponential delay: base * 2^(attempt-1), capped at max_delay + delay=$(( base_delay * 2 ** (attempt - 1) )) + (( delay > max_delay )) && delay="${max_delay}" + # jitter between half and full delay so parallel builds spread out + pause=$(( delay / 2 + RANDOM % (delay / 2 + 1) )) + echo "retry: attempt ${attempt}/${max_attempts} failed (exit ${exit_code}); waiting ${pause}s..." >&2 + sleep "${pause}" + ((attempt++)) + fi + done +} +{% endset %} pipeline { agent { label 'X86-64-MULTI' @@ -37,6 +80,19 @@ pipeline { ''' } } + /* ############################ + Bash Function For GHCR Retry + ############################ */ + // Create a reusable script for a ghcr retry bash function + stage("Create Bash Function"){ + steps{ + sh '''#! /bin/bash + # create our retry function + {{ retry_ghcr_fn | indent(14) }} + declare -f retry_ghcr > ${WORKSPACE}/retry_ghcr.sh + ''' + } + } // Setup all the basic environment variables needed for the build stage("Set ENV Variables base"){ steps{ @@ -64,7 +120,9 @@ pipeline { env.CI_TEST_ATTEMPTED = '' env.PUSH_ATTEMPTED = '' env.LS_RELEASE = sh( - script: '''docker run --rm quay.io/skopeo/stable:v1 inspect docker://ghcr.io/${LS_USER}/${CONTAINER_NAME}:{{ release_tag }} 2>/dev/null | jq -r '.Labels.build_version' | awk '{print $3}' | grep '\\-ls' || : ''', + script: '''#! /bin/bash + source ${WORKSPACE}/retry_ghcr.sh + retry_ghcr docker run --rm quay.io/skopeo/stable:v1 inspect docker://ghcr.io/${LS_USER}/${CONTAINER_NAME}:{{ release_tag }} | jq -r '.Labels.build_version' | awk '{print $3}' | grep '\\-ls' || : ''', returnStdout: true).trim() env.LS_RELEASE_NOTES = sh( script: '''cat readme-vars.yml | awk -F \\" '/date: "[0-9][0-9].[0-9][0-9].[0-9][0-9]:/ {print $4;exit;}' | sed -E ':a;N;$!ba;s/\\r{0,1}\\n/\\\\n/g' ''', @@ -109,54 +167,6 @@ pipeline { } } } - /* ############################ - Bash Function For GHCR Retry - ############################ */ - // Create a reusable script for a ghcr retry bash function - stage("Create Bash Function"){ - steps{ - sh '''#! /bin/bash - # create our retry function - retry_ghcr() { - local max_attempts=5 - local base_delay=1 - local max_delay=30 - local attempt=1 - - while true; do - rm -rf /tmp/cmdstderr - "$@" 2> >(tee /tmp/cmdstderr) - local exit_code="$?" - if [[ "${exit_code}" = "0" ]]; then - rm -rf /tmp/cmdstderr - return 0 - elif cat /tmp/cmdstderr | grep -q -v "retry-after:"; then - rm -rf /tmp/cmdstderr - return "$exit_code" - elif (( attempt >= max_attempts )); then - rm -rf /tmp/cmdstderr - echo "retry: $* failed after $attempt attempts (exit $exit_code)" >&2 - return "$exit_code" - else - # Calculate exponential delay: base * 2^(attempt-1), capped at max_delay - local delay=$(( base_delay * 2 ** (attempt - 1) )) - (( delay > max_delay )) && delay="$max_delay" - - # Apply full jitter (random delay between 0 and calculated delay) - local wait=$(( RANDOM % (delay + 1) )) - - rm -rf /tmp/cmdstderr - - echo "retry: attempt $attempt/$max_attempts failed (exit $exit_code); waiting ${wait}s..." >&2 - sleep "$wait" - ((attempt++)) - fi - done - } - declare -f retry_ghcr > /tmp/retry_ghcr.sh - ''' - } - } /* ####################### Package Version Tagging ####################### */ @@ -258,7 +268,9 @@ pipeline { // If this is a deb repo release calculate a hash for the package version stage("Set EXT tag deb repo"){ steps{ - sh '''docker pull ${DIST_IMAGE}:${DIST_TAG}''' + sh '''#! /bin/bash + source ${WORKSPACE}/retry_ghcr.sh + retry_ghcr docker pull ${DIST_IMAGE}:${DIST_TAG}''' script{ env.EXT_RELEASE = sh( script: '''docker run --rm ${DIST_IMAGE}:${DIST_TAG} bash -c\ @@ -474,21 +486,24 @@ pipeline { // Build Docker container local templating CI runs stage('Build-Jenkins-Builder') { steps { - sh "docker buildx build \ - --label \"org.opencontainers.image.created=${GITHUB_DATE}\" \ - --label \"org.opencontainers.image.authors={{ lsio_project_name }}\" \ - --label \"org.opencontainers.image.url={{ project_github_repo_url }}/packages\" \ - --label \"org.opencontainers.image.documentation={{ lsio_docs_url }}/images/docker-{{ project_name }}\" \ - --label \"org.opencontainers.image.source={{ project_github_repo_url }}\" \ - --label \"org.opencontainers.image.version=${EXT_RELEASE_CLEAN}-ls${LS_TAG_NUMBER}\" \ - --label \"org.opencontainers.image.revision=${COMMIT_SHA}\" \ - --label \"org.opencontainers.image.vendor={{ lsio_project_name }}\" \ - --label \"org.opencontainers.image.licenses=GPL-3.0-only\" \ - --label \"org.opencontainers.image.ref.name=${COMMIT_SHA}\" \ - --label \"org.opencontainers.image.title={{ project_name|capitalize }}\" \ - --label \"org.opencontainers.image.description={% if project_blurb is defined %}{{ project_blurb | replace('"', '') | replace('\n', ' ') }}{% else %}{{ project_name }} image by {{ lsio_project_name }}{% endif %}\" \ - --provenance=false --sbom=false --builder=default \ - --no-cache --pull -t jenkinslocal:${COMMIT_SHA}-${BUILD_NUMBER} --platform=linux/amd64 ." + sh '''#! /bin/bash + source ${WORKSPACE}/retry_ghcr.sh + retry_ghcr docker buildx build \ + --label "org.opencontainers.image.created=${GITHUB_DATE}" \ + --label "org.opencontainers.image.authors={{ lsio_project_name }}" \ + --label "org.opencontainers.image.url={{ project_github_repo_url }}/packages" \ + --label "org.opencontainers.image.documentation={{ lsio_docs_url }}/images/docker-{{ project_name }}" \ + --label "org.opencontainers.image.source={{ project_github_repo_url }}" \ + --label "org.opencontainers.image.version=${EXT_RELEASE_CLEAN}-ls${LS_TAG_NUMBER}" \ + --label "org.opencontainers.image.revision=${COMMIT_SHA}" \ + --label "org.opencontainers.image.vendor={{ lsio_project_name }}" \ + --label "org.opencontainers.image.licenses=GPL-3.0-only" \ + --label "org.opencontainers.image.ref.name=${COMMIT_SHA}" \ + --label "org.opencontainers.image.title={{ project_name|capitalize }}" \ + --label "org.opencontainers.image.description={% if project_blurb is defined %}{{ project_blurb | replace('"', '') | replace('\n', ' ') }}{% else %}{{ project_name }} image by {{ lsio_project_name }}{% endif %}" \ + --provenance=false --sbom=false --builder=default \ + --no-cache --pull -t jenkinslocal:${COMMIT_SHA}-${BUILD_NUMBER} --platform=linux/amd64 . + ''' } } {% endif %} @@ -507,7 +522,7 @@ pipeline { } sh '''curl -sL https://raw.githubusercontent.com/linuxserver/docker-jenkins-builder/master/checkrun.sh | /bin/bash''' sh '''#! /bin/bash - source /tmp/retry_ghcr.sh + source ${WORKSPACE}/retry_ghcr.sh retry_ghcr docker pull ghcr.io/linuxserver/baseimage-alpine:3.23 docker run --rm \ -v ${WORKSPACE}:/mnt \ @@ -535,7 +550,7 @@ pipeline { sh '''#! /bin/bash set -e TEMPDIR=$(mktemp -d) - source /tmp/retry_ghcr.sh + source ${WORKSPACE}/retry_ghcr.sh {% if project_repo_name != "docker-jenkins-builder" %} retry_ghcr docker pull ghcr.io/linuxserver/jenkins-builder:latest {% endif %} @@ -851,7 +866,7 @@ pipeline { sh "sed -r -i 's|(^FROM .*)|\\1\\n\\nENV LSIO_FIRST_PARTY=true|g' Dockerfile" {% endif %} sh '''#! /bin/bash - source /tmp/retry_ghcr.sh + source ${WORKSPACE}/retry_ghcr.sh retry_ghcr docker buildx build \ --label "org.opencontainers.image.created=${GITHUB_DATE}" \ --label "org.opencontainers.image.authors={{ lsio_project_name }}" \ @@ -896,7 +911,14 @@ pipeline { declare -A pids IFS=',' read -ra CACHE <<< "$BUILDCACHE" for i in "${CACHE[@]}"; do - docker push ${i}:amd64-${COMMIT_SHA}-${BUILD_NUMBER} & +{% if gitlab_timeout is defined %} + if [[ "${i}" == *"registry.gitlab.com"* ]]; then + TIMEOUT_CMD="timeout {{ gitlab_timeout }}" + else + TIMEOUT_CMD="" + fi +{% endif %} + {{ gitlab_timeout_cmd }}docker push ${i}:amd64-${COMMIT_SHA}-${BUILD_NUMBER} & pids[$!]="$i" done for p in "${!pids[@]}"; do @@ -927,7 +949,7 @@ pipeline { sh "sed -r -i 's|(^FROM .*)|\\1\\n\\nENV LSIO_FIRST_PARTY=true|g' Dockerfile" {% endif %} sh '''#! /bin/bash - source /tmp/retry_ghcr.sh + source ${WORKSPACE}/retry_ghcr.sh retry_ghcr docker buildx build \ --label "org.opencontainers.image.created=${GITHUB_DATE}" \ --label "org.opencontainers.image.authors={{ lsio_project_name }}" \ @@ -972,7 +994,14 @@ pipeline { declare -A pids IFS=',' read -ra CACHE <<< "$BUILDCACHE" for i in "${CACHE[@]}"; do - docker push ${i}:amd64-${COMMIT_SHA}-${BUILD_NUMBER} & +{% if gitlab_timeout is defined %} + if [[ "${i}" == *"registry.gitlab.com"* ]]; then + TIMEOUT_CMD="timeout {{ gitlab_timeout }}" + else + TIMEOUT_CMD="" + fi +{% endif %} + {{ gitlab_timeout_cmd }}docker push ${i}:amd64-${COMMIT_SHA}-${BUILD_NUMBER} & pids[$!]="$i" done for p in "${!pids[@]}"; do @@ -999,43 +1028,7 @@ pipeline { {% endif %} sh '''#! /bin/bash # create our retry function - retry_ghcr() { - local max_attempts=5 - local base_delay=1 - local max_delay=30 - local attempt=1 - - while true; do - rm -rf /tmp/cmdstderr - "$@" 2> >(tee /tmp/cmdstderr) - local exit_code="$?" - if [[ "${exit_code}" = "0" ]]; then - rm -rf /tmp/cmdstderr - return 0 - elif cat /tmp/cmdstderr | grep -q -v "retry-after:"; then - rm -rf /tmp/cmdstderr - return "$exit_code" - elif (( attempt >= max_attempts )); then - rm -rf /tmp/cmdstderr - echo "retry: $* failed after $attempt attempts (exit $exit_code)" >&2 - return "$exit_code" - else - # Calculate exponential delay: base * 2^(attempt-1), capped at max_delay - local delay=$(( base_delay * 2 ** (attempt - 1) )) - (( delay > max_delay )) && delay="$max_delay" - - # Apply full jitter (random delay between 0 and calculated delay) - local wait=$(( RANDOM % (delay + 1) )) - - rm -rf /tmp/cmdstderr - - echo "retry: attempt $attempt/$max_attempts failed (exit $exit_code); waiting ${wait}s..." >&2 - sleep "$wait" - ((attempt++)) - fi - done - } - declare -f retry_ghcr > /tmp/retry_ghcr.sh + {{ retry_ghcr_fn | indent(18) }} retry_ghcr docker buildx build \ --label "org.opencontainers.image.created=${GITHUB_DATE}" \ --label "org.opencontainers.image.authors={{ lsio_project_name }}" \ @@ -1079,7 +1072,14 @@ pipeline { declare -A pids IFS=',' read -ra CACHE <<< "$BUILDCACHE" for i in "${CACHE[@]}"; do - docker push ${i}:arm64v8-${COMMIT_SHA}-${BUILD_NUMBER} & +{% if gitlab_timeout is defined %} + if [[ "${i}" == *"registry.gitlab.com"* ]]; then + TIMEOUT_CMD="timeout {{ gitlab_timeout }}" + else + TIMEOUT_CMD="" + fi +{% endif %} + {{ gitlab_timeout_cmd }}docker push ${i}:arm64v8-${COMMIT_SHA}-${BUILD_NUMBER} & pids[$!]="$i" done for p in "${!pids[@]}"; do @@ -1115,43 +1115,7 @@ pipeline { {% endif %} sh '''#! /bin/bash # create our retry function - retry_ghcr() { - local max_attempts=5 - local base_delay=1 - local max_delay=30 - local attempt=1 - - while true; do - rm -rf /tmp/cmdstderr - "$@" 2> >(tee /tmp/cmdstderr) - local exit_code="$?" - if [[ "${exit_code}" = "0" ]]; then - rm -rf /tmp/cmdstderr - return 0 - elif cat /tmp/cmdstderr | grep -q -v "retry-after:"; then - rm -rf /tmp/cmdstderr - return "$exit_code" - elif (( attempt >= max_attempts )); then - rm -rf /tmp/cmdstderr - echo "retry: $* failed after $attempt attempts (exit $exit_code)" >&2 - return "$exit_code" - else - # Calculate exponential delay: base * 2^(attempt-1), capped at max_delay - local delay=$(( base_delay * 2 ** (attempt - 1) )) - (( delay > max_delay )) && delay="$max_delay" - - # Apply full jitter (random delay between 0 and calculated delay) - local wait=$(( RANDOM % (delay + 1) )) - - rm -rf /tmp/cmdstderr - - echo "retry: attempt $attempt/$max_attempts failed (exit $exit_code); waiting ${wait}s..." >&2 - sleep "$wait" - ((attempt++)) - fi - done - } - declare -f retry_ghcr > /tmp/retry_ghcr.sh + {{ retry_ghcr_fn | indent(18) }} retry_ghcr docker buildx build \ --label "org.opencontainers.image.created=${GITHUB_DATE}" \ --label "org.opencontainers.image.authors={{ lsio_project_name }}" \ @@ -1196,7 +1160,14 @@ pipeline { declare -A pids IFS=',' read -ra CACHE <<< "$BUILDCACHE" for i in "${CACHE[@]}"; do - docker push ${i}:riscv64-${COMMIT_SHA}-${BUILD_NUMBER} & +{% if gitlab_timeout is defined %} + if [[ "${i}" == *"registry.gitlab.com"* ]]; then + TIMEOUT_CMD="timeout {{ gitlab_timeout }}" + else + TIMEOUT_CMD="" + fi +{% endif %} + {{ gitlab_timeout_cmd }}docker push ${i}:riscv64-${COMMIT_SHA}-${BUILD_NUMBER} & pids[$!]="$i" done for p in "${!pids[@]}"; do @@ -1237,7 +1208,7 @@ pipeline { LOCAL_CONTAINER=${IMAGE}:${META_TAG} fi touch ${TEMPDIR}/package_versions.txt - source /tmp/retry_ghcr.sh + source ${WORKSPACE}/retry_ghcr.sh retry_ghcr docker pull ghcr.io/anchore/syft:${SYFT_IMAGE_TAG} docker run --rm \ -v /var/run/docker.sock:/var/run/docker.sock:ro \ @@ -1331,7 +1302,7 @@ pipeline { CI_DOCKERENV="LSIO_FIRST_PARTY=true" fi fi - source /tmp/retry_ghcr.sh + source ${WORKSPACE}/retry_ghcr.sh retry_ghcr docker pull ghcr.io/linuxserver/ci:${CITEST_IMAGETAG} if [ "${MULTIARCH}" == "true" ]; then retry_ghcr docker pull ghcr.io/linuxserver/lsiodev-buildcache:arm64v8-${COMMIT_SHA}-${BUILD_NUMBER} --platform=arm64 @@ -1397,6 +1368,13 @@ pipeline { sh '''#! /bin/bash set -e for PUSHIMAGE in "${IMAGE}" "${GITLABIMAGE}" "${GITHUBIMAGE}" "${QUAYIMAGE}"; do +{% if gitlab_timeout is defined %} + if [[ "${PUSHIMAGE}" == "${GITLABIMAGE}" ]]; then + TIMEOUT_CMD="timeout {{ gitlab_timeout }}" + else + TIMEOUT_CMD="" + fi +{% endif %} [[ ${PUSHIMAGE%%/*} =~ \\. ]] && PUSHIMAGEPLUS="${PUSHIMAGE}" || PUSHIMAGEPLUS="docker.io/${PUSHIMAGE}" IFS=',' read -ra CACHE <<< "$BUILDCACHE" for i in "${CACHE[@]}"; do @@ -1404,14 +1382,14 @@ pipeline { CACHEIMAGE=${i} fi done - docker buildx imagetools create --prefer-index=false -t ${PUSHIMAGE}:${META_TAG} -t ${PUSHIMAGE}:{{ release_tag }} -t ${PUSHIMAGE}:${EXT_RELEASE_TAG} ${CACHEIMAGE}:amd64-${COMMIT_SHA}-${BUILD_NUMBER} || \ + {{ gitlab_timeout_cmd }}docker buildx imagetools create --prefer-index=false -t ${PUSHIMAGE}:${META_TAG} -t ${PUSHIMAGE}:{{ release_tag }} -t ${PUSHIMAGE}:${EXT_RELEASE_TAG} ${CACHEIMAGE}:amd64-${COMMIT_SHA}-${BUILD_NUMBER} || \ { if [[ "${PUSHIMAGE}" != "${QUAYIMAGE}" && "${PUSHIMAGE}" != "${GITLABIMAGE}" ]]; then exit 1; fi; } if [ -n "${SEMVER}" ]; then - docker buildx imagetools create --prefer-index=false -t ${PUSHIMAGE}:${SEMVER} ${CACHEIMAGE}:amd64-${COMMIT_SHA}-${BUILD_NUMBER} || \ + {{ gitlab_timeout_cmd }}docker buildx imagetools create --prefer-index=false -t ${PUSHIMAGE}:${SEMVER} ${CACHEIMAGE}:amd64-${COMMIT_SHA}-${BUILD_NUMBER} || \ { if [[ "${PUSHIMAGE}" != "${QUAYIMAGE}" && "${PUSHIMAGE}" != "${GITLABIMAGE}" ]]; then exit 1; fi; } fi {% if project_deprecation_status %} - docker buildx imagetools create -t ${PUSHIMAGE}:{{ release_tag }} ghcr.io/linuxserver/jenkins-builder:empty || true + {{ gitlab_timeout_cmd }}docker buildx imagetools create -t ${PUSHIMAGE}:{{ release_tag }} ghcr.io/linuxserver/jenkins-builder:empty || true {% endif %} done ''' @@ -1432,6 +1410,13 @@ pipeline { sh '''#! /bin/bash set -e for MANIFESTIMAGE in "${IMAGE}" "${GITLABIMAGE}" "${GITHUBIMAGE}" "${QUAYIMAGE}"; do +{% if gitlab_timeout is defined %} + if [[ "${MANIFESTIMAGE}" == "${GITLABIMAGE}" ]]; then + TIMEOUT_CMD="timeout {{ gitlab_timeout }}" + else + TIMEOUT_CMD="" + fi +{% endif %} if [[ "${MANIFESTIMAGE%%/*}" =~ \\. ]]; then MANIFESTIMAGEPLUS="${MANIFESTIMAGE}" else @@ -1443,38 +1428,45 @@ pipeline { CACHEIMAGE=${i} fi done - docker buildx imagetools create --prefer-index=false -t ${MANIFESTIMAGE}:amd64-${META_TAG} -t ${MANIFESTIMAGE}:amd64-{{ release_tag }} -t ${MANIFESTIMAGE}:amd64-${EXT_RELEASE_TAG} ${CACHEIMAGE}:amd64-${COMMIT_SHA}-${BUILD_NUMBER} || \ + {{ gitlab_timeout_cmd }}docker buildx imagetools create --prefer-index=false -t ${MANIFESTIMAGE}:amd64-${META_TAG} -t ${MANIFESTIMAGE}:amd64-{{ release_tag }} -t ${MANIFESTIMAGE}:amd64-${EXT_RELEASE_TAG} ${CACHEIMAGE}:amd64-${COMMIT_SHA}-${BUILD_NUMBER} || \ { if [[ "${MANIFESTIMAGE}" != "${QUAYIMAGE}" && "${MANIFESTIMAGE}" != "${GITLABIMAGE}" ]]; then exit 1; fi; } - docker buildx imagetools create --prefer-index=false -t ${MANIFESTIMAGE}:arm64v8-${META_TAG} -t ${MANIFESTIMAGE}:arm64v8-{{ release_tag }} -t ${MANIFESTIMAGE}:arm64v8-${EXT_RELEASE_TAG} ${CACHEIMAGE}:arm64v8-${COMMIT_SHA}-${BUILD_NUMBER} || \ + {{ gitlab_timeout_cmd }}docker buildx imagetools create --prefer-index=false -t ${MANIFESTIMAGE}:arm64v8-${META_TAG} -t ${MANIFESTIMAGE}:arm64v8-{{ release_tag }} -t ${MANIFESTIMAGE}:arm64v8-${EXT_RELEASE_TAG} ${CACHEIMAGE}:arm64v8-${COMMIT_SHA}-${BUILD_NUMBER} || \ { if [[ "${MANIFESTIMAGE}" != "${QUAYIMAGE}" && "${MANIFESTIMAGE}" != "${GITLABIMAGE}" ]]; then exit 1; fi; } {% if build_riscv64 %} - docker buildx imagetools create --prefer-index=false -t ${MANIFESTIMAGE}:riscv64-${META_TAG} -t ${MANIFESTIMAGE}:riscv64-{{ release_tag }} -t ${MANIFESTIMAGE}:riscv64-${EXT_RELEASE_TAG} ${CACHEIMAGE}:riscv64-${COMMIT_SHA}-${BUILD_NUMBER} || \ + {{ gitlab_timeout_cmd }}docker buildx imagetools create --prefer-index=false -t ${MANIFESTIMAGE}:riscv64-${META_TAG} -t ${MANIFESTIMAGE}:riscv64-{{ release_tag }} -t ${MANIFESTIMAGE}:riscv64-${EXT_RELEASE_TAG} ${CACHEIMAGE}:riscv64-${COMMIT_SHA}-${BUILD_NUMBER} || \ { if [[ "${MANIFESTIMAGE}" != "${QUAYIMAGE}" && "${MANIFESTIMAGE}" != "${GITLABIMAGE}" ]]; then exit 1; fi; } {% endif %} if [ -n "${SEMVER}" ]; then - docker buildx imagetools create --prefer-index=false -t ${MANIFESTIMAGE}:amd64-${SEMVER} ${CACHEIMAGE}:amd64-${COMMIT_SHA}-${BUILD_NUMBER} || \ + {{ gitlab_timeout_cmd }}docker buildx imagetools create --prefer-index=false -t ${MANIFESTIMAGE}:amd64-${SEMVER} ${CACHEIMAGE}:amd64-${COMMIT_SHA}-${BUILD_NUMBER} || \ { if [[ "${MANIFESTIMAGE}" != "${QUAYIMAGE}" && "${MANIFESTIMAGE}" != "${GITLABIMAGE}" ]]; then exit 1; fi; } - docker buildx imagetools create --prefer-index=false -t ${MANIFESTIMAGE}:arm64v8-${SEMVER} ${CACHEIMAGE}:arm64v8-${COMMIT_SHA}-${BUILD_NUMBER} || \ + {{ gitlab_timeout_cmd }}docker buildx imagetools create --prefer-index=false -t ${MANIFESTIMAGE}:arm64v8-${SEMVER} ${CACHEIMAGE}:arm64v8-${COMMIT_SHA}-${BUILD_NUMBER} || \ { if [[ "${MANIFESTIMAGE}" != "${QUAYIMAGE}" && "${MANIFESTIMAGE}" != "${GITLABIMAGE}" ]]; then exit 1; fi; } {% if build_riscv64 %} - docker buildx imagetools create --prefer-index=false -t ${MANIFESTIMAGE}:riscv64-${SEMVER} ${CACHEIMAGE}:riscv64-${COMMIT_SHA}-${BUILD_NUMBER} || \ + {{ gitlab_timeout_cmd }}docker buildx imagetools create --prefer-index=false -t ${MANIFESTIMAGE}:riscv64-${SEMVER} ${CACHEIMAGE}:riscv64-${COMMIT_SHA}-${BUILD_NUMBER} || \ { if [[ "${MANIFESTIMAGE}" != "${QUAYIMAGE}" && "${MANIFESTIMAGE}" != "${GITLABIMAGE}" ]]; then exit 1; fi; } {% endif %} fi done for MANIFESTIMAGE in "${IMAGE}" "${GITLABIMAGE}" "${GITHUBIMAGE}" "${QUAYIMAGE}"; do +{% if gitlab_timeout is defined %} + if [[ "${MANIFESTIMAGE}" == "${GITLABIMAGE}" ]]; then + TIMEOUT_CMD="timeout {{ gitlab_timeout }}" + else + TIMEOUT_CMD="" + fi +{% endif %} {% if project_deprecation_status %} - docker buildx imagetools create -t ${MANIFESTIMAGE}:{{ release_tag }} -t ${MANIFESTIMAGE}:amd64-{{ release_tag }} -t ${MANIFESTIMAGE}:arm64v8-{{ release_tag }}{% if build_riscv64 %} -t ${MANIFESTIMAGE}:riscv64-{{ release_tag }}{% endif %} ghcr.io/linuxserver/jenkins-builder:empty || true + {{ gitlab_timeout_cmd }}docker buildx imagetools create -t ${MANIFESTIMAGE}:{{ release_tag }} -t ${MANIFESTIMAGE}:amd64-{{ release_tag }} -t ${MANIFESTIMAGE}:arm64v8-{{ release_tag }}{% if build_riscv64 %} -t ${MANIFESTIMAGE}:riscv64-{{ release_tag }}{% endif %} ghcr.io/linuxserver/jenkins-builder:empty || true {% else %} - docker buildx imagetools create -t ${MANIFESTIMAGE}:{{ release_tag }} ${MANIFESTIMAGE}:amd64-{{ release_tag }}{% if build_riscv64 %} ${MANIFESTIMAGE}:riscv64-{{ release_tag }}{% endif %} ${MANIFESTIMAGE}:arm64v8-{{ release_tag }} || \ + {{ gitlab_timeout_cmd }}docker buildx imagetools create -t ${MANIFESTIMAGE}:{{ release_tag }} ${MANIFESTIMAGE}:amd64-{{ release_tag }}{% if build_riscv64 %} ${MANIFESTIMAGE}:riscv64-{{ release_tag }}{% endif %} ${MANIFESTIMAGE}:arm64v8-{{ release_tag }} || \ { if [[ "${MANIFESTIMAGE}" != "${QUAYIMAGE}" && "${MANIFESTIMAGE}" != "${GITLABIMAGE}" ]]; then exit 1; fi; } {% endif %} - docker buildx imagetools create -t ${MANIFESTIMAGE}:${META_TAG} ${MANIFESTIMAGE}:amd64-${META_TAG}{% if build_riscv64 %} ${MANIFESTIMAGE}:riscv64-${META_TAG}{% endif %} ${MANIFESTIMAGE}:arm64v8-${META_TAG} || \ + {{ gitlab_timeout_cmd }}docker buildx imagetools create -t ${MANIFESTIMAGE}:${META_TAG} ${MANIFESTIMAGE}:amd64-${META_TAG}{% if build_riscv64 %} ${MANIFESTIMAGE}:riscv64-${META_TAG}{% endif %} ${MANIFESTIMAGE}:arm64v8-${META_TAG} || \ { if [[ "${MANIFESTIMAGE}" != "${QUAYIMAGE}" && "${MANIFESTIMAGE}" != "${GITLABIMAGE}" ]]; then exit 1; fi; } - docker buildx imagetools create -t ${MANIFESTIMAGE}:${EXT_RELEASE_TAG} ${MANIFESTIMAGE}:amd64-${EXT_RELEASE_TAG}{% if build_riscv64 %} ${MANIFESTIMAGE}:riscv64-${EXT_RELEASE_TAG}{% endif %} ${MANIFESTIMAGE}:arm64v8-${EXT_RELEASE_TAG} || \ + {{ gitlab_timeout_cmd }}docker buildx imagetools create -t ${MANIFESTIMAGE}:${EXT_RELEASE_TAG} ${MANIFESTIMAGE}:amd64-${EXT_RELEASE_TAG}{% if build_riscv64 %} ${MANIFESTIMAGE}:riscv64-${EXT_RELEASE_TAG}{% endif %} ${MANIFESTIMAGE}:arm64v8-${EXT_RELEASE_TAG} || \ { if [[ "${MANIFESTIMAGE}" != "${QUAYIMAGE}" && "${MANIFESTIMAGE}" != "${GITLABIMAGE}" ]]; then exit 1; fi; } if [ -n "${SEMVER}" ]; then - docker buildx imagetools create -t ${MANIFESTIMAGE}:${SEMVER} ${MANIFESTIMAGE}:amd64-${SEMVER}{% if build_riscv64 %} ${MANIFESTIMAGE}:riscv64-${SEMVER}{% endif %} ${MANIFESTIMAGE}:arm64v8-${SEMVER} || \ + {{ gitlab_timeout_cmd }}docker buildx imagetools create -t ${MANIFESTIMAGE}:${SEMVER} ${MANIFESTIMAGE}:amd64-${SEMVER}{% if build_riscv64 %} ${MANIFESTIMAGE}:riscv64-${SEMVER}{% endif %} ${MANIFESTIMAGE}:arm64v8-${SEMVER} || \ { if [[ "${MANIFESTIMAGE}" != "${QUAYIMAGE}" && "${MANIFESTIMAGE}" != "${GITLABIMAGE}" ]]; then exit 1; fi; } fi done From 935764f5c882b13a506551acdba8bada30e59414 Mon Sep 17 00:00:00 2001 From: thelamer Date: Fri, 9 Oct 2026 17:06:19 -0400 Subject: [PATCH 4/4] add gitlab timout as var in template default to 600 --- .../roles/repository/templates/Jenkinsfile.j2 | 78 ++++++++----------- 1 file changed, 33 insertions(+), 45 deletions(-) diff --git a/ansible/roles/repository/templates/Jenkinsfile.j2 b/ansible/roles/repository/templates/Jenkinsfile.j2 index 4cf3f7ad..cab8e66a 100644 --- a/ansible/roles/repository/templates/Jenkinsfile.j2 +++ b/ansible/roles/repository/templates/Jenkinsfile.j2 @@ -1,5 +1,3 @@ -{# optional gitlab_timeout from jenkins-vars.yml wraps registry.gitlab.com calls in timeout #} -{% set gitlab_timeout_cmd = '${TIMEOUT_CMD} ' if gitlab_timeout is defined else '' %} {# bash function retrying ghcr pulls and builds on rate limit, written to the workspace once and inlined on remote nodes #} {% set retry_ghcr_fn %} retry_ghcr() { @@ -143,8 +141,12 @@ pipeline { if ( env.SYFT_IMAGE_TAG == null ) { env.SYFT_IMAGE_TAG = 'latest' } + if ( env.GITLAB_TIMEOUT == null ) { + env.GITLAB_TIMEOUT = '600' + } } echo "Using syft image tag ${SYFT_IMAGE_TAG}" + echo "Using gitlab registry timeout ${GITLAB_TIMEOUT}" sh '''#! /bin/bash echo "The default github branch detected as ${GH_DEFAULT_BRANCH}" ''' script{ @@ -911,18 +913,16 @@ pipeline { declare -A pids IFS=',' read -ra CACHE <<< "$BUILDCACHE" for i in "${CACHE[@]}"; do -{% if gitlab_timeout is defined %} if [[ "${i}" == *"registry.gitlab.com"* ]]; then - TIMEOUT_CMD="timeout {{ gitlab_timeout }}" + TIMEOUT_CMD="timeout ${GITLAB_TIMEOUT}" else TIMEOUT_CMD="" fi -{% endif %} - {{ gitlab_timeout_cmd }}docker push ${i}:amd64-${COMMIT_SHA}-${BUILD_NUMBER} & + ${TIMEOUT_CMD} docker push ${i}:amd64-${COMMIT_SHA}-${BUILD_NUMBER} & pids[$!]="$i" done for p in "${!pids[@]}"; do - wait "$p" || { [[ "${pids[$p]}" != *"quay.io"* && "${pids[$p]}" != *"registry.gitlab.com"* ]] && exit 1; } + wait "$p" || { if [[ "${pids[$p]}" != *"quay.io"* && "${pids[$p]}" != *"registry.gitlab.com"* ]]; then exit 1; fi; } done fi ''' @@ -994,18 +994,16 @@ pipeline { declare -A pids IFS=',' read -ra CACHE <<< "$BUILDCACHE" for i in "${CACHE[@]}"; do -{% if gitlab_timeout is defined %} if [[ "${i}" == *"registry.gitlab.com"* ]]; then - TIMEOUT_CMD="timeout {{ gitlab_timeout }}" + TIMEOUT_CMD="timeout ${GITLAB_TIMEOUT}" else TIMEOUT_CMD="" fi -{% endif %} - {{ gitlab_timeout_cmd }}docker push ${i}:amd64-${COMMIT_SHA}-${BUILD_NUMBER} & + ${TIMEOUT_CMD} docker push ${i}:amd64-${COMMIT_SHA}-${BUILD_NUMBER} & pids[$!]="$i" done for p in "${!pids[@]}"; do - wait "$p" || { [[ "${pids[$p]}" != *"quay.io"* && "${pids[$p]}" != *"registry.gitlab.com"* ]] && exit 1; } + wait "$p" || { if [[ "${pids[$p]}" != *"quay.io"* && "${pids[$p]}" != *"registry.gitlab.com"* ]]; then exit 1; fi; } done fi ''' @@ -1072,18 +1070,16 @@ pipeline { declare -A pids IFS=',' read -ra CACHE <<< "$BUILDCACHE" for i in "${CACHE[@]}"; do -{% if gitlab_timeout is defined %} if [[ "${i}" == *"registry.gitlab.com"* ]]; then - TIMEOUT_CMD="timeout {{ gitlab_timeout }}" + TIMEOUT_CMD="timeout ${GITLAB_TIMEOUT}" else TIMEOUT_CMD="" fi -{% endif %} - {{ gitlab_timeout_cmd }}docker push ${i}:arm64v8-${COMMIT_SHA}-${BUILD_NUMBER} & + ${TIMEOUT_CMD} docker push ${i}:arm64v8-${COMMIT_SHA}-${BUILD_NUMBER} & pids[$!]="$i" done for p in "${!pids[@]}"; do - wait "$p" || { [[ "${pids[$p]}" != *"quay.io"* && "${pids[$p]}" != *"registry.gitlab.com"* ]] && exit 1; } + wait "$p" || { if [[ "${pids[$p]}" != *"quay.io"* && "${pids[$p]}" != *"registry.gitlab.com"* ]]; then exit 1; fi; } done fi ''' @@ -1160,18 +1156,16 @@ pipeline { declare -A pids IFS=',' read -ra CACHE <<< "$BUILDCACHE" for i in "${CACHE[@]}"; do -{% if gitlab_timeout is defined %} if [[ "${i}" == *"registry.gitlab.com"* ]]; then - TIMEOUT_CMD="timeout {{ gitlab_timeout }}" + TIMEOUT_CMD="timeout ${GITLAB_TIMEOUT}" else TIMEOUT_CMD="" fi -{% endif %} - {{ gitlab_timeout_cmd }}docker push ${i}:riscv64-${COMMIT_SHA}-${BUILD_NUMBER} & + ${TIMEOUT_CMD} docker push ${i}:riscv64-${COMMIT_SHA}-${BUILD_NUMBER} & pids[$!]="$i" done for p in "${!pids[@]}"; do - wait "$p" || { [[ "${pids[$p]}" != *"quay.io"* && "${pids[$p]}" != *"registry.gitlab.com"* ]] && exit 1; } + wait "$p" || { if [[ "${pids[$p]}" != *"quay.io"* && "${pids[$p]}" != *"registry.gitlab.com"* ]]; then exit 1; fi; } done fi ''' @@ -1368,13 +1362,11 @@ pipeline { sh '''#! /bin/bash set -e for PUSHIMAGE in "${IMAGE}" "${GITLABIMAGE}" "${GITHUBIMAGE}" "${QUAYIMAGE}"; do -{% if gitlab_timeout is defined %} if [[ "${PUSHIMAGE}" == "${GITLABIMAGE}" ]]; then - TIMEOUT_CMD="timeout {{ gitlab_timeout }}" + TIMEOUT_CMD="timeout ${GITLAB_TIMEOUT}" else TIMEOUT_CMD="" fi -{% endif %} [[ ${PUSHIMAGE%%/*} =~ \\. ]] && PUSHIMAGEPLUS="${PUSHIMAGE}" || PUSHIMAGEPLUS="docker.io/${PUSHIMAGE}" IFS=',' read -ra CACHE <<< "$BUILDCACHE" for i in "${CACHE[@]}"; do @@ -1382,14 +1374,14 @@ pipeline { CACHEIMAGE=${i} fi done - {{ gitlab_timeout_cmd }}docker buildx imagetools create --prefer-index=false -t ${PUSHIMAGE}:${META_TAG} -t ${PUSHIMAGE}:{{ release_tag }} -t ${PUSHIMAGE}:${EXT_RELEASE_TAG} ${CACHEIMAGE}:amd64-${COMMIT_SHA}-${BUILD_NUMBER} || \ + ${TIMEOUT_CMD} docker buildx imagetools create --prefer-index=false -t ${PUSHIMAGE}:${META_TAG} -t ${PUSHIMAGE}:{{ release_tag }} -t ${PUSHIMAGE}:${EXT_RELEASE_TAG} ${CACHEIMAGE}:amd64-${COMMIT_SHA}-${BUILD_NUMBER} || \ { if [[ "${PUSHIMAGE}" != "${QUAYIMAGE}" && "${PUSHIMAGE}" != "${GITLABIMAGE}" ]]; then exit 1; fi; } if [ -n "${SEMVER}" ]; then - {{ gitlab_timeout_cmd }}docker buildx imagetools create --prefer-index=false -t ${PUSHIMAGE}:${SEMVER} ${CACHEIMAGE}:amd64-${COMMIT_SHA}-${BUILD_NUMBER} || \ + ${TIMEOUT_CMD} docker buildx imagetools create --prefer-index=false -t ${PUSHIMAGE}:${SEMVER} ${CACHEIMAGE}:amd64-${COMMIT_SHA}-${BUILD_NUMBER} || \ { if [[ "${PUSHIMAGE}" != "${QUAYIMAGE}" && "${PUSHIMAGE}" != "${GITLABIMAGE}" ]]; then exit 1; fi; } fi {% if project_deprecation_status %} - {{ gitlab_timeout_cmd }}docker buildx imagetools create -t ${PUSHIMAGE}:{{ release_tag }} ghcr.io/linuxserver/jenkins-builder:empty || true + ${TIMEOUT_CMD} docker buildx imagetools create -t ${PUSHIMAGE}:{{ release_tag }} ghcr.io/linuxserver/jenkins-builder:empty || true {% endif %} done ''' @@ -1410,13 +1402,11 @@ pipeline { sh '''#! /bin/bash set -e for MANIFESTIMAGE in "${IMAGE}" "${GITLABIMAGE}" "${GITHUBIMAGE}" "${QUAYIMAGE}"; do -{% if gitlab_timeout is defined %} if [[ "${MANIFESTIMAGE}" == "${GITLABIMAGE}" ]]; then - TIMEOUT_CMD="timeout {{ gitlab_timeout }}" + TIMEOUT_CMD="timeout ${GITLAB_TIMEOUT}" else TIMEOUT_CMD="" fi -{% endif %} if [[ "${MANIFESTIMAGE%%/*}" =~ \\. ]]; then MANIFESTIMAGEPLUS="${MANIFESTIMAGE}" else @@ -1428,45 +1418,43 @@ pipeline { CACHEIMAGE=${i} fi done - {{ gitlab_timeout_cmd }}docker buildx imagetools create --prefer-index=false -t ${MANIFESTIMAGE}:amd64-${META_TAG} -t ${MANIFESTIMAGE}:amd64-{{ release_tag }} -t ${MANIFESTIMAGE}:amd64-${EXT_RELEASE_TAG} ${CACHEIMAGE}:amd64-${COMMIT_SHA}-${BUILD_NUMBER} || \ + ${TIMEOUT_CMD} docker buildx imagetools create --prefer-index=false -t ${MANIFESTIMAGE}:amd64-${META_TAG} -t ${MANIFESTIMAGE}:amd64-{{ release_tag }} -t ${MANIFESTIMAGE}:amd64-${EXT_RELEASE_TAG} ${CACHEIMAGE}:amd64-${COMMIT_SHA}-${BUILD_NUMBER} || \ { if [[ "${MANIFESTIMAGE}" != "${QUAYIMAGE}" && "${MANIFESTIMAGE}" != "${GITLABIMAGE}" ]]; then exit 1; fi; } - {{ gitlab_timeout_cmd }}docker buildx imagetools create --prefer-index=false -t ${MANIFESTIMAGE}:arm64v8-${META_TAG} -t ${MANIFESTIMAGE}:arm64v8-{{ release_tag }} -t ${MANIFESTIMAGE}:arm64v8-${EXT_RELEASE_TAG} ${CACHEIMAGE}:arm64v8-${COMMIT_SHA}-${BUILD_NUMBER} || \ + ${TIMEOUT_CMD} docker buildx imagetools create --prefer-index=false -t ${MANIFESTIMAGE}:arm64v8-${META_TAG} -t ${MANIFESTIMAGE}:arm64v8-{{ release_tag }} -t ${MANIFESTIMAGE}:arm64v8-${EXT_RELEASE_TAG} ${CACHEIMAGE}:arm64v8-${COMMIT_SHA}-${BUILD_NUMBER} || \ { if [[ "${MANIFESTIMAGE}" != "${QUAYIMAGE}" && "${MANIFESTIMAGE}" != "${GITLABIMAGE}" ]]; then exit 1; fi; } {% if build_riscv64 %} - {{ gitlab_timeout_cmd }}docker buildx imagetools create --prefer-index=false -t ${MANIFESTIMAGE}:riscv64-${META_TAG} -t ${MANIFESTIMAGE}:riscv64-{{ release_tag }} -t ${MANIFESTIMAGE}:riscv64-${EXT_RELEASE_TAG} ${CACHEIMAGE}:riscv64-${COMMIT_SHA}-${BUILD_NUMBER} || \ + ${TIMEOUT_CMD} docker buildx imagetools create --prefer-index=false -t ${MANIFESTIMAGE}:riscv64-${META_TAG} -t ${MANIFESTIMAGE}:riscv64-{{ release_tag }} -t ${MANIFESTIMAGE}:riscv64-${EXT_RELEASE_TAG} ${CACHEIMAGE}:riscv64-${COMMIT_SHA}-${BUILD_NUMBER} || \ { if [[ "${MANIFESTIMAGE}" != "${QUAYIMAGE}" && "${MANIFESTIMAGE}" != "${GITLABIMAGE}" ]]; then exit 1; fi; } {% endif %} if [ -n "${SEMVER}" ]; then - {{ gitlab_timeout_cmd }}docker buildx imagetools create --prefer-index=false -t ${MANIFESTIMAGE}:amd64-${SEMVER} ${CACHEIMAGE}:amd64-${COMMIT_SHA}-${BUILD_NUMBER} || \ + ${TIMEOUT_CMD} docker buildx imagetools create --prefer-index=false -t ${MANIFESTIMAGE}:amd64-${SEMVER} ${CACHEIMAGE}:amd64-${COMMIT_SHA}-${BUILD_NUMBER} || \ { if [[ "${MANIFESTIMAGE}" != "${QUAYIMAGE}" && "${MANIFESTIMAGE}" != "${GITLABIMAGE}" ]]; then exit 1; fi; } - {{ gitlab_timeout_cmd }}docker buildx imagetools create --prefer-index=false -t ${MANIFESTIMAGE}:arm64v8-${SEMVER} ${CACHEIMAGE}:arm64v8-${COMMIT_SHA}-${BUILD_NUMBER} || \ + ${TIMEOUT_CMD} docker buildx imagetools create --prefer-index=false -t ${MANIFESTIMAGE}:arm64v8-${SEMVER} ${CACHEIMAGE}:arm64v8-${COMMIT_SHA}-${BUILD_NUMBER} || \ { if [[ "${MANIFESTIMAGE}" != "${QUAYIMAGE}" && "${MANIFESTIMAGE}" != "${GITLABIMAGE}" ]]; then exit 1; fi; } {% if build_riscv64 %} - {{ gitlab_timeout_cmd }}docker buildx imagetools create --prefer-index=false -t ${MANIFESTIMAGE}:riscv64-${SEMVER} ${CACHEIMAGE}:riscv64-${COMMIT_SHA}-${BUILD_NUMBER} || \ + ${TIMEOUT_CMD} docker buildx imagetools create --prefer-index=false -t ${MANIFESTIMAGE}:riscv64-${SEMVER} ${CACHEIMAGE}:riscv64-${COMMIT_SHA}-${BUILD_NUMBER} || \ { if [[ "${MANIFESTIMAGE}" != "${QUAYIMAGE}" && "${MANIFESTIMAGE}" != "${GITLABIMAGE}" ]]; then exit 1; fi; } {% endif %} fi done for MANIFESTIMAGE in "${IMAGE}" "${GITLABIMAGE}" "${GITHUBIMAGE}" "${QUAYIMAGE}"; do -{% if gitlab_timeout is defined %} if [[ "${MANIFESTIMAGE}" == "${GITLABIMAGE}" ]]; then - TIMEOUT_CMD="timeout {{ gitlab_timeout }}" + TIMEOUT_CMD="timeout ${GITLAB_TIMEOUT}" else TIMEOUT_CMD="" fi -{% endif %} {% if project_deprecation_status %} - {{ gitlab_timeout_cmd }}docker buildx imagetools create -t ${MANIFESTIMAGE}:{{ release_tag }} -t ${MANIFESTIMAGE}:amd64-{{ release_tag }} -t ${MANIFESTIMAGE}:arm64v8-{{ release_tag }}{% if build_riscv64 %} -t ${MANIFESTIMAGE}:riscv64-{{ release_tag }}{% endif %} ghcr.io/linuxserver/jenkins-builder:empty || true + ${TIMEOUT_CMD} docker buildx imagetools create -t ${MANIFESTIMAGE}:{{ release_tag }} -t ${MANIFESTIMAGE}:amd64-{{ release_tag }} -t ${MANIFESTIMAGE}:arm64v8-{{ release_tag }}{% if build_riscv64 %} -t ${MANIFESTIMAGE}:riscv64-{{ release_tag }}{% endif %} ghcr.io/linuxserver/jenkins-builder:empty || true {% else %} - {{ gitlab_timeout_cmd }}docker buildx imagetools create -t ${MANIFESTIMAGE}:{{ release_tag }} ${MANIFESTIMAGE}:amd64-{{ release_tag }}{% if build_riscv64 %} ${MANIFESTIMAGE}:riscv64-{{ release_tag }}{% endif %} ${MANIFESTIMAGE}:arm64v8-{{ release_tag }} || \ + ${TIMEOUT_CMD} docker buildx imagetools create -t ${MANIFESTIMAGE}:{{ release_tag }} ${MANIFESTIMAGE}:amd64-{{ release_tag }}{% if build_riscv64 %} ${MANIFESTIMAGE}:riscv64-{{ release_tag }}{% endif %} ${MANIFESTIMAGE}:arm64v8-{{ release_tag }} || \ { if [[ "${MANIFESTIMAGE}" != "${QUAYIMAGE}" && "${MANIFESTIMAGE}" != "${GITLABIMAGE}" ]]; then exit 1; fi; } {% endif %} - {{ gitlab_timeout_cmd }}docker buildx imagetools create -t ${MANIFESTIMAGE}:${META_TAG} ${MANIFESTIMAGE}:amd64-${META_TAG}{% if build_riscv64 %} ${MANIFESTIMAGE}:riscv64-${META_TAG}{% endif %} ${MANIFESTIMAGE}:arm64v8-${META_TAG} || \ + ${TIMEOUT_CMD} docker buildx imagetools create -t ${MANIFESTIMAGE}:${META_TAG} ${MANIFESTIMAGE}:amd64-${META_TAG}{% if build_riscv64 %} ${MANIFESTIMAGE}:riscv64-${META_TAG}{% endif %} ${MANIFESTIMAGE}:arm64v8-${META_TAG} || \ { if [[ "${MANIFESTIMAGE}" != "${QUAYIMAGE}" && "${MANIFESTIMAGE}" != "${GITLABIMAGE}" ]]; then exit 1; fi; } - {{ gitlab_timeout_cmd }}docker buildx imagetools create -t ${MANIFESTIMAGE}:${EXT_RELEASE_TAG} ${MANIFESTIMAGE}:amd64-${EXT_RELEASE_TAG}{% if build_riscv64 %} ${MANIFESTIMAGE}:riscv64-${EXT_RELEASE_TAG}{% endif %} ${MANIFESTIMAGE}:arm64v8-${EXT_RELEASE_TAG} || \ + ${TIMEOUT_CMD} docker buildx imagetools create -t ${MANIFESTIMAGE}:${EXT_RELEASE_TAG} ${MANIFESTIMAGE}:amd64-${EXT_RELEASE_TAG}{% if build_riscv64 %} ${MANIFESTIMAGE}:riscv64-${EXT_RELEASE_TAG}{% endif %} ${MANIFESTIMAGE}:arm64v8-${EXT_RELEASE_TAG} || \ { if [[ "${MANIFESTIMAGE}" != "${QUAYIMAGE}" && "${MANIFESTIMAGE}" != "${GITLABIMAGE}" ]]; then exit 1; fi; } if [ -n "${SEMVER}" ]; then - {{ gitlab_timeout_cmd }}docker buildx imagetools create -t ${MANIFESTIMAGE}:${SEMVER} ${MANIFESTIMAGE}:amd64-${SEMVER}{% if build_riscv64 %} ${MANIFESTIMAGE}:riscv64-${SEMVER}{% endif %} ${MANIFESTIMAGE}:arm64v8-${SEMVER} || \ + ${TIMEOUT_CMD} docker buildx imagetools create -t ${MANIFESTIMAGE}:${SEMVER} ${MANIFESTIMAGE}:amd64-${SEMVER}{% if build_riscv64 %} ${MANIFESTIMAGE}:riscv64-${SEMVER}{% endif %} ${MANIFESTIMAGE}:arm64v8-${SEMVER} || \ { if [[ "${MANIFESTIMAGE}" != "${QUAYIMAGE}" && "${MANIFESTIMAGE}" != "${GITLABIMAGE}" ]]; then exit 1; fi; } fi done