diff --git a/.github/.env.base b/.github/.env.base
index a0dc290..69fc575 100644
--- a/.github/.env.base
+++ b/.github/.env.base
@@ -39,7 +39,7 @@ GO_SECONDARY_VERSION=1.24.x
# Govulncheck-specific Go version for vulnerability scanning
# Uses newer Go version for accurate standard library vulnerability detection
# Override this in .env.custom if needed for compatibility
-GOVULNCHECK_GO_VERSION=1.25.5
+GOVULNCHECK_GO_VERSION=1.25.6
# ================================================================================================
# ๐ฆ GO MODULE CONFIGURATION
@@ -235,7 +235,7 @@ REDIS_CACHE_FORCE_PULL=false # Force pull Redis images even when cache
# ๐ช MAGE-X CONFIGURATION
# ================================================================================================
-MAGE_X_VERSION=v1.17.4 # https://github.com/mrz1836/mage-x/releases
+MAGE_X_VERSION=v1.18.1 # https://github.com/mrz1836/mage-x/releases
MAGE_X_USE_LOCAL=false # Use local version for development
MAGE_X_CI_SKIP_STEP_SUMMARY=true # Skip duplicate test results in step summary (already in test validation summary)
MAGE_X_AUTO_DISCOVER_BUILD_TAGS=true # Enable auto-discovery of build tags
@@ -509,5 +509,10 @@ GO_BROADCAST_AI_RETRY_MAX_ATTEMPTS=3
GO_BROADCAST_AI_RETRY_INITIAL_DELAY=1
GO_BROADCAST_AI_RETRY_MAX_DELAY=10
+# Error handling behavior
+# When true, AI failures will cause sync to fail with an error (shows which API key env var was used)
+# When false (default), AI failures silently fall back to static templates
+GO_BROADCAST_AI_FAIL_ON_ERROR=false
+
# Diff Debugging
# GO_BROADCAST_DEBUG_DIFF_PATH=/tmp/debug-diff.txt
diff --git a/.github/actions/cancel-workflow-on-failure/action.yml b/.github/actions/cancel-workflow-on-failure/action.yml
new file mode 100644
index 0000000..964ec0b
--- /dev/null
+++ b/.github/actions/cancel-workflow-on-failure/action.yml
@@ -0,0 +1,282 @@
+# ------------------------------------------------------------------------------------
+# Cancel Workflow On Failure (Composite Action) (GoFortress)
+#
+# Purpose: Provide a reusable action that cancels the entire workflow run when
+# a critical job fails. This prevents wasting CI resources on parallel jobs
+# that will ultimately be invalidated by an earlier failure.
+#
+# This action handles:
+# - Cancelling the current workflow run via GitHub API
+# - Optional grace period before cancellation
+# - Detailed logging of the cancellation reason
+# - Skipping cancellation in specific scenarios (e.g., release tags)
+# - Safe handling of API errors and edge cases
+#
+# Usage: Add this as the LAST step in critical jobs with `if: failure()`
+#
+# - name: ๐จ Cancel workflow on failure
+# if: failure()
+# uses: ./.github/actions/cancel-workflow-on-failure
+# with:
+# reason: "Code quality checks failed"
+#
+# Permission Requirements:
+# The calling job needs `actions: write` permission to cancel workflows.
+# Add this to your job's permissions block:
+#
+# permissions:
+# contents: read
+# actions: write # Required for workflow cancellation
+#
+# Security Considerations:
+# - Uses GitHub's built-in GITHUB_TOKEN (no external secrets required)
+# - API calls are scoped to the current repository only
+# - Cancellation only affects the current workflow run
+# - No external network calls or dependencies
+#
+# Maintainer: @mrz1836
+#
+# ------------------------------------------------------------------------------------
+
+name: "Cancel Workflow On Failure"
+description: "Cancels the entire workflow run when a critical job fails to save CI resources"
+
+inputs:
+ reason:
+ description: "Reason for cancellation (displayed in logs and job summary)"
+ required: false
+ default: "A critical job failed"
+ skip-on-tags:
+ description: "Skip cancellation for tag pushes (useful for release workflows)"
+ required: false
+ default: "false"
+ grace-period:
+ description: "Seconds to wait before cancelling (allows logs to flush)"
+ required: false
+ default: "2"
+ github-token:
+ description: "GitHub token with actions:write permission (defaults to GITHUB_TOKEN)"
+ required: false
+ default: ""
+
+outputs:
+ cancelled:
+ description: "Whether the workflow cancellation was requested"
+ value: ${{ steps.cancel.outputs.cancelled }}
+ skipped:
+ description: "Whether cancellation was skipped (e.g., tag push with skip-on-tags)"
+ value: ${{ steps.cancel.outputs.skipped }}
+ skip-reason:
+ description: "Reason why cancellation was skipped (if applicable)"
+ value: ${{ steps.cancel.outputs.skip-reason }}
+
+runs:
+ using: "composite"
+ steps:
+ - name: ๐จ Cancel workflow run
+ id: cancel
+ shell: bash
+ env:
+ # Use provided token or fall back to github.token (composite action *input defaults* cannot use expressions like github.token, so the fallback is handled here)
+ GH_TOKEN: ${{ inputs.github-token || github.token }}
+ CANCEL_REASON: ${{ inputs.reason }}
+ SKIP_ON_TAGS: ${{ inputs.skip-on-tags }}
+ GRACE_PERIOD: ${{ inputs.grace-period }}
+ GITHUB_REF: ${{ github.ref }}
+ GITHUB_RUN_ID: ${{ github.run_id }}
+ GITHUB_REPOSITORY: ${{ github.repository }}
+ GITHUB_JOB: ${{ github.job }}
+ GITHUB_WORKFLOW: ${{ github.workflow }}
+ GITHUB_API_URL: ${{ github.api_url }}
+ run: |
+ # Note: Using set -uo pipefail (but not -e):
+ # -e is avoided so we can handle errors (like curl failures and HTTP status codes) explicitly
+ # -o pipefail causes a pipeline to return a failure exit status if any command in the pipeline fails,
+ # but it does not by itself cause the script to exit without -e; exit behavior is controlled explicitly.
+ # When adding new pipelines, ensure each one either handles failures explicitly (e.g., curl ... || CURL_EXIT=$?)
+ # or that you deliberately check and react to the pipeline's exit status if early exit is desired.
+ set -uo pipefail
+
+ echo "๐จ Workflow Cancellation Triggered"
+ echo "โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ"
+ echo ""
+ echo "๐ Context:"
+ echo " โข Workflow: $GITHUB_WORKFLOW"
+ echo " โข Job: $GITHUB_JOB"
+ echo " โข Run ID: $GITHUB_RUN_ID"
+ echo " โข Ref: $GITHUB_REF"
+ printf ' โข Reason: %s\n' "$CANCEL_REASON"
+ echo ""
+
+ # Initialize outputs
+ echo "cancelled=false" >> "$GITHUB_OUTPUT"
+ echo "skipped=false" >> "$GITHUB_OUTPUT"
+ echo "skip-reason=" >> "$GITHUB_OUTPUT"
+
+ # Check if we should skip cancellation for tags
+ if [[ "$SKIP_ON_TAGS" == "true" && "$GITHUB_REF" =~ ^refs/tags/.+ ]]; then
+ echo "โญ๏ธ Skipping cancellation: Running on a tag and skip-on-tags is enabled"
+ echo " This allows release workflows to complete even if non-critical jobs fail"
+ echo ""
+ echo "skipped=true" >> "$GITHUB_OUTPUT"
+ echo "skip-reason=tag-push-with-skip-enabled" >> "$GITHUB_OUTPUT"
+ exit 0
+ fi
+
+ # Validate grace period is a number
+ if ! [[ "$GRACE_PERIOD" =~ ^[0-9]+$ ]]; then
+ echo "โ ๏ธ Invalid grace period '$GRACE_PERIOD', using default of 2 seconds"
+ GRACE_PERIOD=2
+ fi
+
+ # Grace period to allow logs to flush
+ if [[ "$GRACE_PERIOD" -gt 0 ]]; then
+ echo "โณ Waiting ${GRACE_PERIOD}s grace period before cancellation..."
+ sleep "$GRACE_PERIOD"
+ fi
+
+ echo "๐ Cancelling workflow run $GITHUB_RUN_ID..."
+ echo ""
+
+ # Cancel the workflow run using curl for better control and error handling
+ # This avoids dependency on gh CLI being installed
+ # Added timeouts to prevent hanging on network issues
+ # Note: stderr is NOT redirected to avoid interfering with HTTP status code parsing
+ CURL_EXIT=0
+ HTTP_RESPONSE=$(curl -s -w "\n%{http_code}" \
+ --connect-timeout 10 \
+ --max-time 30 \
+ -X POST \
+ -H "Accept: application/vnd.github+json" \
+ -H "Authorization: Bearer $GH_TOKEN" \
+ -H "X-GitHub-Api-Version: 2022-11-28" \
+ "${GITHUB_API_URL}/repos/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}/cancel") || CURL_EXIT=$?
+
+ # Handle curl-level errors (network issues, timeouts)
+ if [[ $CURL_EXIT -ne 0 ]]; then
+ echo ""
+ echo "โ ๏ธ Network error during cancel request (curl exit code: $CURL_EXIT)"
+ echo " This could be a temporary network issue."
+ echo ""
+ echo "skipped=true" >> "$GITHUB_OUTPUT"
+ echo "skip-reason=network-error-$CURL_EXIT" >> "$GITHUB_OUTPUT"
+ # Don't exit with error - we don't want to mask the original failure
+ # The workflow will fail anyway due to the job that triggered this
+ exit 0
+ fi
+
+ # Extract HTTP status code (last line) and response body (everything except last line)
+ # Note: This spawns subshells, but prioritizes readability and portability over micro-optimization.
+ # This code only runs on job failures (rare), and the performance difference is negligible (milliseconds).
+ # Alternative approaches using mapfile/arrays add complexity and bash 4+ dependency for minimal gain.
+ HTTP_STATUS=$(echo "$HTTP_RESPONSE" | tail -n1)
+ RESPONSE_BODY=$(echo "$HTTP_RESPONSE" | sed '$d')
+
+ # Validate HTTP_STATUS is non-empty (malformed response protection)
+ if [[ -z "$HTTP_STATUS" ]]; then
+ echo ""
+ echo "โ ๏ธ Unable to determine HTTP status from cancel API response"
+ if [[ -n "$RESPONSE_BODY" ]]; then
+ printf ' Raw response (sanitized): %q\n' "$RESPONSE_BODY"
+ fi
+ echo ""
+ echo "skipped=true" >> "$GITHUB_OUTPUT"
+ echo "skip-reason=api-error-empty-status" >> "$GITHUB_OUTPUT"
+ exit 0
+ fi
+
+ echo "๐ก API Response Status: $HTTP_STATUS"
+
+ case "$HTTP_STATUS" in
+ 202)
+ echo ""
+ echo "โ
Workflow cancellation request accepted"
+ echo ""
+ echo "๐ Note: Other jobs may complete their current step before stopping."
+ echo " This is expected GitHub Actions behavior."
+ echo ""
+ echo "cancelled=true" >> "$GITHUB_OUTPUT"
+ ;;
+ 403)
+ echo ""
+ echo "โ ๏ธ Permission denied (403)"
+ echo " The job may be missing 'actions: write' permission."
+ echo " Add this to the job's permissions block:"
+ echo ""
+ echo " permissions:"
+ echo " contents: read"
+ echo " actions: write"
+ echo ""
+ echo "skipped=true" >> "$GITHUB_OUTPUT"
+ echo "skip-reason=permission-denied" >> "$GITHUB_OUTPUT"
+ ;;
+ 404)
+ echo ""
+ echo "โ ๏ธ Workflow run not found (404)"
+ echo " The workflow run may have already completed."
+ echo ""
+ echo "skipped=true" >> "$GITHUB_OUTPUT"
+ echo "skip-reason=run-not-found" >> "$GITHUB_OUTPUT"
+ ;;
+ 409)
+ echo ""
+ echo "โ ๏ธ Conflict (409) - Workflow is already being cancelled or has completed"
+ echo ""
+ echo "skipped=true" >> "$GITHUB_OUTPUT"
+ echo "skip-reason=already-cancelled-or-completed" >> "$GITHUB_OUTPUT"
+ ;;
+ *)
+ echo ""
+ echo "โ ๏ธ Unexpected response (HTTP $HTTP_STATUS)"
+ if [[ -n "$RESPONSE_BODY" ]]; then
+ printf ' Response (sanitized): %q\n' "$RESPONSE_BODY"
+ fi
+ echo ""
+ echo "skipped=true" >> "$GITHUB_OUTPUT"
+ echo "skip-reason=api-error-$HTTP_STATUS" >> "$GITHUB_OUTPUT"
+ ;;
+ esac
+
+ # Escape markdown special characters that could break tables or formatting
+ # Note: Multiple parameter expansions are used intentionally over sed for:
+ # - Pure bash (no external process overhead)
+ # - Explicit, self-documenting escapes
+ # - Easier maintenance and debugging
+ # This only runs on failures, so micro-optimization is not a priority.
+ CANCEL_REASON_MD=$CANCEL_REASON
+ CANCEL_REASON_MD=${CANCEL_REASON_MD//\\/\\\\}
+ CANCEL_REASON_MD=${CANCEL_REASON_MD//|/\\|}
+ CANCEL_REASON_MD=${CANCEL_REASON_MD//\`/\\\`}
+ CANCEL_REASON_MD=${CANCEL_REASON_MD//\*/\\*}
+ CANCEL_REASON_MD=${CANCEL_REASON_MD//_/\\_}
+ CANCEL_REASON_MD=${CANCEL_REASON_MD//[/\\[}
+ CANCEL_REASON_MD=${CANCEL_REASON_MD//]/\\]}
+ CANCEL_REASON_MD=${CANCEL_REASON_MD//\\<}
+ CANCEL_REASON_MD=${CANCEL_REASON_MD//>/\\>}
+
+ # Determine status cell value for job summary
+ if [[ "$HTTP_STATUS" == "202" ]]; then
+ STATUS_CELL_VALUE="โ
Accepted"
+ else
+ STATUS_CELL_VALUE="โ ๏ธ HTTP $HTTP_STATUS"
+ fi
+
+ # Add to job summary (always, regardless of success/failure)
+ {
+ echo "## ๐จ Workflow Cancellation"
+ echo ""
+ echo "| Detail | Value |"
+ echo "|--------|-------|"
+ echo "| **Reason** | $CANCEL_REASON_MD |"
+ echo "| **Triggered by** | \`$GITHUB_JOB\` |"
+ echo "| **Run ID** | $GITHUB_RUN_ID |"
+ echo "| **Status** | $STATUS_CELL_VALUE |"
+ echo ""
+ if [[ "$HTTP_STATUS" == "202" ]]; then
+ echo "This cancellation was triggered to save CI resources after a critical failure."
+ elif [[ "$HTTP_STATUS" == "403" ]]; then
+ echo "โ ๏ธ **Permission Issue**: Add \`actions: write\` permission to enable cancellation."
+ elif [[ "$HTTP_STATUS" == "409" ]]; then
+ echo "โน๏ธ **Already Cancelling**: Another job already triggered cancellation."
+ fi
+ } >> "$GITHUB_STEP_SUMMARY"
diff --git a/.github/actions/download-artifact-resilient/action.yml b/.github/actions/download-artifact-resilient/action.yml
index 12d4114..b98c8aa 100644
--- a/.github/actions/download-artifact-resilient/action.yml
+++ b/.github/actions/download-artifact-resilient/action.yml
@@ -100,10 +100,42 @@ runs:
# Check if artifacts exist first (avoid unnecessary retries)
echo "๐ Checking artifact availability..."
- if ! gh api repos/${{ github.repository }}/actions/runs/${{ github.run_id }}/artifacts | jq -e ".artifacts[] | select(.name | test(\"$REGEX_PATTERN\"))" > /dev/null 2>&1; then
+
+ # Fetch artifacts list, handling API errors gracefully
+ ARTIFACTS_JSON=$(gh api repos/${{ github.repository }}/actions/runs/${{ github.run_id }}/artifacts 2>&1) || {
+ API_ERROR=$?
+ echo "โ ๏ธ Failed to fetch artifacts list (exit code: $API_ERROR)"
+ echo " Response: $ARTIFACTS_JSON"
+
+ if [ "$CONTINUE_ON_ERROR" = "true" ]; then
+ echo "::warning title=Artifact API Error::Failed to fetch artifacts list - API may be unavailable or credentials invalid"
+ DOWNLOAD_SUCCESS=false
+ break
+ else
+ echo "::error title=Artifact API Error::Failed to fetch artifacts list - API may be unavailable or credentials invalid"
+ exit 1
+ fi
+ }
+
+ # Validate JSON response before processing
+ if ! echo "$ARTIFACTS_JSON" | jq -e '.artifacts' > /dev/null 2>&1; then
+ echo "โ ๏ธ Invalid API response (not valid artifacts JSON)"
+ echo " Response: $ARTIFACTS_JSON"
+
+ if [ "$CONTINUE_ON_ERROR" = "true" ]; then
+ echo "::warning title=Invalid API Response::Artifacts API returned invalid response"
+ DOWNLOAD_SUCCESS=false
+ break
+ else
+ echo "::error title=Invalid API Response::Artifacts API returned invalid response"
+ exit 1
+ fi
+ fi
+
+ if ! echo "$ARTIFACTS_JSON" | jq -e ".artifacts[] | select(.name | test(\"$REGEX_PATTERN\"))" > /dev/null 2>&1; then
echo "โ ๏ธ No artifacts found matching pattern '$ARTIFACT_PATTERN'"
echo "๐ Available artifacts:"
- gh api repos/${{ github.repository }}/actions/runs/${{ github.run_id }}/artifacts | jq -r '.artifacts[].name' | sed 's/^/ โข /' || echo " No artifacts available"
+ echo "$ARTIFACTS_JSON" | jq -r '.artifacts[].name' 2>/dev/null | sed 's/^/ โข /' || echo " No artifacts available"
if [ "$CONTINUE_ON_ERROR" = "true" ]; then
echo "::warning title=No Artifacts Found::No artifacts found matching pattern '$ARTIFACT_PATTERN'"
@@ -116,7 +148,7 @@ runs:
fi
# Count available artifacts
- AVAILABLE_ARTIFACTS=$(gh api repos/${{ github.repository }}/actions/runs/${{ github.run_id }}/artifacts | jq "[.artifacts[] | select(.name | test(\"$REGEX_PATTERN\"))] | length")
+ AVAILABLE_ARTIFACTS=$(echo "$ARTIFACTS_JSON" | jq "[.artifacts[] | select(.name | test(\"$REGEX_PATTERN\"))] | length")
echo "๐ Found $AVAILABLE_ARTIFACTS artifact(s) matching pattern"
# Attempt download with timeout
diff --git a/.github/actions/test-statistics/action.yml b/.github/actions/test-statistics/action.yml
deleted file mode 100644
index d4563a9..0000000
--- a/.github/actions/test-statistics/action.yml
+++ /dev/null
@@ -1,370 +0,0 @@
-# ------------------------------------------------------------------------------------
-# Test Statistics Collection (Composite Action)
-#
-# โ ๏ธ DEPRECATED: This action is deprecated in favor of magex native CI mode.
-#
-# magex CI mode automatically produces .mage-x/ci-results.jsonl which includes:
-# - Test pass/fail counts
-# - Duration metrics
-# - Failure details with file:line locations
-# - Summary statistics
-#
-# Usage: Simply run `magex test:*` commands - CI mode auto-detects GitHub Actions.
-# The validation workflow reads results from ci-results.jsonl instead of this action.
-#
-# This action is kept for backwards compatibility but will be removed in a future release.
-#
-# ---------------------------------------------------------------------------------
-#
-# Original Purpose: Calculate and collect comprehensive test statistics including test counts,
-# failure metrics, performance data, and lines of code metrics.
-#
-# This action provides standardized statistics collection:
-# - Test and benchmark counting from source files
-# - Failure analysis from test output files
-# - Performance metrics (duration, output size)
-# - Lines of code metrics via magex
-# - JSON output for consumption by other workflows
-#
-# Maintainer: @mrz1836
-#
-# ------------------------------------------------------------------------------------
-
-name: "Test Statistics Collection"
-description: "Calculate comprehensive test statistics and metrics for test runs"
-
-inputs:
- matrix-name:
- description: 'Matrix job name (e.g., "ubuntu-latest go1.21")'
- required: true
- matrix-os:
- description: "Operating system from matrix"
- required: true
- matrix-go-version:
- description: "Go version from matrix"
- required: true
- test-exit-code:
- description: "Test command exit code"
- required: true
- output-mode:
- description: "Test output mode (FULL or FAILURES_ONLY)"
- required: false
- default: "FULL"
- job-status:
- description: "Current job status"
- required: true
- test-start-time:
- description: "Test start timestamp (epoch)"
- required: true
- race-detection-enabled:
- description: "Whether race detection was enabled"
- required: false
- default: "false"
- code-coverage-enabled:
- description: "Whether code coverage was enabled"
- required: false
- default: "false"
- fuzz-run:
- description: "Whether this is a fuzz test run"
- required: false
- default: "false"
- failures-file:
- description: "Path to test failures file"
- required: false
- default: "test-failures.txt"
- output-file:
- description: "Path to test output file"
- required: false
- default: "test-output.log"
-
-outputs:
- statistics-file:
- description: "Path to generated statistics JSON file"
- value: ${{ steps.generate-stats.outputs.statistics-file }}
- test-count:
- description: "Total number of tests found"
- value: ${{ steps.generate-stats.outputs.test-count }}
- benchmark-count:
- description: "Total number of benchmarks found"
- value: ${{ steps.generate-stats.outputs.benchmark-count }}
- total-failures:
- description: "Total number of test failures"
- value: ${{ steps.generate-stats.outputs.total-failures }}
- test-passed:
- description: "Boolean indicating if tests passed"
- value: ${{ steps.generate-stats.outputs.test-passed }}
- duration-seconds:
- description: "Test execution duration in seconds"
- value: ${{ steps.generate-stats.outputs.duration-seconds }}
- loc-total:
- description: "Total lines of code"
- value: ${{ steps.generate-stats.outputs.loc-total }}
-
-runs:
- using: "composite"
- steps:
- - name: ๐ Calculate test statistics
- id: generate-stats
- shell: bash
- run: |
- # Enable error handling but don't exit on first error to allow cleanup
- set +e
-
- # Get basic values with safe defaults
- TEST_EXIT_CODE="${{ inputs.test-exit-code }}"
- OUTPUT_MODE="${{ inputs.output-mode }}"
- TEST_END=$(date +%s)
- TEST_DURATION=$((TEST_END - ${{ inputs.test-start-time }}))
-
- # Count tests and benchmarks
- FUZZ_RUN="${{ inputs.fuzz-run }}"
- if [[ "$FUZZ_RUN" == "true" ]]; then
- # Count fuzz functions for fuzz runs
- TEST_COUNT=$(find . -type f -name '*_test.go' \
- -not -path './vendor/*' \
- -not -path './third_party/*' \
- -not -path './testdata/*' \
- -exec grep -hE '^\s*func (\([^)]+\) )?Fuzz[A-Z0-9_]' {} + | wc -l | xargs)
- else
- # Count test functions for regular test runs
- TEST_COUNT=$(find . -type f -name '*_test.go' \
- -not -path './vendor/*' \
- -not -path './third_party/*' \
- -not -path './testdata/*' \
- -exec grep -hE '^\s*func (\([^)]+\) )?Test[A-Z0-9_]' {} + | wc -l | xargs)
- fi
- TEST_COUNT=${TEST_COUNT:-0}
-
- BENCHMARK_COUNT=$(find . -type f -name '*_test.go' \
- -not -path './vendor/*' \
- -not -path './third_party/*' \
- -exec grep -h '^func Benchmark' {} + | wc -l | xargs)
- BENCHMARK_COUNT=${BENCHMARK_COUNT:-0}
-
- # Count failures
- TOTAL_FAILURES=0
- FAILURES_FILE="${{ inputs.failures-file }}"
- if [[ -f "$FAILURES_FILE" ]]; then
- TOTAL_FAILURES=$(wc -l < "$FAILURES_FILE" 2>/dev/null || echo "0")
- fi
-
- # Calculate output size
- OUTPUT_SIZE=0
- OUTPUT_FILE="${{ inputs.output-file }}"
- if [[ -f "$OUTPUT_FILE" ]]; then
- OUTPUT_SIZE=$(wc -c < "$OUTPUT_FILE" 2>/dev/null || echo "0")
- fi
-
- # Collect Lines of Code metrics using magex
- LOC_TEST_FILES=""
- LOC_GO_FILES=""
- LOC_TOTAL=""
- LOC_DATE=$(date -u +"%Y-%m-%d")
-
- if command -v magex &> /dev/null; then
- echo "๐ Collecting Lines of Code metrics..."
- LOC_OUTPUT=$(magex metrics:loc 2>&1 || true)
- if [[ -n "$LOC_OUTPUT" ]]; then
- echo "๐ Raw LOC output:"
- echo "$LOC_OUTPUT"
- echo "๐ Parsing LOC data..."
-
- # Extract numbers from magex metrics:loc output - preserve commas for display
- # Format: "| Test Files | 71,476 | 2025-08-28 |" -> extract field 3, trim spaces but keep commas
- LOC_TEST_FILES=$(echo "$LOC_OUTPUT" | grep "Test Files" | awk -F'|' '{print $3}' | sed 's/^[[:space:]]*//;s/[[:space:]]*$//' || echo "")
- LOC_GO_FILES=$(echo "$LOC_OUTPUT" | grep "Go Files" | awk -F'|' '{print $3}' | sed 's/^[[:space:]]*//;s/[[:space:]]*$//' || echo "")
- # Format: "โ
Total lines of code: 93,418" -> extract last field after colon, preserve commas
- LOC_TOTAL=$(echo "$LOC_OUTPUT" | grep "Total lines of code:" | awk -F':' '{print $2}' | sed 's/^[[:space:]]*//;s/[[:space:]]*$//' || echo "")
-
- echo "๐ Parsed values:"
- echo " - Test Files: '$LOC_TEST_FILES'"
- echo " - Go Files: '$LOC_GO_FILES'"
- echo " - Total: '$LOC_TOTAL'"
-
- if [[ -n "$LOC_TOTAL" ]]; then
- echo "โ
LOC collected: $LOC_TOTAL total ($LOC_TEST_FILES test, $LOC_GO_FILES go)"
- else
- echo "โ ๏ธ LOC parsing failed - no total found"
- fi
- else
- echo "โ ๏ธ No LOC output collected from magex"
- fi
- else
- echo "โ ๏ธ magex not available for LOC collection"
- fi
-
- # Pre-compute boolean values
- TEST_PASSED=$([ "$TEST_EXIT_CODE" = "0" ] && echo "true" || echo "false")
- RACE_ENABLED="${{ inputs.race-detection-enabled == 'true' && 'true' || 'false' }}"
- COVERAGE_ENABLED="${{ inputs.code-coverage-enabled == 'true' && 'true' || 'false' }}"
- FUZZ_RUN="${{ inputs.fuzz-run == 'true' && 'true' || 'false' }}"
-
- # Count affected packages from failure details
- AFFECTED_PACKAGES=0
- FAILURE_DETAILS="[]"
- if [[ -f test-failures-summary.json ]] && [[ -s test-failures-summary.json ]]; then
- AFFECTED_PACKAGES=$(jq 'length' test-failures-summary.json 2>/dev/null || echo "0")
- # Extract failure details for completion report
- FAILURE_DETAILS=$(jq '[.[] as $parent | $parent.failures[] | {
- Test: .Test,
- Package: $parent.Package,
- Duration: (.Elapsed // "unknown"),
- Output: ((.Output // "") | if length > 500 then .[0:500] + "..." else . end)
- }]' test-failures-summary.json 2>/dev/null || echo "[]")
- fi
-
- # Secondary validation: Cross-check test_passed against detected failures
- echo "๐ Secondary validation: Cross-checking test_passed against failure indicators..."
- ORIGINAL_TEST_PASSED="$TEST_PASSED"
-
- if [[ "$TEST_PASSED" == "true" ]]; then
- # Check for inconsistencies where test_passed=true but we have failures
- if [[ "$TOTAL_FAILURES" -gt 0 ]] || [[ "$AFFECTED_PACKAGES" -gt 0 ]]; then
- echo "โ ๏ธ Inconsistency detected: test_passed=true but failures found:"
- echo " โข Total failures: $TOTAL_FAILURES"
- echo " โข Affected packages: $AFFECTED_PACKAGES"
- echo "๐ง Overriding test_passed from true to false"
- TEST_PASSED="false"
- fi
-
- # Note: Previously checked for "Error:" patterns in test output, but this was too broad
- # and caught legitimate error strings in test assertions, output formatting, and test data.
- # Removed to rely on more accurate failure detection from test exit codes and structured data.
- fi
-
- if [[ "$ORIGINAL_TEST_PASSED" != "$TEST_PASSED" ]]; then
- echo "โ
Secondary validation corrected test_passed: $ORIGINAL_TEST_PASSED -> $TEST_PASSED"
- else
- echo "โ
Secondary validation confirmed test_passed: $TEST_PASSED"
- fi
-
- # Use jq to build JSON safely - no heredocs, no sed, no complex logic
- # Generate appropriate filename based on test type
- if [[ "$FUZZ_RUN" == "true" ]]; then
- STATS_FILE="fuzz-stats-${{ inputs.matrix-os }}-${{ inputs.matrix-go-version }}.json"
- else
- STATS_FILE="test-stats-${{ inputs.matrix-os }}-${{ inputs.matrix-go-version }}.json"
- fi
-
- # Set fuzz_test_count for fuzz runs (same as test_count for fuzz tests)
- FUZZ_TEST_COUNT=0
- if [[ "$FUZZ_RUN" == "true" ]]; then
- FUZZ_TEST_COUNT=$TEST_COUNT
- fi
-
- # Create JSON with error handling
- JSON_CREATE_SUCCESS=false
- if jq -n \
- --arg name "${{ inputs.matrix-name }}" \
- --arg os "${{ inputs.matrix-os }}" \
- --arg version "${{ inputs.matrix-go-version }}" \
- --arg exit_code "$TEST_EXIT_CODE" \
- --argjson passed "$TEST_PASSED" \
- --arg status "${{ inputs.job-status }}" \
- --arg timestamp "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
- --arg test_mode "$OUTPUT_MODE" \
- --argjson duration "$TEST_DURATION" \
- --argjson test_count "$TEST_COUNT" \
- --argjson benchmark_count "$BENCHMARK_COUNT" \
- --argjson total_failures "$TOTAL_FAILURES" \
- --argjson affected_packages "$AFFECTED_PACKAGES" \
- --argjson failure_details "$FAILURE_DETAILS" \
- --argjson output_size "$OUTPUT_SIZE" \
- --argjson race_enabled "$RACE_ENABLED" \
- --argjson coverage_enabled "$COVERAGE_ENABLED" \
- --argjson fuzz_run "$FUZZ_RUN" \
- --argjson fuzz_test_count "$FUZZ_TEST_COUNT" \
- --arg loc_test_files "$LOC_TEST_FILES" \
- --arg loc_go_files "$LOC_GO_FILES" \
- --arg loc_total "$LOC_TOTAL" \
- --arg loc_date "$LOC_DATE" \
- '{
- name: $name,
- os: $os,
- go_version: $version,
- test_mode: $test_mode,
- duration_seconds: $duration,
- test_count: $test_count,
- benchmark_count: $benchmark_count,
- status: $status,
- test_exit_code: ($exit_code | tonumber),
- test_passed: $passed,
- total_failures: $total_failures,
- affected_packages: $affected_packages,
- failure_details: $failure_details,
- output_size_bytes: $output_size,
- race_enabled: $race_enabled,
- coverage_enabled: $coverage_enabled,
- fuzz_run: $fuzz_run,
- fuzz_test_count: $fuzz_test_count,
- timestamp: $timestamp,
- loc_test_files: $loc_test_files,
- loc_go_files: $loc_go_files,
- loc_total: $loc_total,
- loc_date: $loc_date
- }' > "$STATS_FILE" 2>/dev/null; then
- JSON_CREATE_SUCCESS=true
- echo "๐ Test statistics generated successfully:"
- else
- echo "โ ๏ธ JSON creation failed, creating minimal statistics file"
- # Create minimal fallback JSON
- printf '%s\n' \
- '{' \
- ' "name": "'"${{ inputs.matrix-name }}"'",' \
- ' "os": "'"${{ inputs.matrix-os }}"'",' \
- ' "go_version": "'"${{ inputs.matrix-go-version }}"'",' \
- ' "test_mode": "'"$OUTPUT_MODE"'",' \
- ' "duration_seconds": '"$TEST_DURATION"',' \
- ' "test_count": '"${TEST_COUNT:-0}"',' \
- ' "benchmark_count": '"${BENCHMARK_COUNT:-0}"',' \
- ' "status": "'"${{ inputs.job-status }}"'",' \
- ' "test_exit_code": '"${TEST_EXIT_CODE:-0}"',' \
- ' "test_passed": '"$TEST_PASSED"',' \
- ' "total_failures": '"${TOTAL_FAILURES:-0}"',' \
- ' "affected_packages": '"${AFFECTED_PACKAGES:-0}"',' \
- ' "failure_details": [],' \
- ' "output_size_bytes": '"${OUTPUT_SIZE:-0}"',' \
- ' "race_enabled": '"$RACE_ENABLED"',' \
- ' "coverage_enabled": '"$COVERAGE_ENABLED"',' \
- ' "fuzz_run": '"$FUZZ_RUN"',' \
- ' "fuzz_test_count": '"${FUZZ_TEST_COUNT:-0}"',' \
- ' "timestamp": "'"$(date -u +%Y-%m-%dT%H:%M:%SZ)"'",' \
- ' "loc_test_files": "'"$LOC_TEST_FILES"'",' \
- ' "loc_go_files": "'"$LOC_GO_FILES"'",' \
- ' "loc_total": "'"$LOC_TOTAL"'",' \
- ' "loc_date": "'"$LOC_DATE"'"' \
- '}' > "$STATS_FILE"
- JSON_CREATE_SUCCESS=true
- echo "๐ Minimal test statistics generated successfully:"
- fi
-
- # Display the JSON file if it was created successfully
- if [[ "$JSON_CREATE_SUCCESS" == "true" ]] && [[ -f "$STATS_FILE" ]]; then
- jq . "$STATS_FILE" 2>/dev/null || cat "$STATS_FILE"
- else
- echo "โ Failed to create statistics file"
- fi
-
- # Always set outputs for other steps/workflows (with safe defaults)
- if [[ "$JSON_CREATE_SUCCESS" == "true" ]] && [[ -f "$STATS_FILE" ]]; then
- echo "statistics-file=$STATS_FILE" >> $GITHUB_OUTPUT
- else
- echo "statistics-file=" >> $GITHUB_OUTPUT
- fi
- echo "test-count=${TEST_COUNT:-0}" >> $GITHUB_OUTPUT
- echo "benchmark-count=${BENCHMARK_COUNT:-0}" >> $GITHUB_OUTPUT
- echo "total-failures=${TOTAL_FAILURES:-0}" >> $GITHUB_OUTPUT
- echo "test-passed=${TEST_PASSED:-false}" >> $GITHUB_OUTPUT
- echo "duration-seconds=${TEST_DURATION:-0}" >> $GITHUB_OUTPUT
- echo "loc-total=${LOC_TOTAL:-}" >> $GITHUB_OUTPUT
-
- echo "๐ Statistics collection completed:"
- echo " โข Tests: ${TEST_COUNT:-0}"
- echo " โข Benchmarks: ${BENCHMARK_COUNT:-0}"
- echo " โข Failures: ${TOTAL_FAILURES:-0}"
- echo " โข Passed: ${TEST_PASSED:-false}"
- echo " โข Duration: ${TEST_DURATION:-0}s"
- echo " โข LOC Total: ${LOC_TOTAL:-N/A}"
-
- # Always exit successfully to prevent cascading failures
- exit 0
diff --git a/.github/workflows/auto-merge-on-approval.yml b/.github/workflows/auto-merge-on-approval.yml
index eabc608..85a042c 100644
--- a/.github/workflows/auto-merge-on-approval.yml
+++ b/.github/workflows/auto-merge-on-approval.yml
@@ -65,7 +65,7 @@ jobs:
# Check out code to access env file
# --------------------------------------------------------------------
- name: ๐ฅ Checkout code (sparse)
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
sparse-checkout: |
.github/.env.base
diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml
index b30ab6b..5809bc7 100644
--- a/.github/workflows/codeql-analysis.yml
+++ b/.github/workflows/codeql-analysis.yml
@@ -42,7 +42,7 @@ jobs:
steps:
- name: Checkout repository
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
diff --git a/.github/workflows/dependabot-auto-merge.yml b/.github/workflows/dependabot-auto-merge.yml
index 6cea005..f3ee55a 100644
--- a/.github/workflows/dependabot-auto-merge.yml
+++ b/.github/workflows/dependabot-auto-merge.yml
@@ -63,7 +63,7 @@ jobs:
# Check out code to access env file
# --------------------------------------------------------------------
- name: ๐ฅ Checkout code (sparse)
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
sparse-checkout: |
.github/.env.base
diff --git a/.github/workflows/fortress-benchmarks.yml b/.github/workflows/fortress-benchmarks.yml
index b86ed8f..2d70b67 100644
--- a/.github/workflows/fortress-benchmarks.yml
+++ b/.github/workflows/fortress-benchmarks.yml
@@ -129,7 +129,7 @@ jobs:
# Checkout code and set up Go environment
# --------------------------------------------------------------------
- name: ๐ฅ Checkout code
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
# --------------------------------------------------------------------
# Setup Go with caching and version management
diff --git a/.github/workflows/fortress-code-quality.yml b/.github/workflows/fortress-code-quality.yml
index f675036..86ea33c 100644
--- a/.github/workflows/fortress-code-quality.yml
+++ b/.github/workflows/fortress-code-quality.yml
@@ -66,12 +66,13 @@ jobs:
runs-on: ${{ inputs.primary-runner }}
permissions:
contents: read
+ actions: write # Required for workflow cancellation on failure
steps:
# --------------------------------------------------------------------
# Checkout code (required for local actions)
# --------------------------------------------------------------------
- name: ๐ฅ Checkout code
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
# --------------------------------------------------------------------
# Parse environment variables
@@ -117,9 +118,12 @@ jobs:
# Run go vet with sequential execution to avoid memory issues
# --------------------------------------------------------------------
- name: ๐ Go vet (sequential)
+ id: run-govet
+ continue-on-error: true
run: |
echo "๐ Running static analysis with go vet (sequential mode)..."
GO_MODULE_DIR="${{ env.GO_MODULE_DIR }}"
+ GOVET_EXIT_CODE=0
# Run go vet on packages sequentially to reduce memory usage
if [ -n "$GO_MODULE_DIR" ]; then
@@ -134,37 +138,60 @@ jobs:
# Discard stderr to avoid capturing download progress messages
if ! PACKAGES=$(go list ./... 2>/dev/null | grep -v /vendor/); then
# If command failed, re-run with stderr visible to show the error
- echo "โ go list command failed:"
- go list ./... 2>&1 | head -20
- exit 1
+ echo "โ go list command failed:" | tee govet-output.log
+ go list ./... 2>&1 | head -20 | tee -a govet-output.log
+ echo "govet-exit-code=1" >> $GITHUB_OUTPUT
+ echo "govet-status=failure" >> $GITHUB_OUTPUT
+ exit 0 # Continue to allow summary generation
fi
TOTAL=$(echo "$PACKAGES" | grep -c . || echo 0)
CURRENT=0
echo "๐ฆ Found $TOTAL packages to vet"
+ echo "๐ฆ Found $TOTAL packages to vet" > govet-output.log
if [ "$TOTAL" -eq 0 ]; then
- echo "โ ๏ธ No packages found to vet"
- exit 1
+ echo "โ ๏ธ No packages found to vet" | tee -a govet-output.log
+ echo "govet-exit-code=1" >> $GITHUB_OUTPUT
+ echo "govet-status=failure" >> $GITHUB_OUTPUT
+ exit 0 # Continue to allow summary generation
fi
for pkg in $PACKAGES; do
CURRENT=$((CURRENT + 1))
echo "[$CURRENT/$TOTAL] Vetting $pkg..."
- if ! go vet "$pkg"; then
- echo "โ go vet failed on package: $pkg"
- exit 1
+ if ! go vet "$pkg" 2>&1 | tee -a govet-output.log; then
+ echo "โ go vet failed on package: $pkg" | tee -a govet-output.log
+ GOVET_EXIT_CODE=1
fi
done
- echo "โ
Static analysis completed successfully"
+ echo "govet-exit-code=$GOVET_EXIT_CODE" >> $GITHUB_OUTPUT
+ if [[ $GOVET_EXIT_CODE -eq 0 ]]; then
+ echo "govet-status=success" >> $GITHUB_OUTPUT
+ echo "โ
Static analysis completed successfully"
+ else
+ echo "govet-status=failure" >> $GITHUB_OUTPUT
+ echo "โ Static analysis completed with errors"
+ fi
+
+ # --------------------------------------------------------------------
+ # Create GitHub Annotations for failures
+ # --------------------------------------------------------------------
+ - name: ๐ Create GitHub Annotations
+ if: always() && steps.run-govet.outputs.govet-status == 'failure'
+ run: |
+ echo "::error title=Go Vet Failed::Static analysis issues detected - see job summary for details"
# --------------------------------------------------------------------
# Summary of Go vet results
# --------------------------------------------------------------------
- name: ๐ Job Summary
+ if: always()
run: |
+ GOVET_STATUS="${{ steps.run-govet.outputs.govet-status }}"
+
echo "## ๐ Go Vet Static Analysis Summary" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "| Analysis Details | Status |" >> $GITHUB_STEP_SUMMARY
@@ -172,9 +199,40 @@ jobs:
echo "| **Tool** | go vet (Official Go Static Analyzer) |" >> $GITHUB_STEP_SUMMARY
echo "| **Execution** | Sequential (memory-optimized) |" >> $GITHUB_STEP_SUMMARY
echo "| **Scope** | ./... (excludes dependencies) |" >> $GITHUB_STEP_SUMMARY
- echo "| **Result** | โ
No issues found |" >> $GITHUB_STEP_SUMMARY
- echo "" >> $GITHUB_STEP_SUMMARY
- echo "๐ฏ **All packages passed static analysis checks.**" >> $GITHUB_STEP_SUMMARY
+
+ if [[ "$GOVET_STATUS" == "success" ]]; then
+ echo "| **Result** | โ
No issues found |" >> $GITHUB_STEP_SUMMARY
+ echo "" >> $GITHUB_STEP_SUMMARY
+ echo "๐ฏ **All packages passed static analysis checks.**" >> $GITHUB_STEP_SUMMARY
+ else
+ echo "| **Result** | โ Issues detected |" >> $GITHUB_STEP_SUMMARY
+ echo "" >> $GITHUB_STEP_SUMMARY
+
+ # Show failure details if applicable
+ if [[ -f govet-output.log ]]; then
+ echo "### ๐จ Error Details" >> $GITHUB_STEP_SUMMARY
+ echo "" >> $GITHUB_STEP_SUMMARY
+ echo "" >> $GITHUB_STEP_SUMMARY
+ echo "Click to expand full output
" >> $GITHUB_STEP_SUMMARY
+ echo "" >> $GITHUB_STEP_SUMMARY
+ echo '```' >> $GITHUB_STEP_SUMMARY
+ head -200 govet-output.log >> $GITHUB_STEP_SUMMARY
+ echo '```' >> $GITHUB_STEP_SUMMARY
+ echo " " >> $GITHUB_STEP_SUMMARY
+ fi
+ fi
+
+ # --------------------------------------------------------------------
+ # Upload go vet results
+ # --------------------------------------------------------------------
+ - name: ๐ค Upload go vet results
+ if: always()
+ uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
+ with:
+ name: govet-results
+ path: govet-output.log
+ retention-days: 7
+ if-no-files-found: ignore
# --------------------------------------------------------------------
# Collect cache statistics
@@ -203,6 +261,24 @@ jobs:
artifact-path: cache-stats-govet.json
retention-days: 1
+ # --------------------------------------------------------------------
+ # Fail job if issues found
+ # --------------------------------------------------------------------
+ - name: ๐จ Fail job if issues found
+ if: always() && steps.run-govet.outputs.govet-status == 'failure'
+ run: |
+ echo "โ Go vet detected static analysis issues"
+ exit 1
+
+ # --------------------------------------------------------------------
+ # Cancel workflow on failure (save CI resources)
+ # --------------------------------------------------------------------
+ - name: ๐จ Cancel workflow on failure
+ if: failure()
+ uses: ./.github/actions/cancel-workflow-on-failure
+ with:
+ reason: "Go vet static analysis failed"
+
# ----------------------------------------------------------------------------------
# Lint (Code Linting)
# ----------------------------------------------------------------------------------
@@ -213,6 +289,7 @@ jobs:
runs-on: ${{ inputs.primary-runner }}
permissions:
contents: read
+ actions: write # Required for workflow cancellation on failure
outputs:
golangci-lint-version: ${{ steps.golangci-lint-version.outputs.version }}
steps:
@@ -220,7 +297,7 @@ jobs:
# Checkout code (required for local actions)
# --------------------------------------------------------------------
- name: ๐ฅ Checkout code
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
# --------------------------------------------------------------------
# Parse environment variables
@@ -339,6 +416,8 @@ jobs:
# Run golangci-lint
# --------------------------------------------------------------------
- name: โจ Run golangci-lint
+ id: run-lint
+ continue-on-error: true
run: |
echo "๐งน Running code linting with golangci-lint..."
echo "๐พ Golangci-lint cache location: $GOLANGCI_LINT_CACHE"
@@ -349,19 +428,39 @@ jobs:
GO_MODULE_DIR="${{ env.GO_MODULE_DIR }}"
+ set +e
if [ "$ENABLE_MULTI_MODULE_TESTING" == "true" ]; then
echo "๐ง Multi-module linting enabled - running from repository root"
echo "๐ฆ magex will discover all Go modules"
- magex lint
+ magex lint 2>&1 | tee lint-output.log
+ LINT_EXIT_CODE=${PIPESTATUS[0]}
elif [ -n "$GO_MODULE_DIR" ]; then
echo "๐ง Running magex lint from directory: $GO_MODULE_DIR"
- (cd "$GO_MODULE_DIR" && magex lint)
+ (cd "$GO_MODULE_DIR" && magex lint 2>&1 | tee ../lint-output.log)
+ LINT_EXIT_CODE=${PIPESTATUS[0]}
else
echo "๐ง Running magex lint from repository root"
- magex lint
+ magex lint 2>&1 | tee lint-output.log
+ LINT_EXIT_CODE=${PIPESTATUS[0]}
fi
+ set -e
- echo "โ
Code linting completed successfully"
+ echo "lint-exit-code=$LINT_EXIT_CODE" >> $GITHUB_OUTPUT
+ if [[ $LINT_EXIT_CODE -eq 0 ]]; then
+ echo "lint-status=success" >> $GITHUB_OUTPUT
+ echo "โ
Code linting completed successfully"
+ else
+ echo "lint-status=failure" >> $GITHUB_OUTPUT
+ echo "โ Code linting completed with errors (exit code: $LINT_EXIT_CODE)"
+ fi
+
+ # --------------------------------------------------------------------
+ # Create GitHub Annotations for failures
+ # --------------------------------------------------------------------
+ - name: ๐ Create GitHub Annotations
+ if: always() && steps.run-lint.outputs.lint-status == 'failure'
+ run: |
+ echo "::error title=Lint Failed::Linting issues detected - see job summary for details"
# --------------------------------------------------------------------
# Save golangci-lint binary to cache (on cache miss)
@@ -385,7 +484,10 @@ jobs:
# Summary of golangci-lint results
# --------------------------------------------------------------------
- name: ๐ Job Summary
+ if: always()
run: |
+ LINT_STATUS="${{ steps.run-lint.outputs.lint-status }}"
+
echo "## โจ Code Linting Summary" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "| Linting Details | Status |" >> $GITHUB_STEP_SUMMARY
@@ -394,9 +496,40 @@ jobs:
echo "| **Version** | ${{ steps.golangci-lint-version.outputs.version }} |" >> $GITHUB_STEP_SUMMARY
echo "| **Binary Cache** | ${{ steps.cache-golangci-lint-binary.outputs.cache-hit == 'true' && '๐ Cache Hit' || '๐ฆ Downloaded & Cached' }} |" >> $GITHUB_STEP_SUMMARY
echo "| **Analysis Cache** | ๐พ Enabled |" >> $GITHUB_STEP_SUMMARY
- echo "| **Result** | โ
All checks passed |" >> $GITHUB_STEP_SUMMARY
- echo "" >> $GITHUB_STEP_SUMMARY
- echo "๐ฏ **Code quality standards met - no linting issues found.**" >> $GITHUB_STEP_SUMMARY
+
+ if [[ "$LINT_STATUS" == "success" ]]; then
+ echo "| **Result** | โ
All checks passed |" >> $GITHUB_STEP_SUMMARY
+ echo "" >> $GITHUB_STEP_SUMMARY
+ echo "๐ฏ **Code quality standards met - no linting issues found.**" >> $GITHUB_STEP_SUMMARY
+ else
+ echo "| **Result** | โ Issues detected |" >> $GITHUB_STEP_SUMMARY
+ echo "" >> $GITHUB_STEP_SUMMARY
+
+ # Show failure details if applicable
+ if [[ -f lint-output.log ]]; then
+ echo "### ๐จ Linting Errors" >> $GITHUB_STEP_SUMMARY
+ echo "" >> $GITHUB_STEP_SUMMARY
+ echo "" >> $GITHUB_STEP_SUMMARY
+ echo "Click to expand full output
" >> $GITHUB_STEP_SUMMARY
+ echo "" >> $GITHUB_STEP_SUMMARY
+ echo '```' >> $GITHUB_STEP_SUMMARY
+ head -200 lint-output.log >> $GITHUB_STEP_SUMMARY
+ echo '```' >> $GITHUB_STEP_SUMMARY
+ echo " " >> $GITHUB_STEP_SUMMARY
+ fi
+ fi
+
+ # --------------------------------------------------------------------
+ # Upload lint results
+ # --------------------------------------------------------------------
+ - name: ๐ค Upload lint results
+ if: always()
+ uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
+ with:
+ name: lint-results
+ path: lint-output.log
+ retention-days: 7
+ if-no-files-found: ignore
# --------------------------------------------------------------------
# Collect cache statistics
@@ -426,6 +559,24 @@ jobs:
artifact-path: cache-stats-lint.json
retention-days: 1
+ # --------------------------------------------------------------------
+ # Fail job if lint errors found
+ # --------------------------------------------------------------------
+ - name: ๐จ Fail job if lint errors found
+ if: always() && steps.run-lint.outputs.lint-status == 'failure'
+ run: |
+ echo "โ Lint detected code quality issues"
+ exit 1
+
+ # --------------------------------------------------------------------
+ # Cancel workflow on failure (save CI resources)
+ # --------------------------------------------------------------------
+ - name: ๐จ Cancel workflow on failure
+ if: failure()
+ uses: ./.github/actions/cancel-workflow-on-failure
+ with:
+ reason: "Code linting (golangci-lint) failed"
+
# ----------------------------------------------------------------------------------
# YAML/JSON Format Validation (MAGE-X)
# ----------------------------------------------------------------------------------
@@ -435,6 +586,7 @@ jobs:
runs-on: ${{ inputs.primary-runner }}
permissions:
contents: read
+ actions: write # Required for workflow cancellation on failure
outputs:
yamlfmt-version: ${{ steps.yamlfmt-version.outputs.version }}
steps:
@@ -442,7 +594,7 @@ jobs:
# Checkout code (required for local actions)
# --------------------------------------------------------------------
- name: ๐ฅ Checkout repository
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
# --------------------------------------------------------------------
# Parse environment variables
@@ -523,6 +675,8 @@ jobs:
# Run MAGE-X format:check to validate formatting
# --------------------------------------------------------------------
- name: ๐ Check YAML/JSON formatting with MAGE-X
+ id: run-format-check
+ continue-on-error: true
run: |
echo "๐ Checking YAML/JSON file formatting with MAGE-X format:check..."
echo "๐ Configuration file: .github/.yamlfmt"
@@ -531,50 +685,58 @@ jobs:
GO_MODULE_DIR="${{ env.GO_MODULE_DIR }}"
+ set +e
# Run magex format:check to validate formatting without modifying files
if [ -n "$GO_MODULE_DIR" ]; then
echo "๐ง Running magex format:check from directory: $GO_MODULE_DIR"
- if (cd "$GO_MODULE_DIR" && magex format:check); then
- echo "โ
All YAML/JSON files are properly formatted"
- else
- echo "โ YAML/JSON formatting issues detected"
- echo ""
- echo "๐ง To fix these issues locally, run:"
- echo " cd $GO_MODULE_DIR && magex format:fix"
- echo ""
- echo "๐ yamlfmt Configuration (.github/.yamlfmt):"
- echo " โข Indent style: spaces (2 spaces)"
- echo " โข End of line: LF"
- echo " โข Final newline: required"
- echo " โข Line breaks: preserved where sensible"
- echo " โข Comment padding: 1 space after #"
- exit 1
- fi
+ (cd "$GO_MODULE_DIR" && magex format:check 2>&1 | tee ../format-output.log)
+ FORMAT_EXIT_CODE=${PIPESTATUS[0]}
else
echo "๐ง Running magex format:check from repository root"
- if magex format:check; then
- echo "โ
All YAML/JSON files are properly formatted"
+ magex format:check 2>&1 | tee format-output.log
+ FORMAT_EXIT_CODE=${PIPESTATUS[0]}
+ fi
+ set -e
+
+ echo "format-exit-code=$FORMAT_EXIT_CODE" >> $GITHUB_OUTPUT
+ if [[ $FORMAT_EXIT_CODE -eq 0 ]]; then
+ echo "format-status=success" >> $GITHUB_OUTPUT
+ echo "โ
All YAML/JSON files are properly formatted"
+ else
+ echo "format-status=failure" >> $GITHUB_OUTPUT
+ echo "โ YAML/JSON formatting issues detected"
+ echo ""
+ echo "๐ง To fix these issues locally, run:"
+ if [ -n "$GO_MODULE_DIR" ]; then
+ echo " cd $GO_MODULE_DIR && magex format:fix"
else
- echo "โ YAML/JSON formatting issues detected"
- echo ""
- echo "๐ง To fix these issues locally, run:"
echo " magex format:fix"
- echo ""
- echo "๐ yamlfmt Configuration (.github/.yamlfmt):"
- echo " โข Indent style: spaces (2 spaces)"
- echo " โข End of line: LF"
- echo " โข Final newline: required"
- echo " โข Line breaks: preserved where sensible"
- echo " โข Comment padding: 1 space after #"
- exit 1
fi
+ echo ""
+ echo "๐ yamlfmt Configuration (.github/.yamlfmt):"
+ echo " โข Indent style: spaces (2 spaces)"
+ echo " โข End of line: LF"
+ echo " โข Final newline: required"
+ echo " โข Line breaks: preserved where sensible"
+ echo " โข Comment padding: 1 space after #"
fi
+ # --------------------------------------------------------------------
+ # Create GitHub Annotations for failures
+ # --------------------------------------------------------------------
+ - name: ๐ Create GitHub Annotations
+ if: always() && steps.run-format-check.outputs.format-status == 'failure'
+ run: |
+ echo "::error title=YAML/JSON Format Check Failed::Formatting issues detected - see job summary for details"
+
# --------------------------------------------------------------------
# Job Summary
# --------------------------------------------------------------------
- name: ๐ Job Summary
+ if: always()
run: |
+ FORMAT_STATUS="${{ steps.run-format-check.outputs.format-status }}"
+
echo "## ๐ YAML/JSON Format Validation Summary" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "| Validation Details | Status |" >> $GITHUB_STEP_SUMMARY
@@ -583,7 +745,13 @@ jobs:
echo "| **Version** | ${{ steps.yamlfmt-version.outputs.version }} |" >> $GITHUB_STEP_SUMMARY
echo "| **Configuration** | .github/.yamlfmt |" >> $GITHUB_STEP_SUMMARY
echo "| **Scope** | All .yml, .yaml, and .json files |" >> $GITHUB_STEP_SUMMARY
- echo "| **Result** | โ
All files properly formatted |" >> $GITHUB_STEP_SUMMARY
+
+ if [[ "$FORMAT_STATUS" == "success" ]]; then
+ echo "| **Result** | โ
All files properly formatted |" >> $GITHUB_STEP_SUMMARY
+ else
+ echo "| **Result** | โ Formatting issues detected |" >> $GITHUB_STEP_SUMMARY
+ fi
+
echo "" >> $GITHUB_STEP_SUMMARY
echo "### File Processing Statistics" >> $GITHUB_STEP_SUMMARY
echo "- **Total files processed**: ${{ env.TOTAL_FILES }}" >> $GITHUB_STEP_SUMMARY
@@ -595,4 +763,50 @@ jobs:
echo "- **Line Breaks**: Preserved where sensible" >> $GITHUB_STEP_SUMMARY
echo "- **Comment Padding**: 1 space after #" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
- echo "๐ฏ **All YAML/JSON files meet formatting standards via MAGE-X.**" >> $GITHUB_STEP_SUMMARY
+
+ # Show failure details if applicable
+ if [[ "$FORMAT_STATUS" != "success" ]] && [[ -f format-output.log ]]; then
+ echo "### ๐จ Formatting Issues" >> $GITHUB_STEP_SUMMARY
+ echo "" >> $GITHUB_STEP_SUMMARY
+ echo "" >> $GITHUB_STEP_SUMMARY
+ echo "Click to expand full output
" >> $GITHUB_STEP_SUMMARY
+ echo "" >> $GITHUB_STEP_SUMMARY
+ echo '```' >> $GITHUB_STEP_SUMMARY
+ head -200 format-output.log >> $GITHUB_STEP_SUMMARY
+ echo '```' >> $GITHUB_STEP_SUMMARY
+ echo " " >> $GITHUB_STEP_SUMMARY
+ echo "" >> $GITHUB_STEP_SUMMARY
+ echo "๐ง **To fix these issues locally, run:** \`magex format:fix\`" >> $GITHUB_STEP_SUMMARY
+ else
+ echo "๐ฏ **All YAML/JSON files meet formatting standards via MAGE-X.**" >> $GITHUB_STEP_SUMMARY
+ fi
+
+ # --------------------------------------------------------------------
+ # Upload format check results
+ # --------------------------------------------------------------------
+ - name: ๐ค Upload format check results
+ if: always()
+ uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
+ with:
+ name: format-check-results
+ path: format-output.log
+ retention-days: 7
+ if-no-files-found: ignore
+
+ # --------------------------------------------------------------------
+ # Fail job if formatting issues found
+ # --------------------------------------------------------------------
+ - name: ๐จ Fail job if formatting issues found
+ if: always() && steps.run-format-check.outputs.format-status == 'failure'
+ run: |
+ echo "โ Format check detected YAML/JSON formatting issues"
+ exit 1
+
+ # --------------------------------------------------------------------
+ # Cancel workflow on failure (save CI resources)
+ # --------------------------------------------------------------------
+ - name: ๐จ Cancel workflow on failure
+ if: failure()
+ uses: ./.github/actions/cancel-workflow-on-failure
+ with:
+ reason: "YAML/JSON format validation failed"
diff --git a/.github/workflows/fortress-completion-finalize.yml b/.github/workflows/fortress-completion-finalize.yml
index b610786..c5fba99 100644
--- a/.github/workflows/fortress-completion-finalize.yml
+++ b/.github/workflows/fortress-completion-finalize.yml
@@ -61,7 +61,7 @@ jobs:
# Checkout repository for local actions
# --------------------------------------------------------------------
- name: ๐ฅ Checkout Repository
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
# --------------------------------------------------------------------
# Parse inputs and setup
diff --git a/.github/workflows/fortress-completion-report.yml b/.github/workflows/fortress-completion-report.yml
index b5c2a75..ac2ae9d 100644
--- a/.github/workflows/fortress-completion-report.yml
+++ b/.github/workflows/fortress-completion-report.yml
@@ -23,36 +23,44 @@ on:
default: "skipped"
start-epoch:
description: "Workflow start epoch time"
- required: true
+ required: false
type: string
+ default: "0"
start-time:
description: "Workflow start time"
- required: true
+ required: false
type: string
+ default: "unknown"
setup-result:
description: "Setup job result"
- required: true
+ required: false
type: string
+ default: "skipped"
test-magex-result:
description: "Test MAGE-X job result"
- required: true
+ required: false
type: string
+ default: "skipped"
security-result:
description: "Security job result"
- required: true
+ required: false
type: string
+ default: "skipped"
code-quality-result:
description: "Code quality job result"
- required: true
+ required: false
type: string
+ default: "skipped"
pre-commit-result:
description: "Pre-commit checks job result"
- required: true
+ required: false
type: string
+ default: "skipped"
test-suite-result:
description: "Test suite job result"
- required: true
+ required: false
type: string
+ default: "skipped"
release-result:
description: "Result of the release job"
required: false
@@ -65,8 +73,9 @@ on:
default: "skipped"
test-matrix:
description: "Test matrix JSON"
- required: true
+ required: false
type: string
+ default: "[]"
env-json:
description: "JSON string of environment variables"
required: true
@@ -117,7 +126,7 @@ jobs:
# Checkout repository for local actions
# --------------------------------------------------------------------
- name: ๐ฅ Checkout Repository
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
# --------------------------------------------------------------------
# Parse environment variables
diff --git a/.github/workflows/fortress-completion-statistics.yml b/.github/workflows/fortress-completion-statistics.yml
index ad44028..d63d3bd 100644
--- a/.github/workflows/fortress-completion-statistics.yml
+++ b/.github/workflows/fortress-completion-statistics.yml
@@ -65,7 +65,7 @@ jobs:
# Checkout repository for local actions
# --------------------------------------------------------------------
- name: ๐ฅ Checkout Repository
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
# --------------------------------------------------------------------
# Parse environment variables
diff --git a/.github/workflows/fortress-completion-tests.yml b/.github/workflows/fortress-completion-tests.yml
index 05284ea..e3c2c3b 100644
--- a/.github/workflows/fortress-completion-tests.yml
+++ b/.github/workflows/fortress-completion-tests.yml
@@ -61,7 +61,7 @@ jobs:
# Checkout repository for local actions
# --------------------------------------------------------------------
- name: ๐ฅ Checkout Repository
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
# --------------------------------------------------------------------
# Parse environment variables
diff --git a/.github/workflows/fortress-coverage.yml b/.github/workflows/fortress-coverage.yml
index af69b48..4b94bf0 100644
--- a/.github/workflows/fortress-coverage.yml
+++ b/.github/workflows/fortress-coverage.yml
@@ -156,7 +156,7 @@ jobs:
echo "โ
Branch helper functions created"
- name: ๐ฅ Checkout code
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 0 # Fetch all history including tags for version display
@@ -2355,7 +2355,7 @@ jobs:
done
- name: ๐ฅ Checkout code
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 2 # Need history for codecov to detect changes
diff --git a/.github/workflows/fortress-pre-commit.yml b/.github/workflows/fortress-pre-commit.yml
index cf2c89b..ce011ea 100644
--- a/.github/workflows/fortress-pre-commit.yml
+++ b/.github/workflows/fortress-pre-commit.yml
@@ -54,6 +54,7 @@ jobs:
runs-on: ${{ inputs.primary-runner }}
permissions:
contents: read
+ actions: write # Required for workflow cancellation on failure
outputs:
pre-commit-version: ${{ steps.pre-commit-version.outputs.version }}
checks-executed: ${{ steps.run-checks.outputs.executed }}
@@ -62,7 +63,7 @@ jobs:
# Checkout code (full checkout to ensure local actions are available)
# --------------------------------------------------------------------
- name: ๐ฅ Checkout code
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 0 # Fetch full history to enable file change detection for all commit ranges
@@ -884,3 +885,12 @@ jobs:
artifact-name: cache-stats-pre-commit
artifact-path: cache-stats-pre-commit.json
retention-days: 1
+
+ # --------------------------------------------------------------------
+ # Cancel workflow on failure (save CI resources)
+ # --------------------------------------------------------------------
+ - name: ๐จ Cancel workflow on failure
+ if: failure()
+ uses: ./.github/actions/cancel-workflow-on-failure
+ with:
+ reason: "Pre-commit checks failed"
diff --git a/.github/workflows/fortress-release.yml b/.github/workflows/fortress-release.yml
index 45fce28..4de6864 100644
--- a/.github/workflows/fortress-release.yml
+++ b/.github/workflows/fortress-release.yml
@@ -61,7 +61,7 @@ jobs:
# Checkout code and set up Go environment
# --------------------------------------------------------------------
- name: ๐ฅ Checkout code
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 0 # Required for changelog generation
token: ${{ secrets.github-token }}
diff --git a/.github/workflows/fortress-security-scans.yml b/.github/workflows/fortress-security-scans.yml
index 787b2bd..e88234a 100644
--- a/.github/workflows/fortress-security-scans.yml
+++ b/.github/workflows/fortress-security-scans.yml
@@ -71,12 +71,13 @@ jobs:
if: ${{ inputs.enable-nancy }}
permissions:
contents: read
+ actions: write # Required for workflow cancellation on failure
steps:
# --------------------------------------------------------------------
# Checkout code (required for local actions)
# --------------------------------------------------------------------
- name: ๐ฅ Checkout code
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
# --------------------------------------------------------------------
# Parse environment variables
@@ -130,25 +131,56 @@ jobs:
echo "โ
Module list generated successfully"
+ # --------------------------------------------------------------------
+ # Install Nancy
+ # --------------------------------------------------------------------
+ - name: ๐ฅ Install Nancy
+ run: |
+ echo "๐ฅ Installing nancy version ${{ env.NANCY_VERSION }}..."
+ go install github.com/sonatype-nexus-community/nancy@${{ env.NANCY_VERSION }}
+ echo "โ
Nancy installed successfully"
+
# --------------------------------------------------------------------
# Run Nancy to check for vulnerabilities
# --------------------------------------------------------------------
- name: ๐ Ask Nancy
- uses: sonatype-nexus-community/nancy-github-action@726e338312e68ecdd4b4195765f174d3b3ce1533 # v1.0.3
- continue-on-error: false
+ id: run-nancy
+ continue-on-error: true
env:
OSSI_USERNAME: ${{ secrets.ossi-username }}
OSSI_TOKEN: ${{ secrets.ossi-token }}
- with:
- githubToken: ${{ secrets.github-token }} # โ prevents rate-limit 403
- nancyVersion: ${{ env.NANCY_VERSION }}
- nancyCommand: sleuth --loud --exclude-vulnerability ${{ env.NANCY_EXCLUDES }}
+ run: |
+ echo "๐ Running Nancy security scan..."
+ set +e
+ nancy sleuth --loud --exclude-vulnerability ${{ env.NANCY_EXCLUDES }} < go.list 2>&1 | tee nancy-output.log
+ NANCY_EXIT_CODE=${PIPESTATUS[0]}
+ set -e
+
+ echo "nancy-exit-code=$NANCY_EXIT_CODE" >> $GITHUB_OUTPUT
+ if [[ $NANCY_EXIT_CODE -eq 0 ]]; then
+ echo "nancy-status=success" >> $GITHUB_OUTPUT
+ echo "โ
Nancy scan completed - no vulnerabilities found"
+ else
+ echo "nancy-status=failure" >> $GITHUB_OUTPUT
+ echo "โ Nancy scan completed - vulnerabilities detected (exit code: $NANCY_EXIT_CODE)"
+ fi
+
+ # --------------------------------------------------------------------
+ # Create GitHub Annotations for failures
+ # --------------------------------------------------------------------
+ - name: ๐ Create GitHub Annotations
+ if: always() && steps.run-nancy.outputs.nancy-status == 'failure'
+ run: |
+ echo "::error title=Nancy Security Scan Failed::Vulnerabilities detected in Go dependencies - see job summary for details"
# --------------------------------------------------------------------
# Summary of Nancy results
# --------------------------------------------------------------------
- name: ๐ Job Summary
+ if: always()
run: |
+ NANCY_STATUS="${{ steps.run-nancy.outputs.nancy-status }}"
+
echo "## ๐ก๏ธ Nancy Security Scan Summary" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "| Scan Details | Status |" >> $GITHUB_STEP_SUMMARY
@@ -157,12 +189,44 @@ jobs:
echo "| **Mode** | Loud mode with exclusions |" >> $GITHUB_STEP_SUMMARY
echo "| **Scope** | All Go modules |" >> $GITHUB_STEP_SUMMARY
echo "| **Version** | ${{ env.NANCY_VERSION }} |" >> $GITHUB_STEP_SUMMARY
- echo "| **Result** | โ
No vulnerabilities found |" >> $GITHUB_STEP_SUMMARY
+
+ if [[ "$NANCY_STATUS" == "success" ]]; then
+ echo "| **Result** | โ
No vulnerabilities found |" >> $GITHUB_STEP_SUMMARY
+ else
+ echo "| **Result** | โ Vulnerabilities detected |" >> $GITHUB_STEP_SUMMARY
+ fi
+
echo "" >> $GITHUB_STEP_SUMMARY
echo "### ๐ซ Excluded Vulnerabilities" >> $GITHUB_STEP_SUMMARY
echo "The following vulnerabilities were excluded from the scan:" >> $GITHUB_STEP_SUMMARY
echo "${{ env.NANCY_EXCLUDES }}" >> $GITHUB_STEP_SUMMARY
+ # Show failure details if applicable
+ if [[ "$NANCY_STATUS" != "success" ]] && [[ -f nancy-output.log ]]; then
+ echo "" >> $GITHUB_STEP_SUMMARY
+ echo "### ๐จ Vulnerability Details" >> $GITHUB_STEP_SUMMARY
+ echo "" >> $GITHUB_STEP_SUMMARY
+ echo "" >> $GITHUB_STEP_SUMMARY
+ echo "Click to expand full scan output
" >> $GITHUB_STEP_SUMMARY
+ echo "" >> $GITHUB_STEP_SUMMARY
+ echo '```' >> $GITHUB_STEP_SUMMARY
+ head -200 nancy-output.log >> $GITHUB_STEP_SUMMARY
+ echo '```' >> $GITHUB_STEP_SUMMARY
+ echo " " >> $GITHUB_STEP_SUMMARY
+ fi
+
+ # --------------------------------------------------------------------
+ # Upload Nancy scan results
+ # --------------------------------------------------------------------
+ - name: ๐ค Upload Nancy scan results
+ if: always()
+ uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
+ with:
+ name: nancy-scan-results
+ path: nancy-output.log
+ retention-days: 7
+ if-no-files-found: ignore
+
# --------------------------------------------------------------------
# Collect cache statistics
# --------------------------------------------------------------------
@@ -186,6 +250,24 @@ jobs:
artifact-name: cache-stats-security-nancy
artifact-path: cache-stats-nancy-security.json
+ # --------------------------------------------------------------------
+ # Fail job if vulnerabilities found
+ # --------------------------------------------------------------------
+ - name: ๐จ Fail job if vulnerabilities found
+ if: always() && steps.run-nancy.outputs.nancy-status == 'failure'
+ run: |
+ echo "โ Nancy detected vulnerabilities in dependencies"
+ exit 1
+
+ # --------------------------------------------------------------------
+ # Cancel workflow on failure (save CI resources)
+ # --------------------------------------------------------------------
+ - name: ๐จ Cancel workflow on failure
+ if: failure()
+ uses: ./.github/actions/cancel-workflow-on-failure
+ with:
+ reason: "Nancy dependency security check failed"
+
# ----------------------------------------------------------------------------------
# Govulncheck (Vulnerability Checks)
# ----------------------------------------------------------------------------------
@@ -195,12 +277,13 @@ jobs:
if: ${{ inputs.enable-govulncheck }}
permissions:
contents: read
+ actions: write # Required for workflow cancellation on failure
steps:
# --------------------------------------------------------------------
# Checkout code (required for local actions)
# --------------------------------------------------------------------
- name: ๐ฅ Checkout code
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
# --------------------------------------------------------------------
# Parse environment variables
@@ -288,6 +371,8 @@ jobs:
# Run govulncheck
# --------------------------------------------------------------------
- name: ๐ Run govulncheck
+ id: run-govulncheck
+ continue-on-error: true
run: |
echo "๐ Running vulnerability analysis..."
GO_MODULE_DIR="${{ env.GO_MODULE_DIR }}"
@@ -297,25 +382,48 @@ jobs:
echo "๐ซ CVE exclusions configured: $MAGE_X_CVE_EXCLUDES"
fi
+ set +e
if [ "$ENABLE_MULTI_MODULE_TESTING" == "true" ]; then
echo "๐ง Multi-module enabled - running magex deps:audit from repository root"
echo "๐ฆ magex will discover all Go modules"
- magex deps:audit
+ magex deps:audit 2>&1 | tee govulncheck-output.log
+ GOVULN_EXIT_CODE=${PIPESTATUS[0]}
elif [ -n "$GO_MODULE_DIR" ]; then
echo "๐ง Running magex deps:audit from directory: $GO_MODULE_DIR"
- (cd "$GO_MODULE_DIR" && magex deps:audit)
+ (cd "$GO_MODULE_DIR" && magex deps:audit 2>&1 | tee ../govulncheck-output.log)
+ GOVULN_EXIT_CODE=${PIPESTATUS[0]}
else
echo "๐ง Running magex deps:audit from repository root"
- magex deps:audit
+ magex deps:audit 2>&1 | tee govulncheck-output.log
+ GOVULN_EXIT_CODE=${PIPESTATUS[0]}
+ fi
+ set -e
+
+ echo "govuln-exit-code=$GOVULN_EXIT_CODE" >> $GITHUB_OUTPUT
+ if [[ $GOVULN_EXIT_CODE -eq 0 ]]; then
+ echo "govuln-status=success" >> $GITHUB_OUTPUT
+ echo "โ
Vulnerability scan completed - no vulnerabilities found"
+ else
+ echo "govuln-status=failure" >> $GITHUB_OUTPUT
+ echo "โ Vulnerability scan completed - vulnerabilities detected (exit code: $GOVULN_EXIT_CODE)"
fi
- echo "โ
Vulnerability scan completed"
+ # --------------------------------------------------------------------
+ # Create GitHub Annotations for failures
+ # --------------------------------------------------------------------
+ - name: ๐ Create GitHub Annotations
+ if: always() && steps.run-govulncheck.outputs.govuln-status == 'failure'
+ run: |
+ echo "::error title=Govulncheck Failed::Go vulnerabilities detected - see job summary for details"
# --------------------------------------------------------------------
# Summary of govulncheck results
# --------------------------------------------------------------------
- name: ๐ Job Summary
+ if: always()
run: |
+ GOVULN_STATUS="${{ steps.run-govulncheck.outputs.govuln-status }}"
+
echo "## ๐ govulncheck Summary" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "| Analysis Details | Status |" >> $GITHUB_STEP_SUMMARY
@@ -323,7 +431,13 @@ jobs:
echo "| **Tool** | govulncheck (Official Go Security Tool) |" >> $GITHUB_STEP_SUMMARY
echo "| **Installation** | $( [[ '${{ steps.govuln-cache.outputs.cache-hit }}' == 'true' ]] && echo '๐พ From cache' || echo '๐ฅ Fresh install' ) |" >> $GITHUB_STEP_SUMMARY
echo "| **Scope** | All packages in module |" >> $GITHUB_STEP_SUMMARY
- echo "| **Result** | โ
No vulnerabilities detected |" >> $GITHUB_STEP_SUMMARY
+
+ if [[ "$GOVULN_STATUS" == "success" ]]; then
+ echo "| **Result** | โ
No vulnerabilities detected |" >> $GITHUB_STEP_SUMMARY
+ else
+ echo "| **Result** | โ Vulnerabilities detected |" >> $GITHUB_STEP_SUMMARY
+ fi
+
echo "| **Version** | ${{ env.GOVULNCHECK_VERSION }} |" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
@@ -335,7 +449,32 @@ jobs:
echo "" >> $GITHUB_STEP_SUMMARY
fi
- echo "๐ฏ **Analysis completed successfully with no security issues found.**" >> $GITHUB_STEP_SUMMARY
+ # Show failure details if applicable
+ if [[ "$GOVULN_STATUS" != "success" ]] && [[ -f govulncheck-output.log ]]; then
+ echo "### ๐จ Vulnerability Details" >> $GITHUB_STEP_SUMMARY
+ echo "" >> $GITHUB_STEP_SUMMARY
+ echo "" >> $GITHUB_STEP_SUMMARY
+ echo "Click to expand full scan output
" >> $GITHUB_STEP_SUMMARY
+ echo "" >> $GITHUB_STEP_SUMMARY
+ echo '```' >> $GITHUB_STEP_SUMMARY
+ head -200 govulncheck-output.log >> $GITHUB_STEP_SUMMARY
+ echo '```' >> $GITHUB_STEP_SUMMARY
+ echo " " >> $GITHUB_STEP_SUMMARY
+ else
+ echo "๐ฏ **Analysis completed successfully with no security issues found.**" >> $GITHUB_STEP_SUMMARY
+ fi
+
+ # --------------------------------------------------------------------
+ # Upload govulncheck results
+ # --------------------------------------------------------------------
+ - name: ๐ค Upload govulncheck results
+ if: always()
+ uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
+ with:
+ name: govulncheck-scan-results
+ path: govulncheck-output.log
+ retention-days: 7
+ if-no-files-found: ignore
# --------------------------------------------------------------------
# Collect cache statistics
@@ -360,6 +499,24 @@ jobs:
artifact-name: cache-stats-security-govulncheck
artifact-path: cache-stats-govulncheck-security.json
+ # --------------------------------------------------------------------
+ # Fail job if vulnerabilities found
+ # --------------------------------------------------------------------
+ - name: ๐จ Fail job if vulnerabilities found
+ if: always() && steps.run-govulncheck.outputs.govuln-status == 'failure'
+ run: |
+ echo "โ Govulncheck detected vulnerabilities in dependencies"
+ exit 1
+
+ # --------------------------------------------------------------------
+ # Cancel workflow on failure (save CI resources)
+ # --------------------------------------------------------------------
+ - name: ๐จ Cancel workflow on failure
+ if: failure()
+ uses: ./.github/actions/cancel-workflow-on-failure
+ with:
+ reason: "Govulncheck vulnerability scan failed"
+
# ----------------------------------------------------------------------------------
# Gitleaks (Secret Scanning)
# ----------------------------------------------------------------------------------
@@ -369,12 +526,13 @@ jobs:
if: ${{ inputs.enable-gitleaks }}
permissions:
contents: read
+ actions: write # Required for workflow cancellation on failure
steps:
# --------------------------------------------------------------------
# Checkout code (required for local actions)
# --------------------------------------------------------------------
- name: ๐ฅ Checkout code
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 0 # Fetch all history so Gitleaks can scan commits
@@ -419,7 +577,9 @@ jobs:
fi
- name: ๐ Run gitleaks scan
+ id: run-gitleaks
if: steps.repo-check.outputs.is_same_repo == 'true'
+ continue-on-error: true
uses: gitleaks/gitleaks-action@ff98106e4c7b2bc287b24eaf42907196329070c7 # v2.3.9
env:
GITHUB_TOKEN: ${{ secrets.github-token }}
@@ -431,9 +591,19 @@ jobs:
GITLEAKS_VERSION: ${{ env.GITLEAKS_VERSION }}
GITLEAKS_CONFIG: ${{ env.GITLEAKS_CONFIG_FILE }}
+ # --------------------------------------------------------------------
+ # Create GitHub Annotations for failures
+ # --------------------------------------------------------------------
+ - name: ๐ Create GitHub Annotations
+ if: always() && steps.repo-check.outputs.is_same_repo == 'true' && steps.run-gitleaks.outcome == 'failure'
+ run: |
+ echo "::error title=Gitleaks Secret Scan Failed::Secrets detected in repository - see job summary for details"
+
- name: ๐ Job Summary
- if: steps.repo-check.outputs.is_same_repo == 'true'
+ if: always() && steps.repo-check.outputs.is_same_repo == 'true'
run: |
+ GITLEAKS_OUTCOME="${{ steps.run-gitleaks.outcome }}"
+
echo "## ๐ต๏ธ Gitleaks Secret Scan Summary" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "| Scan Details | Status |" >> $GITHUB_STEP_SUMMARY
@@ -442,9 +612,20 @@ jobs:
echo "| **Version** | ${{ env.GITLEAKS_VERSION }} |" >> $GITHUB_STEP_SUMMARY
echo "| **Scope** | All commits and files |" >> $GITHUB_STEP_SUMMARY
echo "| **Config** | $([ -n "${{ env.GITLEAKS_CONFIG_FILE }}" ] && echo "Custom: \`${{ env.GITLEAKS_CONFIG_FILE }}\`" || echo "Default (built-in rules)") |" >> $GITHUB_STEP_SUMMARY
- echo "| **Result** | โ
No secrets detected (see logs for details) |" >> $GITHUB_STEP_SUMMARY
- echo "" >> $GITHUB_STEP_SUMMARY
- echo "๐ฏ **Secret scan completed successfully.**" >> $GITHUB_STEP_SUMMARY
+
+ if [[ "$GITLEAKS_OUTCOME" == "success" ]]; then
+ echo "| **Result** | โ
No secrets detected |" >> $GITHUB_STEP_SUMMARY
+ echo "" >> $GITHUB_STEP_SUMMARY
+ echo "๐ฏ **Secret scan completed successfully.**" >> $GITHUB_STEP_SUMMARY
+ else
+ echo "| **Result** | โ Secrets detected |" >> $GITHUB_STEP_SUMMARY
+ echo "" >> $GITHUB_STEP_SUMMARY
+ echo "### ๐จ Action Required" >> $GITHUB_STEP_SUMMARY
+ echo "" >> $GITHUB_STEP_SUMMARY
+ echo "Gitleaks has detected secrets in the repository. Please review the scan output and remove any exposed secrets." >> $GITHUB_STEP_SUMMARY
+ echo "" >> $GITHUB_STEP_SUMMARY
+ echo "**Note:** The detailed findings are available in the Gitleaks-generated summary above this section." >> $GITHUB_STEP_SUMMARY
+ fi
- name: ๐ Fork Security Notice
if: steps.repo-check.outputs.is_same_repo == 'false'
@@ -459,3 +640,21 @@ jobs:
echo "| **Result** | โ ๏ธ Skipped for security (fork cannot access secrets) |" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "๐ **Secret scanning was skipped because this PR comes from a fork. This is a security feature to prevent secret exposure.**" >> $GITHUB_STEP_SUMMARY
+
+ # --------------------------------------------------------------------
+ # Fail job if secrets found
+ # --------------------------------------------------------------------
+ - name: ๐จ Fail job if secrets found
+ if: always() && steps.repo-check.outputs.is_same_repo == 'true' && steps.run-gitleaks.outcome == 'failure'
+ run: |
+ echo "โ Gitleaks detected secrets in the repository"
+ exit 1
+
+ # --------------------------------------------------------------------
+ # Cancel workflow on failure (save CI resources)
+ # --------------------------------------------------------------------
+ - name: ๐จ Cancel workflow on failure
+ if: failure()
+ uses: ./.github/actions/cancel-workflow-on-failure
+ with:
+ reason: "Gitleaks secret scan failed"
diff --git a/.github/workflows/fortress-setup-config.yml b/.github/workflows/fortress-setup-config.yml
index d2e2f8b..f4dc84b 100644
--- a/.github/workflows/fortress-setup-config.yml
+++ b/.github/workflows/fortress-setup-config.yml
@@ -308,7 +308,7 @@ jobs:
# Checkout code (sparse checkout)
# --------------------------------------------------------------------
- name: ๐ฅ Checkout (sparse)
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
sparse-checkout: |
.mage.yaml
diff --git a/.github/workflows/fortress-test-fuzz.yml b/.github/workflows/fortress-test-fuzz.yml
index cfbadff..57fa96d 100644
--- a/.github/workflows/fortress-test-fuzz.yml
+++ b/.github/workflows/fortress-test-fuzz.yml
@@ -58,6 +58,7 @@ jobs:
timeout-minutes: 15 # Fuzz tests have shorter timeout
permissions:
contents: read # Read repository content for testing
+ actions: write # Required for workflow cancellation on failure
runs-on: ${{ inputs.primary-runner }}
steps:
@@ -65,7 +66,7 @@ jobs:
# Checkout code (required for local actions)
# --------------------------------------------------------------------
- name: ๐ฅ Checkout code
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
# --------------------------------------------------------------------
# Parse environment variables
@@ -221,27 +222,6 @@ jobs:
fi
fi
- # --------------------------------------------------------------------
- # Generate fuzz test statistics using composite action
- # --------------------------------------------------------------------
- - name: ๐ Calculate fuzz test statistics
- id: fuzz-summary
- if: always()
- uses: ./.github/actions/test-statistics
- with:
- matrix-name: "Fuzz Tests (${{ inputs.primary-runner }})"
- matrix-os: ${{ inputs.primary-runner }}
- matrix-go-version: ${{ inputs.go-primary-version }}
- test-exit-code: ${{ steps.run-fuzz-tests.outputs.fuzz-exit-code || '0' }}
- output-mode: "FULL"
- job-status: ${{ job.status }}
- test-start-time: ${{ steps.fuzz-timer.outputs.fuzz-start || '0' }}
- race-detection-enabled: "false"
- code-coverage-enabled: "false"
- fuzz-run: "true"
- failures-file: "fuzz-failures.txt"
- output-file: "fuzz-output.log"
-
# --------------------------------------------------------------------
# Collect performance cache statistics
# --------------------------------------------------------------------
@@ -280,3 +260,12 @@ jobs:
fuzz-output.log
retention-days: 1
if-no-files-found: ignore
+
+ # --------------------------------------------------------------------
+ # Cancel workflow on failure (save CI resources)
+ # --------------------------------------------------------------------
+ - name: ๐จ Cancel workflow on failure
+ if: failure()
+ uses: ./.github/actions/cancel-workflow-on-failure
+ with:
+ reason: "Fuzz tests failed"
diff --git a/.github/workflows/fortress-test-magex.yml b/.github/workflows/fortress-test-magex.yml
index fb4c4dd..b68a906 100644
--- a/.github/workflows/fortress-test-magex.yml
+++ b/.github/workflows/fortress-test-magex.yml
@@ -53,14 +53,14 @@ jobs:
# Full checkout when using local build (needs cmd/magex directory)
- name: ๐ฅ Checkout (full - local build)
if: env.MAGE_X_USE_LOCAL == 'true'
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 0
# Sparse checkout when using remote build (optimization)
- name: ๐ฅ Checkout (sparse - remote build)
if: env.MAGE_X_USE_LOCAL == 'false'
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 0 # Required for sparse checkout
sparse-checkout: |
diff --git a/.github/workflows/fortress-test-matrix.yml b/.github/workflows/fortress-test-matrix.yml
index 7552acc..eb8414b 100644
--- a/.github/workflows/fortress-test-matrix.yml
+++ b/.github/workflows/fortress-test-matrix.yml
@@ -110,6 +110,7 @@ jobs:
timeout-minutes: 30 # Prevent hung tests
permissions:
contents: read # Read repository content for testing
+ actions: write # Required for workflow cancellation on failure
strategy:
fail-fast: true
matrix: ${{ fromJSON(inputs.test-matrix) }}
@@ -128,7 +129,7 @@ jobs:
# Checkout code (required for local actions)
# --------------------------------------------------------------------
- name: ๐ฅ Checkout code
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
# --------------------------------------------------------------------
# Parse environment variables
@@ -442,3 +443,12 @@ jobs:
name: coverage-data
path: coverage.txt
retention-days: 1
+
+ # --------------------------------------------------------------------
+ # Cancel workflow on failure (save CI resources)
+ # --------------------------------------------------------------------
+ - name: ๐จ Cancel workflow on failure
+ if: failure()
+ uses: ./.github/actions/cancel-workflow-on-failure
+ with:
+ reason: "Test matrix failed (${{ matrix.name }})"
diff --git a/.github/workflows/fortress-test-suite.yml b/.github/workflows/fortress-test-suite.yml
index 5e02fd6..0d8ed55 100644
--- a/.github/workflows/fortress-test-suite.yml
+++ b/.github/workflows/fortress-test-suite.yml
@@ -124,7 +124,7 @@ jobs:
if: inputs.go-tests-enabled == 'true'
permissions:
contents: read
- actions: read
+ actions: write # Required for workflow cancellation on failure
uses: ./.github/workflows/fortress-test-matrix.yml
with:
env-json: ${{ inputs.env-json }}
@@ -152,7 +152,7 @@ jobs:
if: inputs.go-tests-enabled == 'true' && inputs.fuzz-testing-enabled == 'true'
permissions:
contents: read
- actions: read
+ actions: write # Required for workflow cancellation on failure
uses: ./.github/workflows/fortress-test-fuzz.yml
with:
env-json: ${{ inputs.env-json }}
diff --git a/.github/workflows/fortress-test-validation.yml b/.github/workflows/fortress-test-validation.yml
index 527a787..49c616b 100644
--- a/.github/workflows/fortress-test-validation.yml
+++ b/.github/workflows/fortress-test-validation.yml
@@ -55,7 +55,7 @@ jobs:
# Checkout code (required for local actions)
# --------------------------------------------------------------------
- name: ๐ฅ Checkout code
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
# --------------------------------------------------------------------
# Parse environment variables
diff --git a/.github/workflows/fortress-warm-cache.yml b/.github/workflows/fortress-warm-cache.yml
index c75e391..385aaf6 100644
--- a/.github/workflows/fortress-warm-cache.yml
+++ b/.github/workflows/fortress-warm-cache.yml
@@ -107,13 +107,13 @@ jobs:
# --------------------------------------------------------------------
- name: ๐ฅ Checkout code (full - multi-module)
if: steps.extract.outputs.enable_multi_module == 'true'
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- name: ๐ฅ Checkout code (sparse - single module)
if: steps.extract.outputs.enable_multi_module != 'true'
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
sparse-checkout: |
diff --git a/.github/workflows/fortress.yml b/.github/workflows/fortress.yml
index c4ce7ab..0a53313 100644
--- a/.github/workflows/fortress.yml
+++ b/.github/workflows/fortress.yml
@@ -1,7 +1,7 @@
# ------------------------------------------------------------------------------------
# ๐ฐ GoFortress - Enterprise-grade CI/CD fortress for Go applications
#
-# Version: 1.3.0 | Released: 2025-12-14
+# Version: 1.4.0 | Released: 2026-01-16
#
# Built Strong. Tested Harder.
#
@@ -18,7 +18,7 @@
# ๐ Release Citadel: Automated deployments with GoReleaser and GoDocs
#
# Maintainer: @mrz1836
-# Repository: https://github.com/mrz1836/go-fortress
+# Repository: https://github.com/bsv-blockchain/go-wire
#
# Copyright 2025 @mrz1836
# SPDX-License-Identifier: MIT
@@ -91,7 +91,7 @@ jobs:
# Check out code to access env file
# --------------------------------------------------------------------
- name: ๐ฅ Checkout code (sparse)
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
sparse-checkout: |
.github/.env.base
@@ -170,6 +170,7 @@ jobs:
needs.setup.outputs.is-fork-pr != 'true'
permissions:
contents: read # Read repository content for security scanning
+ actions: write # Required for workflow cancellation on failure
uses: ./.github/workflows/fortress-security-scans.yml
with:
env-json: ${{ needs.load-env.outputs.env-json }}
@@ -198,6 +199,7 @@ jobs:
needs.setup.outputs.pre-commit-enabled == 'true'
permissions:
contents: read # Read repository content for pre-commit checks
+ actions: write # Required for workflow cancellation on failure
uses: ./.github/workflows/fortress-pre-commit.yml
with:
env-json: ${{ needs.load-env.outputs.env-json }}
@@ -218,6 +220,7 @@ jobs:
(needs.warm-cache.result == 'success' || needs.warm-cache.result == 'skipped')
permissions:
contents: read # Read repository content for code quality checks
+ actions: write # Required for workflow cancellation on failure
uses: ./.github/workflows/fortress-code-quality.yml
with:
env-json: ${{ needs.load-env.outputs.env-json }}
@@ -248,7 +251,7 @@ jobs:
pages: write # Required: Coverage workflow needs to deploy to GitHub Pages
id-token: write # Required: Coverage workflow needs GitHub Pages authentication
statuses: write # Required: Coverage workflow needs to create commit status checks
- actions: read # Required: Test validation workflow needs to access artifacts
+ actions: write # Required: Manage/cancel child test workflows (test matrix & fuzz tests); artifact access only needs actions: read
uses: ./.github/workflows/fortress-test-suite.yml
with:
code-coverage-enabled: ${{ needs.setup.outputs.code-coverage-enabled }}
@@ -448,9 +451,10 @@ jobs:
name: ๐ Workflow Completion Report
if: |
always() &&
- needs.setup.outputs.completion-report-enabled == 'true' &&
- !contains(fromJSON('["failure", "cancelled"]'), needs.setup.result) &&
- !contains(fromJSON('["failure", "cancelled"]'), needs.test-magex.result)
+ needs.load-env.result == 'success' &&
+ needs.setup.result == 'success' &&
+ needs.test-magex.result == 'success' &&
+ needs.setup.outputs.completion-report-enabled == 'true'
needs: [load-env, setup, test-magex, pre-commit, security, code-quality, test-suite, benchmarks, release, status-check]
permissions:
contents: read # Read repository content for completion report
diff --git a/.github/workflows/pull-request-management-fork.yml b/.github/workflows/pull-request-management-fork.yml
index 6e031d4..9e13321 100644
--- a/.github/workflows/pull-request-management-fork.yml
+++ b/.github/workflows/pull-request-management-fork.yml
@@ -140,7 +140,7 @@ jobs:
# codeql:ignore GH001
# checkov:skip=CKV_GHA_3:Base branch checkout is intentional and safe
- name: ๐ฅ Checkout base repo (sparse)
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
# ๐ CRITICAL SECURITY CONTROL: Base Branch Checkout Only
diff --git a/.github/workflows/pull-request-management.yml b/.github/workflows/pull-request-management.yml
index 55bd0ac..0d466a3 100644
--- a/.github/workflows/pull-request-management.yml
+++ b/.github/workflows/pull-request-management.yml
@@ -69,7 +69,7 @@ jobs:
# Check out code to access env file
# --------------------------------------------------------------------
- name: ๐ฅ Checkout code (sparse)
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
sparse-checkout: |
.github/.env.base
diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml
index a9dabe4..6f58698 100644
--- a/.github/workflows/scorecard.yml
+++ b/.github/workflows/scorecard.yml
@@ -38,7 +38,7 @@ jobs:
steps:
- name: "Checkout code"
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
diff --git a/.github/workflows/stale-check.yml b/.github/workflows/stale-check.yml
index af1fc0e..fd70c68 100644
--- a/.github/workflows/stale-check.yml
+++ b/.github/workflows/stale-check.yml
@@ -53,7 +53,7 @@ jobs:
# Check out code to access env file
# --------------------------------------------------------------------
- name: ๐ฅ Checkout code (sparse)
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
sparse-checkout: |
.github/.env.base
diff --git a/.github/workflows/sync-labels.yml b/.github/workflows/sync-labels.yml
index 80a50da..92786eb 100644
--- a/.github/workflows/sync-labels.yml
+++ b/.github/workflows/sync-labels.yml
@@ -66,7 +66,7 @@ jobs:
# Check out code to access env file
# --------------------------------------------------------------------
- name: ๐ฅ Checkout code (sparse)
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
sparse-checkout: |
.github/.env.base
@@ -136,7 +136,7 @@ jobs:
# Checkout repository
# --------------------------------------------------------------------
- name: ๐ฅ Checkout code
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 2 # Fetch enough history to check parent commits