Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ jobs:
coverage-min: "90"
test-exclude-regex: "/example(s)?($|/)"
codecov-name: sparkplugbctl
go-versions: '["1.27"]'
go-versions: '["1.26", "1.27"]'
golangci-lint-version: v2.15.0
policy-version: v1.4.2
secrets: inherit
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ permissions:

jobs:
release:
uses: otfabric/.github/.github/workflows/go-binary-release.yml@v3.3.0
uses: otfabric/.github/.github/workflows/go-binary-release.yml@v3.6.0
with:
bump: ${{ inputs.bump }}
binary-name: sparkplugbctl
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

Sparkplug B 3.0.0 CLI for MQTT monitoring, publishing, simulation and debugging.

[![Go](https://img.shields.io/badge/Go-1.27-00ADD8?logo=go&logoColor=white)](https://go.dev)
[![Go](https://img.shields.io/badge/Go-1.26-00ADD8?logo=go&logoColor=white)](https://go.dev)
[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
[![CI](https://github.com/otfabric/sparkplugbctl/actions/workflows/ci.yaml/badge.svg)](https://github.com/otfabric/sparkplugbctl/actions/workflows/ci.yaml)
[![Release](https://img.shields.io/github/v/release/otfabric/sparkplugbctl?include_prereleases)](https://github.com/otfabric/sparkplugbctl/releases)
Expand All @@ -26,7 +26,7 @@ irm https://get.otfabric.io/sparkplugbctl.ps1 | iex

Linux (amd64, arm64, armv7), macOS (Intel, Apple silicon) and Windows (amd64, arm64). The installer verifies the release's SHA-256 checksum, installs per user without `sudo` (`~/.local/bin`, Windows `%LOCALAPPDATA%\OTFabric\bin`), and upgrades in place when run again. Pin a version with `OTF_VERSION=x.y.z`; for CI, containers and device images use `OTF_UNMANAGED_INSTALL=<dir>`; all options: [otfabric/install](https://github.com/otfabric/install#options). For offline machines, the archives and checksums are on [Releases](https://github.com/otfabric/sparkplugbctl/releases).

From source (Go 1.27.3+): `go install github.com/otfabric/sparkplugbctl@latest`
From source (Go 1.26.0+): `go install github.com/otfabric/sparkplugbctl@latest`

### Shell completion

Expand Down
17 changes: 17 additions & 0 deletions RELEASE.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,22 @@
# sparkplugbctl Releases

## v0.4.1

**Date:** 2026-11-08
**Previous release:** v0.4.0

### Changed

- Built on go-sparkplugb v0.3.4 (was v0.3.3). Its `edge` fix makes a rebirth (`Node.Rebirth`, and so the answer to an NCMD rebirth) publish the DBIRTHs in the order the devices were first born, instead of map order, and reads the devices' state under the lock, which removes a data race with a device death or data published at the same time. `version` lists `go-sparkplugb 0.3.4`.
- The minimum Go version is now 1.26.0 (was 1.27.3): `go.mod` declares `go 1.26.0`, and CI tests Go 1.26 and 1.27.
- Release binaries are built with the latest Go 1.26 patch release (otfabric/.github release workflow v3.6.0); they were built with the exact Go version in `go.mod`.

### Tests

- `TestVersion` passes on Go 1.26, whose test binaries record no dependencies, so the expected line has no libraries there; the e2e test checks that the built binary names go-sparkplugb in `version` and `version --json`.

---

## v0.4.0

**Date:** 2026-11-07
Expand Down
23 changes: 16 additions & 7 deletions cmd/codec_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,13 @@ func TestVersion(t *testing.T) {
defer func(v, tg, c, d string) { Version, Tag, Commit, BuildDate = v, tg, c, d }(Version, Tag, Commit, BuildDate)
Version, Tag, Commit, BuildDate = "0.4.0", "v0.4.0", "1802d0f9afe8642d1e278120b76fcdfac967cb9e", "2026-11-05T15:41:49Z"
platform := runtime.Version() + ", " + runtime.GOOS + "/" + runtime.GOARCH
lib := sparkplugbVersion(t)
wantText := "sparkplugbctl 0.4.0 (tag v0.4.0, commit 1802d0f9afe8642d1e278120b76fcdfac967cb9e, built 2026-11-05T15:41:49Z, go-sparkplugb " + lib + ", " + platform + ")\n"
libText, libJSON := "", "[]"
if lib, ok := sparkplugbVersion(t); ok {
libText, libJSON = "go-sparkplugb "+lib+", ", `[{"name":"go-sparkplugb","version":"`+lib+`"}]`
}
wantText := "sparkplugbctl 0.4.0 (tag v0.4.0, commit 1802d0f9afe8642d1e278120b76fcdfac967cb9e, built 2026-11-05T15:41:49Z, " + libText + platform + ")\n"
wantJSON := `{"name":"sparkplugbctl","version":"0.4.0","tag":"v0.4.0","commit":"1802d0f9afe8642d1e278120b76fcdfac967cb9e",` +
`"built":"2026-11-05T15:41:49Z","libraries":[{"name":"go-sparkplugb","version":"` + lib + `"}],"go":"` + runtime.Version() + `","platform":"` + runtime.GOOS + "/" + runtime.GOARCH + `"}` + "\n"
`"built":"2026-11-05T15:41:49Z","libraries":` + libJSON + `,"go":"` + runtime.Version() + `","platform":"` + runtime.GOOS + "/" + runtime.GOARCH + `"}` + "\n"

t.Setenv("SPARKPLUGBCTL_FORMAT", "")
t.Setenv("SPARKPLUGBCTL_OUTPUT_FORMAT", "")
Expand Down Expand Up @@ -61,20 +64,26 @@ func TestVersion(t *testing.T) {
}

// sparkplugbVersion is the go-sparkplugb version of the test binary, without
// the leading v.
func sparkplugbVersion(t *testing.T) string {
// the leading v. ok is false when the build information of the test binary
// lists no dependencies: Go 1.26 records none in a test binary (Go 1.27 does),
// and then the version line lists no libraries. The e2e test checks that a
// built binary names go-sparkplugb.
func sparkplugbVersion(t *testing.T) (version string, ok bool) {
t.Helper()
bi, ok := debug.ReadBuildInfo()
if !ok {
t.Fatal("no build information")
}
if len(bi.Deps) == 0 {
return "", false
}
for _, d := range bi.Deps {
if d.Path == "github.com/otfabric/go-sparkplugb" {
return strings.TrimPrefix(d.Version, "v")
return strings.TrimPrefix(d.Version, "v"), true
}
}
t.Fatal("go-sparkplugb is not a dependency")
return ""
return "", false
}

// TestEnvironment checks that a global flag comes from its SPARKPLUGBCTL_
Expand Down
6 changes: 6 additions & 0 deletions e2e/e2e_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,16 @@ func TestVersionPrintsTheBuiltVersion(t *testing.T) {
if !strings.HasPrefix(output, "sparkplugbctl "+want+" (") || strings.Count(output, "\n") != 1 {
t.Fatalf("output is not one line naming sparkplugbctl %s:\n%s", want, output)
}
if !strings.Contains(output, ", go-sparkplugb ") {
t.Fatalf("version does not name go-sparkplugb:\n%s", output)
}
output, code = run(t, "version", "--json")
if code != 0 || !strings.HasPrefix(output, `{"name":"sparkplugbctl","version":"`+want+`","tag":`) {
t.Fatalf("version --json: exit %d\n%s", code, output)
}
if !strings.Contains(output, `"libraries":[{"name":"go-sparkplugb","version":"`) {
t.Fatalf("version --json does not list go-sparkplugb:\n%s", output)
}
}

// An unknown command is a usage error: exit code 2 in docs/exitcodes.md.
Expand Down
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
module github.com/otfabric/sparkplugbctl

go 1.27.3
go 1.26.0

require (
github.com/mochi-mqtt/server/v2 v2.7.9
github.com/otfabric/go-sparkplugb v0.3.3
github.com/otfabric/go-sparkplugb v0.3.4
github.com/spf13/cobra v1.10.2
github.com/spf13/pflag v1.0.10
google.golang.org/protobuf v1.36.12
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ github.com/jinzhu/copier v0.3.5 h1:GlvfUwHk62RokgqVNvYsku0TATCF7bAHVwEXoBh3iJg=
github.com/jinzhu/copier v0.3.5/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg=
github.com/mochi-mqtt/server/v2 v2.7.9 h1:y0g4vrSLAag7T07l2oCzOa/+nKVLoazKEWAArwqBNYI=
github.com/mochi-mqtt/server/v2 v2.7.9/go.mod h1:lZD3j35AVNqJL5cezlnSkuG05c0FCHSsfAKSPBOSbqc=
github.com/otfabric/go-sparkplugb v0.3.3 h1:u1HbdPacfAMjpe0264euEDwOddDfFqYu+LZBlYhO+Vc=
github.com/otfabric/go-sparkplugb v0.3.3/go.mod h1:GzF84cTz3JERwglT2xsMGyxdS2BWr4mHUpYiGJuAYBw=
github.com/otfabric/go-sparkplugb v0.3.4 h1:rNrc2xHgSLdcLzhhHXmHlnkVZq1qa8LMcRvKpbTR2/g=
github.com/otfabric/go-sparkplugb v0.3.4/go.mod h1:GzF84cTz3JERwglT2xsMGyxdS2BWr4mHUpYiGJuAYBw=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rs/xid v1.4.0 h1:qd7wPTDkN6KQx2VmMBLrpHkiyQwgFXRnkOLacUiaSNY=
Expand Down
Loading