diff --git a/.github/workflows/docker-build.yml b/.github/workflows/docker-build.yml index 33bc80b0..744f7c14 100644 --- a/.github/workflows/docker-build.yml +++ b/.github/workflows/docker-build.yml @@ -31,6 +31,10 @@ on: description: "Version to tag when tag_with_version=true" type: string required: false + experimental: + description: "Build experimental image (main branch excluded)" + type: boolean + default: false permissions: contents: read @@ -165,15 +169,18 @@ jobs: DIGEST_LIST="${DIGEST_LIST} ${IMAGE}@${digest}" done - # Create manifest for latest - docker buildx imagetools create -t "${IMAGE}:latest" ${DIGEST_LIST} - - # Create manifest for SHA - docker buildx imagetools create -t "${IMAGE}:${FULL_SHA}" ${DIGEST_LIST} - - # Create manifest for version if needed - if [ "${{ inputs.tag_with_version }}" = "true" ] && [ -n "${{ inputs.version }}" ]; then - docker buildx imagetools create -t "${IMAGE}:v${{ inputs.version }}" ${DIGEST_LIST} + if [ "${{ inputs.experimental }}" = "true" ]; then + # Experimental mode: only tag with commithash-experimental + docker buildx imagetools create -t "${IMAGE}:${FULL_SHA}-experimental" ${DIGEST_LIST} + else + # Standard mode: tag with latest and SHA + docker buildx imagetools create -t "${IMAGE}:latest" ${DIGEST_LIST} + docker buildx imagetools create -t "${IMAGE}:${FULL_SHA}" ${DIGEST_LIST} + + # Create manifest for version if needed + if [ "${{ inputs.tag_with_version }}" = "true" ] && [ -n "${{ inputs.version }}" ]; then + docker buildx imagetools create -t "${IMAGE}:v${{ inputs.version }}" ${DIGEST_LIST} + fi fi - name: Output Image Information @@ -181,12 +188,18 @@ jobs: IMAGE="${{ inputs.image }}" NAME="${IMAGE##*/}" FULL_SHA=$(git rev-parse HEAD) - TAGS="latest, ${FULL_SHA}" - if [ "${{ inputs.tag_with_version }}" = "true" ] && [ -n "${{ inputs.version }}" ]; then - TAGS="${TAGS}, v${{ inputs.version }}" + if [ "${{ inputs.experimental }}" = "true" ]; then + TAGS="${FULL_SHA}-experimental" + MODE="experimental" + else + TAGS="latest, ${FULL_SHA}" + MODE="standard" + if [ "${{ inputs.tag_with_version }}" = "true" ] && [ -n "${{ inputs.version }}" ]; then + TAGS="${TAGS}, v${{ inputs.version }}" + fi fi HUB_PATH=$(echo "${IMAGE}" | sed -E 's@^docker\.io/@@') - echo "✅ Successfully built and pushed ${NAME} multi-arch image" + echo "✅ Successfully built and pushed ${NAME} multi-arch image (${MODE} mode)" echo "🏷️ Tags: ${TAGS}" echo "🏗️ Platforms: linux/amd64, linux/arm64" echo "🔗 View at: https://hub.docker.com/r/${HUB_PATH}" diff --git a/.github/workflows/docker-ci.yml b/.github/workflows/docker-ci.yml index d40b4295..06ac871a 100644 --- a/.github/workflows/docker-ci.yml +++ b/.github/workflows/docker-ci.yml @@ -9,6 +9,11 @@ on: description: "Git ref to build (branch, tag, or SHA)" type: string required: false + experimental: + description: "Build experimental image (main branch excluded)" + type: boolean + required: false + default: false permissions: contents: read @@ -29,7 +34,7 @@ jobs: EVENT_NAME="${GITHUB_EVENT_NAME}" MERGE_SHA=$(jq -r '.pull_request.merge_commit_sha // empty' "$GITHUB_EVENT_PATH") INPUT_REF=$(jq -r '.inputs.ref // empty' "$GITHUB_EVENT_PATH") - + if [[ "$EVENT_NAME" == "pull_request" && -n "$MERGE_SHA" ]]; then REF="$MERGE_SHA" elif [[ -n "$INPUT_REF" ]]; then @@ -38,18 +43,59 @@ jobs: echo "Error: no merge commit or input ref provided" >&2 exit 1 fi - + echo "ref=$REF" >> "$GITHUB_OUTPUT" + validate-experimental: + name: Validate Experimental Build + needs: resolve-ref + runs-on: ubuntu-latest + if: github.event_name == 'workflow_dispatch' && inputs.experimental == true + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + ref: ${{ needs.resolve-ref.outputs.ref }} + fetch-depth: 0 + + - name: Check if building from main branch + run: | + set -euo pipefail + + # Get the current commit SHA + CURRENT_SHA=$(git rev-parse HEAD) + + # Get the main branch SHA + MAIN_SHA=$(git rev-parse origin/main) + + # Check if we're on main + if [[ "$CURRENT_SHA" == "$MAIN_SHA" ]]; then + echo "❌ Error: Cannot build experimental images from the main branch" + echo "Experimental images are meant for pre-merge testing only" + exit 1 + fi + + # Also check if the ref input was explicitly 'main' + INPUT_REF=$(jq -r '.inputs.ref // empty' "$GITHUB_EVENT_PATH") + if [[ "$INPUT_REF" == "main" ]]; then + echo "❌ Error: Cannot build experimental images from 'main' ref" + echo "Experimental images are meant for pre-merge testing only" + exit 1 + fi + + echo "✅ Validation passed: building experimental image from non-main branch" + build: name: Build and Push Images - needs: resolve-ref + needs: [resolve-ref, validate-experimental] # Run only when the PR is merged and is NOT a release PR, or manual run. if: | - github.event_name == 'workflow_dispatch' || ( - github.event_name == 'pull_request' && - github.event.pull_request.merged == true && - !contains(github.event.pull_request.labels.*.name, 'release') + (success() || needs.validate-experimental.result == 'skipped') && ( + github.event_name == 'workflow_dispatch' || ( + github.event_name == 'pull_request' && + github.event.pull_request.merged == true && + !contains(github.event.pull_request.labels.*.name, 'release') + ) ) strategy: matrix: @@ -62,5 +108,6 @@ jobs: file: ./${{ matrix.image }}/Dockerfile push: true tag_with_version: false + experimental: ${{ github.event_name == 'workflow_dispatch' && inputs.experimental || false }} # Build from the resolved ref: merge commit for PRs, or provided ref, fallback to current SHA. checkout_ref: ${{ needs.resolve-ref.outputs.ref }}