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
4 changes: 2 additions & 2 deletions .github/workflows/refresh-versions.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ name: Refresh Splice versions
#
# Candidates are limited to semver tags newer than the highest already-
# catalogued semver whose major has a DevKit adapter (0.5 / 0.6 / 0.7 /
# 0.8) — see internal/localnet/adapters.go. Historical gaps and
# 0.8 / 0.9) — see internal/localnet/adapters.go. Historical gaps and
# unsupported majors are left for a deliberate maintainer add.
#
# The script refuses to overwrite existing entries, so a force-pushed
Expand Down Expand Up @@ -41,7 +41,7 @@ jobs:
# Adapter majors from internal/localnet/adapters.go — cataloguing
# a tag whose major has no adapter makes Resolve succeed then
# adapterFor fail at up time.
supported_majors="0.5 0.6 0.7 0.8"
supported_majors="0.5 0.6 0.7 0.8 0.9"

catalogued=$(python3 -c "import json;print(' '.join(v['tag'] for v in json.load(open('internal/splice/versions.json'))['versions']))")
echo "Catalogued: $catalogued"
Expand Down
6 changes: 3 additions & 3 deletions docs/versions.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ A maintainer then:
The weekly `.github/workflows/refresh-versions.yml` workflow discovers
upstream semver tags that are newer than the highest already-catalogued
semver and whose major has a DevKit adapter (`0.5` / `0.6` / `0.7` /
`0.8`), runs the same script with `GITHUB_TOKEN`, and opens a PR on
`0.8` / `0.9`), runs the same script with `GITHUB_TOKEN`, and opens a PR on
`chore/refresh-splice-versions` for review.

## Two-layer resolution
Expand All @@ -131,7 +131,7 @@ opt-in unlocks arbitrary upstream tags for prerelease testing.
| 2 — Upstream | `--version <tag> --allow-uncurated` for any tag not in the catalogue | `api.github.com/repos/canton-network/splice/git/refs/tags/<tag>` | Computed on first extract, recorded for future runs | Requires explicit opt-in. Network on first call. Cached at `~/.canton-devkit/cache/resolved-versions.json`. |

Layer 2 trades audit for flexibility: it lets a user spin up a
`0.9.0-alpha.1` LocalNet without waiting for a catalogue PR, but
`0.10.0-alpha.1` LocalNet without waiting for a catalogue PR, but
DevKit can't promise the bits were tested against this release.
Orchestrators print a one-line "Using uncurated Splice tag" warning
on the layer-2 path so the user is never surprised.
Expand All @@ -155,7 +155,7 @@ Three reasons the catalogue is curated:
commit that happens to land in the repo.

3. **Adapter routing.** DevKit ships per-major adapters for each Splice
major version (`0.5`–`0.8` today). A new major version (e.g. `0.9.x`)
major version (`0.5`–`0.9` today). A new major version (e.g. `0.10.x`)
needs a corresponding adapter before it can be added — the script
leaves `major` blank for non-N.N.N tags so a maintainer notices.

Expand Down
3 changes: 3 additions & 0 deletions internal/localnet/adapters.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
v06 "github.com/bitdynamics-ab/canton-devkit/internal/splice/v06"
v07 "github.com/bitdynamics-ab/canton-devkit/internal/splice/v07"
v08 "github.com/bitdynamics-ab/canton-devkit/internal/splice/v08"
v09 "github.com/bitdynamics-ab/canton-devkit/internal/splice/v09"
)

// adapterFor returns the splice.Adapter implementation for a Version.
Expand All @@ -27,6 +28,8 @@ func adapterFor(v splice.Version) (splice.Adapter, error) {
return v07.New(), nil
case "0.8":
return v08.New(), nil
case "0.9":
return v09.New(), nil
default:
return nil, fmt.Errorf("no adapter registered for Splice major %q (tag %s) — this is a canton-devkit bug",
v.Major, v.Tag)
Expand Down
8 changes: 6 additions & 2 deletions internal/localnet/adapters_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ func TestCoreServicesFor_Unknown(t *testing.T) {
}
}

