| // Copyright 2023 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| package task |
| |
| import ( |
| "fmt" |
| |
| "golang.org/x/build/internal/relui/groups" |
| wf "golang.org/x/build/internal/workflow" |
| ) |
| |
| type PrivateMasterSyncTask struct { |
| Git *Git |
| PrivateGerritURL string |
| Ref string |
| } |
| |
| func (t *PrivateMasterSyncTask) NewDefinition() *wf.Definition { |
| wd := wf.New(wf.ACL{Groups: []string{groups.ReleaseTeam, groups.SecurityTeam}}) |
| // We use a Task, instead of an Action, even though we don't actually want |
| // to return any result, because nothing depends on the Action, and if we |
| // use an Action the definition will tell us we don't reference it anywhere |
| // and say it should be deleted. |
| synced := wf.Task0(wd, "Sync go-private master to public", func(ctx *wf.TaskContext) (string, error) { |
| repo, err := t.Git.Clone(ctx, t.PrivateGerritURL) |
| if err != nil { |
| return "", err |
| } |
| |
| // NOTE: we assume this is generally safe in the case of a race between |
| // submitting a patch and resetting the master branch due to the ordering |
| // of operations at Gerrit. If the submit wins, we reset the master |
| // branch, and the submitted commit is orphaned, which is the expected |
| // behavior anyway. If the reset wins, the submission will either be |
| // cherry-picked onto the new base, which should either succeed, or fail |
| // due to a merge conflict, or Gerrit will reject the submission because |
| // something changed underneath it. Either case seems fine. |
| if _, err := repo.RunCommand(ctx.Context, "push", "--force", "origin", fmt.Sprintf("origin/%s:refs/heads/master", t.Ref)); err != nil { |
| return "", err |
| } |
| |
| return "finished", nil |
| }) |
| wf.Output(wd, fmt.Sprintf("Reset master to %s", t.Ref), synced) |
| return wd |
| } |