fix(ci): enable workflow_run triggers for all push branches

Update branch triggers and downstream workflow logic to support all
branches defined in docker-build.yml (main, development, feature/**).

Changes:

docker-build.yml: Expand branch glob to feature/**, use branch-based tags
playwright.yml: Replace is_beta_push with generic is_push detection
security-pr.yml: Same branch-agnostic pattern
supply-chain-pr.yml: Same pattern, skip PR comments for push events
The workflows now support any push that triggers docker-build:

main branch → tag: latest
development branch → tag: dev
feature/* branches → tag: {branch-name}
Pull requests → tag: pr-{number}
Dynamic artifact naming:

Push events: push-image (shared across all branches)
Pull requests: pr-image-{number}
This ensures CI/CD pipelines work for stable releases, bug fixes,
and new feature development without hardcoded branch names.
This commit is contained in:
GitHub Actions
2026-01-15 16:07:40 +00:00
parent 3590553519
commit 07796bf610
4 changed files with 98 additions and 40 deletions

View File

@@ -12,13 +12,13 @@ on:
branches:
- main
- development
- feature/beta-release
- 'feature/**'
# Note: Tags are handled by release-goreleaser.yml to avoid duplicate builds
pull_request:
branches:
- main
- development
- feature/beta-release
- 'feature/**'
workflow_dispatch:
workflow_call:
@@ -74,12 +74,12 @@ jobs:
if echo "$HEAD_MSG" | grep -Ei '^chore:' >/dev/null 2>&1; then should_skip=true; fi
if echo "$pr_title" | grep -Ei '^chore\(deps' >/dev/null 2>&1; then should_skip=true; fi
if echo "$pr_title" | grep -Ei '^chore:' >/dev/null 2>&1; then should_skip=true; fi
# Always build on beta-release branch to ensure artifacts for testing
# Always build on feature branches to ensure artifacts for testing
# For PRs: github.ref is refs/pull/N/merge, so check github.head_ref instead
# For pushes: github.ref is refs/heads/branch-name
if [[ "$REF" == "refs/heads/feature/beta-release" ]] || [[ "$HEAD_REF" == "feature/beta-release" ]]; then
if [[ "$REF" == refs/heads/feature/* ]] || [[ "$HEAD_REF" == feature/* ]]; then
should_skip=false
echo "Force building on beta-release branch"
echo "Force building on feature branch"
fi
echo "skip_build=$should_skip" >> $GITHUB_OUTPUT
@@ -115,7 +115,7 @@ jobs:
tags: |
type=raw,value=latest,enable={{is_default_branch}}
type=raw,value=dev,enable=${{ github.ref == 'refs/heads/development' }}
type=raw,value=beta,enable=${{ github.ref == 'refs/heads/feature/beta-release' }}
type=ref,event=branch,enable=${{ startsWith(github.ref, 'refs/heads/feature/') }}
type=raw,value=pr-${{ github.event.pull_request.number }},enable=${{ github.event_name == 'pull_request' }}
type=sha,format=short,enable=${{ github.event_name != 'pull_request' }}
- name: Build and push Docker image
@@ -153,7 +153,7 @@ jobs:
# 2. Image doesn't exist locally after build
# 3. Artifact creation fails
- name: Save Docker Image as Artifact
if: github.event_name == 'pull_request'
if: github.event_name == 'pull_request' || github.event_name == 'push'
run: |
# Extract the first tag from metadata action (PR tag)
IMAGE_TAG=$(echo "${{ steps.meta.outputs.tags }}" | head -n 1)
@@ -184,10 +184,10 @@ jobs:
ls -lh /tmp/charon-pr-image.tar
- name: Upload Image Artifact
if: github.event_name == 'pull_request'
if: github.event_name == 'pull_request' || github.event_name == 'push'
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with:
name: pr-image-${{ github.event.pull_request.number }}
name: ${{ github.event_name == 'pull_request' && format('pr-image-{0}', github.event.pull_request.number) || 'push-image' }}
path: /tmp/charon-pr-image.tar
retention-days: 1 # Only needed for workflow duration

View File

@@ -24,10 +24,11 @@ jobs:
name: E2E Tests
runs-on: ubuntu-latest
timeout-minutes: 20
# Only run for PRs or manual dispatch
# Run for: manual dispatch, PR builds, or any push builds from docker-build
if: >-
github.event_name == 'workflow_dispatch' ||
(github.event.workflow_run.event == 'pull_request' && github.event.workflow_run.conclusion == 'success')
((github.event.workflow_run.event == 'pull_request' || github.event.workflow_run.event == 'push') &&
github.event.workflow_run.conclusion == 'success')
env:
CHARON_ENV: development
@@ -75,14 +76,27 @@ jobs:
echo "pr_number=" >> "$GITHUB_OUTPUT"
fi
# Check if this is a push event (not a PR)
if [[ "${{ github.event.workflow_run.event }}" == "push" ]]; then
echo "is_push=true" >> "$GITHUB_OUTPUT"
echo "✅ Detected push build from branch: ${{ github.event.workflow_run.head_branch }}"
else
echo "is_push=false" >> "$GITHUB_OUTPUT"
fi
- name: Check for PR image artifact
id: check-artifact
if: steps.pr-info.outputs.pr_number != ''
if: steps.pr-info.outputs.pr_number != '' || steps.pr-info.outputs.is_push == 'true'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
PR_NUMBER="${{ steps.pr-info.outputs.pr_number }}"
ARTIFACT_NAME="pr-image-${PR_NUMBER}"
# Determine artifact name based on event type
if [[ "${{ steps.pr-info.outputs.is_push }}" == "true" ]]; then
ARTIFACT_NAME="push-image"
else
PR_NUMBER="${{ steps.pr-info.outputs.pr_number }}"
ARTIFACT_NAME="pr-image-${PR_NUMBER}"
fi
RUN_ID="${{ github.event.workflow_run.id }}"
echo "🔍 Checking for artifact: ${ARTIFACT_NAME}"
@@ -122,7 +136,7 @@ jobs:
fi
- name: Skip if no artifact
if: steps.pr-info.outputs.pr_number == '' || steps.check-artifact.outputs.artifact_exists != 'true'
if: (steps.pr-info.outputs.pr_number == '' && steps.pr-info.outputs.is_push != 'true') || steps.check-artifact.outputs.artifact_exists != 'true'
run: |
echo " Skipping Playwright tests - no PR image artifact available"
echo "This is expected for:"
@@ -136,7 +150,7 @@ jobs:
# actions/download-artifact v4.1.8
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16
with:
name: pr-image-${{ steps.pr-info.outputs.pr_number }}
name: ${{ steps.pr-info.outputs.is_push == 'true' && 'push-image' || format('pr-image-{0}', steps.pr-info.outputs.pr_number) }}
run-id: ${{ steps.check-artifact.outputs.run_id }}
github-token: ${{ secrets.GITHUB_TOKEN }}
@@ -152,13 +166,23 @@ jobs:
if: steps.check-artifact.outputs.artifact_exists == 'true'
run: |
echo "🚀 Starting Charon container..."
# Normalize image name (GitHub lowercases repository owner names in GHCR)
IMAGE_NAME=$(echo "${{ github.repository_owner }}/charon" | tr '[:upper:]' '[:lower:]')
if [[ "${{ steps.pr-info.outputs.is_push }}" == "true" ]]; then
IMAGE_REF="ghcr.io/${IMAGE_NAME}:${{ github.event.workflow_run.head_branch }}"
else
IMAGE_REF="ghcr.io/${IMAGE_NAME}:pr-${{ steps.pr-info.outputs.pr_number }}"
fi
echo "📦 Starting container with image: ${IMAGE_REF}"
docker run -d \
--name charon-test \
-p 8080:8080 \
-e CHARON_ENV="${CHARON_ENV}" \
-e CHARON_DEBUG="${CHARON_DEBUG}" \
-e CHARON_ENCRYPTION_KEY="${CHARON_ENCRYPTION_KEY}" \
charon:pr-${{ steps.pr-info.outputs.pr_number }}
"${IMAGE_REF}"
echo "✅ Container started"
@@ -213,7 +237,7 @@ jobs:
# actions/upload-artifact v4.4.3
uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882
with:
name: playwright-report-pr-${{ steps.pr-info.outputs.pr_number }}
name: ${{ steps.pr-info.outputs.is_push == 'true' && format('playwright-report-{0}', github.event.workflow_run.head_branch) || format('playwright-report-pr-{0}', steps.pr-info.outputs.pr_number) }}
path: playwright-report/
retention-days: 14

View File

@@ -25,10 +25,11 @@ jobs:
name: Trivy Binary Scan
runs-on: ubuntu-latest
timeout-minutes: 10
# Only run for PRs or manual dispatch
# Run for: manual dispatch, PR builds, or any push builds from docker-build
if: >-
github.event_name == 'workflow_dispatch' ||
(github.event.workflow_run.event == 'pull_request' && github.event.workflow_run.conclusion == 'success')
((github.event.workflow_run.event == 'pull_request' || github.event.workflow_run.event == 'push') &&
github.event.workflow_run.conclusion == 'success')
permissions:
contents: read
@@ -77,14 +78,27 @@ jobs:
echo "pr_number=" >> "$GITHUB_OUTPUT"
fi
# Check if this is a push event (not a PR)
if [[ "${{ github.event.workflow_run.event }}" == "push" ]]; then
echo "is_push=true" >> "$GITHUB_OUTPUT"
echo "✅ Detected push build from branch: ${{ github.event.workflow_run.head_branch }}"
else
echo "is_push=false" >> "$GITHUB_OUTPUT"
fi
- name: Check for PR image artifact
id: check-artifact
if: steps.pr-info.outputs.pr_number != ''
if: steps.pr-info.outputs.pr_number != '' || steps.pr-info.outputs.is_push == 'true'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
PR_NUMBER="${{ steps.pr-info.outputs.pr_number }}"
ARTIFACT_NAME="pr-image-${PR_NUMBER}"
# Determine artifact name based on event type
if [[ "${{ steps.pr-info.outputs.is_push }}" == "true" ]]; then
ARTIFACT_NAME="push-image"
else
PR_NUMBER="${{ steps.pr-info.outputs.pr_number }}"
ARTIFACT_NAME="pr-image-${PR_NUMBER}"
fi
RUN_ID="${{ github.event.workflow_run.id }}"
echo "🔍 Checking for artifact: ${ARTIFACT_NAME}"
@@ -124,7 +138,7 @@ jobs:
fi
- name: Skip if no artifact
if: steps.pr-info.outputs.pr_number == '' || steps.check-artifact.outputs.artifact_exists != 'true'
if: (steps.pr-info.outputs.pr_number == '' && steps.pr-info.outputs.is_push != 'true') || steps.check-artifact.outputs.artifact_exists != 'true'
run: |
echo " Skipping security scan - no PR image artifact available"
echo "This is expected for:"
@@ -138,7 +152,7 @@ jobs:
# actions/download-artifact v4.1.8
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16
with:
name: pr-image-${{ steps.pr-info.outputs.pr_number }}
name: ${{ steps.pr-info.outputs.is_push == 'true' && 'push-image' || format('pr-image-{0}', steps.pr-info.outputs.pr_number) }}
run-id: ${{ steps.check-artifact.outputs.run_id }}
github-token: ${{ secrets.GITHUB_TOKEN }}
@@ -156,7 +170,11 @@ jobs:
run: |
# Normalize image name for reference
IMAGE_NAME=$(echo "${{ github.repository_owner }}/charon" | tr '[:upper:]' '[:lower:]')
IMAGE_REF="ghcr.io/${IMAGE_NAME}:pr-${{ steps.pr-info.outputs.pr_number }}"
if [[ "${{ steps.pr-info.outputs.is_push }}" == "true" ]]; then
IMAGE_REF="ghcr.io/${IMAGE_NAME}:${{ github.event.workflow_run.head_branch }}"
else
IMAGE_REF="ghcr.io/${IMAGE_NAME}:pr-${{ steps.pr-info.outputs.pr_number }}"
fi
echo "🔍 Extracting binary from: ${IMAGE_REF}"
@@ -199,7 +217,7 @@ jobs:
uses: github/codeql-action/upload-sarif@cdefb33c0f6224e58673d9004f47f7cb3e328b89
with:
sarif_file: 'trivy-binary-results.sarif'
category: security-scan-pr-${{ steps.pr-info.outputs.pr_number }}
category: ${{ steps.pr-info.outputs.is_push == 'true' && format('security-scan-{0}', github.event.workflow_run.head_branch) || format('security-scan-pr-{0}', steps.pr-info.outputs.pr_number) }}
continue-on-error: true
- name: Run Trivy filesystem scan (fail on CRITICAL/HIGH)
@@ -218,7 +236,7 @@ jobs:
# actions/upload-artifact v4.4.3
uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882
with:
name: security-scan-pr-${{ steps.pr-info.outputs.pr_number }}
name: ${{ steps.pr-info.outputs.is_push == 'true' && format('security-scan-{0}', github.event.workflow_run.head_branch) || format('security-scan-pr-{0}', steps.pr-info.outputs.pr_number) }}
path: |
trivy-binary-results.sarif
retention-days: 14
@@ -226,7 +244,11 @@ jobs:
- name: Create job summary
if: always() && steps.check-artifact.outputs.artifact_exists == 'true'
run: |
echo "## 🔒 Security Scan Results - PR #${{ steps.pr-info.outputs.pr_number }}" >> $GITHUB_STEP_SUMMARY
if [[ "${{ steps.pr-info.outputs.is_push }}" == "true" ]]; then
echo "## 🔒 Security Scan Results - Branch: ${{ github.event.workflow_run.head_branch }}" >> $GITHUB_STEP_SUMMARY
else
echo "## 🔒 Security Scan Results - PR #${{ steps.pr-info.outputs.pr_number }}" >> $GITHUB_STEP_SUMMARY
fi
echo "" >> $GITHUB_STEP_SUMMARY
echo "**Scan Type**: Trivy Filesystem Scan" >> $GITHUB_STEP_SUMMARY
echo "**Target**: \`/app/charon\` binary" >> $GITHUB_STEP_SUMMARY

View File

@@ -34,10 +34,10 @@ jobs:
name: Verify Supply Chain
runs-on: ubuntu-latest
timeout-minutes: 15
# Only run for PRs (workflow_run from PR or manual dispatch with PR number)
# Run for: manual dispatch, PR builds, or any push builds from docker-build
if: >
github.event_name == 'workflow_dispatch' ||
(github.event.workflow_run.event == 'pull_request' &&
((github.event.workflow_run.event == 'pull_request' || github.event.workflow_run.event == 'push') &&
github.event.workflow_run.conclusion == 'success')
steps:
@@ -92,20 +92,32 @@ jobs:
if [[ -z "${PR_NUMBER}" ]]; then
echo "⚠️ Could not find PR number for this workflow run"
echo "pr_number=" >> "$GITHUB_OUTPUT"
exit 0
else
echo "pr_number=${PR_NUMBER}" >> "$GITHUB_OUTPUT"
echo "✅ Found PR number: ${PR_NUMBER}"
fi
echo "pr_number=${PR_NUMBER}" >> "$GITHUB_OUTPUT"
echo "✅ Found PR number: ${PR_NUMBER}"
# Check if this is a push event (not a PR)
if [[ "${{ github.event.workflow_run.event }}" == "push" ]]; then
echo "is_push=true" >> "$GITHUB_OUTPUT"
echo "✅ Detected push build from branch: ${{ github.event.workflow_run.head_branch }}"
else
echo "is_push=false" >> "$GITHUB_OUTPUT"
fi
- name: Check for PR image artifact
id: check-artifact
if: steps.pr-number.outputs.pr_number != ''
if: steps.pr-number.outputs.pr_number != '' || steps.pr-number.outputs.is_push == 'true'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
PR_NUMBER="${{ steps.pr-number.outputs.pr_number }}"
ARTIFACT_NAME="pr-image-${PR_NUMBER}"
# Determine artifact name based on event type
if [[ "${{ steps.pr-number.outputs.is_push }}" == "true" ]]; then
ARTIFACT_NAME="push-image"
else
PR_NUMBER="${{ steps.pr-number.outputs.pr_number }}"
ARTIFACT_NAME="pr-image-${PR_NUMBER}"
fi
RUN_ID="${{ github.event.workflow_run.id }}"
echo "🔍 Looking for artifact: ${ARTIFACT_NAME}"
@@ -140,7 +152,7 @@ jobs:
echo "✅ Found artifact: ${ARTIFACT_NAME} (ID: ${ARTIFACT_ID})"
- name: Skip if no artifact
if: steps.check-artifact.outputs.artifact_found != 'true'
if: (steps.pr-number.outputs.pr_number == '' && steps.pr-number.outputs.is_push != 'true') || steps.check-artifact.outputs.artifact_found != 'true'
run: |
echo " No PR image artifact found - skipping supply chain verification"
echo "This is expected if the Docker build did not produce an artifact for this PR"
@@ -285,14 +297,14 @@ jobs:
# actions/upload-artifact v4.6.0
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08
with:
name: supply-chain-pr-${{ steps.pr-number.outputs.pr_number }}
name: ${{ steps.pr-number.outputs.is_push == 'true' && format('supply-chain-{0}', github.event.workflow_run.head_branch) || format('supply-chain-pr-{0}', steps.pr-number.outputs.pr_number) }}
path: |
sbom.cyclonedx.json
grype-results.json
retention-days: 14
- name: Comment on PR
if: steps.check-artifact.outputs.artifact_found == 'true'
if: steps.check-artifact.outputs.artifact_found == 'true' && steps.pr-number.outputs.is_push != 'true'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |