diff --git a/.github/.env.base b/.github/.env.base
index 21c5941..22178c7 100644
--- a/.github/.env.base
+++ b/.github/.env.base
@@ -235,7 +235,7 @@ REDIS_CACHE_FORCE_PULL=false # Force pull Redis images even when cache
# 🪄 MAGE-X CONFIGURATION
# ================================================================================================
-MAGE_X_VERSION=v1.13.0 # https://github.com/mrz1836/mage-x/releases
+MAGE_X_VERSION=v1.15.0 # 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
@@ -244,7 +244,7 @@ MAGE_X_FORMAT_EXCLUDE_PATHS=vendor,node_modules,.git,.idea # Format exclusion
MAGE_X_GITLEAKS_VERSION=8.30.0 # 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.7.2 # https://github.com/golangci/golangci-lint/releases
-MAGE_X_GORELEASER_VERSION=v2.13.1 # https://github.com/goreleaser/goreleaser/releases
+MAGE_X_GORELEASER_VERSION=v2.13.2 # https://github.com/goreleaser/goreleaser/releases
MAGE_X_GOVULNCHECK_VERSION=v1.1.4 # https://go.googlesource.com/vuln/+refs
MAGE_X_GO_SECONDARY_VERSION=1.24.x # Secondary Go version for MAGE-X (also our secondary)
MAGE_X_GO_VERSION=1.24.x # Primary Go version for MAGE-X (also our primary)
@@ -252,7 +252,8 @@ MAGE_X_MOCKGEN_VERSION=v0.6.0 # https://github.c
MAGE_X_NANCY_VERSION=v1.0.52 # https://github.com/sonatype-nexus-community/nancy/releases
MAGE_X_STATICCHECK_VERSION=2025.1.1 # https://github.com/dominikh/go-tools/releases
MAGE_X_SWAG_VERSION=v1.16.6 # https://github.com/swaggo/swag/releases
-MAGE_X_YAMLFMT_VERSION=v0.20.0 # https://github.com/google/yamlfmt/releases
+MAGE_X_YAMLFMT_VERSION=v0.21.0 # https://github.com/google/yamlfmt/releases
+MAGE_X_BENCHSTAT_VERSION=v0.0.0-20251208221838-04cf7a2dca90 # https://pkg.go.dev/golang.org/x/perf/cmd/benchstat
# Exclude magefiles from prebuild - they require 'mage' build tag and fail without it
# MAGE_X_BUILD_EXCLUDE_PATTERN=magefiles
diff --git a/.github/actions/setup-benchstat/action.yml b/.github/actions/setup-benchstat/action.yml
new file mode 100644
index 0000000..4fc719b
--- /dev/null
+++ b/.github/actions/setup-benchstat/action.yml
@@ -0,0 +1,168 @@
+# ------------------------------------------------------------------------------------
+# Setup Benchstat Composite Action (GoFortress)
+#
+# Purpose: Install and cache the benchstat binary for use in GitHub Actions workflows.
+# Provides efficient caching by OS and version, with automatic binary installation
+# on cache miss and PATH management for seamless integration.
+#
+# Features:
+# - Smart binary caching by OS and version
+# - Automatic go install only on cache miss
+# - PATH management for immediate availability
+# - Performance tracking outputs
+#
+# Usage:
+# - uses: ./.github/actions/setup-benchstat
+# with:
+# benchstat-version: ${{ env.MAGE_X_BENCHSTAT_VERSION }}
+# runner-os: ${{ runner.os }}
+# go-version: ${{ matrix.go-version }}
+#
+# Maintainer: @mrz1836
+#
+# ------------------------------------------------------------------------------------
+
+name: "Setup Benchstat"
+description: "Install and cache benchstat binary for benchmark comparison"
+
+inputs:
+ benchstat-version:
+ description: "Benchstat version to install (e.g., v0.6.0)"
+ required: true
+ runner-os:
+ description: "Runner OS for cache key (e.g., ubuntu-latest, mac-latest)"
+ required: true
+ go-version:
+ description: "Go version being used (e.g., 1.24.x, 1.22). Benchstat requires Go 1.23+"
+ required: true
+
+outputs:
+ cache-hit:
+ description: "Whether benchstat was restored from cache (true/false). Empty if skipped due to Go version."
+ value: ${{ steps.benchstat-cache.outputs.cache-hit }}
+ installation-method:
+ description: "How benchstat was obtained: cached, fresh, or skipped"
+ value: ${{ steps.installation-summary.outputs.method }}
+ skipped:
+ description: "Whether benchstat installation was skipped due to Go version < 1.23"
+ value: ${{ steps.version-check.outputs.skip }}
+
+runs:
+ using: "composite"
+ steps:
+ # --------------------------------------------------------------------
+ # Check Go version compatibility (benchstat requires Go 1.23+)
+ # --------------------------------------------------------------------
+ - name: 🔍 Check Go version compatibility
+ id: version-check
+ shell: bash
+ run: |
+ GO_VERSION="${{ inputs.go-version }}"
+ # Extract major and minor version:
+ # "1.24.x" -> MAJOR=1, MINOR=24
+ # "1.22" -> MAJOR=1, MINOR=22
+ # "1.23.5" -> MAJOR=1, MINOR=23
+ # "2.0.0" -> MAJOR=2, MINOR=0
+ MAJOR=$(echo "$GO_VERSION" | sed -E 's/^([0-9]+)\..*/\1/')
+ MINOR=$(echo "$GO_VERSION" | sed -E 's/^[0-9]+\.([0-9]+).*/\1/')
+
+ if [ -z "$MAJOR" ] || [ -z "$MINOR" ] || ! [[ "$MAJOR" =~ ^[0-9]+$ ]] || ! [[ "$MINOR" =~ ^[0-9]+$ ]]; then
+ echo "❌ Could not parse Go version '$GO_VERSION'. Please provide a valid Go version (e.g., '1.23', '1.24.x')." >&2
+ exit 1
+ elif [ "$MAJOR" -gt 1 ]; then
+ # Any Go major version > 1 is considered compatible with the 1.23+ requirement
+ echo "✅ Go $GO_VERSION >= 1.23: proceeding with benchstat installation"
+ echo "skip=false" >> $GITHUB_OUTPUT
+ elif [ "$MAJOR" -eq 1 ] && [ "$MINOR" -lt 23 ]; then
+ echo "⚠️ Go $GO_VERSION < 1.23: skipping benchstat installation (requires Go 1.23+)"
+ echo "skip=true" >> $GITHUB_OUTPUT
+ else
+ echo "✅ Go $GO_VERSION >= 1.23: proceeding with benchstat installation"
+ echo "skip=false" >> $GITHUB_OUTPUT
+ fi
+
+ # --------------------------------------------------------------------
+ # Restore benchstat binary cache
+ # --------------------------------------------------------------------
+ - name: 💾 Restore benchstat binary cache
+ if: steps.version-check.outputs.skip != 'true'
+ id: benchstat-cache
+ uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4
+ with:
+ path: ~/.cache/benchstat-bin
+ key: ${{ inputs.runner-os }}-benchstat-${{ inputs.benchstat-version }}
+
+ # --------------------------------------------------------------------
+ # Install cached binary to PATH when cache hits
+ # --------------------------------------------------------------------
+ - name: 📦 Install cached benchstat to PATH
+ if: steps.version-check.outputs.skip != 'true' && steps.benchstat-cache.outputs.cache-hit == 'true'
+ shell: bash
+ run: |
+ echo "📦 Installing cached benchstat binary to PATH..."
+
+ # Copy cached binary to GOPATH and add to PATH
+ mkdir -p "$(go env GOPATH)/bin"
+ cp ~/.cache/benchstat-bin/benchstat "$(go env GOPATH)/bin/benchstat"
+ chmod +x "$(go env GOPATH)/bin/benchstat"
+ echo "$(go env GOPATH)/bin" >> "$GITHUB_PATH"
+
+ echo "✅ Cached benchstat binary installed to PATH"
+
+ # --------------------------------------------------------------------
+ # Install benchstat via go install when cache misses
+ # --------------------------------------------------------------------
+ - name: ⬇️ Install benchstat (cache miss)
+ if: steps.version-check.outputs.skip != 'true' && steps.benchstat-cache.outputs.cache-hit != 'true'
+ shell: bash
+ run: |
+ echo "⬇️ Cache miss – installing benchstat via go install..."
+ echo "📋 Installing benchstat version: ${{ inputs.benchstat-version }}"
+
+ # Install benchstat
+ go install "golang.org/x/perf/cmd/benchstat@${{ inputs.benchstat-version }}"
+
+ # Cache the binary for future runs
+ mkdir -p ~/.cache/benchstat-bin
+ cp "$(go env GOPATH)/bin/benchstat" ~/.cache/benchstat-bin/benchstat
+
+ # Ensure GOPATH/bin is in PATH
+ echo "$(go env GOPATH)/bin" >> "$GITHUB_PATH"
+
+ echo "✅ Benchstat installed and cached"
+
+ # --------------------------------------------------------------------
+ # Verify benchstat installation and set outputs
+ # --------------------------------------------------------------------
+ - name: 🔍 Verify benchstat installation
+ id: installation-summary
+ shell: bash
+ run: |
+ # Check if installation was skipped due to Go version
+ if [[ "${{ steps.version-check.outputs.skip }}" == "true" ]]; then
+ echo "⏭️ Benchstat installation skipped (Go version < 1.23)"
+ echo "method=skipped" >> $GITHUB_OUTPUT
+ echo "📋 Installation method: Skipped"
+ exit 0
+ fi
+
+ echo "🔍 Verifying benchstat installation..."
+
+ # Test that benchstat is available and working
+ if ! command -v benchstat >/dev/null 2>&1; then
+ echo "❌ ERROR: benchstat is not available in PATH" >&2
+ exit 1
+ fi
+
+ # Show version
+ echo "✅ benchstat is available"
+ benchstat -h 2>&1 | head -3 || true
+
+ # Determine installation method
+ if [[ "${{ steps.benchstat-cache.outputs.cache-hit }}" == "true" ]]; then
+ echo "method=cached" >> $GITHUB_OUTPUT
+ echo "📋 Installation method: Cached"
+ else
+ echo "method=fresh" >> $GITHUB_OUTPUT
+ echo "📋 Installation method: Fresh install"
+ fi
diff --git a/.github/actions/upload-statistics/action.yml b/.github/actions/upload-statistics/action.yml
index b0ff4d8..145f1ad 100644
--- a/.github/actions/upload-statistics/action.yml
+++ b/.github/actions/upload-statistics/action.yml
@@ -45,6 +45,10 @@ inputs:
description: "Compression level for the artifact (0-9, 6 is default)"
required: false
default: "6"
+ continue-on-error:
+ description: "Continue workflow if upload fails (for non-critical artifacts)"
+ required: false
+ default: "false"
runs:
using: "composite"
@@ -54,6 +58,7 @@ runs:
# --------------------------------------------------------------------
- name: 📤 Upload ${{ inputs.artifact-name }}
if: always() # Always run to capture data even on job failure
+ continue-on-error: ${{ inputs.continue-on-error == 'true' }}
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: ${{ inputs.artifact-name }}
diff --git a/.github/tech-conventions/README.md b/.github/tech-conventions/README.md
index eb8498f..a220d2f 100644
--- a/.github/tech-conventions/README.md
+++ b/.github/tech-conventions/README.md
@@ -59,5 +59,5 @@ Creating and maintaining GitHub Actions workflows with security, reliability, an
### 🏗️ Build & Project Setup
-**[MAGE-X Build Automation](mage-x.md)**
-Zero-boilerplate build automation system with 150+ built-in commands that replaces Makefiles. Includes installation, configuration, command reference, and migration guide.
+**[MAGE-X Build Tooling](mage-x.md)**
+Zero-boilerplate build toolchain with 150+ built-in commands that replaces Makefiles. Includes installation, configuration, command reference, and migration guide.
diff --git a/.github/tech-conventions/mage-x.md b/.github/tech-conventions/mage-x.md
index 3fc200f..78d8507 100644
--- a/.github/tech-conventions/mage-x.md
+++ b/.github/tech-conventions/mage-x.md
@@ -1,16 +1,16 @@
-# MAGE-X Build Automation
+# MAGE-X Build Tooling
-> Zero-boilerplate build automation for Go projects that replaces Makefiles with 150+ built-in commands and intelligent configuration.
+> Zero-boilerplate build tooling for Go projects that replaces Makefiles with 150+ built-in commands and intelligent configuration.
## 🚀 What is MAGE-X?
-**MAGE-X** is a revolutionary zero-configuration build automation system for Go that provides **truly zero-boilerplate** development workflows. Unlike traditional build systems that require extensive configuration or wrapper functions, MAGE-X delivers all commands instantly through a single `magex` binary.
+**MAGE-X** is a revolutionary zero-configuration build toolchain for Go that provides **truly zero-boilerplate** development workflows. Unlike traditional build systems that require extensive configuration or wrapper functions, MAGE-X delivers all commands instantly through a single `magex` binary.
### Core Philosophy
-**"Write Once, Mage Everywhere: Production Build Automation for Go"**
+**"Write Once, Mage Everywhere: Production Build Tooling for Go"**
- **Zero Setup Required**: No magefile.go needed for basic operations
- **150+ Built-in Commands**: Complete build, test, lint, release, and deployment workflows
@@ -654,6 +654,6 @@ magex --help # Global help and options and list all comma
5. **Performance**: Significantly faster than traditional build tools
6. **Production Ready**: Security, compliance, and governance features built-in
-MAGE-X transforms Go build automation from a chore into a productivity multiplier, enabling teams to focus on code rather than tooling configuration.
+MAGE-X transforms Go build tasks from a chore into a productivity multiplier, enabling teams to focus on code rather than tooling configuration.
-**Next Steps**: Install MAGE-X, run `magex build` in your project, and experience zero-configuration build automation.
+**Next Steps**: Install MAGE-X, run `magex build` in your project, and experience zero-configuration build tooling.
diff --git a/.github/workflows/dependabot-auto-merge.yml b/.github/workflows/dependabot-auto-merge.yml
index b8f6246..6cea005 100644
--- a/.github/workflows/dependabot-auto-merge.yml
+++ b/.github/workflows/dependabot-auto-merge.yml
@@ -164,7 +164,7 @@ jobs:
# --------------------------------------------------------------------
- name: 📊 Fetch Dependabot metadata
id: metadata
- uses: dependabot/fetch-metadata@08eff52bf64351f401fb50d4972fa95b9f2c2d1b # v2.4.0
+ uses: dependabot/fetch-metadata@21025c705c08248db411dc16f3619e6b5f9ea21a # v2.5.0
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
diff --git a/.github/workflows/fortress-completion-statistics.yml b/.github/workflows/fortress-completion-statistics.yml
index ec943c4..13d8c5d 100644
--- a/.github/workflows/fortress-completion-statistics.yml
+++ b/.github/workflows/fortress-completion-statistics.yml
@@ -632,6 +632,7 @@ jobs:
artifact-path: "statistics-section.md"
retention-days: "1"
if-no-files-found: "warn"
+ continue-on-error: "true"
- name: 📋 Set Output Content
id: set-output
diff --git a/.github/workflows/fortress-coverage.yml b/.github/workflows/fortress-coverage.yml
index 890191f..7f58cd5 100644
--- a/.github/workflows/fortress-coverage.yml
+++ b/.github/workflows/fortress-coverage.yml
@@ -737,7 +737,7 @@ jobs:
# Count processed files from coverage output
if [ -f "$COVERAGE_FILE" ]; then
- FILES_PROCESSED=$(wc -l < "$COVERAGE_FILE" || echo "0")
+ FILES_PROCESSED=$(grep -v '^mode:' "$COVERAGE_FILE" | grep '^[^:]*:' | grep -o '^[^:]*' | sort -u | wc -l | tr -d ' ' || echo "0")
echo "📁 Files processed: $FILES_PROCESSED"
fi
@@ -2425,12 +2425,51 @@ jobs:
# Calculate coverage from coverage.txt file using go tool cover
if [ -f "coverage-artifacts/coverage-data/coverage.txt" ]; then
- COVERAGE_PERCENTAGE=$(go tool cover -func="coverage-artifacts/coverage-data/coverage.txt" | tail -1 | awk '{print $3}' | sed 's/%//' || echo "0")
- FILES_PROCESSED=$(wc -l < "coverage-artifacts/coverage-data/coverage.txt" || echo "0")
+ # First, try direct calculation (suppress stderr to avoid module warnings)
+ COVERAGE_PERCENTAGE=$(go tool cover -func="coverage-artifacts/coverage-data/coverage.txt" 2>/dev/null | tail -1 | awk '{print $3}' | sed 's/%//' || true)
+
+ # Validate result - must be a number (handles empty output or errors)
+ if [[ -z "$COVERAGE_PERCENTAGE" ]] || ! [[ "$COVERAGE_PERCENTAGE" =~ ^[0-9]+\.?[0-9]*$ ]]; then
+ echo "⚠️ Could not calculate coverage percentage directly, trying manual calculation..."
+ COVERAGE_PERCENTAGE=""
+
+ # Fallback: Calculate from coverage file lines manually
+ # Coverage file format: path/file.go:startLine.startCol,endLine.endCol stmtCount hitCount
+ TOTAL_STATEMENTS=0
+ COVERED_STATEMENTS=0
+ while IFS= read -r line; do
+ # Skip header line (mode: ...)
+ [[ "$line" == mode:* ]] && continue
+ # Skip empty lines
+ [[ -z "$line" ]] && continue
+ # Extract statement count (first number) and hit count (second number)
+ # Format: path/file.go:startLine.startCol,endLine.endCol stmtCount hitCount
+ if [[ "$line" =~ [[:space:]]([0-9]+)[[:space:]]([0-9]+)$ ]]; then
+ STMT_COUNT="${BASH_REMATCH[1]}"
+ HIT_COUNT="${BASH_REMATCH[2]}"
+ TOTAL_STATEMENTS=$((TOTAL_STATEMENTS + STMT_COUNT))
+ if [[ $HIT_COUNT -gt 0 ]]; then
+ COVERED_STATEMENTS=$((COVERED_STATEMENTS + STMT_COUNT))
+ fi
+ fi
+ done < "coverage-artifacts/coverage-data/coverage.txt"
+
+ if [[ $TOTAL_STATEMENTS -gt 0 ]]; then
+ COVERAGE_PERCENTAGE=$(awk "BEGIN {printf \"%.1f\", ($COVERED_STATEMENTS / $TOTAL_STATEMENTS) * 100}")
+ echo "📈 Calculated coverage manually: ${COVERAGE_PERCENTAGE}% ($COVERED_STATEMENTS/$TOTAL_STATEMENTS statements)"
+ else
+ COVERAGE_PERCENTAGE="0"
+ echo "⚠️ No coverage data found, defaulting to 0%"
+ fi
+ fi
+
+ FILES_PROCESSED=$(grep -v '^mode:' "coverage-artifacts/coverage-data/coverage.txt" | grep '^[^:]*:' | grep -o '^[^:]*' | sort -u | wc -l | tr -d ' ' || echo "0")
echo "📈 Calculated coverage percentage: ${COVERAGE_PERCENTAGE}%"
echo "📁 Files processed: $FILES_PROCESSED"
else
echo "⚠️ Coverage file not found for statistics"
+ COVERAGE_PERCENTAGE="0"
+ FILES_PROCESSED="0"
fi
# Codecov job doesn't generate badges or deploy pages directly
diff --git a/.github/workflows/fortress-test-matrix.yml b/.github/workflows/fortress-test-matrix.yml
index a3acdc6..5cbc5eb 100644
--- a/.github/workflows/fortress-test-matrix.yml
+++ b/.github/workflows/fortress-test-matrix.yml
@@ -170,6 +170,17 @@ jobs:
runner-os: ${{ matrix.os }}
use-local: ${{ env.MAGE_X_USE_LOCAL }}
+ # --------------------------------------------------------------------
+ # Setup benchstat (required for benchmark comparison tests)
+ # Note: benchstat requires Go 1.23+, action will skip for older versions
+ # --------------------------------------------------------------------
+ - name: 📊 Setup benchstat
+ uses: ./.github/actions/setup-benchstat
+ with:
+ benchstat-version: ${{ env.MAGE_X_BENCHSTAT_VERSION }}
+ runner-os: ${{ matrix.os }}
+ go-version: ${{ matrix.go-version }}
+
# --------------------------------------------------------------------
# Setup Redis service using composite action with caching
# --------------------------------------------------------------------
diff --git a/.gitpod.yml b/.gitpod.yml
index c1942ee..00e4e6b 100644
--- a/.gitpod.yml
+++ b/.gitpod.yml
@@ -1,5 +1,5 @@
-# Gitpod workspace configuration for go-wire
-# Uses magex for build automation and development tasks
+# Gitpod workspace configuration for this project.
+# Uses magex for build tooling, linting, and testing.
# This creates a one-click development environment for contributors
image: gitpod/workspace-go:latest
@@ -7,35 +7,35 @@ image: gitpod/workspace-go:latest
tasks:
- name: setup-and-test
init: |
- echo "🚀 Setting up go-wire development environment..."
+ echo "🚀 Setting up development environment..."
echo "📦 Installing MAGE-X build tool..."
go install github.com/mrz1836/mage-x/cmd/magex@latest
- echo "📥 Downloading dependencies..."
+ echo "🔽 Downloading dependencies..."
magex deps:download
- echo "🔧 Initial build..."
- magex build
+ echo "🔍 Running linters..."
+ magex lint
echo "✅ Running initial tests..."
magex test
command: |
echo "==============================================="
- echo "🎯 Welcome to go-wire development!"
+ echo "🎯 Welcome to development environment!"
echo "==============================================="
echo ""
echo "🛠️ Available magex commands:"
echo " magex test - Run all tests"
echo " magex lint - Run linters"
echo " magex format:fix - Format the code"
- echo " magex build - Build the project"
+ echo " magex build - Build the project (binary)"
echo " magex help - List all available commands"
echo ""
echo "📖 Quick start:"
echo " 1. Try: magex test"
echo " 2. Make your changes"
- echo " 3. Run: magex format:fix && magex lint && magex test"
+ echo " 3. Run: magex format:fix && magex lint && magex test:race"
echo " 4. Commit and push your changes"
echo ""
echo "💡 For more help: magex help"