goss vs Syver
Syver is the renamed continuation of the krameff/goss fork of
goss-org/goss. The product renamed; the file
format did not. Existing gossfiles, env vars, wrapper scripts and CI pipelines keep
working. The breaking changes are limited to things that referenced the product by
name, and are listed first.
Syver is not a tracking fork. Its changes are driven by client requirements rather
than by following goss-org/goss, so the gap between the two grows over time and
release-for-release parity with upstream is not a goal. What is deliberately held
stable is the file format: the tables below exist so you can tell which of the two
you are dealing with in any given case.
This page is the one place for moving to Syver from goss: what breaks, what does
not, and the steps for krameff/goss v0.6.0
and for upstream goss-org/goss. Spec files need no
conversion, because the format did not change.
Breaking changes
Nothing that reads or writes a spec file changes. Almost everything that breaks is
something that referenced the product by name; the exception is the Go library API,
which changed to carry a context.Context (last two rows).
| What | goss | Syver | Affects you if |
|---|---|---|---|
| Binary name | goss |
syver |
Anything shells out to goss by name. install.sh no longer puts a goss on your PATH |
Outbound User-Agent on http checks |
goss/<version> |
syver/<version> |
You assert on the User-Agent server-side |
| Checksum file | goss_<ver>_SHA256SUMS |
syver_<ver>_SHA256SUMS |
You verify release checksums by filename |
| Container image | ghcr.io/krameff/goss |
ghcr.io/krameff/syver |
You pull the image |
| Go module path | github.com/krameff/goss |
github.com/krameff/syver |
You import this as a library, not as a CLI |
Resource interface |
Validate(sys) |
Validate(ctx, sys) |
You implement your own resource type against the library |
| Library entry points | Validate(c), ValidateResults(c), ValidateConfig(c, cfg), Serve(c) |
same, each taking ctx first |
You call these directly instead of using the CLI |
Release binaries are published under the syver name only. The goss-named
binaries were last published with v0.9.1, so a goss-<os>-<arch> download URL
does not exist for any later release.
For the binary-name break specifically, the fix is one line:
See Upgrading from krameff/goss v0.6.0 for the full upgrade path.
Nothing to change
These are the compatibility guarantees. If your setup relies on any of them, it keeps working. How long they last is set out in the compatibility policy below.
| What | Still true in Syver | Notes |
|---|---|---|
| Config file key | gossfile: |
Still canonical, still what gets written |
goss.yaml / goss.yml filenames |
Accepted | Probed alongside the syver names |
GOSS_* environment variables |
All 16 still honoured | New variables get a SYVER_* name only |
--gossfile / -g flag |
Still accepted | Demoted to an alias, not removed |
dgoss / dcgoss / kgoss wrappers |
Still shipped and working | Print a one-line notice naming the syver script |
| JUnit suite name | goss |
Deliberately unchanged |
| Nagios output prefix | GOSS OK / GOSS CRITICAL |
Deliberately unchanged |
goss_tests_* Prometheus metrics |
Still emitted | Syver metrics emit alongside, not instead |
application/vnd.goss-* Accept headers |
Still accepted | No vendor header still yields vnd.goss- |
| gossfile syntax, resource types, matchers | Unchanged | No spec rewrite needed |
Compatibility policy
Syver keeps the goss names working, and there are no current plans to remove
them: the gossfile: key, goss.yaml files, the GOSS_* environment
variables, --gossfile, the goss_tests_* metrics, the vnd.goss- media types
and the dgoss, dcgoss and kgoss scripts.
They are maintained for compatibility but no longer extended. New features
arrive under the syver names only: for example, SYVER_TEMP_DIR has no GOSS_*
equivalent, and sbxsyver has no goss-named copy. If removal is ever planned,
it will be announced in the changelog at least one minor release beforehand.
Upgrading from krameff/goss v0.6.0
If you are already on the krameff/goss fork, this is the rename. Your gossfiles
need no changes. What changes is the product's own name.
| If you | Do this |
|---|---|
Invoke goss by name in scripts or CI |
Call syver, or symlink it (below) |
| Use the community integrations | Symlink, see below |
| Pull the container image | Use ghcr.io/krameff/syver |
| Import this as a Go library | Update the path to github.com/krameff/syver, and pass a context.Context (see Breaking changes) |
| Verify release checksums by filename | It is now syver_<version>_SHA256SUMS |
| Nothing above | Nothing. Install the new binary and carry on |
The third-party integrations listed in the README (goss-ansible,
kitchen-goss, packer-provisioner-goss and the rest) all invoke a binary
named goss, and install.sh installs syver, dsyver and dgoss but no
goss. One symlink covers all of them:
Everything in Nothing to change carries over as it is.
Verifying releases
Upstream goss-org/goss publishes no signatures. This fork GPG-signs its
release checksums.
The key for 0.7.0 onward is krameff-syver-key.asc, fingerprint
CD218D529C95DC65A71F18D84C9E5095CABE5092. If you imported the earlier
krameff-goss-key.asc from a 0.6.0 release, import the new one as well: the
old key will not verify 0.7.0 artifacts. See
Verifying release signatures.
Coming from goss-org/goss
Syntax, resource types, matchers and CLI flags carry over, so a gossfile that worked under upstream goss works here. Change where you get the binary, and the names in Breaking changes if you used any of them:
| If you | Change to |
|---|---|
| Install manually or by script | The krameff/syver releases page and this repo's install.sh. See Installation |
| Use the container image | ghcr.io/krameff/syver, replacing the aelsabbahy or goss-org image |
| Import it as a Go library | github.com/krameff/syver |
None of the following are required. Leave them out and nothing changes.
| Addition | What it does |
|---|---|
| discovery | Runs lightweight checks before the main suite and feeds results into templates |
depends-on |
Declares test prerequisites, so dependents are skipped rather than failed |
process.status |
Catches zombie processes |
process.user |
Catches something running as root that shouldn't be |
port.pid |
Identifies which process owns a listening socket |
Process and port lookups moved from two unmaintained libraries
(goss-org/go-ps and goss-org/GOnetstat) to the maintained gopsutil. Specs
and output are unchanged.
Behaviour differences
One thing Syver does that goss does not: Ctrl-C stops work in progress. goss
mints a fresh context.Background() inside each check, so interrupting a run
leaves any command it had already started to run to completion, orphaned. Syver
threads the signal handler's context all the way down to exec, so the child is
killed with the parent. syver serve shuts down in an orderly way on SIGTERM
rather than being killed mid-request, and a second signal always terminates the
process outright, so nothing becomes unkillable.
This is a difference, not a compatibility break: no spec file behaves differently, and a run that is allowed to finish produces identical results either way.
Another: a top-level key syver doesn't recognise now gets a warning. goss
(and syver before this) silently dropped the whole block under an unknown
top-level key -- a typo'd resource name, most often -- and validated the rest
of the file as if it had never been written, still exiting 0. A spec that
silently skips a block you thought was being checked is worse than one that
fails, so syver now logs a [WARN] naming the file, the line, and (if it's
close to a real key) a suggested fix. See
Unknown top-level keys for the details,
including the two patterns -- an x--prefixed key, and a YAML anchor carrier
-- that are deliberately exempt and never warn. This is worth checking if
you're migrating a large gossfile collection: a key that validated clean
under goss may turn out to have been ignored the whole time.
Product identity
| Item | goss | Syver |
|---|---|---|
| Binary name | goss |
syver |
| Go module path | github.com/krameff/goss |
github.com/krameff/syver |
| Repository | github.com/krameff/goss |
github.com/krameff/syver |
| Container image | ghcr.io/krameff/goss |
ghcr.io/krameff/syver |
| Release artifacts | goss-<os>-<arch> |
syver-<os>-<arch>; the goss names were last published with v0.9.1 |
| Checksum file | goss_<ver>_SHA256SUMS |
syver_<ver>_SHA256SUMS, no legacy twin |
| Container volume | /goss |
/syver, and /goss is still declared |
Config files
| Behaviour | goss | Syver |
|---|---|---|
| Canonical key written on save | gossfile: |
gossfile:, unchanged |
| Accepted input key | gossfile: |
gossfile: or syverfile: |
Is syverfile: ever written out? |
n/a | No, input alias only, folded in at decode |
| Both keys present in one file | n/a | gossfile: wins, logs one WARN |
| Spec filenames probed | goss.yaml, goss.yml |
syver.yaml, syver.yml, goss.yaml, goss.yml |
Where add writes |
The gossfile | Whichever file the read resolved to |
| Unrecognised top-level key (typo, or a key syver doesn't know) | Silently ignored -- the block is dropped and the run still exits 0 | Still ignored, but now logs a WARN naming the file, line, and a suggestion if one is close |
CLI
| Item | goss | Syver |
|---|---|---|
| Primary spec-file flag | --gossfile |
--syverfile, with --gossfile and -g as aliases |
| Default spec path | Static ./goss.yaml |
Resolved dynamically across all four names |
| Nested add subcommand | add goss |
add syver, and add goss still works |
| Subcommands, flags, matchers | n/a | Identical |
Environment variables
Every variable is paired. SYVER_* takes priority when set to a non-empty value;
otherwise GOSS_* applies. An exported-but-empty SYVER_* is treated as unset and
never shadows a real GOSS_*.
| Item | goss | Syver |
|---|---|---|
| Recognised prefixes | GOSS_* only |
SYVER_* and GOSS_* |
| Precedence | n/a | SYVER_* first, GOSS_* fallback |
| Number paired | n/a | All 16, e.g. _FILE, _VARS, _FMT, _LOGLEVEL, _SLEEP |
| Wrapper script variables | GOSS_* only |
Both, same precedence rule |
install.sh variables |
GOSS_VER, GOSS_DST |
SYVER_VER, SYVER_DST, with the GOSS_* names still honoured |
Wrapper scripts
| Item | goss | Syver |
|---|---|---|
| Docker wrapper | dgoss |
dsyver, with dgoss kept as a working shim |
| Compose wrapper | dcgoss |
dcsyver, with dcgoss kept as a working shim |
| Kubernetes wrapper | kgoss |
ksyver, with kgoss kept as a working shim |
| Binary discovery | which goss |
which syver, falling back to which goss |
| Spec staged into container | goss.yaml |
First of the four probed names that exists |
Output and wire formats
| Format | goss | Syver |
|---|---|---|
| Prometheus metric names | goss_tests_* |
goss_tests_* and syver_tests_*, same labels and values |
| Accept header vendor prefix | vnd.goss- |
Both prefixes accepted, the client's own is echoed back |
| Accept header absent | vnd.goss- |
vnd.goss-, since no preference was expressed |
/metrics endpoint |
Served an empty registry, a bug | Serves the real metrics |
| JUnit, Nagios, TAP, JSON | n/a | Unchanged |
Test matrix
| Distro | goss | Syver |
|---|---|---|
| CentOS 7 | Present | Removed, EOL and its systemd never activates services in a container |
| bullseye | Present | Removed, Debian 11 is EOL |
| almalinux10, alpine3, arch, jammy, rockylinux9 | Present | Unchanged |
Keeping this page current
This page is a living record of the rename and should be updated in the same commit as any change that alters it. Update it when you:
- add or remove a
SYVER_*/GOSS_*variable pair - change which spec filenames are probed, or which key is canonical
- rename or retire a wrapper script, flag, or subcommand alias
- change a metric name, media type, or output-format identifier
- drop a compatibility shim, moving a row out of Nothing to change
The Nothing to change table is the promise this project makes to existing goss users. Moving a row out of it is a breaking change and belongs in the changelog, not just here.