blob: 462c73d4d0b70640a447b037e9e41dfefb485b47 [file] [log] [blame]
package main
import (
"context"
"fmt"
"path"
"regexp"
"strings"
"go.skia.org/infra/cd/go/cd"
"go.skia.org/infra/go/auth"
"go.skia.org/infra/go/exec"
"go.skia.org/infra/go/gerrit"
"go.skia.org/infra/go/git"
"go.skia.org/infra/go/gitiles"
"go.skia.org/infra/go/httputils"
"go.skia.org/infra/go/skerr"
"go.skia.org/infra/task_driver/go/td"
"golang.org/x/oauth2/google"
)
func updateRefs(ctx context.Context, repoURL, workspace, username, email, louhiPubsubProject, louhiExecutionID, srcRepo, srcCommit string) error {
ctx = td.StartStep(ctx, td.Props("Update References"))
defer td.EndStep(ctx)
// Create the git repo.
ts, err := google.DefaultTokenSource(ctx, auth.ScopeUserinfoEmail, gerrit.AuthScope)
if err != nil {
return td.FailStep(ctx, err)
}
client := httputils.DefaultClientConfig().WithTokenSource(ts).With2xxOnly().Client()
repo := gitiles.NewRepo(repoURL, client)
imageInfo, err := readBuildImagesJSON(ctx, workspace)
if err != nil {
return td.FailStep(ctx, err)
}
// First, obtain the sha256 sums for the images.
for _, image := range imageInfo.Images {
imageAndTag := fmt.Sprintf("%s:%s", image.Image, image.Tag)
if _, err := exec.RunCwd(ctx, ".", "docker", "pull", imageAndTag); err != nil {
return td.FailStep(ctx, err)
}
output, err := exec.RunCwd(ctx, ".", "docker", "inspect", "--format='{{index .RepoDigests 0}}'", imageAndTag)
if err != nil {
return td.FailStep(ctx, err)
}
split := strings.Split(strings.TrimSpace(output), "@")
if len(split) != 2 {
return td.FailStep(ctx, skerr.Fmt("Failed to obtain sha256 sum for %s; expected <image>@<sha256> but got %q", image.Image, output))
}
image.Sha256 = strings.TrimSuffix(strings.TrimPrefix(split[1], "sha256:"), "'")
}
// Obtain the current contents of all files in the repo.
baseCommit, err := repo.ResolveRef(ctx, git.DefaultRef)
if err != nil {
return td.FailStep(ctx, err)
}
oldFiles, err := repo.ListFilesRecursiveAtRef(ctx, ".", baseCommit)
if err != nil {
return td.FailStep(ctx, err)
}
oldContents := map[string][]byte{}
for _, f := range oldFiles {
contents, err := repo.ReadFileAtRef(ctx, f, baseCommit)
if err != nil {
return td.FailStep(ctx, err)
}
oldContents[f] = contents
}
// Create regexes for each of the images.
imageRegexes := make([]*regexp.Regexp, 0, len(imageInfo.Images))
imageReplace := make([]string, 0, len(imageInfo.Images))
for _, image := range imageInfo.Images {
imageRegexes = append(imageRegexes, regexp.MustCompile(fmt.Sprintf(`%s@sha256:[a-f0-9]+`, image.Image)))
imageReplace = append(imageReplace, fmt.Sprintf("%s@sha256:%s", image.Image, image.Sha256))
}
// Find-and-replace each of the image references.
changes := map[string]string{}
for f, oldFileContents := range oldContents {
// Replace all instances of the old image specification with the new.
contentsStr := string(oldFileContents)
for idx, re := range imageRegexes {
contentsStr = re.ReplaceAllString(contentsStr, imageReplace[idx])
}
// Write out the updated file.
newFileContents := contentsStr
if string(oldFileContents) != newFileContents {
changes[f] = newFileContents
}
}
// Upload a CL.
if len(changes) > 0 {
imageList := make([]string, 0, len(imageInfo.Images))
for _, image := range imageInfo.Images {
imageList = append(imageList, path.Base(image.Image))
}
commitSubject := fmt.Sprintf("Update %s", strings.Join(imageList, ", "))
return cd.UploadCL(ctx, changes, repoURL, baseCommit, commitSubject, srcRepo, srcCommit, louhiPubsubProject, louhiExecutionID)
}
return nil
}
func bazelRegexAndReplaceForImage(image *SingleImageInfo) (*regexp.Regexp, string) {
const regexTmpl = `(container_pull\(\s*name\s*=\s*"%s",\s*digest\s*=\s*)"sha256:[a-f0-9]+",`
regex := regexp.MustCompile(fmt.Sprintf(regexTmpl, path.Base(image.Image)))
const replTmpl = `$1"%s",`
replace := fmt.Sprintf(replTmpl, image.Sha256)
return regex, replace
}