@@ -46,7 +46,8 @@ func (x *PrivXPatch) NewDefinition(tagx *TagXReposTasks) *wf.Definition {
46
46
47
47
repos := wf .Task0 (wd , "Load all repositories" , tagx .SelectRepos )
48
48
49
- repos = wf .Task4 (wd , "Publish change" , func (ctx * wf.TaskContext , clNumber string , reviewers []string , repos []TagRepo , repoName string ) ([]TagRepo , error ) {
49
+ // check change is ready
50
+ checkedChange := wf .Task3 (wd , "Check change" , func (ctx * wf.TaskContext , clNumber string , repoName string , repos []TagRepo ) (* gerrit.ChangeInfo , error ) {
50
51
if ! slices .ContainsFunc (repos , func (r TagRepo ) bool { return r .Name == repoName }) {
51
52
return nil , fmt .Errorf ("no repository %q" , repoName )
52
53
}
@@ -58,6 +59,82 @@ func (x *PrivXPatch) NewDefinition(tagx *TagXReposTasks) *wf.Definition {
58
59
if changeInfo .Project != repoName {
59
60
return nil , fmt .Errorf ("CL is for unexpected project, got: %s, want %s" , changeInfo .Project , repoName )
60
61
}
62
+
63
+ if ! changeInfo .Submittable {
64
+ return nil , fmt .Errorf ("Change %s is not submittable" , internalGerritChangeURL (clNumber ))
65
+ }
66
+ ra , err := x .PrivateGerrit .GetRevisionActions (ctx .Context , clNumber , "current" )
67
+ if err != nil {
68
+ return nil , err
69
+ }
70
+ if ra ["submit" ] == nil || ! ra ["submit" ].Enabled {
71
+ return nil , fmt .Errorf ("Change %s is not submittable" , internalGerritChangeURL (clNumber ))
72
+ }
73
+
74
+ return changeInfo , nil
75
+ }, clNumber , repoName , repos )
76
+
77
+ // create checkpoint branch
78
+ checkpointBranch := wf .Task1 (wd , "Create checkpoint branch" , func (ctx * wf.TaskContext , repoName string ) (string , error ) {
79
+ publicHead , err := x .PrivateGerrit .ReadBranchHead (ctx .Context , repoName , "public" )
80
+ if err != nil {
81
+ return "" , err
82
+ }
83
+ checkpointName := fmt .Sprintf ("public-%s" , time .Now ().UTC ().Format ("2006-01-02-1504" ))
84
+ if _ , err := x .PrivateGerrit .CreateBranch (ctx .Context , "go" , checkpointName , gerrit.BranchInput {Revision : publicHead }); err != nil {
85
+ return "" , err
86
+ }
87
+ return checkpointName , nil
88
+ }, repoName , wf .After (checkedChange ))
89
+
90
+ // move and rebase change onto checkpoint branch
91
+ movedChange := wf .Task2 (wd , "Move change+rebase onto checkpoint branch" , func (ctx * wf.TaskContext , change * gerrit.ChangeInfo , checkpointBranch string ) (* gerrit.ChangeInfo , error ) {
92
+ newCI , err := x .PrivateGerrit .MoveChange (ctx .Context , change .ChangeID , checkpointBranch , true )
93
+ if err != nil {
94
+ return nil , err
95
+ }
96
+ newCI , err = x .PrivateGerrit .RebaseChange (ctx .Context , change .ChangeID , "" )
97
+ if err != nil {
98
+ return nil , err
99
+ }
100
+ return & newCI , nil
101
+ }, checkedChange , checkpointBranch )
102
+
103
+ // wait for change to be submitted
104
+ submittedChange := wf .Task1 (wd , "Await submission" , func (ctx * wf.TaskContext , change * gerrit.ChangeInfo ) (* gerrit.ChangeInfo , error ) {
105
+ var submitted gerrit.ChangeInfo
106
+ if _ , err := AwaitCondition (ctx , time .Second * 10 , func () (string , bool , error ) {
107
+ // The ChangeInfo object returned by RebaseChange doesn't contain
108
+ // information about submittability, so we need to refetch it using
109
+ // GetChange.
110
+ ci , err := x .PrivateGerrit .GetChange (ctx , change .ChangeID , gerrit.QueryChangesOpt {Fields : []string {"SUBMITTABLE" }})
111
+ if err != nil {
112
+ return "" , false , err
113
+ }
114
+
115
+ if ! ci .Submittable {
116
+ return "" , false , nil
117
+ }
118
+
119
+ submitted , err = x .PrivateGerrit .SubmitChange (ctx , ci .ChangeID )
120
+ if err != nil {
121
+ return "" , false , err
122
+ }
123
+ return "" , true , nil
124
+
125
+ }); err != nil {
126
+ return nil , err
127
+ }
128
+
129
+ return & submitted , nil
130
+ }, movedChange )
131
+
132
+ // publish change publicly
133
+ publicChange := wf .Task3 (wd , "Publish change" , func (ctx * wf.TaskContext , change * gerrit.ChangeInfo , reviewers []string , repoName string ) (* gerrit.ChangeInfo , error ) {
134
+ changeInfo , err := x .PrivateGerrit .GetChange (ctx , change .ChangeID , gerrit.QueryChangesOpt {Fields : []string {"CURRENT_REVISION" }})
135
+ if err != nil {
136
+ return nil , err
137
+ }
61
138
if changeInfo .Status != gerrit .ChangeStatusMerged {
62
139
return nil , fmt .Errorf ("CL %s not merged, status is %s" , clNumber , changeInfo .Status )
63
140
}
@@ -136,13 +213,16 @@ func (x *PrivXPatch) NewDefinition(tagx *TagXReposTasks) *wf.Definition {
136
213
if err != nil {
137
214
return nil , err
138
215
}
139
- return repos , nil
140
- }, clNumber , reviewers , repos , repoName )
216
+ return change , nil
217
+ }, submittedChange , reviewers , repoName )
141
218
142
- tagged := wf .Expand4 (wd , "Create single-repo plan" , tagx .BuildSingleRepoPlan , repos , repoName , skipPostSubmit , reviewers )
219
+ // tag repository
220
+ tagged := wf .Expand4 (wd , "Create single-repo plan" , tagx .BuildSingleRepoPlan , repos , repoName , skipPostSubmit , reviewers , wf .After (publicChange ))
143
221
222
+ // wait for manual approval of the announcement message
144
223
okayToAnnoucne := wf .Action0 (wd , "Wait to Announce" , x .ApproveAction , wf .After (tagged ))
145
224
225
+ // send announcement email
146
226
wf .Task5 (wd , "Mail announcement" , func (ctx * wf.TaskContext , tagged TagRepo , cve string , githubIssue string , relNote string , acknowledgement string ) (string , error ) {
147
227
var buf bytes.Buffer
148
228
if err := privXPatchAnnouncementTmpl .Execute (& buf , map [string ]string {
0 commit comments