Skip to content

Commit 01947ce

Browse files
Merge pull request #49 from CodeMonkeyCybersecurity/claude/eos-testing-hooks-research-011CUqdYgtJ84JQGM45kEXYh
Claude/eos testing hooks research 011 c uqd ygt j84 jqgm45k ex yh
2 parents ace646a + b0b6db4 commit 01947ce

504 files changed

Lines changed: 16436 additions & 7026 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
# Flakiness Detection Workflow
2+
# Runs changed tests multiple times to detect flaky/unstable tests
3+
# Last Updated: 2025-11-05
4+
5+
name: Flakiness Detection
6+
7+
on:
8+
pull_request:
9+
paths:
10+
- '**/*_test.go' # Run when test files change
11+
- 'pkg/**/*.go' # Run when production code changes (tests might become flaky)
12+
13+
jobs:
14+
detect-flaky-tests:
15+
runs-on: ubuntu-latest
16+
timeout-minutes: 30
17+
18+
steps:
19+
- name: Checkout code
20+
uses: actions/checkout@v4
21+
with:
22+
fetch-depth: 2 # Need previous commit for diff
23+
24+
- name: Set up Go
25+
uses: actions/setup-go@v5
26+
with:
27+
go-version: '1.24'
28+
cache: true
29+
30+
- name: Get changed test files
31+
id: changed-tests
32+
run: |
33+
# Find all changed test files (both new and modified)
34+
git diff --name-only HEAD~1 HEAD | grep '_test.go$' > changed_tests.txt || true
35+
36+
if [ -s changed_tests.txt ]; then
37+
echo "has_changes=true" >> $GITHUB_OUTPUT
38+
echo "::notice::Found $(wc -l < changed_tests.txt) changed test files"
39+
cat changed_tests.txt
40+
else
41+
echo "has_changes=false" >> $GITHUB_OUTPUT
42+
echo "::notice::No test files changed"
43+
fi
44+
45+
- name: Run changed tests 10 times to detect flakiness
46+
if: steps.changed-tests.outputs.has_changes == 'true'
47+
id: flakiness-check
48+
continue-on-error: true
49+
run: |
50+
# Track failures
51+
FLAKY_TESTS=""
52+
EXIT_CODE=0
53+
54+
while IFS= read -r test_file; do
55+
package_path=$(dirname "$test_file")
56+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
57+
echo "Testing $package_path for flakiness (10 runs with race detector)..."
58+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
59+
60+
# Run test 10 times with race detector
61+
if ! go test -count=10 -race -v "./$package_path"; then
62+
echo "::error file=$test_file::Flaky test detected - failed when run multiple times"
63+
FLAKY_TESTS="$FLAKY_TESTS\n- $test_file"
64+
EXIT_CODE=1
65+
else
66+
echo "::notice file=$test_file::Test is stable (passed all 10 runs)"
67+
fi
68+
69+
echo ""
70+
done < changed_tests.txt
71+
72+
if [ $EXIT_CODE -ne 0 ]; then
73+
echo "flaky_tests<<EOF" >> $GITHUB_OUTPUT
74+
echo -e "$FLAKY_TESTS" >> $GITHUB_OUTPUT
75+
echo "EOF" >> $GITHUB_OUTPUT
76+
fi
77+
78+
exit $EXIT_CODE
79+
80+
- name: Comment on PR if flaky tests found
81+
if: failure() && steps.flakiness-check.outcome == 'failure'
82+
uses: actions/github-script@v7
83+
with:
84+
script: |
85+
const flakyTests = process.env.FLAKY_TESTS || 'Unknown tests';
86+
87+
const message = `## ⚠️ Flaky Test Detected!
88+
89+
One or more tests failed when run multiple times with the race detector. This indicates non-deterministic behavior that must be fixed before merging.
90+
91+
### Flaky Tests
92+
${flakyTests}
93+
94+
### Common Causes
95+
- **Race conditions**: Use \`-race\` flag to detect data races
96+
- **Timing dependencies**: Replace \`time.Sleep()\` with polling + timeout
97+
- **Map iteration order**: Sort maps before comparing
98+
- **Shared global state**: Ensure proper test isolation
99+
- **Non-deterministic random values**: Use fixed seeds for testing
100+
101+
### How to Fix
102+
1. Run locally with \`go test -count=10 -race ./path/to/package\`
103+
2. Review [Flakiness Prevention Guide](https://github.com/CodeMonkeyCybersecurity/eos/blob/main/INTEGRATION_TESTING.md#flakiness-prevention)
104+
3. Consider quarantining with \`//go:build flaky\` tag if immediate fix isn't possible
105+
106+
### Resources
107+
- [Go Testing Best Practices](https://go.dev/wiki/TestComments)
108+
- [Detecting Flakiness](https://circleci.com/blog/reducing-flaky-test-failures/)
109+
- [Eos Integration Testing Guide](/INTEGRATION_TESTING.md)
110+
111+
**This PR cannot be merged until flakiness is resolved.**`;
112+
113+
await github.rest.issues.createComment({
114+
issue_number: context.issue.number,
115+
owner: context.repo.owner,
116+
repo: context.repo.repo,
117+
body: message
118+
});
119+
env:
120+
FLAKY_TESTS: ${{ steps.flakiness-check.outputs.flaky_tests }}
121+
122+
- name: Fail workflow if flaky tests detected
123+
if: failure() && steps.flakiness-check.outcome == 'failure'
124+
run: |
125+
echo "::error::Flaky tests detected. See PR comment for details."
126+
exit 1

