@@ -509,8 +509,8 @@ func (svc *Service) listTagsIfConstrained(ctx context.Context, moduleName string
509509// this function, and a future constraint type would need its own
510510// proxy-aware code path.
511511func (svc * Service ) probeModuleTags (ctx context.Context , moduleName string , constraint VersionConstraint ) ([]string , error ) {
512- semverConstraint , ok := constraint .( * SemanticVersionConstraint )
513- if ! ok {
512+ semverConstraints := SemverConstraintsOf ( constraint )
513+ if len ( semverConstraints ) == 0 {
514514 // Be loud — silently falling back to ListTags here would defeat
515515 // the whole purpose of --proxy-registry on a registry that
516516 // refuses catalog access.
@@ -532,14 +532,17 @@ func (svc *Service) probeModuleTags(ctx context.Context, moduleName string, cons
532532 return false , fmt .Errorf ("check module %s tag %q: %w" , moduleName , tag , err )
533533 }
534534
535- versions , err := ProbeAvailableVersions (ctx , semverConstraint , check )
536- if err != nil {
537- return nil , fmt .Errorf ("probe tags for module %s: %w" , moduleName , err )
538- }
535+ tags := make ([]string , 0 )
536+
537+ for _ , semverConstraint := range semverConstraints {
538+ versions , err := ProbeAvailableVersions (ctx , semverConstraint , check )
539+ if err != nil {
540+ return nil , fmt .Errorf ("probe tags for module %s: %w" , moduleName , err )
541+ }
539542
540- tags := make ([] string , 0 , len ( versions ))
541- for _ , v := range versions {
542- tags = append ( tags , "v" + v . String ())
543+ for _ , v := range versions {
544+ tags = append ( tags , "v" + v . String ())
545+ }
543546 }
544547
545548 return tags , nil
@@ -1028,32 +1031,40 @@ func (svc *Service) applyChannelAliases(moduleName string) error {
10281031 return nil
10291032 }
10301033
1031- exact , ok := constraint .(* ExactTagConstraint )
1032- if ! ok {
1033- return nil
1034- }
1035-
10361034 moduleLayout := svc .layout .Module (moduleName )
10371035 if moduleLayout == nil || moduleLayout .ModulesReleaseChannels == nil {
10381036 return nil
10391037 }
10401038
1041- desc , err := layouts .FindImageDescriptorByTag (moduleLayout .ModulesReleaseChannels .Path (), exact .Tag ())
1042- if err != nil {
1043- if errors .Is (err , layouts .ErrImageNotFound ) {
1044- return nil
1045- }
1039+ exacts := ExactConstraintsOf (constraint )
10461040
1047- return err
1048- }
1041+ // A single pinned tag without an explicit +channel suffix is published to
1042+ // every release channel (the historical --deckhouse-tag-like behaviour).
1043+ // When several tags are pinned at once, propagating each to all channels
1044+ // would just clobber one another, so only tags that name their own channel
1045+ // (=vX.Y.Z+stable) are aliased; the rest are simply pulled as-is.
1046+ propagateToAllChannels := len (exacts ) == 1 && ! exacts [0 ].HasChannelAlias ()
1047+
1048+ for _ , exact := range exacts {
1049+ desc , err := layouts .FindImageDescriptorByTag (moduleLayout .ModulesReleaseChannels .Path (), exact .Tag ())
1050+ if err != nil {
1051+ if errors .Is (err , layouts .ErrImageNotFound ) {
1052+ continue
1053+ }
10491054
1050- if exact .HasChannelAlias () {
1051- if err := layouts .TagImage (moduleLayout .ModulesReleaseChannels .Path (), desc .Digest , exact .Channel ()); err != nil {
10521055 return err
10531056 }
1054- } else {
1055- // Tag all channels with this version
1056- for _ , channel := range append (internal .GetAllDefaultReleaseChannels (), internal .LTSChannel ) {
1057+
1058+ var channels []string
1059+
1060+ switch {
1061+ case exact .HasChannelAlias ():
1062+ channels = []string {exact .Channel ()}
1063+ case propagateToAllChannels :
1064+ channels = append (internal .GetAllDefaultReleaseChannels (), internal .LTSChannel )
1065+ }
1066+
1067+ for _ , channel := range channels {
10571068 if err := layouts .TagImage (moduleLayout .ModulesReleaseChannels .Path (), desc .Digest , channel ); err != nil {
10581069 return err
10591070 }
0 commit comments