Read a go download failure as a pin on a pull request head only when go does not know the revision, so a network failure is retaken and says its own cause
Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
This commit is contained in:
@@ -106,7 +106,7 @@ func (m *Module) resolvePins(ctx context.Context, root, dir, failure string) (bo
|
||||
}
|
||||
progress := false
|
||||
for _, p := range forgePins(string(raw)) {
|
||||
if !strings.Contains(failure, p.short) || strings.Contains(done, "replace "+p.module+" =>") {
|
||||
if !unknownRevision(failure) || !strings.Contains(failure, p.short) || strings.Contains(done, "replace "+p.module+" =>") {
|
||||
continue
|
||||
}
|
||||
where, err := m.placePin(ctx, root, p, failure)
|
||||
|
||||
@@ -103,6 +103,11 @@ func (m *Module) takeVersion(ctx context.Context, root, dir string, tv *TakenVer
|
||||
if r.Status != 0 || r.Err != "" || info.Version == "" || info.Error != "" {
|
||||
// Not a commit Go can fetch: the head of a group's pull request (ADR 0573 §4), placed from the forge's heads.
|
||||
failure := strings.TrimSpace(info.Error + "\n" + r.Err + "\n" + r.Stderr)
|
||||
if !unknownRevision(failure) {
|
||||
// A download that failed for another cause (the forge or the resolver did not answer) says nothing of the pin: it
|
||||
// fails with go's own words, and not as a kind the builder holds until the module changes (issue 1748).
|
||||
return fmt.Errorf("downloading the asked version %s of %s failed (a download failure that may be retaken): %s", tv.Asked, tv.Package, causeLine(failure))
|
||||
}
|
||||
repo, sub, _ := strings.Cut(strings.TrimPrefix(tv.Package, forgePrefix), "/")
|
||||
p := pin{module: tv.Package, repo: repo, sub: sub, short: tv.Asked[:12]}
|
||||
pins.Lock()
|
||||
@@ -263,3 +268,10 @@ func comparePre(a, b string) int {
|
||||
}
|
||||
return strings.Compare(a, b)
|
||||
}
|
||||
|
||||
// unknownRevision says whether a go failure is go not knowing the revision (cmd/go's "unknown revision" and the
|
||||
// "invalid version" it wraps it in): the only failure that means a commit no tag or trunk holds, which may be the head of a
|
||||
// pull request. Every other failure is the network's or the forge's.
|
||||
func unknownRevision(failure string) bool {
|
||||
return strings.Contains(failure, "unknown revision") || strings.Contains(failure, "invalid version")
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ func TestAnAskedVersionIsWrittenIntoTheModfileWhateverGoModNames(t *testing.T) {
|
||||
name, asked, answer string
|
||||
failing bool
|
||||
built, said, edit string
|
||||
failsWith string // a download failure that is not an unknown revision: the step fails with go's own words
|
||||
}{
|
||||
{name: "a trunk commit newer than go.mod's", asked: trunk,
|
||||
answer: `{"Path":"` + sdk + `","Version":"v0.1.15-0.20261101000000-aaaaaaaaaaaa","Sum":"h1:zip=","GoModSum":"h1:mod="}`,
|
||||
@@ -34,6 +35,12 @@ func TestAnAskedVersionIsWrittenIntoTheModfileWhateverGoModNames(t *testing.T) {
|
||||
{name: "a group's head Go cannot fetch", asked: commitSHA, failing: true,
|
||||
answer: `{"Path":"` + sdk + `","Error":"invalid version: unknown revision ` + pinShort + `"}`,
|
||||
built: commitSHA, said: "placed from the pull request's head"},
|
||||
// The wording of go's errors: "unknown revision" is in cmd/go/internal/modfetch/coderepo_test.go; the lookup and
|
||||
// connection texts are those of issue 1748's report and of the dial errors go prints for an unreachable forge.
|
||||
{name: "a lookup that times out is no pin", asked: commitSHA, failing: true, failsWith: "i/o timeout",
|
||||
answer: `{"Path":"` + sdk + `","Error":"git.novox.be/novox/mesh-sdk/go@` + commitSHA + `: dial tcp: lookup git.novox.be on 10.10.0.3:53: read udp 10.10.0.3:42292->10.10.0.3:53: i/o timeout"}`},
|
||||
{name: "a refused connection is no pin", asked: commitSHA, failing: true, failsWith: "connection refused",
|
||||
answer: `{"Path":"` + sdk + `","Error":"git ls-remote -q origin in /tmp/gopath: dial tcp 10.10.0.1:443: connect: connection refused"}`},
|
||||
} {
|
||||
t.Run(c.name, func(t *testing.T) {
|
||||
h, states := newPinHarness(t, pinnedGoMod, false, pullList)
|
||||
@@ -69,6 +76,13 @@ func TestAnAskedVersionIsWrittenIntoTheModfileWhateverGoModNames(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
st := states.waitEnd(t)
|
||||
if c.failsWith != "" {
|
||||
if st.State != delivery.StepFailed || !strings.Contains(st.Reason, c.failsWith) || strings.Contains(st.Reason, "no pull request head") ||
|
||||
!strings.Contains(st.Reason, "may be retaken") || delivery.FailedUntilChanged(st.Reason) || h.ran("ls-remote") {
|
||||
t.Errorf("the download failure ended %s: %q (ls-remote ran: %v)", st.State, st.Reason, h.ran("ls-remote"))
|
||||
}
|
||||
return
|
||||
}
|
||||
if st.State != delivery.StepPassed {
|
||||
t.Fatalf("the step ended %s: %s", st.State, st.Reason)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user