Skip to content

Nightly

Nightly #136

Workflow file for this run

name: Nightly
on:
schedule:
# Run daily at 2 AM UTC (same as security scans)
- cron: '0 2 * * *'
workflow_dispatch: # Allow manual triggering
permissions:
contents: read
jobs:
# =============================================================================
# Benchmark Comparison (detailed analysis against develop branch)
# =============================================================================
# This runs full benchmarks with statistical comparison against develop.
# PRs run basic benchmarks; nightly runs the full comparison.
benchmark-comparison:
name: Benchmark Comparison
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Checkout code
uses: actions/checkout@v6
with:
fetch-depth: 0 # Need full history for branch comparison
- name: Set up Go
uses: actions/setup-go@v6
with:
go-version: '1.26.1'
cache: true
- name: Set up buf
uses: bufbuild/buf-setup-action@v1
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
- name: Generate protobuf files
run: buf generate
- name: Download dependencies
run: go mod download
- name: Install benchstat
run: go install golang.org/x/perf/cmd/benchstat@latest
- name: Run current benchmarks
run: |
echo "Running benchmarks on current HEAD..."
go test -bench=. -benchmem -count=5 ./shared/domain/models/ ./shared/platform/audit/ > new.txt 2>&1 || true
- name: Run develop branch benchmarks
run: |
echo "Checking out develop branch for comparison..."
git stash --include-untracked || true
git checkout origin/develop -- shared/domain/models/ shared/platform/audit/ 2>/dev/null || true
echo "Running benchmarks on develop..."
go test -bench=. -benchmem -count=5 ./shared/domain/models/ ./shared/platform/audit/ > old.txt 2>&1 || true
# Restore current branch
git checkout - -- . 2>/dev/null || true
git stash pop || true
- name: Generate comparison report
run: |
echo "## Nightly Benchmark Comparison" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "Comparing HEAD against develop branch" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
if [ -f old.txt ] && [ -f new.txt ]; then
echo '```' >> $GITHUB_STEP_SUMMARY
benchstat old.txt new.txt >> $GITHUB_STEP_SUMMARY 2>&1 || echo "Comparison failed" >> $GITHUB_STEP_SUMMARY
echo '```' >> $GITHUB_STEP_SUMMARY
else
echo "Benchmark files not available for comparison" >> $GITHUB_STEP_SUMMARY
fi
# =============================================================================
# Full Integration Tests (including slow/timing-sensitive tests)
# =============================================================================
# These tests are timing-sensitive (network timeouts, exponential backoff)
# and are skipped in regular CI (via -short flag) to avoid flakiness from
# CPU scheduler variance. Running them nightly ensures they're validated.
slow-integration-tests:
name: Slow Integration Tests
runs-on: ubuntu-latest
timeout-minutes: 45
# Note: No postgres service container needed - tests use testcontainers
# which manage their own ephemeral containers with proper isolation.
steps:
- name: Checkout code
uses: actions/checkout@v6
- name: Set up Go
uses: actions/setup-go@v6
with:
go-version: '1.26.1'
cache: true
- name: Set up buf
uses: bufbuild/buf-setup-action@v1
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
- name: Generate protobuf files
run: buf generate
- name: Download dependencies
run: go mod download
- name: Install gotestsum
run: go install gotest.tools/gotestsum@v1.13.0
- name: Run full test suite (including slow tests)
env:
SKIP_KAFKA_TESTS: "1"
# Note: No DATABASE_URL needed - tests that require a database
# use testcontainers or mock their own configuration
run: |
# Run WITHOUT -short flag to include all timing-sensitive tests
# Regular CI runs with -short, but nightly runs the full suite
mkdir -p coverage
echo "Running full test suite including timing-sensitive tests..."
gotestsum --format testdox \
--junitfile test-results.xml \
--jsonfile test-results.json \
-- -race -coverprofile=coverage/coverage.out -covermode=atomic -timeout 15m ./...
- name: Filter generated files from coverage
if: always()
run: |
if [ -f coverage/coverage.out ]; then
grep -v -E '\.pb\.go|\.pb\.validate\.go|_grpc\.pb\.go' coverage/coverage.out > coverage/coverage-filtered.out || true
fi
- name: Upload coverage to Codecov
if: always()
uses: codecov/codecov-action@v5
with:
files: ./coverage/coverage-filtered.out
flags: integration
name: nightly-full-suite
fail_ci_if_error: false
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
- name: Upload test results
uses: actions/upload-artifact@v7
if: always()
with:
name: nightly-test-results
path: |
test-results.xml
test-results.json
- name: Test summary
uses: test-summary/action@v2
if: always()
with:
paths: test-results.xml
- name: Annotate failures
if: failure()
run: |
# gotestsum --jsonfile produces newline-delimited JSON (one object per line)
# Filter for test failures (not package-level) and deduplicate
jq -r 'select(.Action == "fail" and .Test != null) | "::error file=\(.Package | sub("github.com/meridianhub/meridian/"; "")),line=1::\(.Test) failed"' test-results.json | sort -u || true