-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpush_rules.go
127 lines (104 loc) · 3.68 KB
/
push_rules.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
package config
import (
"fmt"
"net/http"
"os"
"github.com/xanzy/go-gitlab"
"gitlab.com/tozd/go/errors"
)
func getPushRules(client *gitlab.Client, project string) (map[string]interface{}, errors.E) {
u := fmt.Sprintf("projects/%s/push_rule", gitlab.PathEscape(project))
req, err := client.NewRequest(http.MethodGet, u, nil, nil)
if err != nil {
return nil, errors.WithMessage(err, "failed to get push rules")
}
pushRules := map[string]interface{}{}
_, err = client.Do(req, &pushRules)
if err != nil {
return nil, errors.WithMessage(err, "failed to get push rules")
}
return pushRules, nil
}
// getPushRules populates configuration struct with GitLab's project's
// push rules available from GitLab push rules API endpoint.
func (c *GetCommand) getPushRules(client *gitlab.Client, configuration *Configuration) (bool, errors.E) { //nolint:unparam
fmt.Fprintf(os.Stderr, "Getting push rules...\n")
configuration.PushRules = map[string]interface{}{}
descriptions, errE := getPushRulesDescriptions(c.DocsRef)
if errE != nil {
return false, errE
}
pushRules, errE := getPushRules(client, c.Project)
if errE != nil {
return false, errE
}
// Only retain those keys which can be edited through the API
// (which are those available in descriptions).
for key := range pushRules {
_, ok := descriptions[key]
if !ok {
delete(pushRules, key)
}
}
// Add comments for keys. We process these keys before writing YAML out.
describeKeys(pushRules, descriptions)
configuration.PushRules = pushRules
return false, nil
}
// parsePushRulesDocumentation parses GitLab's documentation in Markdown for
// push rules API endpoint and extracts description of fields used to describe
// payload for project's push rules.
func parsePushRulesDocumentation(input []byte) (map[string]string, errors.E) {
return parseTable(input, "Edit project push rule", nil)
}
// getPushRulesDescriptions obtains description of fields used to describe payload for
// project's push rules from GitLab's documentation for push rules API endpoint.
func getPushRulesDescriptions(gitRef string) (map[string]string, errors.E) {
data, err := downloadFile(fmt.Sprintf("https://gitlab.com/gitlab-org/gitlab/-/raw/%s/doc/api/projects.md", gitRef))
if err != nil {
return nil, errors.WithMessage(err, "failed to get push rules descriptions")
}
return parsePushRulesDocumentation(data)
}
// updatePushRules updates GitLab project's push rules
// using GitLab push rules API endpoint based on the configuration struct.
func (c *SetCommand) updatePushRules(client *gitlab.Client, configuration *Configuration) errors.E {
if configuration.PushRules == nil {
return nil
}
fmt.Fprintf(os.Stderr, "Updating push rules...\n")
pushRules, errE := getPushRules(client, c.Project)
if errE != nil {
return errE
}
if len(configuration.PushRules) == 0 {
// The call is not really idempotent, so we delete rules only if they exist.
// See: https://gitlab.com/gitlab-org/gitlab/-/issues/427352
if len(pushRules) > 0 {
_, err := client.Projects.DeleteProjectPushRule(c.Project)
if err != nil {
return errors.WithMessage(err, "failed to delete push rules")
}
}
return nil
}
var method string
var description string
if len(pushRules) == 0 {
method = http.MethodPost
description = "create"
} else {
method = http.MethodPut
description = "update"
}
u := fmt.Sprintf("projects/%s/push_rule", gitlab.PathEscape(c.Project))
req, err := client.NewRequest(method, u, configuration.PushRules, nil)
if err != nil {
return errors.WithMessagef(err, "failed to %s push rules", description)
}
_, err = client.Do(req, nil)
if err != nil {
return errors.WithMessagef(err, "failed to %s push rules", description)
}
return nil
}