Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion docs/BUILD-FILE.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ The following are the high level sections for the build file, with detailed desc
### subpackages

List of subpackages that this package also produces. For example, docs.
Subpackages may define their own `target-architecture` entries to limit
which architectures produce that subpackage.

### data

Expand Down Expand Up @@ -499,4 +501,3 @@ TODO(vaikas): melange config points to apko here:

# pipeline
Pipeline defines the ordered steps to build the package.

47 changes: 34 additions & 13 deletions pkg/build/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,39 @@ func (b *Build) Close(ctx context.Context) error {
return errors.Join(errs...)
}

func filterSubpackages(ctx context.Context, subpackages []config.Subpackage, arch apko_types.Architecture) []config.Subpackage {
log := clog.FromContext(ctx)

return slices.DeleteFunc(subpackages, func(sp config.Subpackage) bool {
result, err := shouldRun(sp.If)
if err != nil {
// This shouldn't give an error because we evaluate it in Compile.
panic(err)
}
if !result {
log.Infof("skipping subpackage %s because %s == false", sp.Name, sp.If)
return true
}

if !subpackageTargetsArch(sp, arch) {
log.Infof("skipping subpackage %s because target-architecture does not include %s", sp.Name, arch.ToAPK())
return true
}

return false
})
}

func subpackageTargetsArch(sp config.Subpackage, arch apko_types.Architecture) bool {
if len(sp.TargetArchitecture) == 0 {
return true
}
if len(sp.TargetArchitecture) == 1 && sp.TargetArchitecture[0] == "all" {
return true
}
return slices.Contains(sp.TargetArchitecture, arch.ToAPK())
}

// buildGuest invokes apko to build the guest environment, returning a reference to the image
// loaded by the OCI Image loader.
//
Expand Down Expand Up @@ -594,19 +627,7 @@ func (b *Build) BuildPackage(ctx context.Context) error {
return fmt.Errorf("compiling %s: %w", b.ConfigFile, err)
}

// Filter out any subpackages with false If conditions.
b.Configuration.Subpackages = slices.DeleteFunc(b.Configuration.Subpackages, func(sp config.Subpackage) bool {
result, err := shouldRun(sp.If)
if err != nil {
// This shouldn't give an error because we evaluate it in Compile.
panic(err)
}
if !result {
log.Infof("skipping subpackage %s because %s == false", sp.Name, sp.If)
}

return !result
})
b.Configuration.Subpackages = filterSubpackages(ctx, b.Configuration.Subpackages, b.Arch)

// Initialize SBOMGroup for the main package and all subpackages
pkgNames := []string{b.Configuration.Package.Name}
Expand Down
22 changes: 22 additions & 0 deletions pkg/build/compile_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,28 @@ func TestCompileTest(t *testing.T) {
}
}

func TestFilterSubpackagesTargetArchitecture(t *testing.T) {
subpackages := []config.Subpackage{
{Name: "default"},
{Name: "all", TargetArchitecture: []string{"all"}},
{Name: "native", TargetArchitecture: []string{"x86_64"}},
{Name: "other", TargetArchitecture: []string{"aarch64"}},
}

got := filterSubpackages(context.Background(), subpackages, apko_types.ParseArchitecture("x86_64"))
if got, want := packageNames(got), []string{"default", "all", "native"}; !slices.Equal(got, want) {
t.Errorf("subpackage names: want %v, got %v", want, got)
}
}

func packageNames(subpackages []config.Subpackage) []string {
names := make([]string, 0, len(subpackages))
for _, sp := range subpackages {
names = append(names, sp.Name)
}
return names
}