// TestCoreServicesFor_VersionsAgree pins the hoist: 0.5.x through 0.8.x
// TestCoreServicesFor_VersionsAgree pins the hoist: 0.5.x through 0.9.x
// adapters all delegate to splice.CoreServices, so any drift between
// majors is impossible by construction. If a future major needs a
// different list, this test should be updated together with that
Expand All @@ -40,14 +40,18 @@ func TestCoreServicesFor_VersionsAgree(t *testing.T) {
if !reflect.DeepEqual(v05, v06) {
t.Fatalf("core services drifted between majors: 0.5.18=%v 0.6.4=%v", v05, v06)
}
// 0.7.x and 0.8.x reuse the 0.6.x adapter (identical compose interface),
// 0.7.x–0.9.x reuse the 0.6.x adapter (identical compose interface),
// so their core-services list must match too.
v07 := CoreServicesFor("0.7.5")
v08 := CoreServicesFor("0.8.1")
v09 := CoreServicesFor("0.9.0")
if !reflect.DeepEqual(v06, v07) {
t.Fatalf("core services drifted between majors: 0.6.4=%v 0.7.5=%v", v06, v07)
}
if !reflect.DeepEqual(v06, v08) {
t.Fatalf("core services drifted between majors: 0.6.4=%v 0.8.1=%v", v06, v08)
}
if !reflect.DeepEqual(v06, v09) {
t.Fatalf("core services drifted between majors: 0.6.4=%v 0.9.0=%v", v06, v09)
}
}
6 changes: 3 additions & 3 deletions internal/splice/resolver_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -256,9 +256,9 @@ func TestResolveForOperation_ThreeTiers(t *testing.T) {

// Tier 3: an uncurated tag NOT in the cache still yields a Version
// carrying the Major inferred from the tag, so the adapter resolves.
v, err = ResolveForOperation("0.8.1-rc.2")
if err != nil || v.Major != "0.8" {
t.Errorf("inferred: got (%+v, %v), want Major 0.8", v, err)
v, err = ResolveForOperation("0.9.0-rc.1")
if err != nil || v.Major != "0.9" {
t.Errorf("inferred: got (%+v, %v), want Major 0.9", v, err)
}

// A genuinely unparseable tag is the only error case.
Expand Down
23 changes: 23 additions & 0 deletions internal/splice/v09/adapter.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Package v09 implements the Adapter contract for Splice LocalNet 0.9.x.
//
// The cluster/compose/localnet/ tree is unchanged from 0.6.x upstream —
// same compose files, env-file set, profile names, service/port map, and
// the env-var contract the adapter wires (IMAGE_TAG, IMAGE_REPO,
// PARTY_HINT, ALPHA_PROTOCOL_VERSION_ENV, …). So 0.9.x embeds the 0.6.x
// adapter and only relabels its major slot.
package v09

import (
"github.com/bitdynamics-ab/canton-devkit/internal/splice"
v06 "github.com/bitdynamics-ab/canton-devkit/internal/splice/v06"
)

// Adapter is the 0.6.x adapter under the 0.9 major label.
type Adapter struct{ *v06.Adapter }

// New returns a fresh 0.9.x adapter. Stateless — safe to reuse.
func New() *Adapter { return &Adapter{v06.New()} }

func (*Adapter) MajorVersion() string { return "0.9" }

var _ splice.Adapter = (*Adapter)(nil)
19 changes: 19 additions & 0 deletions internal/splice/v09/adapter_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package v09

import "testing"

func TestMajorVersion(t *testing.T) {
if got := New().MajorVersion(); got != "0.9" {
t.Fatalf("MajorVersion() = %q, want 0.9", got)
}
}

func TestDelegatesComposeSurface(t *testing.T) {
a := New()
if len(a.ComposeFiles()) == 0 || len(a.EnvFiles()) == 0 || len(a.Profiles()) == 0 {
t.Fatal("0.9 adapter must expose the same compose surface as 0.6")
}
if !a.SupportsAlphaProtocol() {
t.Fatal("0.9 must keep alpha-protocol support from 0.6")
}
}
Loading