Skip to content

Commit

Permalink
Lock image configs before building (#1441)
Browse files Browse the repository at this point in the history
The embedded /etc/apko.json included both archs in the config, which was
a little weird. It also wasn't locked, which is maybe on purpose, but
locking feels better than not locking. Will make sure this is acceptable
before merging.

Signed-off-by: Jon Johnson <[email protected]>
  • Loading branch information
jonjohnsonjr authored Dec 14, 2024
1 parent 0686921 commit 559534f
Show file tree
Hide file tree
Showing 16 changed files with 86 additions and 98 deletions.
76 changes: 32 additions & 44 deletions internal/cli/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"log/slog"
"os"
"path/filepath"
"slices"
"sync"

"github.com/google/go-containerregistry/pkg/v1/layout"
Expand All @@ -38,6 +39,7 @@ import (
"chainguard.dev/apko/pkg/build/oci"
"chainguard.dev/apko/pkg/build/types"
"chainguard.dev/apko/pkg/sbom"
"chainguard.dev/apko/pkg/tarfs"
)

func buildCmd() *cobra.Command {
Expand Down Expand Up @@ -236,6 +238,7 @@ func buildImageComponents(ctx context.Context, workDir string, archs []types.Arc
// computation.
multiArchBDE := o.SourceDateEpoch

configs, _, err := build.LockImageConfiguration(ctx, *ic, opts...)
mc, err := build.NewMultiArch(ctx, archs, opts...)
if err != nil {
return nil, nil, err
Expand All @@ -247,26 +250,27 @@ func buildImageComponents(ctx context.Context, workDir string, archs []types.Arc
}
}

// This is a little different, but we use a multiarch builder to call BuildLayers because we want
// each architecture to be aware of the other architectures during the solve stage. We don't want
// to select any packages unless they are available on every architecture because we want solutions
// to match across architectures.
//
// Eventually, we probably want to do something similar for all this logic around stitching images together.
layers, err := mc.BuildLayers(ctx)
if err != nil {
return nil, nil, fmt.Errorf("building layers: %w", err)
}

for _, arch := range archs {
arch := arch

for arch, ic := range configs {
errg.Go(func() error {
if arch == "index" {
return nil
}

arch := types.ParseArchitecture(arch)
log := clog.New(slog.Default().Handler()).With("arch", arch.ToAPK())
ctx := clog.WithLogger(ctx, log)

bc := mc.Contexts[arch]
layer := layers[arch]
opts := slices.Clone(opts)
opts = append(opts, build.WithArch(arch), build.WithImageConfiguration(*ic))

bc, err := build.New(ctx, tarfs.New(), opts...)
if err != nil {
return fmt.Errorf("new build for arch %s: %w", arch, err)
}
_, layer, err := bc.BuildLayer(ctx)
if err != nil {
return fmt.Errorf("building %q layer: %w", arch, err)
}

// Compute the "build date epoch" from the packages that were
// installed. The "build date epoch" is the MAX of the builddate
Expand All @@ -285,6 +289,14 @@ func buildImageComponents(ctx context.Context, workDir string, archs []types.Arc
return fmt.Errorf("failed to build OCI image for %q: %w", arch, err)
}

var outputs []types.SBOM
if len(o.SBOMFormats) != 0 {
outputs, err = bc.GenerateImageSBOM(ctx, arch, img)
if err != nil {
return fmt.Errorf("generating sbom for %s: %w", arch, err)
}
}

mtx.Lock()
defer mtx.Unlock()

Expand All @@ -294,6 +306,10 @@ func buildImageComponents(ctx context.Context, workDir string, archs []types.Arc
multiArchBDE = bde
}

if len(o.SBOMFormats) != 0 {
sboms = append(sboms, outputs...)
}

return nil
})
}
Expand Down Expand Up @@ -323,34 +339,6 @@ func buildImageComponents(ctx context.Context, workDir string, archs []types.Arc

// the sboms are saved to the same working directory as the image components
if len(o.SBOMFormats) != 0 {
var (
g errgroup.Group
mtx sync.Mutex
)
for arch, img := range imgs {
arch, img := arch, img
bc := mc.Contexts[arch]

g.Go(func() error {
log := clog.New(slog.Default().Handler()).With("arch", arch.ToAPK())
ctx := clog.WithLogger(ctx, log)

outputs, err := bc.GenerateImageSBOM(ctx, arch, img)
if err != nil {
return fmt.Errorf("generating sbom for %s: %w", arch, err)
}
mtx.Lock()
defer mtx.Unlock()

sboms = append(sboms, outputs...)
return nil
})
}

if err := g.Wait(); err != nil {
return nil, nil, err
}

files, err := build.GenerateIndexSBOM(ctx, *o, *ic, finalDigest, imgs)
if err != nil {
return nil, nil, fmt.Errorf("generating index SBOM: %w", err)
Expand Down
8 changes: 4 additions & 4 deletions internal/cli/publish_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ func TestPublish(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:df77d3071fed05b55a2c76ce0af54b4e8174404ee29962162b627aaa42b43b91"
want := "sha256:df086c6b126032e9ed1b4aa6fecdb6988b45d86d9c1e8d2eb81dea647f4c7a7f"
require.Equal(t, want, digest.String())

sdst := fmt.Sprintf("%s:%s.sbom", dst, strings.ReplaceAll(want, ":", "-"))
Expand All @@ -109,7 +109,7 @@ func TestPublish(t *testing.T) {

// This test will fail if we ever make a change in apko that changes the SBOM.
// Sometimes, this is intentional, and we need to change this and bump the version.
swant := "sha256:18b8dc7cd228ab657a248b94c256ec4b3e12a69901161d027ee4b6bbee0e87b6"
swant := "sha256:d1faff2316aa480d1400e6c86af431402cee84f980b97a06f096bdab9a52075f"
require.Equal(t, swant, got)

im, err := idx.IndexManifest()
Expand All @@ -118,8 +118,8 @@ func TestPublish(t *testing.T) {
// We also want to check the children SBOMs because the index SBOM does not have
// references to the children SBOMs, just the children!
wantBoms := []string{
"sha256:b30707314d196b3f65b1e9b05f34b795588f0031343bf3e3e75f256aff3fc7e6",
"sha256:1449715ad955e02f8a8f8f5b9adff17d89c2443e199af2555f8336df18720fe7",
"sha256:c483478580314a253c2170b32de7686d1664ec936be3a4df51ef2bba92c46261",
"sha256:18d9c631ac5656d52d2595bc80195ad1c68c517db8bded1ec229f775ee682d98",
}

for i, m := range im.Manifests {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"schemaVersion":2,"mediaType":"application/vnd.oci.image.manifest.v1+json","config":{"mediaType":"application/vnd.oci.image.config.v1+json","size":593,"digest":"sha256:5e0be8f8dbc1497d60148df3be08869342df17c951370416999e19cda0d36624"},"layers":[{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","size":3272,"digest":"sha256:89c9e3bd4d4968247bdf82182560718f22427628a3c112902377fa7ff897f9f7"}],"annotations":{"org.opencontainers.image.created":"1970-01-01T00:00:00Z"}}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"schemaVersion":2,"mediaType":"application/vnd.oci.image.manifest.v1+json","config":{"mediaType":"application/vnd.oci.image.config.v1+json","size":593,"digest":"sha256:cff7a34bf75690ef289b741fd026cb52cac94ff0f057996c829ac546f6819c75"},"layers":[{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","size":3273,"digest":"sha256:fab53f6bbeb155d8f33acb6e7a1d961317ffb6352fc775b133b1af8656a6d0bb"}],"annotations":{"org.opencontainers.image.created":"1970-01-01T00:00:00Z"}}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"architecture":"amd64","author":"github.com/chainguard-dev/apko","created":"1970-01-01T00:00:00Z","history":[{"author":"apko","created":"1970-01-01T00:00:00Z","created_by":"apko","comment":"This is an apko single-layer image"}],"os":"linux","rootfs":{"type":"layers","diff_ids":["sha256:b606e55d50a4a23dd4092a9983b45887dd7c979a38acd5dc9736a09cc899e600"]},"config":{"Entrypoint":["/bin/sh","-l"],"Env":["PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin","SSL_CERT_FILE=/etc/ssl/certs/ca-certificates.crt"],"Labels":{"org.opencontainers.image.created":"1970-01-01T00:00:00Z"}}}
{"architecture":"amd64","author":"github.com/chainguard-dev/apko","created":"1970-01-01T00:00:00Z","history":[{"author":"apko","created":"1970-01-01T00:00:00Z","created_by":"apko","comment":"This is an apko single-layer image"}],"os":"linux","rootfs":{"type":"layers","diff_ids":["sha256:8f9c734d8ec1cd189067042886090e052d1e32c6622124061dd7baf8be1c1e56"]},"config":{"Entrypoint":["/bin/sh","-l"],"Env":["PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin","SSL_CERT_FILE=/etc/ssl/certs/ca-certificates.crt"],"Labels":{"org.opencontainers.image.created":"1970-01-01T00:00:00Z"}}}
Binary file not shown.
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"architecture":"arm64","author":"github.com/chainguard-dev/apko","created":"1970-01-01T00:00:00Z","history":[{"author":"apko","created":"1970-01-01T00:00:00Z","created_by":"apko","comment":"This is an apko single-layer image"}],"os":"linux","rootfs":{"type":"layers","diff_ids":["sha256:568821083896751c424c849bd0222c7026e123b72906839f4123d4be014bfead"]},"config":{"Entrypoint":["/bin/sh","-l"],"Env":["PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin","SSL_CERT_FILE=/etc/ssl/certs/ca-certificates.crt"],"Labels":{"org.opencontainers.image.created":"1970-01-01T00:00:00Z"}}}
{"architecture":"arm64","author":"github.com/chainguard-dev/apko","created":"1970-01-01T00:00:00Z","history":[{"author":"apko","created":"1970-01-01T00:00:00Z","created_by":"apko","comment":"This is an apko single-layer image"}],"os":"linux","rootfs":{"type":"layers","diff_ids":["sha256:ae5eac0428855226d637f784d90664e537cb40a42871dc7e58daabf93cfe86ca"]},"config":{"Entrypoint":["/bin/sh","-l"],"Env":["PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin","SSL_CERT_FILE=/etc/ssl/certs/ca-certificates.crt"],"Labels":{"org.opencontainers.image.created":"1970-01-01T00:00:00Z"}}}

This file was deleted.

Binary file not shown.
2 changes: 1 addition & 1 deletion internal/cli/testdata/golden/index.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"schemaVersion":2,"mediaType":"application/vnd.oci.image.index.v1+json","manifests":[{"mediaType":"application/vnd.oci.image.manifest.v1+json","size":476,"digest":"sha256:43e3f561cb0910cb25ea304331454f74315d2edbcf68e2af172f8efa5c95fe19","platform":{"architecture":"amd64","os":"linux"}},{"mediaType":"application/vnd.oci.image.manifest.v1+json","size":476,"digest":"sha256:dcc96a7dc51e9f68b3402c82332b61325ae8e6f8ddc49159e7bafc30453bfc17","platform":{"architecture":"arm64","os":"linux"}}],"annotations":{"org.opencontainers.image.created":"1970-01-01T00:00:00Z"}}
{"schemaVersion":2,"mediaType":"application/vnd.oci.image.index.v1+json","manifests":[{"mediaType":"application/vnd.oci.image.manifest.v1+json","size":476,"digest":"sha256:0c3a3431cb3d08f1de9b3ebd19671fe54c227a6cfd33c1164cb8f67a86baadea","platform":{"architecture":"amd64","os":"linux"}},{"mediaType":"application/vnd.oci.image.manifest.v1+json","size":476,"digest":"sha256:2daa2a0b7c784bbda06b9a342d2b70e72d4f213642f488250fdb62ccd65a4ba7","platform":{"architecture":"arm64","os":"linux"}}],"annotations":{"org.opencontainers.image.created":"1970-01-01T00:00:00Z"}}
24 changes: 12 additions & 12 deletions internal/cli/testdata/golden/sboms/sbom-aarch64.spdx.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"SPDXID": "SPDXRef-DOCUMENT",
"name": "sbom-sha256:82c91678ac0f40848c5cdac918022ba897a381c264722a6b1d5c986471e9751e",
"name": "sbom-sha256:fab53f6bbeb155d8f33acb6e7a1d961317ffb6352fc775b133b1af8656a6d0bb",
"spdxVersion": "SPDX-2.3",
"creationInfo": {
"created": "1970-01-01T00:00:00Z",
Expand All @@ -13,13 +13,13 @@
"dataLicense": "CC0-1.0",
"documentNamespace": "https://spdx.org/spdxdocs/apko/",
"documentDescribes": [
"SPDXRef-Package-sha256-dcc96a7dc51e9f68b3402c82332b61325ae8e6f8ddc49159e7bafc30453bfc17"
"SPDXRef-Package-sha256-2daa2a0b7c784bbda06b9a342d2b70e72d4f213642f488250fdb62ccd65a4ba7"
],
"packages": [
{
"SPDXID": "SPDXRef-Package-sha256-dcc96a7dc51e9f68b3402c82332b61325ae8e6f8ddc49159e7bafc30453bfc17",
"name": "sha256:dcc96a7dc51e9f68b3402c82332b61325ae8e6f8ddc49159e7bafc30453bfc17",
"versionInfo": "sha256:dcc96a7dc51e9f68b3402c82332b61325ae8e6f8ddc49159e7bafc30453bfc17",
"SPDXID": "SPDXRef-Package-sha256-2daa2a0b7c784bbda06b9a342d2b70e72d4f213642f488250fdb62ccd65a4ba7",
"name": "sha256:2daa2a0b7c784bbda06b9a342d2b70e72d4f213642f488250fdb62ccd65a4ba7",
"versionInfo": "sha256:2daa2a0b7c784bbda06b9a342d2b70e72d4f213642f488250fdb62ccd65a4ba7",
"filesAnalyzed": false,
"description": "apko container image",
"downloadLocation": "NOASSERTION",
Expand All @@ -28,20 +28,20 @@
"checksums": [
{
"algorithm": "SHA256",
"checksumValue": "dcc96a7dc51e9f68b3402c82332b61325ae8e6f8ddc49159e7bafc30453bfc17"
"checksumValue": "2daa2a0b7c784bbda06b9a342d2b70e72d4f213642f488250fdb62ccd65a4ba7"
}
],
"externalRefs": [
{
"referenceCategory": "PACKAGE-MANAGER",
"referenceLocator": "pkg:oci/golden@sha256%3Adcc96a7dc51e9f68b3402c82332b61325ae8e6f8ddc49159e7bafc30453bfc17?arch=arm64\u0026mediaType=application%2Fvnd.oci.image.manifest.v1%2Bjson\u0026os=linux",
"referenceLocator": "pkg:oci/golden@sha256%3A2daa2a0b7c784bbda06b9a342d2b70e72d4f213642f488250fdb62ccd65a4ba7?arch=arm64\u0026mediaType=application%2Fvnd.oci.image.manifest.v1%2Bjson\u0026os=linux",
"referenceType": "purl"
}
]
},
{
"SPDXID": "SPDXRef-Package-sha256-82c91678ac0f40848c5cdac918022ba897a381c264722a6b1d5c986471e9751e",
"name": "sha256:82c91678ac0f40848c5cdac918022ba897a381c264722a6b1d5c986471e9751e",
"SPDXID": "SPDXRef-Package-sha256-fab53f6bbeb155d8f33acb6e7a1d961317ffb6352fc775b133b1af8656a6d0bb",
"name": "sha256:fab53f6bbeb155d8f33acb6e7a1d961317ffb6352fc775b133b1af8656a6d0bb",
"versionInfo": "1.0.0",
"filesAnalyzed": false,
"description": "apko operating system layer",
Expand All @@ -50,7 +50,7 @@
"externalRefs": [
{
"referenceCategory": "PACKAGE-MANAGER",
"referenceLocator": "pkg:oci/golden@sha256%3A82c91678ac0f40848c5cdac918022ba897a381c264722a6b1d5c986471e9751e?arch=arm64\u0026mediaType=application%2Fvnd.oci.image.layer.v1.tar%2Bgzip\u0026os=linux",
"referenceLocator": "pkg:oci/golden@sha256%3Afab53f6bbeb155d8f33acb6e7a1d961317ffb6352fc775b133b1af8656a6d0bb?arch=arm64\u0026mediaType=application%2Fvnd.oci.image.layer.v1.tar%2Bgzip\u0026os=linux",
"referenceType": "purl"
}
]
Expand Down Expand Up @@ -96,9 +96,9 @@
],
"relationships": [
{
"spdxElementId": "SPDXRef-Package-sha256-dcc96a7dc51e9f68b3402c82332b61325ae8e6f8ddc49159e7bafc30453bfc17",
"spdxElementId": "SPDXRef-Package-sha256-2daa2a0b7c784bbda06b9a342d2b70e72d4f213642f488250fdb62ccd65a4ba7",
"relationshipType": "CONTAINS",
"relatedSpdxElement": "SPDXRef-Package-sha256-82c91678ac0f40848c5cdac918022ba897a381c264722a6b1d5c986471e9751e"
"relatedSpdxElement": "SPDXRef-Package-sha256-fab53f6bbeb155d8f33acb6e7a1d961317ffb6352fc775b133b1af8656a6d0bb"
}
]
}
Loading

0 comments on commit 559534f

Please sign in to comment.