From 08c9eb4420f516bbcc065ca79337ced72e148799 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Thu, 4 Dec 2025 19:50:29 -0500 Subject: [PATCH 1/2] ci: Split image publishing into separate workflow for security Previously, the CI workflow granted packages:write permission at the workflow level, making GITHUB_TOKEN with write access available to all jobs including those running on pull requests. While the actual push steps were gated with conditionals, malicious PR code could use the token to push arbitrary images to ghcr.io. Split image publishing into a dedicated build-and-publish.yml workflow that only runs on push to main, with no PR execution. This follows GitHub security best practices by isolating write credentials from untrusted PR code. The new workflow builds and publishes all image variants using a simple matrix with explicit exclude for centos-9 UKI (broken per #1812). Assisted-by: Claude Code (Sonnet 4.5) Signed-off-by: Colin Walters --- .github/workflows/build-and-publish.yml | 62 +++++++++++++++++++++++++ .github/workflows/ci.yml | 29 ------------ 2 files changed, 62 insertions(+), 29 deletions(-) create mode 100644 .github/workflows/build-and-publish.yml diff --git a/.github/workflows/build-and-publish.yml b/.github/workflows/build-and-publish.yml new file mode 100644 index 000000000..817778f9b --- /dev/null +++ b/.github/workflows/build-and-publish.yml @@ -0,0 +1,62 @@ +name: Build and Publish Images + +permissions: + packages: write + +on: + push: + branches: [main] + workflow_dispatch: {} + +env: + CARGO_TERM_COLOR: always + LIBVIRT_DEFAULT_URI: "qemu:///session" + DEV_IMAGE: ghcr.io/bootc-dev/dev-bootc + +jobs: + # Build and publish container images to ghcr.io + publish-images: + strategy: + matrix: + test_os: [fedora-42, fedora-43, fedora-44, centos-9, centos-10] + variant: [ostree, composefs-sealeduki-sdboot] + exclude: + # centos-9 UKI is experimental/broken (https://github.com/bootc-dev/bootc/issues/1812) + - test_os: centos-9 + variant: composefs-sealeduki-sdboot + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v6 + - name: Bootc Ubuntu Setup + uses: ./.github/actions/bootc-ubuntu-setup + + - name: Setup env + run: | + BASE=$(just pullspec-for-os base ${{ matrix.test_os }}) + echo "BOOTC_base=${BASE}" >> $GITHUB_ENV + echo "BOOTC_variant=${{ matrix.variant }}" >> $GITHUB_ENV + + if [ "${{ matrix.variant }}" = "composefs-sealeduki-sdboot" ]; then + BUILDROOTBASE=$(just pullspec-for-os buildroot-base ${{ matrix.test_os }}) + echo "BOOTC_buildroot_base=${BUILDROOTBASE}" >> $GITHUB_ENV + fi + + - name: Build container + run: just build-integration-test-image + + - name: Login to ghcr.io + uses: redhat-actions/podman-login@v1 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Push container image + run: | + if [ "${{ matrix.variant }}" = "composefs-sealeduki-sdboot" ]; then + TAG="${{ matrix.test_os }}-uki" + else + TAG="${{ matrix.test_os }}" + fi + podman tag localhost/bootc ${{ env.DEV_IMAGE }}:${TAG} + podman push ${{ env.DEV_IMAGE }}:${TAG} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fa330f72d..7bdec4d34 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,7 +10,6 @@ name: CI permissions: actions: read - packages: write on: push: @@ -159,20 +158,6 @@ jobs: name: tmt-log-PR-${{ github.event.number }}-${{ matrix.test_os }}-ostree-${{ env.ARCH }} path: /var/tmp/tmt - - name: Login to ghcr.io - if: github.event_name == 'push' && github.ref == 'refs/heads/main' - uses: redhat-actions/podman-login@v1 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Push container image - if: github.event_name == 'push' && github.ref == 'refs/heads/main' - run: | - podman tag localhost/bootc ${{ env.DEV_IMAGE }}:${{ matrix.test_os }} - podman push ${{ env.DEV_IMAGE }}:${{ matrix.test_os }} - # This variant does composefs testing test-integration-cfs: continue-on-error: ${{ matrix.experimental }} @@ -229,20 +214,6 @@ jobs: name: tmt-log-PR-${{ github.event.number }}-${{ matrix.test_os }}-cfs-${{ env.ARCH }} path: /var/tmp/tmt - - name: Login to ghcr.io - if: github.event_name == 'push' && github.ref == 'refs/heads/main' - uses: redhat-actions/podman-login@v1 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Push container image - if: github.event_name == 'push' && github.ref == 'refs/heads/main' - run: | - podman tag localhost/bootc ${{ env.DEV_IMAGE }}:stream10-uki - podman push ${{ env.DEV_IMAGE }}:stream10-uki - # Sentinel job for required checks - configure this job name in repository settings required-checks: if: always() From 0ca59fc3d1a771eedc91211f9f104ee6df521351 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Thu, 4 Dec 2025 19:56:47 -0500 Subject: [PATCH 2/2] ci: Unify test-integration jobs into single matrix MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Consolidate test-integration and test-integration-cfs into a single job using a unified matrix (test_os × variant) matching the structure of build-and-publish.yml. This eliminates code duplication and simplifies maintenance. Updated required-checks sentinel to depend only on the unified job. Assisted-by: Claude Code (Sonnet 4.5) Signed-off-by: Colin Walters --- .github/workflows/ci.yml | 79 ++++++++++------------------------------ 1 file changed, 19 insertions(+), 60 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7bdec4d34..063e62e23 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -120,59 +120,12 @@ jobs: strategy: fail-fast: false matrix: - test_os: [fedora-42, fedora-43, centos-9, centos-10] - - runs-on: ubuntu-24.04 - - steps: - - uses: actions/checkout@v6 - - name: Bootc Ubuntu Setup - uses: ./.github/actions/bootc-ubuntu-setup - with: - libvirt: true - - name: Install tmt - run: pip install --user "tmt[provision-virtual]" - - - name: Setup env - run: | - BASE=$(just pullspec-for-os base ${{ matrix.test_os }}) - echo "BOOTC_base=${BASE}" >> $GITHUB_ENV - - - name: Build container - run: | - just build-integration-test-image - # Extra cross-check (duplicating the integration test) that we're using the right base - used_vid=$(podman run --rm localhost/bootc-integration bash -c '. /usr/lib/os-release && echo ${ID}-${VERSION_ID}') - test ${{ matrix.test_os }} = "${used_vid}" - - - name: Unit and container integration tests - run: just test-container - - - name: Run all TMT tests - run: just test-tmt - - - name: Archive TMT logs - if: always() - uses: actions/upload-artifact@v5 - with: - name: tmt-log-PR-${{ github.event.number }}-${{ matrix.test_os }}-ostree-${{ env.ARCH }} - path: /var/tmp/tmt - - # This variant does composefs testing - test-integration-cfs: - continue-on-error: ${{ matrix.experimental }} - strategy: - fail-fast: false - matrix: - # OS via Justfile variables too - test_os: [fedora-42, fedora-43, fedora-44, centos-10] - variant: [composefs-sealeduki-sdboot] - experimental: [false] - # For issue https://github.com/bootc-dev/bootc/issues/1812 - include: + test_os: [fedora-42, fedora-43, fedora-44, centos-9, centos-10] + variant: [ostree, composefs-sealeduki-sdboot] + exclude: + # centos-9 UKI is experimental/broken (https://github.com/bootc-dev/bootc/issues/1812) - test_os: centos-9 variant: composefs-sealeduki-sdboot - experimental: true runs-on: ubuntu-24.04 @@ -188,10 +141,13 @@ jobs: - name: Setup env run: | BASE=$(just pullspec-for-os base ${{ matrix.test_os }}) - BUILDROOTBASE=$(just pullspec-for-os buildroot-base ${{ matrix.test_os }}) echo "BOOTC_base=${BASE}" >> $GITHUB_ENV - echo "BOOTC_buildroot_base=${BUILDROOTBASE}" >> $GITHUB_ENV - echo "BOOTC_variant="${{ matrix.variant }} >> $GITHUB_ENV + echo "BOOTC_variant=${{ matrix.variant }}" >> $GITHUB_ENV + + if [ "${{ matrix.variant }}" = "composefs-sealeduki-sdboot" ]; then + BUILDROOTBASE=$(just pullspec-for-os buildroot-base ${{ matrix.test_os }}) + echo "BOOTC_buildroot_base=${BUILDROOTBASE}" >> $GITHUB_ENV + fi - name: Build container run: | @@ -204,25 +160,28 @@ jobs: run: just test-container - name: Run TMT tests - # Note that this one only runs a subset of tests right now - run: just test-composefs + run: | + if [ "${{ matrix.variant }}" = "composefs-sealeduki-sdboot" ]; then + just test-composefs + else + just test-tmt + fi - name: Archive TMT logs if: always() uses: actions/upload-artifact@v5 with: - name: tmt-log-PR-${{ github.event.number }}-${{ matrix.test_os }}-cfs-${{ env.ARCH }} + name: tmt-log-PR-${{ github.event.number }}-${{ matrix.test_os }}-${{ matrix.variant }}-${{ env.ARCH }} path: /var/tmp/tmt # Sentinel job for required checks - configure this job name in repository settings required-checks: if: always() - needs: [cargo-deny, validate, test-integration, test-integration-cfs] + needs: [cargo-deny, validate, test-integration] runs-on: ubuntu-latest steps: - run: exit 1 if: >- needs.cargo-deny.result != 'success' || needs.validate.result != 'success' || - needs.test-integration.result != 'success' || - needs.test-integration-cfs.result != 'success' + needs.test-integration.result != 'success'