.pre-commit-config.yaml

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
# Eos Pre-Commit Hook Configuration
2+
# Last Updated: 2025-11-05
3+
#
4+
# Installation:
5+
# pip install pre-commit
6+
# pre-commit install
7+
#
8+
# Run manually:
9+
# pre-commit run --all-files
10+
#
11+
# Update hooks:
12+
# pre-commit autoupdate
13+
14+
repos:
15+
# Go-specific hooks from TekWizely (most flexible for Go monorepos)
16+
- repo: https://github.com/TekWizely/pre-commit-golang
17+
rev: v1.0.0-rc.1
18+
hooks:
19+
# Format Go code
20+
- id: go-fmt
21+
name: Format Go code (gofmt)
22+
description: Ensures all Go code is properly formatted
23+
24+
# Organize imports
25+
- id: go-imports
26+
name: Organize imports (goimports)
27+
description: Ensures imports are organized correctly
28+
29+
# Run go vet
30+
- id: go-vet
31+
name: Static analysis (go vet)
32+
description: Runs go vet for static analysis
33+
args: [] # Can add CGO_ENABLED=1 if needed
34+
35+
# Run golangci-lint
36+
- id: golangci-lint
37+
name: Lint (golangci-lint)
38+
description: Runs golangci-lint with project config
39+
args: [--timeout=5m]
40+
41+
# Ensure go.mod and go.sum are tidy
42+
- id: go-mod-tidy
43+
name: Verify go.mod is tidy
44+
description: Ensures go.mod and go.sum are up to date
45+
args: [-v]
46+
47+
# Local hooks for custom checks
48+
- repo: local
49+
hooks:
50+
# Run fast tests (skip integration and E2E)
51+
- id: go-test-fast
52+
name: Run unit tests
53+
entry: go test -race -short -v ./...
54+
language: system
55+
pass_filenames: false
56+
description: Runs fast unit tests with race detector
57+
58+
# Check test coverage
59+
- id: go-coverage-check
60+
name: Check test coverage
61+
entry: bash -c 'go test -coverprofile=coverage.out -covermode=atomic ./... && go run github.com/vladopajic/go-test-coverage/v2@latest --config=.testcoverage.yml'
62+
language: system
63+
pass_filenames: false
64+
description: Ensures test coverage meets thresholds
65+
66+
# Build verification
67+
- id: go-build
68+
name: Verify build
69+
entry: go build -o /tmp/eos-build-precommit ./cmd/
70+
language: system
71+
pass_filenames: false
72+
description: Ensures code compiles successfully
73+
74+
# Verify E2E tests have build tags
75+
- id: verify-e2e-build-tags
76+
name: Verify E2E build tags
77+
entry: bash -c 'for f in test/e2e/*_test.go; do head -1 "$f" | grep -q "//go:build e2e" || { echo "ERROR: $f missing //go:build e2e tag"; exit 1; }; done'
78+
language: system
79+
pass_filenames: false
80+
description: Ensures all E2E tests have proper build tags
81+
82+
# Check for deprecated benchmark pattern
83+
- id: check-benchmark-pattern
84+
name: Check for deprecated benchmarks
85+
entry: bash -c '! git grep -n "for.*b\.N.*{" -- "*_test.go" || { echo "ERROR: Found deprecated benchmark pattern. Use B.Loop() instead of for b.N"; exit 1; }'
86+
language: system
87+
pass_filenames: false
88+
description: Detects deprecated benchmark patterns
89+
90+
# Global settings
91+
fail_fast: false # Run all hooks even if one fails
92+
minimum_pre_commit_version: '2.20.0'

.testcoverage.yml

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
# Test Coverage Configuration for Eos
2+
# Last Updated: 2025-11-05
3+
#
4+
# Tool: vladopajic/go-test-coverage
5+
# Docs: https://github.com/vladopajic/go-test-coverage
6+
#
7+
# Usage:
8+
# go test -coverprofile=coverage.out -covermode=atomic ./...
9+
# go-test-coverage --config=.testcoverage.yml
10+
11+
# Coverage thresholds
12+
threshold:
13+
# Overall minimum coverage across all packages
14+
total: 80
15+
16+
# Per-file minimum coverage
17+
file: 70
18+
19+
# Files to exclude from coverage requirements
20+
exclude:
21+
# Generated code (protobuf, codegen, etc.)
22+
- ".*\\.pb\\.go$"
23+
- ".*\\.gen\\.go$"
24+
- ".*_generated\\.go$"
25+
26+
# Mock files
27+
- "mock_.*\\.go$"
28+
- ".*_mock\\.go$"
29+
30+
# Platform compatibility stubs (intentionally minimal)
31+
- ".*_stub\\.go$"
32+
33+
# Test utilities themselves
34+
- "pkg/testutil/.*"
35+
- "test/e2e/framework\\.go$"
36+
37+
# Main functions (hard to test without full binary execution)
38+
- "cmd/.*/main\\.go$"
39+
40+
# Vendor directory (external dependencies)
41+
- "vendor/.*"
42+
43+
# Documentation/examples that don't need coverage
44+
- ".*_example\\.go$"
45+
46+
# Badge configuration (optional - generates coverage badge)
47+
badge:
48+
# File name for coverage badge SVG
49+
file-name: coverage.svg
50+
51+
# Badge styling
52+
badge-color: green # Color when coverage is good
53+
54+
# Output format
55+
output:
56+
format: text # Options: text, github-actions
57+
58+
# Exclusion rules by package
59+
package:
60+
# Example: Exclude entire packages if needed
61+
# exclude:
62+
# - "github.com/CodeMonkeyCybersecurity/eos/pkg/deprecated"

0 commit comments

Comments
 (0)