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 cmd/versions/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ func TestTheCommandsAnswerFromTheFile(t *testing.T) {
source: https://cdn.kernel.org/pub/linux/kernel/v{major}.x/linux-{version}.tar.xz
version: 7.2.8
pin: 1111111111111111111111111111111111111111111111111111111111111111
track: kernel-stable
track: kernel
`), 0o600))
for name, tc := range map[string]struct {
argv []string
Expand Down Expand Up @@ -88,7 +88,7 @@ func TestOneEntrySaysWhatItsKindHas(t *testing.T) {
source: https://git.kernel.org/torvalds/t/linux-{version}.tar.gz
version: 7.3-rc5
pin: 1111111111111111111111111111111111111111111111111111111111111111
track: kernel-stable
track: kernel
- name: alpine
kind: image
source: alpine
Expand Down
2 changes: 1 addition & 1 deletion site/src/content/docs/versions.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ date.
source: https://cdn.kernel.org/pub/linux/kernel/v{major}.x/linux-{version}.tar.xz
version: 7.2.8
pin: 12e8d5a973d1... # the file's sha256
track: kernel-stable
track: kernel
note: what a bump has to be checked with.

- name: debian
Expand Down
3 changes: 1 addition & 2 deletions site/src/content/docs/versions/reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,7 @@ description: Every kind of entry versions.yaml takes, the build arguments each b
| `tags <repo>` | the highest release-numbered tag of a git repository; for a download, the highest whose file is published |
| `commit <repo> <branch>` | the commit a branch is at, for a download whose version is a commit: behind only when the file changed |
| `go` | the newest stable Go, spelled as the tag is (`1.27.1-trixie`) |
| `kernel-stable` | the newest release of the same stable series; a series that has ended is for a person to decide |
| `kernel-mainline` | the newest series Linus released (`7.3`), its first tarball: no stable fixes, and while mainline is at an -rc, the series before it |
| `kernel` | the newest release of the pinned series; moving to another series is naming it (`versions bump kernel 7.4.1`), and a series kernel.org no longer lists is reported and the pin stays |
| `digest` | the same tag: behind when it names another image |
| `branch` | the same branch: behind when it is at another commit |
| `pypi` | the package's newest on PyPI |
Expand Down
2 changes: 1 addition & 1 deletion versions/gate/gate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ func TestTheGateSaysWhereAPinIsNotVersionsYAMLs(t *testing.T) {
good := func() map[string]string {
return map[string]string{
versions.File: "- name: kernel\n kind: download\n source: https://x/{version}\n version: '1'\n pin: " + strings.Repeat("a", 64) +
"\n track: kernel-stable\n- name: go\n kind: image\n source: golang\n version: '1'\n pin: sha256:" + strings.Repeat("b", 64) + "\n track: go\n",
"\n track: kernel\n- name: go\n kind: image\n source: golang\n version: '1'\n pin: sha256:" + strings.Repeat("b", 64) + "\n track: go\n",
"Taskfile.yml": "cmds:\n - docker build $(go tool versions args kernel) .\n - '{{.VERSIONS}} ref go'\n",
"kernel/Dockerfile": "ARG KERNEL_VERSION\nARG KERNEL_SHA256\nFROM scratch\n",
// Written by other tools, or by a build: not the gate's.
Expand Down
55 changes: 17 additions & 38 deletions versions/upstream/upstream.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ import (
// errFollows is an entry whose newest version is another's to say: a person reads it there.
var errFollows = errors.New("versions: follows another")

// errSeriesOver is a kernel whose series kernel.org no longer lists: check says so, and a bump
// leaves the pin where it is, so a refresh goes on with its other entries.
var errSeriesOver = errors.New("the series is over: the pin stays until a person names another")

// newest is the version check says e could be at: the same for an image tracked by its digest,
// or a branch, whose pin is what moves.
func newest(ctx context.Context, e versions.Entry) (string, error) {
Expand All @@ -49,18 +53,12 @@ func newest(ctx context.Context, e versions.Entry) (string, error) {
return tag, err
case "go":
return newestGo(ctx, e.Version)
case "kernel-stable":
releases, err := kernelReleases(ctx)
if err != nil {
return "", err
}
return kernelStable(e.Version, releases)
case "kernel-mainline":
case "kernel":
releases, err := kernelReleases(ctx)
if err != nil {
return "", err
}
return kernelMainline(releases)
return kernelSeries(e.Version, releases)
case "digest", "branch":
return e.Version, nil
case "tags":
Expand Down Expand Up @@ -147,7 +145,11 @@ func Bump(ctx context.Context, v *versions.Versions, name, version string) (vers
return versions.Entry{}, nil, fmt.Errorf("versions: %s's archive is what a build's git writes of the commit, so it is bumped by hand: see its note", name)
}
if version == "" {
if version, err = newest(ctx, e); err != nil {
version, err = newest(ctx, e)
switch {
case errors.Is(err, errSeriesOver):
version = e.Version
case err != nil:
return versions.Entry{}, nil, fmt.Errorf("%w; name the version", err)
}
}
Expand Down Expand Up @@ -389,44 +391,21 @@ func kernelReleases(ctx context.Context) ([]kernelRelease, error) {
return doc.Releases, nil
}

// kernelStable is the newest release of version's series, 7.2 for 7.2.8.
func kernelStable(version string, releases []kernelRelease) (string, error) {
// kernelSeries is the newest release of version's series: 7.3.1 for 7.3, and the series itself
// while its first tarball is all there is. An -rc of it has no tarball.
func kernelSeries(version string, releases []kernelRelease) (string, error) {
major, rest, _ := strings.Cut(version, ".")
minor, _, _ := strings.Cut(rest, ".")
if minor == "" {
return "", fmt.Errorf("versions: %q is not a kernel release", version)
}
series := major + "." + minor + "."
series := major + "." + minor
for _, r := range releases {
if r.Moniker != "mainline" && strings.HasPrefix(r.Version, series) {
if r.Version == series || strings.HasPrefix(r.Version, series+".") {
return r.Version, nil
}
}
return "", fmt.Errorf("versions: kernel.org lists no %sx: the series is over, and moving to another is a decision, not a bump", series)
}

// kernelMainline is the newest X.Y Linus released. While mainline is at a release candidate,
// which has no tarball on cdn.kernel.org, that is the series stable carries: 7.3 for 7.4-rc2
// beside 7.3.2.
func kernelMainline(releases []kernelRelease) (string, error) {
var newest []int
for _, r := range releases {
if r.Moniker == "linux-next" {
continue
}
// An -rc is no number, and 7.3.2 is of 7.3: the series is the first two.
n, err := numbers(r.Version)
if err != nil || len(n) < 2 {
continue
}
if slices.Compare(n[:2], newest) > 0 {
newest = n[:2]
}
}
if newest == nil {
return "", errors.New("versions: kernel.org lists no released kernel")
}
return fmt.Sprintf("%d.%d", newest[0], newest[1]), nil
return "", fmt.Errorf("versions: kernel.org lists no %s.x: %w", series, errSeriesOver)
}

// Status is one entry as check finds it.
Expand Down
67 changes: 24 additions & 43 deletions versions/upstream/upstream_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -187,57 +187,38 @@ func TestAPinnedDownloadIsOnlyThePinnedBytes(t *testing.T) {
}
}

// Mainline is the newest X.Y Linus released: a release candidate has no tarball, so while one is
// mainline the newest is the series stable carries, and linux-next is never one.
func TestKernelMainlineIsTheNewestRelease(t *testing.T) {
for name, tc := range map[string]struct {
releases []kernelRelease
want string // "" is an error
}{
"mainline released": {[]kernelRelease{{"7.3", "mainline"}, {"7.2.13", "stable"}, {"6.18.59", "longterm"}, {"next-20261029", "linux-next"}}, "7.3"},
"mainline at an rc": {[]kernelRelease{{"7.4-rc2", "mainline"}, {"7.3.2", "stable"}, {"7.2.14", "stable"}}, "7.3"},
"a later major": {[]kernelRelease{{"8.0", "mainline"}, {"7.9.4", "stable"}}, "8.0"},
"nothing released": {[]kernelRelease{{"8.0-rc1", "mainline"}, {"next-20261029", "linux-next"}}, ""},
"a bare major": {[]kernelRelease{{"8", "mainline"}, {"7.9.4", "stable"}}, "7.9"},
} {
t.Run(name, func(t *testing.T) {
got, err := kernelMainline(tc.releases)
if tc.want == "" && err == nil {
t.Fatalf("newest %q, want an error", got)
}
if tc.want != "" && (err != nil || got != tc.want) {
t.Errorf("newest %q, %v; want %q", got, err, tc.want)
}
})
}
}

// Stable is the newest of the pinned series past mainline: a series mainline alone lists, or none
// does, is over.
func TestKernelStableIsTheNewestOfTheSeries(t *testing.T) {
releases := []kernelRelease{{"7.3", "mainline"}, {"7.2.13", "stable"}, {"6.18.59", "longterm"}}
// A kernel stays in the series it is pinned in, whatever else kernel.org has released, and a series
// nothing lists is over rather than a failure to read kernel.org.
func TestKernelStaysInItsSeries(t *testing.T) {
releases := []kernelRelease{{"7.4-rc1", "mainline"}, {"7.3.1", "stable"}, {"7.2.15", "stable"}, {"6.18.60", "longterm"}, {"next-20261029", "linux-next"}}
for version, want := range map[string]string{
"7.2.8": "7.2.13", "6.18": "6.18.59",
"7.3": "", "7.1.4": "", "7": "",
"7.3": "7.3.1", "7.3.1": "7.3.1", "7.2.8": "7.2.15", "6.18": "6.18.60",
} {
got, err := kernelStable(version, releases)
if want == "" && err == nil {
t.Errorf("%s: newest %q, want an error", version, got)
}
if want != "" && (err != nil || got != want) {
if got, err := kernelSeries(version, releases); err != nil || got != want {
t.Errorf("%s: newest %q, %v; want %q", version, got, err, want)
}
}
// Its first tarball, while mainline alone lists it.
if got, err := kernelSeries("7.4", []kernelRelease{{"7.4", "mainline"}, {"7.3.9", "stable"}}); err != nil || got != "7.4" {
t.Errorf("a first tarball: newest %q, %v", got, err)
}
// 7.4-rc1 is no release of 7.4, and 7.1 is none of 7.15's.
for _, version := range []string{"7.4", "7.1.4"} {
if got, err := kernelSeries(version, append(releases, kernelRelease{"7.15.2", "stable"})); !errors.Is(err, errSeriesOver) {
t.Errorf("%s: newest %q, %v; want the series over", version, got, err)
}
}
if _, err := kernelSeries("7", releases); err == nil || errors.Is(err, errSeriesOver) {
t.Errorf("a bare major: %v, want refused as no release", err)
}
}

// Either kernel track says it could not read kernel.org, not that kernel.org lists nothing.
func TestAKernelTrackSaysKernelOrgDidNotAnswer(t *testing.T) {
// A kernel says it could not read kernel.org, not that kernel.org lists nothing.
func TestAKernelSaysKernelOrgDidNotAnswer(t *testing.T) {
ctx, cancel := context.WithCancel(t.Context())
cancel()
for _, track := range []string{"kernel-stable", "kernel-mainline"} {
_, err := newest(ctx, versions.Entry{Version: "7.2.8", Track: track})
if !errors.Is(err, context.Canceled) {
t.Errorf("%s: %v, want kernel.org's request's error", track, err)
}
_, err := newest(ctx, versions.Entry{Version: "7.2.8", Track: "kernel"})
if !errors.Is(err, context.Canceled) {
t.Errorf("%v, want kernel.org's request's error", err)
}
}
Loading