diff --git a/build.go b/build.go index cc10821..bde2f76 100644 --- a/build.go +++ b/build.go @@ -19,8 +19,8 @@ package libpak import ( "github.com/buildpacks/libcnb/v2" - "github.com/paketo-buildpacks/libpak/v2/bard" "github.com/paketo-buildpacks/libpak/v2/internal" + "github.com/paketo-buildpacks/libpak/v2/log" ) // Build is called by the main function of a buildpack, for build. @@ -40,7 +40,7 @@ type buildDelegate struct { func (b buildDelegate) Build(context libcnb.BuildContext) (libcnb.BuildResult, error) { result, err := b.delegate(context) if err != nil { - err = bard.IdentifiableError{ + err = log.IdentifiableError{ Name: context.Buildpack.Info.Name, Description: context.Buildpack.Info.Version, Err: err, diff --git a/build_test.go b/build_test.go index b52cf38..a988277 100644 --- a/build_test.go +++ b/build_test.go @@ -29,7 +29,7 @@ import ( "github.com/stretchr/testify/mock" "github.com/paketo-buildpacks/libpak/v2" - "github.com/paketo-buildpacks/libpak/v2/bard" + "github.com/paketo-buildpacks/libpak/v2/log" ) func testBuild(t *testing.T, context spec.G, it spec.S) { @@ -132,7 +132,7 @@ version = "test-version"`), libcnb.WithExitHandler(exitHandler), ) - Expect(exitHandler.Calls[0].Arguments.Get(0)).To(MatchError(bard.IdentifiableError{ + Expect(exitHandler.Calls[0].Arguments.Get(0)).To(MatchError(log.IdentifiableError{ Name: "test-name", Description: "test-version", Err: fmt.Errorf("test-error"), diff --git a/buildmodule.go b/buildmodule.go index 03cc725..fc51049 100644 --- a/buildmodule.go +++ b/buildmodule.go @@ -28,7 +28,7 @@ import ( "github.com/Masterminds/semver/v3" "github.com/heroku/color" - "github.com/paketo-buildpacks/libpak/v2/bard" + "github.com/paketo-buildpacks/libpak/v2/log" "github.com/paketo-buildpacks/libpak/v2/sbom" ) @@ -284,7 +284,6 @@ func NewBuildModuleMetadata(metadata map[string]interface{}) (BuildModuleMetadat // ConfigurationResolver provides functionality for resolving a configuration value. type ConfigurationResolver struct { - // Configurations are the configurations to resolve against Configurations []BuildModuleConfiguration } @@ -319,16 +318,20 @@ func (c configurationEntry) String(nameLength int, valueLength int) string { return sb.String() } -// NewConfigurationResolver creates a new instance from buildmodule metadata. Logs configuration options to the body -// level int the form 'Set $Name to configure $Description[. Default $Default.]'. -func NewConfigurationResolver(md BuildModuleMetadata, logger *bard.Logger) (ConfigurationResolver, error) { - +// NewConfigurationResolver creates a new instance from buildmodule metadata. +func NewConfigurationResolver(md BuildModuleMetadata) (ConfigurationResolver, error) { cr := ConfigurationResolver{Configurations: md.Configurations} - if logger == nil { - return cr, nil - } + sort.Slice(md.Configurations, func(i, j int) bool { + return md.Configurations[i].Name < md.Configurations[j].Name + }) + return cr, nil +} + +// LogConfiguration will write the configuration options to the body level in +// the form 'Set $Name to configure $Description[. Default $Default.]'. +func (c *ConfigurationResolver) LogConfiguration(logger log.Logger) { var ( build []configurationEntry launch []configurationEntry @@ -338,16 +341,12 @@ func NewConfigurationResolver(md BuildModuleMetadata, logger *bard.Logger) (Conf valueLength int ) - sort.Slice(md.Configurations, func(i, j int) bool { - return md.Configurations[i].Name < md.Configurations[j].Name - }) - - for _, c := range md.Configurations { - s, _ := cr.Resolve(c.Name) + for _, config := range c.Configurations { + s, _ := c.Resolve(config.Name) e := configurationEntry{ - Name: c.Name, - Description: c.Description, + Name: config.Name, + Description: config.Description, Value: s, } @@ -359,15 +358,15 @@ func NewConfigurationResolver(md BuildModuleMetadata, logger *bard.Logger) (Conf valueLength = l } - if c.Build { + if config.Build { build = append(build, e) } - if c.Launch { + if config.Launch { launch = append(launch, e) } - if !c.Build && !c.Launch { + if !config.Build && !config.Launch { unknown = append(unknown, e) } } @@ -394,8 +393,6 @@ func NewConfigurationResolver(md BuildModuleMetadata, logger *bard.Logger) (Conf logger.Body(e.String(nameLength, valueLength)) } } - - return cr, nil } // Resolve resolves the value for a configuration option, returning the default value and false if it was not set. @@ -435,7 +432,7 @@ type DependencyResolver struct { StackID string // Logger is the logger used to write to the console. - Logger *bard.Logger + Logger log.Logger } // NewDependencyResolver creates a new instance from the build module metadata and stack id. diff --git a/buildmodule_test.go b/buildmodule_test.go index a9a9a84..2a70a9d 100644 --- a/buildmodule_test.go +++ b/buildmodule_test.go @@ -29,8 +29,8 @@ import ( "github.com/sclevine/spec" "github.com/paketo-buildpacks/libpak/v2" - "github.com/paketo-buildpacks/libpak/v2/bard" "github.com/paketo-buildpacks/libpak/v2/internal" + "github.com/paketo-buildpacks/libpak/v2/log" "github.com/paketo-buildpacks/libpak/v2/sbom" ) @@ -284,7 +284,6 @@ func testBuildpack(t *testing.T, context spec.G, it spec.S) { ) context("Resolve", func() { - it("filters by id", func() { resolver.Dependencies = []libpak.BuildModuleDependency{ { @@ -601,8 +600,8 @@ func testBuildpack(t *testing.T, context spec.G, it spec.S) { it("prints outdated dependencies", func() { buff := bytes.NewBuffer(nil) - logger := bard.NewLogger(buff) - resolver.Logger = &logger + logger := log.NewPaketoLogger(buff) + resolver.Logger = logger soonDeprecated := time.Now().UTC().Add(30 * 24 * time.Hour) notSoSoonDeprecated := time.Now().UTC().Add(60 * 24 * time.Hour) resolver.Dependencies = []libpak.BuildModuleDependency{ diff --git a/carton/build_image_dependency.go b/carton/build_image_dependency.go index 3611f92..af3b960 100644 --- a/carton/build_image_dependency.go +++ b/carton/build_image_dependency.go @@ -21,8 +21,8 @@ import ( "os" "regexp" - "github.com/paketo-buildpacks/libpak/v2/bard" "github.com/paketo-buildpacks/libpak/v2/internal" + "github.com/paketo-buildpacks/libpak/v2/log" ) const ( @@ -44,8 +44,8 @@ func (i BuildImageDependency) Update(options ...Option) { config = option(config) } - logger := bard.NewLogger(os.Stdout) - _, _ = fmt.Fprintf(logger.TitleWriter(), "\n%s\n", bard.FormatIdentity("Build Image", i.Version)) + logger := log.NewPaketoLogger(os.Stdout) + _, _ = fmt.Fprintf(logger.TitleWriter(), "\n%s\n", log.FormatIdentity("Build Image", i.Version)) c, err := os.ReadFile(i.BuilderPath) if err != nil { diff --git a/carton/buildmodule_dependency.go b/carton/buildmodule_dependency.go index bfbd24f..0722c9a 100644 --- a/carton/buildmodule_dependency.go +++ b/carton/buildmodule_dependency.go @@ -23,8 +23,8 @@ import ( "regexp" "github.com/BurntSushi/toml" - "github.com/paketo-buildpacks/libpak/v2/bard" "github.com/paketo-buildpacks/libpak/v2/internal" + "github.com/paketo-buildpacks/libpak/v2/log" ) const ( @@ -54,8 +54,8 @@ func (b BuildModuleDependency) Update(options ...Option) { config = option(config) } - logger := bard.NewLogger(os.Stdout) - _, _ = fmt.Fprintf(logger.TitleWriter(), "\n%s\n", bard.FormatIdentity(b.ID, b.VersionPattern)) + logger := log.NewPaketoLogger(os.Stdout) + _, _ = fmt.Fprintf(logger.TitleWriter(), "\n%s\n", log.FormatIdentity(b.ID, b.VersionPattern)) logger.Headerf("Version: %s", b.Version) logger.Headerf("PURL: %s", b.PURL) logger.Headerf("CPEs: %s", b.CPE) diff --git a/carton/lifecycle_dependency.go b/carton/lifecycle_dependency.go index 54b503e..d4636c2 100644 --- a/carton/lifecycle_dependency.go +++ b/carton/lifecycle_dependency.go @@ -21,8 +21,8 @@ import ( "os" "regexp" - "github.com/paketo-buildpacks/libpak/v2/bard" "github.com/paketo-buildpacks/libpak/v2/internal" + "github.com/paketo-buildpacks/libpak/v2/log" ) const ( @@ -44,8 +44,8 @@ func (l LifecycleDependency) Update(options ...Option) { config = option(config) } - logger := bard.NewLogger(os.Stdout) - _, _ = fmt.Fprintf(logger.TitleWriter(), "\n%s\n", bard.FormatIdentity("Lifecycle", l.Version)) + logger := log.NewPaketoLogger(os.Stdout) + _, _ = fmt.Fprintf(logger.TitleWriter(), "\n%s\n", log.FormatIdentity("Lifecycle", l.Version)) c, err := os.ReadFile(l.BuilderPath) if err != nil { diff --git a/carton/package.go b/carton/package.go index 2f96c25..56d7e4f 100644 --- a/carton/package.go +++ b/carton/package.go @@ -29,9 +29,9 @@ import ( "github.com/heroku/color" "github.com/paketo-buildpacks/libpak/v2" - "github.com/paketo-buildpacks/libpak/v2/bard" "github.com/paketo-buildpacks/libpak/v2/effect" "github.com/paketo-buildpacks/libpak/v2/internal" + "github.com/paketo-buildpacks/libpak/v2/log" ) // Package is an object that contains the configuration for building a package. @@ -76,7 +76,7 @@ func (p Package) Create(options ...Option) { file string ) - logger := bard.NewLogger(os.Stdout) + logger := log.NewPaketoLogger(os.Stdout) // Is this a buildpack or an extension? bpfile := filepath.Join(p.Source, "buildpack.toml") @@ -103,7 +103,7 @@ func (p Package) Create(options ...Option) { name = b.Info.Name version = b.Info.Version homepage = b.Info.Homepage - logger.Debug("Buildpack: %+v", b) + logger.Debugf("Buildpack: %+v", b) } else if _, err := os.Stat(extnfile); err == nil { s, err := os.ReadFile(extnfile) if err != nil { @@ -121,7 +121,7 @@ func (p Package) Create(options ...Option) { version = e.Info.Version homepage = e.Info.Homepage extension = true - logger.Debug("Extension: %+v", e) + logger.Debugf("Extension: %+v", e) } else { config.exitHandler.Error(fmt.Errorf("unable to read buildpack/extension.toml at %s", p.Source)) return @@ -138,7 +138,7 @@ func (p Package) Create(options ...Option) { for _, i := range metadata.IncludeFiles { entries[i] = filepath.Join(p.Source, i) } - logger.Debug("Include files: %+v", entries) + logger.Debugf("Include files: %+v", entries) if p.Version != "" { version = p.Version diff --git a/carton/package_dependency.go b/carton/package_dependency.go index f1ac3e3..174de0c 100644 --- a/carton/package_dependency.go +++ b/carton/package_dependency.go @@ -23,8 +23,8 @@ import ( "strings" "github.com/BurntSushi/toml" - "github.com/paketo-buildpacks/libpak/v2/bard" "github.com/paketo-buildpacks/libpak/v2/internal" + "github.com/paketo-buildpacks/libpak/v2/log" ) type PackageDependency struct { @@ -44,8 +44,8 @@ func (p PackageDependency) Update(options ...Option) { config = option(config) } - logger := bard.NewLogger(os.Stdout) - _, _ = fmt.Fprintf(logger.TitleWriter(), "\n%s\n", bard.FormatIdentity(p.ID, p.Version)) + logger := log.NewPaketoLogger(os.Stdout) + _, _ = fmt.Fprintf(logger.TitleWriter(), "\n%s\n", log.FormatIdentity(p.ID, p.Version)) if p.BuilderPath != "" { if err := updateFile(p.BuilderPath, updateByKey("buildpacks", p.ID, p.Version)); err != nil { diff --git a/dependency_cache.go b/dependency_cache.go index c4898e5..513367a 100644 --- a/dependency_cache.go +++ b/dependency_cache.go @@ -34,7 +34,7 @@ import ( "github.com/buildpacks/libcnb/v2" "github.com/heroku/color" - "github.com/paketo-buildpacks/libpak/v2/bard" + "github.com/paketo-buildpacks/libpak/v2/log" "github.com/paketo-buildpacks/libpak/v2/sherpa" ) @@ -49,7 +49,6 @@ type HttpClientTimeouts struct { // DependencyCache allows a user to get an artifact either from a buildmodule's cache, a previous download, or to download // directly. type DependencyCache struct { - // CachePath is the location where the buildmodule has cached its dependencies. CachePath string @@ -57,7 +56,7 @@ type DependencyCache struct { DownloadPath string // Logger is the logger used to write to the console. - Logger bard.Logger + Logger log.Logger // UserAgent is the User-Agent string to use with requests. UserAgent string @@ -71,12 +70,13 @@ type DependencyCache struct { // NewDependencyCache creates a new instance setting the default cache path (/dependencies) and user // agent (/). -func NewDependencyCache(buildModuleID string, buildModuleVersion string, buildModulePath string, platformBindings libcnb.Bindings) (DependencyCache, error) { +func NewDependencyCache(buildModuleID string, buildModuleVersion string, buildModulePath string, platformBindings libcnb.Bindings, logger log.Logger) (DependencyCache, error) { cache := DependencyCache{ CachePath: filepath.Join(buildModulePath, "dependencies"), DownloadPath: os.TempDir(), - UserAgent: fmt.Sprintf("%s/%s", buildModuleID, buildModuleVersion), + Logger: logger, Mappings: map[string]string{}, + UserAgent: fmt.Sprintf("%s/%s", buildModuleID, buildModuleVersion), } mappings, err := mappingsFromBindings(platformBindings) if err != nil { @@ -161,7 +161,6 @@ type RequestModifierFunc func(request *http.Request) (*http.Request, error) // If the BuildpackDependency's SHA256 is not set, the download can never be verified to be up to date and will always // download, skipping all the caches. func (d *DependencyCache) Artifact(dependency BuildModuleDependency, mods ...RequestModifierFunc) (*os.File, error) { - var ( artifact string file string diff --git a/dependency_cache_test.go b/dependency_cache_test.go index 02bc10f..697ddc0 100644 --- a/dependency_cache_test.go +++ b/dependency_cache_test.go @@ -32,6 +32,7 @@ import ( "github.com/sclevine/spec" "github.com/paketo-buildpacks/libpak/v2" + "github.com/paketo-buildpacks/libpak/v2/log" ) func testDependencyCache(t *testing.T, context spec.G, it spec.S) { @@ -55,7 +56,7 @@ func testDependencyCache(t *testing.T, context spec.G, it spec.S) { }) it("set default CachePath and UserAgent", func() { - dependencyCache, err := libpak.NewDependencyCache(ctx.Buildpack.Info.ID, ctx.Buildpack.Info.Version, ctx.Buildpack.Path, ctx.Platform.Bindings) + dependencyCache, err := libpak.NewDependencyCache(ctx.Buildpack.Info.ID, ctx.Buildpack.Info.Version, ctx.Buildpack.Path, ctx.Platform.Bindings, log.NewDiscardLogger()) Expect(err).NotTo(HaveOccurred()) Expect(dependencyCache.CachePath).To(Equal(filepath.Join("some/path/dependencies"))) Expect(dependencyCache.UserAgent).To(Equal("some-buildpack-id/some-buildpack-version")) @@ -63,7 +64,7 @@ func testDependencyCache(t *testing.T, context spec.G, it spec.S) { }) it("uses default timeout values", func() { - dependencyCache, err := libpak.NewDependencyCache(ctx.Buildpack.Info.ID, ctx.Buildpack.Info.Version, ctx.Buildpack.Path, ctx.Platform.Bindings) + dependencyCache, err := libpak.NewDependencyCache(ctx.Buildpack.Info.ID, ctx.Buildpack.Info.Version, ctx.Buildpack.Path, ctx.Platform.Bindings, log.NewDiscardLogger()) Expect(err).NotTo(HaveOccurred()) Expect(dependencyCache.HttpClientTimeouts.DialerTimeout).To(Equal(6 * time.Second)) Expect(dependencyCache.HttpClientTimeouts.DialerKeepAlive).To(Equal(60 * time.Second)) @@ -82,7 +83,7 @@ func testDependencyCache(t *testing.T, context spec.G, it spec.S) { }) it("uses custom timeout values", func() { - dependencyCache, err := libpak.NewDependencyCache(ctx.Buildpack.Info.ID, ctx.Buildpack.Info.Version, ctx.Buildpack.Path, ctx.Platform.Bindings) + dependencyCache, err := libpak.NewDependencyCache(ctx.Buildpack.Info.ID, ctx.Buildpack.Info.Version, ctx.Buildpack.Path, ctx.Platform.Bindings, log.NewDiscardLogger()) Expect(err).NotTo(HaveOccurred()) Expect(dependencyCache.HttpClientTimeouts.DialerTimeout).To(Equal(7 * time.Second)) Expect(dependencyCache.HttpClientTimeouts.DialerKeepAlive).To(Equal(50 * time.Second)) @@ -119,7 +120,7 @@ func testDependencyCache(t *testing.T, context spec.G, it spec.S) { }) it("sets Mappings", func() { - dependencyCache, err := libpak.NewDependencyCache(ctx.Buildpack.Info.ID, ctx.Buildpack.Info.Version, ctx.Buildpack.Path, ctx.Platform.Bindings) + dependencyCache, err := libpak.NewDependencyCache(ctx.Buildpack.Info.ID, ctx.Buildpack.Info.Version, ctx.Buildpack.Path, ctx.Platform.Bindings, log.NewDiscardLogger()) Expect(err).NotTo(HaveOccurred()) Expect(dependencyCache.Mappings).To(Equal( map[string]string{ @@ -142,7 +143,7 @@ func testDependencyCache(t *testing.T, context spec.G, it spec.S) { }) it("errors", func() { - _, err := libpak.NewDependencyCache(ctx.Buildpack.Info.ID, ctx.Buildpack.Info.Version, ctx.Buildpack.Path, ctx.Platform.Bindings) + _, err := libpak.NewDependencyCache(ctx.Buildpack.Info.ID, ctx.Buildpack.Info.Version, ctx.Buildpack.Path, ctx.Platform.Bindings, log.NewDiscardLogger()) Expect(err).To(HaveOccurred()) }) }) @@ -191,6 +192,7 @@ func testDependencyCache(t *testing.T, context spec.G, it spec.S) { dependencyCache = libpak.DependencyCache{ CachePath: cachePath, DownloadPath: downloadPath, + Logger: log.NewDiscardLogger(), UserAgent: "test-user-agent", } }) diff --git a/detect.go b/detect.go index a1391ca..9d29fb6 100644 --- a/detect.go +++ b/detect.go @@ -19,8 +19,8 @@ package libpak import ( "github.com/buildpacks/libcnb/v2" - "github.com/paketo-buildpacks/libpak/v2/bard" "github.com/paketo-buildpacks/libpak/v2/internal" + "github.com/paketo-buildpacks/libpak/v2/log" ) // Detect is called by the main function of a buildpack, for detection. @@ -39,7 +39,7 @@ type detectDelegate struct { func (d detectDelegate) Detect(context libcnb.DetectContext) (libcnb.DetectResult, error) { result, err := d.delegate(context) if err != nil { - err = bard.IdentifiableError{ + err = log.IdentifiableError{ Name: context.Buildpack.Info.Name, Description: context.Buildpack.Info.Version, Err: err, diff --git a/detect_test.go b/detect_test.go index f846df0..4f23925 100644 --- a/detect_test.go +++ b/detect_test.go @@ -29,7 +29,7 @@ import ( "github.com/stretchr/testify/mock" "github.com/paketo-buildpacks/libpak/v2" - "github.com/paketo-buildpacks/libpak/v2/bard" + "github.com/paketo-buildpacks/libpak/v2/log" ) func testDetect(t *testing.T, context spec.G, it spec.S) { @@ -131,7 +131,7 @@ version = "test-version"`), libcnb.WithExitHandler(exitHandler), ) - Expect(exitHandler.Calls[0].Arguments.Get(0)).To(MatchError(bard.IdentifiableError{ + Expect(exitHandler.Calls[0].Arguments.Get(0)).To(MatchError(log.IdentifiableError{ Name: "test-name", Description: "test-version", Err: fmt.Errorf("test-error"), diff --git a/generate.go b/generate.go index e531718..1fce952 100644 --- a/generate.go +++ b/generate.go @@ -19,8 +19,8 @@ package libpak import ( "github.com/buildpacks/libcnb/v2" - "github.com/paketo-buildpacks/libpak/v2/bard" "github.com/paketo-buildpacks/libpak/v2/internal" + "github.com/paketo-buildpacks/libpak/v2/log" ) // Generate is called by the main function of an extension, for generation. @@ -40,7 +40,7 @@ type generateDelegate struct { func (b generateDelegate) Generate(context libcnb.GenerateContext) (libcnb.GenerateResult, error) { result, err := b.delegate(context) if err != nil { - err = bard.IdentifiableError{ + err = log.IdentifiableError{ Name: context.Extension.Info.Name, Description: context.Extension.Info.Version, Err: err, diff --git a/generate_test.go b/generate_test.go index ee47f35..c201e80 100644 --- a/generate_test.go +++ b/generate_test.go @@ -29,7 +29,7 @@ import ( "github.com/stretchr/testify/mock" "github.com/paketo-buildpacks/libpak/v2" - "github.com/paketo-buildpacks/libpak/v2/bard" + "github.com/paketo-buildpacks/libpak/v2/log" ) func testGenerate(t *testing.T, context spec.G, it spec.S) { @@ -128,7 +128,7 @@ version = "test-version"`), libcnb.WithExitHandler(exitHandler), ) - Expect(exitHandler.Calls[0].Arguments.Get(0)).To(MatchError(bard.IdentifiableError{ + Expect(exitHandler.Calls[0].Arguments.Get(0)).To(MatchError(log.IdentifiableError{ Name: "test-name", Description: "test-version", Err: fmt.Errorf("test-error"), diff --git a/internal/environment_writer.go b/internal/environment_writer.go index f2470d5..68041d6 100644 --- a/internal/environment_writer.go +++ b/internal/environment_writer.go @@ -22,29 +22,29 @@ import ( "path/filepath" "sort" - "github.com/paketo-buildpacks/libpak/v2/bard" + "github.com/paketo-buildpacks/libpak/v2/log" ) // EnvironmentWriter is an implementation of the libcnb.EnvironmentWriter interface. type EnvironmentWriter struct { - logger bard.Logger + logger log.Logger } // EnvironmentWriterOption is a function for configuring a EnvironmentWriter instance. type EnvironmentWriterOption func(writer EnvironmentWriter) EnvironmentWriter // WithEnvironmentWriterLogger creates an EnvironmentWriterOption that configures the logger. -func WithEnvironmentWriterLogger(logger bard.Logger) EnvironmentWriterOption { +func WithEnvironmentWriterLogger(logger log.Logger) EnvironmentWriterOption { return func(writer EnvironmentWriter) EnvironmentWriter { writer.logger = logger return writer } } -// NewEnvironmentWriter creates a new instance that writes to the filesystem and writes to the default bard.Logger. +// NewEnvironmentWriter creates a new instance that writes to the filesystem and writes to the default log.Logger. func NewEnvironmentWriter(options ...EnvironmentWriterOption) EnvironmentWriter { w := EnvironmentWriter{ - logger: bard.NewLogger(os.Stdout), + logger: log.NewPaketoLogger(os.Stdout), } for _, option := range options { diff --git a/internal/environment_writer_test.go b/internal/environment_writer_test.go index 973e179..a8e406c 100644 --- a/internal/environment_writer_test.go +++ b/internal/environment_writer_test.go @@ -25,8 +25,8 @@ import ( . "github.com/onsi/gomega" "github.com/sclevine/spec" - "github.com/paketo-buildpacks/libpak/v2/bard" "github.com/paketo-buildpacks/libpak/v2/internal" + "github.com/paketo-buildpacks/libpak/v2/log" ) func testEnvironmentWriter(t *testing.T, context spec.G, it spec.S) { @@ -41,7 +41,7 @@ func testEnvironmentWriter(t *testing.T, context spec.G, it spec.S) { path = t.TempDir() Expect(os.RemoveAll(path)).To(Succeed()) - writer = internal.EnvironmentWriter{} + writer = internal.NewEnvironmentWriter() }) it("writes the given environment to a directory", func() { @@ -85,7 +85,7 @@ func testEnvironmentWriter(t *testing.T, context spec.G, it spec.S) { it.Before(func() { b = bytes.NewBuffer(nil) - writer = internal.NewEnvironmentWriter(internal.WithEnvironmentWriterLogger(bard.NewLogger(b))) + writer = internal.NewEnvironmentWriter(internal.WithEnvironmentWriterLogger(log.NewPaketoLogger(b))) }) it("logs environment", func() { diff --git a/internal/exit_handler.go b/internal/exit_handler.go index 13ac366..2024098 100644 --- a/internal/exit_handler.go +++ b/internal/exit_handler.go @@ -21,7 +21,7 @@ import ( "io" "os" - "github.com/paketo-buildpacks/libpak/v2/bard" + "github.com/paketo-buildpacks/libpak/v2/log" ) const ( @@ -38,7 +38,7 @@ const ( // ExitHandler is an implementation of the libcnb.ExitHandler interface. type ExitHandler struct { exitFunc func(int) - logger bard.Logger + logger log.Logger writer io.Writer } @@ -54,7 +54,7 @@ func WithExitHandlerExitFunc(exitFunc func(int)) ExitHandlerOption { } // WithExitHandlerLogger creates an ExitHandlerOption that configures the logger. -func WithExitHandlerLogger(logger bard.Logger) ExitHandlerOption { +func WithExitHandlerLogger(logger log.Logger) ExitHandlerOption { return func(handler ExitHandler) ExitHandler { handler.logger = logger return handler @@ -69,11 +69,11 @@ func WithExitHandlerWriter(writer io.Writer) ExitHandlerOption { } } -// NewExitHandler creates a new instance that calls os.Exit and writes to the default bard.Logger and os.stderr. +// NewExitHandler creates a new instance that calls os.Exit and writes to the default log.Logger and os.stderr. func NewExitHandler(options ...ExitHandlerOption) ExitHandler { h := ExitHandler{ exitFunc: os.Exit, - logger: bard.NewLogger(os.Stdout), + logger: log.NewPaketoLogger(os.Stdout), writer: os.Stderr, } @@ -85,7 +85,7 @@ func NewExitHandler(options ...ExitHandlerOption) ExitHandler { } func (e ExitHandler) Error(err error) { - if i, ok := err.(bard.IdentifiableError); ok { + if i, ok := err.(log.IdentifiableError); ok { e.logger.TerminalError(i) } else { _, _ = fmt.Fprintln(e.writer, err) diff --git a/internal/exit_handler_test.go b/internal/exit_handler_test.go index 10058d5..62e4549 100644 --- a/internal/exit_handler_test.go +++ b/internal/exit_handler_test.go @@ -25,8 +25,8 @@ import ( . "github.com/onsi/gomega" "github.com/sclevine/spec" - "github.com/paketo-buildpacks/libpak/v2/bard" "github.com/paketo-buildpacks/libpak/v2/internal" + "github.com/paketo-buildpacks/libpak/v2/log" ) func testExitHandler(t *testing.T, context spec.G, it spec.S) { @@ -43,7 +43,7 @@ func testExitHandler(t *testing.T, context spec.G, it spec.S) { handler = internal.NewExitHandler( internal.WithExitHandlerExitFunc(func(c int) { exitCode = c }), - internal.WithExitHandlerLogger(bard.NewLogger(b)), + internal.WithExitHandlerLogger(log.NewPaketoLogger(b)), internal.WithExitHandlerWriter(b), ) }) @@ -69,7 +69,7 @@ func testExitHandler(t *testing.T, context spec.G, it spec.S) { }) it("writes terminal error", func() { - handler.Error(bard.IdentifiableError{Name: "test-name", Description: "test-description", Err: fmt.Errorf("test-error")}) + handler.Error(log.IdentifiableError{Name: "test-name", Description: "test-description", Err: fmt.Errorf("test-error")}) Expect(b).To(ContainSubstring("\x1b[31m\x1b[0m\n\x1b[31m\x1b[1mtest-name\x1b[0m\x1b[31m test-description\x1b[0m\n\x1b[31;1m test-error\x1b[0m\n")) }) } diff --git a/internal/toml_writer.go b/internal/toml_writer.go index 354dfde..083e70e 100644 --- a/internal/toml_writer.go +++ b/internal/toml_writer.go @@ -26,30 +26,29 @@ import ( "github.com/BurntSushi/toml" "github.com/buildpacks/libcnb/v2" "github.com/heroku/color" - - "github.com/paketo-buildpacks/libpak/v2/bard" + "github.com/paketo-buildpacks/libpak/v2/log" ) // TOMLWriter is an implementation of the libcnb.TOMLWriter interface. type TOMLWriter struct { - logger bard.Logger + logger log.Logger } // TOMLWriterOption is a function for configuring a TOMLWriter instance. type TOMLWriterOption func(writer TOMLWriter) TOMLWriter // WithTOMLWriterLogger creates an TOMLWriterOption that configures the logger. -func WithTOMLWriterLogger(logger bard.Logger) TOMLWriterOption { +func WithTOMLWriterLogger(logger log.Logger) TOMLWriterOption { return func(writer TOMLWriter) TOMLWriter { writer.logger = logger return writer } } -// NewTOMLWriter creates a new instance that writes to the filesystem and writes to the default bard.Logger. +// NewTOMLWriter creates a new instance that writes to the filesystem and writes to the default log.Logger. func NewTOMLWriter(options ...TOMLWriterOption) TOMLWriter { w := TOMLWriter{ - logger: bard.NewLogger(os.Stdout), + logger: log.NewPaketoLogger(os.Stdout), } for _, option := range options { diff --git a/internal/toml_writer_test.go b/internal/toml_writer_test.go index 570c976..9c7b134 100644 --- a/internal/toml_writer_test.go +++ b/internal/toml_writer_test.go @@ -28,8 +28,8 @@ import ( . "github.com/onsi/gomega" "github.com/sclevine/spec" - "github.com/paketo-buildpacks/libpak/v2/bard" "github.com/paketo-buildpacks/libpak/v2/internal" + "github.com/paketo-buildpacks/libpak/v2/log" ) func testTOMLWriter(t *testing.T, context spec.G, it spec.S) { @@ -65,7 +65,7 @@ other-field = "other-value"`)) it.Before(func() { b = bytes.NewBuffer(nil) - tomlWriter = internal.NewTOMLWriter(internal.WithTOMLWriterLogger(bard.NewLogger(b))) + tomlWriter = internal.NewTOMLWriter(internal.WithTOMLWriterLogger(log.NewPaketoLogger(b))) }) it("does not log for uninteresting types", func() { diff --git a/layer.go b/layer.go index 79c3cb0..a1ed94a 100644 --- a/layer.go +++ b/layer.go @@ -29,54 +29,59 @@ import ( "github.com/buildpacks/libcnb/v2" "github.com/paketo-buildpacks/libpak/v2/internal" + "github.com/paketo-buildpacks/libpak/v2/log" "github.com/paketo-buildpacks/libpak/v2/sbom" "github.com/paketo-buildpacks/libpak/v2/sherpa" - - "github.com/paketo-buildpacks/libpak/v2/bard" ) -// libcnb.LayerContributor was removed as a concept from libcnb 2.x -// -// The capability is still useful, and is renamed here as Contributable to avoid clashing with the existing -// libpak.LayerContributor struct. Create instances of Contributable as required, and flatten them to layers -// when required using a FlattenContributableFn implementation. One is supplied as DefaultFlattenContributableFn -// but you may wish to use your own for test, or other purposes. -type Contributable interface { - // Contribute accepts a layer and transforms it, returning a layer. - Contribute(layer libcnb.Layer) (libcnb.Layer, error) - // Name is the name of the layer. - Name() string -} +// ContributeLayersFunc takes a context and result pointer returning a list of Contributables, the list of Contributables will be turned into layers automatically +type ContributeLayersFunc func(context libcnb.BuildContext, result *libcnb.BuildResult) ([]Contributable, error) -// libcnb used to flatten libcnb.LayerContributors after the build had completed. -// this was problematic for some buildpack implementations, so the flattening is now -// able to be driven via buildpacks when required. -type FlattenContributableFn func(Contributable, libcnb.BuildContext) (libcnb.Layer, error) +// ContributableBuildFunc is a standard libcnb.BuildFunc implementation that delegates to a list of Contributables +func ContributableBuildFunc(contributeLayersFunc ContributeLayersFunc) libcnb.BuildFunc { + return func(context libcnb.BuildContext) (libcnb.BuildResult, error) { + result := libcnb.NewBuildResult() -// a default implementation of FlattenContributableFn that can be used by buildpacks to -// flatten libpak.Contributables into libcnb.Layers -func DefaultFlattenContributableFn(creator Contributable, ctx libcnb.BuildContext) (libcnb.Layer, error) { - name := creator.Name() - layer, err := ctx.Layers.Layer(name) - if err != nil { - return libcnb.Layer{}, fmt.Errorf("unable to create layer %s\n%w", name, err) - } - layer, err = creator.Contribute(layer) - if err != nil { - return libcnb.Layer{}, fmt.Errorf("unable to invoke layer creator\n%w", err) + layerContributors, err := contributeLayersFunc(context, &result) + if err != nil { + return libcnb.BuildResult{}, fmt.Errorf("unable to fetch layer contributors\n%w", err) + } + + for _, creator := range layerContributors { + name := creator.Name() + layer, err := context.Layers.Layer(name) + if err != nil { + return libcnb.BuildResult{}, fmt.Errorf("unable to create layer %s\n%w", name, err) + } + + err = creator.Contribute(&layer) + if err != nil { + return libcnb.BuildResult{}, fmt.Errorf("unable to invoke layer creator\n%w", err) + } + + result.Layers = append(result.Layers, layer) + } + + return result, nil } - return layer, nil } -// LayerContributor is a helper for implementing a libpak.Contributable in order to get consistent logging and -// avoidance. -type LayerContributor struct { +// Contributable is an interface that is implemented when you want to contribute new layers +type Contributable interface { + // Contribute accepts a new empty layer and transforms it + Contribute(layer *libcnb.Layer) error + + // Name is the name of the layer. + Name() string +} +// LayerContributor is a helper for implementing Contributable in order to get consistent logging and avoidance. +type LayerContributor struct { // ExpectedMetadata is the metadata to compare against any existing layer metadata. ExpectedMetadata interface{} // Logger is the logger to use. - Logger bard.Logger + Logger log.Logger // Name is the user readable name of the contribution. Name string @@ -86,33 +91,34 @@ type LayerContributor struct { } // NewLayerContributor creates a new instance. -func NewLayerContributor(name string, expectedMetadata interface{}, expectedTypes libcnb.LayerTypes) LayerContributor { +func NewLayerContributor(name string, expectedMetadata interface{}, expectedTypes libcnb.LayerTypes, logger log.Logger) LayerContributor { return LayerContributor{ ExpectedMetadata: expectedMetadata, - Name: name, ExpectedTypes: expectedTypes, + Logger: logger, + Name: name, } } // LayerFunc is a callback function that is invoked when a layer needs to be contributed. -type LayerFunc func() (libcnb.Layer, error) +type LayerFunc func(*libcnb.Layer) error -// Contribute is the function to call when implementing your libpak.Contributable -func (l *LayerContributor) Contribute(layer libcnb.Layer, f LayerFunc) (libcnb.Layer, error) { - layerRestored, err := l.checkIfLayerRestored(layer) +// Contribute is the function to call when implementing Contributable. +func (l *LayerContributor) Contribute(layer *libcnb.Layer, f LayerFunc) error { + layerRestored, err := l.checkIfLayerRestored(*layer) if err != nil { - return libcnb.Layer{}, fmt.Errorf("unable to check metadata\n%w", err) + return fmt.Errorf("unable to check metadata\n%w", err) } - expected, cached, err := l.checkIfMetadataMatches(layer) + expected, cached, err := l.checkIfMetadataMatches(*layer) if err != nil { - return libcnb.Layer{}, fmt.Errorf("unable to check metadata\n%w", err) + return fmt.Errorf("unable to check metadata\n%w", err) } if cached && layerRestored { l.Logger.Headerf("%s: %s cached layer", color.BlueString(l.Name), color.GreenString("Reusing")) layer.LayerTypes = l.ExpectedTypes - return layer, nil + return nil } if !layerRestored { @@ -123,18 +129,18 @@ func (l *LayerContributor) Contribute(layer libcnb.Layer, f LayerFunc) (libcnb.L err = l.reset(layer) if err != nil { - return libcnb.Layer{}, fmt.Errorf("unable to reset\n%w", err) + return fmt.Errorf("unable to reset\n%w", err) } - layer, err = f() + err = f(layer) if err != nil { - return libcnb.Layer{}, err + return err } layer.LayerTypes = l.ExpectedTypes layer.Metadata = expected - return layer, nil + return nil } func (l *LayerContributor) checkIfMetadataMatches(layer libcnb.Layer) (map[string]interface{}, bool, error) { @@ -179,7 +185,7 @@ func (l *LayerContributor) checkIfLayerRestored(layer libcnb.Layer) (bool, error return !(tomlExists && (!layerDirExists || len(dirContents) == 0) && (l.ExpectedTypes.Cache || l.ExpectedTypes.Build)), nil } -func (l *LayerContributor) reset(layer libcnb.Layer) error { +func (l *LayerContributor) reset(layer *libcnb.Layer) error { if err := os.RemoveAll(layer.Path); err != nil { return fmt.Errorf("unable to remove existing layer directory %s\n%w", layer.Path, err) } @@ -191,10 +197,9 @@ func (l *LayerContributor) reset(layer libcnb.Layer) error { return nil } -// DependencyLayerContributor is a helper for implementing a libpak.Contributable for a BuildpackDependency in order +// DependencyLayerContributor is a helper for implementing a Contributable for a BuildpackDependency in order // to get consistent logging and avoidance. type DependencyLayerContributor struct { - // Dependency is the dependency being contributed. Dependency BuildModuleDependency @@ -208,51 +213,51 @@ type DependencyLayerContributor struct { ExpectedMetadata interface{} // Logger is the logger to use. - Logger bard.Logger + Logger log.Logger // RequestModifierFuncs is an optional Request Modifier to use when downloading the dependency. RequestModifierFuncs []RequestModifierFunc } // NewDependencyLayerContributor returns a new DependencyLayerContributor for the given BuildpackDependency -func NewDependencyLayerContributor(dependency BuildModuleDependency, cache DependencyCache, types libcnb.LayerTypes) DependencyLayerContributor { +func NewDependencyLayerContributor(dependency BuildModuleDependency, cache DependencyCache, types libcnb.LayerTypes, logger log.Logger) DependencyLayerContributor { return DependencyLayerContributor{ Dependency: dependency, - ExpectedMetadata: dependency, DependencyCache: cache, + ExpectedMetadata: dependency, ExpectedTypes: types, + Logger: logger, } } // DependencyLayerFunc is a callback function that is invoked when a dependency needs to be contributed. -type DependencyLayerFunc func(artifact *os.File) (libcnb.Layer, error) +type DependencyLayerFunc func(layer *libcnb.Layer, artifact *os.File) error -// Contribute is the function to call whe implementing your libpak.Contributable -func (d *DependencyLayerContributor) Contribute(layer libcnb.Layer, f DependencyLayerFunc) (libcnb.Layer, error) { - lc := NewLayerContributor(d.Name(), d.ExpectedMetadata, d.ExpectedTypes) - lc.Logger = d.Logger +// Contribute is the function to call whe implementing your Contributable. +func (d *DependencyLayerContributor) Contribute(layer *libcnb.Layer, f DependencyLayerFunc) error { + lc := NewLayerContributor(d.Name(), d.ExpectedMetadata, d.ExpectedTypes, d.Logger) - return lc.Contribute(layer, func() (libcnb.Layer, error) { + return lc.Contribute(layer, func(_ *libcnb.Layer) error { artifact, err := d.DependencyCache.Artifact(d.Dependency, d.RequestModifierFuncs...) if err != nil { - return libcnb.Layer{}, fmt.Errorf("unable to get dependency %s\n%w", d.Dependency.ID, err) + return fmt.Errorf("unable to get dependency %s\n%w", d.Dependency.ID, err) } defer artifact.Close() // Only buildpacks can create layers, so source must be buildpack.toml sbomArtifact, err := d.Dependency.AsSyftArtifact("buildpack.toml") if err != nil { - return libcnb.Layer{}, fmt.Errorf("unable to get SBOM artifact %s\n%w", d.Dependency.ID, err) + return fmt.Errorf("unable to get SBOM artifact %s\n%w", d.Dependency.ID, err) } sbomPath := layer.SBOMPath(libcnb.SyftJSON) dep := sbom.NewSyftDependency(layer.Path, []sbom.SyftArtifact{sbomArtifact}) d.Logger.Debugf("Writing Syft SBOM at %s: %+v", sbomPath, dep) if err := dep.WriteTo(sbomPath); err != nil { - return libcnb.Layer{}, fmt.Errorf("unable to write SBOM\n%w", err) + return fmt.Errorf("unable to write SBOM\n%w", err) } - return f(artifact) + return f(layer, artifact) }) } @@ -266,7 +271,7 @@ func (d *DependencyLayerContributor) Name() string { return fmt.Sprintf("%s %s", d.Dependency.Name, d.Dependency.Version) } -// HelperLayerContributor is a helper for implementing a libpak.Contributable for a buildpack helper application in +// HelperLayerContributor is a helper for implementing a Contributable for a buildpack helper application in // order to get consistent logging and avoidance. type HelperLayerContributor struct { @@ -277,18 +282,19 @@ type HelperLayerContributor struct { BuildpackInfo libcnb.BuildpackInfo // Logger is the logger to use. - Logger bard.Logger + Logger log.Logger // Names are the names of the helpers to create Names []string } // NewHelperLayerContributor returns a new HelperLayerContributor -func NewHelperLayerContributor(buildpack libcnb.Buildpack, names ...string) HelperLayerContributor { +func NewHelperLayerContributor(buildpack libcnb.Buildpack, logger log.Logger, names ...string) HelperLayerContributor { return HelperLayerContributor{ - Path: filepath.Join(buildpack.Path, "bin", "helper"), - Names: names, BuildpackInfo: buildpack.Info, + Logger: logger, + Names: names, + Path: filepath.Join(buildpack.Path, "bin", "helper"), } } @@ -297,25 +303,23 @@ func (h HelperLayerContributor) Name() string { return filepath.Base(h.Path) } -// Contribute is the function to call whe implementing your libpak.Contributable -func (h HelperLayerContributor) Contribute(layer libcnb.Layer) (libcnb.Layer, error) { +// Contribute is the function to call whe implementing your Contributable. +func (h HelperLayerContributor) Contribute(layer *libcnb.Layer) error { expected := map[string]interface{}{"buildpackInfo": h.BuildpackInfo, "helperNames": h.Names} lc := NewLayerContributor("Launch Helper", expected, libcnb.LayerTypes{ Launch: true, - }) - - lc.Logger = h.Logger + }, h.Logger) - return lc.Contribute(layer, func() (libcnb.Layer, error) { + return lc.Contribute(layer, func(_ *libcnb.Layer) error { in, err := os.Open(h.Path) if err != nil { - return libcnb.Layer{}, fmt.Errorf("unable to open %s\n%w", h.Path, err) + return fmt.Errorf("unable to open %s\n%w", h.Path, err) } defer in.Close() out := filepath.Join(layer.Path, "helper") if err := sherpa.CopyFile(in, out); err != nil { - return libcnb.Layer{}, fmt.Errorf("unable to copy %s to %s", h.Path, out) + return fmt.Errorf("unable to copy %s to %s", h.Path, out) } for _, n := range h.Names { @@ -324,27 +328,27 @@ func (h HelperLayerContributor) Contribute(layer libcnb.Layer) (libcnb.Layer, er f := filepath.Dir(link) if err := os.MkdirAll(f, 0755); err != nil { - return libcnb.Layer{}, fmt.Errorf("unable to create %s\n%w", f, err) + return fmt.Errorf("unable to create %s\n%w", f, err) } if err := os.Symlink(out, link); err != nil { - return libcnb.Layer{}, fmt.Errorf("unable to link %s to %s\n%w", out, link, err) + return fmt.Errorf("unable to link %s to %s\n%w", out, link, err) } } sbomArtifact, err := h.AsSyftArtifact() if err != nil { - return libcnb.Layer{}, fmt.Errorf("unable to get SBOM artifact for helper\n%w", err) + return fmt.Errorf("unable to get SBOM artifact for helper\n%w", err) } sbomPath := layer.SBOMPath(libcnb.SyftJSON) dep := sbom.NewSyftDependency(layer.Path, []sbom.SyftArtifact{sbomArtifact}) h.Logger.Debugf("Writing Syft SBOM at %s: %+v", sbomPath, dep) if err := dep.WriteTo(sbomPath); err != nil { - return libcnb.Layer{}, fmt.Errorf("unable to write SBOM\n%w", err) + return fmt.Errorf("unable to write SBOM\n%w", err) } - return layer, nil + return nil }) } diff --git a/layer_test.go b/layer_test.go index fa87f96..02ea425 100644 --- a/layer_test.go +++ b/layer_test.go @@ -31,7 +31,7 @@ import ( "github.com/sclevine/spec" "github.com/paketo-buildpacks/libpak/v2" - "github.com/paketo-buildpacks/libpak/v2/bard" + "github.com/paketo-buildpacks/libpak/v2/log" ) func testLayer(t *testing.T, context spec.G, it spec.S) { @@ -39,11 +39,12 @@ func testLayer(t *testing.T, context spec.G, it spec.S) { Expect = NewWithT(t).Expect layersDir string - layer libcnb.Layer + layer *libcnb.Layer ) it.Before(func() { layersDir = t.TempDir() + layer = &libcnb.Layer{} layer.Path = filepath.Join(layersDir, "test-layer") layer.Exec.Path = layer.Path @@ -51,17 +52,13 @@ func testLayer(t *testing.T, context spec.G, it spec.S) { layer.Profile = libcnb.Profile{} }) - it.After(func() { - Expect(os.RemoveAll(layersDir)).To(Succeed()) - }) - context("LayerContributor", func() { var ( lc libpak.LayerContributor ) it.Before(func() { - lc.Logger = bard.NewLogger(bytes.NewBuffer(nil)) + lc.Logger = log.NewPaketoLogger(bytes.NewBuffer(nil)) lc.ExpectedMetadata = map[string]interface{}{ "alpha": "test-alpha", "bravo": map[string]interface{}{ @@ -74,9 +71,9 @@ func testLayer(t *testing.T, context spec.G, it spec.S) { it("calls function with no existing metadata", func() { var called bool - _, err := lc.Contribute(layer, func() (libcnb.Layer, error) { + err := lc.Contribute(layer, func(layer *libcnb.Layer) error { called = true - return layer, nil + return nil }) Expect(err).NotTo(HaveOccurred()) @@ -89,9 +86,9 @@ func testLayer(t *testing.T, context spec.G, it spec.S) { var called bool - _, err := lc.Contribute(layer, func() (libcnb.Layer, error) { + err := lc.Contribute(layer, func(layer *libcnb.Layer) error { called = true - return layer, nil + return nil }) Expect(err).NotTo(HaveOccurred()) @@ -117,9 +114,9 @@ func testLayer(t *testing.T, context spec.G, it spec.S) { Expect(os.RemoveAll(layer.Path)).To(Succeed()) lc.ExpectedTypes.Cache = true - _, err := lc.Contribute(layer, func() (libcnb.Layer, error) { + err := lc.Contribute(layer, func(layer *libcnb.Layer) error { called = true - return layer, nil + return nil }) Expect(err).NotTo(HaveOccurred()) @@ -131,9 +128,9 @@ func testLayer(t *testing.T, context spec.G, it spec.S) { Expect(os.RemoveAll(layer.Path)).To(Succeed()) lc.ExpectedTypes.Build = true - _, err := lc.Contribute(layer, func() (libcnb.Layer, error) { + err := lc.Contribute(layer, func(layer *libcnb.Layer) error { called = true - return layer, nil + return nil }) Expect(err).NotTo(HaveOccurred()) @@ -145,9 +142,9 @@ func testLayer(t *testing.T, context spec.G, it spec.S) { Expect(os.MkdirAll(layer.Path, 0755)).To(Succeed()) lc.ExpectedTypes.Build = true - _, err := lc.Contribute(layer, func() (libcnb.Layer, error) { + err := lc.Contribute(layer, func(layer *libcnb.Layer) error { called = true - return layer, nil + return nil }) Expect(err).NotTo(HaveOccurred()) @@ -160,9 +157,9 @@ func testLayer(t *testing.T, context spec.G, it spec.S) { Expect(os.WriteFile(filepath.Join(layer.Path, "foo"), []byte{}, 0644)).To(Succeed()) lc.ExpectedTypes.Build = true - _, err := lc.Contribute(layer, func() (libcnb.Layer, error) { + err := lc.Contribute(layer, func(layer *libcnb.Layer) error { called = true - return layer, nil + return nil }) Expect(err).NotTo(HaveOccurred()) @@ -173,9 +170,9 @@ func testLayer(t *testing.T, context spec.G, it spec.S) { Expect(os.MkdirAll(layer.Path, 0755)).To(Succeed()) layer.Build = true - _, err := lc.Contribute(layer, func() (libcnb.Layer, error) { + err := lc.Contribute(layer, func(layer *libcnb.Layer) error { called = true - return layer, nil + return nil }) Expect(err).NotTo(HaveOccurred()) @@ -194,9 +191,9 @@ func testLayer(t *testing.T, context spec.G, it spec.S) { var called bool - _, err := lc.Contribute(layer, func() (libcnb.Layer, error) { + err := lc.Contribute(layer, func(layer *libcnb.Layer) error { called = true - return layer, nil + return nil }) Expect(err).NotTo(HaveOccurred()) @@ -204,15 +201,15 @@ func testLayer(t *testing.T, context spec.G, it spec.S) { }) it("returns function error", func() { - _, err := lc.Contribute(layer, func() (libcnb.Layer, error) { - return libcnb.Layer{}, fmt.Errorf("test-error") + err := lc.Contribute(layer, func(layer *libcnb.Layer) error { + return fmt.Errorf("test-error") }) Expect(err).To(MatchError("test-error")) }) it("adds expected metadata to layer", func() { - layer, err := lc.Contribute(layer, func() (libcnb.Layer, error) { - return layer, nil + err := lc.Contribute(layer, func(layer *libcnb.Layer) error { + return nil }) Expect(err).NotTo(HaveOccurred()) @@ -227,8 +224,8 @@ func testLayer(t *testing.T, context spec.G, it spec.S) { it("sets build layer flag", func() { lc.ExpectedTypes.Build = true - layer, err := lc.Contribute(layer, func() (libcnb.Layer, error) { - return layer, nil + err := lc.Contribute(layer, func(layer *libcnb.Layer) error { + return nil }) Expect(err).NotTo(HaveOccurred()) @@ -237,8 +234,8 @@ func testLayer(t *testing.T, context spec.G, it spec.S) { it("sets cache layer flag", func() { lc.ExpectedTypes.Cache = true - layer, err := lc.Contribute(layer, func() (libcnb.Layer, error) { - return layer, nil + err := lc.Contribute(layer, func(layer *libcnb.Layer) error { + return nil }) Expect(err).NotTo(HaveOccurred()) @@ -247,8 +244,8 @@ func testLayer(t *testing.T, context spec.G, it spec.S) { it("sets launch layer flag", func() { lc.ExpectedTypes.Launch = true - layer, err := lc.Contribute(layer, func() (libcnb.Layer, error) { - return layer, nil + err := lc.Contribute(layer, func(layer *libcnb.Layer) error { + return nil }) Expect(err).NotTo(HaveOccurred()) @@ -270,9 +267,9 @@ func testLayer(t *testing.T, context spec.G, it spec.S) { var called bool - layer, err := lc.Contribute(layer, func() (libcnb.Layer, error) { + err := lc.Contribute(layer, func(layer *libcnb.Layer) error { called = true - return layer, nil + return nil }) Expect(err).NotTo(HaveOccurred()) Expect(called).To(BeFalse()) @@ -317,11 +314,12 @@ func testLayer(t *testing.T, context spec.G, it spec.S) { layer.Metadata = map[string]interface{}{} - dlc.Logger = bard.NewLogger(bytes.NewBuffer(nil)) + dlc.Logger = log.NewDiscardLogger() dlc.ExpectedMetadata = dependency dlc.Dependency = dependency dlc.DependencyCache.CachePath = layer.Path dlc.DependencyCache.DownloadPath = layer.Path + dlc.DependencyCache.Logger = log.NewDiscardLogger() }) it.After(func() { @@ -333,11 +331,11 @@ func testLayer(t *testing.T, context spec.G, it spec.S) { var called bool - _, err := dlc.Contribute(layer, func(artifact *os.File) (libcnb.Layer, error) { + err := dlc.Contribute(layer, func(layer *libcnb.Layer, artifact *os.File) error { defer artifact.Close() called = true - return layer, nil + return nil }) Expect(err).NotTo(HaveOccurred()) @@ -355,9 +353,9 @@ func testLayer(t *testing.T, context spec.G, it spec.S) { return request, nil }) - _, err := dlc.Contribute(layer, func(artifact *os.File) (libcnb.Layer, error) { + err := dlc.Contribute(layer, func(layer *libcnb.Layer, artifact *os.File) error { defer artifact.Close() - return layer, nil + return nil }) Expect(err).NotTo(HaveOccurred()) }) @@ -369,11 +367,11 @@ func testLayer(t *testing.T, context spec.G, it spec.S) { var called bool - _, err := dlc.Contribute(layer, func(artifact *os.File) (libcnb.Layer, error) { + err := dlc.Contribute(layer, func(layer *libcnb.Layer, artifact *os.File) error { defer artifact.Close() called = true - return layer, nil + return nil }) Expect(err).NotTo(HaveOccurred()) @@ -401,11 +399,11 @@ func testLayer(t *testing.T, context spec.G, it spec.S) { var called bool - _, err := dlc.Contribute(layer, func(artifact *os.File) (libcnb.Layer, error) { + err := dlc.Contribute(layer, func(layer *libcnb.Layer, artifact *os.File) error { defer artifact.Close() called = true - return layer, nil + return nil }) Expect(err).NotTo(HaveOccurred()) @@ -415,10 +413,10 @@ func testLayer(t *testing.T, context spec.G, it spec.S) { it("returns function error", func() { server.AppendHandlers(ghttp.RespondWith(http.StatusOK, "test-fixture")) - _, err := dlc.Contribute(layer, func(artifact *os.File) (libcnb.Layer, error) { + err := dlc.Contribute(layer, func(layer *libcnb.Layer, artifact *os.File) error { defer artifact.Close() - return libcnb.Layer{}, fmt.Errorf("test-error") + return fmt.Errorf("test-error") }) Expect(err).To(MatchError("test-error")) }) @@ -426,9 +424,9 @@ func testLayer(t *testing.T, context spec.G, it spec.S) { it("adds expected metadata to layer", func() { server.AppendHandlers(ghttp.RespondWith(http.StatusOK, "test-fixture")) - layer, err := dlc.Contribute(layer, func(artifact *os.File) (libcnb.Layer, error) { + err := dlc.Contribute(layer, func(layer *libcnb.Layer, artifact *os.File) error { defer artifact.Close() - return layer, nil + return nil }) Expect(err).NotTo(HaveOccurred()) @@ -475,11 +473,11 @@ func testLayer(t *testing.T, context spec.G, it spec.S) { var called bool - layer, err := dlc.Contribute(layer, func(artifact *os.File) (libcnb.Layer, error) { + err := dlc.Contribute(layer, func(layer *libcnb.Layer, artifact *os.File) error { defer artifact.Close() called = true - return layer, nil + return nil }) Expect(err).NotTo(HaveOccurred()) @@ -493,9 +491,9 @@ func testLayer(t *testing.T, context spec.G, it spec.S) { it("adds expected Syft SBOM file", func() { server.AppendHandlers(ghttp.RespondWith(http.StatusOK, "test-fixture")) - layer, err := dlc.Contribute(layer, func(artifact *os.File) (libcnb.Layer, error) { + err := dlc.Contribute(layer, func(layer *libcnb.Layer, artifact *os.File) error { defer artifact.Close() - return layer, nil + return nil }) Expect(err).NotTo(HaveOccurred()) @@ -537,7 +535,7 @@ func testLayer(t *testing.T, context spec.G, it spec.S) { hlc = libpak.HelperLayerContributor{ Path: file, BuildpackInfo: buildpack.Info, - Logger: bard.NewLogger(bytes.NewBuffer(nil)), + Logger: log.NewPaketoLogger(bytes.NewBuffer(nil)), Names: []string{"test-name-1", "test-name-2"}, } }) @@ -547,7 +545,7 @@ func testLayer(t *testing.T, context spec.G, it spec.S) { }) it("calls function with no existing metadata", func() { - _, err := hlc.Contribute(layer) + err := hlc.Contribute(layer) Expect(err).NotTo(HaveOccurred()) Expect(filepath.Join(layer.Exec.FilePath("test-name-1"))).To(BeAnExistingFile()) @@ -556,7 +554,7 @@ func testLayer(t *testing.T, context spec.G, it spec.S) { it("calls function with non-matching metadata", func() { layer.Metadata["alpha"] = "other-alpha" - _, err := hlc.Contribute(layer) + err := hlc.Contribute(layer) Expect(err).NotTo(HaveOccurred()) file := filepath.Join(layer.Exec.FilePath("test-name-1")) @@ -580,7 +578,7 @@ func testLayer(t *testing.T, context spec.G, it spec.S) { layer.Metadata["buildpackInfo"] = buildpackInfo layer.Metadata["helperNames"] = []interface{}{hlc.Names[0], hlc.Names[1]} - _, err := hlc.Contribute(layer) + err := hlc.Contribute(layer) Expect(err).NotTo(HaveOccurred()) @@ -589,7 +587,7 @@ func testLayer(t *testing.T, context spec.G, it spec.S) { }) it("adds expected metadata to layer", func() { - layer, err := hlc.Contribute(layer) + err := hlc.Contribute(layer) Expect(err).NotTo(HaveOccurred()) buildpackInfo := map[string]interface{}{ @@ -617,7 +615,7 @@ func testLayer(t *testing.T, context spec.G, it spec.S) { // Launch is the only one set & always true - layer, err := hlc.Contribute(layer) + err := hlc.Contribute(layer) Expect(err).NotTo(HaveOccurred()) Expect(filepath.Join(layer.Exec.FilePath("test-name-1"))).NotTo(BeAnExistingFile()) @@ -631,7 +629,7 @@ func testLayer(t *testing.T, context spec.G, it spec.S) { it("adds expected Syft SBOM file", func() { layer.Metadata = map[string]interface{}{} - _, err := hlc.Contribute(layer) + err := hlc.Contribute(layer) Expect(err).NotTo(HaveOccurred()) Expect(filepath.Join(layer.Exec.FilePath("test-name-1"))).To(BeAnExistingFile()) diff --git a/bard/formatter.go b/log/formatter.go similarity index 98% rename from bard/formatter.go rename to log/formatter.go index d010829..1d7abf7 100644 --- a/bard/formatter.go +++ b/log/formatter.go @@ -14,7 +14,7 @@ * limitations under the License. */ -package bard +package log import ( "fmt" diff --git a/bard/formatter_test.go b/log/formatter_test.go similarity index 86% rename from bard/formatter_test.go rename to log/formatter_test.go index f0c5ffd..ace344b 100644 --- a/bard/formatter_test.go +++ b/log/formatter_test.go @@ -14,7 +14,7 @@ * limitations under the License. */ -package bard_test +package log_test import ( "fmt" @@ -22,9 +22,8 @@ import ( "github.com/heroku/color" . "github.com/onsi/gomega" + "github.com/paketo-buildpacks/libpak/v2/log" "github.com/sclevine/spec" - - "github.com/paketo-buildpacks/libpak/v2/bard" ) func testFormatter(t *testing.T, context spec.G, it spec.S) { @@ -35,12 +34,12 @@ func testFormatter(t *testing.T, context spec.G, it spec.S) { context("FormatIdentity", func() { it("it formats name", func() { - Expect(bard.FormatIdentity("test-name", "")). + Expect(log.FormatIdentity("test-name", "")). To(Equal(color.New(color.Bold).Sprint("test-name"))) }) it("formats name and description", func() { - Expect(bard.FormatIdentity("test-name", "test-description")). + Expect(log.FormatIdentity("test-name", "test-description")). To(Equal(fmt.Sprintf("%s test-description", color.New(color.Bold).Sprint("test-name")))) }) }) diff --git a/bard/init_test.go b/log/init_test.go similarity index 91% rename from bard/init_test.go rename to log/init_test.go index cffb67d..5218e05 100644 --- a/bard/init_test.go +++ b/log/init_test.go @@ -14,7 +14,7 @@ * limitations under the License. */ -package bard_test +package log_test import ( "testing" @@ -24,7 +24,7 @@ import ( ) func TestUnit(t *testing.T) { - suite := spec.New("libpak/bard", spec.Report(report.Terminal{})) + suite := spec.New("libpak/log", spec.Report(report.Terminal{})) suite("Logger", testLogger) suite("Formatter", testFormatter) suite("Writer", testWriter) diff --git a/bard/logger.go b/log/logger.go similarity index 53% rename from bard/logger.go rename to log/logger.go index fa35bd4..218a720 100644 --- a/bard/logger.go +++ b/log/logger.go @@ -14,11 +14,12 @@ * limitations under the License. */ -package bard +package log import ( "fmt" "io" + "os" "strings" "github.com/buildpacks/libcnb/v2/log" @@ -30,10 +31,32 @@ func init() { color.Enabled() } -// Logger logs message to a writer. -type Logger struct { +type Logger interface { log.Logger + Body(a ...interface{}) + Bodyf(format string, a ...interface{}) + BodyWriter() io.Writer + IsBodyEnabled() bool + + Header(a ...interface{}) + Headerf(format string, a ...interface{}) + HeaderWriter() io.Writer + IsHeaderEnabled() bool + + TerminalError(err IdentifiableError) + TerminalErrorWriter() io.Writer + IsTerminalErrorEnabled() bool + + Title(name string, version string, homepage string) + Titlef(format string, a ...interface{}) + TitleWriter() io.Writer + IsTitleEnabled() bool +} + +// Logger logs message to a writer. +type PaketoLogger struct { + debug io.Writer body io.Writer header io.Writer terminalBody io.Writer @@ -41,18 +64,35 @@ type Logger struct { title io.Writer } -// NewLogger creates a new instance of Logger. It configures debug logging if $BP_DEBUG is set. -func NewLogger(writer io.Writer) Logger { +// NewDiscardLogger creates a new instance of PaketoLogger that discards all log messages. Useful in testing. +func NewDiscardLogger() PaketoLogger { + return PaketoLogger{ + debug: io.Discard, + body: io.Discard, + header: io.Discard, + terminalBody: io.Discard, + terminalHeader: io.Discard, + title: io.Discard, + } +} + +// NewPaketoLogger creates a new instance of PaketoLogger. It configures debug logging if $BP_DEBUG is set. +func NewPaketoLogger(writer io.Writer) PaketoLogger { var options []Option - return NewLoggerWithOptions(writer, options...) + return NewPaketoLoggerWithOptions(writer, options...) } // Option is a function for configuring a Logger instance. -type Option func(logger Logger) Logger +type Option func(logger PaketoLogger) PaketoLogger -func NewLoggerWithOptions(writer io.Writer, options ...Option) Logger { - l := Logger{ - Logger: log.New(writer), +func NewPaketoLoggerWithOptions(writer io.Writer, options ...Option) PaketoLogger { + var debugWriter io.Writer + if strings.ToLower(os.Getenv("BP_LOG_LEVEL")) == "debug" || os.Getenv("BP_DEBUG") != "" { + debugWriter = NewWriter(writer, WithAttributes(color.BgCyan)) + } + + l := PaketoLogger{ + debug: debugWriter, body: NewWriter(writer, WithAttributes(color.Faint), WithIndent(2)), header: NewWriter(writer, WithIndent(1)), terminalBody: NewWriter(writer, WithAttributes(color.FgRed, color.Bold), WithIndent(1)), @@ -69,7 +109,7 @@ func NewLoggerWithOptions(writer io.Writer, options ...Option) Logger { // Body formats using the default formats for its operands and logs a message to the configured body writer. Spaces // are added between operands when neither is a string. -func (l Logger) Body(a ...interface{}) { +func (l PaketoLogger) Body(a ...interface{}) { if !l.IsBodyEnabled() { return } @@ -78,7 +118,7 @@ func (l Logger) Body(a ...interface{}) { } // Bodyf formats according to a format specifier and logs a message to the configured body writer. -func (l Logger) Bodyf(format string, a ...interface{}) { +func (l PaketoLogger) Bodyf(format string, a ...interface{}) { if !l.IsBodyEnabled() { return } @@ -87,18 +127,18 @@ func (l Logger) Bodyf(format string, a ...interface{}) { } // BodyWriter returns the configured body writer. -func (l Logger) BodyWriter() io.Writer { +func (l PaketoLogger) BodyWriter() io.Writer { return l.body } // IsBodyEnabled indicates whether body logging is enabled. -func (l Logger) IsBodyEnabled() bool { +func (l PaketoLogger) IsBodyEnabled() bool { return l.body != nil } // Header formats using the default formats for its operands and logs a message to the configured header writer. Spaces // are added between operands when neither is a string. -func (l Logger) Header(a ...interface{}) { +func (l PaketoLogger) Header(a ...interface{}) { if !l.IsHeaderEnabled() { return } @@ -107,7 +147,7 @@ func (l Logger) Header(a ...interface{}) { } // Headerf formats according to a format specifier and logs a message to the configured header writer. -func (l Logger) Headerf(format string, a ...interface{}) { +func (l PaketoLogger) Headerf(format string, a ...interface{}) { if !l.IsHeaderEnabled() { return } @@ -116,18 +156,17 @@ func (l Logger) Headerf(format string, a ...interface{}) { } // HeaderWriter returns the configured header writer. -func (l Logger) HeaderWriter() io.Writer { +func (l PaketoLogger) HeaderWriter() io.Writer { return l.header } // IsHeaderEnabled indicates whether header logging is enabled. -func (l Logger) IsHeaderEnabled() bool { +func (l PaketoLogger) IsHeaderEnabled() bool { return l.header != nil } // IdentifiableError is an error associated with an Identifiable for logging purposes. type IdentifiableError struct { - // Name is the name of the identified object. Name string @@ -143,7 +182,7 @@ func (i IdentifiableError) Error() string { } // TerminalError logs a message to the configured terminal error writer. -func (l Logger) TerminalError(err IdentifiableError) { +func (l PaketoLogger) TerminalError(err IdentifiableError) { if !l.IsTerminalErrorEnabled() { return } @@ -153,16 +192,16 @@ func (l Logger) TerminalError(err IdentifiableError) { } // TerminalErrorWriter returns the configured terminal error writer. -func (l Logger) TerminalErrorWriter() io.Writer { +func (l PaketoLogger) TerminalErrorWriter() io.Writer { return l.terminalBody } // IsTerminalErrorEnabled indicates whether terminal error logging is enabled. -func (l Logger) IsTerminalErrorEnabled() bool { +func (l PaketoLogger) IsTerminalErrorEnabled() bool { return l.terminalHeader != nil && l.terminalBody != nil } -func (l Logger) Title(name string, version string, homepage string) { +func (l PaketoLogger) Title(name string, version string, homepage string) { if !l.IsTitleEnabled() { return } @@ -171,17 +210,67 @@ func (l Logger) Title(name string, version string, homepage string) { l.Header(color.New(color.FgBlue, color.Faint, color.Italic).Sprint(homepage)) } +func (l PaketoLogger) Titlef(format string, a ...interface{}) { + if !l.IsTitleEnabled() { + return + } + + l.printf(l.title, format, a...) +} + // TitleWriter returns the configured title writer. -func (l Logger) TitleWriter() io.Writer { +func (l PaketoLogger) TitleWriter() io.Writer { return l.title } // IsTitleEnabled indicates whether title logging is enabled. -func (l Logger) IsTitleEnabled() bool { +func (l PaketoLogger) IsTitleEnabled() bool { return l.title != nil } -func (Logger) print(writer io.Writer, a ...interface{}) { +// Debug formats using the default formats for its operands and writes to the configured debug writer. Spaces are added +// between operands when neither is a string. +func (l PaketoLogger) Debug(a ...interface{}) { + if !l.IsDebugEnabled() { + return + } + + s := fmt.Sprint(a...) + + if !strings.HasSuffix(s, "\n") { + s += "\n" + } + + _, _ = fmt.Fprint(l.debug, s) +} + +// Debugf formats according to a format specifier and writes to the configured debug writer. +func (l PaketoLogger) Debugf(format string, a ...interface{}) { + if !l.IsDebugEnabled() { + return + } + + if !strings.HasSuffix(format, "\n") { + format += "\n" + } + + _, _ = fmt.Fprintf(l.debug, format, a...) +} + +// DebugWriter returns the configured debug writer. +func (l PaketoLogger) DebugWriter() io.Writer { + if l.IsDebugEnabled() { + return l.debug + } + return io.Discard +} + +// IsDebugEnabled indicates whether debug logging is enabled. +func (l PaketoLogger) IsDebugEnabled() bool { + return l.debug != nil +} + +func (PaketoLogger) print(writer io.Writer, a ...interface{}) { s := fmt.Sprint(a...) if !strings.HasSuffix(s, "\n") { @@ -191,7 +280,7 @@ func (Logger) print(writer io.Writer, a ...interface{}) { _, _ = fmt.Fprint(writer, s) } -func (Logger) printf(writer io.Writer, format string, a ...interface{}) { +func (PaketoLogger) printf(writer io.Writer, format string, a ...interface{}) { if !strings.HasSuffix(format, "\n") { format = format + "\n" } diff --git a/bard/logger_test.go b/log/logger_test.go similarity index 83% rename from bard/logger_test.go rename to log/logger_test.go index 9fc763d..fd35374 100644 --- a/bard/logger_test.go +++ b/log/logger_test.go @@ -14,7 +14,7 @@ * limitations under the License. */ -package bard_test +package log_test import ( "bytes" @@ -23,9 +23,8 @@ import ( "testing" . "github.com/onsi/gomega" + "github.com/paketo-buildpacks/libpak/v2/log" "github.com/sclevine/spec" - - "github.com/paketo-buildpacks/libpak/v2/bard" ) func testLogger(t *testing.T, context spec.G, it spec.S) { @@ -33,7 +32,7 @@ func testLogger(t *testing.T, context spec.G, it spec.S) { Expect = NewWithT(t).Expect b *bytes.Buffer - l bard.Logger + l log.Logger ) it.Before(func() { @@ -42,7 +41,7 @@ func testLogger(t *testing.T, context spec.G, it spec.S) { context("without BP_DEBUG", func() { it.Before(func() { - l = bard.NewLogger(b) + l = log.NewPaketoLogger(b) }) it("does not configure debug", func() { @@ -54,12 +53,8 @@ func testLogger(t *testing.T, context spec.G, it spec.S) { it.Before(func() { //libcnb defines BP_DEBUG as enabled if it has _any_ value //this does not include empty string as previously tested here. - Expect(os.Setenv("BP_DEBUG", "true")).To(Succeed()) - l = bard.NewLogger(b) - }) - - it.After(func() { - Expect(os.Unsetenv("BP_DEBUG")).To(Succeed()) + t.Setenv("BP_DEBUG", "true") + l = log.NewPaketoLogger(b) }) it("configures debug", func() { @@ -69,12 +64,8 @@ func testLogger(t *testing.T, context spec.G, it spec.S) { context("with BP_LOG_LEVEL set to DEBUG", func() { it.Before(func() { - Expect(os.Setenv("BP_LOG_LEVEL", "DEBUG")).To(Succeed()) - l = bard.NewLogger(b) - }) - - it.After(func() { - Expect(os.Unsetenv("BP_LOG_LEVEL")).To(Succeed()) + t.Setenv("BP_LOG_LEVEL", "DEBUG") + l = log.NewPaketoLogger(b) }) it("configures debug", func() { @@ -85,7 +76,7 @@ func testLogger(t *testing.T, context spec.G, it spec.S) { context("with debug disabled", func() { it.Before(func() { Expect(os.Unsetenv("BP_LOG_LEVEL")).To(Succeed()) - l = bard.NewLoggerWithOptions(b) + l = log.NewPaketoLoggerWithOptions(b) }) it("does not write debug log", func() { @@ -105,11 +96,8 @@ func testLogger(t *testing.T, context spec.G, it spec.S) { context("with debug enabled", func() { it.Before(func() { - Expect(os.Setenv("BP_LOG_LEVEL", "debug")).To(Succeed()) - l = bard.NewLogger(b) - }) - it.After(func() { - Expect(os.Unsetenv("BP_LOG_LEVEL")).To(Succeed()) + t.Setenv("BP_LOG_LEVEL", "debug") + l = log.NewPaketoLogger(b) }) it("writes body log", func() { @@ -132,12 +120,12 @@ func testLogger(t *testing.T, context spec.G, it spec.S) { it("writes debug log", func() { l.Debug("test-message") - Expect(b.String()).To(Equal("test-message\n")) + Expect(b.String()).To(Equal("\x1b[46mtest-message\x1b[0m\n")) }) it("writes debug formatted log", func() { l.Debugf("test-%s", "message") - Expect(b.String()).To(Equal("test-message\n")) + Expect(b.String()).To(Equal("\x1b[46mtest-message\x1b[0m\n")) }) it("returns debug writer", func() { @@ -163,7 +151,7 @@ func testLogger(t *testing.T, context spec.G, it spec.S) { }) it("writes terminal error", func() { - l.TerminalError(bard.IdentifiableError{Name: "test-name", Description: "test-description", Err: fmt.Errorf("test-error")}) + l.TerminalError(log.IdentifiableError{Name: "test-name", Description: "test-description", Err: fmt.Errorf("test-error")}) Expect(b.String()).To(Equal("\x1b[31m\x1b[0m\n\x1b[31m\x1b[1mtest-name\x1b[0m\x1b[31m test-description\x1b[0m\n\x1b[31;1m test-error\x1b[0m\n")) }) diff --git a/bard/writer.go b/log/writer.go similarity index 99% rename from bard/writer.go rename to log/writer.go index 61f2600..c1df30b 100644 --- a/bard/writer.go +++ b/log/writer.go @@ -14,7 +14,7 @@ * limitations under the License. */ -package bard +package log import ( "bytes" diff --git a/bard/writer_test.go b/log/writer_test.go similarity index 86% rename from bard/writer_test.go rename to log/writer_test.go index 7b8fda5..92b1cbf 100644 --- a/bard/writer_test.go +++ b/log/writer_test.go @@ -14,7 +14,7 @@ * limitations under the License. */ -package bard_test +package log_test import ( "bytes" @@ -22,9 +22,8 @@ import ( "github.com/heroku/color" . "github.com/onsi/gomega" + "github.com/paketo-buildpacks/libpak/v2/log" "github.com/sclevine/spec" - - "github.com/paketo-buildpacks/libpak/v2/bard" ) func testWriter(t *testing.T, context spec.G, it spec.S) { @@ -35,12 +34,12 @@ func testWriter(t *testing.T, context spec.G, it spec.S) { context("Writer", func() { var ( buffer *bytes.Buffer - writer *bard.Writer + writer *log.Writer ) it.Before(func() { buffer = bytes.NewBuffer(nil) - writer = bard.NewWriter(buffer) + writer = log.NewWriter(buffer) }) context("Write", func() { @@ -52,7 +51,7 @@ func testWriter(t *testing.T, context spec.G, it spec.S) { context("when the writer has a color", func() { it.Before(func() { - writer = bard.NewWriter(buffer, bard.WithAttributes(color.FgBlue)) + writer = log.NewWriter(buffer, log.WithAttributes(color.FgBlue)) }) it("prints to the writer with the correct color codes", func() { @@ -64,7 +63,7 @@ func testWriter(t *testing.T, context spec.G, it spec.S) { context("when the writer has an indent", func() { it.Before(func() { - writer = bard.NewWriter(buffer, bard.WithIndent(2)) + writer = log.NewWriter(buffer, log.WithIndent(2)) }) it("prints to the writer with the correct indentation", func() { @@ -76,7 +75,7 @@ func testWriter(t *testing.T, context spec.G, it spec.S) { context("when the writer has a return prefix", func() { it.Before(func() { - writer = bard.NewWriter(buffer, bard.WithAttributes(color.FgRed), bard.WithIndent(2)) + writer = log.NewWriter(buffer, log.WithAttributes(color.FgRed), log.WithIndent(2)) }) it("prints to the writer with the correct indentation", func() { @@ -88,7 +87,7 @@ func testWriter(t *testing.T, context spec.G, it spec.S) { context("when the writer has a newline suffix", func() { it.Before(func() { - writer = bard.NewWriter(buffer, bard.WithAttributes(color.FgRed), bard.WithIndent(2)) + writer = log.NewWriter(buffer, log.WithAttributes(color.FgRed), log.WithIndent(2)) }) it("prints to the writer with the correct indentation", func() { @@ -100,7 +99,7 @@ func testWriter(t *testing.T, context spec.G, it spec.S) { context("when there is multiple input", func() { it.Before(func() { - writer = bard.NewWriter(buffer, bard.WithIndent(2)) + writer = log.NewWriter(buffer, log.WithIndent(2)) }) it("skips indentation if there was not a line break", func() { @@ -126,7 +125,7 @@ func testWriter(t *testing.T, context spec.G, it spec.S) { context("when the input has a percent symbol", func() { it.Before(func() { - writer = bard.NewWriter(buffer, bard.WithAttributes(color.FgMagenta)) + writer = log.NewWriter(buffer, log.WithAttributes(color.FgMagenta)) }) it("prints to the writer with the correct indentation", func() { diff --git a/sbom/sbom.go b/sbom/sbom.go index fb90d35..b42b734 100644 --- a/sbom/sbom.go +++ b/sbom/sbom.go @@ -7,8 +7,8 @@ import ( "github.com/buildpacks/libcnb/v2" "github.com/mitchellh/hashstructure/v2" - "github.com/paketo-buildpacks/libpak/v2/bard" "github.com/paketo-buildpacks/libpak/v2/effect" + "github.com/paketo-buildpacks/libpak/v2/log" ) //go:generate mockery --name SBOMScanner --case=underscore @@ -105,10 +105,10 @@ type SyftSchema struct { type SyftCLISBOMScanner struct { Executor effect.Executor Layers libcnb.Layers - Logger bard.Logger + Logger log.Logger } -func NewSyftCLISBOMScanner(layers libcnb.Layers, executor effect.Executor, logger bard.Logger) SyftCLISBOMScanner { +func NewSyftCLISBOMScanner(layers libcnb.Layers, executor effect.Executor, logger log.Logger) SyftCLISBOMScanner { return SyftCLISBOMScanner{ Executor: executor, Layers: layers, diff --git a/sbom/sbom_test.go b/sbom/sbom_test.go index 1dcaed4..8a36130 100644 --- a/sbom/sbom_test.go +++ b/sbom/sbom_test.go @@ -1,7 +1,6 @@ package sbom_test import ( - "io" "os" "path/filepath" "strings" @@ -9,9 +8,9 @@ import ( "github.com/buildpacks/libcnb/v2" . "github.com/onsi/gomega" - "github.com/paketo-buildpacks/libpak/v2/bard" "github.com/paketo-buildpacks/libpak/v2/effect" "github.com/paketo-buildpacks/libpak/v2/effect/mocks" + "github.com/paketo-buildpacks/libpak/v2/log" "github.com/paketo-buildpacks/libpak/v2/sbom" "github.com/sclevine/spec" "github.com/stretchr/testify/mock" @@ -62,7 +61,7 @@ func testSBOM(t *testing.T, context spec.G, it spec.S) { }).Return(nil) // uses interface here intentionally, to force that inteface and implementation match - scanner = sbom.NewSyftCLISBOMScanner(layers, &executor, bard.NewLogger(io.Discard)) + scanner = sbom.NewSyftCLISBOMScanner(layers, &executor, log.NewDiscardLogger()) Expect(scanner.ScanBuild("something", format)).To(Succeed()) @@ -105,7 +104,7 @@ func testSBOM(t *testing.T, context spec.G, it spec.S) { }).Return(nil) // uses interface here intentionally, to force that inteface and implementation match - scanner = sbom.NewSyftCLISBOMScanner(layers, &executor, bard.NewLogger(io.Discard)) + scanner = sbom.NewSyftCLISBOMScanner(layers, &executor, log.NewDiscardLogger()) Expect(scanner.ScanBuild("something", format)).To(Succeed()) @@ -133,7 +132,7 @@ func testSBOM(t *testing.T, context spec.G, it spec.S) { scanner := sbom.SyftCLISBOMScanner{ Executor: &executor, Layers: layers, - Logger: bard.NewLogger(io.Discard), + Logger: log.NewDiscardLogger(), } Expect(scanner.ScanLayer(layer, "something", format)).To(Succeed()) @@ -160,7 +159,7 @@ func testSBOM(t *testing.T, context spec.G, it spec.S) { scanner := sbom.SyftCLISBOMScanner{ Executor: &executor, Layers: layers, - Logger: bard.NewLogger(io.Discard), + Logger: log.NewDiscardLogger(), } Expect(scanner.ScanLaunch("something", libcnb.CycloneDXJSON, libcnb.SyftJSON, libcnb.SPDXJSON)).To(Succeed())