Skip to content

Commit

Permalink
Style and error handling fixes
Browse files Browse the repository at this point in the history
* Better error messages
* Handling missing mappings file
* Don't export entire file schema

Signed-off-by: Emily Casey <[email protected]>
  • Loading branch information
ekcasey committed Jul 16, 2020
1 parent 884bb81 commit 0f8eb47
Show file tree
Hide file tree
Showing 5 changed files with 73 additions and 62 deletions.
26 changes: 12 additions & 14 deletions dependency_cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,30 +49,28 @@ type DependencyCache struct {
// UserAgent is the User-Agent string to use with requests.
UserAgent string

// DependencyMap optionally provides override URIs for BuildpackDependencies
// Mappings optionally provides URIs mapping for BuildpackDependencies
Mappings []DependencyMapping
}

// NewDependencyCache creates a new instance setting the default cache path (<BUILDPACK_PATH>/dependencies) and user
// agent (<BUILDPACK_ID>/<BUILDPACK_VERSION>).
// Mappings will be read from <PLATFORM_DIR>/dependencies/mappings.toml
func NewDependencyCache(context libcnb.BuildContext) (DependencyCache, error) {
mappingsFile, err := ReadMappingsFile(DefaultMappingsFilePath(context.Platform.Path))
if err != nil {
return DependencyCache{}, err
}
var mappings []DependencyMapping
for _, bpm := range mappingsFile.BuildpackMappings {
if bpm.BuildpackID == context.Buildpack.Info.ID {
mappings = bpm.Mappings
}
}
return DependencyCache{
cache := DependencyCache{
CachePath: filepath.Join(context.Buildpack.Path, "dependencies"),
DownloadPath: os.TempDir(),
UserAgent: fmt.Sprintf("%s/%s", context.Buildpack.Info.ID, context.Buildpack.Info.Version),
Mappings: mappings,
}, nil
}
mappings, err := ReadMappingsForBuildpack(
DefaultMappingsFilePath(context.Platform.Path),
context.Buildpack.Info.ID,
)
if err != nil {
return DependencyCache{}, fmt.Errorf("unable to read dependency mappings file\n%w", err)
}
cache.Mappings = mappings
return cache, nil
}

