From b6b66a2d70163cd7fbc1ec5ded56db3d206c10af Mon Sep 17 00:00:00 2001 From: Matthias Linhuber Date: Tue, 25 Aug 2026 15:56:15 +0200 Subject: [PATCH] ci: build on GitHub runners, dual-arch, via EduIDE/.github@v1 Repoints the three image builds at the org-owned reusable workflow and collapses three near-identical 18-line jobs into one matrix (107 -> 62 lines). Why this matters beyond tidiness: - Drops the dependency on ls1intum/.github@feature/split-build-workflow-modes, an unmerged PR branch in another organisation. If that branch is deleted, every image build here breaks. - operator, service and conversion-webhook are now built for both linux/amd64 and linux/arm64 on every event, including pull requests. Previously arm64 was skipped for PRs, so a PR image could not be scheduled onto an arm64 node. - fail-fast: false, so one component failing no longer cancels the other two. Removes verify-cache.yml and certs/squid-proxy-ca.crt. That workflow only probed cluster-internal services (apt-cacher-ng, verdaccio, squid and the two registry mirrors, all .svc.cluster.local) which are unreachable from GitHub-hosted runners, and the CA certificate existed solely for it. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_019qeiQRFu8xAMRYWPdZewjG --- .github/workflows/build.yml | 81 +++------- .github/workflows/verify-cache.yml | 228 ----------------------------- certs/squid-proxy-ca.crt | 19 --- 3 files changed, 18 insertions(+), 310 deletions(-) delete mode 100644 .github/workflows/verify-cache.yml delete mode 100644 certs/squid-proxy-ca.crt diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 58696ac4f..df4572ae6 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -19,26 +19,13 @@ on: workflow_dispatch: inputs: - execution_mode: - description: "Build backend to use" - required: false - default: self-hosted-buildkit - type: choice - options: - - self-hosted-buildkit - - github-runners image_tag: - description: "Optional image tag override (e.g. my-test-tag)" + description: "Optional image tag override (e.g. my-test-tag, or 2.3.0 for the release train)" required: false default: "" type: string - arc_registry_cache: - description: "Enable ARC registry cache import/export (slower on stateful BuildKit; default off)" - required: false - default: false - type: boolean disable_layer_cache: - description: "Disable Docker layer cache (--no-cache) for stress testing while keeping BuildKit mount caches" + description: "Disable the Docker layer cache (--no-cache) for stress testing" required: false default: false type: boolean @@ -48,60 +35,28 @@ permissions: packages: write concurrency: - group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}-${{ github.event_name == 'workflow_dispatch' && inputs.execution_mode || 'self-hosted-buildkit' }} + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} cancel-in-progress: false jobs: - - build-and-push-operator: - uses: ls1intum/.github/.github/workflows/build-and-push-docker-image.yml@feature/split-build-workflow-modes + build: + name: ${{ matrix.component }} + strategy: + # One component failing must not cancel the other two. + fail-fast: false + matrix: + include: + - component: operator + - component: service + - component: conversion-webhook + uses: EduIDE/.github/.github/workflows/build-and-push-docker-image.yml@v1 with: - docker-file: dockerfiles/operator/Dockerfile - image-name: eduide/eduide-cloud/operator + docker-file: dockerfiles/${{ matrix.component }}/Dockerfile + image-name: eduide/eduide-cloud/${{ matrix.component }} docker-context: . image-tag: ${{ github.event_name == 'release' && github.event.release.tag_name || github.event_name == 'workflow_dispatch' && inputs.image_tag || '' }} - execution-mode: ${{ github.event_name == 'workflow_dispatch' && inputs.execution_mode || 'self-hosted-buildkit' }} - arc-registry-cache: ${{ github.event_name == 'workflow_dispatch' && inputs.arc_registry_cache || false }} no-cache: ${{ github.event_name == 'schedule' || (github.event_name == 'workflow_dispatch' && inputs.disable_layer_cache) || false }} - cache-from: ${{ (github.event_name == 'workflow_dispatch' && inputs.execution_mode || 'self-hosted-buildkit') == 'github-runners' && 'type=registry,ref=ghcr.io/eduide/eduide-cloud/operator:build-cache' || '' }} - cache-to: ${{ (github.event_name == 'workflow_dispatch' && inputs.execution_mode || 'self-hosted-buildkit') == 'github-runners' && 'type=registry,ref=ghcr.io/eduide/eduide-cloud/operator:build-cache,mode=max,image-manifest=true,oci-mediatypes=true' || '' }} - build-amd64: true - build-arm64: ${{ github.event_name != 'pull_request' }} - network: host + # These are small Java images; the disk-reclaim step is not worth the time. + free-disk-space: false secrets: docker-secrets: ${{ secrets.SENTRY_AUTH_TOKEN != '' && format('SENTRY_AUTH_TOKEN={0}', secrets.SENTRY_AUTH_TOKEN) || '' }} - - build-and-push-service: - uses: ls1intum/.github/.github/workflows/build-and-push-docker-image.yml@feature/split-build-workflow-modes - with: - docker-file: dockerfiles/service/Dockerfile - image-name: eduide/eduide-cloud/service - docker-context: . - image-tag: ${{ github.event_name == 'release' && github.event.release.tag_name || github.event_name == 'workflow_dispatch' && inputs.image_tag || '' }} - execution-mode: ${{ github.event_name == 'workflow_dispatch' && inputs.execution_mode || 'self-hosted-buildkit' }} - arc-registry-cache: ${{ github.event_name == 'workflow_dispatch' && inputs.arc_registry_cache || false }} - no-cache: ${{ github.event_name == 'schedule' || (github.event_name == 'workflow_dispatch' && inputs.disable_layer_cache) || false }} - cache-from: ${{ (github.event_name == 'workflow_dispatch' && inputs.execution_mode || 'self-hosted-buildkit') == 'github-runners' && 'type=registry,ref=ghcr.io/eduide/eduide-cloud/service:build-cache' || '' }} - cache-to: ${{ (github.event_name == 'workflow_dispatch' && inputs.execution_mode || 'self-hosted-buildkit') == 'github-runners' && 'type=registry,ref=ghcr.io/eduide/eduide-cloud/service:build-cache,mode=max,image-manifest=true,oci-mediatypes=true' || '' }} - build-amd64: true - build-arm64: ${{ github.event_name != 'pull_request' }} - network: host - secrets: - docker-secrets: ${{ secrets.SENTRY_AUTH_TOKEN != '' && format('SENTRY_AUTH_TOKEN={0}', secrets.SENTRY_AUTH_TOKEN) || '' }} - - build-and-push-conversion-webhook: - uses: ls1intum/.github/.github/workflows/build-and-push-docker-image.yml@feature/split-build-workflow-modes - with: - docker-file: dockerfiles/conversion-webhook/Dockerfile - image-name: eduide/eduide-cloud/conversion-webhook - docker-context: . - image-tag: ${{ github.event_name == 'release' && github.event.release.tag_name || github.event_name == 'workflow_dispatch' && inputs.image_tag || '' }} - execution-mode: ${{ github.event_name == 'workflow_dispatch' && inputs.execution_mode || 'self-hosted-buildkit' }} - arc-registry-cache: ${{ github.event_name == 'workflow_dispatch' && inputs.arc_registry_cache || false }} - no-cache: ${{ github.event_name == 'schedule' || (github.event_name == 'workflow_dispatch' && inputs.disable_layer_cache) || false }} - cache-from: ${{ (github.event_name == 'workflow_dispatch' && inputs.execution_mode || 'self-hosted-buildkit') == 'github-runners' && 'type=registry,ref=ghcr.io/eduide/eduide-cloud/conversion-webhook:build-cache' || '' }} - cache-to: ${{ (github.event_name == 'workflow_dispatch' && inputs.execution_mode || 'self-hosted-buildkit') == 'github-runners' && 'type=registry,ref=ghcr.io/eduide/eduide-cloud/conversion-webhook:build-cache,mode=max,image-manifest=true,oci-mediatypes=true' || '' }} - build-amd64: true - build-arm64: ${{ github.event_name != 'pull_request' }} - network: host - secrets: inherit diff --git a/.github/workflows/verify-cache.yml b/.github/workflows/verify-cache.yml deleted file mode 100644 index 2f25471f7..000000000 --- a/.github/workflows/verify-cache.yml +++ /dev/null @@ -1,228 +0,0 @@ -name: Verify Cache Infrastructure - -on: - workflow_dispatch: - schedule: - - cron: '0 6 * * 1' # Weekly check on Mondays - push: - paths: - - '.github/workflows/verify-cache.yml' - -jobs: - verify-apt-cache: - name: Verify APT Cache (apt-cacher-ng) - runs-on: arc-runner-set-arm64 - steps: - - name: Connectivity Check - run: | - PROXY="http://apt-cacher-ng.apt-cacher-ng.svc.cluster.local:3142" - echo "Testing connectivity to $PROXY..." - if curl -f -s -o /dev/null "$PROXY/acng-report.html"; then - echo "✅ apt-cacher-ng is reachable" - else - echo "❌ apt-cacher-ng is NOT reachable" - exit 1 - fi - - - name: Functional Test - Large Install - run: | - # Create a Dockerfile that installs multiple packages to stress test the cache - cat > Dockerfile.apt-stress <<'EOF' - FROM ubuntu:24.04 - ARG APT_HTTP_PROXY - ENV DEBIAN_FRONTEND=noninteractive - - # Configure Proxy - RUN if [ -n "$APT_HTTP_PROXY" ]; then \ - echo "Acquire::http::Proxy \"$APT_HTTP_PROXY\";" > /etc/apt/apt.conf.d/01proxy; \ - sed -i 's|https://|http://|g' /etc/apt/sources.list.d/*.sources 2>/dev/null || true; \ - echo "✅ Configured APT Proxy"; \ - fi - - # 1. Update Index (Metadata Cache) - RUN apt-get update - - # 2. Install common build tools (Medium load) - RUN apt-get install -y --no-install-recommends \ - build-essential \ - git \ - curl \ - ca-certificates \ - jq - - # 3. Install a larger package set (Heavier load) - RUN apt-get install -y --no-install-recommends \ - python3 \ - python3-pip \ - openjdk-21-jre-headless - - RUN echo "✅ APT stress test completed successfully" - EOF - - echo "Building stress-test image..." - docker buildx build \ - --build-arg APT_HTTP_PROXY=http://apt-cacher-ng.apt-cacher-ng.svc.cluster.local:3142 \ - --network host \ - -f Dockerfile.apt-stress \ - --progress=plain \ - . - - verify-registry-mirrors: - name: Verify Registry Mirrors - runs-on: arc-runner-set-arm64 - steps: - - name: Docker Hub Mirror Check - run: | - MIRROR="http://registry-mirror.registry-mirror.svc.cluster.local:5000" - echo "Testing Docker Hub Mirror ($MIRROR)..." - - # 1. API Connectivity - if curl -f -s "$MIRROR/v2/" > /dev/null; then - echo "✅ /v2/ endpoint reachable" - else - echo "❌ /v2/ endpoint unreachable" - exit 1 - fi - - # 2. Pull Test (Alpine - Small) - echo "Pulling alpine:latest..." - docker pull alpine:latest - docker rmi alpine:latest - - # 3. Pull Test (Python Slim - Medium) - echo "Pulling python:3.11-slim..." - docker pull python:3.11-slim - docker rmi python:3.11-slim - - - name: GHCR Mirror Check - run: | - MIRROR="http://registry-mirror-ghcr.registry-mirror.svc.cluster.local:5000" - echo "Testing GHCR Mirror ($MIRROR)..." - - # 1. API Connectivity - if curl -f -s "$MIRROR/v2/" > /dev/null; then - echo "✅ /v2/ endpoint reachable" - else - echo "❌ /v2/ endpoint unreachable" - exit 1 - fi - - # 2. Pull Test (ghcr.io image) - # We use a public GHCR image for testing - IMAGE="ghcr.io/actions/actions-runner:latest" - echo "Pulling $IMAGE..." - docker pull $IMAGE - docker rmi $IMAGE - - verify-npm-cache: - name: Verify NPM Cache (Verdaccio) - runs-on: arc-runner-set-arm64 - steps: - - name: Verdaccio Functional Test - run: | - REGISTRY="http://verdaccio.verdaccio.svc.cluster.local:4873" - echo "Testing Verdaccio ($REGISTRY)..." - - # Use a node container to run the test since the runner lacks npm - # We use --network host to ensure access to cluster DNS - docker run --rm --network host node:20-alpine sh -c " - echo 'Configuring NPM...' - mkdir -p /tmp/npm-test - cd /tmp/npm-test - npm config set registry $REGISTRY - - echo 'Ping check...' - npm ping - - echo 'Installing lodash...' - npm install lodash - - echo 'Installing react...' - npm install react - - echo '✅ NPM install tests passed' - " - - verify-squid-cache: - name: Verify Squid HTTPS Proxy (Extension Cache) - runs-on: arc-runner-set-arm64 - steps: - - name: Checkout for CA certificate - uses: actions/checkout@v4 - - - name: Install Squid CA Certificate - run: | - sudo cp certs/squid-proxy-ca.crt /usr/local/share/ca-certificates/squid-proxy-ca.crt - sudo update-ca-certificates - echo "✅ Squid CA certificate installed" - - - name: Squid Connectivity Check - run: | - PROXY_HTTP="http://squid.squid.svc.cluster.local:3128" - PROXY_HTTPS="http://squid.squid.svc.cluster.local:3129" - - echo "Testing Squid HTTP proxy ($PROXY_HTTP)..." - if curl -f -s -o /dev/null -x "$PROXY_HTTP" http://www.google.com; then - echo "✅ Squid HTTP proxy (port 3128) is reachable" - else - echo "❌ Squid HTTP proxy (port 3128) is NOT reachable" - exit 1 - fi - - echo "Testing Squid HTTPS proxy ($PROXY_HTTPS)..." - if curl -f -s -o /dev/null -x "$PROXY_HTTPS" -k https://www.google.com; then - echo "✅ Squid HTTPS proxy (port 3129) is reachable" - else - echo "❌ Squid HTTPS proxy (port 3129) is NOT reachable" - exit 1 - fi - - - name: Functional Test - VSIX Extension Download - run: | - PROXY="http://squid.squid.svc.cluster.local:3129" - - echo "Testing VSIX extension caching through Squid..." - echo "This tests the primary use case: caching VS Code extensions" - - EXTENSION_URL="https://open-vsx.org/api/dbaeumer/vscode-eslint/2.4.4/file/dbaeumer.vscode-eslint-2.4.4.vsix" - - echo "First download (cache MISS expected)..." - time curl -f -s -o /dev/null \ - -x "$PROXY" \ - -k \ - "$EXTENSION_URL" - - echo "" - echo "Second download (cache HIT expected - should be faster)..." - time curl -f -s -o /dev/null \ - -x "$PROXY" \ - -k \ - "$EXTENSION_URL" - - echo "✅ Squid proxy successfully cached VSIX extension" - - report-status: - name: Cache Health Report - runs-on: arc-runner-set-arm64 - needs: [verify-apt-cache, verify-registry-mirrors, verify-npm-cache, verify-squid-cache] - if: always() - steps: - - name: Generate Report - run: | - echo "## 🛡️ Cache Infrastructure Health Report" >> $GITHUB_STEP_SUMMARY - echo "| Cache Service | Status |" >> $GITHUB_STEP_SUMMARY - echo "|---------------|--------|" >> $GITHUB_STEP_SUMMARY - echo "| APT Cache | ${{ needs.verify-apt-cache.result }} |" >> $GITHUB_STEP_SUMMARY - echo "| Docker Mirror | ${{ needs.verify-registry-mirrors.result }} |" >> $GITHUB_STEP_SUMMARY - echo "| NPM Cache | ${{ needs.verify-npm-cache.result }} |" >> $GITHUB_STEP_SUMMARY - echo "| Squid Proxy | ${{ needs.verify-squid-cache.result }} |" >> $GITHUB_STEP_SUMMARY - - if [ "${{ needs.verify-apt-cache.result }}" == "success" ] && \ - [ "${{ needs.verify-registry-mirrors.result }}" == "success" ] && \ - [ "${{ needs.verify-npm-cache.result }}" == "success" ] && \ - [ "${{ needs.verify-squid-cache.result }}" == "success" ]; then - echo "✅ **All Systems Operational**" >> $GITHUB_STEP_SUMMARY - else - echo "⚠️ **Issues Detected**" >> $GITHUB_STEP_SUMMARY - exit 1 - fi diff --git a/certs/squid-proxy-ca.crt b/certs/squid-proxy-ca.crt deleted file mode 100644 index 9ba57272a..000000000 --- a/certs/squid-proxy-ca.crt +++ /dev/null @@ -1,19 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDEzCCAfugAwIBAgIUTqheUroyRY7HXO/ZWOtYRLb9UNEwDQYJKoZIhvcNAQEL -BQAwGTEXMBUGA1UEAwwOU3F1aWQgUHJveHkgQ0EwHhcNMjYwMTMwMTM1MzQ1WhcN -MzYwMTI4MTM1MzQ1WjAZMRcwFQYDVQQDDA5TcXVpZCBQcm94eSBDQTCCASIwDQYJ -KoZIhvcNAQEBBQADggEPADCCAQoCggEBAK9IsocfXPEE2WzM2W7waBxrGDUx5Awb -dS9ZgW+0JDzKQUjsAScSEjo8pyJqWwDSoXyK+8m5oUzItCK2QYavKfD+QPgm9+xY -DYhTS9x2jANozamWwKRdA9ItoI3McsUW8vDZ4rAEaclK3Scuu8/Ak1dMcDzfaHqY -zjiRba0tW4MSpHGaJCBhyiwWF5imuLfZDsUSaSGwC8TmrcD8/yHQtWre2pC5OFQT -+ug3E/w5oolOvSNXtwyCjAUDhrLUBncC+xNfcyAa4VGx2kfusrQBW1TKgVaag5Ih -Sny2slRo3eo6wwfXi90YaYt82B7PCuZ+ScrbjOURLgC+zYip5yWsfAcCAwEAAaNT -MFEwHQYDVR0OBBYEFIG0Ue9aaRtkXMNnp1vYaSyg1a2XMB8GA1UdIwQYMBaAFIG0 -Ue9aaRtkXMNnp1vYaSyg1a2XMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEL -BQADggEBAKQ4F0UdfnfSJRqaAHs+aWuPtJqAruCUM0f1j1qfCo2MXtHQUfXste6K -ip7wrwpyXktrEov6xN5VzMwKIfhaWrwl1LuHxVTgMdXg7TmmrrLFRF1fgD+e1a03 -O2jkCYqdiNYnE/mz/ktWfYe8iGslt0wBye7pbI7XzlcYCmwHF9Nqday3Dj5cnb0t -VG91cSXfqSaLI6WeAygjoYkSchPn6XF3+x4+Ts6s78N/XWpCANxtsrb22/Vz+qXJ -rTzlXoNrFq3KWRaWuGKrI8d375xeUf9jQgv8jLcYJFpYnMe1j40tNd0coEx1nIHh -MOR1nRBTbgIlIzILTFq60T0b2znFiok= ------END CERTIFICATE-----