diff --git a/.gitea/workflows/redhat_build.yml b/.gitea/workflows/redhat_build.yml index c5e101b..aa2ed16 100644 --- a/.gitea/workflows/redhat_build.yml +++ b/.gitea/workflows/redhat_build.yml @@ -1,9 +1,6 @@ name: Build container image on: - # pull_request: - # branches: - # - main schedule: - cron: '05 12 * * 2,5' workflow_dispatch: @@ -28,46 +25,70 @@ jobs: id-token: write steps: + + # ------------------------------------------------------------ + # Environment + # ------------------------------------------------------------ + - name: Prepare environment run: | # Extrahiert die reine Domain/Host aus der Gitea-URL REGISTRY_HOST=$(echo "${{ github.server_url }}" | awk -F/ '{print $3}') + OWNER_LOWER="${{ github.repository_owner }}" NAME_LOWER="${{ env.IMAGE_NAME }}" - echo "REGISTRY_HOST=${REGISTRY_HOST}" >> ${GITHUB_ENV} - echo "IMAGE_REGISTRY=${REGISTRY_HOST}/${OWNER_LOWER,,}" >> ${GITHUB_ENV} - echo "IMAGE_NAME=${NAME_LOWER,,}" >> ${GITHUB_ENV} + echo "REGISTRY_HOST=${REGISTRY_HOST}" >> "${GITHUB_ENV}" + echo "IMAGE_REGISTRY=${REGISTRY_HOST}/${OWNER_LOWER,,}" >> "${GITHUB_ENV}" + echo "IMAGE_NAME=${NAME_LOWER,,}" >> "${GITHUB_ENV}" - name: Determine image tag run: | BRANCH="${GITHUB_REF_NAME}" + if [[ "$BRANCH" == "main" ]]; then - echo "IMAGE_TAG=${DEFAULT_TAG}" >> ${GITHUB_ENV} - echo "IS_TEST_BUILD=false" >> ${GITHUB_ENV} + echo "IMAGE_TAG=${DEFAULT_TAG}" >> "${GITHUB_ENV}" + echo "IS_TEST_BUILD=false" >> "${GITHUB_ENV}" else - SANITIZED=$(echo "$BRANCH" | sed 's/[^a-zA-Z0-9._-]/-/g' | head -c 50) - echo "IMAGE_TAG=test-${SANITIZED}" >> ${GITHUB_ENV} - echo "IS_TEST_BUILD=true" >> ${GITHUB_ENV} + SANITIZED=$(echo "$BRANCH" \ + | sed 's/[^a-zA-Z0-9._-]/-/g' \ + | head -c 50) + + echo "IMAGE_TAG=test-${SANITIZED}" >> "${GITHUB_ENV}" + echo "IS_TEST_BUILD=true" >> "${GITHUB_ENV}" fi + # ------------------------------------------------------------ + # Source + # ------------------------------------------------------------ + - name: Checkout uses: actions/checkout@v7.0.1 + # ------------------------------------------------------------ + # Buildx + # ------------------------------------------------------------ + - name: Set up Docker Buildx uses: docker/setup-buildx-action@v4.2.0 + # ------------------------------------------------------------ + # Image metadata + # ------------------------------------------------------------ + - name: Image Metadata id: metadata uses: docker/metadata-action@v6.2.0 with: images: ${{ env.IMAGE_REGISTRY }}/${{ env.IMAGE_NAME }} + tags: | type=raw,value=${{ env.IMAGE_TAG }} type=raw,value=${{ env.IMAGE_TAG }}.{{date 'YYYYMMDD'}},enable=${{ env.IS_TEST_BUILD == 'false' }} type=raw,value={{date 'YYYYMMDD'}},enable=${{ env.IS_TEST_BUILD == 'false' }} type=sha,enable=${{ github.event_name == 'pull_request' }} type=ref,event=pr + labels: | org.opencontainers.image.created={{date 'YYYY-MM-DDTHH:mm:ssZ'}} org.opencontainers.image.description=${{ env.IMAGE_DESC }} @@ -80,13 +101,35 @@ jobs: containers.bootc=1 ostree.bootable=1 + # ------------------------------------------------------------ + # Registry login + # ------------------------------------------------------------ + - name: Login to Gitea Container Registry if: github.event_name != 'pull_request' uses: docker/login-action@v4.6.0 with: registry: ${{ env.REGISTRY_HOST }} username: ${{ github.repository_owner }} - password: ${{ secrets.REGISTRY }} + password: ${{ secrets.REGISTRY }} + + # ------------------------------------------------------------ + # Prepare OCI archive destination + # ------------------------------------------------------------ + + - name: Prepare OCI archive + run: | + # Wichtig: + # Falls aus einem vorherigen Lauf / Schritt ein Verzeichnis + # namens oci-layout.tar existiert, muss es weg. + rm -rf "${{ github.workspace }}/oci-layout.tar" + + echo "OCI output path:" + echo "${{ github.workspace }}/oci-layout.tar" + + # ------------------------------------------------------------ + # Build + # ------------------------------------------------------------ - name: Build Image (Docker Buildx OCI-Export) uses: docker/build-push-action@v7.3.0 @@ -94,36 +137,92 @@ jobs: with: context: . file: ./Containerfile + push: false pull: true + tags: ${{ steps.metadata.outputs.tags }} labels: ${{ steps.metadata.outputs.labels }} + cache-from: type=registry,ref=${{ env.IMAGE_REGISTRY }}/${{ env.IMAGE_NAME }}:buildcache cache-to: type=registry,ref=${{ env.IMAGE_REGISTRY }}/${{ env.IMAGE_NAME }}:buildcache,mode=max - outputs: type=oci,dest=oci-layout.tar + # Explizit ein OCI-TAR-Archiv erzeugen. + # + # tar=true ist absichtlich explizit gesetzt. + outputs: type=oci,dest=${{ github.workspace }}/oci-layout.tar,tar=true + + # ------------------------------------------------------------ + # Verify OCI archive + # ------------------------------------------------------------ + + - name: Verify OCI archive + if: github.event_name != 'pull_request' + run: | + set -e + + OCI_ARCHIVE="${{ github.workspace }}/oci-layout.tar" + + echo "Checking OCI archive..." + + if [ ! -f "$OCI_ARCHIVE" ]; then + echo "ERROR: OCI archive is not a regular file!" + ls -lah "${{ github.workspace }}" + exit 1 + fi + + echo "OCI archive:" + ls -lh "$OCI_ARCHIVE" + + echo + echo "Archive contents:" + tar -tf "$OCI_ARCHIVE" | head -30 + + # ------------------------------------------------------------ + # Push using Skopeo + # ------------------------------------------------------------ - name: Push Image via Skopeo (zstd:chunked) if: github.event_name != 'pull_request' run: | + set -e + + OCI_ARCHIVE="${{ github.workspace }}/oci-layout.tar" TAGS="${{ steps.metadata.outputs.tags }}" - for TAG in $TAGS; do - echo "Pushe ${TAG} via Skopeo mit zstd:chunked..." + echo "OCI archive: ${OCI_ARCHIVE}" + echo + echo "Tags:" + echo "${TAGS}" + echo - docker run --rm \ - -v "${{ github.workspace }}/oci-layout.tar:/workspace/oci-layout.tar:ro" \ - quay.io/skopeo/stable copy \ - --dest-creds "${{ github.repository_owner }}:${{ secrets.REGISTRY }}" \ - --dest-compress-format zstd:chunked \ - oci-archive:/workspace/oci-layout.tar \ - "docker://${TAG}" + for TAG in $TAGS; do + echo "============================================================" + echo "Pushe ${TAG} via Skopeo mit zstd:chunked..." + echo "============================================================" + + docker run --rm \ + -v "${OCI_ARCHIVE}:/workspace/oci-layout.tar:ro" \ + quay.io/skopeo/stable copy \ + --dest-creds "${{ github.repository_owner }}:${{ secrets.REGISTRY }}" \ + --dest-compress-format zstd:chunked \ + oci-archive:/workspace/oci-layout.tar \ + "docker://${TAG}" done + # ------------------------------------------------------------ + # Install dependencies for signing + # ------------------------------------------------------------ + - name: Install envsubst dependencies if: github.event_name != 'pull_request' && env.IS_TEST_BUILD == 'false' run: | - sudo apt-get update && sudo apt-get install -y gettext + sudo apt-get update + sudo apt-get install -y gettext + + # ------------------------------------------------------------ + # Cosign + # ------------------------------------------------------------ - name: Install Cosign if: github.event_name != 'pull_request' && env.IS_TEST_BUILD == 'false' @@ -134,19 +233,36 @@ jobs: env: COSIGN_PRIVATE_KEY: ${{ secrets.SIGNING_SECRET }} COSIGN_PASSWORD: "" + run: | + set -e + # 1. Cosign an der Gitea-Registry anmelden - echo "${{ secrets.REGISTRY }}" | cosign login "${{ env.REGISTRY_HOST }}" -u "${{ github.repository_owner }}" --password-stdin - - # 2. Skopeo als Docker-Container ausführen, um den Digest zu holen - echo "Frage finalen Manifest-List-Digest via Skopeo-Container ab..." - OUTER_DIGEST=$(docker run --rm quay.io/skopeo/stable inspect --creds "${{ github.repository_owner }}:${{ secrets.REGISTRY }}" docker://${{ env.IMAGE_REGISTRY }}/${{ env.IMAGE_NAME }}:stable | jq -r .Digest) - - # 3. Die Referenz über den äußeren Digest bauen + echo "${{ secrets.REGISTRY }}" \ + | cosign login "${{ env.REGISTRY_HOST }}" \ + -u "${{ github.repository_owner }}" \ + --password-stdin + + # 2. Finalen Digest via Skopeo abfragen + echo "Frage finalen Registry-Digest via Skopeo ab..." + + OUTER_DIGEST=$( + docker run --rm \ + quay.io/skopeo/stable inspect \ + --creds "${{ github.repository_owner }}:${{ secrets.REGISTRY }}" \ + "docker://${{ env.IMAGE_REGISTRY }}/${{ env.IMAGE_NAME }}:stable" \ + | jq -r .Digest + ) + + echo "Registry digest: ${OUTER_DIGEST}" + + # 3. Digest-basierte Referenz bauen IMAGE_REF="${{ env.IMAGE_REGISTRY }}/${{ env.IMAGE_NAME }}@${OUTER_DIGEST}" - echo "Signiere Manifest-List und alle Sub-Architekturen rekursiv via Digest: ${IMAGE_REF}" - - # 4. Signatur rekursiv auf Gitea pushen (ohne deprecated tlog-Flag) + + echo "Signiere Image rekursiv:" + echo "${IMAGE_REF}" + + # 4. Rekursive Signatur cosign sign -y \ --key env://COSIGN_PRIVATE_KEY \ --recursive \ @@ -154,10 +270,16 @@ jobs: --new-bundle-format=false \ --registry-referrers-mode=legacy \ "${IMAGE_REF}" - + + # ------------------------------------------------------------ + # Cleanup + # ------------------------------------------------------------ + - name: Post-Build Cleanup if: always() run: | echo "Räume temporäre Dateien und Buildx-Cache auf..." - rm -f "${{ github.workspace }}/oci-layout.tar" + + rm -rf "${{ github.workspace }}/oci-layout.tar" + docker buildx prune -a -f || true \ No newline at end of file