@@ -13,6 +13,8 @@ import (
13
13
"path/filepath"
14
14
"time"
15
15
16
+ "golang.org/x/mod/semver"
17
+
16
18
ociclient "github.com/fluxcd/pkg/oci"
17
19
"github.com/go-git/go-git/v5/utils/ioutil"
18
20
"github.com/google/go-containerregistry/pkg/compression"
@@ -23,7 +25,9 @@ import (
23
25
"github.com/google/go-containerregistry/pkg/v1/tarball"
24
26
typesv1 "github.com/google/go-containerregistry/pkg/v1/types"
25
27
28
+ "github.com/errordeveloper/tape/attest/manifest"
26
29
attestTypes "github.com/errordeveloper/tape/attest/types"
30
+ "github.com/errordeveloper/tape/attest/vcs/git"
27
31
manifestTypes "github.com/errordeveloper/tape/manifest/types"
28
32
)
29
33
@@ -250,7 +254,11 @@ func (c *Client) PushArtefact(ctx context.Context, destinationRef, sourceDir str
250
254
}
251
255
hash := hex .EncodeToString (c .hash .Sum (nil ))
252
256
tag := repo .Tag (manifestTypes .ConfigImageTagPrefix + hash )
253
- tagAlias := tag .Context ().Tag (manifestTypes .ConfigImageTagPrefix + hash [:7 ])
257
+
258
+ tagAliases := append (
259
+ SemVerTagsFromAttestations (ctx , tag , sourceAttestations ... ),
260
+ tag .Context ().Tag (manifestTypes .ConfigImageTagPrefix + hash [:7 ]),
261
+ )
254
262
255
263
if timestamp == nil {
256
264
timestamp = new (time.Time )
@@ -341,11 +349,51 @@ func (c *Client) PushArtefact(ctx context.Context, destinationRef, sourceDir str
341
349
return "" , fmt .Errorf ("pushing index failed: %w" , err )
342
350
}
343
351
344
- if err := remote .Tag (tagAlias , index , c .remoteWithContext (ctx )... ); err != nil {
345
- return "" , fmt .Errorf ("adding alias tagging failed: %w" , err )
352
+ for i := range tagAliases {
353
+ if err := remote .Tag (tagAliases [i ], index , c .remoteWithContext (ctx )... ); err != nil {
354
+ return "" , fmt .Errorf ("adding alias tagging failed: %w" , err )
355
+ }
356
+ }
357
+ // TODO: reteurn tag and all of its aliases
358
+ return tagAliases [0 ].String () + "@" + digest .String (), err
359
+ }
360
+
361
+ func SemVerTagsFromAttestations (ctx context.Context , tag name.Tag , sourceAttestations ... attestTypes.Statement ) []name.Tag {
362
+ statements := attestTypes .FilterByPredicateType (manifest .ManifestDirPredicateType , sourceAttestations )
363
+ if len (statements ) != 1 {
364
+ return []name.Tag {}
346
365
}
347
366
348
- return tagAlias .String () + "@" + digest .String (), err
367
+ entries := manifest .MakeDirContentsStatementFrom (statements [0 ]).GetUnderlyingPredicate ().VCSEntries
368
+ if len (entries .EntryGroups ) != 1 && len (entries .Providers ) != 1 ||
369
+ entries .Providers [0 ] != git .ProviderName {
370
+ return []name.Tag {}
371
+ }
372
+ if len (entries .EntryGroups [0 ]) == 0 {
373
+ return []name.Tag {}
374
+ }
375
+
376
+ // TODO: try to use generics for this?
377
+ groupSummary , ok := entries .EntryGroups [0 ][0 ].Full ().(* git.Summary )
378
+ if ! ok {
379
+ return []name.Tag {}
380
+ }
381
+ ref := groupSummary .Git .Reference
382
+ if len (ref .Tags ) == 0 {
383
+ return []name.Tag {}
384
+ }
385
+ // TODO: detect tags with groupSummary.Path+"/" as prefix and priorities them
386
+ tags := make ([]name.Tag , 0 , len (ref .Tags ))
387
+ for i := range ref .Tags {
388
+ t := ref .Tags [i ].Name
389
+ if semver .IsValid (t ) || semver .IsValid ("v" + t ) {
390
+ tags = append (tags , tag .Context ().Tag (ref .Tags [i ].Name ))
391
+ }
392
+ }
393
+ if len (tags ) == 0 {
394
+ return []name.Tag {}
395
+ }
396
+ return tags
349
397
}
350
398
351
399
func makeDescriptorWithPlatform () Descriptor {
0 commit comments