func Test_stripComments(t *testing.T) {
tests := []struct {
in, want string
Expand Down
15 changes: 1 addition & 14 deletions pkg/build/test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import (
"os"
"path/filepath"
"runtime"
"slices"
"time"

"chainguard.dev/apko/pkg/apk/apk"
Expand Down Expand Up @@ -251,19 +250,7 @@ func (t *Test) TestPackage(ctx context.Context) error {
return fmt.Errorf("compiling %s tests: %w", t.ConfigFile, err)
}

// Filter out any subpackages with false If conditions.
t.Configuration.Subpackages = slices.DeleteFunc(t.Configuration.Subpackages, func(sp config.Subpackage) bool {
result, err := shouldRun(sp.If)
if err != nil {
// This shouldn't give an error because we evaluate it in Compile.
panic(err)
}
if !result {
log.Infof("skipping subpackage %s because %s == false", sp.Name, sp.If)
}

return !result
})
t.Configuration.Subpackages = filterSubpackages(ctx, t.Configuration.Subpackages, t.Arch)

// Unless a specific architecture is requests, we run the test for all.
inarchs := len(pkg.TargetArchitecture) == 0
Expand Down
25 changes: 14 additions & 11 deletions pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -861,6 +861,8 @@ type Subpackage struct {
URL string `json:"url,omitempty" yaml:"url,omitempty"`
// Optional: The git commit of the subpackage build configuration
Commit string `json:"commit,omitempty" yaml:"commit,omitempty"`
// List of target architectures for which this subpackage should be built
TargetArchitecture []string `json:"target-architecture,omitempty" yaml:"target-architecture,omitempty"`
// Optional: enabling, disabling, and configuration of build checks
Checks Checks `json:"checks" yaml:"checks,omitempty"`
// Test section for the subpackage.
Expand Down Expand Up @@ -1551,17 +1553,18 @@ func replacePackage(r *strings.Replacer, commit string, in Package) Package {

func replaceSubpackage(r *strings.Replacer, detectedCommit string, in Subpackage) Subpackage {
return Subpackage{
If: r.Replace(in.If),
Name: r.Replace(in.Name),
Pipeline: replacePipelines(r, in.Pipeline),
Dependencies: replaceDependencies(r, in.Dependencies),
Options: in.Options,
Scriptlets: replaceScriptlets(r, in.Scriptlets),
Description: r.Replace(in.Description),
URL: r.Replace(in.URL),
Commit: replaceCommit(detectedCommit, in.Commit),
Checks: in.Checks,
Test: replaceTest(r, in.Test),
If: r.Replace(in.If),
Name: r.Replace(in.Name),
Pipeline: replacePipelines(r, in.Pipeline),
Dependencies: replaceDependencies(r, in.Dependencies),
Options: in.Options,
Scriptlets: replaceScriptlets(r, in.Scriptlets),
Description: r.Replace(in.Description),
URL: r.Replace(in.URL),
Commit: replaceCommit(detectedCommit, in.Commit),
TargetArchitecture: replaceAll(r, in.TargetArchitecture),
Checks: in.Checks,
Test: replaceTest(r, in.Test),
}
}

Expand Down
4 changes: 4 additions & 0 deletions pkg/config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ environment:
vars:
foo: FOO
bar: BAR
arch: x86_64

var-transforms:
- from: ${{package.version}}
Expand All @@ -107,6 +108,8 @@ var-transforms:

subpackages:
- name: subpackage-${{vars.short-package-version}}
target-architecture:
- ${{vars.arch}}
dependencies:
runtime:
- ${{package.name}}-config-${{package.version}}
Expand Down Expand Up @@ -181,6 +184,7 @@ test:
}, cfg.Test.Environment.Contents.Packages)

require.Equal(t, cfg.Subpackages[0].Name, "subpackage-0.0")
require.Equal(t, []string{"x86_64"}, cfg.Subpackages[0].TargetArchitecture)

require.Equal(t, "/usr/local/FOO", cfg.Test.Environment.Environment["LD_LIBRARY_PATH"])
}
Expand Down
4 changes: 4 additions & 0 deletions pkg/config/schema.cue
Original file line number Diff line number Diff line change
Expand Up @@ -567,6 +567,10 @@
// Optional: The git commit of the subpackage build configuration
commit?: string

// List of target architectures for which this subpackage should be
// built
"target-architecture"?: [...string]

// Optional: enabling, disabling, and configuration of build
// checks
checks!: #Checks
Expand Down
7 changes: 7 additions & 0 deletions pkg/config/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -1033,6 +1033,13 @@
"type": "string",
"description": "Optional: The git commit of the subpackage build configuration"
},
"target-architecture": {
"items": {
"type": "string"
},
"type": "array",
"description": "List of target architectures for which this subpackage should be built"
},
"checks": {
"$ref": "#/$defs/Checks",
"description": "Optional: enabling, disabling, and configuration of build checks"
Expand Down