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
26 changes: 15 additions & 11 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -1,22 +1,26 @@
version: 2
updates:
# Library module: the state kernel.
# Go modules across the whole suite. The "/**" glob covers every module that
# carries a go.mod (the state kernel, telemetry adapters, transport, wasm, the
# sink core, every SDK-backed sink destination, the examples, and the build
# tooling). The SDK destinations are where transitive advisories (x/crypto,
# x/net, x/sys, and the cloud SDKs themselves) surface, so they must be watched
# too. Updates are grouped per module so each module's bumps land in a single
# PR rather than one PR per dependency.
- package-ecosystem: gomod
directory: /state
directories:
- "/**"
schedule:
interval: weekly
groups:
go-modules:
patterns:
- "*"
commit-message:
prefix: "chore"

# Build-automation module.
- package-ecosystem: gomod
directory: /magefiles
schedule:
interval: weekly
commit-message:
prefix: "chore"

# GitHub Actions workflows.
# GitHub Actions workflows. Keeps the SHA-pinned action references current
# (Dependabot updates both the pin and its version comment).
- package-ecosystem: github-actions
directory: /
schedule:
Expand Down
155 changes: 28 additions & 127 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ jobs:
code: ${{ steps.detect.outputs.code }}
docs: ${{ steps.detect.outputs.docs }}
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
with:
fetch-depth: 0
- name: Detect non-docs changes
Expand Down Expand Up @@ -69,8 +69,8 @@ jobs:
if: needs.changes.outputs.code == 'true'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/setup-go@v6
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
with:
go-version: "1.26.4"
cache-dependency-path: "**/go.sum"
Expand Down Expand Up @@ -132,24 +132,34 @@ jobs:
working-directory: sink/slog
run: go run "$GOLANGCI_LINT" run --config "$GITHUB_WORKSPACE/.golangci.yml" ./...

# The race-test matrix lives in a reusable workflow so its legs render as a
# single collapsible tree in the checks UI ("tests / test (1.25.11, …)") rather
# than as flat top-level checks. Keep the module list in sync with the lint,
# vuln, and coverage jobs below.
# The state-machine race-test matrix lives in a reusable workflow so its legs
# render as a single collapsible "state machine tests / …" tree in the checks
# UI rather than as flat top-level checks. The sink-domain legs live in their
# own "sink" tree (see the `sink` job below). Keep this module list in sync
# with the lint, vuln, and coverage jobs below.
tests:
name: state machine tests
needs: changes
if: needs.changes.outputs.code == 'true'
uses: ./.github/workflows/test.yml
with:
modules: "state state/expr durable cluster transport wasm e2e examples/fooddelivery examples/dispatch telemetry telemetry/slog telemetry/otel telemetry/datadog sink sink/bridge sink/file sink/http sink/prometheus sink/slog"
modules: "state state/expr durable cluster transport wasm e2e examples/fooddelivery examples/dispatch telemetry telemetry/slog telemetry/otel telemetry/datadog"

# Every sink-domain check (in-workspace race tests, the SDK-backed destination
# matrix, and the integration leg) groups under a single collapsible "sink / …"
# tree via this reusable workflow.
sink:
needs: changes
if: needs.changes.outputs.code == 'true'
uses: ./.github/workflows/sink.yml

vuln:
needs: changes
if: needs.changes.outputs.code == 'true'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/setup-go@v6
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
with:
go-version: "1.26.4"
cache-dependency-path: "**/go.sum"
Expand Down Expand Up @@ -218,8 +228,8 @@ jobs:
env:
THRESHOLD: "80"
steps:
- uses: actions/checkout@v6
- uses: actions/setup-go@v6
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
with:
go-version: "1.26.4"
cache-dependency-path: "**/go.sum"
Expand Down Expand Up @@ -435,11 +445,11 @@ jobs:
BASE_SHA: ${{ github.event.pull_request.base.sha }}
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
with:
# Need both base and head commits present for the worktree diff.
fetch-depth: 0
- uses: actions/setup-go@v6
- uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
with:
go-version: "1.26.4"
cache-dependency-path: "**/go.sum"
Expand Down Expand Up @@ -511,8 +521,8 @@ jobs:
run:
working-directory: docs
steps:
- uses: actions/checkout@v6
- uses: actions/setup-go@v6
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
with:
go-version: "1.26.4"
cache-dependency-path: "**/go.sum"
Expand All @@ -522,7 +532,7 @@ jobs:
- name: Generate API reference + diagrams
working-directory: .
run: go run ./tools/docsgen
- uses: actions/setup-node@v5
- uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0
with:
node-version: "22"
cache: npm
Expand All @@ -532,115 +542,6 @@ jobs:
- name: Build site
run: npm run build

