diff --git a/internal/acceptance/workflows/baking_a_tile.feature b/internal/acceptance/workflows/baking_a_tile.feature index 1067fc72..65ba0da6 100644 --- a/internal/acceptance/workflows/baking_a_tile.feature +++ b/internal/acceptance/workflows/baking_a_tile.feature @@ -15,7 +15,8 @@ Feature: As a developer, I want to bake a tile And "bake_records/0.2.0-dev.json" contains substring: "version": "0.2.0-dev" And "bake_records/0.2.0-dev.json" contains substring: "source_revision": "bc3ac24e192ba06a2eca19381ad785ec7069e0d0" And "bake_records/0.2.0-dev.json" contains substring: "kiln_version": "0.0.0+acceptance-tests" - And "tile-0.2.0-dev.pivotal" has sha256 sum "ec0f718ffcf2f066024b4bb6ae0249677e641c4753e28b0ca6d8b8ea6b2e29c5" + And "bake_records/0.2.0-dev.json" contains substring: "file_checksum": "342fd94f1f3ccaaa1b964977067a1d89915b2c6957242d18bd1ef39babcda915" + And "tile-0.2.0-dev.pivotal" has sha256 sum "342fd94f1f3ccaaa1b964977067a1d89915b2c6957242d18bd1ef39babcda915" Scenario: it reads directory configuration from Kilnfile Given I have a tile source directory "testdata/tiles/non-standard-paths" diff --git a/internal/acceptance/workflows/scenario/step_funcs_tile_source_code.go b/internal/acceptance/workflows/scenario/step_funcs_tile_source_code.go index 215be4d2..d65b44e3 100644 --- a/internal/acceptance/workflows/scenario/step_funcs_tile_source_code.go +++ b/internal/acceptance/workflows/scenario/step_funcs_tile_source_code.go @@ -126,11 +126,18 @@ func copyTileDirectory(dir, tileDirectory string) (string, error) { if err := executeAndWrapError(testTileDir, env, "git", "add", "."); err != nil { return "", fmt.Errorf("tile path is not a repository: adding initial files failed: %w", err) } - env = updateEnvVar(env, "GIT_AUTHOR_DATE", "Thu, 07 Apr 2005 22:13:13") - env = updateEnvVar(env, "GIT_COMMITTER_DATE", "Thu, 07 Apr 2005 22:13:13") + env = updateEnvVar(env, "GIT_AUTHOR_DATE", "1112937193 -0700") + env = updateEnvVar(env, "GIT_COMMITTER_DATE", "1112937193 -0700") if err := executeAndWrapError(testTileDir, env, "git", "commit", "-m", "initial commit"); err != nil { return "", fmt.Errorf("tile path is not a repository: adding initial files failed: %w", err) } + //catFile := exec.Command("git", "cat-file", "-p", "HEAD") + //catFile.Dir = testTileDir + //catFile.Stdout = os.Stdout + //catFile.Stderr = os.Stdout + //if err := catFile.Run(); err != nil { + // return "", fmt.Errorf("tile path is not a repository: adding initial files failed: %w", err) + //} return testTileDir, nil } diff --git a/internal/commands/bake.go b/internal/commands/bake.go index fc429217..0d1bca10 100644 --- a/internal/commands/bake.go +++ b/internal/commands/bake.go @@ -2,6 +2,8 @@ package commands import ( "bytes" + "crypto/sha256" + "encoding/hex" "errors" "fmt" "io" @@ -138,7 +140,7 @@ func NewBake(fs billy.Filesystem, releasesService baking.ReleasesService, outLog } } -type writeBakeRecordSignature func(string, []byte) error +type writeBakeRecordSignature func(string, string, []byte) error type Bake struct { interpolator interpolator @@ -226,8 +228,12 @@ func NewBakeWithInterfaces(interpolator interpolator, tileWriter tileWriter, out var _ writeBakeRecordSignature = writeBakeRecord -func writeBakeRecord(metadataFilepath string, productTemplate []byte) error { - b, err := source.NewBakeRecord(productTemplate) +func writeBakeRecord(tileFilepath, metadataFilepath string, productTemplate []byte) error { + tileSum, err := tileChecksum(tileFilepath) + if err != nil { + return fmt.Errorf("failed to calculate checksum: %w", err) + } + b, err := source.NewBakeRecord(tileSum, productTemplate) if err != nil { return fmt.Errorf("failed to create bake record: %w", err) } @@ -242,6 +248,19 @@ func writeBakeRecord(metadataFilepath string, productTemplate []byte) error { return nil } +func tileChecksum(tileFilepath string) (string, error) { + f, err := os.Open(tileFilepath) + if err != nil { + return "", fmt.Errorf("failed to open tile file: %w", err) + } + defer closeAndIgnoreError(f) + s := sha256.New() + if _, err := io.Copy(s, f); err != nil { + return "", fmt.Errorf("failed to calculate checksum: %w", err) + } + return hex.EncodeToString(s.Sum(nil)), nil +} + func shouldGenerateTileFileName(b *Bake, args []string) bool { return b.Options.OutputFile == "" && !b.Options.MetadataOnly && @@ -536,12 +555,6 @@ func (b Bake) Execute(args []string) error { return nil } - if b.Options.IsFinal { - if err := b.writeBakeRecord(b.Options.Metadata, interpolatedMetadata); err != nil { - return err - } - } - err = b.tileWriter.Write(interpolatedMetadata, builder.WriteInput{ OutputFile: b.Options.OutputFile, StubReleases: b.Options.StubReleases, @@ -561,6 +574,11 @@ func (b Bake) Execute(args []string) error { } } + if b.Options.IsFinal { + if err := b.writeBakeRecord(b.Options.OutputFile, b.Options.Metadata, interpolatedMetadata); err != nil { + return err + } + } return nil } diff --git a/internal/commands/bake_test.go b/internal/commands/bake_test.go index a7d578e5..1a36baea 100644 --- a/internal/commands/bake_test.go +++ b/internal/commands/bake_test.go @@ -389,7 +389,7 @@ var _ = Describe("Bake", func() { someReleasesDirectory, })) - Expect(fakeBakeRecordFunc.filePath).To(Equal("some-metadata"), "it informs the bake recorder the path to the metadata template") + Expect(fakeBakeRecordFunc.recordPath).To(Equal("some-metadata"), "it informs the bake recorder the path to the metadata template") Expect(string(fakeBakeRecordFunc.productTemplate)).To(Equal("some-interpolated-metadata"), "it gives the bake recorder the product template") }) @@ -941,14 +941,15 @@ var _ = Describe("Bake", func() { }) type fakeWriteBakeRecordFunc struct { - filePath string - productTemplate []byte + tilePath, recordPath string + productTemplate []byte err error } -func (f *fakeWriteBakeRecordFunc) call(filePath string, productTemplate []byte) error { - f.filePath = filePath +func (f *fakeWriteBakeRecordFunc) call(tilePath, recordPath string, productTemplate []byte) error { + f.tilePath = tilePath + f.recordPath = recordPath f.productTemplate = productTemplate return f.err } diff --git a/pkg/source/bake_record.go b/pkg/source/bake_record.go index c732e706..b8e41b55 100644 --- a/pkg/source/bake_record.go +++ b/pkg/source/bake_record.go @@ -34,10 +34,13 @@ type BakeRecord struct { // TileName might record the tile name used in baking because sometimes multiple tiles can be generated from the same tile source directory // An example of this is the two Tanzu Application Service tiles with different topologies listed on TanzuNetwork. TileName string `yaml:"tile_name,omitempty" json:"tile_name,omitempty"` + + // FileChecksum is the SHA256 checksum of the baked tile. + FileChecksum string `yaml:"file_checksum,omitempty" json:"file_checksum,omitempty"` } // NewBakeRecord parses build information from an OpsManger Product Template (aka metadata/metadata.yml) -func NewBakeRecord(productTemplateBytes []byte) (BakeRecord, error) { +func NewBakeRecord(fileChecksum string, productTemplateBytes []byte) (BakeRecord, error) { var productTemplate struct { ProductVersion string `yaml:"product_version"` KilnMetadata builder.KilnMetadata `yaml:"kiln_metadata"` @@ -54,6 +57,7 @@ func NewBakeRecord(productTemplateBytes []byte) (BakeRecord, error) { Version: productTemplate.ProductVersion, KilnVersion: productTemplate.KilnMetadata.KilnVersion, TileName: productTemplate.KilnMetadata.TileName, + FileChecksum: fileChecksum, }, err } diff --git a/pkg/source/bake_record_test.go b/pkg/source/bake_record_test.go index 839a2ed3..bb841376 100644 --- a/pkg/source/bake_record_test.go +++ b/pkg/source/bake_record_test.go @@ -15,7 +15,7 @@ import ( func TestBuild(t *testing.T) { t.Run("when creating a bake record from a product template", func(t *testing.T) { // language=yaml - b, err := source.NewBakeRecord([]byte(` + b, err := source.NewBakeRecord("some-peach-jam", []byte(` product_name: p-each product_version: some-product-version kiln_metadata: @@ -29,12 +29,13 @@ kiln_metadata: KilnVersion: "some-kiln-version", SourceRevision: "some-tile-source-revision", TileName: "srt", + FileChecksum: "some-peach-jam", }, b) }) t.Run("when the product template is missing kiln_metadata", func(t *testing.T) { // language=yaml - _, err := source.NewBakeRecord([]byte(` + _, err := source.NewBakeRecord("some-peach-jam", []byte(` product_name: p-each product_version: some-product-version `)) @@ -116,42 +117,49 @@ product_version: some-product-version SourceRevision: "some-hash-000", KilnVersion: "some-kiln-version", Version: "0.1.0.0", + FileChecksum: "some-hash-browns", }, { TileName: "p-each", SourceRevision: "some-hash-000", KilnVersion: "some-kiln-version", Version: "0.1.0.2", + FileChecksum: "some-hash-browns", }, { TileName: "p-each", SourceRevision: "some-hash-000", KilnVersion: "some-kiln-version", Version: "1.1.0", + FileChecksum: "some-hash-browns", }, { TileName: "p-each", SourceRevision: "some-hash-002", KilnVersion: "some-kiln-version", Version: "1.2.0", + FileChecksum: "some-hash-browns", }, { TileName: "p-each", SourceRevision: "some-hash-003", KilnVersion: "some-kiln-version", Version: "2.0.0", + FileChecksum: "some-hash-browns", }, { TileName: "p-ear", SourceRevision: "some-hash-004", KilnVersion: "some-kiln-version", Version: "2.0.0", + FileChecksum: "some-hash-browns", }, { TileName: "p-each", SourceRevision: "some-hash-005", KilnVersion: "some-kiln-version", Version: "2.2.0", + FileChecksum: "some-hash-browns", }, }