// RequestModifierFunc is a callback that enables modification of a download request before it is sent. It is often
Expand Down
64 changes: 35 additions & 29 deletions dependency_cache_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,56 +37,62 @@ import (
func testDependencyCache(t *testing.T, context spec.G, it spec.S) {
var (
Expect = NewWithT(t).Expect

dependencyCache libpak.DependencyCache
)

context("NewDependencyCache", func() {
var ctx libcnb.BuildContext

it.Before(func() {
var err error
dependencyCache, err = libpak.NewDependencyCache(libcnb.BuildContext{
ctx = libcnb.BuildContext{
Buildpack: libcnb.Buildpack{
Info: libcnb.BuildpackInfo{
ID: "some-buildpack-id",
Version: "some-buildpack-version",
},
Path: "some/path",
},
Platform: libcnb.Platform{
Path: filepath.Join("testdata", "platform"),
},
})
Expect(err).NotTo(HaveOccurred())
}
})

it("defaults CachePath to <BUILDPACK_PATH>/dependencies", func() {
it("set default CachePath and UserAgent", func() {
dependencyCache, err := libpak.NewDependencyCache(ctx)
Expect(err).NotTo(HaveOccurred())
Expect(dependencyCache.CachePath).To(Equal(filepath.Join("some/path/dependencies")))
})
it("sets the user agent to <BUILDPACK_ID>/<BUILDPACK_VERSION>", func() {
Expect(dependencyCache.UserAgent).To(Equal("some-buildpack-id/some-buildpack-version"))
Expect(dependencyCache.Mappings).To(BeEmpty())
})
it("reads mappings for buildpack from the platform dir", func() {
Expect(dependencyCache.Mappings).To(ConsistOf(
libpak.DependencyMapping{
ID: "some-dependency-id",
Version: "some-dependency-version",
URI: "some-uri",
},
libpak.DependencyMapping{
ID: "other-dependency-id",
Version: "other-dependency-version",
URI: "other-uri",
},
))

context("mappings file exists in the platform dir", func() {
it.Before(func() {
ctx.Platform.Path = filepath.Join("testdata", "platform")
})

it("reads mappings for buildpack", func() {
dependencyCache, err := libpak.NewDependencyCache(ctx)
Expect(err).NotTo(HaveOccurred())
Expect(dependencyCache.Mappings).To(ConsistOf(
libpak.DependencyMapping{
ID: "some-dependency-id",
Version: "some-dependency-version",
URI: "some-uri",
},
libpak.DependencyMapping{
ID: "other-dependency-id",
Version: "other-dependency-version",
URI: "other-uri",
},
))
})
})
})

context("artifacts", func() {
var (
cachePath string
downloadPath string
dependency libpak.BuildpackDependency
server *ghttp.Server
cachePath string
downloadPath string
dependency libpak.BuildpackDependency
dependencyCache libpak.DependencyCache
server *ghttp.Server
)

it.Before(func() {
Expand Down
39 changes: 22 additions & 17 deletions dependency_mapping.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,38 +17,43 @@
package libpak

import (
"fmt"
"os"
"path/filepath"

"github.com/BurntSushi/toml"
)

// MappingsFile defines dependency mappings for a set of buildpacks
type MappingsFile struct {
BuildpackMappings []BuildpackMappings `toml:"buildpacks"`
}

type BuildpackMappings struct {
BuildpackID string `toml:"id"`
Mappings []DependencyMapping `toml:"mappings"`
}

// DependencyMapping defines a new URI for a dependency with the given ID and Version
type DependencyMapping struct {
ID string `toml:"id"`
Version string `toml:"version"`
URI string `toml:"uri"`
}

// ReadMappingsFile read MappingsFile from path
func ReadMappingsFile(path string) (MappingsFile, error) {
mappingsFile := MappingsFile{}
_, err := toml.DecodeFile(path, &mappingsFile)
if err != nil {
return MappingsFile{}, err
// ReadMappingsForBuildpack reads the mappings for the buildpack with ID buildpackID from the file at path
func ReadMappingsForBuildpack(path string, buildpackID string) ([]DependencyMapping, error) {
mappingsFile := struct {
Buildpacks []struct {
ID string `toml:"id"`
Mappings []DependencyMapping `toml:"mappings"`
} `toml:"buildpacks"`
}{}
if _, err := toml.DecodeFile(path, &mappingsFile); err != nil {
if os.IsNotExist(err) {
return nil, nil
}
return nil, fmt.Errorf("unable to decode dependency mappings file%s\n%w", path, err)
}
for _, bps := range mappingsFile.Buildpacks {
if bps.ID == buildpackID {
return bps.Mappings, nil
}
}
return mappingsFile, nil
return nil, nil
}

// DefaultMappingsFilePath returns default path for mappings file
func DefaultMappingsFilePath(platformDir string) string {
return filepath.Join(platformDir, "dependencies", "mappings.toml")
}
3 changes: 1 addition & 2 deletions effect/mocks/executor.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions testdata/platform/dependencies/mappings.toml
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
[[buildpacks]]
id = "some-buildpack-id"

[[buildpacks.mappings]]
id = "some-dependency-id"
version = "some-dependency-version"
uri = "some-uri"

[[buildpacks.mappings]]
id = "other-dependency-id"
version = "other-dependency-version"
uri = "other-uri"

[[buildpacks]]
id = "exclude-buildpack-id"

[[buildpacks.mappings]]
id = "exclude-dependency-id"
version = "exclude-dependency-version"
Expand Down

0 comments on commit 0f8eb47

Please sign in to comment.