diff --git a/.github/workflows/cerberus-integration.yml b/.github/workflows/cerberus-integration.yml index 2d156a0c..5cb4ce24 100644 --- a/.github/workflows/cerberus-integration.yml +++ b/.github/workflows/cerberus-integration.yml @@ -32,67 +32,6 @@ jobs: steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 - # Determine the correct image tag based on trigger context - # For PRs: pr-{number}-{sha}, For branches: {sanitized-branch}-{sha} - - name: Determine image tag - id: image - env: - EVENT: ${{ github.event_name == 'pull_request' && 'pull_request' || github.event.workflow_run.event }} - REF: ${{ github.event_name == 'pull_request' && github.head_ref || github.event.workflow_run.head_branch }} - SHA: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.event.workflow_run.head_sha }} - MANUAL_TAG: ${{ inputs.image_tag }} - run: | - # Manual trigger uses provided tag - if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then - if [[ -n "$MANUAL_TAG" ]]; then - echo "tag=${MANUAL_TAG}" >> $GITHUB_OUTPUT - else - # Default to latest if no tag provided - echo "tag=latest" >> $GITHUB_OUTPUT - fi - echo "source_type=manual" >> $GITHUB_OUTPUT - exit 0 - fi - - # Extract 7-character short SHA - SHORT_SHA=$(echo "$SHA" | cut -c1-7) - - if [[ "$EVENT" == "pull_request" ]]; then - # Direct PR trigger uses github.event.pull_request.number - # workflow_run trigger uses pull_requests array - if [[ "${{ github.event_name }}" == "pull_request" ]]; then - PR_NUM="${{ github.event.pull_request.number }}" - else - PR_NUM=$(echo '${{ toJson(github.event.workflow_run.pull_requests) }}' | jq -r '.[0].number') - fi - - if [[ -z "$PR_NUM" || "$PR_NUM" == "null" ]]; then - echo "❌ ERROR: Could not determine PR number" - echo "Event: $EVENT" - echo "Ref: $REF" - echo "SHA: $SHA" - echo "Pull Requests JSON: ${{ toJson(github.event.workflow_run.pull_requests) }}" - exit 1 - fi - - # Immutable tag with SHA suffix prevents race conditions - echo "tag=pr-${PR_NUM}-${SHORT_SHA}" >> $GITHUB_OUTPUT - echo "source_type=pr" >> $GITHUB_OUTPUT - else - # Branch push: sanitize branch name and append SHA - # Sanitization: lowercase, replace / with -, remove special chars - SANITIZED=$(echo "$REF" | \ - tr '[:upper:]' '[:lower:]' | \ - tr '/' '-' | \ - sed 's/[^a-z0-9-._]/-/g' | \ - sed 's/^-//; s/-$//' | \ - sed 's/--*/-/g' | \ - cut -c1-121) # Leave room for -SHORT_SHA (7 chars) - - echo "tag=${SANITIZED}-${SHORT_SHA}" >> $GITHUB_OUTPUT - echo "source_type=branch" >> $GITHUB_OUTPUT - fi - # Determine the correct image tag based on trigger context # For PRs: pr-{number}-{sha}, For branches: {sanitized-branch}-{sha} - name: Determine image tag diff --git a/.github/workflows/crowdsec-integration.yml b/.github/workflows/crowdsec-integration.yml index 5f6b1d29..bc9ef2f4 100644 --- a/.github/workflows/crowdsec-integration.yml +++ b/.github/workflows/crowdsec-integration.yml @@ -11,11 +11,7 @@ on: workflow_dispatch: inputs: image_tag: -<<<<<<< HEAD - description: 'Docker image tag to test (e.g., pr-123-abc1234)' -======= description: 'Docker image tag to test (e.g., pr-123-abc1234, latest)' ->>>>>>> 8edde88f (fix(ci): add image_tag input for manual triggers in integration workflows) required: false type: string @@ -40,104 +36,6 @@ jobs: # For PRs: pr-{number}-{sha}, For branches: {sanitized-branch}-{sha} - name: Determine image tag id: image - env: - EVENT: ${{ github.event_name == 'pull_request' && 'pull_request' || github.event.workflow_run.event }} - REF: ${{ github.event_name == 'pull_request' && github.head_ref || github.event.workflow_run.head_branch }} - SHA: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.event.workflow_run.head_sha }} - MANUAL_TAG: ${{ inputs.image_tag }} - run: | - # Manual trigger uses provided tag - if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then - if [[ -n "$MANUAL_TAG" ]]; then - echo "tag=${MANUAL_TAG}" >> $GITHUB_OUTPUT - else - # Default to latest if no tag provided - echo "tag=latest" >> $GITHUB_OUTPUT - fi - echo "source_type=manual" >> $GITHUB_OUTPUT - exit 0 - fi - - # Extract 7-character short SHA - SHORT_SHA=$(echo "$SHA" | cut -c1-7) - - if [[ "$EVENT" == "pull_request" ]]; then - # Direct PR trigger uses github.event.pull_request.number - # workflow_run trigger uses pull_requests array - if [[ "${{ github.event_name }}" == "pull_request" ]]; then - PR_NUM="${{ github.event.pull_request.number }}" - else - PR_NUM=$(echo '${{ toJson(github.event.workflow_run.pull_requests) }}' | jq -r '.[0].number') - fi - - if [[ -z "$PR_NUM" || "$PR_NUM" == "null" ]]; then - echo "❌ ERROR: Could not determine PR number" - echo "Event: $EVENT" - echo "Ref: $REF" - echo "SHA: $SHA" - echo "Pull Requests JSON: ${{ toJson(github.event.workflow_run.pull_requests) }}" - exit 1 - fi - - # Immutable tag with SHA suffix prevents race conditions - echo "tag=pr-${PR_NUM}-${SHORT_SHA}" >> $GITHUB_OUTPUT - echo "source_type=pr" >> $GITHUB_OUTPUT - else - # Branch push: sanitize branch name and append SHA - # Sanitization: lowercase, replace / with -, remove special chars - SANITIZED=$(echo "$REF" | \ - tr '[:upper:]' '[:lower:]' | \ - tr '/' '-' | \ - sed 's/[^a-z0-9-._]/-/g' | \ - sed 's/^-//; s/-$//' | \ - sed 's/--*/-/g' | \ - cut -c1-121) # Leave room for -SHORT_SHA (7 chars) - - echo "tag=${SANITIZED}-${SHORT_SHA}" >> $GITHUB_OUTPUT - echo "source_type=branch" >> $GITHUB_OUTPUT - fi - - echo "sha=${SHORT_SHA}" >> $GITHUB_OUTPUT - echo "Determined image tag: $(cat $GITHUB_OUTPUT | grep tag=)" - - # Pull image from registry with retry logic (dual-source strategy) - # Try registry first (fast), fallback to artifact if registry fails - - name: Pull Docker image from registry - id: pull_image - uses: nick-fields/retry@ce71cc2ab81d554ebbe88c79ab5975992d79ba08 # v3 - with: - timeout_minutes: 5 - max_attempts: 3 - retry_wait_seconds: 10 - command: | - IMAGE_NAME="ghcr.io/${{ github.repository_owner }}/charon:${{ steps.image.outputs.tag }}" - echo "Pulling image: $IMAGE_NAME" - docker pull "$IMAGE_NAME" - docker tag "$IMAGE_NAME" charon:local - echo "✅ Successfully pulled from registry" - continue-on-error: true - - # Fallback: Download artifact if registry pull failed - - name: Fallback to artifact download - if: steps.pull_image.outcome == 'failure' - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - SHA: ${{ steps.image.outputs.sha }} - run: | - echo "⚠️ Registry pull failed, falling back to artifact..." - - # Determine artifact name based on source type - if [[ "${{ steps.image.outputs.source_type }}" == "pr" ]]; then - PR_NUM=$(echo '${{ toJson(github.event.workflow_run.pull_requests) }}' | jq -r '.[0].number') - ARTIFACT_NAME="pr-image-${PR_NUM}" - else - ARTIFACT_NAME="push-image" - fi - - # Determine the correct image tag based on trigger context - # For PRs: pr-{number}-{sha}, For branches: {sanitized-branch}-{sha} - - name: Determine image tag - id: determine-tag env: EVENT: ${{ github.event.workflow_run.event }} REF: ${{ github.event.workflow_run.head_branch }} @@ -203,7 +101,7 @@ jobs: max_attempts: 3 retry_wait_seconds: 10 command: | - IMAGE_NAME="ghcr.io/${{ github.repository_owner }}/charon:${{ steps.determine-tag.outputs.tag }}" + IMAGE_NAME="ghcr.io/${{ github.repository_owner }}/charon:${{ steps.image.outputs.tag }}" echo "Pulling image: $IMAGE_NAME" docker pull "$IMAGE_NAME" docker tag "$IMAGE_NAME" charon:local @@ -215,12 +113,12 @@ jobs: if: steps.pull_image.outcome == 'failure' env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - SHA: ${{ steps.determine-tag.outputs.sha }} + SHA: ${{ steps.image.outputs.sha }} run: | echo "⚠️ Registry pull failed, falling back to artifact..." # Determine artifact name based on source type - if [[ "${{ steps.determine-tag.outputs.source_type }}" == "pr" ]]; then + if [[ "${{ steps.image.outputs.source_type }}" == "pr" ]]; then PR_NUM=$(echo '${{ toJson(github.event.workflow_run.pull_requests) }}' | jq -r '.[0].number') ARTIFACT_NAME="pr-image-${PR_NUM}" else @@ -244,7 +142,7 @@ jobs: # Validate image freshness by checking SHA label - name: Validate image SHA env: - SHA: ${{ steps.determine-tag.outputs.sha }} + SHA: ${{ steps.image.outputs.sha }} run: | LABEL_SHA=$(docker inspect charon:local --format '{{index .Config.Labels "org.opencontainers.image.revision"}}' | cut -c1-7) echo "Expected SHA: $SHA" diff --git a/.github/workflows/e2e-tests.yml b/.github/workflows/e2e-tests.yml index 4961754a..12a13f67 100644 --- a/.github/workflows/e2e-tests.yml +++ b/.github/workflows/e2e-tests.yml @@ -41,7 +41,7 @@ on: workflow_dispatch: inputs: image_tag: - description: 'Docker image tag to test (e.g., pr-123-abc1234)' + description: 'Docker image tag to test (e.g., pr-123-abc1234, latest)' required: false type: string browser: @@ -74,11 +74,7 @@ env: # Prevent race conditions when PR is updated mid-test # Cancels old test runs when new build completes with different SHA concurrency: -<<<<<<< HEAD group: e2e-${{ github.workflow }}-${{ github.event.workflow_run.head_branch || github.ref }}-${{ github.event.workflow_run.head_sha || github.sha }} -======= - group: e2e-${{ github.workflow }}-${{ github.ref }} ->>>>>>> 8edde88f (fix(ci): add image_tag input for manual triggers in integration workflows) cancel-in-progress: true jobs: @@ -115,7 +111,7 @@ jobs: # Determine the correct image tag based on trigger context # For PRs: pr-{number}-{sha}, For branches: {sanitized-branch}-{sha} - name: Determine image tag - id: determine-tag + id: image env: EVENT: ${{ github.event.workflow_run.event }} REF: ${{ github.event.workflow_run.head_branch }} @@ -171,7 +167,6 @@ jobs: echo "sha=${SHORT_SHA}" >> $GITHUB_OUTPUT echo "Determined image tag: $(cat $GITHUB_OUTPUT | grep tag=)" -<<<<<<< HEAD # Pull image from registry with retry logic (dual-source strategy) # Try registry first (fast), fallback to artifact if registry fails - name: Pull Docker image from registry @@ -207,7 +202,7 @@ jobs: fi echo "Downloading artifact: $ARTIFACT_NAME" - gh run download ${{ github.event.workflow_run.id }} \ + gh run run download ${{ github.event.workflow_run.id }} \ --name "$ARTIFACT_NAME" \ --dir /tmp/docker-image || { echo "❌ ERROR: Artifact download failed!" @@ -237,14 +232,6 @@ jobs: else echo "✅ Image SHA matches expected commit" fi -======= - # Download Docker image artifact from build job - - name: Download Docker image - uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7 - with: - name: docker-image - path: . ->>>>>>> 8edde88f (fix(ci): add image_tag input for manual triggers in integration workflows) - name: Validate Emergency Token Configuration run: | diff --git a/.github/workflows/rate-limit-integration.yml b/.github/workflows/rate-limit-integration.yml index 1bcf7a1f..cfdb946d 100644 --- a/.github/workflows/rate-limit-integration.yml +++ b/.github/workflows/rate-limit-integration.yml @@ -11,11 +11,7 @@ on: workflow_dispatch: inputs: image_tag: -<<<<<<< HEAD - description: 'Docker image tag to test (e.g., pr-123-abc1234)' -======= description: 'Docker image tag to test (e.g., pr-123-abc1234, latest)' ->>>>>>> 8edde88f (fix(ci): add image_tag input for manual triggers in integration workflows) required: false type: string @@ -40,67 +36,6 @@ jobs: # For PRs: pr-{number}-{sha}, For branches: {sanitized-branch}-{sha} - name: Determine image tag id: image - env: - EVENT: ${{ github.event_name == 'pull_request' && 'pull_request' || github.event.workflow_run.event }} - REF: ${{ github.event_name == 'pull_request' && github.head_ref || github.event.workflow_run.head_branch }} - SHA: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.event.workflow_run.head_sha }} - MANUAL_TAG: ${{ inputs.image_tag }} - run: | - # Manual trigger uses provided tag - if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then - if [[ -n "$MANUAL_TAG" ]]; then - echo "tag=${MANUAL_TAG}" >> $GITHUB_OUTPUT - else - # Default to latest if no tag provided - echo "tag=latest" >> $GITHUB_OUTPUT - fi - echo "source_type=manual" >> $GITHUB_OUTPUT - exit 0 - fi - - # Extract 7-character short SHA - SHORT_SHA=$(echo "$SHA" | cut -c1-7) - - if [[ "$EVENT" == "pull_request" ]]; then - # Direct PR trigger uses github.event.pull_request.number - # workflow_run trigger uses pull_requests array - if [[ "${{ github.event_name }}" == "pull_request" ]]; then - PR_NUM="${{ github.event.pull_request.number }}" - else - PR_NUM=$(echo '${{ toJson(github.event.workflow_run.pull_requests) }}' | jq -r '.[0].number') - fi - - if [[ -z "$PR_NUM" || "$PR_NUM" == "null" ]]; then - echo "❌ ERROR: Could not determine PR number" - echo "Event: $EVENT" - echo "Ref: $REF" - echo "SHA: $SHA" - echo "Pull Requests JSON: ${{ toJson(github.event.workflow_run.pull_requests) }}" - exit 1 - fi - - # Immutable tag with SHA suffix prevents race conditions - echo "tag=pr-${PR_NUM}-${SHORT_SHA}" >> $GITHUB_OUTPUT - echo "source_type=pr" >> $GITHUB_OUTPUT - else - # Branch push: sanitize branch name and append SHA - # Sanitization: lowercase, replace / with -, remove special chars - SANITIZED=$(echo "$REF" | \ - tr '[:upper:]' '[:lower:]' | \ - tr '/' '-' | \ - sed 's/[^a-z0-9-._]/-/g' | \ - sed 's/^-//; s/-$//' | \ - sed 's/--*/-/g' | \ - cut -c1-121) # Leave room for -SHORT_SHA (7 chars) - - echo "tag=${SANITIZED}-${SHORT_SHA}" >> $GITHUB_OUTPUT - echo "source_type=branch" >> $GITHUB_OUTPUT - fi - - # Determine the correct image tag based on trigger context - # For PRs: pr-{number}-{sha}, For branches: {sanitized-branch}-{sha} - - name: Determine image tag - id: determine-tag env: EVENT: ${{ github.event.workflow_run.event }} REF: ${{ github.event.workflow_run.head_branch }} @@ -166,7 +101,7 @@ jobs: max_attempts: 3 retry_wait_seconds: 10 command: | - IMAGE_NAME="ghcr.io/${{ github.repository_owner }}/charon:${{ steps.determine-tag.outputs.tag }}" + IMAGE_NAME="ghcr.io/${{ github.repository_owner }}/charon:${{ steps.image.outputs.tag }}" echo "Pulling image: $IMAGE_NAME" docker pull "$IMAGE_NAME" docker tag "$IMAGE_NAME" charon:local @@ -178,12 +113,12 @@ jobs: if: steps.pull_image.outcome == 'failure' env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - SHA: ${{ steps.determine-tag.outputs.sha }} + SHA: ${{ steps.image.outputs.sha }} run: | echo "⚠️ Registry pull failed, falling back to artifact..." # Determine artifact name based on source type - if [[ "${{ steps.determine-tag.outputs.source_type }}" == "pr" ]]; then + if [[ "${{ steps.image.outputs.source_type }}" == "pr" ]]; then PR_NUM=$(echo '${{ toJson(github.event.workflow_run.pull_requests) }}' | jq -r '.[0].number') ARTIFACT_NAME="pr-image-${PR_NUM}" else @@ -207,7 +142,7 @@ jobs: # Validate image freshness by checking SHA label - name: Validate image SHA env: - SHA: ${{ steps.determine-tag.outputs.sha }} + SHA: ${{ steps.image.outputs.sha }} run: | LABEL_SHA=$(docker inspect charon:local --format '{{index .Config.Labels "org.opencontainers.image.revision"}}' | cut -c1-7) echo "Expected SHA: $SHA" diff --git a/.github/workflows/waf-integration.yml b/.github/workflows/waf-integration.yml index e7ecbd59..1c1fe38d 100644 --- a/.github/workflows/waf-integration.yml +++ b/.github/workflows/waf-integration.yml @@ -11,11 +11,7 @@ on: workflow_dispatch: inputs: image_tag: -<<<<<<< HEAD - description: 'Docker image tag to test (e.g., pr-123-abc1234)' -======= description: 'Docker image tag to test (e.g., pr-123-abc1234, latest)' ->>>>>>> 8edde88f (fix(ci): add image_tag input for manual triggers in integration workflows) required: false type: string @@ -40,67 +36,6 @@ jobs: # For PRs: pr-{number}-{sha}, For branches: {sanitized-branch}-{sha} - name: Determine image tag id: image - env: - EVENT: ${{ github.event_name == 'pull_request' && 'pull_request' || github.event.workflow_run.event }} - REF: ${{ github.event_name == 'pull_request' && github.head_ref || github.event.workflow_run.head_branch }} - SHA: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.event.workflow_run.head_sha }} - MANUAL_TAG: ${{ inputs.image_tag }} - run: | - # Manual trigger uses provided tag - if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then - if [[ -n "$MANUAL_TAG" ]]; then - echo "tag=${MANUAL_TAG}" >> $GITHUB_OUTPUT - else - # Default to latest if no tag provided - echo "tag=latest" >> $GITHUB_OUTPUT - fi - echo "source_type=manual" >> $GITHUB_OUTPUT - exit 0 - fi - - # Extract 7-character short SHA - SHORT_SHA=$(echo "$SHA" | cut -c1-7) - - if [[ "$EVENT" == "pull_request" ]]; then - # Direct PR trigger uses github.event.pull_request.number - # workflow_run trigger uses pull_requests array - if [[ "${{ github.event_name }}" == "pull_request" ]]; then - PR_NUM="${{ github.event.pull_request.number }}" - else - PR_NUM=$(echo '${{ toJson(github.event.workflow_run.pull_requests) }}' | jq -r '.[0].number') - fi - - if [[ -z "$PR_NUM" || "$PR_NUM" == "null" ]]; then - echo "❌ ERROR: Could not determine PR number" - echo "Event: $EVENT" - echo "Ref: $REF" - echo "SHA: $SHA" - echo "Pull Requests JSON: ${{ toJson(github.event.workflow_run.pull_requests) }}" - exit 1 - fi - - # Immutable tag with SHA suffix prevents race conditions - echo "tag=pr-${PR_NUM}-${SHORT_SHA}" >> $GITHUB_OUTPUT - echo "source_type=pr" >> $GITHUB_OUTPUT - else - # Branch push: sanitize branch name and append SHA - # Sanitization: lowercase, replace / with -, remove special chars - SANITIZED=$(echo "$REF" | \ - tr '[:upper:]' '[:lower:]' | \ - tr '/' '-' | \ - sed 's/[^a-z0-9-._]/-/g' | \ - sed 's/^-//; s/-$//' | \ - sed 's/--*/-/g' | \ - cut -c1-121) # Leave room for -SHORT_SHA (7 chars) - - echo "tag=${SANITIZED}-${SHORT_SHA}" >> $GITHUB_OUTPUT - echo "source_type=branch" >> $GITHUB_OUTPUT - fi - - # Determine the correct image tag based on trigger context - # For PRs: pr-{number}-{sha}, For branches: {sanitized-branch}-{sha} - - name: Determine image tag - id: determine-tag env: EVENT: ${{ github.event.workflow_run.event }} REF: ${{ github.event.workflow_run.head_branch }} @@ -166,7 +101,7 @@ jobs: max_attempts: 3 retry_wait_seconds: 10 command: | - IMAGE_NAME="ghcr.io/${{ github.repository_owner }}/charon:${{ steps.determine-tag.outputs.tag }}" + IMAGE_NAME="ghcr.io/${{ github.repository_owner }}/charon:${{ steps.image.outputs.tag }}" echo "Pulling image: $IMAGE_NAME" docker pull "$IMAGE_NAME" docker tag "$IMAGE_NAME" charon:local @@ -178,12 +113,12 @@ jobs: if: steps.pull_image.outcome == 'failure' env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - SHA: ${{ steps.determine-tag.outputs.sha }} + SHA: ${{ steps.image.outputs.sha }} run: | echo "⚠️ Registry pull failed, falling back to artifact..." # Determine artifact name based on source type - if [[ "${{ steps.determine-tag.outputs.source_type }}" == "pr" ]]; then + if [[ "${{ steps.image.outputs.source_type }}" == "pr" ]]; then PR_NUM=$(echo '${{ toJson(github.event.workflow_run.pull_requests) }}' | jq -r '.[0].number') ARTIFACT_NAME="pr-image-${PR_NUM}" else @@ -207,7 +142,7 @@ jobs: # Validate image freshness by checking SHA label - name: Validate image SHA env: - SHA: ${{ steps.determine-tag.outputs.sha }} + SHA: ${{ steps.image.outputs.sha }} run: | LABEL_SHA=$(docker inspect charon:local --format '{{index .Config.Labels "org.opencontainers.image.revision"}}' | cut -c1-7) echo "Expected SHA: $SHA" diff --git a/docs/plans/rebase_resolution.md b/docs/plans/rebase_resolution.md new file mode 100644 index 00000000..73d1b400 --- /dev/null +++ b/docs/plans/rebase_resolution.md @@ -0,0 +1,53 @@ +# Rebase Resolution Plan + +## Overview +We are resolving conflicts in 4 workflow files during an interactive rebase. The conflicts primarily involve: +1. Updates to `workflow_dispatch` inputs (adding `latest` to description) from the rebase target. +2. Regression/simplification of `concurrency` groups in `e2e-tests.yml` (we must keep our robust HEAD version). +3. A massive duplication of logic ("Determine tag" -> "Pull image") in integration workflows caused by git auto-merge. +4. A conflict between "Pull from Registry" (HEAD) vs "Download Artifact" (Incoming) in `e2e-tests.yml` (we must keep Registry pull). + +## File-by-File Instructions + +### 1. `.github/workflows/crowdsec-integration.yml` + +* **Conflict Area 1 (Inputs)**: + * **Resolution**: Accept the *Incoming* change for the description (includes `latest`). + * **Action**: Update description to `'Docker image tag to test (e.g., pr-123-abc1234, latest)'`. +* **Duplication Fix (CRITICAL)**: + * **Issue**: The steps "Determine image tag", "Pull Docker image from registry", and "Fallback to artifact download" appear TWICE sequentially. + * **Resolution**: Delete the **FIRST** occurrence of this block. Keep the sequence that leads directly into "Validate image SHA". + * **Block to Delete**: Approximately lines 26-124. + +### 2. `.github/workflows/e2e-tests.yml` + +* **Inputs Issue (No marker, but duplicated)**: + * **Issue**: `image_tag` input appears twice in `workflow_dispatch`. + * **Resolution**: Keep the second one (with `latest` in description) and delete the first one. +* **Conflict Area 2 (Concurrency)**: + * **Resolution**: Keep **HEAD**. It contains the robust concurrency group key (`e2e-${{ github.workflow }}-${{ ... }}`) whereas the incoming change reverts to a simpler, less safe one. +* **Conflict Area 3 (Pull vs Download)**: + * **Issue**: HEAD uses "Pull Docker image from registry" (Phase 4 strategy). Incoming uses "Download Docker image" (old strategy). + * **Resolution**: Keep **HEAD**. + +### 3. `.github/workflows/rate-limit-integration.yml` + +* **Conflict Area 1 (Inputs)**: + * **Resolution**: Accept *Incoming* (with `latest`). +* **Duplication Fix**: + * **Issue**: Same as CrowdSec. Duplicate logic block. + * **Resolution**: Delete the **FIRST** occurrence of the [Determine -> Pull -> Fallback] sequence. + +### 4. `.github/workflows/waf-integration.yml` + +* **Conflict Area 1 (Inputs)**: + * **Resolution**: Accept *Incoming* (with `latest`). +* **Duplication Fix**: + * **Issue**: Same as CrowdSec. Duplicate logic block. + * **Resolution**: Delete the **FIRST** occurrence of the [Determine -> Pull -> Fallback] sequence. + +## Verification +After applying these fixes, we will verify: +1. No conflict markers (`<<<<<<<`, `=======`, `>>>>>>>`) remain. +2. No duplicate steps in the flows. +3. `e2e-tests.yml` specifically retains "Pull Docker image from registry".