feat(update): felis update 报告 JRE 与 PostgreSQL(含停更提示),bootstrap 支持 FELIS_UPGRADE_DEPS=1 升级 k3s/cloudflared
This commit is contained in:
19 files changed
+790
-78
No files matched your search
@@ -35,6 +35,9 @@ type Version struct {
|
||||
Major int
|
||||
Minor int
|
||||
Patch int
|
||||
// Revision is an optional fourth numeric component. Temurin numbers an emergency
|
||||
// respin of a JDK update that way ("25.0.4.1+1"), and it orders after Patch.
|
||||
Revision int
|
||||
// Prerelease is the dot-separated identifier set after "-" (empty for a normal
|
||||
// release). Its presence is what IsPrerelease reports and what makes this version
|
||||
// sort below the same Major.Minor.Patch without a prerelease.
|
||||
@@ -45,7 +48,8 @@ type Version struct {
|
||||
}
|
||||
|
||||
// Parse reads a tolerant semantic version. It accepts an optional leading "v",
|
||||
// fills missing minor/patch with 0 (so "v2" and "2.0" parse), strips build
|
||||
// fills missing minor/patch with 0 (so "v2" and "2.0" parse), takes an optional
|
||||
// fourth numeric component (the JDK's "25.0.4.1"), strips build
|
||||
// metadata after "+" for ordering while preserving it in the raw string, and keeps
|
||||
// any "-prerelease" tail. It fails closed: an unparseable core (non-numeric
|
||||
// major/minor/patch) returns an error rather than a zero Version, so a garbled feed
|
||||
@@ -71,10 +75,10 @@ func Parse(s string) (Version, error) {
|
||||
}
|
||||
|
||||
parts := strings.Split(core, ".")
|
||||
if len(parts) == 0 || len(parts) > 3 {
|
||||
if len(parts) == 0 || len(parts) > 4 {
|
||||
return Version{}, fmt.Errorf("updates: %q is not a dotted version", raw)
|
||||
}
|
||||
nums := make([]int, 3)
|
||||
nums := make([]int, 4)
|
||||
for i, p := range parts {
|
||||
n, err := strconv.Atoi(strings.TrimSpace(p))
|
||||
if err != nil {
|
||||
@@ -85,7 +89,7 @@ func Parse(s string) (Version, error) {
|
||||
}
|
||||
nums[i] = n
|
||||
}
|
||||
v.Major, v.Minor, v.Patch = nums[0], nums[1], nums[2]
|
||||
v.Major, v.Minor, v.Patch, v.Revision = nums[0], nums[1], nums[2], nums[3]
|
||||
return v, nil
|
||||
}
|
||||
|
||||
@@ -101,6 +105,9 @@ func (v Version) String() string {
|
||||
return v.raw
|
||||
}
|
||||
base := fmt.Sprintf("%d.%d.%d", v.Major, v.Minor, v.Patch)
|
||||
if v.Revision != 0 {
|
||||
base += fmt.Sprintf(".%d", v.Revision)
|
||||
}
|
||||
if v.Prerelease != "" {
|
||||
return base + "-" + v.Prerelease
|
||||
}
|
||||
@@ -108,7 +115,7 @@ func (v Version) String() string {
|
||||
}
|
||||
|
||||
// Compare returns -1, 0, or +1 as v sorts before, equal to, or after o, by SemVer
|
||||
// 2.0.0 precedence: numeric Major.Minor.Patch first, then — for an equal core — a
|
||||
// 2.0.0 precedence: numeric Major.Minor.Patch(.Revision) first, then — for an equal core — a
|
||||
// version WITH a prerelease sorts below one without, and two prereleases compare by
|
||||
// their dot-separated identifiers (numeric identifiers numerically, others
|
||||
// lexically; a numeric identifier always sorts below an alphanumeric one). Build
|
||||
@@ -123,6 +130,9 @@ func (v Version) Compare(o Version) int {
|
||||
if c := cmpInt(v.Patch, o.Patch); c != 0 {
|
||||
return c
|
||||
}
|
||||
if c := cmpInt(v.Revision, o.Revision); c != 0 {
|
||||
return c
|
||||
}
|
||||
return comparePrerelease(v.Prerelease, o.Prerelease)
|
||||
}
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ func TestParseTolerant(t *testing.T) {
|
||||
{"v2", 2, 0, 0, ""}, // missing minor/patch fill 0
|
||||
{"2.0", 2, 0, 0, ""}, // missing patch fills 0
|
||||
{" v1.2.3 ", 1, 2, 3, ""}, // surrounding whitespace
|
||||
{"25.0.4.1+1", 25, 0, 4, ""}, // Temurin respin: fourth component, see TestParseRevision
|
||||
}
|
||||
for _, c := range cases {
|
||||
v, err := Parse(c.in)
|
||||
@@ -38,7 +39,7 @@ func TestParseTolerant(t *testing.T) {
|
||||
// TestParseFailsClosed proves a garbled version is an error, never a silent 0.0.0
|
||||
// that would read as "older than everything" and trigger a spurious upgrade.
|
||||
func TestParseFailsClosed(t *testing.T) {
|
||||
bad := []string{"", " ", "vx.y.z", "1.2.x", "1.2.3.4", "abc", "-1.2.3", "1.-2.3"}
|
||||
bad := []string{"", " ", "vx.y.z", "1.2.x", "1.2.3.4.5", "1.2.3.x", "abc", "-1.2.3", "1.-2.3"}
|
||||
for _, in := range bad {
|
||||
if v, err := Parse(in); err == nil {
|
||||
t.Errorf("Parse(%q) = %+v, want error", in, v)
|
||||
@@ -46,6 +47,24 @@ func TestParseFailsClosed(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestParseRevision covers the fourth component Temurin uses for an emergency respin
|
||||
// of a JDK update: it is read, kept in the report, and ordered after Patch.
|
||||
func TestParseRevision(t *testing.T) {
|
||||
v, err := Parse("25.0.4.1+1")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if v.Revision != 1 || v.String() != "25.0.4.1+1" {
|
||||
t.Fatalf("Parse(25.0.4.1+1) = %+v (%s), want revision 1 and the raw string kept", v, v)
|
||||
}
|
||||
if got := (Version{Major: 25, Patch: 4, Revision: 1}).String(); got != "25.0.4.1" {
|
||||
t.Fatalf("String() without raw = %q, want 25.0.4.1", got)
|
||||
}
|
||||
if got := (Version{Major: 25, Patch: 4}).String(); got != "25.0.4" {
|
||||
t.Fatalf("String() of a three-part version = %q, want 25.0.4", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCompareAndAfter(t *testing.T) {
|
||||
cases := []struct {
|
||||
a, b string
|
||||
@@ -65,6 +84,9 @@ func TestCompareAndAfter(t *testing.T) {
|
||||
{"1.2.3-alpha", "1.2.3-beta", -1}, // alphanumeric lexical
|
||||
{"1.2.3-rc.1", "1.2.3-rc.1.1", -1}, // longer identifier set is higher
|
||||
{"1.2.3-1", "1.2.3-alpha", -1}, // numeric identifier sorts below alphanumeric
|
||||
{"25.0.4.1+1", "25.0.4+8", 1}, // a respin is newer than the update it respins
|
||||
{"25.0.4.1+1", "25.0.5+3", -1}, // and older than the next update
|
||||
{"25.0.4", "25.0.4.0", 0}, // an absent revision is zero
|
||||
|
||||
// A dev build's own stamp, "<tag>+g<sha>", against the tag it is built past.
|
||||
// It must read EQUAL, never newer: deploy/bootstrap.sh's dev channel stamps the
|
||||
|
||||
Reference in new issue
Block a user