Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b2cc4482f6 |
@@ -17,7 +17,7 @@ shell hooks. Application-specific data activation remains application-specific.
|
||||
|
||||
```text
|
||||
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 status --config /etc/example/tend.json
|
||||
tend rollback --config /etc/example/tend.json
|
||||
|
||||
+7
-1
@@ -1,6 +1,6 @@
|
||||
# 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
|
||||
Sandwich Hime website, including injected-failure restoration and explicit
|
||||
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
|
||||
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`.
|
||||
GitHub is a read-only discovery snapshot. Private development history is not
|
||||
published or merged into either public history.
|
||||
|
||||
@@ -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
|
||||
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
|
||||
|
||||
The singleton-candidate strategy packaged and activated website preview 25:
|
||||
|
||||
@@ -2,8 +2,81 @@
|
||||
|
||||
package version
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
"runtime/debug"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const developmentVersion = "v0.1.0-dev"
|
||||
|
||||
var (
|
||||
Version = "v0.1.0-dev"
|
||||
Version = developmentVersion
|
||||
Commit = "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
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -36,6 +36,7 @@ internal/provenance/git.go
|
||||
internal/state/state.go
|
||||
internal/state/state_test.go
|
||||
internal/version/version.go
|
||||
internal/version/version_test.go
|
||||
release/tend.json
|
||||
scripts/check-licenses.sh
|
||||
scripts/export-public.sh
|
||||
|
||||
Reference in New Issue
Block a user