Skip to content

Commit 972c641

Browse files
dmitshurgopherbot
authored andcommitted
design/69095-x-repo-continuous-go.md: add design
For golang/go#69095. Change-Id: I6aa58154739456432b60ea332d324c5b7b048612 Reviewed-on: https://go-review.googlesource.com/c/proposal/+/608955 Reviewed-by: Dmitri Shuralyov <[email protected]> Auto-Submit: Dmitri Shuralyov <[email protected]>
1 parent 0392412 commit 972c641

File tree

1 file changed

+179
-0
lines changed

1 file changed

+179
-0
lines changed

design/69095-x-repo-continuous-go.md

+179
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
# Proposal: all, x/build/cmd/relui: automate go directive maintenance in golang.org/x repositories
2+
3+
Author(s): Dmitri Shuralyov
4+
Thanks to: Russ Cox, Michael Pratt, Robert Findley, Hana Kim, Cody Oss, Tim King, Carlos Amedee, and others for input
5+
6+
Last updated: 2024-08-27
7+
8+
Discussion at https://go.dev/issue/69095.
9+
10+
## Abstract
11+
12+
The value of the `go` directive in golang.org/x repositories
13+
is automatically maintained
14+
to be at least 1.(N-1).0,
15+
where Go 1.N is the most recent major Go release,
16+
and Go 1.(N-1) is the previous major Go release.
17+
18+
## Background
19+
20+
In the beginning, there was the GOPATH mode and versions of dependencies
21+
of golang.org/x repositories weren't explicitly tracked.
22+
Go 1.11 introduced the module mode, and over time it became the default mode.
23+
All golang.org/x repositories had an initial go.mod file checked in, and
24+
that file was maintained manually.
25+
This meant that a bug fix or a new feature in one golang.org/x repository
26+
didn't benefit another golang.org/x repository until someone chose to manually
27+
update that dependency.
28+
It also meant that eventual updates sometimes jumped many versions at once
29+
to catch up.
30+
This was resolved in 2022, when an automated monthly relui workflow began to
31+
create tags and update golang.org/x dependencies across all golang.org/x
32+
repositories ([issue 48523](https://go.dev/issue/48523)).
33+
34+
At this point there are upwards of 35 [golang.org/x](https://golang.org/x)
35+
repositories.
36+
Owners of each repository update the "go" directive manually, ad-hoc,
37+
so golang.org/x repositories may receive different levels of "go" directive
38+
maintenance.
39+
For example, owners of the golang.org/x/mod module wished to use the
40+
new-to-Go-1.22 `go/version` package as soon as Go 1.23 came out, and
41+
so its "go" directive was recently updated to "1.22.0".
42+
On the other hand, golang.org/x/image hasn't been updated in a while, and
43+
its "go" directive is currently still at "1.18",
44+
which itself was an upgrade from "1.12" in [CL 526895](https://go.dev/cl/526895)
45+
as part of bringing all golang.org/x repos to use at minimum Go 1.18 language
46+
version ([issue 60268](https://go.dev/issue/48523)).
47+
48+
Leaving go directive maintenance to be done entirely manually creates the
49+
possibility of some repositories staying on an older Go language version longer.
50+
When there's enough of a need to finally upgrade it to a recent Go language
51+
version, this requires a change across multiple major Go releases at once,
52+
which can be harder to review.
53+
Having continuous, smaller incremental upgrades requires creating many CLs for
54+
all of golang.org/x repositories every 6 months, which is toilsome if always
55+
done manually.
56+
57+
## Proposal
58+
59+
I propose that each time that a new major Go release 1.N.0 is made,
60+
the `go` directive in all golang.org/x repos will be upgraded to `go 1.(N-1).0`.
61+
For example,
62+
when Go 1.28.0 is released,
63+
golang.org/x modules would have their `go` directive set to `go 1.27.0`.
64+
65+
This would be done automatically as part of a relui release workflow,
66+
which will generate CLs by running the following sequence at the module root
67+
of applicable repositories:
68+
69+
```
70+
go get go@1.(N-1).0
71+
go mod tidy
72+
go fix ./...
73+
```
74+
75+
Using the go command at version `go1.N.0`.
76+
77+
Modules whose `go` directive at the time is already a higher version will be
78+
skipped rather than downgraded.
79+
80+
If a `toolchain` directive is present and higher than the new go directive,
81+
it will be kept as is.
82+
(The go command does this automatically while updating the go line.)
83+
If a `toolchain` directive isn't present,
84+
these automated CLs will not try to introduce it.
85+
86+
The first two commands in the sequence leave the module in a tidy state.
87+
The `go fix ./...` command will apply high-confidence automated changes,
88+
in case any begin to apply with the updated Go language version.
89+
For example, go fix began to remove the now-obsolete
90+
[`// +build` lines](https://go.dev/doc/go1.18#go-build-lines) once a module
91+
is upgraded to 1.18 or later.
92+
For many new language versions this will be a no-op, but it is expected
93+
that including a `go fix ./...` invocation will be a net positive.
94+
We can decide to stop including it in the generated CLs based on experience.
95+
96+
If a `go.work` file is checked in (rare case), then `go work sync` will also
97+
be run to sync the workspace's build list back to the workspace's modules.
98+
99+
## Rationale
100+
101+
### Why 1.(N-1).0?
102+
103+
N-1 is chosen to align with the
104+
[Go release policy](https://go.dev/doc/devel/release#policy).
105+
The Go release policy states that a given major Go release is supported
106+
until there are two newer major releases.
107+
108+
Picking N-1 makes this a no-op for golang.org/x module users who are using
109+
a supported Go release. If a user is using a pre-release version of the
110+
previous (also supported) major Go release, they'll be upgraded to
111+
the stable major release (e.g., `go1.22rc1` to `go1.22.0`).
112+
For golang.org/x module authors, raising the go directive from a lower value
113+
to N-1 enables taking advantage of newer language features and fixes potentially
114+
sooner than if no one got to updating the module's language version manually.
115+
116+
### Why not 1.(N-0).0?
117+
118+
N-0 would get in the way of one's ability to use the latest versions of
119+
golang.org/x modules with all supported Go releases.
120+
It would be possible to use the latest major Go release,
121+
but not the previous (still supported) major Go release,
122+
at least not without triggering a toolchain upgrade to a newer major Go release.
123+
The Go release policy states we support both releases equally,
124+
and issue bug fixes and security fixes to both,
125+
so this proposal preserves that equality.
126+
127+
### Why not N-2 (or N-3, or N-4, and so on)?
128+
129+
Using older versions gives the impression that those releases
130+
are still supported,
131+
but they are not.
132+
133+
### Why not bump on each minor release?
134+
135+
Another option would be to always use the latest 1.(N-1).X,
136+
updating all the x repos each time a new minor Go release comes out.
137+
That forces everyone to update to that new minor release
138+
in order to incorporate any new x repo changes,
139+
which seems too aggressive.
140+
As much as we try to avoid it, minor Go releases do sometimes contain bugs,
141+
and it should be possible to choose to use older ones if needed.
142+
143+
### Why not bump the toolchain lines too?
144+
145+
The `toolchain` line can only be set to a toolchain the same or newer than
146+
the `go` line, and it only affects people working in the repo itself.
147+
That is, it does not affect users of the x repos.
148+
Therefore it is not as important.
149+
Just as we want to allow users to use the x repos with any supported Go version,
150+
we want to allow users to work in the x repos with any supported Go version, so
151+
leaving the toolchain lines implied by the go line seems like the right choice.
152+
153+
### Future work
154+
155+
There are aspects of this work that have been considered but chosen to be left
156+
out of scope for the initial version.
157+
We may want to refine some of the smaller details down the road,
158+
especially once there's more experience with the proposed mechanism.
159+
160+
#### Nested modules
161+
162+
Nested modules are not in scope of the current tagging,
163+
and not in scope of the initial go directive maintenance either.
164+
There are fewer of them, and they often have custom constraints
165+
or release processes.
166+
They can be left to be managed by their corresponding repo owners for now.
167+
This can be revisited in the future, when it's more worthwhile.
168+
169+
## Compatibility
170+
171+
This proposal takes the [Go 1 Compatibility Promise](https://go.dev/doc/go1compat)
172+
and the [Go Release Policy](https://go.dev/doc/devel/release#policy) into account,
173+
and does not introduce compatibility problems.
174+
175+
## Implementation
176+
177+
This will be implemented as part of [relui](https://golang.org/x/build/cmd/relui),
178+
a service already responsible for Go release automation and
179+
monthly golang.org/x repository tagging.

0 commit comments

Comments
 (0)