Skip to content

Commit cf55448

Browse files
repo-brancher: Improve error handling (#4581)
* chore(repo-branch): improve error handling * make generate
1 parent 245a237 commit cf55448

File tree

1 file changed

+69
-38
lines changed

1 file changed

+69
-38
lines changed

cmd/repo-brancher/main.go

Lines changed: 69 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ import (
1515

1616
"github.com/sirupsen/logrus"
1717

18+
"k8s.io/apimachinery/pkg/util/sets"
19+
1820
"github.com/openshift/ci-tools/pkg/api"
1921
"github.com/openshift/ci-tools/pkg/config"
2022
"github.com/openshift/ci-tools/pkg/promotion"
@@ -77,6 +79,8 @@ func (f *censoringFormatter) Format(entry *logrus.Entry) ([]byte, error) {
7779
return f.delegate.Format(entry)
7880
}
7981

82+
type gitCmd func(l *logrus.Entry, args ...string) error
83+
8084
func main() {
8185
o := gatherOptions()
8286
if err := o.Validate(); err != nil {
@@ -107,7 +111,16 @@ func main() {
107111
}
108112
}
109113

110-
failed := false
114+
brachingFailure := false
115+
failedConfigs := sets.New[string]()
116+
appendFailedConfig := func(c *api.ReleaseBuildConfiguration) {
117+
configInfo := fmt.Sprintf("%s/%s@%s", c.Metadata.Org, c.Metadata.Repo, c.Metadata.Branch)
118+
if c.Metadata.Variant != "" {
119+
configInfo += "__" + c.Metadata.Variant
120+
}
121+
failedConfigs.Insert(configInfo)
122+
}
123+
111124
if err := o.OperateOnCIOperatorConfigDir(o.ConfigDir, api.WithoutOKD, func(configuration *api.ReleaseBuildConfiguration, repoInfo *config.Info) error {
112125
logger := config.LoggerForInfo(*repoInfo)
113126

@@ -117,27 +130,29 @@ func main() {
117130
return nil
118131
}
119132

120-
executeGitCmd := executeGitCMDFactory(repoDir)
133+
gitCmd := gitCmdFunc(repoDir)
121134

122135
remote, err := url.Parse(fmt.Sprintf("https://github.com/%s/%s", repoInfo.Org, repoInfo.Repo))
123136
if err != nil {
124-
logger.WithError(err).Fatal("Could not construct remote URL.")
137+
logger.WithError(err).Error("Could not construct remote URL.")
138+
appendFailedConfig(configuration)
139+
return err
125140
}
126141
if o.Confirm {
127142
remote.User = url.UserPassword(o.username, token)
128143
}
129144
for _, command := range [][]string{{"init"}, {"fetch", "--depth", "1", remote.String(), repoInfo.Branch}} {
130-
if err := executeGitCmd(logger, command...); err != nil {
131-
failed = true
132-
return nil
145+
if err := gitCmd(logger, command...); err != nil {
146+
appendFailedConfig(configuration)
147+
return err
133148
}
134149
}
135150

136151
for _, futureRelease := range o.FutureReleases.Strings() {
137152
futureBranch, err := promotion.DetermineReleaseBranch(o.CurrentRelease, futureRelease, repoInfo.Branch)
138153
if err != nil {
139154
logger.WithError(err).Error("could not determine release branch")
140-
failed = true
155+
appendFailedConfig(configuration)
141156
return nil
142157
}
143158
if futureBranch == repoInfo.Branch {
@@ -148,8 +163,8 @@ func main() {
148163
// it is in sync with the current branch that is promoting
149164
logger := logger.WithField("future-branch", futureBranch)
150165
command := []string{"ls-remote", remote.String(), fmt.Sprintf("refs/heads/%s", futureBranch)}
151-
if err := executeGitCmd(logger, command...); err != nil {
152-
failed = true
166+
if err := gitCmd(logger, command...); err != nil {
167+
appendFailedConfig(configuration)
153168
continue
154169
}
155170

@@ -158,53 +173,69 @@ func main() {
158173
continue
159174
}
160175

161-
pushBranch := func() (retry bool) {
162-
command = []string{"push", remote.String(), fmt.Sprintf("FETCH_HEAD:refs/heads/%s", futureBranch)}
163-
logger := logger.WithFields(logrus.Fields{"commands": fmt.Sprintf("git %s", strings.Join(command, " "))})
164-
if err := executeGitCmd(logger, command...); err != nil {
165-
tooShallowErr := strings.Contains(err.Error(), "Updates were rejected because the remote contains work that you do")
166-
if tooShallowErr {
167-
logger.Warn("Failed to push, trying a deeper clone...")
168-
return true
169-
}
170-
failed = true
171-
}
172-
return false
173-
}
174-
175-
fetchDeeper := func(depth int) error {
176-
command = []string{"fetch", "--depth", strconv.Itoa(depth), remote.String(), repoInfo.Branch}
177-
if err := executeGitCmd(logger, command...); err != nil {
178-
failed = true
179-
return err
176+
for depth := 1; depth < 9; depth += 1 {
177+
retry, err := pushBranch(logger, remote, futureBranch, gitCmd)
178+
if err != nil {
179+
logger.WithError(err).Error("Failed to push branch")
180+
appendFailedConfig(configuration)
181+
break
180182
}
181-
return nil
182-
}
183183

184-
for depth := 1; depth < 9; depth += 1 {
185-
retry := pushBranch()
186184
if !retry {
187185
break
188186
}
189187

190188
if depth == 8 && retry {
191189
logger.Error("Could not push branch even with retries.")
192-
failed = true
190+
appendFailedConfig(configuration)
193191
break
194192
}
195193

196-
if err := fetchDeeper(int(math.Exp2(float64(depth)))); err != nil {
197-
break
194+
if err := fetchDeeper(logger, remote, gitCmd, repoInfo, int(math.Exp2(float64(depth)))); err != nil {
195+
appendFailedConfig(configuration)
196+
return nil
198197
}
199198
}
200199
}
201200
return nil
202-
}); err != nil || failed {
203-
logrus.WithError(err).Fatal("Could not branch configurations.")
201+
}); err != nil {
202+
logrus.WithError(err).Error("Could not branch configurations.")
203+
brachingFailure = true
204+
}
205+
206+
if len(failedConfigs) > 0 {
207+
logrus.WithField("configs", failedConfigs.UnsortedList()).Error("Failed configurations.")
208+
brachingFailure = true
209+
}
210+
211+
if brachingFailure {
212+
os.Exit(1)
213+
}
214+
}
215+
216+
func pushBranch(logger *logrus.Entry, remote *url.URL, futureBranch string, gitCmd gitCmd) (bool, error) {
217+
command := []string{"push", remote.String(), fmt.Sprintf("FETCH_HEAD:refs/heads/%s", futureBranch)}
218+
logger = logger.WithFields(logrus.Fields{"commands": fmt.Sprintf("git %s", strings.Join(command, " "))})
219+
if err := gitCmd(logger, command...); err != nil {
220+
tooShallowErr := strings.Contains(err.Error(), "Updates were rejected because the remote contains work that you do")
221+
if tooShallowErr {
222+
logger.Warn("Failed to push, trying a deeper clone...")
223+
return true, nil
224+
}
225+
return false, err
204226
}
227+
return false, nil
228+
}
229+
230+
func fetchDeeper(logger *logrus.Entry, remote *url.URL, gitCmd gitCmd, repoInfo *config.Info, depth int) error {
231+
command := []string{"fetch", "--depth", strconv.Itoa(depth), remote.String(), repoInfo.Branch}
232+
if err := gitCmd(logger, command...); err != nil {
233+
return err
234+
}
235+
return nil
205236
}
206237

207-
func executeGitCMDFactory(dir string) func(l *logrus.Entry, args ...string) error {
238+
func gitCmdFunc(dir string) gitCmd {
208239
return func(l *logrus.Entry, args ...string) error {
209240
l = l.WithField("commands", fmt.Sprintf("git %s", strings.Join(args, " ")))
210241
var b []byte

0 commit comments

Comments
 (0)