Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .github/actions/upload-artifact-resilient/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ runs:
- name: "📤 Upload ${{ inputs.artifact-name }} (attempt 1)"
id: attempt1
continue-on-error: true
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: ${{ inputs.artifact-name }}
path: ${{ inputs.artifact-path }}
Expand Down Expand Up @@ -80,7 +80,7 @@ runs:
id: attempt2
if: steps.attempt1.outcome == 'failure'
continue-on-error: true
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: ${{ inputs.artifact-name }}
path: ${{ inputs.artifact-path }}
Expand Down Expand Up @@ -108,7 +108,7 @@ runs:
id: attempt3
if: steps.attempt1.outcome == 'failure' && steps.attempt2.outcome == 'failure'
continue-on-error: ${{ inputs.continue-on-error == 'true' }}
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: ${{ inputs.artifact-name }}
path: ${{ inputs.artifact-path }}
Expand Down
2 changes: 1 addition & 1 deletion .github/actions/upload-statistics/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,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@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: ${{ inputs.artifact-name }}
path: ${{ inputs.artifact-path }}
Expand Down
2 changes: 1 addition & 1 deletion .github/actions/warm-cache/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -461,7 +461,7 @@ runs:
# --------------------------------------------------------------------
- name: 📤 Upload cache statistics
if: always()
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: cache-stats-${{ inputs.matrix-os }}-${{ inputs.go-version }}
path: cache-stats-*.json
Expand Down
12 changes: 6 additions & 6 deletions .github/env/10-mage-x.env
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
# ================================================================================================

# MAGE-X version
MAGE_X_VERSION=v1.28.0
MAGE_X_VERSION=v1.29.0

# For mage-x development, set to 'true' to use local version instead of downloading from releases
MAGE_X_USE_LOCAL=false
Expand Down Expand Up @@ -84,17 +84,17 @@ MAGE_X_GOFUMPT_VERSION=v0.11.0
MAGE_X_GOFUMPT_VERSION_LATEST=v0.12.0
MAGE_X_GOFUMPT_VERSION_LATEST_MIN_GO=1.26
MAGE_X_GOLANGCI_LINT_VERSION=v2.14.0
MAGE_X_GORELEASER_VERSION=v2.18.2
MAGE_X_GOVULNCHECK_VERSION=v1.8.0
MAGE_X_GORELEASER_VERSION=v2.18.3
MAGE_X_GOVULNCHECK_VERSION=v1.9.0
MAGE_X_GO_SECONDARY_VERSION=1.24.x
MAGE_X_GO_VERSION=1.24.x
MAGE_X_MOCKGEN_VERSION=v0.6.0
MAGE_X_NANCY_VERSION=v2.1.0
# OSV-Scanner version for MAGE-X parity (authoritative pin is OSV_SCANNER_VERSION in
# 10-security.env, which the CI workflow uses to download the official release binary
# and verify it against the SHA-256 digests pinned there).
MAGE_X_OSV_SCANNER_VERSION=v2.6.0
MAGE_X_STATICCHECK_VERSION=2026.2.1
MAGE_X_OSV_SCANNER_VERSION=v2.7.0
MAGE_X_STATICCHECK_VERSION=2026.2.2
MAGE_X_SWAG_VERSION=v1.16.6
MAGE_X_YAMLFMT_VERSION=v0.21.0
# benchstat is versioned by two pins. golang.org/x/perf ships only pseudo-versions
Expand All @@ -117,7 +117,7 @@ MAGE_X_YAMLFMT_VERSION=v0.21.0
# runners on Go >= _LATEST_MIN_GO install _LATEST; Go 1.25.x runners install the held
# MAGE_X_BENCHSTAT_VERSION; Go < 1.25 is skipped (benchstat's floor).
MAGE_X_BENCHSTAT_VERSION=v0.0.0-20260813145340-fd4a688df892
MAGE_X_BENCHSTAT_VERSION_LATEST=v0.0.0-20260929162123-406019bb8b68
MAGE_X_BENCHSTAT_VERSION_LATEST=v0.0.0-20261009192801-be2c69fb417e
MAGE_X_BENCHSTAT_VERSION_LATEST_MIN_GO=1.26
MAGE_X_MAGE_VERSION=v1.17.2

Expand Down
8 changes: 4 additions & 4 deletions .github/env/10-security.env
Original file line number Diff line number Diff line change
Expand Up @@ -80,9 +80,9 @@ OSV_SCANNER_FAIL_ON_VULNERABILITY=true
# ================================================================================================

GITLEAKS_VERSION=8.30.1
GOVULNCHECK_VERSION=v1.8.0
GOVULNCHECK_VERSION=v1.9.0
NANCY_VERSION=v2.1.0
OSV_SCANNER_VERSION=v2.6.0
OSV_SCANNER_VERSION=v2.7.0

# SHA-256 digests of the OFFICIAL OSV-Scanner release binaries, per runner
# platform. These are the supply-chain trust anchor for the prebuilt-binary
Expand All @@ -100,5 +100,5 @@ OSV_SCANNER_VERSION=v2.6.0
# `osv-scanner_SHA256SUMS` asset (<OSV_SCANNER_VERSION> is the pinned version above,
# e.g. v2.5.1); the URL is illustrative, so it is not rewritten on a version bump:
# https://github.com/google/osv-scanner/releases/download/<OSV_SCANNER_VERSION>/osv-scanner_SHA256SUMS
OSV_SCANNER_SHA256_LINUX_AMD64=ca69b3d3cd08f889a49dc0a383122f71cc528b83803671df5fd874d97485b108
OSV_SCANNER_SHA256_LINUX_ARM64=2c71403eb443d05891c4f268c3ad771cf4f16e5443463fd7851ef8f454d3c7e4
OSV_SCANNER_SHA256_LINUX_AMD64=160c6253e2922e9e0a6a9771c5c4c40a4b3c6090b34a3cdd5e80c96cc2e4218b
OSV_SCANNER_SHA256_LINUX_ARM64=4061ef4c021ed3c47f203b818f337e351336cc5cd67c0274fc36bd1dfc728dd7
13 changes: 6 additions & 7 deletions .github/tech-conventions/go-essentials.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ Context should flow through your entire call stack—no exceptions.

