@@ -115,6 +115,7 @@ type (
115115 PushOnly bool // Push only mode, skips build process
116116 SourceTarPath string // Path to Docker image tar file to load and push
117117 TarPath string // Path to save Docker image as tar file
118+ SourceImage string // Source image to push (optional)
118119 }
119120
120121 Card []struct {
@@ -1002,12 +1003,72 @@ func (p Plugin) pushOnly() error {
10021003 }
10031004 }
10041005
1005- // For each tag, verify image exists and push
1006+ // Check if source image is specified
1007+ sourceImageName := p .SourceImage
1008+ var sourceTags []string
1009+
1010+ if sourceImageName == "" {
1011+ // If no source image specified, use the repo (original behavior)
1012+ sourceImageName = p .Build .Repo
1013+ sourceTags = p .Build .Tags
1014+ } else {
1015+ // If source image is specified, check if it has a tag
1016+ parts := strings .Split (sourceImageName , ":" )
1017+ if len (parts ) > 1 {
1018+ sourceImageName = parts [0 ]
1019+ sourceTags = []string {parts [1 ]}
1020+ } else {
1021+ // Default to "latest" if no tag specified
1022+ sourceTags = []string {"latest" }
1023+ }
1024+ fmt .Printf ("Using source image: %s with tag(s): %s\n " , sourceImageName , strings .Join (sourceTags , ", " ))
1025+ }
1026+
1027+ // For each source tag and target tag combination
10061028 var digest string
1029+ taggedForPush := make (map [string ]bool )
1030+
1031+ for _ , sourceTag := range sourceTags {
1032+ sourceFullImageName := fmt .Sprintf ("%s:%s" , sourceImageName , sourceTag )
1033+
1034+ // Check if the source image exists in local daemon
1035+ if ! imageExists (sourceFullImageName ) {
1036+ fmt .Printf ("Warning: Source image %s not found\n " , sourceFullImageName )
1037+ // Continue to the next source tag if available, otherwise return error
1038+ if len (sourceTags ) > 1 {
1039+ continue
1040+ }
1041+ return fmt .Errorf ("source image %s not found, cannot push" , sourceFullImageName )
1042+ }
1043+
1044+ // For each target tag, tag and push
1045+ for _ , targetTag := range p .Build .Tags {
1046+ targetFullImageName := fmt .Sprintf ("%s:%s" , p .Build .Repo , targetTag )
1047+
1048+ // Skip if source and target are identical
1049+ if sourceFullImageName == targetFullImageName {
1050+ fmt .Printf ("Source and target image names are identical: %s\n " , sourceFullImageName )
1051+ } else {
1052+ // Tag the source image with the target name
1053+ fmt .Printf ("Tagging %s as %s\n " , sourceFullImageName , targetFullImageName )
1054+ tagCmd := commandTag (Build {Name : sourceFullImageName }, targetFullImageName )
1055+ tagCmd .Stdout = os .Stdout
1056+ tagCmd .Stderr = os .Stderr
1057+ trace (tagCmd )
1058+ if err := tagCmd .Run (); err != nil {
1059+ return fmt .Errorf ("failed to tag image %s as %s: %w" , sourceFullImageName , targetFullImageName , err )
1060+ }
1061+ }
1062+
1063+ taggedForPush [targetFullImageName ] = true
1064+ }
1065+ }
1066+
1067+ // Push all successfully tagged images
10071068 for _ , tag := range p .Build .Tags {
10081069 fullImageName := fmt .Sprintf ("%s:%s" , p .Build .Repo , tag )
10091070
1010- // Check if image exists in local daemon
1071+ // Verify the image exists (it should since we just tagged it)
10111072 if ! imageExists (fullImageName ) {
10121073 return fmt .Errorf ("image %s not found, cannot push" , fullImageName )
10131074 }
0 commit comments