# The SDK-backed sink destinations are standalone modules kept out of the
# workspace (see go.work / the magefile), so they build with GOWORK=off via
# their own replace directives. Each is one matrix leg across the OS matrix for
# race tests; lint, vuln, and the coverage gate run on Linux. This keeps the
# vendor SDKs out of the core modules' dependency graphs.
sink-destinations:
needs: changes
if: needs.changes.outputs.code == 'true'
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
module:
- sink/cloudwatch
- sink/dynamo
- sink/eventbridge
- sink/firehose
- sink/gcppubsub
- sink/kafka
- sink/kinesis
- sink/nats
- sink/otel
- sink/redis
- sink/s3
- sink/sns
- sink/sql
- sink/sqs
- sink/statsd
- sink/timestream
- examples/sinkflow
runs-on: ${{ matrix.os }}
env:
GOWORK: "off"
THRESHOLD: "80"
steps:
- uses: actions/checkout@v6
- uses: actions/setup-go@v6
with:
go-version: "1.26.4"
cache-dependency-path: "**/go.sum"
- name: test -race
shell: bash
run: go test -C "${{ matrix.module }}" -race ./...
- name: golangci-lint
if: matrix.os == 'ubuntu-latest'
shell: bash
run: go -C "${{ matrix.module }}" run "$GOLANGCI_LINT" run --config "$GITHUB_WORKSPACE/.golangci.yml" ./...
- name: govulncheck
if: matrix.os == 'ubuntu-latest'
shell: bash
run: go -C "${{ matrix.module }}" run "$GOVULNCHECK" ./...
- name: coverage gate
if: matrix.os == 'ubuntu-latest'
shell: bash
run: |
go test -C "${{ matrix.module }}" -covermode=atomic -coverprofile=coverage.out ./...
pct=$(go -C "${{ matrix.module }}" tool cover -func=coverage.out | awk '/^total:/ {sub(/%/,"",$3); print $3}')
echo "total coverage: ${pct}% (threshold ${THRESHOLD}%)"
awk -v p="$pct" -v t="$THRESHOLD" 'BEGIN { exit (p+0 < t+0) ? 1 : 0 }' \
|| { echo "::error::coverage ${pct}% is below the ${THRESHOLD}% threshold"; exit 1; }

# Integration / E2E leg, behind the `integration` build tag, run with
# GOWORK=off. The hermetic destinations (sql, http, file, slog, prometheus,
# statsd, otel) and the flagship sinkflow example run end-to-end; the
# container-backed destinations drive a real emulator via testcontainers
# (Docker is available on GitHub-hosted ubuntu runners) and skip cleanly if a
# daemon is ever absent. Kept off the default test matrix so the hermetic
# checks stay fast.
integration:
needs: changes
if: needs.changes.outputs.code == 'true'
strategy:
fail-fast: false
matrix:
module:
- sink/file
- sink/http
- sink/prometheus
- sink/slog
- sink/sql
- sink/statsd
- sink/otel
- sink/cloudwatch
- sink/dynamo
- sink/eventbridge
- sink/firehose
- sink/gcppubsub
- sink/kafka
- sink/kinesis
- sink/nats
- sink/redis
- sink/s3
- sink/sns
- sink/sqs
- sink/timestream
- examples/sinkflow
runs-on: ubuntu-latest
env:
GOWORK: "off"
steps:
- uses: actions/checkout@v6
- uses: actions/setup-go@v6
with:
go-version: "1.26.4"
cache-dependency-path: "**/go.sum"
- name: integration tests
shell: bash
run: go test -C "${{ matrix.module }}" -tags integration ./...

