Author SHA1 Message Date
gamertan b2cc4482f6 fix: prepare Tend preview 2
Publish the reviewed version identity fix and mark preview 1 withdrawn.\n\nPrivate-Source-Commit: 9907afdfa18099ac488fe4011291ea454036435a\nPrivate-Source-Tree: 3a5e666dd6a0c69a07f7804612c8e3dc3474966a\nHimesan-Output-Permission: v1.0\nAI-Assistance: OpenAI Codex assisted implementation and review.

Signed-off-by: Cole Speelman <crspeelman@gmail.com>
2026-08-14 14:19:01 -04:00
6 changed files with 123 additions and 3 deletions
+1 -1
View File
@@ -17,7 +17,7 @@ shell hooks. Application-specific data activation remains application-specific.
```text ```text
tend check --config tend.json tend check --config tend.json
tend package --config tend.json --version v0.1.0-preview.1 --out dist tend package --config tend.json --version v0.1.0-preview.2 --out dist
tend deploy --config /etc/example/tend.json --artifact FILE --sha256 HEX --approve-sha256 HEX tend deploy --config /etc/example/tend.json --artifact FILE --sha256 HEX --approve-sha256 HEX
tend status --config /etc/example/tend.json tend status --config /etc/example/tend.json
tend rollback --config /etc/example/tend.json tend rollback --config /etc/example/tend.json
+7 -1
View File
@@ -1,6 +1,6 @@
# Preview release policy # Preview release policy
`v0.1.0-preview.1` may be published only after one identical candidate Tend `v0.1.0-preview.2` may be published only after one identical candidate Tend
binary has successfully completed maintenance releases for Gamertan and the binary has successfully completed maintenance releases for Gamertan and the
Sandwich Hime website, including injected-failure restoration and explicit Sandwich Hime website, including injected-failure restoration and explicit
rollback proof. The August 14, 2026 campaign met that gate; the scoped, rollback proof. The August 14, 2026 campaign met that gate; the scoped,
@@ -19,6 +19,12 @@ The release tag and attached candidate must be built from the final reviewed
source commit. Documentation-only changes after the recorded campaign require source commit. Documentation-only changes after the recorded campaign require
one final identical-candidate maintenance pass before tagging. one final identical-candidate maintenance pass before tagging.
`v0.1.0-preview.1` is immutable but withdrawn: its source and module checksums
are valid, while a fresh `go install` reports the development identity because
the CLI did not yet adopt the tagged module version from Go build information.
Preview 2 adds that identity path and its regression tests; preview 1 is never
retagged or rewritten.
The canonical public origin is `ssh://git@gitea.speelman.ca:2222/gamertan/tend.git`. The canonical public origin is `ssh://git@gitea.speelman.ca:2222/gamertan/tend.git`.
GitHub is a read-only discovery snapshot. Private development history is not GitHub is a read-only discovery snapshot. Private development history is not
published or merged into either public history. published or merged into either public history.
+7
View File
@@ -22,6 +22,13 @@ The release tag and attached assets must still identify their own exact source
commit and digests. Any code change after this campaign requires the dogfood commit and digests. Any code change after this campaign requires the dogfood
sequence to be repeated. sequence to be repeated.
A fresh-install check after the first immutable source tag found that the CLI
reported its development identity instead of the tagged module version. No
deployment logic or artifact content was ambiguous, but the distribution
identity was not acceptable. Preview 1 remains immutable and withdrawn;
Preview 2 adds Go build-information version selection and repeats the release
gates rather than retagging old content.
## Sandwich Hime website ## Sandwich Hime website
The singleton-candidate strategy packaged and activated website preview 25: The singleton-candidate strategy packaged and activated website preview 25:
+74 -1
View File
@@ -2,8 +2,81 @@
package version package version
import (
"regexp"
"runtime/debug"
"strings"
)
const developmentVersion = "v0.1.0-dev"
var ( var (
Version = "v0.1.0-dev" Version = developmentVersion
Commit = "unknown" Commit = "unknown"
Date = "unknown" Date = "unknown"
) )
var (
taggedVersionPattern = regexp.MustCompile(`^v(?:0|[1-9][0-9]*)\.(?:0|[1-9][0-9]*)\.(?:0|[1-9][0-9]*)(?:-([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?$`)
pseudoVersionSuffixPattern = regexp.MustCompile(`(?:^|[.-])(?:0\.)?[0-9]{14}-[0-9a-f]{12,}$`)
)
func init() {
information, ok := debug.ReadBuildInfo()
if !ok {
return
}
Version = selectVersion(Version, information.Main.Version)
for _, setting := range information.Settings {
switch setting.Key {
case "vcs.revision":
if Commit == "unknown" && setting.Value != "" {
Commit = setting.Value
}
case "vcs.time":
if Date == "unknown" && setting.Value != "" {
Date = setting.Value
}
}
}
}
func selectVersion(linkerValue, moduleVersion string) string {
if linkerValue != developmentVersion {
return linkerValue
}
moduleVersion = strings.TrimSpace(moduleVersion)
if !isTaggedVersion(moduleVersion) {
return linkerValue
}
return moduleVersion
}
func isTaggedVersion(value string) bool {
matches := taggedVersionPattern.FindStringSubmatch(value)
if matches == nil {
return false
}
prerelease := matches[1]
if pseudoVersionSuffixPattern.MatchString(prerelease) {
return false
}
for _, identifier := range strings.Split(prerelease, ".") {
if len(identifier) > 1 && identifier[0] == '0' && allDecimal(identifier) {
return false
}
}
return true
}
func allDecimal(value string) bool {
if value == "" {
return false
}
for _, character := range value {
if character < '0' || character > '9' {
return false
}
}
return true
}
+33
View File
@@ -0,0 +1,33 @@
// SPDX-License-Identifier: AGPL-3.0-only
package version
import "testing"
func TestSelectVersion(t *testing.T) {
t.Parallel()
tests := []struct {
name, linker, module, want string
}{
{"local build", developmentVersion, "(devel)", developmentVersion},
{"missing build info", developmentVersion, "", developmentVersion},
{"preview one install", developmentVersion, "v0.1.0-preview.1", "v0.1.0-preview.1"},
{"preview two install", developmentVersion, "v0.1.0-preview.2", "v0.1.0-preview.2"},
{"release install", developmentVersion, "v1.0.0", "v1.0.0"},
{"linker override", "v0.1.0-preview.2", "(devel)", "v0.1.0-preview.2"},
{"pseudo version", developmentVersion, "v0.0.0-20260814120000-0123456789ab", developmentVersion},
{"pseudo after release", developmentVersion, "v0.1.1-0.20260814120000-0123456789ab", developmentVersion},
{"build metadata", developmentVersion, "v0.1.0+dirty", developmentVersion},
{"leading zero release", developmentVersion, "v00.1.0", developmentVersion},
{"leading zero prerelease", developmentVersion, "v0.1.0-preview.02", developmentVersion},
}
for _, test := range tests {
test := test
t.Run(test.name, func(t *testing.T) {
t.Parallel()
if got := selectVersion(test.linker, test.module); got != test.want {
t.Fatalf("selectVersion(%q, %q)=%q want %q", test.linker, test.module, got, test.want)
}
})
}
}
+1
View File
@@ -36,6 +36,7 @@ internal/provenance/git.go
internal/state/state.go internal/state/state.go
internal/state/state_test.go internal/state/state_test.go
internal/version/version.go internal/version/version.go
internal/version/version_test.go
release/tend.json release/tend.json
scripts/check-licenses.sh scripts/check-licenses.sh
scripts/export-public.sh scripts/export-public.sh