Cache Go modules in platform builder
This commit is contained in:
@@ -52,6 +52,7 @@ type DockerDistributionBuilderConfig struct {
|
||||
Image string
|
||||
SourceDir string
|
||||
WorkspaceDir string
|
||||
CacheDir string
|
||||
Timeout time.Duration
|
||||
PlatformURL string
|
||||
CommandRunner func(ctx context.Context, name string, args ...string) ([]byte, error)
|
||||
@@ -198,6 +199,10 @@ func (builder *DockerDistributionBuilder) BuildWithProgress(input domain.Distrib
|
||||
if err != nil {
|
||||
return nil, validationError("platform builder workspace directory is invalid")
|
||||
}
|
||||
cacheDir, err := builder.cacheDir(workspaceDir)
|
||||
if err != nil {
|
||||
return nil, validationError("platform builder cache directory is invalid")
|
||||
}
|
||||
// Workspaces stay isolated per plugin and per job as required by
|
||||
// run-build-download-flow.
|
||||
jobDir := filepath.Join(workspaceDir, sanitizeIDPart(input.PluginID), sanitizeIDPart(input.JobID))
|
||||
@@ -207,7 +212,9 @@ func (builder *DockerDistributionBuilder) BuildWithProgress(input domain.Distrib
|
||||
outputDir := filepath.Join(jobDir, "output")
|
||||
inputDir := filepath.Join(jobDir, "input")
|
||||
buildDir := filepath.Join(jobDir, "build")
|
||||
for _, directory := range []string{outputDir, inputDir, buildDir} {
|
||||
goBuildCacheDir := filepath.Join(cacheDir, "go-build")
|
||||
goModCacheDir := filepath.Join(cacheDir, "go-mod")
|
||||
for _, directory := range []string{outputDir, inputDir, buildDir, goBuildCacheDir, goModCacheDir} {
|
||||
if err := os.MkdirAll(directory, 0o700); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -256,7 +263,7 @@ func (builder *DockerDistributionBuilder) BuildWithProgress(input domain.Distrib
|
||||
}
|
||||
ctx, cancel := context.WithTimeout(context.Background(), builder.config.Timeout)
|
||||
defer cancel()
|
||||
args := builder.containerArgs(input, sourceDir, inputDir, buildDir, outputDir, outputName)
|
||||
args := builder.containerArgs(input, sourceDir, inputDir, buildDir, outputDir, goBuildCacheDir, goModCacheDir, outputName)
|
||||
reportBuilderProgress(progress, 18, "git_sync: platform builder container starting")
|
||||
output, err := builder.runBuildCommand(ctx, args, progress)
|
||||
if err != nil {
|
||||
@@ -283,6 +290,14 @@ func (builder *DockerDistributionBuilder) BuildWithProgress(input domain.Distrib
|
||||
return packageClientManagerDistribution(input.PackageFormat, outputName, binary, configPayload)
|
||||
}
|
||||
|
||||
func (builder *DockerDistributionBuilder) cacheDir(workspaceDir string) (string, error) {
|
||||
configured := strings.TrimSpace(builder.config.CacheDir)
|
||||
if configured == "" {
|
||||
configured = filepath.Join(workspaceDir, "_cache")
|
||||
}
|
||||
return filepath.Abs(configured)
|
||||
}
|
||||
|
||||
func (builder *DockerDistributionBuilder) runBuildCommand(ctx context.Context, args []string, progress func(DistributionBuildProgress)) ([]byte, error) {
|
||||
if builder.config.CommandStream == nil {
|
||||
return builder.config.CommandRunner(ctx, builder.config.DockerBinary, args...)
|
||||
@@ -410,7 +425,7 @@ cp config.yaml /workspace/output/config.yaml
|
||||
progress 88 'package_finalize: client-manager package inputs written'
|
||||
`
|
||||
|
||||
func (builder *DockerDistributionBuilder) containerArgs(input domain.DistributionBuildInput, sourceDir string, inputDir string, buildDir string, outputDir string, outputName string) []string {
|
||||
func (builder *DockerDistributionBuilder) containerArgs(input domain.DistributionBuildInput, sourceDir string, inputDir string, buildDir string, outputDir string, goBuildCacheDir string, goModCacheDir string, outputName string) []string {
|
||||
platformURL := strings.TrimSpace(input.PlatformURL)
|
||||
if platformURL == "" {
|
||||
platformURL = strings.TrimSpace(builder.config.PlatformURL)
|
||||
@@ -424,11 +439,13 @@ func (builder *DockerDistributionBuilder) containerArgs(input domain.Distributio
|
||||
"-v", inputDir + ":/workspace/input:ro",
|
||||
"-v", buildDir + ":/workspace/build",
|
||||
"-v", outputDir + ":/workspace/output",
|
||||
"-v", goBuildCacheDir + ":/workspace/cache/go-build",
|
||||
"-v", goModCacheDir + ":/workspace/cache/go-mod",
|
||||
"-e", "CGO_ENABLED=0",
|
||||
"-e", "GOOS=" + input.TargetOS,
|
||||
"-e", "GOARCH=" + input.TargetArch,
|
||||
"-e", "GOCACHE=/tmp/go-build",
|
||||
"-e", "GOMODCACHE=/tmp/go-mod",
|
||||
"-e", "GOCACHE=/workspace/cache/go-build",
|
||||
"-e", "GOMODCACHE=/workspace/cache/go-mod",
|
||||
"-e", "COMPONENT_KIND=" + string(input.ComponentKind),
|
||||
"-e", "SERVER_INSTANCE_ID=" + input.ServerInstanceID,
|
||||
"-e", "PLUGIN_ID=" + input.PluginID,
|
||||
|
||||
@@ -97,6 +97,7 @@ func TestDockerDistributionBuilderReadinessNamesPlatformBuilderFailures(t *testi
|
||||
func TestDockerDistributionBuilderKeepsSecretInIsolatedInput(t *testing.T) {
|
||||
sourceDir := createBuilderSource(t)
|
||||
workspaceDir := t.TempDir()
|
||||
cacheDir := filepath.Join(t.TempDir(), "builder-cache")
|
||||
secret := "component-auth-key-that-must-not-leave-input"
|
||||
var dockerArgs []string
|
||||
builder := NewDockerDistributionBuilder(DockerDistributionBuilderConfig{
|
||||
@@ -104,6 +105,7 @@ func TestDockerDistributionBuilderKeepsSecretInIsolatedInput(t *testing.T) {
|
||||
Image: "browser-platform-distribution-builder:1.0.0",
|
||||
SourceDir: sourceDir,
|
||||
WorkspaceDir: workspaceDir,
|
||||
CacheDir: cacheDir,
|
||||
CommandRunner: func(_ context.Context, name string, args ...string) ([]byte, error) {
|
||||
if name != "docker-test" {
|
||||
t.Fatalf("unexpected container runtime %q", name)
|
||||
@@ -114,6 +116,11 @@ func TestDockerDistributionBuilderKeepsSecretInIsolatedInput(t *testing.T) {
|
||||
dockerArgs = append([]string(nil), args...)
|
||||
inputDir := builderMountHostPath(t, args, "/workspace/input:ro")
|
||||
outputDir := builderMountHostPath(t, args, "/workspace/output")
|
||||
goBuildCacheDir := builderMountHostPath(t, args, "/workspace/cache/go-build")
|
||||
goModCacheDir := builderMountHostPath(t, args, "/workspace/cache/go-mod")
|
||||
if goBuildCacheDir != filepath.Join(cacheDir, "go-build") || goModCacheDir != filepath.Join(cacheDir, "go-mod") {
|
||||
t.Fatalf("unexpected Go cache mounts: build=%q mod=%q", goBuildCacheDir, goModCacheDir)
|
||||
}
|
||||
authPath := filepath.Join(inputDir, "auth-key")
|
||||
payload, err := os.ReadFile(authPath)
|
||||
if err != nil {
|
||||
@@ -174,7 +181,7 @@ func TestDockerDistributionBuilderKeepsSecretInIsolatedInput(t *testing.T) {
|
||||
if strings.Contains(joinedArgs, secret) {
|
||||
t.Fatal("component auth key leaked into Docker arguments or environment")
|
||||
}
|
||||
for _, required := range []string{"--read-only", "--pull\x00never", sourceDir + ":/workspace/source:ro", ":/workspace/input:ro", ":/workspace/output"} {
|
||||
for _, required := range []string{"--read-only", "--pull\x00never", sourceDir + ":/workspace/source:ro", ":/workspace/input:ro", ":/workspace/output", cacheDir + "/go-build:/workspace/cache/go-build", cacheDir + "/go-mod:/workspace/cache/go-mod", "GOCACHE=/workspace/cache/go-build", "GOMODCACHE=/workspace/cache/go-mod"} {
|
||||
if !strings.Contains(joinedArgs, required) {
|
||||
t.Fatalf("Docker arguments do not contain required isolation %q: %q", required, joinedArgs)
|
||||
}
|
||||
@@ -183,6 +190,9 @@ func TestDockerDistributionBuilderKeepsSecretInIsolatedInput(t *testing.T) {
|
||||
if _, err := os.Stat(jobDir); !errors.Is(err, os.ErrNotExist) {
|
||||
t.Fatalf("per-job workspace was not removed: %v", err)
|
||||
}
|
||||
if _, err := os.Stat(filepath.Join(cacheDir, "go-mod")); err != nil {
|
||||
t.Fatalf("persistent Go module cache was not retained: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDockerDistributionBuilderStreamsProgressMarkers(t *testing.T) {
|
||||
|
||||
Reference in New Issue
Block a user