mirror of
https://github.com/kevinveenbirkenbach/computer-playbook.git
synced 2026-11-11 21:26:44 +00:00
ci: add pull_request_target image build/mirror workflow flow
This commit is contained in:
16 files changed
+384
-60
No files matched your search
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in new issue
Block a user