Skip to content

Commit

Permalink
fix(actions,docker): make the retag operation concurrent
Browse files Browse the repository at this point in the history
  • Loading branch information
Aaron Schlesinger committed Jun 9, 2016
1 parent c72275c commit 3ac5132
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 21 deletions.
27 changes: 23 additions & 4 deletions actions/docker/retag.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,12 +62,31 @@ func retag(ghClient *github.Client, dockerCl *dlib.Client) func(c *cli.Context)
}
}
fmt.Println("Re-tagging images...")
newTags, err := docker.Retag(dockerCl, allReposAndShas, newTag)
if err != nil {
log.Fatalf("Error re-tagging images (%s)", err)
taggedCh, errCh, doneCh := docker.Retag(dockerCl, allReposAndShas, newTag)
errFound := false
newImages := []*docker.Image{}
for {
shouldBreak := false
select {
case img := <-taggedCh:
fmt.Printf("Tagged image %s\n", *img)
newImages = append(newImages, img)
case retErr := <-errCh:
fmt.Printf("Error tagging image: %s", retErr)
errFound = true
case <-doneCh:
shouldBreak = true
}
if shouldBreak {
break
}
}
if errFound {
log.Fatalf("Error re-tagging images")
}

if push {
if err := docker.Push(dockerCl, newTags); err != nil {
if err := docker.Push(dockerCl, newImages); err != nil {
log.Fatalf("Error pushing new images (%s)", err)
}
}
Expand Down
61 changes: 44 additions & 17 deletions docker/retag.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package docker
import (
"fmt"
"io/ioutil"
"sync"

"github.com/deis/deisrel/git"
dlib "github.com/fsouza/go-dockerclient"
Expand Down Expand Up @@ -44,24 +45,50 @@ func fullImageName(ras git.RepoAndSha) string {
return fmt.Sprintf("quay.io/deisci/%s:git-%s", ras.Name, ras.SHA)
}

// Retag re-tags images from tags based on items in rasl to target
func Retag(dockerCl *dlib.Client, rasl []git.RepoAndSha, target string) ([]*Image, error) {
ret := make([]*Image, len(rasl))
// Retag re-tags images from tags based on items in rasl, pulling existing images if necessary, to target. It returns a channel indicating the progress of the tagging (which may be out of order) and a channel of errors which indicates any errors encountered during the entire process. Some images may be successfully tagged and some may not, but at the end of execution, the final channel (<-chan struct{}) will be closed
func Retag(dockerCl *dlib.Client, rasl []git.RepoAndSha, target string) (<-chan *Image, <-chan error, <-chan struct{}) {
imagesCh := make(chan *Image)
errCh := make(chan error)
doneCh := make(chan struct{})

var wg sync.WaitGroup
for i, ras := range rasl {
fullName := fullImageName(ras)
img, err := ParseImageFromName(fullName, true)
if err != nil {
return nil, err
}
if err := pullIfMissing(dockerCl, img); err != nil {
return nil, err
}
newImg, err := retagOne(dockerCl, img, target)
if err != nil {
return nil, err
}
ret[i] = newImg
wg.Add(1)
iCh := make(chan *Image)
eCh := make(chan error)
go func(i int, ras git.RepoAndSha) {
fullName := fullImageName(ras)
img, err := ParseImageFromName(fullName, true)
if err != nil {
eCh <- err
return
}
if pullErr := pullIfMissing(dockerCl, img); pullErr != nil {
eCh <- pullErr
return
}
newImg, err := retagOne(dockerCl, img, target)
if err != nil {
eCh <- err
return
}
iCh <- newImg
}(i, ras)
go func() {
defer wg.Done()
select {
case img := <-iCh:
imagesCh <- img
case err := <-eCh:
errCh <- err
}
}()
}

return ret, nil
go func() {
wg.Wait()
close(doneCh)
}()

return imagesCh, errCh, doneCh
}

0 comments on commit 3ac5132

Please sign in to comment.