Skip to content

chore: release

chore: release #2689

Workflow file for this run

name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
env:
CARGO_TERM_COLOR: always
jobs:
changes:
name: Detect Changes
runs-on: ubuntu-latest
outputs:
sdk: ${{ steps.filter.outputs.sdk }}
apply_schema: ${{ steps.filter.outputs.apply_schema }}
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: dorny/paths-filter@fbd0ab8f3e69293af611ebaee6363fc25e6d187d # v4.0.1
id: filter
with:
filters: |
sdk:
- 'sdk/**'
apply_schema:
- 'cli/src/cli.rs'
- 'cli/src/main.rs'
- 'lite/src/init.rs'
- 'cli/schema.json'
cli-schema-drift:
name: CLI Schema Drift
needs: [changes]
if: needs.changes.outputs.apply_schema == 'true'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1
- name: Generate apply schema
run: cargo run -q -p s2-cli -- apply --schema > /tmp/apply.schema.json
- name: Check for schema drift
run: diff -u cli/schema.json /tmp/apply.schema.json
fmt:
name: Format
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: dtolnay/rust-toolchain@nightly
with:
components: rustfmt
- run: cargo +nightly fmt --all --check
- run: cargo +nightly fmt --manifest-path sim/Cargo.toml --check
lockfile:
name: Lockfile
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
- name: Verify Cargo.lock is up-to-date
run: cargo metadata --locked --format-version 1 >/dev/null
sort:
name: Cargo Sort
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: dtolnay/rust-toolchain@stable
- uses: taiki-e/install-action@cargo-sort
- run: cargo sort --workspace --check
deny:
name: Cargo Deny
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: dtolnay/rust-toolchain@stable
- uses: taiki-e/install-action@cargo-deny
- run: cargo deny check
clippy:
name: Clippy
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
submodules: true
- uses: dtolnay/rust-toolchain@stable
with:
components: clippy
- uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1
- name: Install Protoc
uses: arduino/setup-protoc@c65c819552d16ad3c9b72d9dfd5ba5237b9c906b # v3.0.0
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
- run: cargo clippy --workspace --all-features --all-targets -- -D warnings --allow deprecated
- name: Clippy (simulator)
env:
RUSTFLAGS: --cfg tokio_unstable
run: cargo clippy --manifest-path sim/Cargo.toml --all-targets -- -D warnings --allow deprecated
test:
name: Tests
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
submodules: true
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1
- uses: arduino/setup-protoc@c65c819552d16ad3c9b72d9dfd5ba5237b9c906b # v3.0.0
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
- uses: taiki-e/install-action@nextest
- run: cargo nextest run --workspace --all-features --exclude s2-sdk --exclude s2-testcontainers -E 'not (package(s2-cli) & binary(integration))'
testcontainers:
name: Testcontainers
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
submodules: true
- name: Resolve source revision
id: source_revision
run: echo "value=$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT"
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1
- uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0
- name: Read image version
id: image-version
run: |
VERSION=$(sed -n 's/^version = "\(.*\)"$/\1/p' testcontainers/Cargo.toml | head -n1)
echo "value=${VERSION}" >> "$GITHUB_OUTPUT"
- name: Build local S2 Docker image
uses: docker/build-push-action@d08e5c354a6adb9ed34480a06d141179aa583294 # v7.0.0
with:
context: .
target: runtime
tags: ghcr.io/s2-streamstore/s2:${{ steps.image-version.outputs.value }}
load: true
build-args: |
S2_GIT_REV=${{ steps.source_revision.outputs.value }}
cache-from: type=gha,scope=s2-testcontainers
cache-to: type=gha,mode=max,scope=s2-testcontainers
- name: Verify image source revision
env:
S2_GIT_REV: ${{ steps.source_revision.outputs.value }}
run: |
docker run --rm ghcr.io/s2-streamstore/s2:${{ steps.image-version.outputs.value }} --version \
| grep -F "rev $S2_GIT_REV"
- run: cargo test -p s2-testcontainers
simulation:
name: Simulation Tests
# arm64, deliberately: on x86_64 Linux, fastant (via slatedb -> foyer) runs
# a pre-main TSC calibration loop that spins forever under mad-turmoil's
# interposed clock_gettime, hanging the simulator at startup. On aarch64
# fastant does not take that code path. Revisit if mad-turmoil falls back
# to the real clock outside simulation context.
runs-on: ubuntu-24.04-arm
# Simulations that lose determinism or deadlock can hang; fail fast.
timeout-minutes: 30
env:
# Required so turmoil can seed tokio's internal RNG for determinism.
RUSTFLAGS: --cfg tokio_unstable
# The Go linearizability checker must be built from the same rev as the
# s2-verification dependency pinned in sim/Cargo.toml.
S2_VERIFICATION_REV: b4af8c8ef4965d9b335101c422eadb33f3169004
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
submodules: true
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1
- uses: arduino/setup-protoc@c65c819552d16ad3c9b72d9dfd5ba5237b9c906b # v3.0.0
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
- name: Build simulator
run: cargo build --manifest-path sim/Cargo.toml --profile sim
# Determinism first: a broken meta test means seeds are not reproducible
# and any linearizability failure would not be debuggable. Children
# inherit RUST_LOG; trace level compares vastly more output (~50MB vs a
# dozen lines per run), catching nondeterminism that info level misses.
- name: Determinism (meta) tests
env:
RUST_LOG: trace
run: |
./sim/target/sim/sim meta smoke --seed 1
./sim/target/sim/sim meta linearizable --seed 1
./sim/target/sim/sim meta linearizable --seed 2 --fail-rate 0.005
- uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
with:
go-version: stable
cache: false
- name: Build s2-porcupine checker
run: |
git clone https://github.com/s2-streamstore/s2-verification /tmp/s2-verification
git -C /tmp/s2-verification checkout "$S2_VERIFICATION_REV"
cd /tmp/s2-verification/golang/s2-porcupine
go build -o /tmp/s2-porcupine .
- name: Linearizability tests
run: |
for seed in 1 2 3; do
echo "starting"
./sim/target/sim/sim linearizable --seed "$seed" --clients 3 --ops-per-client 50
/tmp/s2-porcupine -file="history.$seed.jsonl"
echo "finished"
done
# And under network chaos (message loss).
for seed in 4 5; do
echo "starting"
./sim/target/sim/sim --fail-rate 0.005 linearizable --seed "$seed" --clients 3 --ops-per-client 50
/tmp/s2-porcupine -file="history.$seed.jsonl"
echo "finished"
done
- name: Upload histories on failure
if: failure()
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
with:
name: sim-histories
path: |
history.*.jsonl
porcupine-outputs/
if-no-files-found: ignore
helm-lint:
name: Helm Chart Lint & Test
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Install Helm
uses: azure/setup-helm@dda3372f752e03dde6b3237bc9431cdc2f7a02a2 # v5.0.0
with:
version: v3.14.0
- name: Lint Helm chart
run: helm lint charts/s2-lite-helm
- name: Test template rendering (default)
run: helm template test-release charts/s2-lite-helm --dry-run > /dev/null
- name: Test with TLS self-signed
run: helm template test-release charts/s2-lite-helm --set tls.enabled=true --set tls.selfSigned=true --dry-run > /dev/null
- name: Test with TLS provided cert
run: helm template test-release charts/s2-lite-helm --set tls.enabled=true --set tls.cert=/etc/tls/tls.crt --set tls.key=/etc/tls/tls.key --dry-run > /dev/null
- name: Test with S3 object storage
run: helm template test-release charts/s2-lite-helm --set objectStorage.enabled=true --set objectStorage.bucket=test-bucket --dry-run > /dev/null
- name: Test with S3 and TLS
run: |
helm template test-release charts/s2-lite-helm \
--set tls.enabled=true \
--set tls.selfSigned=true \
--set objectStorage.enabled=true \
--set objectStorage.bucket=test-bucket \
--set objectStorage.endpoint=https://s3.amazonaws.com \
--set metrics.serviceMonitor.enabled=true \
--dry-run > /dev/null
- name: Test TLS without cert/key fails but selfSigned and provided cert work
run: |
if helm template test-release charts/s2-lite-helm \
--set tls.enabled=true \
--dry-run 2>&1; then
echo "Expected failure but got success"
exit 1
fi
helm template test-release charts/s2-lite-helm \
--set tls.enabled=true \
--set tls.selfSigned=true \
--dry-run > /dev/null
helm template test-release charts/s2-lite-helm \
--set tls.enabled=true \
--set tls.cert=/etc/tls/tls.crt \
--set tls.key=/etc/tls/tls.key \
--dry-run > /dev/null
- name: Test objectStorage without bucket fails
run: |
if helm template test-release charts/s2-lite-helm \
--set objectStorage.enabled=true \
--dry-run 2>&1; then
echo "Expected failure but got success"
exit 1
fi
build-server:
name: Build s2-lite
uses: ./.github/workflows/build-s2-lite.yml
with:
ref: ${{ github.sha }}
sdk-integration-tests:
name: SDKs <> s2-lite Integration Tests
needs: [build-server, test, clippy]
uses: ./.github/workflows/sdk-tests.yml
with:
mode: local
server-binary: server
server-args: "--port 8080"
server-port: 8080
sdks: |
[
{
"name": "go",
"repo": "s2-streamstore/s2-sdk-go",
"ref": "main",
"lang": "go",
"go-version": "1.24",
"test_cmd": "go test -v -count=1 -skip 'WithScope|AccessToken|Metrics|Client_InvalidToken|Location' ./s2/..."
},
{
"name": "typescript",
"repo": "s2-streamstore/s2-sdk-typescript",
"ref": "main",
"lang": "bun",
"bun-version": "latest",
"test_cmd": "S2_LITE=1 bun run vitest --run --exclude '**/account-basin*' --exclude '**/accessTokens*' --exclude '**/metrics*'"
},
{
"name": "python",
"repo": "s2-streamstore/s2-sdk-python",
"ref": "main",
"lang": "python",
"uv-version": "0.11.6",
"test_cmd": "uv run pytest tests/ -v -s -m '(account or basin or stream) and not access_tokens and not locations'"
},
{
"name": "rust",
"repo": "${{ github.repository }}",
"ref": "${{ github.sha }}",
"lang": "rust",
"test_cmd": "cargo test -p s2-sdk --all-features -- --skip access_token --skip metrics"
}
]
rust-sdk:
name: Rust SDK
needs: [test, clippy, changes]
if: needs.changes.outputs.sdk == 'true'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1
- name: Check docs
run: cargo doc -p s2-sdk --all-features --no-deps
env:
RUSTDOCFLAGS: "-D warnings"
- name: Run tests
run: cargo test -p s2-sdk --all-features
env:
S2_ACCESS_TOKEN: ${{ secrets.S2_ACCESS_TOKEN_FOR_RUST_SDK_TESTS }}
cli-integration-tests:
name: CLI <> s2-lite Integration Tests
needs: [build-server, test, clippy]
uses: ./.github/workflows/sdk-tests.yml
with:
mode: local
server-binary: server
server-args: "--port 8080"
server-port: 8080
sdks: |
[
{
"name": "cli",
"repo": "${{ github.repository }}",
"ref": "${{ github.sha }}",
"lang": "rust",
"test_cmd": "cargo test -p s2-cli --test integration -j 1"
}
]