Documentation for v2.11.0. Read the latest, v2.12.0.
Developer
Clients
Builds do not call curl. Each client reads
sanshain.yaml
and speaks the same contract; what differs is how it is installed and invoked. This chapter gives
the shape of each one and links its own documentation, which stays the authority for flags and
edge cases.
What every client has in common#
-
Compatibility: client 2.x speaks Sanshain Service 2.x. The catalog push and
format: openapineed Sanshain Service 2.4.0 or later, the origin of a provide 2.9.0 or later (an older service refuses it; the client warns and provides without it); everything else works with any 2.x service. - Three commands: provide, require, catalog, each a separate step.
-
The ga switch: every provide is a
snapshot unless
SANSHAIN_GA=true(or the client's flag) is set. No git detection anywhere. -
Streams:
SANSHAIN_TRUNK=truemarks a trunk build,SANSHAIN_TAG=<branch>a sanshain-branch build. Both set, the client sends neither and warns (strict mode fails before any request). -
Origin: every provide carries the build URL and the pull or merge request from
the runner's variables on GitHub Actions, GitLab CI and Jenkins, and the ticket ids and the note
from
SANSHAIN_TICKETSandSANSHAIN_NOTE; each client's flag wins overSANSHAIN_BUILD_URL,SANSHAIN_CHANGE_URLand the other variables, which win over the runner. The variables, the order and each client's flag names are in CI integration. -
Dry runs: Maven (
-Dsanshain.dry.run=true) and the JavaScript CLI (--dry-run) senddry_run; the Rust, Go and Conan clients and the GitHub Action do not. -
Environment:
SANSHAIN_URLoverridessanshainUrl,SANSHAIN_TOKENis the bearer token,SANSHAIN_BEST_EFFORT=trueturns failed calls into warnings. Boolean switches are on fortrueor1. -
Warnings: a
Sanshain-Warningheader is printed and the build carries on; in strict mode it fails the command withstrict: Sanshain warned: <text>. -
Caching: provides always upload (the server's
no-op makes that free); requires keep the
ETag in a state file and skip rewriting on
304. -
Rejections: a
409is printed with its proposed version; a404on require means the pin does not exist, a410that the version lacks the endpoint. -
Unknown fields in
sanshain.yamlare reported; the 1.x fields (branch,timeout,baseVersion,releaseBranches) are rejected with a migration hint.
Maven (Java, Kotlin)#
paxel/sanshain-maven-plugin, artifact
io.github.paxel.sanshain:sanshain-maven-plugin on Maven Central, Java 11 or later.
Three goals, all bound to the initialize phase by default:
mvn sanshain:provide # snapshot
mvn sanshain:provide -Dsanshain.ga=true
mvn sanshain:require
mvn sanshain:catalog
Configuration comes from sanshain.yaml, overridable by Maven properties
(-Dsanshain.url, -Dsanshain.token, -Dsanshain.ga,
-Dsanshain.trunk, -Dsanshain.tag, -Dsanshain.strict,
-Dsanshain.dry.run, and for the origin -Dsanshain.buildUrl,
-Dsanshain.changeUrl, -Dsanshain.tickets, -Dsanshain.note)
and by the environment. Unlike the other clients, -Dsanshain.trunk=false also turns
off a SANSHAIN_TRUNK=true from the environment; URL and token can also live in
settings.xml (a <server> with id sanshain for the
token). The plugin inlines local $refs and proto imports into one
document before upload (combine, on by default), and picks
/require-bundle automatically when an entry has two or more endpoints.
configFile points it at another sanshain.yaml. Require ETags are kept in
target/.sanshain-cache.json, removed by mvn clean. Its README documents
the full precedence chain, strict and best-effort modes, and the
openapi-generator wiring.
Rust (cargo)#
paxel/sanshain-rs: the
sanshain library crate and the cargo-sanshain subcommand.
cargo install cargo-sanshain
cargo sanshain provide # snapshot (the default)
cargo sanshain provide --ga # immutable GA
cargo sanshain require # download the pinned snippets
cargo sanshain catalog # push catalog-info.yaml
cargo sanshain provide --tickets PAY-12 --note "card refunds"
The subcommand README has the flags and CI recipes; the library README has the configuration
reference and the Client API for builds that embed the client.
Go#
paxel/sanshain-go, a CLI and a client library
under the /v2 module path:
go install github.com/paxel/sanshain-go/v2/cmd/sanshain-go@latest
SANSHAIN_TOKEN=san_… sanshain-go provide
sanshain-go --ga provide
sanshain-go --trunk provide # or SANSHAIN_TRUNK=true
sanshain-go --tag R1 provide # or SANSHAIN_TAG=R1
sanshain-go require
sanshain-go catalog
sanshain-go -tickets PAY-12 -note "card refunds" provide
--config path/to/sanshain.yaml points it at another file; strict: true
in the file turns on strict mode. The README covers the failure modes, the ETag state file and the
1.x migration.
JavaScript and TypeScript, and the GitHub Action#
paxel/sanshain-js: the sanshain
npm package with a Node client, a CLI and a composite GitHub Action.
npm install --save-dev sanshain
npx sanshain provide # snapshot
npx sanshain provide --ga
npx sanshain provide --trunk # or --tag R1
npx sanshain require
npx sanshain catalog
npx sanshain provide --dry-run # validate only, e.g. on a pull request
npx sanshain provide --tickets PAY-12 --note "card refunds"
A "prebuild": "sanshain require" script in package.json fetches the
pinned snippets before every build. Beyond the shared variables the CLI reads
SANSHAIN_SERVICE_NAME, SANSHAIN_STRICT and
SANSHAIN_COMPRESSION; --url wins over SANSHAIN_URL, which
wins over the file.
The Action wraps the CLI. Its inputs are command (provide, require or catalog),
token (or the SANSHAIN_TOKEN secret in the environment),
ga, trunk, tag, tickets, note and
working-directory; the build and pull-request URLs come from GitHub's own variables:
- uses: paxel/sanshain-js@main
with:
command: provide
ga: ${{ github.ref == 'refs/heads/main' }}
trunk: ${{ github.ref == 'refs/heads/main' }}
env:
SANSHAIN_URL: ${{ vars.SANSHAIN_URL }}
SANSHAIN_TOKEN: ${{ secrets.SANSHAIN_TOKEN }}
Conan (C, C++)#
paxel/sanshain-conan, the
sanshain-conan package on PyPI, installed into the environment Conan runs in. The
earlier python_requires pattern is gone.
pip install sanshain-conan
# conanfile.py
from conan import ConanFile
from sanshainconan import Sanshain
class MyProject(ConanFile):
def generate(self):
sanshain = Sanshain(self)
sanshain.require() # runs during `conan install`
sanshain.catalog() # optional
Providing runs from the CLI, after the tests: sanshain-conan provide (or
python3 -m sanshainconan.cli provide), with --ga, --trunk,
--tag, --best-effort and the origin flags --build-url,
--change-url, --tickets and --note. The
conanfile.py integration reads the SANSHAIN_* variables only.
strict: true in sanshain.yaml turns on strict mode.
No client for your language?#
The contract is eight routes: POST /provide,
/provide/asyncapi and /provide/grpc; GET /require,
/require/asyncapi and /require/grpc; POST /require-bundle;
PUT /catalog/{systemname}. CI integration shows
each of them as a curl line, and
Using the API covers tokens and error shapes.
api.yaml in the repository is the OpenAPI document to generate a client from.
Checked against v2.10.0.