Merge branch 'hotfix/ci' into renovate/development-weekly-non-major-updates
This commit is contained in:
78
.github/workflows/security-pr.yml
vendored
78
.github/workflows/security-pr.yml
vendored
@@ -8,6 +8,11 @@ on:
|
||||
workflows: ["Docker Build, Publish & Test"]
|
||||
types:
|
||||
- completed
|
||||
branches: [main, development, 'feature/**', 'hotfix/**']
|
||||
push:
|
||||
branches: [main, development, 'feature/**', 'hotfix/**']
|
||||
pull_request:
|
||||
branches: [main, development, 'feature/**', 'hotfix/**']
|
||||
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
@@ -17,7 +22,7 @@ on:
|
||||
type: string
|
||||
|
||||
concurrency:
|
||||
group: security-pr-${{ github.event.workflow_run.head_branch || github.ref }}
|
||||
group: security-pr-${{ github.event.workflow_run.event || github.event_name }}-${{ github.event.workflow_run.head_branch || github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
@@ -28,6 +33,8 @@ jobs:
|
||||
# Run for: manual dispatch, PR builds, or any push builds from docker-build
|
||||
if: >-
|
||||
github.event_name == 'workflow_dispatch' ||
|
||||
github.event_name == 'push' ||
|
||||
github.event_name == 'pull_request' ||
|
||||
((github.event.workflow_run.event == 'pull_request' || github.event.workflow_run.event == 'push') &&
|
||||
github.event.workflow_run.conclusion == 'success')
|
||||
|
||||
@@ -59,8 +66,8 @@ jobs:
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Extract PR number from workflow_run context
|
||||
HEAD_SHA="${{ github.event.workflow_run.head_sha }}"
|
||||
# Extract PR number from context
|
||||
HEAD_SHA="${{ github.event.workflow_run.head_sha || github.event.pull_request.head.sha || github.sha }}"
|
||||
echo "🔍 Looking for PR with head SHA: ${HEAD_SHA}"
|
||||
|
||||
# Query GitHub API for PR associated with this commit
|
||||
@@ -79,16 +86,24 @@ jobs:
|
||||
fi
|
||||
|
||||
# Check if this is a push event (not a PR)
|
||||
if [[ "${{ github.event.workflow_run.event }}" == "push" ]]; then
|
||||
if [[ "${{ github.event.workflow_run.event }}" == "push" || "${{ github.event_name }}" == "push" ]]; then
|
||||
HEAD_BRANCH="${{ github.event.workflow_run.head_branch || github.ref_name }}"
|
||||
echo "is_push=true" >> "$GITHUB_OUTPUT"
|
||||
echo "✅ Detected push build from branch: ${{ github.event.workflow_run.head_branch }}"
|
||||
echo "✅ Detected push build from branch: ${HEAD_BRANCH}"
|
||||
else
|
||||
echo "is_push=false" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
|
||||
- name: Build Docker image (Local)
|
||||
if: github.event_name == 'push' || github.event_name == 'pull_request'
|
||||
run: |
|
||||
echo "Building image locally for security scan..."
|
||||
docker build -t charon:local .
|
||||
echo "✅ Successfully built charon:local"
|
||||
|
||||
- name: Check for PR image artifact
|
||||
id: check-artifact
|
||||
if: steps.pr-info.outputs.pr_number != '' || steps.pr-info.outputs.is_push == 'true'
|
||||
if: (steps.pr-info.outputs.pr_number != '' || steps.pr-info.outputs.is_push == 'true') && github.event_name != 'push' && github.event_name != 'pull_request'
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
@@ -116,6 +131,21 @@ jobs:
|
||||
echo "artifact_exists=false" >> "$GITHUB_OUTPUT"
|
||||
exit 0
|
||||
fi
|
||||
elif [[ -z "${RUN_ID}" ]]; then
|
||||
# If triggered by push/pull_request, RUN_ID is empty. Find recent run for this commit.
|
||||
HEAD_SHA="${{ github.event.workflow_run.head_sha || github.event.pull_request.head.sha || github.sha }}"
|
||||
echo "🔍 Searching for workflow run for SHA: ${HEAD_SHA}"
|
||||
# Retry a few times as the run might be just starting or finishing
|
||||
for i in {1..3}; do
|
||||
RUN_ID=$(gh api \
|
||||
-H "Accept: application/vnd.github+json" \
|
||||
-H "X-GitHub-Api-Version: 2022-11-28" \
|
||||
"/repos/${{ github.repository }}/actions/workflows/docker-build.yml/runs?head_sha=${HEAD_SHA}&status=success&per_page=1" \
|
||||
--jq '.workflow_runs[0].id // empty' 2>/dev/null || echo "")
|
||||
if [[ -n "${RUN_ID}" ]]; then break; fi
|
||||
echo "⏳ Waiting for workflow run to appear/complete... ($i/3)"
|
||||
sleep 5
|
||||
done
|
||||
fi
|
||||
|
||||
echo "run_id=${RUN_ID}" >> "$GITHUB_OUTPUT"
|
||||
@@ -138,7 +168,7 @@ jobs:
|
||||
fi
|
||||
|
||||
- name: Skip if no artifact
|
||||
if: (steps.pr-info.outputs.pr_number == '' && steps.pr-info.outputs.is_push != 'true') || 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') && github.event_name != 'push' && github.event_name != 'pull_request'
|
||||
run: |
|
||||
echo "ℹ️ Skipping security scan - no PR image artifact available"
|
||||
echo "This is expected for:"
|
||||
@@ -165,9 +195,31 @@ jobs:
|
||||
docker images | grep charon
|
||||
|
||||
- name: Extract charon binary from container
|
||||
if: steps.check-artifact.outputs.artifact_exists == 'true'
|
||||
if: steps.check-artifact.outputs.artifact_exists == 'true' || github.event_name == 'push' || github.event_name == 'pull_request'
|
||||
id: extract
|
||||
run: |
|
||||
# Use local image for Push/PR events
|
||||
if [[ "${{ github.event_name }}" == "push" || "${{ github.event_name }}" == "pull_request" ]]; then
|
||||
echo "Using local image: charon:local"
|
||||
CONTAINER_ID=$(docker create "charon:local")
|
||||
echo "container_id=${CONTAINER_ID}" >> "$GITHUB_OUTPUT"
|
||||
|
||||
# Extract the charon binary
|
||||
mkdir -p ./scan-target
|
||||
docker cp "${CONTAINER_ID}:/app/charon" ./scan-target/charon
|
||||
docker rm "${CONTAINER_ID}"
|
||||
|
||||
if [[ -f "./scan-target/charon" ]]; then
|
||||
echo "✅ Binary extracted successfully"
|
||||
ls -lh ./scan-target/charon
|
||||
echo "binary_path=./scan-target" >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
echo "❌ Failed to extract binary"
|
||||
exit 1
|
||||
fi
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Normalize image name for reference
|
||||
IMAGE_NAME=$(echo "${{ github.repository_owner }}/charon" | tr '[:upper:]' '[:lower:]')
|
||||
if [[ "${{ steps.pr-info.outputs.is_push }}" == "true" ]]; then
|
||||
@@ -220,7 +272,7 @@ jobs:
|
||||
fi
|
||||
|
||||
- name: Run Trivy filesystem scan (SARIF output)
|
||||
if: steps.check-artifact.outputs.artifact_exists == 'true'
|
||||
if: steps.check-artifact.outputs.artifact_exists == 'true' || github.event_name == 'push' || github.event_name == 'pull_request'
|
||||
# aquasecurity/trivy-action v0.33.1
|
||||
uses: aquasecurity/trivy-action@22438a435773de8c97dc0958cc0b823c45b064ac
|
||||
with:
|
||||
@@ -232,7 +284,7 @@ jobs:
|
||||
continue-on-error: true
|
||||
|
||||
- name: Upload Trivy SARIF to GitHub Security
|
||||
if: steps.check-artifact.outputs.artifact_exists == 'true'
|
||||
if: steps.check-artifact.outputs.artifact_exists == 'true' || github.event_name == 'push' || github.event_name == 'pull_request'
|
||||
# github/codeql-action v4
|
||||
uses: github/codeql-action/upload-sarif@b13d724d35ff0a814e21683638ed68ed34cf53d1
|
||||
with:
|
||||
@@ -241,7 +293,7 @@ jobs:
|
||||
continue-on-error: true
|
||||
|
||||
- name: Run Trivy filesystem scan (fail on CRITICAL/HIGH)
|
||||
if: steps.check-artifact.outputs.artifact_exists == 'true'
|
||||
if: steps.check-artifact.outputs.artifact_exists == 'true' || github.event_name == 'push' || github.event_name == 'pull_request'
|
||||
# aquasecurity/trivy-action v0.33.1
|
||||
uses: aquasecurity/trivy-action@22438a435773de8c97dc0958cc0b823c45b064ac
|
||||
with:
|
||||
@@ -252,7 +304,7 @@ jobs:
|
||||
exit-code: '1'
|
||||
|
||||
- name: Upload scan artifacts
|
||||
if: always() && steps.check-artifact.outputs.artifact_exists == 'true'
|
||||
if: always() && (steps.check-artifact.outputs.artifact_exists == 'true' || github.event_name == 'push' || github.event_name == 'pull_request')
|
||||
# actions/upload-artifact v4.4.3
|
||||
uses: actions/upload-artifact@47309c993abb98030a35d55ef7ff34b7fa1074b5
|
||||
with:
|
||||
@@ -262,7 +314,7 @@ jobs:
|
||||
retention-days: 14
|
||||
|
||||
- name: Create job summary
|
||||
if: always() && steps.check-artifact.outputs.artifact_exists == 'true'
|
||||
if: always() && (steps.check-artifact.outputs.artifact_exists == 'true' || github.event_name == 'push' || github.event_name == 'pull_request')
|
||||
run: |
|
||||
if [[ "${{ steps.pr-info.outputs.is_push }}" == "true" ]]; then
|
||||
echo "## 🔒 Security Scan Results - Branch: ${{ github.event.workflow_run.head_branch }}" >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
Reference in New Issue
Block a user