Prove a done build's artifacts resolve in a real artifact store, in both build modules (issue 1587, S9 S10, ADR 0498's check)
The integration tests start the distribution registry (the store's own program) in the test with its in-memory storage and the real PushBlob: the built bundle and archive each answer a reference ending in its digest, the key the builder would write is valid and deliverable, and the store serves bytes of that digest at the reference. The registry is imported by these tests alone (go list -deps of the programs does not name it).
This commit is contained in:
@@ -0,0 +1,77 @@
|
||||
//go:build integration
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/distribution/distribution/v3/configuration"
|
||||
"github.com/distribution/distribution/v3/registry/handlers"
|
||||
_ "github.com/distribution/distribution/v3/registry/storage/driver/inmemory"
|
||||
|
||||
"git.novox.be/novox/mesh-sdk/go/delivery"
|
||||
)
|
||||
|
||||
// realStore starts the artifact store's own program (the distribution registry, modules/distribution) inside this
|
||||
// test, with its in-memory storage, on a loopback port, and points m at it with the real push client. It is imported
|
||||
// by this integration test alone: the module's program does not carry it.
|
||||
func realStore(t *testing.T, m *Module) string {
|
||||
t.Helper()
|
||||
config := &configuration.Configuration{Storage: configuration.Storage{"inmemory": configuration.Parameters{}}}
|
||||
config.HTTP.Secret = "a throwaway store"
|
||||
config.Log.Level = "error"
|
||||
config.Log.AccessLog.Disabled = true
|
||||
srv := httptest.NewServer(handlers.NewApp(context.Background(), config))
|
||||
t.Cleanup(srv.Close)
|
||||
addr := strings.TrimPrefix(srv.URL, "http://")
|
||||
m.RegistryFile = filepath.Join(t.TempDir(), "registry")
|
||||
if err := os.WriteFile(m.RegistryFile, []byte(addr+"\n"), 0o644); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
m.Push = nil
|
||||
return addr
|
||||
}
|
||||
|
||||
// 1587-S10 (ADR 0498's check): a done bundle names a reference whose tail is its digest, and that reference resolves in
|
||||
// a real artifact store to bytes of that digest. The build is the real tsc's and esbuild's, shut off.
|
||||
func TestADoneBundleResolvesInARealArtifactStore(t *testing.T) {
|
||||
if _, err := exec.LookPath("bwrap"); err != nil {
|
||||
t.Skip("NOT RUN: no bubblewrap installed where this check runs; every build node has it (the module declares it)")
|
||||
}
|
||||
m, _ := realMachine(t)
|
||||
addr := realStore(t, m)
|
||||
out, err := m.build(context.Background(), map[string]any{"workspace": "w1", "module": "modules/m", "artifact": "tools"})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
r := out.(BuildResult)
|
||||
done := delivery.BuilderBuild{V: 1, State: delivery.BuildDone, Manifest: strings.Repeat("0", 64),
|
||||
Artifacts: []delivery.BuiltArtifact{{Name: "tools", Kind: "bundle", Digest: r.Digest, Reference: r.Reference}}}
|
||||
if _, err := delivery.EncodeBuilderBuild(done); err != nil {
|
||||
t.Errorf("the done key the builder would write is refused: %v", err)
|
||||
}
|
||||
path, ok := strings.CutPrefix(r.Reference, "artifact-store://")
|
||||
if !ok || !strings.HasSuffix(r.Reference, "/blobs/"+r.Digest) {
|
||||
t.Fatalf("the reference %q", r.Reference)
|
||||
}
|
||||
resp, err := http.Get("http://" + addr + "/v2/" + path)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
body, _ := io.ReadAll(resp.Body)
|
||||
sum := sha256.Sum256(body)
|
||||
if resp.StatusCode != http.StatusOK || "sha256:"+hex.EncodeToString(sum[:]) != r.Digest {
|
||||
t.Errorf("the store answered %s with bytes of sha256:%x for %s", resp.Status, sum, r.Reference)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user