Skip to content

test(stack-kms-vendor): share the vendor test harness and live workflow - #1556

Draft
freshtonic wants to merge 2 commits into
james/kms-tests-vendor-key-namefrom
james/kms-vendor-test-harness
Draft

freshtonic wants to merge 2 commits into
james/kms-tests-vendor-key-namefrom
james/kms-vendor-test-harness

Conversation

@freshtonic

Copy link
Copy Markdown
Contributor

Summary

The four key vendor crates (AWS KMS, HashiCorp Vault, Google Cloud KMS, Azure Key Vault) each had their own copy of the same test harness: the fixture types, the fixture loader and a Replay transport that answers HTTP calls from recorded fixtures. The copies had started to differ. This PR moves the harness to one place. It also moves the job that the two opt-in live-test workflows had in common into one reusable workflow.

No library behaviour changes.

Changes

  • stack-kms-vendor: new replay module behind the existing test-support feature (which already holds the contract suite and FakeVendor). No new crate.
  • packages/stack-kms-{aws,vault,gcp,azure}/tests/common/mod.rs: keep only the vendor-specific parts (emulator, test keys, constants).
  • Two small test-harness changes: every Replay now records the waits the client asks for (only Azure did before), and AWS sends a null fixture body as no bytes, as the other three did. No AWS fixture has a null body.
  • .github/workflows/_test-kms-live.yml: new reusable workflow. integration-gcp-kms.yml and integration-azure-key-vault.yml call it, and each keeps its triggers, permissions, concurrency, job id, opt-in variable and fork-PR condition.
  • scripts/__tests__/crates-ci.test.mjs: it now follows a call to a reusable workflow in this repository, so it still finds the caller of each test:live:* task.
  • AGENTS.md: notes on the replay module and the new workflow.
  • Changeset: @cipherstash/auth patch, because code under stack-kms-vendor/src/ changed. The binding does not turn on test-support, so its binary does not change.

Verification

Run on the top branch of this stack (james/kms-vendor-dispatch), on macOS:

  • cargo fmt --all --check and cargo clippy --workspace --all-features --all-targets -- -D warnings: pass.
  • mise x --env test -- cargo nextest run --workspace --all-features: 1401 of 1402 pass. The one failure is stack-encrypt::ui derive_diagnostics (trybuild). It fails on every snapshot because of a local rustc wrapper that changes the paths in the compiler output. This stack does not touch stack-encrypt. CI is the check for it.
  • mise run wasm:guest:test: 80 of 80 pass.
  • All four Go guests rebuilt, then go vet ./... and go test -count=1 ./... in languages/golang: pass.
  • pnpm --filter @cipherstash/auth test: 92 pass. pnpm --filter stash test: 1667 pass.
  • Biome on the changed TypeScript and script files: no errors.
  • cargo check of the workspace and the guest (native and wasm32-wasip1) on each branch of the stack: pass.
  • pnpm run test:scripts: pass.
  • Not run: actionlint on the three workflow files. It is not installed on this machine.

Review notes

  • The check names change. A run of the live tests now shows as <caller job name> / live. These jobs do nothing until a repository variable is set, so they should not be required checks. Please confirm that branch protection does not name them.

Related

Refs #1541. Code-smell follow-up to the key vendor backend stack.

The fixture types, the fixture loader, body_json and the Replay transport
were in each of the four vendor crates' tests/common/mod.rs. The copies
were almost the same, but they had started to differ: only the Azure
Replay kept its waits, and only the AWS copy sent a null body as "null".

Move the harness to stack_kms_vendor::replay, behind the test-support
feature. That feature already holds the contract suite and FakeVendor,
which every vendor crate uses as a dev-dependency, so this needs no new
crate and no new dependency edge. The module also holds the Recording
transport that the Vault crate uses to write fixtures.

Each tests/common/mod.rs now keeps only its vendor parts: the emulator,
the test keys and the constants. The fixture files do not change.

The feature now pulls in serde for the fixture types. The
@cipherstash/auth binding does not turn on test-support, so its binary
does not change. The changeset records the src/ change, as the repo rule
requires.
integration-gcp-kms.yml and integration-azure-key-vault.yml had the same
job: a secret pre-flight, checkout, mise, the Rust cache and
mise run test:live:<crate>. Only the secrets were different.

Move that job to the reusable workflow _test-kms-live.yml. Each caller
keeps its triggers, its permissions, its concurrency group, and the job
id "live" with its name, its opt-in on the repository variable and its
fork-PR condition. So both stay inert until STACK_KMS_GCP_LIVE_KEY or
STACK_KMS_AZURE_LIVE_KEY is set, and the scans in
workflow-dispatch-job-conditions.test.mjs see the same jobs. The secret
names and the pre-flight messages do not change. The Google key still
goes to a file only the runner user can read, and the Azure secrets
still reach only the test step. Both path filters now include the shared
file.

The reusable workflow runs mise run test:live:${{ inputs.crate }}.
crates-ci.test.mjs read only the run lines of a workflow's own steps, so
it saw no caller for the two live tasks. It now reads the steps of a
reusable workflow in this repository through each job that calls it,
with the caller's inputs put in. A task counts for the caller, so
removing a caller still orphans its task.
@coderabbitai

coderabbitai Bot commented Nov 6, 2026

Copy link
Copy Markdown
Contributor

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
  auto_review:
    drafts: true

@changeset-bot

changeset-bot Bot commented Nov 6, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: d4ca39e

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 19 packages
Name Type
@cipherstash/auth Patch
stash Patch
@cipherstash/stack Patch
@cipherstash/wizard Patch
@cipherstash/ffi-integration-tests Patch
@cipherstash/basic-example Patch
@cipherstash/e2e Patch
@cipherstash/bench Patch
@cipherstash/stack-drizzle Patch
@cipherstash/stack-prisma Patch
@cipherstash/stack-supabase Patch
@cipherstash/test-kit Patch
@cipherstash/prisma-example Patch
@cipherstash/auth-darwin-arm64 Patch
@cipherstash/auth-darwin-x64 Patch
@cipherstash/auth-linux-arm64-gnu Patch
@cipherstash/auth-linux-x64-gnu Patch
@cipherstash/auth-linux-x64-musl Patch
@cipherstash/auth-win32-x64-msvc Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@freshtonic
freshtonic added this pull request to stack #1523 November 6, 2026 11:25
@github-actions

github-actions Bot commented Nov 6, 2026

Copy link
Copy Markdown
Contributor

Mutation testing (cargo-mutants, --in-diff, stack-auth + stack-encrypt)

No mutants were generated for the changed lines.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant