Skip to content

docs: update Jupiter program ID and health status example in README +… #7

docs: update Jupiter program ID and health status example in README +…

docs: update Jupiter program ID and health status example in README +… #7

Workflow file for this run

name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
workflow_dispatch: {}
concurrency:
group: ci-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
env:
CARGO_TERM_COLOR: always
RUST_BACKTRACE: 1
jobs:
# ---------------------------------------------------------------------------
# Hard-gate jobs (required on every PR to main).
# ---------------------------------------------------------------------------
lint:
name: lint (fmt + clippy)
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 1
- name: Install toolchain (pinned MSRV via rust-toolchain.toml)
uses: dtolnay/rust-toolchain@1.88.0
with:
components: rustfmt, clippy
- name: Cache cargo registry + target
uses: Swatinem/rust-cache@v2
with:
shared-key: "solarix-ci"
- name: cargo fmt --check
run: cargo fmt -- --check
- name: cargo clippy (all-targets, -D warnings)
run: cargo clippy --release --all-targets -- -D warnings
unit:
name: unit tests
runs-on: ubuntu-latest
timeout-minutes: 12
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 1
- name: Install toolchain
uses: dtolnay/rust-toolchain@1.88.0
- name: Cache cargo registry + target
uses: Swatinem/rust-cache@v2
with:
shared-key: "solarix-ci"
- name: cargo test --lib
run: cargo test --release --lib
integration:
name: integration tests
runs-on: ubuntu-latest
timeout-minutes: 15
services:
postgres:
image: postgres:16
env:
POSTGRES_DB: solarix
POSTGRES_USER: solarix
POSTGRES_PASSWORD: solarix
ports:
- 5432:5432
options: >-
--health-cmd "pg_isready -U solarix -d solarix"
--health-interval 5s
--health-timeout 5s
--health-retries 5
env:
DATABASE_URL: postgres://solarix:solarix@localhost:5432/solarix
RUST_LOG: warn
# NOTE: SOLANA_RPC_URL is NOT set at this level. The integration tests
# that run today (bootstrap_test.rs, registration_test.rs) do not hit
# the Solana RPC — they only exercise the DB bootstrap and registration
# paths. Any future test that needs RPC should use a LiteSVM harness or
# a local RPC fake; devnet is too rate-limited and too flaky for the
# per-PR critical path (see ADR-0002 D2 — this is the same reason the
# mainnet smoke test is isolated into `nightly.yml`).
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 1
- name: Install toolchain
uses: dtolnay/rust-toolchain@1.88.0
- name: Cache cargo registry + target
uses: Swatinem/rust-cache@v2
with:
shared-key: "solarix-ci"
- name: Run integration tests (branches on 6.5 feature flag)
run: |
# Story 6.5 adds `[features] integration = []` to Cargo.toml and the
# `tests/common/postgres.rs` harness. Until the harness lands, run the
# existing bootstrap_test.rs / registration_test.rs against the
# postgres service container above. The feature guard check below
# automatically flips to `--features integration` once Cargo.toml
# declares it.
if grep -q '^integration\b' Cargo.toml; then
cargo test --release --tests --features integration
else
cargo test --release --tests
fi
coverage:
name: coverage (lcov artifact)
runs-on: ubuntu-latest
timeout-minutes: 12
# NOTE: intentionally no `needs: unit`. Both jobs build the same code;
# running them in parallel means a broken PR surfaces both failures at
# once and the 12-minute end-to-end target is easier to hit. The previous
# `needs: unit` gave no correctness benefit.
steps:
- uses: actions/checkout@v4
with:
# Coverage does not currently need git history; the delta gate is
# descoped (ADR-0002 D3). Restore to `fetch-depth: 0` when the
# delta-gate follow-up story lands.
fetch-depth: 1
- name: Install toolchain
uses: dtolnay/rust-toolchain@1.88.0
with:
components: llvm-tools-preview
- name: Cache cargo registry + target
# Separate cache key from the rest of `solarix-ci` because
# `cargo-llvm-cov` sets `RUSTFLAGS=-Cinstrument-coverage`, which
# produces `.rlib` artifacts that are incompatible with the other
# jobs' builds. Sharing the cache would cause thrashing (either
# job's target/ would force the other to fully rebuild).
uses: Swatinem/rust-cache@v2
with:
shared-key: "solarix-ci-coverage"
- name: Install cargo-llvm-cov (cached binary)
# `cargo install --locked` re-compiles from source every run (~3–5 min
# cold tax). `taiki-e/install-action` fetches a prebuilt binary and
# caches it per version, bringing the install down to a few seconds.
uses: taiki-e/install-action@v2
with:
tool: cargo-llvm-cov
- name: Run coverage (lib only — see ADR-0002 D6)
run: cargo llvm-cov --release --lib --lcov --output-path lcov.info
- name: Print coverage summary
run: cargo llvm-cov report --summary-only
- name: Upload lcov artifact
uses: actions/upload-artifact@v4
with:
name: lcov-info
path: lcov.info
retention-days: 14
# Fail the step (not just warn) if `cargo llvm-cov` silently
# produced no output. The default `warn` hides this regression.
if-no-files-found: error
fuzz-smoke:
name: fuzz smoke (60s)
runs-on: ubuntu-latest
timeout-minutes: 8
# NOTE: this job is now a HARD gate on every run. The original "soft gate"
# guard `if: hashFiles('fuzz/Cargo.toml') != ''` was permanently true
# because Story 6.4 already landed `fuzz/Cargo.toml` and
# `fuzz/fuzz_targets/decode_instruction.rs` before this story merged
# (see ADR-0002 § D1). Removing the guard matches what actually runs.
continue-on-error: false
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 1
- name: Install nightly toolchain
uses: dtolnay/rust-toolchain@nightly
- name: Cache cargo registry + target
uses: Swatinem/rust-cache@v2
with:
shared-key: "solarix-ci-nightly"
- name: Install cargo-fuzz (cached binary)
uses: taiki-e/install-action@v2
with:
tool: cargo-fuzz
- name: Run fuzz smoke
# cargo-fuzz defaults to x86_64-unknown-linux-musl on some runners,
# which is incompatible with ASAN (-Zsanitizer=address requires dynamic
# libc). Explicitly target gnu to avoid the "sanitizer is incompatible
# with statically linked libc" build error.
run: cargo +nightly fuzz run --target x86_64-unknown-linux-gnu decode_instruction -- -max_total_time=60
security:
name: security (audit + deny + gitleaks)
runs-on: ubuntu-latest
timeout-minutes: 8
steps:
- uses: actions/checkout@v4
with:
# gitleaks scans against the diff base, and a future audit step may
# want history too.
fetch-depth: 0
- name: Install toolchain
uses: dtolnay/rust-toolchain@1.88.0
- name: Cache cargo registry + target
uses: Swatinem/rust-cache@v2
with:
shared-key: "solarix-ci"
- name: Install cargo-audit and cargo-deny (cached binaries)
uses: taiki-e/install-action@v2
with:
tool: cargo-audit,cargo-deny
- name: cargo audit
# --deny warnings is intentionally omitted: unmaintained/yanked warnings
# from Solana transitive deps (litesvm, sqlx-mysql) have no upgrade path.
# Unfixable CVEs are explicitly acknowledged here; cargo deny check
# advisories (below) enforces the full advisory policy via deny.toml.
run: |
cargo audit \
--ignore RUSTSEC-2024-0344 \
--ignore RUSTSEC-2022-0093 \
--ignore RUSTSEC-2023-0071
- name: cargo deny check (advisories + bans + sources — licenses is fail-soft per ADR-0002 D5)
run: cargo deny check advisories bans sources
- name: gitleaks
uses: gitleaks/gitleaks-action@v2
with:
config: .gitleaks.toml
docker-smoke:
name: docker smoke (compose up → /health → logs)
runs-on: ubuntu-latest
timeout-minutes: 15
env:
# Inherited by `docker-compose.yml`'s `${SOLANA_RPC_URL:-...}` expansion.
# `docker-compose.yml` wires DATABASE_URL itself via the postgres service;
# the workflow must NOT set DATABASE_URL at this level.
SOLANA_RPC_URL: https://api.devnet.solana.com
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 1
- name: Reset any stale compose state
run: docker compose down -v || true
- name: docker compose up --build -d
run: docker compose up --build -d
- name: Wait for /health
# 30 retries × 10 s = 300 s ceiling on runtime startup. The in-container
# Solarix build already completed during `docker compose up --build`,
# so this budget is purely for the binary cold-start + postgres
# healthcheck + axum route mounting window. `--retry-all-errors`
# covers a race where `/health` briefly 404s during route mounting
# (default `--retry` only covers 5xx + connection-refused).
run: |
curl --retry 30 --retry-delay 10 --retry-connrefused --retry-all-errors --fail \
--connect-timeout 5 \
http://localhost:3000/health
- name: Soft-check /ready (warning only until Story 6.3)
run: |
if curl -fsS http://localhost:3000/ready; then
echo "/ready ok"
else
echo "::warning::/ready not yet implemented (Story 6.3)"
fi
- name: Log format check (every captured line must be valid JSON)
run: |
set -euo pipefail
docker compose logs solarix --no-log-prefix > /tmp/solarix.log
if [ ! -s /tmp/solarix.log ]; then
echo "::error::No log lines captured from solarix container"
exit 1
fi
# Scan the full log (not just the first 5 lines). The previous
# `head -5` version would false-negative on any `pretty` regression
# that landed after the startup banner, and false-positive on any
# clap/dotenv warning that landed in the first 5 lines.
python3 - <<'PY'
import json, sys
path = "/tmp/solarix.log"
count = 0
with open(path) as f:
for i, raw in enumerate(f, 1):
line = raw.strip()
if not line:
continue
try:
json.loads(line)
except json.JSONDecodeError:
print(f"::error::Non-JSON log line {i}: {line}")
sys.exit(1)
count += 1
if count == 0:
print("::error::No non-empty log lines found — container may have crashed silently")
sys.exit(1)
print(f"All {count} captured log lines are valid JSON")
PY
- name: Soft-check /metrics (warning only until Story 6.2)
run: |
if curl -fsS http://localhost:3000/metrics | grep -q solarix_build_info; then
echo "metrics ok"
else
echo "::warning::/metrics not yet implemented (Story 6.2)"
fi
- name: Capture logs on failure
if: failure()
run: docker compose logs solarix > solarix.log 2>&1 || true
- name: Upload logs artifact on failure
if: failure()
uses: actions/upload-artifact@v4
with:
name: docker-smoke-logs
path: solarix.log
retention-days: 7
if-no-files-found: warn
- name: Cleanup
# Intentionally NOT using `|| true` here. A cleanup failure means
# `docker compose down -v` could not tear down the containers, which
# is a real problem we want surfaced — not silently masked.
# `if: always()` still guarantees the step runs on both success and
# failure branches.
if: always()
run: docker compose down -v
msrv:
name: msrv build (1.88)
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 1
- name: Install pinned MSRV toolchain
uses: dtolnay/rust-toolchain@1.88.0
- name: Cache cargo registry + target
uses: Swatinem/rust-cache@v2
with:
shared-key: "solarix-ci"
- name: cargo build --release
run: cargo build --release
# The matrix for stable/beta is split into two explicit jobs rather than a
# `strategy.matrix` block. GitHub Actions does not allow expressions in
# `uses:` fields, so a matrix would force the action ref back to
# `dtolnay/rust-toolchain@master` (a moving target that the action's own
# README discourages). Two explicit jobs trade a few YAML lines for an
# elimination of the `@master` supply-chain hole.
toolchain-stable:
name: toolchain build (stable)
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 1
- name: Install stable toolchain
uses: dtolnay/rust-toolchain@stable
- name: Cache cargo registry + target
uses: Swatinem/rust-cache@v2
with:
shared-key: "solarix-ci-stable"
- name: cargo build --release
# `RUSTUP_TOOLCHAIN` env overrides `rust-toolchain.toml` per rustup
# docs, so the job actually exercises stable instead of the pinned
# MSRV channel.
env:
RUSTUP_TOOLCHAIN: stable
run: cargo build --release
toolchain-beta:
name: toolchain build (beta)
runs-on: ubuntu-latest
timeout-minutes: 15
# Beta is allowed to flake — surfacing upcoming breakages as a warning
# annotation, not a hard fail.
continue-on-error: true
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 1
- name: Install beta toolchain
uses: dtolnay/rust-toolchain@beta
- name: Cache cargo registry + target
uses: Swatinem/rust-cache@v2
with:
shared-key: "solarix-ci-beta"
- name: cargo build --release
env:
RUSTUP_TOOLCHAIN: beta
run: cargo build --release