From 6ffe220dab16a8831468cdd11627b261107f5ff0 Mon Sep 17 00:00:00 2001 From: stewartshea Date: Fri, 10 Apr 2026 19:44:41 -0400 Subject: [PATCH 1/5] Update Dockerfile and GitHub Actions workflow for improved build process - Enhanced Dockerfile by adding essential development tools and optimizing package installation. - Updated GitHub Actions workflow to use newer action versions and streamlined the build process with Docker Buildx for multi-platform support. - Configured build arguments and tags for better artifact management during CI/CD. --- .github/workflows/build-push.yaml | 56 ++++++++++++++++++++----------- Dockerfile | 15 ++++++--- 2 files changed, 47 insertions(+), 24 deletions(-) diff --git a/.github/workflows/build-push.yaml b/.github/workflows/build-push.yaml index a435194..13c6699 100644 --- a/.github/workflows/build-push.yaml +++ b/.github/workflows/build-push.yaml @@ -41,13 +41,22 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v4 - - name: Build Test - run: | - echo "Running a quick Docker build test..." - docker build -f Dockerfile . - echo "Build test completed." + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Build test (linux/amd64, linux/arm64) + uses: docker/build-push-action@v6 + with: + context: . + file: Dockerfile + platforms: linux/amd64,linux/arm64 + push: false + tags: codecollection-devtools:pr-test # ------------------------------------------------------------------------------ # JOB 2: Build and Push on Push to Main (or manual trigger) @@ -58,7 +67,13 @@ jobs: if: ${{ github.event_name == 'push' || github.event_name == 'workflow_dispatch' }} runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 + + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 - id: 'auth-runwhen' name: 'Authenticate to Google Cloud' @@ -89,19 +104,20 @@ jobs: docker login --username ${{ github.actor }} --password-stdin ghcr.io - name: Build & Push - run: |- - docker buildx create --use --name=mybuilder - docker buildx inspect --bootstrap - docker buildx build \ - --push \ - --platform linux/amd64,linux/arm64 \ - --tag "${{ env.SHARED_ARTIFACT_REPOSITORY_PATH }}/${{ env.IMAGE }}:${{ env.VERSION }}" \ - --tag "${{ env.SHARED_ARTIFACT_REPOSITORY_PATH }}/${{ env.IMAGE }}:latest" \ - --tag "ghcr.io/${{ env.GHCR_ORG }}/${{ env.IMAGE }}:${{ env.VERSION }}" \ - --tag "ghcr.io/${{ env.GHCR_ORG }}/${{ env.IMAGE }}:latest" \ - --build-arg GITHUB_SHA="${GITHUB_SHA}" \ - --build-arg GITHUB_REF="${GITHUB_REF}" \ - -f Dockerfile . + uses: docker/build-push-action@v6 + with: + context: . + file: Dockerfile + platforms: linux/amd64,linux/arm64 + push: true + tags: | + ${{ env.SHARED_ARTIFACT_REPOSITORY_PATH }}/${{ env.IMAGE }}:${{ env.VERSION }} + ${{ env.SHARED_ARTIFACT_REPOSITORY_PATH }}/${{ env.IMAGE }}:latest + ghcr.io/${{ env.GHCR_ORG }}/${{ env.IMAGE }}:${{ env.VERSION }} + ghcr.io/${{ env.GHCR_ORG }}/${{ env.IMAGE }}:latest + build-args: | + GITHUB_SHA=${{ github.sha }} + GITHUB_REF=${{ github.ref }} - name: Notify Slack of Container Build id: slack-publish-nonprod-shared-artifact-repo diff --git a/Dockerfile b/Dockerfile index d68fb89..50cd624 100644 --- a/Dockerfile +++ b/Dockerfile @@ -24,13 +24,20 @@ RUN usermod -u 1000 runwhen && \ groupmod -g 1000 runwhen ############################################################################### -# Dev tools: sudo, lnav, go-task, terraform +# Dev tools: sudo, gpg/apt deps (bookworm+ has HTTPS in apt; skip apt-transport-https) ############################################################################### +ENV DEBIAN_FRONTEND=noninteractive RUN apt-get update && \ apt-get install -y --no-install-recommends \ - sudo apt-transport-https gnupg2 lsb-release && \ - apt-get clean && \ - rm -rf /var/lib/apt/lists/* + ca-certificates \ + curl \ + gnupg \ + lsb-release \ + sudo \ + unzip \ + wget \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* RUN echo "runwhen ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers From 96fb282d4862a888fc2572eb56b841786c6f7bb5 Mon Sep 17 00:00:00 2001 From: stewartshea Date: Fri, 10 Apr 2026 19:55:18 -0400 Subject: [PATCH 2/5] Optimize Dockerfile for improved APT configuration and installation process - Added custom APT configuration to handle timeouts and retries, enhancing reliability during package installation. - Removed unnecessary package installations, streamlining the Dockerfile for better performance. --- Dockerfile | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/Dockerfile b/Dockerfile index 50cd624..fc9b875 100644 --- a/Dockerfile +++ b/Dockerfile @@ -25,17 +25,22 @@ RUN usermod -u 1000 runwhen && \ ############################################################################### # Dev tools: sudo, gpg/apt deps (bookworm+ has HTTPS in apt; skip apt-transport-https) +# Base image (robot-runtime-base) already ships: curl, ca-certificates, wget, unzip. +# Apt under QEMU (arm64 on amd64 CI) often exits 100 without Pipeline-Depth=0 + retries. ############################################################################### ENV DEBIAN_FRONTEND=noninteractive -RUN apt-get update && \ - apt-get install -y --no-install-recommends \ - ca-certificates \ - curl \ +RUN printf '%s\n' \ + 'Acquire::http::Pipeline-Depth "0";' \ + 'Acquire::https::Pipeline-Depth "0";' \ + 'Acquire::Retries "5";' \ + 'Acquire::http::Timeout "120";' \ + 'Acquire::https::Timeout "120";' \ + > /etc/apt/apt.conf.d/99docker-ci \ + && apt-get update \ + && apt-get install -y --no-install-recommends \ gnupg \ lsb-release \ sudo \ - unzip \ - wget \ && apt-get clean \ && rm -rf /var/lib/apt/lists/* From 7b3de225f42451321ecdde87e7c2da6bbb2b76e5 Mon Sep 17 00:00:00 2001 From: stewartshea Date: Fri, 10 Apr 2026 19:58:52 -0400 Subject: [PATCH 3/5] Enhance GitHub Actions workflow for multi-architecture builds - Introduced separate jobs for building and pushing Docker images for linux/amd64 and linux/arm64 architectures. - Added workflow inputs to control the build process for each architecture during manual triggers. - Streamlined the build process by ensuring parallel execution of tests for both architectures in pull requests. - Updated tagging strategy for built images to include architecture-specific tags for better artifact management. --- .github/workflows/build-push.yaml | 199 ++++++++++++++++++++++-------- 1 file changed, 148 insertions(+), 51 deletions(-) diff --git a/.github/workflows/build-push.yaml b/.github/workflows/build-push.yaml index 13c6699..eb60829 100644 --- a/.github/workflows/build-push.yaml +++ b/.github/workflows/build-push.yaml @@ -1,12 +1,9 @@ name: Build and Push on: - # 1) Trigger on pull request (e.g., to main branch) for a simple build test pull_request: branches: - main - # 2) Trigger on push to main (and optionally only when certain files change), - # plus allow manual runs push: branches: - main @@ -17,6 +14,15 @@ on: - ".devcontainer/**" - ".github/workflows/build-push.yaml" workflow_dispatch: + inputs: + build_amd64: + description: "Release: push linux/amd64 (uncheck to skip). PRs always test both arches in parallel." + type: boolean + default: true + build_arm64: + description: "Release: push linux/arm64 (uncheck to skip). PRs always test both arches in parallel." + type: boolean + default: true permissions: contents: "read" @@ -33,103 +39,194 @@ env: jobs: # ------------------------------------------------------------------------------ - # JOB 1: Build Test for Pull Requests + # PR: parallel build tests (native amd64; arm64 via QEMU) # ------------------------------------------------------------------------------ - build-test: - # Only run this job if the event is a Pull Request + build-test-amd64: if: ${{ github.event_name == 'pull_request' }} runs-on: ubuntu-latest steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 + - uses: actions/checkout@v4 + - uses: docker/setup-buildx-action@v3 + - name: Build test (linux/amd64) + uses: docker/build-push-action@v6 + with: + context: . + file: Dockerfile + platforms: linux/amd64 + push: false + tags: codecollection-devtools:pr-test-amd64 - - name: Build test (linux/amd64, linux/arm64) + build-test-arm64: + if: ${{ github.event_name == 'pull_request' }} + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: docker/setup-qemu-action@v3 + - uses: docker/setup-buildx-action@v3 + - name: Build test (linux/arm64) uses: docker/build-push-action@v6 with: context: . file: Dockerfile - platforms: linux/amd64,linux/arm64 + platforms: linux/arm64 push: false - tags: codecollection-devtools:pr-test + tags: codecollection-devtools:pr-test-arm64 # ------------------------------------------------------------------------------ - # JOB 2: Build and Push on Push to Main (or manual trigger) + # Release: shared VERSION for per-arch pushes + manifest merge # ------------------------------------------------------------------------------ - build-and-push: - # Only run this job if the event is a 'push' (incl. workflow_dispatch). - # That way PRs won't push images. + prepare-release: if: ${{ github.event_name == 'push' || github.event_name == 'workflow_dispatch' }} runs-on: ubuntu-latest + outputs: + version: ${{ steps.version.outputs.version }} steps: - uses: actions/checkout@v4 - - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - - id: 'auth-runwhen' - name: 'Authenticate to Google Cloud' - uses: 'google-github-actions/auth@v0.4.0' - with: - workload_identity_provider: ${{ secrets.RUNWHEN_NONPROD_SHARED_WI_PROVIDER }} - service_account: ${{ secrets.RUNWHEN_NONPROD_SHARED_WI_SA }} - - - name: Set tag and version - run: |- + - id: version + run: | if [[ -s VERSION ]]; then - VERSION=$(cat VERSION) - echo "VERSION=$VERSION" >> $GITHUB_ENV + VERSION=$(cat VERSION | tr -d '[:space:]') + echo "version=$VERSION" >> "$GITHUB_OUTPUT" + echo "VERSION=$VERSION" >> "$GITHUB_ENV" echo "VERSION extracted: $VERSION" else echo "VERSION file is missing or empty" >&2 exit 1 fi - # Create a 'TAG' environment variable from the branch name + short SHA - echo "TAG=$(echo $GITHUB_REF_NAME | sed 's/[^a-zA-Z0-9]/-/g')-${GITHUB_SHA::8}" >> $GITHUB_ENV + build-push-amd64: + needs: [prepare-release] + if: | + (github.event_name == 'push' || github.event_name == 'workflow_dispatch') && + (github.event_name == 'push' || github.event.inputs.build_amd64 == 'true') + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: docker/setup-buildx-action@v3 + - id: auth-runwhen + name: Authenticate to Google Cloud + uses: google-github-actions/auth@v0.4.0 + with: + workload_identity_provider: ${{ secrets.RUNWHEN_NONPROD_SHARED_WI_PROVIDER }} + service_account: ${{ secrets.RUNWHEN_NONPROD_SHARED_WI_SA }} - name: Configure docker for GCP run: gcloud --quiet auth configure-docker us-docker.pkg.dev - - name: Login to GHCR run: | echo "${{ secrets.GITHUB_TOKEN }}" | \ docker login --username ${{ github.actor }} --password-stdin ghcr.io + - name: Build & push (linux/amd64) + uses: docker/build-push-action@v6 + with: + context: . + file: Dockerfile + platforms: linux/amd64 + push: true + tags: | + ${{ env.SHARED_ARTIFACT_REPOSITORY_PATH }}/${{ env.IMAGE }}:${{ needs.prepare-release.outputs.version }}-amd64 + ghcr.io/${{ env.GHCR_ORG }}/${{ env.IMAGE }}:${{ needs.prepare-release.outputs.version }}-amd64 + build-args: | + GITHUB_SHA=${{ github.sha }} + GITHUB_REF=${{ github.ref }} - - name: Build & Push + build-push-arm64: + needs: [prepare-release] + if: | + (github.event_name == 'push' || github.event_name == 'workflow_dispatch') && + (github.event_name == 'push' || github.event.inputs.build_arm64 == 'true') + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: docker/setup-qemu-action@v3 + - uses: docker/setup-buildx-action@v3 + - id: auth-runwhen + name: Authenticate to Google Cloud + uses: google-github-actions/auth@v0.4.0 + with: + workload_identity_provider: ${{ secrets.RUNWHEN_NONPROD_SHARED_WI_PROVIDER }} + service_account: ${{ secrets.RUNWHEN_NONPROD_SHARED_WI_SA }} + - name: Configure docker for GCP + run: gcloud --quiet auth configure-docker us-docker.pkg.dev + - name: Login to GHCR + run: | + echo "${{ secrets.GITHUB_TOKEN }}" | \ + docker login --username ${{ github.actor }} --password-stdin ghcr.io + - name: Build & push (linux/arm64) uses: docker/build-push-action@v6 with: context: . file: Dockerfile - platforms: linux/amd64,linux/arm64 + platforms: linux/arm64 push: true tags: | - ${{ env.SHARED_ARTIFACT_REPOSITORY_PATH }}/${{ env.IMAGE }}:${{ env.VERSION }} - ${{ env.SHARED_ARTIFACT_REPOSITORY_PATH }}/${{ env.IMAGE }}:latest - ghcr.io/${{ env.GHCR_ORG }}/${{ env.IMAGE }}:${{ env.VERSION }} - ghcr.io/${{ env.GHCR_ORG }}/${{ env.IMAGE }}:latest + ${{ env.SHARED_ARTIFACT_REPOSITORY_PATH }}/${{ env.IMAGE }}:${{ needs.prepare-release.outputs.version }}-arm64 + ghcr.io/${{ env.GHCR_ORG }}/${{ env.IMAGE }}:${{ needs.prepare-release.outputs.version }}-arm64 build-args: | GITHUB_SHA=${{ github.sha }} GITHUB_REF=${{ github.ref }} + merge-manifests: + needs: [prepare-release, build-push-amd64, build-push-arm64] + if: | + always() && !cancelled() && + needs.prepare-release.result == 'success' && + ( + (github.event_name == 'push' && + needs.build-push-amd64.result == 'success' && + needs.build-push-arm64.result == 'success') || + (github.event_name == 'workflow_dispatch' && + (needs.build-push-amd64.result == 'success' || needs.build-push-arm64.result == 'success')) + ) + runs-on: ubuntu-latest + steps: + - id: auth-runwhen + name: Authenticate to Google Cloud + uses: google-github-actions/auth@v0.4.0 + with: + workload_identity_provider: ${{ secrets.RUNWHEN_NONPROD_SHARED_WI_PROVIDER }} + service_account: ${{ secrets.RUNWHEN_NONPROD_SHARED_WI_SA }} + - name: Configure docker for GCP + run: gcloud --quiet auth configure-docker us-docker.pkg.dev + - name: Login to GHCR + run: | + echo "${{ secrets.GITHUB_TOKEN }}" | \ + docker login --username ${{ github.actor }} --password-stdin ghcr.io + - uses: docker/setup-buildx-action@v3 + - name: Merge multi-arch manifests (GCP + GHCR) + env: + V: ${{ needs.prepare-release.outputs.version }} + GCP_BASE: ${{ env.SHARED_ARTIFACT_REPOSITORY_PATH }}/${{ env.IMAGE }} + GHCR_BASE: ghcr.io/${{ env.GHCR_ORG }}/${{ env.IMAGE }} + AMD64_OK: ${{ needs.build-push-amd64.result }} + ARM64_OK: ${{ needs.build-push-arm64.result }} + run: | + set -euo pipefail + GCP_REF=() + GHCR_REF=() + if [[ "$AMD64_OK" == "success" ]]; then + GCP_REF+=("${GCP_BASE}:${V}-amd64") + GHCR_REF+=("${GHCR_BASE}:${V}-amd64") + fi + if [[ "$ARM64_OK" == "success" ]]; then + GCP_REF+=("${GCP_BASE}:${V}-arm64") + GHCR_REF+=("${GHCR_BASE}:${V}-arm64") + fi + docker buildx imagetools create \ + -t "${GCP_BASE}:${V}" -t "${GCP_BASE}:latest" \ + "${GCP_REF[@]}" + docker buildx imagetools create \ + -t "${GHCR_BASE}:${V}" -t "${GHCR_BASE}:latest" \ + "${GHCR_REF[@]}" + - name: Notify Slack of Container Build - id: slack-publish-nonprod-shared-artifact-repo uses: slackapi/slack-github-action@v1.19.0 with: channel-id: "#notifications" - slack-message: "Just Pushed to ${{ env.SHARED_ARTIFACT_REPOSITORY_PATH }}/${{ env.IMAGE }}:${{ env.VERSION }}" + slack-message: "Just Pushed to ${{ env.SHARED_ARTIFACT_REPOSITORY_PATH }}/${{ env.IMAGE }}:${{ needs.prepare-release.outputs.version }}" env: SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }} - name: Notify Slack of GHCR Push - id: slack-deploy-to-ghcr uses: slackapi/slack-github-action@v1.19.0 with: channel-id: "#codecollections" From cc1965708263cc75d60914893c85bd50ad0bc579 Mon Sep 17 00:00:00 2001 From: stewartshea Date: Fri, 10 Apr 2026 20:02:57 -0400 Subject: [PATCH 4/5] Refactor Dockerfile and GitHub Actions workflow for improved reliability and clarity - Updated APT configuration in the Dockerfile to enhance reliability during package installation with retries and timeout handling. - Simplified the installation process by clearing APT lists and adding retry logic for better performance under flaky network conditions. - Adjusted the CMD instruction to use JSON format for cleaner signal handling and specified the log directory directly. - Modified the GitHub Actions workflow to enable loading of the Docker image, improving the build process for multi-architecture support. --- .github/workflows/build-push.yaml | 1 + Dockerfile | 31 ++++++++++++++++--------------- docker/apt-ci.conf | 6 ++++++ 3 files changed, 23 insertions(+), 15 deletions(-) create mode 100644 docker/apt-ci.conf diff --git a/.github/workflows/build-push.yaml b/.github/workflows/build-push.yaml index eb60829..1e82e28 100644 --- a/.github/workflows/build-push.yaml +++ b/.github/workflows/build-push.yaml @@ -54,6 +54,7 @@ jobs: file: Dockerfile platforms: linux/amd64 push: false + load: true tags: codecollection-devtools:pr-test-amd64 build-test-arm64: diff --git a/Dockerfile b/Dockerfile index fc9b875..a73666e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -26,21 +26,20 @@ RUN usermod -u 1000 runwhen && \ ############################################################################### # Dev tools: sudo, gpg/apt deps (bookworm+ has HTTPS in apt; skip apt-transport-https) # Base image (robot-runtime-base) already ships: curl, ca-certificates, wget, unzip. -# Apt under QEMU (arm64 on amd64 CI) often exits 100 without Pipeline-Depth=0 + retries. +# Apt config via COPY avoids BuildKit/shell quoting issues; retries help QEMU CI. ############################################################################### +COPY docker/apt-ci.conf /etc/apt/apt.conf.d/99docker-ci ENV DEBIAN_FRONTEND=noninteractive -RUN printf '%s\n' \ - 'Acquire::http::Pipeline-Depth "0";' \ - 'Acquire::https::Pipeline-Depth "0";' \ - 'Acquire::Retries "5";' \ - 'Acquire::http::Timeout "120";' \ - 'Acquire::https::Timeout "120";' \ - > /etc/apt/apt.conf.d/99docker-ci \ - && apt-get update \ - && apt-get install -y --no-install-recommends \ - gnupg \ - lsb-release \ - sudo \ +# Clear lists + retry apt under flaky QEMU/network (exit 100). +RUN rm -rf /var/lib/apt/lists/* \ + && ( \ + apt-get update \ + && apt-get install -y --no-install-recommends gnupg lsb-release sudo \ + || (echo "apt retry 1" && sleep 15 && apt-get update \ + && apt-get install -y --no-install-recommends gnupg lsb-release sudo) \ + || (echo "apt retry 2" && sleep 25 && apt-get update \ + && apt-get install -y --no-install-recommends gnupg lsb-release sudo) \ + ) \ && apt-get clean \ && rm -rf /var/lib/apt/lists/* @@ -166,7 +165,9 @@ ENV USER="runwhen" RUN pip install --user --no-cache-dir -r requirements.txt ENV PATH="${PATH}:/usr/local/bin:${RUNWHEN_HOME}/.local/bin:${RUNWHEN_HOME}" -ENV PYTHONPATH="$PYTHONPATH:.:${RUNWHEN_HOME}/codecollection/libraries:${RUNWHEN_HOME}/codecollection/codebundles" +# Do not reference $PYTHONPATH here — it is often unset in the base image (BuildKit UndefinedVar). +ENV PYTHONPATH=".:${RUNWHEN_HOME}/codecollection/libraries:${RUNWHEN_HOME}/codecollection/codebundles" EXPOSE 3000 -CMD python -m http.server --bind 0.0.0.0 --directory $ROBOT_LOG_DIR 3000 +# JSON form for clean signals; use literal log dir (same as ENV ROBOT_LOG_DIR). +CMD ["python", "-m", "http.server", "--bind", "0.0.0.0", "--directory", "/robot_logs", "3000"] diff --git a/docker/apt-ci.conf b/docker/apt-ci.conf new file mode 100644 index 0000000..936f1a3 --- /dev/null +++ b/docker/apt-ci.conf @@ -0,0 +1,6 @@ +Acquire::http::Pipeline-Depth "0"; +Acquire::https::Pipeline-Depth "0"; +Acquire::Retries "5"; +Acquire::http::Timeout "120"; +Acquire::https::Timeout "120"; +Acquire::Check-Valid-Until "false"; From 5d877bd0aba2fd475993bba0f63829a5cf261e2a Mon Sep 17 00:00:00 2001 From: stewartshea Date: Fri, 10 Apr 2026 20:07:41 -0400 Subject: [PATCH 5/5] Refactor Dockerfile for improved APT configuration and installation process - Updated APT sources to exclusively use the bookworm suite, preventing potential conflicts with sid. - Simplified the installation process by removing unnecessary retry logic and ensuring a clean APT list before installation. - Enhanced clarity and reliability of the Dockerfile by consolidating commands and improving error handling. --- Dockerfile | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/Dockerfile b/Dockerfile index a73666e..1635c1f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -26,22 +26,27 @@ RUN usermod -u 1000 runwhen && \ ############################################################################### # Dev tools: sudo, gpg/apt deps (bookworm+ has HTTPS in apt; skip apt-transport-https) # Base image (robot-runtime-base) already ships: curl, ca-certificates, wget, unzip. -# Apt config via COPY avoids BuildKit/shell quoting issues; retries help QEMU CI. +# +# Official python:3.14-slim-bookworm can ship sid (or other suites) alongside bookworm. +# Mixing sid + bookworm breaks dpkg (openssl 3.6 vs libssl3 3.0, libgcrypt, etc.). +# Drop all list.d entries and pin /etc/apt/sources.list to bookworm only. ############################################################################### COPY docker/apt-ci.conf /etc/apt/apt.conf.d/99docker-ci ENV DEBIAN_FRONTEND=noninteractive -# Clear lists + retry apt under flaky QEMU/network (exit 100). -RUN rm -rf /var/lib/apt/lists/* \ - && ( \ - apt-get update \ - && apt-get install -y --no-install-recommends gnupg lsb-release sudo \ - || (echo "apt retry 1" && sleep 15 && apt-get update \ - && apt-get install -y --no-install-recommends gnupg lsb-release sudo) \ - || (echo "apt retry 2" && sleep 25 && apt-get update \ - && apt-get install -y --no-install-recommends gnupg lsb-release sudo) \ - ) \ - && apt-get clean \ - && rm -rf /var/lib/apt/lists/* +RUN set -eux; \ + rm -rf /var/lib/apt/lists/*; \ + for f in /etc/apt/sources.list.d/*.sources /etc/apt/sources.list.d/*.list; do \ + if [ -f "$f" ]; then rm -f "$f"; fi; \ + done; \ + printf '%s\n' \ + 'deb http://deb.debian.org/debian bookworm main' \ + 'deb http://deb.debian.org/debian bookworm-updates main' \ + 'deb http://deb.debian.org/debian-security bookworm-security main' \ + > /etc/apt/sources.list; \ + apt-get update; \ + apt-get install -y --no-install-recommends gnupg lsb-release sudo; \ + apt-get clean; \ + rm -rf /var/lib/apt/lists/* RUN echo "runwhen ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers