From e660a0438f8364130d9ca173b139d469a69d7e89 Mon Sep 17 00:00:00 2001 From: "Mr. Z" Date: Thu, 20 Nov 2025 16:49:57 -0500 Subject: [PATCH] sync: update 8 files from source repository --- .github/.env.base | 15 +- .github/workflows/auto-merge-on-approval.yml | 28 + .github/workflows/codeql-analysis.yml | 6 +- .github/workflows/dependabot-auto-merge.yml | 517 +++++++++++++++++-- .github/workflows/fortress-code-quality.yml | 64 ++- .github/workflows/fortress-pre-commit.yml | 120 ++++- .github/workflows/fortress.yml | 2 +- .github/workflows/scorecard.yml | 2 +- 8 files changed, 698 insertions(+), 56 deletions(-) diff --git a/.github/.env.base b/.github/.env.base index 350d110..0df31a5 100644 --- a/.github/.env.base +++ b/.github/.env.base @@ -232,12 +232,12 @@ REDIS_CACHE_FORCE_PULL=false # Force pull Redis images even when cache # đŸĒ„ MAGE-X CONFIGURATION # ================================================================================================ -MAGE_X_VERSION=v1.7.15 # https://github.com/mrz1836/mage-x/releases +MAGE_X_VERSION=v1.7.16 # https://github.com/mrz1836/mage-x/releases MAGE_X_USE_LOCAL=false # Use local version for development MAGE_X_AUTO_DISCOVER_BUILD_TAGS=true # Enable auto-discovery of build tags MAGE_X_AUTO_DISCOVER_BUILD_TAGS_EXCLUDE=race,custom # Comma-separated list of tags to exclude MAGE_X_FORMAT_EXCLUDE_PATHS=vendor,node_modules,.git,.idea # Format exclusion paths (comma-separated directories to exclude from formatting) -MAGE_X_GITLEAKS_VERSION=8.29.0 # https://github.com/gitleaks/gitleaks/releases +MAGE_X_GITLEAKS_VERSION=8.29.1 # https://github.com/gitleaks/gitleaks/releases MAGE_X_GOFUMPT_VERSION=v0.9.2 # https://github.com/mvdan/gofumpt/releases MAGE_X_GOLANGCI_LINT_VERSION=v2.6.2 # https://github.com/golangci/golangci-lint/releases MAGE_X_GORELEASER_VERSION=v2.12.7 # https://github.com/goreleaser/goreleaser/releases @@ -291,7 +291,7 @@ NANCY_EXCLUDES=CVE-2024-38513,CVE-2023-45142 # Github Secret(s): OSSI_USERNAME and OSSI_TOKEN # Security Tools -GITLEAKS_VERSION=8.29.0 # https://github.com/gitleaks/gitleaks/releases +GITLEAKS_VERSION=8.29.1 # https://github.com/gitleaks/gitleaks/releases GOVULNCHECK_VERSION=v1.1.4 # https://pkg.go.dev/golang.org/x/vuln NANCY_VERSION=v1.0.51 # https://github.com/sonatype-nexus-community/nancy/releases @@ -300,7 +300,7 @@ NANCY_VERSION=v1.0.51 # https://github.com/sonatype-nexus-commu # ================================================================================================ # Pre-Commit System -GO_PRE_COMMIT_VERSION=v1.4.2 # https://github.com/mrz1836/go-pre-commit/releases +GO_PRE_COMMIT_VERSION=v1.4.3 # https://github.com/mrz1836/go-pre-commit/releases GO_PRE_COMMIT_USE_LOCAL=false # Use local version for development # System Settings @@ -312,6 +312,7 @@ GO_PRE_COMMIT_PARALLEL_WORKERS=2 GO_PRE_COMMIT_LOG_LEVEL=debug GO_PRE_COMMIT_MAX_FILE_SIZE_MB=10 GO_PRE_COMMIT_MAX_FILES_OPEN=100 +GO_PRE_COMMIT_DEBUG=false # Enable verbose debug output for tool caching and locations # File Detection Strategy for CI # true = Check all repository files (comprehensive but slower) @@ -322,7 +323,7 @@ GO_PRE_COMMIT_ALL_FILES=true GO_PRE_COMMIT_GOLANGCI_LINT_VERSION=v2.6.2 # https://github.com/golangci/golangci-lint/releases GO_PRE_COMMIT_FUMPT_VERSION=v0.9.2 # https://github.com/mvdan/gofumpt/releases GO_PRE_COMMIT_GOIMPORTS_VERSION=latest # https://github.com/golang/tools -GO_PRE_COMMIT_GITLEAKS_VERSION=v8.29.0 # https://github.com/gitleaks/gitleaks/releases +GO_PRE_COMMIT_GITLEAKS_VERSION=v8.29.1 # https://github.com/gitleaks/gitleaks/releases # Build tags for golangci-lint and other tools GO_PRE_COMMIT_BUILD_TAGS= @@ -393,6 +394,8 @@ DEPENDABOT_MAINTAINER_USERNAME=mrz1836 DEPENDABOT_AUTO_MERGE_PATCH=true DEPENDABOT_AUTO_MERGE_MINOR_DEV=true DEPENDABOT_AUTO_MERGE_MINOR_PROD=true +DEPENDABOT_AUTO_MERGE_PATCH_INDIRECT=true +DEPENDABOT_AUTO_MERGE_MINOR_INDIRECT=true DEPENDABOT_AUTO_MERGE_SECURITY_NON_MAJOR=true DEPENDABOT_ALERT_ON_MAJOR=true DEPENDABOT_ALERT_ON_MINOR_PROD=true @@ -418,6 +421,8 @@ AUTO_MERGE_SKIP_FORK_PRS=true # Note: Fork PRs receive welcome comments from pull-request-management-fork.yml instead # This setting only affects same-repo PRs (fork PRs use read-only GITHUB_TOKEN) AUTO_MERGE_COMMENT_ON_FORK_SKIP=true +AUTO_MERGE_REQUIRE_LABEL=true +AUTO_MERGE_LABEL=automerge # ================================================================================================ # 📝 PULL REQUEST MANAGEMENT CONFIGURATION diff --git a/.github/workflows/auto-merge-on-approval.yml b/.github/workflows/auto-merge-on-approval.yml index e26868a..f92e5f6 100644 --- a/.github/workflows/auto-merge-on-approval.yml +++ b/.github/workflows/auto-merge-on-approval.yml @@ -88,6 +88,7 @@ jobs: runs-on: ubuntu-latest permissions: pull-requests: write # Required: Update PR status and enable auto-merge + issues: write # Required: Add labels and create comments outputs: action-taken: ${{ steps.process.outputs.action }} pr-number: ${{ github.event.pull_request.number }} @@ -117,6 +118,8 @@ jobs: SKIP_BOT_PRS=$(echo "$ENV_JSON" | jq -r '.AUTO_MERGE_SKIP_BOT_PRS') SKIP_FORK_PRS=$(echo "$ENV_JSON" | jq -r '.AUTO_MERGE_SKIP_FORK_PRS') COMMENT_ON_FORK_SKIP=$(echo "$ENV_JSON" | jq -r '.AUTO_MERGE_COMMENT_ON_FORK_SKIP') + AUTO_MERGE_REQUIRE_LABEL=$(echo "$ENV_JSON" | jq -r '.AUTO_MERGE_REQUIRE_LABEL') + AUTO_MERGE_LABEL=$(echo "$ENV_JSON" | jq -r '.AUTO_MERGE_LABEL') PREFERRED_TOKEN=$(echo "$ENV_JSON" | jq -r '.PREFERRED_GITHUB_TOKEN') # Validate required configuration @@ -138,6 +141,8 @@ jobs: echo "SKIP_BOT_PRS=$SKIP_BOT_PRS" >> $GITHUB_ENV echo "SKIP_FORK_PRS=$SKIP_FORK_PRS" >> $GITHUB_ENV echo "COMMENT_ON_FORK_SKIP=$COMMENT_ON_FORK_SKIP" >> $GITHUB_ENV + echo "AUTO_MERGE_REQUIRE_LABEL=$AUTO_MERGE_REQUIRE_LABEL" >> $GITHUB_ENV + echo "AUTO_MERGE_LABEL=$AUTO_MERGE_LABEL" >> $GITHUB_ENV # Determine default merge type DEFAULT_MERGE_TYPE=$(echo "$MERGE_TYPES" | cut -d',' -f1) @@ -161,6 +166,8 @@ jobs: echo " 🤖 Skip bot PRs: $SKIP_BOT_PRS" echo " 🍴 Skip fork PRs: $SKIP_FORK_PRS" echo " đŸ’Ŧ Comment on fork skip: $COMMENT_ON_FORK_SKIP" + echo " đŸˇī¸ Require automerge label: $AUTO_MERGE_REQUIRE_LABEL" + echo " đŸˇī¸ Automerge label name: $AUTO_MERGE_LABEL" echo " 🔑 Token: Selected via github-script action" # -------------------------------------------------------------------- @@ -261,6 +268,21 @@ jobs: } } + // ———————————————————————————————————————————————————————————————— + // Check for automerge label requirement + // ———————————————————————————————————————————————————————————————— + if (process.env.AUTO_MERGE_REQUIRE_LABEL === 'true') { + const automergeLabel = process.env.AUTO_MERGE_LABEL || 'automerge'; + const hasAutomergeLabel = labels.includes(automergeLabel); + + if (!hasAutomergeLabel) { + console.log(`đŸˇī¸ Missing required label "${automergeLabel}" - skipping auto-merge`); + core.setOutput('action', 'skip-missing-automerge-label'); + return; + } + console.log(`✅ Has required automerge label: "${automergeLabel}"`); + } + // ———————————————————————————————————————————————————————————————— // Check review conditions // ———————————————————————————————————————————————————————————————— @@ -517,6 +539,9 @@ jobs: "skip-wip") ACTION_DESC="🚧 Skipped (work in progress)" ;; + "skip-missing-automerge-label") + ACTION_DESC="đŸˇī¸ Skipped (missing automerge label)" + ;; "conditions-not-met") ACTION_DESC="âŗ Conditions not met" ;; @@ -580,6 +605,9 @@ jobs: skip-fork) echo "🍴 Action: Skipped - Fork PR (security policy)" ;; + skip-missing-automerge-label) + echo "đŸˇī¸ Action: Skipped - Missing automerge label" + ;; skip-*) echo "â­ī¸ Action: Skipped - $ACTION" ;; diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 24a2193..bd587bb 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -47,7 +47,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@014f16e7ab1402f30e7c3329d33797e7948572db # v4.31.3 + uses: github/codeql-action/init@e12f0178983d466f2f6028f5cc7a6d786fd97f4b # v4.31.4 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -58,7 +58,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@014f16e7ab1402f30e7c3329d33797e7948572db # v4.31.3 + uses: github/codeql-action/autobuild@e12f0178983d466f2f6028f5cc7a6d786fd97f4b # v4.31.4 # â„šī¸ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -68,4 +68,4 @@ jobs: # uses a compiled language - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@014f16e7ab1402f30e7c3329d33797e7948572db # v4.31.3 + uses: github/codeql-action/analyze@e12f0178983d466f2f6028f5cc7a6d786fd97f4b # v4.31.4 diff --git a/.github/workflows/dependabot-auto-merge.yml b/.github/workflows/dependabot-auto-merge.yml index fd0e1bd..c441ee5 100644 --- a/.github/workflows/dependabot-auto-merge.yml +++ b/.github/workflows/dependabot-auto-merge.yml @@ -110,6 +110,8 @@ jobs: AUTO_MERGE_PATCH=$(echo "$ENV_JSON" | jq -r '.DEPENDABOT_AUTO_MERGE_PATCH') AUTO_MERGE_MINOR_DEV=$(echo "$ENV_JSON" | jq -r '.DEPENDABOT_AUTO_MERGE_MINOR_DEV') AUTO_MERGE_MINOR_PROD=$(echo "$ENV_JSON" | jq -r '.DEPENDABOT_AUTO_MERGE_MINOR_PROD') + AUTO_MERGE_PATCH_INDIRECT=$(echo "$ENV_JSON" | jq -r '.DEPENDABOT_AUTO_MERGE_PATCH_INDIRECT') + AUTO_MERGE_MINOR_INDIRECT=$(echo "$ENV_JSON" | jq -r '.DEPENDABOT_AUTO_MERGE_MINOR_INDIRECT') AUTO_MERGE_SECURITY=$(echo "$ENV_JSON" | jq -r '.DEPENDABOT_AUTO_MERGE_SECURITY_NON_MAJOR') ALERT_ON_MAJOR=$(echo "$ENV_JSON" | jq -r '.DEPENDABOT_ALERT_ON_MAJOR') ALERT_ON_MINOR_PROD=$(echo "$ENV_JSON" | jq -r '.DEPENDABOT_ALERT_ON_MINOR_PROD') @@ -128,6 +130,8 @@ jobs: echo "AUTO_MERGE_PATCH=$AUTO_MERGE_PATCH" >> $GITHUB_ENV echo "AUTO_MERGE_MINOR_DEV=$AUTO_MERGE_MINOR_DEV" >> $GITHUB_ENV echo "AUTO_MERGE_MINOR_PROD=$AUTO_MERGE_MINOR_PROD" >> $GITHUB_ENV + echo "AUTO_MERGE_PATCH_INDIRECT=$AUTO_MERGE_PATCH_INDIRECT" >> $GITHUB_ENV + echo "AUTO_MERGE_MINOR_INDIRECT=$AUTO_MERGE_MINOR_INDIRECT" >> $GITHUB_ENV echo "AUTO_MERGE_SECURITY=$AUTO_MERGE_SECURITY" >> $GITHUB_ENV echo "ALERT_ON_MAJOR=$ALERT_ON_MAJOR" >> $GITHUB_ENV echo "ALERT_ON_MINOR_PROD=$ALERT_ON_MINOR_PROD" >> $GITHUB_ENV @@ -140,6 +144,8 @@ jobs: echo " 🔧 Auto-merge patch: $AUTO_MERGE_PATCH" echo " 🔧 Auto-merge minor dev: $AUTO_MERGE_MINOR_DEV" echo " 🔧 Auto-merge minor prod: $AUTO_MERGE_MINOR_PROD" + echo " 🔧 Auto-merge patch indirect: $AUTO_MERGE_PATCH_INDIRECT" + echo " 🔧 Auto-merge minor indirect: $AUTO_MERGE_MINOR_INDIRECT" echo " 🔒 Auto-merge security (non-major): $AUTO_MERGE_SECURITY" echo " âš ī¸ Alert on major: $ALERT_ON_MAJOR" echo " 🔍 Alert on minor prod: $ALERT_ON_MINOR_PROD" @@ -183,19 +189,111 @@ jobs: env: PR_TITLE: ${{ github.event.pull_request.title }} PR_LABELS: ${{ join(github.event.pull_request.labels.*.name, ',') }} + PR_BODY: ${{ github.event.pull_request.body }} + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | - echo "🔒 Checking if this is a security update..." + echo "════════════════════════════════════════════════════════════════" + echo "🔒 SECURITY UPDATE DETECTION" + echo "════════════════════════════════════════════════════════════════" + + # Check 1: PR title and labels for security indicators + echo "📋 Check 1: Analyzing PR labels and title..." + echo " Labels: $PR_LABELS" + echo " Title: $PR_TITLE" - # Check PR title and labels for security indicators # Using environment variables to prevent script injection - if [[ "$PR_LABELS" == *"security"* ]] || \ - [[ "$PR_TITLE" == *"security"* ]] || \ - [[ "$PR_TITLE" == *"[Security]"* ]]; then + if [[ "${PR_LABELS,,}" == *"security"* ]]; then + echo " ✅ MATCH: 'security' found in PR labels" + echo "is_security=true" >> $GITHUB_OUTPUT + echo "════════════════════════════════════════════════════════════════" + echo "đŸŽ¯ RESULT: Security update detected (via labels)" + echo "════════════════════════════════════════════════════════════════" + exit 0 + elif [[ "${PR_TITLE,,}" == *"security"* ]]; then + echo " ✅ MATCH: Security keyword found in PR title" + echo "is_security=true" >> $GITHUB_OUTPUT + echo "════════════════════════════════════════════════════════════════" + echo "đŸŽ¯ RESULT: Security update detected (via title)" + echo "════════════════════════════════════════════════════════════════" + exit 0 + else + echo " ❌ NO MATCH: No security indicators in labels/title" + fi + + # Check 2: PR body for security/vulnerability indicators + echo "" + echo "📄 Check 2: Scanning PR body for security indicators..." + + if [[ "${PR_BODY,,}" == *"security"* ]]; then + echo " ✅ MATCH: 'security' found in PR body" + echo "is_security=true" >> $GITHUB_OUTPUT + echo "════════════════════════════════════════════════════════════════" + echo "đŸŽ¯ RESULT: Security update detected (via PR body - 'security')" + echo "════════════════════════════════════════════════════════════════" + exit 0 + elif [[ "${PR_BODY,,}" == *"vulnerability"* ]]; then + echo " ✅ MATCH: 'vulnerability' found in PR body" + echo "is_security=true" >> $GITHUB_OUTPUT + echo "════════════════════════════════════════════════════════════════" + echo "đŸŽ¯ RESULT: Security update detected (via PR body - 'vulnerability')" + echo "════════════════════════════════════════════════════════════════" + exit 0 + elif [[ "$PR_BODY" == *"CVE-"* ]]; then + echo " ✅ MATCH: CVE identifier found in PR body" + echo "is_security=true" >> $GITHUB_OUTPUT + echo "════════════════════════════════════════════════════════════════" + echo "đŸŽ¯ RESULT: Security update detected (via PR body - CVE)" + echo "════════════════════════════════════════════════════════════════" + exit 0 + elif [[ "$PR_BODY" == *"GHSA-"* ]]; then + echo " ✅ MATCH: GitHub Security Advisory found in PR body" + echo "is_security=true" >> $GITHUB_OUTPUT + echo "════════════════════════════════════════════════════════════════" + echo "đŸŽ¯ RESULT: Security update detected (via PR body - GHSA)" + echo "════════════════════════════════════════════════════════════════" + exit 0 + else + echo " ❌ NO MATCH: No security indicators in PR body" + fi + + # Check 3: Query GitHub Security Advisories for Go ecosystem + echo "" + echo "🌐 Check 3: Querying GitHub Security Advisories API..." + DEPENDENCY="${{ steps.metadata.outputs.dependency-names }}" + echo " Package: $DEPENDENCY" + echo " Ecosystem: GO" + + # Query for vulnerabilities affecting this package + echo " Executing GraphQL query..." + ADVISORIES=$(gh api graphql -f query=' + query($ecosystem: SecurityAdvisoryEcosystem!, $package: String!) { + securityVulnerabilities(first: 10, ecosystem: $ecosystem, package: $package) { + nodes { + advisory { + severity + publishedAt + summary + } + vulnerableVersionRange + } + } + }' -f ecosystem=GO -f package="$DEPENDENCY" --jq '.data.securityVulnerabilities.nodes | length' 2>/dev/null || echo "0") + + echo " Advisories found: $ADVISORIES" + + if [[ "$ADVISORIES" -gt 0 ]]; then + echo " ✅ MATCH: $ADVISORIES vulnerabilities found in GitHub Advisories" echo "is_security=true" >> $GITHUB_OUTPUT - echo "✅ Security update detected" + echo "════════════════════════════════════════════════════════════════" + echo "đŸŽ¯ RESULT: Security update detected (via GitHub Advisories)" + echo "════════════════════════════════════════════════════════════════" + exit 0 else + echo " ❌ NO MATCH: No vulnerabilities found in GitHub Advisories" echo "is_security=false" >> $GITHUB_OUTPUT - echo "â„šī¸ Not a security update" + echo "════════════════════════════════════════════════════════════════" + echo "đŸŽ¯ RESULT: Not a security update" + echo "════════════════════════════════════════════════════════════════" fi # -------------------------------------------------------------------- @@ -204,60 +302,272 @@ jobs: - name: đŸŽ¯ Determine action id: determine-action run: | - echo "đŸŽ¯ Determining action based on update type and configuration..." + echo "════════════════════════════════════════════════════════════════" + echo "đŸŽ¯ ACTION DETERMINATION LOGIC" + echo "════════════════════════════════════════════════════════════════" UPDATE_TYPE="${{ steps.metadata.outputs.update-type }}" DEP_TYPE="${{ steps.metadata.outputs.dependency-type }}" IS_SECURITY="${{ steps.check-security.outputs.is_security }}" ACTION="none" + echo "📊 Input Variables:" + echo " Update Type: $UPDATE_TYPE" + echo " Dependency Type: $DEP_TYPE" + echo " Is Security: $IS_SECURITY" + echo "" + echo "📋 Active Configuration:" + echo " AUTO_MERGE_SECURITY: ${{ env.AUTO_MERGE_SECURITY }}" + echo " AUTO_MERGE_PATCH: ${{ env.AUTO_MERGE_PATCH }}" + echo " AUTO_MERGE_PATCH_INDIRECT: ${{ env.AUTO_MERGE_PATCH_INDIRECT }}" + echo " AUTO_MERGE_MINOR_DEV: ${{ env.AUTO_MERGE_MINOR_DEV }}" + echo " AUTO_MERGE_MINOR_PROD: ${{ env.AUTO_MERGE_MINOR_PROD }}" + echo " AUTO_MERGE_MINOR_INDIRECT: ${{ env.AUTO_MERGE_MINOR_INDIRECT }}" + echo " ALERT_ON_MAJOR: ${{ env.ALERT_ON_MAJOR }}" + echo " ALERT_ON_MINOR_PROD: ${{ env.ALERT_ON_MINOR_PROD }}" + echo "" + echo "🔄 Evaluating decision tree..." + echo "────────────────────────────────────────────────────────────────" + # Security updates (if enabled) - if [[ "$IS_SECURITY" == "true" ]] && [[ "${{ env.AUTO_MERGE_SECURITY }}" == "true" ]]; then - if [[ "$UPDATE_TYPE" != "version-update:semver-major" ]]; then - ACTION="auto-merge-security" + echo "🔍 Checking Rule 1: Security updates..." + if [[ "$IS_SECURITY" == "true" ]]; then + echo " ✅ IS_SECURITY == true" + if [[ "${{ env.AUTO_MERGE_SECURITY }}" == "true" ]]; then + echo " ✅ AUTO_MERGE_SECURITY == true" + if [[ "$UPDATE_TYPE" != "version-update:semver-major" ]]; then + echo " ✅ UPDATE_TYPE != major" + ACTION="auto-merge-security" + echo " đŸŽ¯ MATCH! Action: $ACTION" + echo " 📝 Reason: Non-major security update with auto-merge enabled" + else + echo " ❌ UPDATE_TYPE == major" + ACTION="alert-security-major" + echo " đŸŽ¯ MATCH! Action: $ACTION" + echo " 📝 Reason: Major security update requires manual review" + fi + else + echo " ❌ AUTO_MERGE_SECURITY == false" + echo " â­ī¸ Skipping security auto-merge (disabled)" + fi + else + echo " ❌ IS_SECURITY == false" + echo " â­ī¸ Not a security update, checking other rules..." + fi + echo "" + + # Patch updates - direct dependencies + if [[ "$ACTION" == "none" ]]; then + echo "🔍 Checking Rule 2: Patch updates (direct dependencies)..." + if [[ "$UPDATE_TYPE" == "version-update:semver-patch" ]]; then + echo " ✅ UPDATE_TYPE == patch" + if [[ "$DEP_TYPE" != "indirect" ]]; then + echo " ✅ DEP_TYPE != indirect (is direct)" + if [[ "${{ env.AUTO_MERGE_PATCH }}" == "true" ]]; then + echo " ✅ AUTO_MERGE_PATCH == true" + ACTION="auto-merge-patch" + echo " đŸŽ¯ MATCH! Action: $ACTION" + echo " 📝 Reason: Patch update for direct dependency with auto-merge enabled" + else + echo " ❌ AUTO_MERGE_PATCH == false" + ACTION="manual-review" + echo " đŸŽ¯ MATCH! Action: $ACTION" + echo " 📝 Reason: Patch auto-merge is disabled in configuration" + fi + else + echo " ❌ DEP_TYPE == indirect" + echo " â­ī¸ Skipping, will check indirect patch rule next" + fi else - ACTION="alert-security-major" + echo " ❌ UPDATE_TYPE != patch" + echo " â­ī¸ Not a patch update" fi - # Patch updates - elif [[ "$UPDATE_TYPE" == "version-update:semver-patch" ]]; then - if [[ "${{ env.AUTO_MERGE_PATCH }}" == "true" ]]; then - ACTION="auto-merge-patch" + fi + echo "" + + # Patch updates - indirect dependencies + if [[ "$ACTION" == "none" ]]; then + echo "🔍 Checking Rule 3: Patch updates (indirect dependencies)..." + if [[ "$UPDATE_TYPE" == "version-update:semver-patch" ]]; then + echo " ✅ UPDATE_TYPE == patch" + if [[ "$DEP_TYPE" == "indirect" ]]; then + echo " ✅ DEP_TYPE == indirect" + if [[ "${{ env.AUTO_MERGE_PATCH_INDIRECT }}" == "true" ]]; then + echo " ✅ AUTO_MERGE_PATCH_INDIRECT == true" + ACTION="auto-merge-patch-indirect" + echo " đŸŽ¯ MATCH! Action: $ACTION" + echo " 📝 Reason: Patch update for indirect dependency with auto-merge enabled" + else + echo " ❌ AUTO_MERGE_PATCH_INDIRECT == false" + ACTION="manual-review" + echo " đŸŽ¯ MATCH! Action: $ACTION" + echo " 📝 Reason: Indirect patch auto-merge is disabled in configuration" + fi + else + echo " ❌ DEP_TYPE != indirect" + echo " â­ī¸ Not an indirect dependency" + fi else - ACTION="manual-review" + echo " ❌ UPDATE_TYPE != patch" + echo " â­ī¸ Not a patch update" fi + fi + echo "" + # Minor updates - development dependencies - elif [[ "$UPDATE_TYPE" == "version-update:semver-minor" ]] && [[ "$DEP_TYPE" == "direct:development" ]]; then - if [[ "${{ env.AUTO_MERGE_MINOR_DEV }}" == "true" ]]; then - ACTION="auto-merge-minor-dev" + if [[ "$ACTION" == "none" ]]; then + echo "🔍 Checking Rule 4: Minor updates (development dependencies)..." + if [[ "$UPDATE_TYPE" == "version-update:semver-minor" ]]; then + echo " ✅ UPDATE_TYPE == minor" + if [[ "$DEP_TYPE" == "direct:development" ]]; then + echo " ✅ DEP_TYPE == direct:development" + if [[ "${{ env.AUTO_MERGE_MINOR_DEV }}" == "true" ]]; then + echo " ✅ AUTO_MERGE_MINOR_DEV == true" + ACTION="auto-merge-minor-dev" + echo " đŸŽ¯ MATCH! Action: $ACTION" + echo " 📝 Reason: Minor update for dev dependency with auto-merge enabled" + else + echo " ❌ AUTO_MERGE_MINOR_DEV == false" + ACTION="manual-review" + echo " đŸŽ¯ MATCH! Action: $ACTION" + echo " 📝 Reason: Minor dev dependency auto-merge is disabled" + fi + else + echo " ❌ DEP_TYPE != direct:development (is: $DEP_TYPE)" + echo " â­ī¸ Not a development dependency" + fi else - ACTION="manual-review" + echo " ❌ UPDATE_TYPE != minor" + echo " â­ī¸ Not a minor update" fi + fi + echo "" + # Minor updates - production dependencies - elif [[ "$UPDATE_TYPE" == "version-update:semver-minor" ]] && [[ "$DEP_TYPE" == "direct:production" ]]; then - if [[ "${{ env.AUTO_MERGE_MINOR_PROD }}" == "true" ]]; then - ACTION="auto-merge-minor-prod" - elif [[ "${{ env.ALERT_ON_MINOR_PROD }}" == "true" ]]; then - ACTION="alert-minor-prod" + if [[ "$ACTION" == "none" ]]; then + echo "🔍 Checking Rule 5: Minor updates (production dependencies)..." + if [[ "$UPDATE_TYPE" == "version-update:semver-minor" ]]; then + echo " ✅ UPDATE_TYPE == minor" + if [[ "$DEP_TYPE" == "direct:production" ]]; then + echo " ✅ DEP_TYPE == direct:production" + if [[ "${{ env.AUTO_MERGE_MINOR_PROD }}" == "true" ]]; then + echo " ✅ AUTO_MERGE_MINOR_PROD == true" + ACTION="auto-merge-minor-prod" + echo " đŸŽ¯ MATCH! Action: $ACTION" + echo " 📝 Reason: Minor update for prod dependency with auto-merge enabled" + elif [[ "${{ env.ALERT_ON_MINOR_PROD }}" == "true" ]]; then + echo " ❌ AUTO_MERGE_MINOR_PROD == false" + echo " ✅ ALERT_ON_MINOR_PROD == true" + ACTION="alert-minor-prod" + echo " đŸŽ¯ MATCH! Action: $ACTION" + echo " 📝 Reason: Minor prod dependency - alerting maintainer per config" + else + echo " ❌ AUTO_MERGE_MINOR_PROD == false" + echo " ❌ ALERT_ON_MINOR_PROD == false" + ACTION="manual-review" + echo " đŸŽ¯ MATCH! Action: $ACTION" + echo " 📝 Reason: Minor prod dependency auto-merge and alerts disabled" + fi + else + echo " ❌ DEP_TYPE != direct:production (is: $DEP_TYPE)" + echo " â­ī¸ Not a production dependency" + fi + else + echo " ❌ UPDATE_TYPE != minor" + echo " â­ī¸ Not a minor update" + fi + fi + echo "" + + # Minor updates - indirect dependencies + if [[ "$ACTION" == "none" ]]; then + echo "🔍 Checking Rule 6: Minor updates (indirect dependencies)..." + if [[ "$UPDATE_TYPE" == "version-update:semver-minor" ]]; then + echo " ✅ UPDATE_TYPE == minor" + if [[ "$DEP_TYPE" == "indirect" ]]; then + echo " ✅ DEP_TYPE == indirect" + if [[ "${{ env.AUTO_MERGE_MINOR_INDIRECT }}" == "true" ]]; then + echo " ✅ AUTO_MERGE_MINOR_INDIRECT == true" + ACTION="auto-merge-minor-indirect" + echo " đŸŽ¯ MATCH! Action: $ACTION" + echo " 📝 Reason: Minor update for indirect dependency with auto-merge enabled" + else + echo " ❌ AUTO_MERGE_MINOR_INDIRECT == false" + ACTION="manual-review" + echo " đŸŽ¯ MATCH! Action: $ACTION" + echo " 📝 Reason: Indirect minor auto-merge is disabled in configuration" + fi + else + echo " ❌ DEP_TYPE != indirect" + echo " â­ī¸ Not an indirect dependency" + fi else - ACTION="manual-review" + echo " ❌ UPDATE_TYPE != minor" + echo " â­ī¸ Not a minor update" fi + fi + echo "" + # Major updates - elif [[ "$UPDATE_TYPE" == "version-update:semver-major" ]]; then - if [[ "${{ env.ALERT_ON_MAJOR }}" == "true" ]]; then - ACTION="alert-major" + if [[ "$ACTION" == "none" ]]; then + echo "🔍 Checking Rule 7: Major updates..." + if [[ "$UPDATE_TYPE" == "version-update:semver-major" ]]; then + echo " ✅ UPDATE_TYPE == major" + if [[ "${{ env.ALERT_ON_MAJOR }}" == "true" ]]; then + echo " ✅ ALERT_ON_MAJOR == true" + ACTION="alert-major" + echo " đŸŽ¯ MATCH! Action: $ACTION" + echo " 📝 Reason: Major update - alerting maintainer for breaking changes" + else + echo " ❌ ALERT_ON_MAJOR == false" + ACTION="manual-review" + echo " đŸŽ¯ MATCH! Action: $ACTION" + echo " 📝 Reason: Major update with alerts disabled - requires manual review" + fi else - ACTION="manual-review" + echo " ❌ UPDATE_TYPE != major" + echo " â­ī¸ Not a major update" fi - else + fi + echo "" + + # Fallback + if [[ "$ACTION" == "none" ]]; then + echo "âš ī¸ No rules matched - applying fallback..." ACTION="manual-review" + echo " đŸŽ¯ FALLBACK Action: $ACTION" + echo " 📝 Reason: No matching rule found - defaulting to manual review" + echo " âš ī¸ This shouldn't happen - check workflow logic!" fi + echo "" + echo "════════════════════════════════════════════════════════════════" + echo "đŸŽ¯ FINAL DECISION: $ACTION" + echo "════════════════════════════════════════════════════════════════" + echo "action=$ACTION" >> $GITHUB_OUTPUT - echo "✅ Determined action: $ACTION" # -------------------------------------------------------------------- # Handle major version alerts # -------------------------------------------------------------------- + - name: 📊 Log major version alert decision + run: | + ACTION="${{ steps.determine-action.outputs.action }}" + if [[ "$ACTION" == "alert-major" ]] || [[ "$ACTION" == "alert-security-major" ]]; then + echo "════════════════════════════════════════════════════════════════" + echo "âš ī¸ MAJOR VERSION ALERT - WILL EXECUTE" + echo "════════════════════════════════════════════════════════════════" + echo "Action: $ACTION" + echo "Next step: Creating alert comment and adding manual-review label" + else + echo "════════════════════════════════════════════════════════════════" + echo "âš ī¸ MAJOR VERSION ALERT - SKIPPED" + echo "════════════════════════════════════════════════════════════════" + echo "Action: $ACTION" + echo "Reason: Not a major version update requiring alert" + echo "Skipping: Major version alert step" + fi + - name: âš ī¸ Alert on major version bump if: steps.determine-action.outputs.action == 'alert-major' || steps.determine-action.outputs.action == 'alert-security-major' uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 @@ -326,6 +636,24 @@ jobs: # -------------------------------------------------------------------- # Handle minor production dependency alerts # -------------------------------------------------------------------- + - name: 📊 Log minor prod dependency alert decision + run: | + ACTION="${{ steps.determine-action.outputs.action }}" + if [[ "$ACTION" == "alert-minor-prod" ]]; then + echo "════════════════════════════════════════════════════════════════" + echo "🔍 MINOR PROD DEPENDENCY ALERT - WILL EXECUTE" + echo "════════════════════════════════════════════════════════════════" + echo "Action: $ACTION" + echo "Next step: Creating alert comment for maintainer review" + else + echo "════════════════════════════════════════════════════════════════" + echo "🔍 MINOR PROD DEPENDENCY ALERT - SKIPPED" + echo "════════════════════════════════════════════════════════════════" + echo "Action: $ACTION" + echo "Reason: Not a minor production dependency requiring alert" + echo "Skipping: Minor prod alert step" + fi + - name: 🔍 Alert on minor production dependency if: steps.determine-action.outputs.action == 'alert-minor-prod' uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 @@ -378,16 +706,62 @@ jobs: # -------------------------------------------------------------------- # Auto-merge approved updates # -------------------------------------------------------------------- + - name: 📊 Log auto-merge decision + run: | + ACTION="${{ steps.determine-action.outputs.action }}" + if [[ "$ACTION" == auto-merge-* ]]; then + echo "════════════════════════════════════════════════════════════════" + echo "🚀 AUTO-MERGE - WILL EXECUTE" + echo "════════════════════════════════════════════════════════════════" + echo "Action: $ACTION" + echo "Dependency: ${{ steps.metadata.outputs.dependency-names }}" + echo "Version: ${{ steps.metadata.outputs.previous-version }} → ${{ steps.metadata.outputs.new-version }}" + echo "Next steps:" + echo " 1. Approve the PR with appropriate message" + echo " 2. Enable auto-merge (squash)" + echo " 3. PR will merge automatically when CI passes" + else + echo "════════════════════════════════════════════════════════════════" + echo "🚀 AUTO-MERGE - SKIPPED" + echo "════════════════════════════════════════════════════════════════" + echo "Action: $ACTION" + echo "Reason: Action does not start with 'auto-merge-'" + if [[ "$ACTION" == "manual-review" ]]; then + echo "" + echo "âš ī¸ MANUAL REVIEW REQUIRED" + echo "This PR was not auto-merged due to configuration settings." + echo "Possible reasons:" + echo " - Auto-merge is disabled for this update type" + echo " - Update type doesn't match any auto-merge rules" + echo " - Major version update requiring review" + echo "" + echo "Please review the decision tree output above for specific reason." + elif [[ "$ACTION" == alert-* ]]; then + echo "" + echo "đŸ“ĸ ALERT ACTION TAKEN" + echo "An alert comment was created instead of auto-merge." + echo "Check the alert step output for details." + fi + echo "Skipping: Auto-merge step" + fi + - name: 🚀 Auto-merge approved updates if: | startsWith(steps.determine-action.outputs.action, 'auto-merge-') run: | - echo "🚀 Processing auto-merge for ${{ steps.determine-action.outputs.action }}..." + echo "════════════════════════════════════════════════════════════════" + echo "🚀 EXECUTING AUTO-MERGE" + echo "════════════════════════════════════════════════════════════════" ACTION="${{ steps.determine-action.outputs.action }}" DEPENDENCY="${{ steps.metadata.outputs.dependency-names }}" VERSION_CHANGE="${{ steps.metadata.outputs.previous-version }} → ${{ steps.metadata.outputs.new-version }}" + echo "Processing: $ACTION" + echo "Dependency: $DEPENDENCY" + echo "Version: $VERSION_CHANGE" + echo "" + # Check token availability (use env var to avoid expanding secrets in run block) # TOKEN_TYPE is passed as environment variable to indicate which token is being used if [[ "$TOKEN_TYPE" == "PAT" ]]; then @@ -401,12 +775,18 @@ jobs: "auto-merge-patch") APPROVAL_MSG="✅ Auto-approving patch update" ;; + "auto-merge-patch-indirect") + APPROVAL_MSG="✅ Auto-approving patch update (indirect dependency)" + ;; "auto-merge-minor-dev") APPROVAL_MSG="✅ Auto-approving minor development dependency update" ;; "auto-merge-minor-prod") APPROVAL_MSG="✅ Auto-approving minor production dependency update" ;; + "auto-merge-minor-indirect") + APPROVAL_MSG="✅ Auto-approving minor update (indirect dependency)" + ;; "auto-merge-security") APPROVAL_MSG="🔒 Auto-approving security update" ;; @@ -416,22 +796,67 @@ jobs: esac # Approve the PR - echo "📝 Approving PR..." + echo "Step 1: Approving PR..." + echo "────────────────────────────────────────────────────────────────" if ! gh pr review --approve "$PR_URL" --body "$APPROVAL_MSG: $DEPENDENCY ($VERSION_CHANGE)"; then echo "❌ Failed to approve PR" + echo "════════════════════════════════════════════════════════════════" + echo "đŸšĢ AUTO-MERGE FAILED" + echo "════════════════════════════════════════════════════════════════" + echo "Reason: Could not approve PR via GitHub CLI" + echo "This is likely a permissions or network issue." exit 1 fi + echo "✅ PR approved successfully" + echo "" # Attempt to enable auto-merge - echo "🚀 Attempting to enable auto-merge..." + echo "Step 2: Enabling auto-merge..." + echo "────────────────────────────────────────────────────────────────" if gh pr merge --auto --squash "$PR_URL"; then - echo "✅ Successfully enabled auto-merge for $ACTION" + echo "✅ Auto-merge enabled successfully" + echo "" + echo "════════════════════════════════════════════════════════════════" + echo "✅ AUTO-MERGE COMPLETED" + echo "════════════════════════════════════════════════════════════════" + echo "Status: PR approved and auto-merge enabled" + echo "Action: $ACTION" + echo "Dependency: $DEPENDENCY" + echo "Version: $VERSION_CHANGE" + echo "Merge method: squash" + echo "" + echo "Next steps:" + echo " ✓ PR will automatically merge when:" + echo " - All required checks pass" + echo " - All required reviews are approved" + echo " ✓ Branch will be deleted after merge" + echo "════════════════════════════════════════════════════════════════" else - echo "âš ī¸ Auto-merge failed (likely permissions issue)" - echo "💡 Tip: Ensure GH_PAT_TOKEN is set with repo permissions for Dependabot PRs" + echo "❌ Auto-merge command failed" + echo "" + echo "════════════════════════════════════════════════════════════════" + echo "âš ī¸ AUTO-MERGE PARTIALLY COMPLETED" + echo "════════════════════════════════════════════════════════════════" + echo "Status: PR approved but auto-merge failed" + echo "Action: $ACTION" + echo "Dependency: $DEPENDENCY" + echo "Version: $VERSION_CHANGE" + echo "" + echo "Reason: Auto-merge command failed (permissions issue)" + echo "" + echo "Common causes:" + echo " - Using GITHUB_TOKEN instead of GH_PAT_TOKEN" + echo " - PAT doesn't have 'repo' scope" + echo " - Auto-merge not enabled in repository settings" + echo " - Branch protection rules prevent auto-merge" + echo "" + echo "Resolution:" + echo " ✓ PR is approved and ready" + echo " ✓ You can manually merge when CI passes" + echo " ✓ Or add GH_PAT_TOKEN secret with repo permissions" + echo "════════════════════════════════════════════════════════════════" # Fallback: Set up for manual merge - echo "🔄 PR has been approved and is ready for manual merge" echo "action-taken=approved-ready-for-merge" >> $GITHUB_OUTPUT # Don't exit with error - the PR is still approved @@ -467,6 +892,8 @@ jobs: labels.push('dev-dependency'); } else if (depType === 'direct:production') { labels.push('prod-dependency'); + } else if (depType === 'indirect') { + labels.push('indirect-dependency'); } // Add update type label @@ -533,12 +960,18 @@ jobs: "auto-merge-patch") ACTION_DESC="✅ Auto-merged (patch update)" ;; + "auto-merge-patch-indirect") + ACTION_DESC="✅ Auto-merged (patch update - indirect dependency)" + ;; "auto-merge-minor-dev") ACTION_DESC="✅ Auto-merged (minor dev dependency)" ;; "auto-merge-minor-prod") ACTION_DESC="✅ Auto-merged (minor prod dependency)" ;; + "auto-merge-minor-indirect") + ACTION_DESC="✅ Auto-merged (minor update - indirect dependency)" + ;; "auto-merge-security") ACTION_DESC="🔒 Auto-merged (security update)" ;; @@ -575,6 +1008,8 @@ jobs: AUTO_MERGE_PATCH=$(echo "$ENV_JSON" | jq -r '.DEPENDABOT_AUTO_MERGE_PATCH') AUTO_MERGE_MINOR_DEV=$(echo "$ENV_JSON" | jq -r '.DEPENDABOT_AUTO_MERGE_MINOR_DEV') AUTO_MERGE_MINOR_PROD=$(echo "$ENV_JSON" | jq -r '.DEPENDABOT_AUTO_MERGE_MINOR_PROD') + AUTO_MERGE_PATCH_INDIRECT=$(echo "$ENV_JSON" | jq -r '.DEPENDABOT_AUTO_MERGE_PATCH_INDIRECT') + AUTO_MERGE_MINOR_INDIRECT=$(echo "$ENV_JSON" | jq -r '.DEPENDABOT_AUTO_MERGE_MINOR_INDIRECT') AUTO_MERGE_SECURITY=$(echo "$ENV_JSON" | jq -r '.DEPENDABOT_AUTO_MERGE_SECURITY_NON_MAJOR') echo "| Setting | Value |" >> $GITHUB_STEP_SUMMARY @@ -582,6 +1017,8 @@ jobs: echo "| Auto-merge patch | $AUTO_MERGE_PATCH |" >> $GITHUB_STEP_SUMMARY echo "| Auto-merge minor dev | $AUTO_MERGE_MINOR_DEV |" >> $GITHUB_STEP_SUMMARY echo "| Auto-merge minor prod | $AUTO_MERGE_MINOR_PROD |" >> $GITHUB_STEP_SUMMARY + echo "| Auto-merge patch indirect | $AUTO_MERGE_PATCH_INDIRECT |" >> $GITHUB_STEP_SUMMARY + echo "| Auto-merge minor indirect | $AUTO_MERGE_MINOR_INDIRECT |" >> $GITHUB_STEP_SUMMARY echo "| Auto-merge security | $AUTO_MERGE_SECURITY |" >> $GITHUB_STEP_SUMMARY echo "| Maintainer | @$MAINTAINER |" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY diff --git a/.github/workflows/fortress-code-quality.yml b/.github/workflows/fortress-code-quality.yml index e4902af..7894737 100644 --- a/.github/workflows/fortress-code-quality.yml +++ b/.github/workflows/fortress-code-quality.yml @@ -273,7 +273,48 @@ jobs: echo "version=${{ env.MAGE_X_GOLANGCI_LINT_VERSION }}" >> $GITHUB_OUTPUT # -------------------------------------------------------------------- - # Restore Cache golangci-lint + # Cache golangci-lint binary (prevents re-downloading) + # -------------------------------------------------------------------- + - name: 💾 Restore golangci-lint binary cache + id: cache-golangci-lint-binary + uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 + with: + path: ~/.cache/golangci-lint-bin + key: ${{ inputs.primary-runner }}-golangci-lint-binary-${{ env.MAGE_X_GOLANGCI_LINT_VERSION }} + + # -------------------------------------------------------------------- + # Install cached golangci-lint binary to GOPATH/bin + # -------------------------------------------------------------------- + - name: đŸ“Ļ Install cached golangci-lint binary + if: steps.cache-golangci-lint-binary.outputs.cache-hit == 'true' + run: | + echo "đŸ“Ļ Restoring cached golangci-lint binary..." + GOPATH_BIN="$(go env GOPATH)/bin" + mkdir -p "$GOPATH_BIN" + + if [[ -f ~/.cache/golangci-lint-bin/golangci-lint ]]; then + cp ~/.cache/golangci-lint-bin/golangci-lint "$GOPATH_BIN/" + chmod +x "$GOPATH_BIN/golangci-lint" + echo "✅ Cached golangci-lint binary installed to $GOPATH_BIN" + echo "📍 Version: $(golangci-lint --version | head -n1 || echo 'version check failed')" + else + echo "âš ī¸ Cache hit but binary not found, will install via MAGE-X" + fi + + # -------------------------------------------------------------------- + # Cache golangci-lint build cache (prevents re-compiling) + # -------------------------------------------------------------------- + - name: 💾 Cache golangci-lint build cache + id: cache-golangci-lint-build + uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 + with: + path: ~/.cache/go-build + key: ${{ inputs.primary-runner }}-go-build-golangci-${{ env.MAGE_X_GOLANGCI_LINT_VERSION }}-${{ hashFiles('**/*.go') }} + restore-keys: | + ${{ inputs.primary-runner }}-go-build-golangci-${{ env.MAGE_X_GOLANGCI_LINT_VERSION }}- + + # -------------------------------------------------------------------- + # Cache golangci-lint analysis results # -------------------------------------------------------------------- - name: 💾 Cache golangci-lint analysis id: cache-golangci-lint @@ -313,6 +354,24 @@ jobs: echo "✅ Code linting completed successfully" + # -------------------------------------------------------------------- + # Save golangci-lint binary to cache (on cache miss) + # -------------------------------------------------------------------- + - name: 💾 Save golangci-lint binary to cache + if: steps.cache-golangci-lint-binary.outputs.cache-hit != 'true' + run: | + echo "💾 Caching golangci-lint binary for future runs..." + GOPATH_BIN="$(go env GOPATH)/bin" + mkdir -p ~/.cache/golangci-lint-bin + + if [[ -f "$GOPATH_BIN/golangci-lint" ]]; then + cp "$GOPATH_BIN/golangci-lint" ~/.cache/golangci-lint-bin/ + echo "✅ golangci-lint binary cached" + echo "📊 Binary size: $(du -h "$GOPATH_BIN/golangci-lint" | cut -f1)" + else + echo "âš ī¸ golangci-lint binary not found at $GOPATH_BIN, cannot cache" + fi + # -------------------------------------------------------------------- # Summary of golangci-lint results # -------------------------------------------------------------------- @@ -324,7 +383,8 @@ jobs: echo "|---|---|" >> $GITHUB_STEP_SUMMARY echo "| **Configuration** | Custom ruleset via .golangci.json |" >> $GITHUB_STEP_SUMMARY echo "| **Version** | ${{ steps.golangci-lint-version.outputs.version }} |" >> $GITHUB_STEP_SUMMARY - echo "| **Cache** | 💾 Analysis cache enabled |" >> $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 diff --git a/.github/workflows/fortress-pre-commit.yml b/.github/workflows/fortress-pre-commit.yml index 70aaafa..f0f4421 100644 --- a/.github/workflows/fortress-pre-commit.yml +++ b/.github/workflows/fortress-pre-commit.yml @@ -131,7 +131,9 @@ jobs: # -------------------------------------------------------------------- # Restore (and later save) a compact cache for go-pre-commit tools - # (golangci-lint, gofumpt) to avoid reinstalling on every run + # Primary: gitleaks (installed as binary by go-pre-commit) + # Note: golangci-lint, gofumpt, goimports are managed by MAGE-X/other workflows + # Cache key includes all versions to invalidate when any tool version changes # -------------------------------------------------------------------- - name: 💾 Restore go-pre-commit tools cache id: go-pre-commit-tools-cache @@ -157,12 +159,13 @@ jobs: if [[ -f "$GO_PRE_COMMIT_BIN" ]]; then echo "✅ Using cached go-pre-commit binary" cp "$GO_PRE_COMMIT_BIN" "$GOPATH_BIN/" + chmod +x "$GOPATH_BIN/go-pre-commit" fi # If we restored tools cache, copy them to GOPATH/bin if [[ -d "$TOOLS_DIR" ]]; then echo "✅ Using cached go-pre-commit tools" - for tool in golangci-lint gofumpt; do + for tool in golangci-lint gofumpt gitleaks goimports; do if [[ -f "$TOOLS_DIR/$tool" ]]; then echo " â€ĸ Restoring cached $tool" cp "$TOOLS_DIR/$tool" "$GOPATH_BIN/" @@ -535,6 +538,53 @@ jobs: echo "files_found=false" >> $GITHUB_OUTPUT fi + # -------------------------------------------------------------------- + # Debug: Show tool locations before go-pre-commit runs + # Only runs when GO_PRE_COMMIT_DEBUG=true + # -------------------------------------------------------------------- + - name: 🔍 Debug tool locations (before execution) + if: steps.install-pre-commit.outputs.install_success == 'true' || steps.install-pre-commit-cached.outputs.install_success == 'true' + run: | + # Skip debug output unless explicitly enabled + if [[ "${{ env.GO_PRE_COMMIT_DEBUG }}" != "true" ]]; then + echo "🔍 Debug mode disabled (set GO_PRE_COMMIT_DEBUG=true to enable)" + exit 0 + fi + + echo "🔍 Checking tool locations BEFORE go-pre-commit execution..." + echo "============================================================" + GOPATH_BIN="$(go env GOPATH)/bin" + echo "" + echo "📂 GOPATH/bin contents ($GOPATH_BIN):" + if [[ -d "$GOPATH_BIN" ]]; then + for tool in golangci-lint gofumpt gitleaks goimports go-pre-commit; do + if [[ -f "$GOPATH_BIN/$tool" ]]; then + SIZE=$(du -h "$GOPATH_BIN/$tool" 2>/dev/null | cut -f1) + echo " ✅ $tool: $SIZE" + else + echo " ❌ $tool: NOT FOUND" + fi + done + else + echo " ❌ Directory does not exist" + fi + echo "" + echo "📂 ~/.cache/go-pre-commit contents:" + if [[ -d "$HOME/.cache/go-pre-commit" ]]; then + echo " Directory exists" + find "$HOME/.cache/go-pre-commit" -type f \( -name "golangci-lint" -o -name "gofumpt" -o -name "gitleaks" -o -name "goimports" \) 2>/dev/null || echo " No tools found" + else + echo " ❌ Directory does not exist" + fi + echo "" + echo "📂 ~/.cache/go-pre-commit-tools contents:" + if [[ -d "$HOME/.cache/go-pre-commit-tools" ]]; then + ls -lah "$HOME/.cache/go-pre-commit-tools" 2>/dev/null || echo " Empty" + else + echo " ❌ Directory does not exist" + fi + echo "============================================================" + # -------------------------------------------------------------------- # Run pre-commit checks # -------------------------------------------------------------------- @@ -644,9 +694,71 @@ jobs: echo "" echo "✅ All pre-commit checks passed successfully" + # -------------------------------------------------------------------- + # Debug: Show tool locations after go-pre-commit runs + # Only runs when GO_PRE_COMMIT_DEBUG=true + # -------------------------------------------------------------------- + - name: 🔍 Debug tool locations (after execution) + if: always() && (steps.install-pre-commit.outputs.install_success == 'true' || steps.install-pre-commit-cached.outputs.install_success == 'true') + run: | + # Skip debug output unless explicitly enabled + if [[ "${{ env.GO_PRE_COMMIT_DEBUG }}" != "true" ]]; then + echo "🔍 Debug mode disabled (set GO_PRE_COMMIT_DEBUG=true to enable)" + exit 0 + fi + + echo "🔍 Checking tool locations AFTER go-pre-commit execution..." + echo "===========================================================" + GOPATH_BIN="$(go env GOPATH)/bin" + echo "" + echo "📂 GOPATH/bin contents ($GOPATH_BIN):" + if [[ -d "$GOPATH_BIN" ]]; then + for tool in golangci-lint gofumpt gitleaks goimports go-pre-commit; do + if [[ -f "$GOPATH_BIN/$tool" ]]; then + SIZE=$(du -h "$GOPATH_BIN/$tool" 2>/dev/null | cut -f1) + VERSION=$("$GOPATH_BIN/$tool" --version 2>&1 | head -1 || echo "unknown") + echo " ✅ $tool: $SIZE - $VERSION" + else + echo " ❌ $tool: NOT FOUND" + fi + done + else + echo " ❌ Directory does not exist" + fi + echo "" + echo "📂 ~/.cache/go-pre-commit contents:" + if [[ -d "$HOME/.cache/go-pre-commit" ]]; then + echo " 📊 Directory exists - checking for tools:" + find "$HOME/.cache/go-pre-commit" -type f \( -name "golangci-lint" -o -name "gofumpt" -o -name "gitleaks" -o -name "goimports" \) -exec ls -lh {} \; 2>/dev/null || echo " No tools found" + echo " 📊 Directory size: $(du -sh "$HOME/.cache/go-pre-commit" 2>/dev/null | cut -f1)" + else + echo " ❌ Directory does not exist" + fi + echo "" + echo "📂 ~/.cache/go-pre-commit-tools contents:" + if [[ -d "$HOME/.cache/go-pre-commit-tools" ]]; then + echo " 📊 Directory exists:" + ls -lah "$HOME/.cache/go-pre-commit-tools" 2>/dev/null || echo " Empty" + echo " 📊 Directory size: $(du -sh "$HOME/.cache/go-pre-commit-tools" 2>/dev/null | cut -f1)" + else + echo " ❌ Directory does not exist" + fi + echo "" + echo "📂 Searching common tool locations for binaries:" + echo " (Checking: GOPATH/bin, .local/bin, .cache, bin)" + for tool in golangci-lint gofumpt gitleaks goimports; do + echo " 🔍 Searching for $tool:" + find "$HOME/go/bin" "$HOME/.local/bin" "$HOME/.cache" "$HOME/bin" \ + -maxdepth 3 -type f -name "$tool" 2>/dev/null | head -5 | sed 's/^/ /' || echo " Not found" + done + echo "===========================================================" + # -------------------------------------------------------------------- # Cache tools that were installed during pre-commit execution - # This step ensures tools like golangci-lint and gofumpt are cached for future runs + # Primary tool: gitleaks (installed as binary by go-pre-commit) + # Note: golangci-lint, gofumpt, goimports are not installed as binaries + # (managed by MAGE-X or invoked via go run by go-pre-commit) + # Only cache when tools cache was not hit - tools won't have changed if restored from cache # -------------------------------------------------------------------- - name: 💾 Cache go-pre-commit tools after installation if: steps.go-pre-commit-tools-cache.outputs.cache-hit != 'true' && (steps.install-pre-commit.outputs.install_success == 'true' || steps.install-pre-commit-cached.outputs.install_success == 'true') @@ -660,7 +772,7 @@ jobs: mkdir -p "$TOOLS_DIR" # Cache tools that may have been installed by go-pre-commit - for tool in golangci-lint gofumpt; do + for tool in golangci-lint gofumpt gitleaks goimports; do if [[ -f "$GOPATH_BIN/$tool" ]]; then echo " â€ĸ Caching $tool" cp "$GOPATH_BIN/$tool" "$TOOLS_DIR/" diff --git a/.github/workflows/fortress.yml b/.github/workflows/fortress.yml index b0a50bd..d37378b 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.1.0 | Released: 2025-09-15 +# Version: 1.2.0 | Released: 2025-11-20 # # Built Strong. Tested Harder. # diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index ce724fa..6ce4a14 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -78,6 +78,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard (optional). # Commenting out will disable the upload of results to your repo's Code Scanning dashboard - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@014f16e7ab1402f30e7c3329d33797e7948572db # v4.31.3 + uses: github/codeql-action/upload-sarif@e12f0178983d466f2f6028f5cc7a6d786fd97f4b # v4.31.4 with: sarif_file: results.sarif