* **Always pass `context.Context` as the first parameter** for any operation that could be canceled, timeout, or carry request-scoped values
* **Never store context in structs**—pass it explicitly through function calls
* **Use `context.Background()` only at the top level** (main, tests, or service initialization)
* **Use `context.Background()` only at the top level** (main or service initialization); tests use `t.Context()`
* **Derive child contexts** using `context.WithTimeout()`, `context.WithCancel()`, or `context.WithValue()`
* **Respect context cancellation** by checking `ctx.Done()` in long-running operations

Expand Down Expand Up @@ -197,13 +197,13 @@ func CreateUser(ctx context.Context, user User) error {
// ✅ Explicit initialization
type Cache struct {
mu sync.RWMutex
data map[string]interface{}
data map[string]any
once sync.Once
}

func NewCache() *Cache {
return &Cache{
data: make(map[string]interface{}),
data: make(map[string]any),
}
}

Expand All @@ -215,10 +215,10 @@ func (c *Cache) ensureInitialized() {
}

// 🚫 Hidden initialization
var globalCache map[string]interface{}
var globalCache map[string]any

func init() {
globalCache = make(map[string]interface{})
globalCache = make(map[string]any)
// This runs at import time - unpredictable order
// Hard to test, hard to control
}
Expand Down Expand Up @@ -344,8 +344,7 @@ Write code that performs well by default, and measure when optimization is neede
func BenchmarkUserProcessing(b *testing.B) {
users := generateTestUsers(1000)

b.ResetTimer()
for i := 0; i < b.N; i++ {
for b.Loop() { // times only the loop, not the setup above
processUsers(users)
}
}
Expand Down
9 changes: 4 additions & 5 deletions .github/tech-conventions/testing-standards.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,18 +24,17 @@ We use the `testify` suite for unit tests. All tests must follow these conventio
* Mock external dependencies — tests should be fast and deterministic
* Use descriptive test names that explain the scenario being tested
* Test error cases — ensure your error handling actually works
* Use the test's own helpers: `t.Context()` instead of `context.Background()`, `t.Setenv()` instead of `os.Setenv()`, `t.Chdir()` instead of `os.Chdir()`, and `t.TempDir()` instead of `os.MkdirTemp()`. `t.Setenv()` and `t.Chdir()` restore process state when the test ends; neither can be used in parallel tests or tests with parallel ancestors
* Handle all errors in tests properly:
* `os.Setenv()` returns an error - use `require.NoError(t, err)`
* `os.Unsetenv()` returns an error - use `require.NoError(t, err)`
* `db.Close()` in defer statements - wrap in anonymous function: `defer func() { _ = db.Close() }()`
* Deferred `os.Setenv()` for cleanup - wrap in anonymous function to ignore error

<br><br>

## 📝 Test Structure Example

```go
func TestUserService_CreateUser(t *testing.T) {
func TestUserServiceCreateUser(t *testing.T) {
tests := []struct {
name string
input User
Expand Down Expand Up @@ -78,7 +77,7 @@ func TestUserService_CreateUser(t *testing.T) {
service := NewUserService(mockDB)

// Execute
err := service.CreateUser(context.Background(), tt.input)
err := service.CreateUser(t.Context(), tt.input)

// Assert
if tt.wantErr {
Expand Down Expand Up @@ -207,7 +206,7 @@ func requireUserEqual(t *testing.T, expected, actual User) {
}

// Bad: Overly generic helper
func assertStuff(t *testing.T, a, b interface{}) {
func assertStuff(t *testing.T, a, b any) {
// Too vague, hard to understand intent
}
```
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/codeql-analysis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ jobs:

# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2 # v4.38.2
uses: github/codeql-action/init@24c54180a607b1449ed407dd24f251e4e9147c8d # v4.38.3
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
Expand All @@ -60,7 +60,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@2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2 # v4.38.2
uses: github/codeql-action/autobuild@24c54180a607b1449ed407dd24f251e4e9147c8d # v4.38.3

# ℹ️ Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
Expand All @@ -70,4 +70,4 @@ jobs:
# uses a compiled language

- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2 # v4.38.2
uses: github/codeql-action/analyze@24c54180a607b1449ed407dd24f251e4e9147c8d # v4.38.3
2 changes: 1 addition & 1 deletion .github/workflows/fortress-security-scans.yml
Original file line number Diff line number Diff line change
Expand Up @@ -854,7 +854,7 @@ jobs:
# Scanning hiccup must not fail the security job.
if: always() && inputs.enable-osv && hashFiles('osv-results.sarif') != ''
continue-on-error: true
uses: github/codeql-action/upload-sarif@2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2 # v4.38.2
uses: github/codeql-action/upload-sarif@24c54180a607b1449ed407dd24f251e4e9147c8d # v4.38.3
with:
sarif_file: osv-results.sarif
category: osv-scanner
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/scorecard.yml
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ jobs:
# Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF
# format to the repository Actions tab.
- name: "Upload artifact"
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: SARIF file
path: results.sarif
Expand All @@ -77,6 +77,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@2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2 # v4.38.2
uses: github/codeql-action/upload-sarif@24c54180a607b1449ed407dd24f251e4e9147c8d # v4.38.3
with:
sarif_file: results.sarif
Loading