diff --git a/.github/workflows/build-ci-images.yml b/.github/workflows/build-ci-images.yml index 5bb1a15c4b..f846ef0f3b 100644 --- a/.github/workflows/build-ci-images.yml +++ b/.github/workflows/build-ci-images.yml @@ -7,13 +7,28 @@ on: description: "Space-separated distro list" required: true type: string + checkout_ref: + description: "Optional git ref to checkout before build (default: event ref)" + required: false + type: string + default: "" + image_tag: + description: "Optional image tag override (default: ci-${github.sha})" + required: false + type: string + default: "" + concurrency_channel: + description: "Optional channel to separate concurrency groups between callers" + required: false + type: string + default: "default" permissions: contents: read packages: write concurrency: - group: infinito-build-${{ github.ref }} + group: infinito-build-${{ github.repository }}-${{ inputs.concurrency_channel }}-${{ inputs.checkout_ref || github.ref }} cancel-in-progress: false jobs: @@ -22,7 +37,7 @@ jobs: runs-on: ubuntu-latest outputs: matrix: ${{ steps.out.outputs.matrix }} - image_tag: ci-${{ github.sha }} + image_tag: ${{ steps.out.outputs.image_tag }} steps: - name: Install jq run: | @@ -36,8 +51,14 @@ jobs: set -euo pipefail distros="${{ inputs.distros }}" json="$(printf '%s' "$distros" | jq -Rc 'split(" ") | map(select(length>0))')" + image_tag="${{ inputs.image_tag }}" + if [ -z "${image_tag}" ]; then + image_tag="ci-${GITHUB_SHA}" + fi echo "matrix=${json}" >> "$GITHUB_OUTPUT" + echo "image_tag=${image_tag}" >> "$GITHUB_OUTPUT" echo "Using matrix: ${json}" + echo "Using image tag: ${image_tag}" build: name: 🏗️ Build image (${{ matrix.distro }}) @@ -50,8 +71,19 @@ jobs: distro: ${{ fromJson(needs.prepare.outputs.matrix) }} steps: - - name: Checkout + - name: Checkout trusted workflow repo (helpers) uses: actions/checkout@v6 + with: + ref: ${{ github.sha }} + persist-credentials: false + + - name: Checkout source to build + uses: actions/checkout@v6 + with: + repository: ${{ github.repository }} + ref: ${{ inputs.checkout_ref || github.ref }} + path: _src + persist-credentials: false - name: Disk pressure (start) shell: bash @@ -96,39 +128,24 @@ jobs: run: echo "owner=$(echo '${{ github.repository_owner }}' | tr '[:upper:]' '[:lower:]')" >> "$GITHUB_OUTPUT" - name: Build & push (retry 7x, 20s) + if: ${{ !(github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository) }} shell: bash - run: | - set -euo pipefail + env: + BUILD_CONTEXT_DIR: _src + MATRIX_DISTRO: ${{ matrix.distro }} + IMAGE_TAG: ${{ needs.prepare.outputs.image_tag }} + USE_NIX_TOKEN: ${{ !(github.event_name == 'pull_request_target' && github.event.pull_request.head.repo.full_name != github.repository) }} + NIX_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + MAX_ATTEMPTS: "7" + RETRY_DELAY_SECONDS: "20" + run: ./scripts/ci/build_and_push_ci_image.sh - max_attempts=7 - retry_delay_seconds=20 - attempt=1 - - while true; do - echo "=== Build & push attempt ${attempt}/${max_attempts} ===" - - if docker buildx build \ - --file ./Dockerfile \ - --push \ - --tag "ghcr.io/${{ steps.lower_owner.outputs.owner }}/infinito-${{ matrix.distro }}:${{ needs.prepare.outputs.image_tag }}" \ - --build-arg "PKGMGR_IMAGE=ghcr.io/kevinveenbirkenbach/pkgmgr-${{ matrix.distro }}:stable" \ - --build-arg "NIX_CONFIG=access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}" \ - --cache-from "type=gha,scope=infinito-${{ matrix.distro }}" \ - --cache-to "type=gha,mode=max,scope=infinito-${{ matrix.distro }}" \ - .; then - echo "Build & push succeeded on attempt ${attempt}/${max_attempts}." - break - fi - - if [ "${attempt}" -ge "${max_attempts}" ]; then - echo "Build & push failed after ${max_attempts} attempts." - exit 1 - fi - - echo "Attempt ${attempt} failed. Retrying in ${retry_delay_seconds}s..." - sleep "${retry_delay_seconds}" - attempt=$((attempt + 1)) - done + - name: Wait for prebuilt image (fork PR) + if: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository }} + env: + MATRIX_DISTRO: ${{ matrix.distro }} + IMAGE_TAG: ${{ needs.prepare.outputs.image_tag }} + run: ./scripts/ci/wait_prebuilt_ci_image.sh - name: Disk pressure (post-build) if: always() diff --git a/.github/workflows/ci-orchestrator.yml b/.github/workflows/ci-orchestrator.yml index 07600ea2ef..50c833129f 100644 --- a/.github/workflows/ci-orchestrator.yml +++ b/.github/workflows/ci-orchestrator.yml @@ -48,6 +48,7 @@ jobs: uses: ./.github/workflows/build-ci-images.yml with: distros: "arch debian ubuntu fedora centos" + concurrency_channel: ci-orchestrator-build-consumer # Code Testing test-code-integration: @@ -85,6 +86,8 @@ jobs: # Sync Missing Images images-mirror-missing: uses: ./.github/workflows/images-mirror-missing.yml + with: + concurrency_channel: ci-orchestrator-mirror-consumer secrets: inherit # Deploy tests diff --git a/.github/workflows/entry-pull-request-target-build-ci-images.yml b/.github/workflows/entry-pull-request-target-build-ci-images.yml new file mode 100644 index 0000000000..c60e7e4874 --- /dev/null +++ b/.github/workflows/entry-pull-request-target-build-ci-images.yml @@ -0,0 +1,42 @@ +name: CI (On Pull-Request Target / Build CI Images For Forks) + +on: + pull_request_target: + types: + - opened + - synchronize + - reopened + - ready_for_review + +permissions: + contents: read + packages: write + +jobs: + prepare-fork-merge-ref: + if: ${{ github.event.pull_request.head.repo.full_name != github.repository }} + runs-on: ubuntu-latest + outputs: + checkout_ref: ${{ steps.out.outputs.checkout_ref }} + image_tag: ${{ steps.out.outputs.image_tag }} + steps: + - name: Checkout + uses: actions/checkout@v6 + + - name: Resolve merge ref and image tag + id: out + env: + PR_NUMBER: ${{ github.event.pull_request.number }} + PR_MERGE_SHA: ${{ github.event.pull_request.merge_commit_sha || '' }} + run: ./scripts/ci/resolve_pr_merge_ref.sh + + build-ci-images-fork: + if: ${{ github.event.pull_request.head.repo.full_name != github.repository }} + needs: prepare-fork-merge-ref + uses: ./.github/workflows/build-ci-images.yml + with: + distros: "arch debian ubuntu fedora centos" + checkout_ref: ${{ needs.prepare-fork-merge-ref.outputs.checkout_ref }} + image_tag: ${{ needs.prepare-fork-merge-ref.outputs.image_tag }} + concurrency_channel: pr-target-build-producer + secrets: inherit diff --git a/.github/workflows/entry-pull-request-target-mirror.yml b/.github/workflows/entry-pull-request-target-mirror.yml new file mode 100644 index 0000000000..ccb8374d36 --- /dev/null +++ b/.github/workflows/entry-pull-request-target-mirror.yml @@ -0,0 +1,43 @@ +name: CI (On Pull-Request Target / Mirror Fork Images) + +on: + pull_request_target: + types: + - opened + - synchronize + - reopened + - ready_for_review + +permissions: + contents: read + packages: write + +jobs: + prepare-fork-merge-ref: + if: ${{ github.event.pull_request.head.repo.full_name != github.repository }} + runs-on: ubuntu-latest + outputs: + checkout_ref: ${{ steps.out.outputs.checkout_ref }} + steps: + - name: Checkout + uses: actions/checkout@v6 + + - name: Resolve merge ref + id: out + env: + PR_NUMBER: ${{ github.event.pull_request.number }} + PR_MERGE_SHA: ${{ github.event.pull_request.merge_commit_sha || '' }} + run: ./scripts/ci/resolve_pr_merge_ref.sh + + images-mirror-missing-fork: + if: ${{ github.event.pull_request.head.repo.full_name != github.repository }} + needs: prepare-fork-merge-ref + uses: ./.github/workflows/images-mirror-missing.yml + with: + repo_root: _pr_source + source_repository: ${{ github.repository }} + source_ref: ${{ needs.prepare-fork-merge-ref.outputs.checkout_ref }} + source_path: _pr_source + concurrency_channel: pr-target-mirror-producer + concurrency_key: pr-${{ github.event.pull_request.number }} + secrets: inherit diff --git a/.github/workflows/entry-push-latest.yml b/.github/workflows/entry-push-latest.yml index e5e8b1f8b5..2847e8d240 100644 --- a/.github/workflows/entry-push-latest.yml +++ b/.github/workflows/entry-push-latest.yml @@ -7,7 +7,6 @@ concurrency: on: push: branches: - - master - main - "feature/**" - "hotfix/**" @@ -76,7 +75,7 @@ jobs: distros: ${{ needs.pick-distro.outputs.distros }} secrets: inherit - # Guard job: only allow version releases if the tag commit is contained in origin/master + # Guard job: only allow version releases if the tag commit is contained in origin/main release-guard: name: "🛡️ Guard release" if: github.event.created == false && needs.pick-distro.outputs.is_version == 'true' @@ -93,13 +92,13 @@ jobs: fetch-depth: 0 fetch-tags: true - - name: Fetch master + - name: Fetch main shell: bash run: | set -euo pipefail - git fetch origin master:refs/remotes/origin/master --force + git fetch origin main:refs/remotes/origin/main --force - - name: "Guard: tag commit must be contained in origin/master" + - name: "Guard: tag commit must be contained in origin/main" id: guard shell: bash env: @@ -117,12 +116,12 @@ jobs: tag_sha="$(git rev-list -n 1 "${tag}")" echo "Tag: ${tag} -> ${tag_sha}" - if git merge-base --is-ancestor "${tag_sha}" "origin/master"; then + if git merge-base --is-ancestor "${tag_sha}" "origin/main"; then echo "allowed=true" >> "$GITHUB_OUTPUT" - echo "✅ Tag commit is on origin/master" + echo "✅ Tag commit is on origin/main" else echo "allowed=false" >> "$GITHUB_OUTPUT" - echo "⛔ Tag commit is NOT on origin/master" + echo "⛔ Tag commit is NOT on origin/main" fi release-version: diff --git a/.github/workflows/images-mirror-missing.yml b/.github/workflows/images-mirror-missing.yml index eeb06c87d2..e58c393e7b 100644 --- a/.github/workflows/images-mirror-missing.yml +++ b/.github/workflows/images-mirror-missing.yml @@ -17,11 +17,36 @@ on: required: false type: string default: "." + source_repository: + description: "Optional source repository for image config scan (e.g. fork owner/repo)" + required: false + type: string + default: "" + source_ref: + description: "Optional source ref/SHA for image config scan" + required: false + type: string + default: "" + source_path: + description: "Optional checkout path for source_repository/source_ref" + required: false + type: string + default: "_pr_source" images_per_hour: description: "Optional throttle: max images mirrored per hour" required: false type: string default: "" + concurrency_channel: + description: "Optional channel to separate concurrency groups between callers" + required: false + type: string + default: "default" + concurrency_key: + description: "Optional key (e.g. pr-123) to scope concurrency within a channel" + required: false + type: string + default: "" secrets: DOCKERHUB_USERNAME: required: false @@ -33,7 +58,7 @@ permissions: packages: write concurrency: - group: mirror-images-${{ github.repository }}-${{ github.ref_name }} + group: mirror-images-${{ github.repository }}-${{ inputs.concurrency_channel }}-${{ inputs.concurrency_key || github.ref_name }} # Cancel scheduled Mirror sync, because may it works with outdatet mirror lists cancel-in-progress: true @@ -52,6 +77,16 @@ jobs: - name: Checkout uses: actions/checkout@v6 + - name: Checkout source repo for scan (optional) + if: ${{ inputs.source_repository != '' && inputs.source_ref != '' }} + uses: actions/checkout@v6 + with: + repository: ${{ inputs.source_repository }} + ref: ${{ inputs.source_ref }} + path: ${{ inputs.source_path }} + fetch-depth: 1 + persist-credentials: false + - name: Setup Python uses: actions/setup-python@v6 with: @@ -69,7 +104,7 @@ jobs: # Optional: Docker Hub login to avoid rate limits while mirroring - name: Login to Docker Hub (optional) - if: ${{ env.DOCKERHUB_USERNAME != '' && env.DOCKERHUB_TOKEN != '' }} + if: ${{ env.DOCKERHUB_USERNAME != '' && env.DOCKERHUB_TOKEN != '' && !(github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository) }} uses: docker/login-action@v4 with: username: ${{ env.DOCKERHUB_USERNAME }} @@ -82,7 +117,16 @@ jobs: username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} + - name: Wait for mirrored images (fork PR) + if: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository }} + env: + GHCR_NAMESPACE: ${{ inputs.ghcr_namespace || github.repository_owner }} + GHCR_PREFIX: ${{ inputs.ghcr_prefix || 'mirror' }} + REPO_ROOT: ${{ inputs.repo_root || '.' }} + run: ./scripts/ci/wait_mirrored_images.sh + - name: Mirror images to GHCR (only missing, best-effort) + if: ${{ !(github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository) }} shell: bash run: | set -euo pipefail diff --git a/MIRRORS b/MIRRORS index b2ef20d2c1..14f5d65f8a 100644 --- a/MIRRORS +++ b/MIRRORS @@ -1,4 +1,3 @@ git@github.com:infinito-nexus/core.git ssh://git@code.infinito.nexus:2201/infinito/nexus.git ssh://git@git.veen.world:2201/kevinveenbirkenbach/infinito-nexus -git@github.com:kevinveenbirkenbach/infinito-nexus.git diff --git a/cli/build/graph/__main__.py b/cli/build/graph/__main__.py index 904954f57c..1095ea89b5 100644 --- a/cli/build/graph/__main__.py +++ b/cli/build/graph/__main__.py @@ -146,7 +146,7 @@ def build_single_graph( "id": role, **galaxy_info, "doc_url": f"https://docs.infinito.nexus/roles/{role}/README.html", - "source_url": f"https://github.com/kevinveenbirkenbach/infinito-nexus/tree/master/roles/{role}", + "source_url": f"https://github.com/infinito-nexus/core/tree/main/roles/{role}", } nodes[role] = node diff --git a/docs/guides/developer/index.rst b/docs/guides/developer/index.rst index 0b344abedc..05dec2fc0f 100644 --- a/docs/guides/developer/index.rst +++ b/docs/guides/developer/index.rst @@ -25,7 +25,7 @@ Contributing to Infinito.Nexus Want to contribute to the project or explore the source code? Check out our **GitHub repository**: -- `Infinito.Nexus GitHub Repository `_ +- `Infinito.Nexus GitHub Repository `_ Contribution Guidelines ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/roles/web-app-akaunting/tasks/main.yml b/roles/web-app-akaunting/tasks/main.yml index 4e0eba6754..484187039a 100644 --- a/roles/web-app-akaunting/tasks/main.yml +++ b/roles/web-app-akaunting/tasks/main.yml @@ -14,7 +14,7 @@ vars: docker_git_repository_address: "https://github.com/akaunting/docker.git" docker_git_repository_pull: true - docker_git_repository_version: "master" + docker_git_repository_version: "master" docker_compose_flush_handlers: true - name: "Akaunting | Create first-run marker to disable future setup" diff --git a/roles/web-app-mailu/README.md b/roles/web-app-mailu/README.md index c41ce49549..d37819e9c1 100644 --- a/roles/web-app-mailu/README.md +++ b/roles/web-app-mailu/README.md @@ -15,7 +15,7 @@ For further details on installation, configuration, and upgrades, please refer t - [User_Administration.md](./User_Administration.md) For more information about this role, visit the GitHub repositories: -- [Mailu](https://s.infinito.nexus/code/tree/master/roles/web-app-mailu) +- [Mailu](https://github.com/infinito-nexus/core/tree/main/roles/web-app-mailu) - [Mailu-OIDC](https://github.com/heviat/Mailu-OIDC) ## Features diff --git a/roles/web-app-nextcloud/config/main.yml b/roles/web-app-nextcloud/config/main.yml index dd7b50fa92..df71ccf89a 100644 --- a/roles/web-app-nextcloud/config/main.yml +++ b/roles/web-app-nextcloud/config/main.yml @@ -108,9 +108,9 @@ compose: onboard_enabled: true standalone_enabled: false network_mode: bridge - cpus: "1.0" - mem_reservation: "256m" - mem_limit: "1g" + cpus: "2.0" + mem_reservation: "1g" + mem_limit: "2g" pids_limit: 1024 whiteboard: name: "nextcloud-whiteboard" @@ -126,15 +126,15 @@ compose: enabled: true shared: true talk_recording: - name: "nextcloud-talk-recording" - image: "nextcloud/aio-talk-recording" - version: "latest" + name: "nextcloud-talk-recording" + image: "nextcloud/aio-talk-recording" + version: "latest" backup: - no_stop_required: true - cpus: "2.0" - mem_reservation: "2g" - mem_limit: "4g" - pids_limit: 1024 + no_stop_required: true + cpus: "2.0" + mem_reservation: "2g" + mem_limit: "6g" + pids_limit: 1024 css: enabled: false hcaptcha: diff --git a/scripts/ci/build_and_push_ci_image.sh b/scripts/ci/build_and_push_ci_image.sh new file mode 100755 index 0000000000..98f03a76cc --- /dev/null +++ b/scripts/ci/build_and_push_ci_image.sh @@ -0,0 +1,46 @@ +#!/usr/bin/env bash +set -euo pipefail + +: "${BUILD_CONTEXT_DIR:?Missing BUILD_CONTEXT_DIR}" +: "${MATRIX_DISTRO:?Missing MATRIX_DISTRO}" +: "${IMAGE_TAG:?Missing IMAGE_TAG}" +: "${GITHUB_REPOSITORY_OWNER:?Missing GITHUB_REPOSITORY_OWNER}" +: "${USE_NIX_TOKEN:?Missing USE_NIX_TOKEN}" + +max_attempts="${MAX_ATTEMPTS:-7}" +retry_delay_seconds="${RETRY_DELAY_SECONDS:-20}" +attempt=1 + +nix_arg=() +if [[ "${USE_NIX_TOKEN}" == "true" ]]; then + : "${NIX_GITHUB_TOKEN:?Missing NIX_GITHUB_TOKEN}" + nix_arg=( --build-arg "NIX_CONFIG=access-tokens = github.com=${NIX_GITHUB_TOKEN}" ) +else + echo "pull_request_target on fork detected: skipping NIX_CONFIG token build-arg." +fi + +while true; do + echo "=== Build & push attempt ${attempt}/${max_attempts} ===" + + if docker buildx build \ + --file "${BUILD_CONTEXT_DIR}/Dockerfile" \ + --push \ + --tag "ghcr.io/${GITHUB_REPOSITORY_OWNER}/infinito-${MATRIX_DISTRO}:${IMAGE_TAG}" \ + --build-arg "PKGMGR_IMAGE=ghcr.io/kevinveenbirkenbach/pkgmgr-${MATRIX_DISTRO}:stable" \ + "${nix_arg[@]}" \ + --cache-from "type=gha,scope=infinito-${MATRIX_DISTRO}" \ + --cache-to "type=gha,mode=max,scope=infinito-${MATRIX_DISTRO}" \ + "${BUILD_CONTEXT_DIR}"; then + echo "Build & push succeeded on attempt ${attempt}/${max_attempts}." + break + fi + + if [[ "${attempt}" -ge "${max_attempts}" ]]; then + echo "Build & push failed after ${max_attempts} attempts." + exit 1 + fi + + echo "Attempt ${attempt} failed. Retrying in ${retry_delay_seconds}s..." + sleep "${retry_delay_seconds}" + attempt=$((attempt + 1)) +done diff --git a/scripts/ci/resolve_pr_merge_ref.sh b/scripts/ci/resolve_pr_merge_ref.sh new file mode 100755 index 0000000000..514eedda63 --- /dev/null +++ b/scripts/ci/resolve_pr_merge_ref.sh @@ -0,0 +1,36 @@ +#!/usr/bin/env bash +set -euo pipefail + +: "${PR_NUMBER:?Missing PR_NUMBER}" +: "${GITHUB_REPOSITORY:?Missing GITHUB_REPOSITORY}" +: "${GITHUB_OUTPUT:?Missing GITHUB_OUTPUT}" + +ref="refs/pull/${PR_NUMBER}/merge" +repo_url="https://github.com/${GITHUB_REPOSITORY}.git" +sha="${PR_MERGE_SHA:-}" +checkout_ref="${ref}" + +if [[ -n "${sha}" ]]; then + if [[ ! "${sha}" =~ ^[0-9a-f]{40}$ ]]; then + echo "Invalid PR_MERGE_SHA '${sha}', falling back to ${ref}" >&2 + sha="" + else + checkout_ref="${sha}" + fi +fi + +if [[ -z "${sha}" ]]; then + sha="$(git ls-remote "${repo_url}" "${ref}" | awk '{print $1}')" + if [[ -z "${sha}" ]]; then + echo "Failed to resolve merge SHA for ${ref}" >&2 + exit 1 + fi + checkout_ref="${sha}" +fi + +{ + echo "checkout_ref=${checkout_ref}" + echo "image_tag=ci-${sha}" +} >> "${GITHUB_OUTPUT}" + +echo "Resolved fork PR merge ref ${ref} -> ${sha} (checkout_ref=${checkout_ref})" diff --git a/scripts/ci/wait_mirrored_images.sh b/scripts/ci/wait_mirrored_images.sh new file mode 100755 index 0000000000..331355eae8 --- /dev/null +++ b/scripts/ci/wait_mirrored_images.sh @@ -0,0 +1,70 @@ +#!/usr/bin/env bash +set -euo pipefail + +: "${GHCR_NAMESPACE:?Missing GHCR_NAMESPACE}" +: "${GHCR_PREFIX:?Missing GHCR_PREFIX}" +: "${REPO_ROOT:?Missing REPO_ROOT}" + +max_attempts="${MAX_WAIT_ATTEMPTS:-180}" +sleep_seconds="${WAIT_SLEEP_SECONDS:-10}" + +mapfile -t mirror_refs < <( + GHCR_NAMESPACE="${GHCR_NAMESPACE}" \ + GHCR_PREFIX="${GHCR_PREFIX}" \ + REPO_ROOT="${REPO_ROOT}" \ + python - <<'PY' +import os +from pathlib import Path +from cli.mirror.providers import GHCRProvider +from cli.mirror.util import iter_role_images + +provider = GHCRProvider( + os.environ["GHCR_NAMESPACE"], + os.environ["GHCR_PREFIX"], +) +repo_root = Path(os.environ["REPO_ROOT"]).resolve() + +seen = set() +for img in iter_role_images(repo_root): + ref = f"{provider.image_base(img)}:{img.version}" + if ref in seen: + continue + seen.add(ref) + print(ref) +PY +) + +total="${#mirror_refs[@]}" +if [[ "${total}" -eq 0 ]]; then + echo "No mirror refs found. Nothing to wait for." + exit 0 +fi + +echo "Fork pull_request detected; waiting for mirrored images from pull_request_target." +echo "Need ${total} mirror refs." + +missing=() +for attempt in $(seq 1 "${max_attempts}"); do + missing=() + for ref in "${mirror_refs[@]}"; do + if ! skopeo inspect "docker://${ref}" >/dev/null 2>&1; then + missing+=("${ref}") + fi + done + + if [[ "${#missing[@]}" -eq 0 ]]; then + echo "All mirrored images are available." + exit 0 + fi + + echo "[${attempt}/${max_attempts}] Missing ${#missing[@]}/${total} mirror refs. Waiting ${sleep_seconds}s..." + echo "Example missing: ${missing[0]}" + sleep "${sleep_seconds}" +done + +echo "Timed out waiting for mirrored images." >&2 +echo "Still missing (first 20):" >&2 +for ref in "${missing[@]:0:20}"; do + echo " - ${ref}" >&2 +done +exit 1 diff --git a/scripts/ci/wait_prebuilt_ci_image.sh b/scripts/ci/wait_prebuilt_ci_image.sh new file mode 100755 index 0000000000..7f574e27ea --- /dev/null +++ b/scripts/ci/wait_prebuilt_ci_image.sh @@ -0,0 +1,25 @@ +#!/usr/bin/env bash +set -euo pipefail + +: "${MATRIX_DISTRO:?Missing MATRIX_DISTRO}" +: "${IMAGE_TAG:?Missing IMAGE_TAG}" +: "${GITHUB_REPOSITORY_OWNER:?Missing GITHUB_REPOSITORY_OWNER}" + +image="ghcr.io/${GITHUB_REPOSITORY_OWNER}/infinito-${MATRIX_DISTRO}:${IMAGE_TAG}" +max_attempts="${MAX_WAIT_ATTEMPTS:-180}" +sleep_seconds="${WAIT_SLEEP_SECONDS:-10}" + +echo "Fork pull_request detected; waiting for image built via pull_request_target:" +echo " ${image}" + +for attempt in $(seq 1 "${max_attempts}"); do + if docker buildx imagetools inspect "${image}" >/dev/null 2>&1; then + echo "Image is available: ${image}" + exit 0 + fi + echo "[${attempt}/${max_attempts}] Waiting for image..." + sleep "${sleep_seconds}" +done + +echo "Timed out waiting for prebuilt image: ${image}" >&2 +exit 1