blob: 2a3afb271f5a1ad03c5d97736aacedf020137fda [file] [log] [blame]
package main
import (
"context"
"errors"
"fmt"
"path"
"path/filepath"
"strings"
"testing"
"github.com/stretchr/testify/require"
"go.skia.org/infra/autoroll/go/config"
"go.skia.org/infra/autoroll/go/config_vars"
"go.skia.org/infra/go/gitiles/mocks"
"go.skia.org/infra/go/testutils"
"go.skia.org/infra/go/testutils/unittest"
"google.golang.org/protobuf/encoding/prototext"
)
const (
testTemplate = `
{{ define "roller" }}
config {
roller_name: "{{.Name}}-chromium-m{{.Milestone.Milestone}}"
child_bug_link: "https://bugs.chromium.org/p/{{.Name}}/issues/entry"
child_display_name: "{{.Name}}"
parent_bug_link: "https://bugs.chromium.org/p/chromium/issues/entry"
parent_display_name: "Chromium m{{.Milestone.Milestone}}"
parent_waterfall: "https://build.chromium.org"
owner_primary: "borenet"
owner_secondary: "rmistry"
contacts: "skiabot@google.com"
service_account: "chromium-release-autoroll@skia-public.iam.gserviceaccount.com"
reviewer: ""
commit_msg: {
bug_project: "chromium"
child_log_url_tmpl: "{{.Repo}}/+log/{{` + "`" + `{{.RollingFrom}}` + "`" + `}}..{{` + "`" + `{{.RollingTo}}` + "`" + `}}"
include_log: true
include_revision_count: true
include_tbr_line: true
built_in: DEFAULT
}
gerrit: {
url: "https://chromium-review.googlesource.com"
project: "chromium/src"
config: CHROMIUM_BOT_COMMIT
}
kubernetes: {
cpu: "1"
memory: "2Gi"
readiness_failure_threshold: 10
readiness_initial_delay_seconds: 30
readiness_period_seconds: 30
image: "TODO"
}
parent_child_repo_manager: {
gitiles_parent: {
gitiles: {
branch: "{{.Milestone.Ref}}"
repo_url: "https://chromium.googlesource.com/chromium/src.git"
}
dep: {
primary: {
id: "{{.Repo}}"
path: "DEPS"
}
}
gerrit: {
url: "https://chromium-review.googlesource.com"
project: "chromium/src"
config: CHROMIUM_BOT_COMMIT
}
}
gitiles_child: {
gitiles: {
branch: "refs/heads/chrome/m{{.Milestome.Milestone}}"
repo_url: "{{.Repo}}"
}
}
}
}
{{ end }}
{{ range $index, $milestone := .Branches.ActiveMilestones }}
{{ template "roller" map "Name" "skia" "Repo" "https://skia.googlesource.com/skia.git" "Milestone" $milestone }}
{{ end }}
`
staticTemplate = `config {
roller_name: "skia-skiabot-test-autoroll"
child_bug_link: "https://bugs.chromium.org/p/skia/issues/entry"
child_display_name: "Skia"
parent_display_name: "Skiabot Test"
parent_waterfall: "https://status-staging.skia.org/repo/skiabot-test"
owner_primary: "borenet"
owner_secondary: "rmistry"
contacts: "borenet@google.com"
service_account: "skia-autoroll@skia-public.iam.gserviceaccount.com"
reviewer: "borenet@google.com"
supports_manual_rolls: true
commit_msg: {
child_log_url_tmpl: "https://skia.googlesource.com/skia.git/+log/{{` + "`" + `{{.RollingFrom}}` + "`" + `}}..{{` + "`" + `{{.RollingTo}}` + "`" + `}}"
include_log: true
include_revision_count: true
include_tbr_line: true
include_tests: true
built_in: DEFAULT
}
gerrit: {
url: "https://skia-review.googlesource.com"
project: "skiabot-test"
config: CHROMIUM_BOT_COMMIT
}
kubernetes: {
cpu: "1"
memory: "2Gi"
readiness_failure_threshold: 10
readiness_initial_delay_seconds: 30
readiness_period_seconds: 30
image: "gcr.io/skia-public/autoroll-be@sha256:4b4842f020a993e7fa2458e83ece11f51d1906f65ced4706a37eeb06f7ac11c9"
}
parent_child_repo_manager: {
gitiles_parent: {
gitiles: {
branch: "main"
repo_url: "https://skia.googlesource.com/skiabot-test.git"
}
dep: {
primary: {
id: "https://skia.googlesource.com/skia.git"
path: "DEPS"
}
}
gerrit: {
url: "https://skia-review.googlesource.com"
project: "skiabot-test"
config: CHROMIUM_BOT_COMMIT
}
}
gitiles_child: {
gitiles: {
branch: "main"
repo_url: "https://skia.googlesource.com/skia.git"
}
}
}
notifiers: {
msg_type: LAST_N_FAILED
monorail: {
project: "skia"
owner: "borenet"
cc: "rmistry@google.com"
components: "AutoRoll"
}
}
}
`
)
var expectedPaths = []string{
"skia-public/skia-chromium-m80.cfg",
"skia-public/skia-chromium-m81.cfg",
"skia-public/skia-chromium-m82.cfg",
}
func checkResults(t *testing.T, expectedPaths []string, results map[string]string) {
// Ensure that all expected paths are in the result set.
require.Len(t, results, len(expectedPaths))
for _, key := range expectedPaths {
_, ok := results[key]
require.True(t, ok)
}
// Ensure that the generated configs are parseable.
for path, contents := range results {
require.NotEmpty(t, contents, "Path %s is empty; was the file deleted?", path)
// Strip the first two lines from the config bytes (the header comment).
configBytes := []byte(strings.Join(strings.Split(contents, "\n")[2:], "\n"))
var cfg config.Config
require.NoError(t, prototext.Unmarshal(configBytes, &cfg))
require.NoError(t, cfg.Validate())
rollerName := strings.TrimSuffix(filepath.Base(path), filepath.Ext(path))
require.Equal(t, cfg.RollerName, rollerName)
}
}
func TestProcess(t *testing.T) {
unittest.SmallTest(t)
// Setup.
ctx := context.Background()
relPath := path.Join("skia-public", "templates", "test.tmpl")
dstDir := "skia-public"
// Process the meta config.
results, err := process(ctx, relPath, testTemplate, dstDir, config_vars.FakeVars())
require.NoError(t, err)
// Check the results.
checkResults(t, expectedPaths, results)
}
func TestProcessDir(t *testing.T) {
unittest.SmallTest(t)
// Setup.
ctx := context.Background()
srcDir := "skia-public/templates"
dstDir := "skia-public"
vars := config_vars.FakeVars()
mockRepo := &mocks.GitilesRepo{}
mockCommit := "abc123"
tmplBaseName := "test.tmpl"
tmplPath := srcDir + "/" + tmplBaseName
// Mock the interactions with Gitiles.
oldConfigFile := "skia-public/skia-chromium-m79.cfg"
mockPaths := append([]string{oldConfigFile}, expectedPaths[:len(expectedPaths)-1]...)
for index := range mockPaths {
mockPaths[index] = strings.SplitN(mockPaths[index], "/", 2)[1]
}
mockRepo.On("ListFilesRecursiveAtRef", testutils.AnyContext, dstDir, mockCommit).Return(mockPaths, nil)
mockRepo.On("ListFilesRecursiveAtRef", testutils.AnyContext, srcDir, mockCommit).Return([]string{tmplBaseName}, nil)
for _, path := range mockPaths {
contents := []byte(fmt.Sprintf(generatedFileHeaderTmpl, tmplPath))
mockRepo.On("ReadFileAtRef", testutils.AnyContext, strings.Join([]string{"skia-public", path}, "/"), mockCommit).Return(contents, nil)
}
// This config file doesn't exist yet.
mockRepo.On("ReadFileAtRef", testutils.AnyContext, expectedPaths[len(expectedPaths)-1], mockCommit).Return(nil, errors.New("does not exist"))
mockRepo.On("ReadFileAtRef", testutils.AnyContext, tmplPath, mockCommit).Return([]byte(testTemplate), nil)
// Compute the results.
results, err := processDir(ctx, "skia-public/templates", "skia-public", vars, mockRepo, mockCommit)
require.NoError(t, err)
// We should have deleted the old config file.
got, ok := results[oldConfigFile]
require.True(t, ok)
require.Equal(t, got, "")
// Delete the entry from the results; it's empty so it'll fail checkResults.
delete(results, oldConfigFile)
checkResults(t, expectedPaths, results)
}
func TestProcessDir_NoChanges(t *testing.T) {
unittest.SmallTest(t)
// Setup.
ctx := context.Background()
srcDir := "skia-public/templates"
dstDir := "skia-public"
vars := config_vars.FakeVars()
mockRepo := &mocks.GitilesRepo{}
mockCommit := "abc123"
tmplBaseName := "test.tmpl"
tmplPath := srcDir + "/" + tmplBaseName
// Mock the interactions with Gitiles.
configFile := "skia-public/skia-skiabot-test-autoroll.cfg"
mockPaths := []string{strings.SplitN(configFile, "/", 2)[1]}
mockRepo.On("ListFilesRecursiveAtRef", testutils.AnyContext, dstDir, mockCommit).Return(mockPaths, nil)
mockRepo.On("ListFilesRecursiveAtRef", testutils.AnyContext, srcDir, mockCommit).Return([]string{tmplBaseName}, nil)
for _, path := range mockPaths {
// Generate the contents of the file.
results, err := process(ctx, tmplPath, staticTemplate, "skia-public", vars)
require.NoError(t, err)
contents, ok := results[configFile]
require.True(t, ok)
mockRepo.On("ReadFileAtRef", testutils.AnyContext, strings.Join([]string{"skia-public", path}, "/"), mockCommit).Return([]byte(contents), nil)
}
mockRepo.On("ReadFileAtRef", testutils.AnyContext, tmplPath, mockCommit).Return([]byte(staticTemplate), nil)
// Compute the results.
results, err := processDir(ctx, "skia-public/templates", "skia-public", vars, mockRepo, mockCommit)
require.NoError(t, err)
require.Len(t, results, 0)
}