From faa9e605382e8b71691f7391f8b4e3edeabf4cb4 Mon Sep 17 00:00:00 2001 From: Ilya Dmitrichenko Date: Thu, 27 Jun 2024 17:58:52 +0100 Subject: [PATCH] WIP --- manifest/packager/packager.go | 4 +-- oci/artefact.go | 59 ++++++++++++++++++++++------------- tape/app/package.go | 8 +++-- 3 files changed, 45 insertions(+), 26 deletions(-) diff --git a/manifest/packager/packager.go b/manifest/packager/packager.go index c047985..bb519e9 100644 --- a/manifest/packager/packager.go +++ b/manifest/packager/packager.go @@ -10,7 +10,7 @@ import ( type Packager interface { //Pull(string) error - Push(context.Context, string) (string, error) + Push(context.Context, string) (*oci.PackageRefs, error) } type DefaultPackager struct { @@ -32,7 +32,7 @@ func NewDefaultPackager(client *oci.Client, destinationRef string, sourceEpochTi } } -func (r *DefaultPackager) Push(ctx context.Context, dir string) (string, error) { +func (r *DefaultPackager) Push(ctx context.Context, dir string) (*oci.PackageRefs, error) { return r.Client.PushArtefact(ctx, r.destinationRef, dir, r.sourceEpochTimestamp, r.sourceAttestations...) } diff --git a/oci/artefact.go b/oci/artefact.go index bbbca74..180ae82 100644 --- a/oci/artefact.go +++ b/oci/artefact.go @@ -57,6 +57,13 @@ type ArtefactInfo struct { Digest string } +type PackageRefs struct { + Digest string + Primary string + Short string + SemVer []string +} + func (c *Client) Fetch(ctx context.Context, ref string, mediaTypes ...MediaType) ([]*ArtefactInfo, error) { imageIndex, indexManifest, image, err := c.GetIndexOrImage(ctx, ref) if err != nil { @@ -220,10 +227,10 @@ func (c *Client) getImage(ctx context.Context, imageIndex ImageIndex, digest Has } // based on https://github.com/fluxcd/pkg/blob/2a323d771e17af02dee2ccbbb9b445b78ab048e5/oci/client/push.go -func (c *Client) PushArtefact(ctx context.Context, destinationRef, sourceDir string, timestamp *time.Time, sourceAttestations ...attestTypes.Statement) (string, error) { +func (c *Client) PushArtefact(ctx context.Context, destinationRef, sourceDir string, timestamp *time.Time, sourceAttestations ...attestTypes.Statement) (*PackageRefs, error) { tmpDir, err := os.MkdirTemp("", "bpt-oci-artefact-*") if err != nil { - return "", err + return nil, err } defer os.RemoveAll(tmpDir) @@ -231,7 +238,7 @@ func (c *Client) PushArtefact(ctx context.Context, destinationRef, sourceDir str outputFile, err := os.OpenFile(tmpFile, os.O_RDWR|os.O_CREATE|os.O_EXCL, regularFileMode) if err != nil { - return "", err + return nil, err } defer outputFile.Close() @@ -240,25 +247,22 @@ func (c *Client) PushArtefact(ctx context.Context, destinationRef, sourceDir str output := io.MultiWriter(outputFile, c.hash) if err := c.BuildArtefact(tmpFile, sourceDir, output); err != nil { - return "", err + return nil, err } attestLayer, err := c.BuildAttestations(sourceAttestations) if err != nil { - return "", fmt.Errorf("failed to serialise attestations: %w", err) + return nil, fmt.Errorf("failed to serialise attestations: %w", err) } repo, err := name.NewRepository(destinationRef) if err != nil { - return "", fmt.Errorf("invalid URL: %w", err) + return nil, fmt.Errorf("invalid URL: %w", err) } hash := hex.EncodeToString(c.hash.Sum(nil)) tag := repo.Tag(manifestTypes.ConfigImageTagPrefix + hash) - - tagAliases := append( - SemVerTagsFromAttestations(ctx, tag, sourceAttestations...), - tag.Context().Tag(manifestTypes.ConfigImageTagPrefix+hash[:7]), - ) + shortTag := tag.Context().Tag(manifestTypes.ConfigImageTagPrefix + hash[:7]) + semVerTags := SemVerTagsFromAttestations(ctx, tag, sourceAttestations...) if timestamp == nil { timestamp = new(time.Time) @@ -295,12 +299,12 @@ func (c *Client) PushArtefact(ctx context.Context, destinationRef, sourceDir str tarball.WithCompressedCaching, ) if err != nil { - return "", fmt.Errorf("creating artefact content layer failed: %w", err) + return nil, fmt.Errorf("creating artefact content layer failed: %w", err) } config, err = mutate.Append(config, mutate.Addendum{Layer: configLayer}) if err != nil { - return "", fmt.Errorf("appeding content to artifact failed: %w", err) + return nil, fmt.Errorf("appeding content to artifact failed: %w", err) } index = mutate.AppendManifests(index, @@ -315,7 +319,7 @@ func (c *Client) PushArtefact(ctx context.Context, destinationRef, sourceDir str summary, err := (attestTypes.Statements)(sourceAttestations).MarshalSummaryAnnotation() if err != nil { - return "", err + return nil, err } attestAnnotations[AttestationsSummaryAnnotation] = summary @@ -329,7 +333,7 @@ func (c *Client) PushArtefact(ctx context.Context, destinationRef, sourceDir str attest, err = mutate.Append(attest, mutate.Addendum{Layer: attestLayer}) if err != nil { - return "", fmt.Errorf("appeding attestations to artifact failed: %w", err) + return nil, fmt.Errorf("appeding attestations to artifact failed: %w", err) } index = mutate.AppendManifests(index, @@ -342,22 +346,33 @@ func (c *Client) PushArtefact(ctx context.Context, destinationRef, sourceDir str digest, err := index.Digest() if err != nil { - return "", fmt.Errorf("parsing index digest failed: %w", err) + return nil, fmt.Errorf("parsing index digest failed: %w", err) } if err := remote.WriteIndex(tag, index, c.remoteWithContext(ctx)...); err != nil { - return "", fmt.Errorf("pushing index failed: %w", err) + return nil, fmt.Errorf("pushing index failed: %w", err) + } + + refs := &PackageRefs{ + Digest: digest.String(), + Primary: tag.String(), + Short: shortTag.String(), + SemVer: make([]string, len(semVerTags)), } - for i := range tagAliases { - if err := remote.Tag(tagAliases[i], index, c.remoteWithContext(ctx)...); err != nil { - return "", fmt.Errorf("adding alias tagging failed: %w", err) + for i, tagAlias := range append(semVerTags, shortTag) { + if err := remote.Tag(tagAlias, index, c.remoteWithContext(ctx)...); err != nil { + return nil, fmt.Errorf("adding alias tagging failed: %w", err) + } + if i < len(semVerTags) { + refs.SemVer[i] = tagAlias.String() + "@" + digest.String() } } - // TODO: reteurn tag and all of its aliases - return tagAliases[0].String() + "@" + digest.String(), err + return refs, nil } +func (p *PackageRefs) String() string { return p.Short + "@" + p.Digest } + func SemVerTagsFromAttestations(ctx context.Context, tag name.Tag, sourceAttestations ...attestTypes.Statement) []name.Tag { statements := attestTypes.FilterByPredicateType(manifest.ManifestDirPredicateType, sourceAttestations) if len(statements) != 1 { diff --git a/tape/app/package.go b/tape/app/package.go index 0710216..2417a48 100644 --- a/tape/app/package.go +++ b/tape/app/package.go @@ -182,11 +182,15 @@ func (c *TapePackageCommand) Execute(args []string) error { path, sourceEpochTimestamp := loader.MostRecentlyModified() c.tape.log.Debugf("using source epoch timestamp %s from most recently modified manifest file %q", sourceEpochTimestamp, path) packager := packager.NewDefaultPackager(client, c.OutputImage, &sourceEpochTimestamp, attreg.GetStatements()...) - packageRef, err := packager.Push(ctx, images.Dir()) + packageRefs, err := packager.Push(ctx, images.Dir()) if err != nil { return fmt.Errorf("failed to create package: %w", err) } - c.tape.log.Infof("created package %q", packageRef) + c.tape.log.Infof("created package %q", packageRefs[1]) + + if len(packageRefs) > 2 { + c.tape.log.Infof("additional tags: %s", strings.Join(packageRefs[1:], ", ")) + } return nil }