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///\\>} + + # 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