Make delivery asset outcomes disjoint

This commit is contained in:
2026-10-06 17:54:22 +00:00
parent 0eec4a30ed
commit c9afc8dd12
10 changed files with 322 additions and 32 deletions

View File

@@ -317,6 +317,82 @@ func TestDeliverBuildsTaggedArtifactsAndReusesAssets(t *testing.T) {
}
}
func TestDeliverFailureReportsRecoveryForPartialConflictAndUnknownStates(t *testing.T) {
for _, test := range []struct {
name string
state string
status int
recovery []string
assetObservation string
missingObservation string
}{
{
name: "partial",
status: 1,
recovery: []string{"recovery: fix the reported cause", "retry this version"},
assetObservation: "pending helper-v1.2.3-linux-amd64",
},
{
name: "conflict",
status: 1,
recovery: []string{"investigate conflicting hosted content", "new version", "retain the original build artifacts"},
assetObservation: "conflicting helper-v1.2.3-linux-amd64",
missingObservation: "pending SHA256SUMS",
},
{
name: "unknown",
status: 3,
recovery: []string{"resolve the remote state before retrying"},
assetObservation: "uncertain helper-v1.2.3-linux-amd64",
missingObservation: "pending SHA256SUMS",
},
} {
t.Run(test.name, func(t *testing.T) {
repository := newCLIRepository(t)
state := &deliveryServerState{}
server := newDeliveryServer(t, state)
defer server.Close()
build := cli.BuildSettings{MainPackage: ".", BinaryName: "helper", Targets: []string{"linux/amd64"}}
writeDeliveryProfile(t, repository, cli.Settings{
Product: "Example Product",
Build: &build,
Delivery: &cli.DeliverySettings{BaseURL: server.URL, Owner: "owner", Repository: "example"},
})
state.commit = cliGitOutput(t, repository, "rev-parse", "HEAD")
cliGitRun(t, repository, "tag", "v1.2.3")
assetsDir, _ := writeDeliveryReceipt(t, repository, build)
switch test.name {
case "partial":
state.failAssetName = "helper-v1.2.3-linux-amd64"
case "conflict":
state.assets["helper-v1.2.3-linux-amd64"] = []byte("different hosted bytes")
case "unknown":
state.ambiguousAssetName = "helper-v1.2.3-linux-amd64"
}
t.Setenv("RELEASEKIT_GITEA_TOKEN", "fixture-token")
var stdout, stderr bytes.Buffer
status := run(context.Background(), []string{"deliver", "--repo", repository, "--assets", assetsDir, "v1.2.3"}, &stdout, &stderr)
if status != test.status || !strings.Contains(stderr.String(), "state="+test.name) {
t.Fatalf("status=%d output=%q want status=%d state=%s", status, stderr.String(), test.status, test.name)
}
for _, phrase := range test.recovery {
if !strings.Contains(stderr.String(), phrase) {
t.Errorf("delivery output does not include recovery guidance %q: %s", phrase, stderr.String())
}
}
if !strings.Contains(stderr.String(), test.assetObservation) {
t.Errorf("delivery output does not include asset observation %q: %s", test.assetObservation, stderr.String())
}
if test.missingObservation != "" && !strings.Contains(stderr.String(), test.missingObservation) {
t.Errorf("delivery output does not include later missing asset %q: %s", test.missingObservation, stderr.String())
}
if test.name == "unknown" && strings.Contains(stderr.String(), "pending helper-v1.2.3-linux-amd64") {
t.Errorf("uncertain asset also appears pending: %s", stderr.String())
}
})
}
}
func TestDeliverRejectsWrongHostedTagBeforeReleaseWrite(t *testing.T) {
repository := newCLIRepository(t)
state := &deliveryServerState{remoteCommit: strings.Repeat("0", 40)}
@@ -443,6 +519,8 @@ type deliveryServerState struct {
malformedCreate bool
failAssetListing bool
failAssetDownloads bool
failAssetName string
ambiguousAssetName string
commit string
product string
remoteCommit string
@@ -543,6 +621,14 @@ func newDeliveryServer(t *testing.T, state *deliveryServerState) *httptest.Serve
if _, exists := state.assets[name]; exists {
t.Errorf("asset %q uploaded more than once", name)
}
if name == state.failAssetName {
http.Error(w, "upload failed", http.StatusBadRequest)
return
}
if name == state.ambiguousAssetName {
http.Error(w, "upload outcome ambiguous", http.StatusInternalServerError)
return
}
state.assets[name] = content
state.assetUploads++
_ = json.NewEncoder(w).Encode(map[string]any{"id": state.assetUploads, "name": name, "size": len(content)})
@@ -751,6 +837,9 @@ func TestUnreadableAssetsDoNotClaimAnUnknownWrite(t *testing.T) {
if status != 1 || !strings.Contains(stderr.String(), "state="+expectedState) || state.assetUploads != 0 || state.releaseCreates != expectedCreates {
t.Fatalf("status=%d creates=%d uploads=%d %s", status, state.releaseCreates, state.assetUploads, stderr.String())
}
if existingPage && !strings.Contains(stderr.String(), "recovery: fix the local or preflight failure") {
t.Fatalf("not-attempted recovery guidance missing: %s", stderr.String())
}
})
}
}