Skip to content

Commit db0fe58

Browse files
committed
Enable architecture specific dependencies
1 parent 9d649db commit db0fe58

File tree

5 files changed

+123
-3
lines changed

5 files changed

+123
-3
lines changed

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ require (
1414
github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5
1515
github.com/gabriel-vasile/mimetype v1.4.7
1616
github.com/google/uuid v1.6.0
17+
github.com/onsi/ginkgo v1.16.5 // indirect
1718
github.com/onsi/gomega v1.34.1
1819
github.com/pelletier/go-toml v1.9.5
1920
github.com/sclevine/spec v1.4.0

go.sum

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1108,6 +1108,7 @@ github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMo
11081108
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
11091109
github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU=
11101110
github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU=
1111+
github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
11111112
github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
11121113
github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa/go.mod h1:KnogPXtdwXqoenmZCw6S+25EAm2MkxbG0deNDu4cbSA=
11131114
github.com/fxamacker/cbor/v2 v2.4.0/go.mod h1:TA1xS00nchWmaBnEIxPSE5oHLuJBAVvqrtAnWBwBCVo=
@@ -1657,6 +1658,7 @@ github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLA
16571658
github.com/nwaples/rardecode v1.1.0 h1:vSxaY8vQhOcVr4mm5e8XllHWTiM4JF507A0Katqw7MQ=
16581659
github.com/nwaples/rardecode v1.1.0/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0=
16591660
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
1661+
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
16601662
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
16611663
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
16621664
github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
@@ -3100,6 +3102,7 @@ gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
31003102
gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
31013103
gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
31023104
gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
3105+
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
31033106
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
31043107
gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
31053108
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=

postal/buildpack.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,9 @@ type Dependency struct {
7474
// StripComponents behaves like the --strip-components flag on tar command
7575
// removing the first n levels from the final decompression destination.
7676
StripComponents int `toml:"strip-components"`
77+
78+
// ARCH is the architecture of this dependency
79+
Arch string `toml:"arch"`
7780
}
7881

7982
func parseBuildpack(path, name string) ([]Dependency, string, error) {

postal/service.go

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,10 @@ import (
44
"errors"
55
"fmt"
66
"io"
7+
"os"
78
"path/filepath"
89
"regexp"
10+
"runtime"
911
"sort"
1012
"strings"
1113
"time"
@@ -52,15 +54,17 @@ type ErrNoDeps struct {
5254
id string
5355
version string
5456
stack string
57+
arch string
5558
supportedVersions []string
5659
}
5760

5861
// Error implements the error.Error interface
5962
func (e *ErrNoDeps) Error() string {
60-
return fmt.Sprintf("failed to satisfy %q dependency version constraint %q: no compatible versions on %q stack. Supported versions are: [%s]",
63+
return fmt.Sprintf("failed to satisfy %q dependency version constraint %q: no compatible versions on %q stack with architecture %q. Supported versions are: [%s]",
6164
e.id,
6265
e.version,
6366
e.stack,
67+
e.arch,
6468
strings.Join(e.supportedVersions, ", "),
6569
)
6670
}
@@ -147,6 +151,10 @@ func (s Service) Resolve(path, id, version, stack string) (Dependency, error) {
147151
continue
148152
}
149153

154+
if !isCorrectArch(dependency) {
155+
continue
156+
}
157+
150158
sVersion, err := semver.NewVersion(dependency.Version)
151159
if err != nil {
152160
return Dependency{}, err
@@ -160,7 +168,7 @@ func (s Service) Resolve(path, id, version, stack string) (Dependency, error) {
160168
}
161169

162170
if len(compatibleVersions) == 0 {
163-
return Dependency{}, &ErrNoDeps{id, version, stack, supportedVersions}
171+
return Dependency{}, &ErrNoDeps{id, version, stack, archFromSystem(), supportedVersions}
164172
}
165173

166174
stacksForVersion := map[string][]string{}
@@ -220,6 +228,25 @@ func (s Service) Resolve(path, id, version, stack string) (Dependency, error) {
220228
return compatibleVersions[0], nil
221229
}
222230

231+
func isCorrectArch(dep Dependency) bool {
232+
systemArch := archFromSystem()
233+
234+
if systemArch == "amd64" && dep.Arch == "" {
235+
return true
236+
}
237+
238+
return systemArch == dep.Arch
239+
}
240+
241+
func archFromSystem() string {
242+
archFromEnv, ok := os.LookupEnv("BP_ARCH")
243+
if !ok {
244+
archFromEnv = runtime.GOARCH
245+
}
246+
247+
return archFromEnv
248+
}
249+
223250
func stringSliceContains(slice []string, str string) bool {
224251
for _, s := range slice {
225252
if s == str {

postal/service_test.go

Lines changed: 87 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
//nolint Ignore SA1019, usage of deprecated package within a deprecated test case
2424
"github.com/paketo-buildpacks/packit/v2/paketosbom"
2525

26+
. "github.com/onsi/ginkgo"
2627
. "github.com/onsi/gomega"
2728
)
2829

@@ -115,6 +116,12 @@ strip-components = 1
115116
service = postal.NewService(transport).
116117
WithDependencyMappingResolver(mappingResolver).
117118
WithDependencyMirrorResolver(mirrorResolver)
119+
120+
Expect(os.Setenv("BP_ARCH", "amd64")).To(Succeed())
121+
})
122+
123+
AfterEach(func() {
124+
Expect(os.Unsetenv("BP_ARCH")).To(Succeed())
118125
})
119126

120127
context("Resolve", func() {
@@ -310,6 +317,85 @@ version = "4.5.6"
310317
})
311318
})
312319

320+
context("when there architecture specific versions", func() {
321+
it.Before(func() {
322+
err := os.WriteFile(path, []byte(`
323+
[metadata]
324+
[metadata.default-versions]
325+
some-entry = "1.2.x"
326+
327+
[[metadata.dependencies]]
328+
id = "some-entry"
329+
sha256 = "some-sha-amd64"
330+
stacks = ["*"]
331+
uri = "some-uri"
332+
version = "1.2.3"
333+
arch = "amd64"
334+
335+
[[metadata.dependencies]]
336+
id = "some-entry"
337+
sha256 = "some-sha-arm"
338+
stacks = ["*"]
339+
uri = "some-uri"
340+
version = "1.2.3"
341+
arch = "arm"
342+
343+
[[metadata.dependencies]]
344+
id = "some-other-entry"
345+
sha256 = "some-other-sha"
346+
stacks = ["*"]
347+
uri = "some-uri"
348+
version = "1.2.4"
349+
350+
`), 0600)
351+
Expect(err).NotTo(HaveOccurred())
352+
})
353+
354+
context("BP_ARCH=amd64", func() {
355+
it.Before(func() {
356+
Expect(os.Setenv("BP_ARCH", "amd64")).To(Succeed())
357+
})
358+
359+
it.After(func() {
360+
Expect(os.Unsetenv("BP_ARCH")).To(Succeed())
361+
})
362+
363+
it("picks the dependency with the correct arch", func() {
364+
dependency, err := service.Resolve(path, "some-entry", "1.2.3", "some-stack")
365+
Expect(err).NotTo(HaveOccurred())
366+
Expect(dependency.SHA256).To(Equal("some-sha-amd64"))
367+
})
368+
369+
it("picks the dependency with the no arch", func() {
370+
dependency, err := service.Resolve(path, "some-other-entry", "1.2.4", "some-stack")
371+
Expect(err).NotTo(HaveOccurred())
372+
Expect(dependency.SHA256).To(Equal("some-other-sha"))
373+
})
374+
})
375+
376+
context("BP_ARCH=arm", func() {
377+
it.Before(func() {
378+
Expect(os.Setenv("BP_ARCH", "arm")).To(Succeed())
379+
})
380+
381+
it.After(func() {
382+
Expect(os.Unsetenv("BP_ARCH")).To(Succeed())
383+
})
384+
385+
it("picks the dependency with the correct arch", func() {
386+
dependency, err := service.Resolve(path, "some-entry", "1.2.3", "some-stack")
387+
Expect(err).NotTo(HaveOccurred())
388+
Expect(dependency.SHA256).To(Equal("some-sha-arm"))
389+
})
390+
391+
it("fails if no dependency with the correct arch is found", func() {
392+
_, err := service.Resolve(path, "some-other-entry", "1.2.4", "some-stack")
393+
Expect(err).To(MatchError(ContainSubstring("failed to satisfy")))
394+
Expect(err).To(MatchError(ContainSubstring("\"arm\"")))
395+
})
396+
})
397+
})
398+
313399
context("when both a wildcard stack constraint and a specific stack constraint exist for the same dependency version", func() {
314400
it.Before(func() {
315401
err := os.WriteFile(path, []byte(`
@@ -429,7 +515,7 @@ version = "1.2.3"
429515
expectedErr := &postal.ErrNoDeps{}
430516
_, err := service.Resolve(path, "some-entry", "9.9.9", "some-stack")
431517
Expect(errors.As(err, &expectedErr)).To(BeTrue())
432-
Expect(err).To(MatchError(ContainSubstring("failed to satisfy \"some-entry\" dependency version constraint \"9.9.9\": no compatible versions on \"some-stack\" stack. Supported versions are: [1.2.3, 4.5.6]")))
518+
Expect(err).To(MatchError(ContainSubstring("failed to satisfy \"some-entry\" dependency version constraint \"9.9.9\": no compatible versions on \"some-stack\" stack with architecture \"amd64\". Supported versions are: [1.2.3, 4.5.6]")))
433519
})
434520
})
435521
})

0 commit comments

Comments
 (0)