# Single required status check. Branch protection requires only `gate`, which
# aggregates the required jobs: it fails if any of them failed or was
# cancelled, and treats a skipped job (docs-only PRs, or PRs that touch no
Expand All @@ -649,7 +550,7 @@ jobs:
# never blocks a merge.
gate:
if: always()
needs: [changes, lint, tests, vuln, coverage, docs, sink-destinations, integration]
needs: [changes, lint, tests, sink, vuln, coverage, docs]
runs-on: ubuntu-latest
steps:
- name: Fail if a required job did not pass
Expand Down
77 changes: 77 additions & 0 deletions .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
name: CodeQL

# Static analysis (SAST) over the Go sources. Runs on every PR and on pushes to
# the default branch, plus a weekly scheduled scan so newly published query
# packs catch existing code. Results land in the code-scanning dashboard.
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
schedule:
- cron: '24 6 * * 1'

# Read-only by default; the analyze job opts into security-events:write.
permissions:
contents: read

concurrency:
group: codeql-${{ github.ref }}
cancel-in-progress: true

jobs:
analyze:
name: Analyze (Go)
runs-on: ubuntu-latest
permissions:
# Required to upload CodeQL results to the code-scanning dashboard.
security-events: write
contents: read
steps:
- name: Checkout
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
with:
persist-credentials: false

# cache: false is deliberate. CodeQL's Go extractor only sees code that is
# actually compiled while it traces the build; a warm build cache (shared
# with the other CI jobs) would make `go build` a no-op and yield "no source
# code seen during build". Starting cold guarantees real compilation.
- uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
with:
go-version: "1.26.4"
cache: false

# Go does not support build-mode: none, so extraction is traced through a
# real build. There is no root module to build and the SDK-backed sink
# destinations live outside the workspace, so the manual build walks the
# in-workspace modules (the same set ci.yml lints and tests) and compiles
# each under the CodeQL tracer.
- name: Initialize CodeQL
uses: github/codeql-action/init@d77b13a0df3134d64a457ea9003f600b09fa1c8a # v3.36.1
with:
languages: go
build-mode: manual

- name: Build (CodeQL tracing)
shell: bash
env:
MODULES: "state state/expr durable cluster transport wasm e2e examples/fooddelivery examples/dispatch telemetry telemetry/slog telemetry/otel telemetry/datadog sink sink/bridge sink/file sink/http sink/prometheus sink/slog"
run: |
# Force a cold build cache so every package is recompiled under the
# CodeQL tracer (otherwise nothing is extracted; see cache: false above).
go clean -cache
# Build from inside each module dir (cd, not `go build -C`): the
# extractor traces the in-process compiles, and `-C` re-execs the go
# command in a way the tracer does not follow, which yields an empty
# database ("no source code seen during build").
for module in $MODULES; do
echo "::group::build ($module)"
( cd "$module" && go build ./... )
echo "::endgroup::"
done

- name: Perform CodeQL analysis
uses: github/codeql-action/analyze@d77b13a0df3134d64a457ea9003f600b09fa1c8a # v3.36.1
with:
category: "/language:go"
10 changes: 5 additions & 5 deletions .github/workflows/docs-deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ jobs:
run:
working-directory: docs
steps:
- uses: actions/checkout@v6
- uses: actions/setup-go@v6
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
with:
go-version: "1.26.4"
cache-dependency-path: "**/go.sum"
Expand All @@ -42,7 +42,7 @@ jobs:
- name: Generate API reference + diagrams
working-directory: .
run: go run ./tools/docsgen
- uses: actions/setup-node@v5
- uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0
with:
node-version: "22"
cache: npm
Expand All @@ -52,7 +52,7 @@ jobs:
- name: Build site
run: npm run build
- name: Upload Pages artifact
uses: actions/upload-pages-artifact@v5
uses: actions/upload-pages-artifact@fc324d3547104276b827a68afc52ff2a11cc49c9 # v5.0.0
with:
path: docs/dist

Expand All @@ -65,4 +65,4 @@ jobs:
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v5
uses: actions/deploy-pages@cd2ce8fcbc39b97be8ca5fce6e763baed58fa128 # v5.0.0
Loading
Loading