diff --git a/examples/one-arch.yaml b/examples/one-arch.yaml index 653de707a..5de833f76 100644 --- a/examples/one-arch.yaml +++ b/examples/one-arch.yaml @@ -30,10 +30,10 @@ test: packages: - busybox pipeline: - - if: ${{targets.architecture == "x86_64"}} + - if: ${{build.arch}} == "x86_64" runs: | echo hello test - - if: ${{targets.architecture == "arm64"}} + - if: ${{build.arch}} == "aarch64" runs: | echo "BAD ARCHITECTURE" exit 1 diff --git a/pkg/build/build.go b/pkg/build/build.go index aefce5641..def828327 100644 --- a/pkg/build/build.go +++ b/pkg/build/build.go @@ -274,6 +274,9 @@ func (b *Build) Close(ctx context.Context) error { // buildGuest invokes apko to build the guest environment, returning a reference to the image // loaded by the OCI Image loader. +// +// NB: This has side effects! This mutates Build by overwriting Configuration.Environment with +// a locked version (packages resolved to versions) so we can record which packages were used. func (b *Build) buildGuest(ctx context.Context, imgConfig apko_types.ImageConfiguration, guestFS apkofs.FullFS) (string, error) { log := clog.FromContext(ctx) ctx, span := otel.Tracer("melange").Start(ctx, "buildGuest") @@ -291,15 +294,34 @@ func (b *Build) buildGuest(ctx context.Context, imgConfig apko_types.ImageConfig }...) } - bc, err := apko_build.New(ctx, guestFS, - apko_build.WithImageConfiguration(imgConfig), + // Work around LockImageConfiguration assuming multi-arch. + imgConfig.Archs = []apko_types.Architecture{b.Arch} + + opts := []apko_build.Option{apko_build.WithImageConfiguration(imgConfig), apko_build.WithArch(b.Arch), apko_build.WithExtraKeys(b.ExtraKeys), apko_build.WithExtraBuildRepos(b.ExtraRepos), apko_build.WithExtraPackages(b.ExtraPackages), apko_build.WithCache(b.ApkCacheDir, false, apk.NewCache(true)), apko_build.WithTempDir(tmp), - apko_build.WithIgnoreSignatures(b.IgnoreSignatures)) + apko_build.WithIgnoreSignatures(b.IgnoreSignatures), + } + + locked, warn, err := apko_build.LockImageConfiguration(ctx, imgConfig, opts...) + if err != nil { + return "", fmt.Errorf("unable to lock image configuration: %w", err) + } + + for k, v := range warn { + log.Warnf("Unable to lock package %s: %s", k, v) + } + + // Overwrite the environment with the locked one. + b.Configuration.Environment = *locked + + opts = append(opts, apko_build.WithImageConfiguration(*locked)) + + bc, err := apko_build.New(ctx, guestFS, opts...) if err != nil { return "", fmt.Errorf("unable to create build context: %w", err) } diff --git a/pkg/build/package.go b/pkg/build/package.go index 2bb45ee61..1ed1ccd9a 100644 --- a/pkg/build/package.go +++ b/pkg/build/package.go @@ -210,6 +210,14 @@ func (pc *PackageBuild) generateControlSection(ctx context.Context) ([]byte, err return nil, fmt.Errorf("unable to build control FS: %w", err) } + locked, err := json.Marshal(pc.Build.Configuration) + if err != nil { + return nil, fmt.Errorf("marshalling config: %w", err) + } + if err := fsys.WriteFile(".melange.json", locked, 0644); err != nil { + return nil, fmt.Errorf("unable to build control FS: %w", err) + } + if scriptlets := pc.Scriptlets; scriptlets != nil { if scriptlets.Trigger.Script != "" { // #nosec G306 -- scriptlets must be executable