Repository: chainguard-dev/apko
Pull request #1663 (2025-05-07 18:01:22)

Fix build_repositories for layered images
I neglected to call the method that overwrites etc/apk/repositories with RuntimeRepositories instead of BuildRepositories + RuntimeRepositories.

Added a test to make that not happen again.

Also moved tarfs around to make it accessible from that test.


Patch:
diff --git a/pkg/apk/internal/tarfs/tarfs.go b/internal/tarfs/tarfs.go
similarity index 100%
rename from pkg/apk/internal/tarfs/tarfs.go
rename to internal/tarfs/tarfs.go
diff --git a/pkg/apk/apk/implementation.go b/pkg/apk/apk/implementation.go
index 19154fc..2e2f794 100644
--- a/pkg/apk/apk/implementation.go
+++ b/pkg/apk/apk/implementation.go
@@ -51,10 +51,10 @@ import (
 	"golang.org/x/sys/unix"
 	"gopkg.in/ini.v1"
 
+	"chainguard.dev/apko/internal/tarfs"
 	"chainguard.dev/apko/pkg/apk/auth"
 	"chainguard.dev/apko/pkg/apk/expandapk"
 	apkfs "chainguard.dev/apko/pkg/apk/fs"
-	"chainguard.dev/apko/pkg/apk/internal/tarfs"
 	"chainguard.dev/apko/pkg/paths"
 
 	"github.com/chainguard-dev/clog"
diff --git a/pkg/apk/apk/install.go b/pkg/apk/apk/install.go
index c6bed73..4fc5f11 100644
--- a/pkg/apk/apk/install.go
+++ b/pkg/apk/apk/install.go
@@ -29,7 +29,7 @@ import (
 
 	"go.opentelemetry.io/otel"
 
-	"chainguard.dev/apko/pkg/apk/internal/tarfs"
+	"chainguard.dev/apko/internal/tarfs"
 )
 
 // writeOneFile writes one file from the APK given the tar header and tar reader.
diff --git a/pkg/apk/expandapk/expandapk.go b/pkg/apk/expandapk/expandapk.go
index 5900b89..1beb028 100644
--- a/pkg/apk/expandapk/expandapk.go
+++ b/pkg/apk/expandapk/expandapk.go
@@ -22,7 +22,7 @@ import (
 	"strings"
 	"sync"
 
-	"chainguard.dev/apko/pkg/apk/internal/tarfs"
+	"chainguard.dev/apko/internal/tarfs"
 	"github.com/klauspost/compress/gzip"
 
 	"go.opentelemetry.io/otel"
diff --git a/pkg/build/layers.go b/pkg/build/layers.go
index 52fe866..02a4b30 100644
--- a/pkg/build/layers.go
+++ b/pkg/build/layers.go
@@ -49,6 +49,18 @@ func (bc *Context) buildLayers(ctx context.Context) ([]v1.Layer, error) {
 		return nil, fmt.Errorf("building filesystem: %w", err)
 	}
 
+	// We don't pass around repositories cleanly between apko and the library
+	// formerly known as go-apk. Instead, we write stuff to bc.fs directly
+	// and the library formerly known as go-apk reads from bc.fs to know
+	// which repositories it can fetch packages from. We need to call this
+	// to overwrite etc/apk/repositories with _only_ runtime repositories
+	// and not runtime + build repositories.
+	//
+	// TODO: Clean this up when time permits.
+	if err := bc.postBuildSetApk(ctx); err != nil {
+		return nil, err
+	}
+
 	// Use our layering strategy to partition packages into a set of Budget groups.
 	groups, err := groupByOriginAndSize(pkgs, bc.ic.Layering.Budget)
 	if err != nil {


Test patch:
diff --git a/internal/cli/publish_test.go b/internal/cli/publish_test.go
index 0100792..e287c85 100644
--- a/internal/cli/publish_test.go
+++ b/internal/cli/publish_test.go
@@ -17,20 +17,25 @@ package cli_test
 import (
 	"context"
 	"fmt"
+	"io"
+	"io/fs"
 	"net/http"
 	"net/http/httptest"
 	"net/url"
 	"os"
 	"path/filepath"
+	"strings"
 	"testing"
 
 	"github.com/google/go-containerregistry/pkg/name"
 	"github.com/google/go-containerregistry/pkg/registry"
+	"github.com/google/go-containerregistry/pkg/v1/mutate"
 	"github.com/google/go-containerregistry/pkg/v1/remote"
 	"github.com/google/go-containerregistry/pkg/v1/validate"
 	"github.com/stretchr/testify/require"
 
 	"chainguard.dev/apko/internal/cli"
+	"chainguard.dev/apko/internal/tarfs"
 	"chainguard.dev/apko/pkg/build"
 	"chainguard.dev/apko/pkg/build/types"
 	"chainguard.dev/apko/pkg/sbom"
@@ -162,7 +167,7 @@ func TestPublishLayering(t *testing.T) {
 
 	// This test will fail if we ever make a change in apko that changes the image.
 	// Sometimes, this is intentional, and we need to change this and bump the version.
-	want := "sha256:316b607c2d30e686d9170edcefa9bc07aae922e4c20c06cc85bd6e4c0ed85f25"
+	want := "sha256:d5fe88a41005bc378fc42d3066d4762b2c082e528cd2856e27f4e005031bfd35"
 	require.Equal(t, want, digest.String())
 
 	im, err := idx.IndexManifest()
@@ -176,5 +181,20 @@ func TestPublishLayering(t *testing.T) {
 		require.NoError(t, err)
 
 		require.Equal(t, 2, len(cm.Layers))
+
+		tr := mutate.Extract(child)
+		tmp, err := os.CreateTemp(t.TempDir(), "")
+		require.NoError(t, err)
+		size, err := io.Copy(tmp, tr)
+		require.NoError(t, err)
+		fsys, err := tarfs.New(tmp, size)
+		require.NoError(t, err)
+
+		b, err := fs.ReadFile(fsys, "etc/apk/repositories")
+		require.NoError(t, err)
+
+		if strings.Contains(string(b), "./packages") {
+			t.Errorf("etc/apk/repositories contains build_repositories entry %q", "./packages")
+		}
 	}
 }
diff --git a/internal/cli/testdata/layering.yaml b/internal/cli/testdata/layering.yaml
index 4b7b66c..f1254a9 100644
--- a/internal/cli/testdata/layering.yaml
+++ b/internal/cli/testdata/layering.yaml
@@ -1,6 +1,8 @@
 contents:
   keyring:
     - ./testdata/melange.rsa.pub
+  build_repositories:
+    - ./packages
   repositories:
     - ./testdata/packages
   packages: