saltext.github 1.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- saltext/github/__init__.py +31 -0
- saltext/github/modules/__init__.py +0 -0
- saltext/github/modules/github.py +1873 -0
- saltext/github/modules/github_org.py +667 -0
- saltext/github/modules/github_repo.py +1658 -0
- saltext/github/modules/github_user.py +75 -0
- saltext/github/resources/__init__.py +0 -0
- saltext/github/resources/github/__init__.py +251 -0
- saltext/github/resources/github/modules/__init__.py +0 -0
- saltext/github/resources/github/modules/actions.py +175 -0
- saltext/github/resources/github/modules/config.py +69 -0
- saltext/github/resources/github/modules/deploy_key.py +122 -0
- saltext/github/resources/github/modules/environment.py +241 -0
- saltext/github/resources/github/modules/grains.py +18 -0
- saltext/github/resources/github/modules/issue.py +157 -0
- saltext/github/resources/github/modules/label.py +161 -0
- saltext/github/resources/github/modules/milestone.py +103 -0
- saltext/github/resources/github/modules/pages.py +149 -0
- saltext/github/resources/github/modules/pull.py +90 -0
- saltext/github/resources/github/modules/repo.py +155 -0
- saltext/github/resources/github/modules/ruleset.py +144 -0
- saltext/github/resources/github/modules/saltutil.py +24 -0
- saltext/github/resources/github/modules/state.py +116 -0
- saltext/github/resources/github/modules/test.py +29 -0
- saltext/github/resources/github/states/__init__.py +0 -0
- saltext/github/resources/github/states/actions.py +117 -0
- saltext/github/resources/github/states/deploy_key.py +130 -0
- saltext/github/resources/github/states/environment.py +99 -0
- saltext/github/resources/github/states/label.py +71 -0
- saltext/github/resources/github/states/pages.py +92 -0
- saltext/github/resources/github/states/repo.py +108 -0
- saltext/github/resources/github/states/ruleset.py +81 -0
- saltext/github/states/__init__.py +0 -0
- saltext/github/states/github.py +966 -0
- saltext/github/states/github_org.py +369 -0
- saltext/github/states/github_repo.py +722 -0
- saltext/github/utils/__init__.py +72 -0
- saltext/github/utils/gh/__init__.py +14 -0
- saltext/github/utils/gh/actions.py +195 -0
- saltext/github/utils/gh/cache.py +126 -0
- saltext/github/utils/gh/client.py +534 -0
- saltext/github/utils/gh/deploy_keys.py +121 -0
- saltext/github/utils/gh/environments.py +271 -0
- saltext/github/utils/gh/exceptions.py +28 -0
- saltext/github/utils/gh/grains_files.py +366 -0
- saltext/github/utils/gh/issues.py +193 -0
- saltext/github/utils/gh/labels.py +142 -0
- saltext/github/utils/gh/members.py +157 -0
- saltext/github/utils/gh/milestones.py +122 -0
- saltext/github/utils/gh/pages.py +128 -0
- saltext/github/utils/gh/profile.py +458 -0
- saltext/github/utils/gh/pulls.py +99 -0
- saltext/github/utils/gh/repos.py +465 -0
- saltext/github/utils/gh/resource.py +35 -0
- saltext/github/utils/gh/rulesets.py +191 -0
- saltext/github/utils/gh/statecores/__init__.py +70 -0
- saltext/github/utils/gh/statecores/actions.py +180 -0
- saltext/github/utils/gh/statecores/deploy_keys.py +241 -0
- saltext/github/utils/gh/statecores/environments.py +212 -0
- saltext/github/utils/gh/statecores/labels.py +116 -0
- saltext/github/utils/gh/statecores/pages.py +177 -0
- saltext/github/utils/gh/statecores/repo.py +249 -0
- saltext/github/utils/gh/statecores/rulesets.py +115 -0
- saltext/github/utils/gh/teams.py +375 -0
- saltext/github/utils/gh/users.py +87 -0
- saltext/github/version.py +1 -0
- saltext_github-1.1.0.dist-info/METADATA +151 -0
- saltext_github-1.1.0.dist-info/RECORD +73 -0
- saltext_github-1.1.0.dist-info/WHEEL +5 -0
- saltext_github-1.1.0.dist-info/entry_points.txt +2 -0
- saltext_github-1.1.0.dist-info/licenses/LICENSE +201 -0
- saltext_github-1.1.0.dist-info/licenses/NOTICE +10 -0
- saltext_github-1.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Operations on GitHub repository issues.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import logging
|
|
6
|
+
|
|
7
|
+
log = logging.getLogger(__name__)
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def get(conn, repo_name, number, *, owner=None):
|
|
11
|
+
"""
|
|
12
|
+
Return the raw data of a single issue.
|
|
13
|
+
|
|
14
|
+
conn
|
|
15
|
+
:class:`~saltext.github.utils.gh.client.GitHubConnection` to use.
|
|
16
|
+
|
|
17
|
+
repo_name
|
|
18
|
+
Repository the issue belongs to.
|
|
19
|
+
|
|
20
|
+
number
|
|
21
|
+
Issue number to retrieve.
|
|
22
|
+
|
|
23
|
+
owner
|
|
24
|
+
Owner of the repository. Defaults to the connection's owner.
|
|
25
|
+
"""
|
|
26
|
+
return conn.repo_query(owner, repo_name, "issues", str(number))
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def get_comments(conn, repo_name, number, since=None, *, owner=None):
|
|
30
|
+
"""
|
|
31
|
+
Return the raw comment data for a single issue.
|
|
32
|
+
|
|
33
|
+
conn
|
|
34
|
+
:class:`~saltext.github.utils.gh.client.GitHubConnection` to use.
|
|
35
|
+
|
|
36
|
+
repo_name
|
|
37
|
+
Repository the issue belongs to.
|
|
38
|
+
|
|
39
|
+
number
|
|
40
|
+
Issue number whose comments to retrieve.
|
|
41
|
+
|
|
42
|
+
since
|
|
43
|
+
Only comments updated at or after this time are returned. This is a
|
|
44
|
+
timestamp in ISO 8601 format: ``YYYY-MM-DDTHH:MM:SSZ``.
|
|
45
|
+
|
|
46
|
+
owner
|
|
47
|
+
Owner of the repository. Defaults to the connection's owner.
|
|
48
|
+
"""
|
|
49
|
+
params = {}
|
|
50
|
+
if since:
|
|
51
|
+
params["since"] = since
|
|
52
|
+
return conn.repo_query(
|
|
53
|
+
owner,
|
|
54
|
+
*(repo_name, "issues", str(number), "comments"),
|
|
55
|
+
params=params,
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def list_all(
|
|
60
|
+
conn,
|
|
61
|
+
repo_name,
|
|
62
|
+
*,
|
|
63
|
+
milestone=None,
|
|
64
|
+
state="open",
|
|
65
|
+
assignee=None,
|
|
66
|
+
creator=None,
|
|
67
|
+
mentioned=None,
|
|
68
|
+
labels=None,
|
|
69
|
+
sort="created",
|
|
70
|
+
direction="desc",
|
|
71
|
+
since=None,
|
|
72
|
+
per_page=None,
|
|
73
|
+
owner=None,
|
|
74
|
+
):
|
|
75
|
+
"""
|
|
76
|
+
Return the raw data of all issues in a repository matching the search
|
|
77
|
+
options. Pull requests are excluded.
|
|
78
|
+
|
|
79
|
+
conn
|
|
80
|
+
:class:`~saltext.github.utils.gh.client.GitHubConnection` to use.
|
|
81
|
+
|
|
82
|
+
repo_name
|
|
83
|
+
Repository whose issues to list.
|
|
84
|
+
|
|
85
|
+
milestone
|
|
86
|
+
Number of a GitHub milestone, or a string of either ``*`` or ``none``.
|
|
87
|
+
|
|
88
|
+
state
|
|
89
|
+
Filter returned issues by their state. Can be either ``open``,
|
|
90
|
+
``closed``, or ``all``. Default is ``open``.
|
|
91
|
+
|
|
92
|
+
assignee
|
|
93
|
+
Filter returned issues by assigned user handle. Pass ``none``
|
|
94
|
+
(as a string) for issues with no assigned user or ``*`` for
|
|
95
|
+
issues assigned to any user.
|
|
96
|
+
|
|
97
|
+
creator
|
|
98
|
+
Filter by the username that created the issue.
|
|
99
|
+
|
|
100
|
+
mentioned
|
|
101
|
+
Filter issues for a user that's mentioned in the issue.
|
|
102
|
+
|
|
103
|
+
labels
|
|
104
|
+
Filter issues by associated labels. String of comma separated
|
|
105
|
+
label names. For example, ``bug,ui,@high``.
|
|
106
|
+
|
|
107
|
+
sort
|
|
108
|
+
Field to sort results by. Either ``created``, ``updated``, or
|
|
109
|
+
``comments``. Default is ``created``.
|
|
110
|
+
|
|
111
|
+
direction
|
|
112
|
+
Sort direction. Either ``asc`` or ``desc``. Default is ``desc``.
|
|
113
|
+
|
|
114
|
+
since
|
|
115
|
+
Only list issues updated at or after this time. This is a
|
|
116
|
+
timestamp in ISO 8601 format: ``YYYY-MM-DDTHH:MM:SSZ``.
|
|
117
|
+
|
|
118
|
+
per_page
|
|
119
|
+
Pagination size, maximum 100.
|
|
120
|
+
|
|
121
|
+
owner
|
|
122
|
+
Owner of the repository. Defaults to the connection's owner.
|
|
123
|
+
"""
|
|
124
|
+
params = {}
|
|
125
|
+
|
|
126
|
+
# Build API arguments, as necessary.
|
|
127
|
+
if milestone:
|
|
128
|
+
params["milestone"] = milestone
|
|
129
|
+
if assignee:
|
|
130
|
+
params["assignee"] = assignee
|
|
131
|
+
if creator:
|
|
132
|
+
params["creator"] = creator
|
|
133
|
+
if mentioned:
|
|
134
|
+
params["mentioned"] = mentioned
|
|
135
|
+
if labels:
|
|
136
|
+
params["labels"] = labels
|
|
137
|
+
if since:
|
|
138
|
+
params["since"] = since
|
|
139
|
+
if per_page:
|
|
140
|
+
params["per_page"] = per_page
|
|
141
|
+
|
|
142
|
+
# Only pass the following API args if they're not the defaults listed.
|
|
143
|
+
if state and state != "open":
|
|
144
|
+
params["state"] = state
|
|
145
|
+
if sort and sort != "created":
|
|
146
|
+
params["sort"] = sort
|
|
147
|
+
if direction and direction != "desc":
|
|
148
|
+
params["direction"] = direction
|
|
149
|
+
|
|
150
|
+
issues = conn.repo_query(owner, repo_name, "issues", params=params)
|
|
151
|
+
|
|
152
|
+
# Pull requests are included in the issue list from GitHub.
|
|
153
|
+
# Let's not include those in the return.
|
|
154
|
+
return [issue for issue in issues if not issue.get("pull_request")]
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
def format_issue(issue):
|
|
158
|
+
"""
|
|
159
|
+
Format API return information into a more manageable
|
|
160
|
+
and useful dictionary for issue information.
|
|
161
|
+
|
|
162
|
+
Legacy function, only used by deprecated callers.
|
|
163
|
+
|
|
164
|
+
issue
|
|
165
|
+
Issue to format.
|
|
166
|
+
"""
|
|
167
|
+
ret = {
|
|
168
|
+
"id": issue.get("id"),
|
|
169
|
+
"issue_number": issue.get("number"),
|
|
170
|
+
"state": issue.get("state"),
|
|
171
|
+
"title": issue.get("title"),
|
|
172
|
+
"user": issue.get("user").get("login"),
|
|
173
|
+
"html_url": issue.get("html_url"),
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
assignee = issue.get("assignee")
|
|
177
|
+
if assignee:
|
|
178
|
+
assignee = assignee.get("login")
|
|
179
|
+
|
|
180
|
+
labels = issue.get("labels")
|
|
181
|
+
label_names = []
|
|
182
|
+
for label in labels:
|
|
183
|
+
label_names.append(label.get("name"))
|
|
184
|
+
|
|
185
|
+
milestone = issue.get("milestone")
|
|
186
|
+
if milestone:
|
|
187
|
+
milestone = milestone.get("title")
|
|
188
|
+
|
|
189
|
+
ret["assignee"] = assignee
|
|
190
|
+
ret["labels"] = label_names
|
|
191
|
+
ret["milestone"] = milestone
|
|
192
|
+
|
|
193
|
+
return ret
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Operations on GitHub repository (issue) labels.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import logging
|
|
6
|
+
from urllib.parse import quote
|
|
7
|
+
|
|
8
|
+
from saltext.github.utils import filter_unset
|
|
9
|
+
|
|
10
|
+
log = logging.getLogger(__name__)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def _path(*suffix):
|
|
14
|
+
# Label names can contain characters that are invalid in URL paths
|
|
15
|
+
return ["labels"] + [quote(str(segment), safe="") for segment in suffix]
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def normalize_color(color):
|
|
19
|
+
"""
|
|
20
|
+
Normalize a label color for comparisons: lowercase, no leading ``#``.
|
|
21
|
+
|
|
22
|
+
color
|
|
23
|
+
Hexadecimal color code to normalize.
|
|
24
|
+
"""
|
|
25
|
+
if color is None:
|
|
26
|
+
return None
|
|
27
|
+
return color.lstrip("#").lower()
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def list_all(conn, repo_name, *, owner=None):
|
|
31
|
+
"""
|
|
32
|
+
Return all labels of a repository.
|
|
33
|
+
|
|
34
|
+
conn
|
|
35
|
+
:class:`~saltext.github.utils.gh.client.GitHubConnection` to use.
|
|
36
|
+
|
|
37
|
+
repo_name
|
|
38
|
+
Repository name.
|
|
39
|
+
|
|
40
|
+
owner
|
|
41
|
+
Owner of the repository. Defaults to the connection's owner.
|
|
42
|
+
"""
|
|
43
|
+
return conn.repo_query(owner, repo_name, "labels")
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def get(conn, repo_name, name, *, owner=None):
|
|
47
|
+
"""
|
|
48
|
+
Return the data of a single label.
|
|
49
|
+
|
|
50
|
+
conn
|
|
51
|
+
:class:`~saltext.github.utils.gh.client.GitHubConnection` to use.
|
|
52
|
+
|
|
53
|
+
repo_name
|
|
54
|
+
Repository name.
|
|
55
|
+
|
|
56
|
+
name
|
|
57
|
+
Label name.
|
|
58
|
+
|
|
59
|
+
owner
|
|
60
|
+
Owner of the repository. Defaults to the connection's owner.
|
|
61
|
+
|
|
62
|
+
Raises :class:`~saltext.github.utils.gh.exceptions.GitHubNotFoundError`
|
|
63
|
+
if the label does not exist.
|
|
64
|
+
"""
|
|
65
|
+
return conn.repo_query(owner, repo_name, *_path(name))
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def create(conn, repo_name, name, *, color=None, description=None, owner=None):
|
|
69
|
+
"""
|
|
70
|
+
Create a label in a repository. Returns the data of the created label.
|
|
71
|
+
|
|
72
|
+
conn
|
|
73
|
+
:class:`~saltext.github.utils.gh.client.GitHubConnection` to use.
|
|
74
|
+
|
|
75
|
+
repo_name
|
|
76
|
+
Repository name.
|
|
77
|
+
|
|
78
|
+
name
|
|
79
|
+
Label name.
|
|
80
|
+
|
|
81
|
+
color
|
|
82
|
+
Hexadecimal color code for the label, without the leading ``#``.
|
|
83
|
+
If unset, GitHub assigns a random one.
|
|
84
|
+
|
|
85
|
+
description
|
|
86
|
+
Short description of the label.
|
|
87
|
+
|
|
88
|
+
owner
|
|
89
|
+
Owner of the repository. Defaults to the connection's owner.
|
|
90
|
+
"""
|
|
91
|
+
data = filter_unset({"name": name, "color": normalize_color(color), "description": description})
|
|
92
|
+
return conn.repo_query(owner, repo_name, "labels", method="POST", data=data)
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def update(conn, repo_name, name, *, new_name=None, color=None, description=None, owner=None):
|
|
96
|
+
"""
|
|
97
|
+
Update an existing label. Returns the data of the updated label.
|
|
98
|
+
|
|
99
|
+
conn
|
|
100
|
+
:class:`~saltext.github.utils.gh.client.GitHubConnection` to use.
|
|
101
|
+
|
|
102
|
+
repo_name
|
|
103
|
+
Repository name.
|
|
104
|
+
|
|
105
|
+
name
|
|
106
|
+
Current label name.
|
|
107
|
+
|
|
108
|
+
new_name
|
|
109
|
+
New name for the label.
|
|
110
|
+
|
|
111
|
+
color
|
|
112
|
+
Hexadecimal color code for the label, without the leading ``#``.
|
|
113
|
+
|
|
114
|
+
description
|
|
115
|
+
Short description of the label.
|
|
116
|
+
|
|
117
|
+
owner
|
|
118
|
+
Owner of the repository. Defaults to the connection's owner.
|
|
119
|
+
"""
|
|
120
|
+
data = filter_unset(
|
|
121
|
+
{"new_name": new_name, "color": normalize_color(color), "description": description}
|
|
122
|
+
)
|
|
123
|
+
return conn.repo_query(owner, repo_name, *_path(name), method="PATCH", data=data)
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def delete(conn, repo_name, name, *, owner=None):
|
|
127
|
+
"""
|
|
128
|
+
Delete a label from a repository.
|
|
129
|
+
|
|
130
|
+
conn
|
|
131
|
+
:class:`~saltext.github.utils.gh.client.GitHubConnection` to use.
|
|
132
|
+
|
|
133
|
+
repo_name
|
|
134
|
+
Repository name.
|
|
135
|
+
|
|
136
|
+
name
|
|
137
|
+
Label name.
|
|
138
|
+
|
|
139
|
+
owner
|
|
140
|
+
Owner of the repository. Defaults to the connection's owner.
|
|
141
|
+
"""
|
|
142
|
+
conn.repo_query(owner, repo_name, *_path(name), method="DELETE")
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Operations on GitHub organization members.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import logging
|
|
6
|
+
|
|
7
|
+
from github.GithubException import UnknownObjectException
|
|
8
|
+
|
|
9
|
+
from saltext.github.utils.gh.client import api_request
|
|
10
|
+
|
|
11
|
+
log = logging.getLogger(__name__)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@api_request
|
|
15
|
+
def list_all(conn, *, owner=None, ignore_cache=False):
|
|
16
|
+
"""
|
|
17
|
+
Return the logins of all members of an organization (cached).
|
|
18
|
+
|
|
19
|
+
conn
|
|
20
|
+
:class:`~saltext.github.utils.gh.client.GitHubConnection` to use.
|
|
21
|
+
|
|
22
|
+
owner
|
|
23
|
+
Organization to target. Defaults to the connection's owner.
|
|
24
|
+
|
|
25
|
+
ignore_cache
|
|
26
|
+
Bypass the cached member list.
|
|
27
|
+
"""
|
|
28
|
+
owner = owner or conn.owner
|
|
29
|
+
key = ("members", owner.lower())
|
|
30
|
+
if key not in conn.cache or ignore_cache:
|
|
31
|
+
conn.cache[key] = [member.login for member in conn.get_org(owner).get_members()]
|
|
32
|
+
return conn.cache[key]
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
@api_request
|
|
36
|
+
def get_info(conn, login, *, owner=None):
|
|
37
|
+
"""
|
|
38
|
+
Return information about a user, including their organization
|
|
39
|
+
membership state.
|
|
40
|
+
|
|
41
|
+
conn
|
|
42
|
+
:class:`~saltext.github.utils.gh.client.GitHubConnection` to use.
|
|
43
|
+
|
|
44
|
+
login
|
|
45
|
+
User handle to look up.
|
|
46
|
+
|
|
47
|
+
owner
|
|
48
|
+
Organization to target. Defaults to the connection's owner.
|
|
49
|
+
|
|
50
|
+
Raises :class:`~saltext.github.utils.gh.exceptions.GitHubNotFoundError`
|
|
51
|
+
if the user does not exist.
|
|
52
|
+
"""
|
|
53
|
+
user = conn.client.get_user(login)
|
|
54
|
+
|
|
55
|
+
ret = {
|
|
56
|
+
"company": user.company,
|
|
57
|
+
"created_at": user.created_at,
|
|
58
|
+
"email": user.email,
|
|
59
|
+
"html_url": user.html_url,
|
|
60
|
+
"id": user.id,
|
|
61
|
+
"login": user.login,
|
|
62
|
+
"name": user.name,
|
|
63
|
+
"type": user.type,
|
|
64
|
+
"url": user.url,
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
org = conn.get_org(owner)
|
|
68
|
+
try:
|
|
69
|
+
membership = user.get_organization_membership(org)
|
|
70
|
+
except UnknownObjectException:
|
|
71
|
+
ret["membership_state"] = "nonexistent"
|
|
72
|
+
ret["in_org"] = False
|
|
73
|
+
return ret
|
|
74
|
+
|
|
75
|
+
ret["in_org"] = org.has_in_members(user)
|
|
76
|
+
ret["membership_state"] = membership.state
|
|
77
|
+
|
|
78
|
+
return ret
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
@api_request
|
|
82
|
+
def invite(conn, login, *, owner=None):
|
|
83
|
+
"""
|
|
84
|
+
Invite a user into the organization. Returns whether the resulting
|
|
85
|
+
membership state is ``pending``.
|
|
86
|
+
|
|
87
|
+
conn
|
|
88
|
+
:class:`~saltext.github.utils.gh.client.GitHubConnection` to use.
|
|
89
|
+
|
|
90
|
+
login
|
|
91
|
+
User handle to invite.
|
|
92
|
+
|
|
93
|
+
owner
|
|
94
|
+
Organization to target. Defaults to the connection's owner.
|
|
95
|
+
|
|
96
|
+
Raises :class:`~saltext.github.utils.gh.exceptions.GitHubNotFoundError`
|
|
97
|
+
if the user does not exist.
|
|
98
|
+
"""
|
|
99
|
+
user = conn.client.get_user(login)
|
|
100
|
+
|
|
101
|
+
# There is no public method that also returns the resulting membership state
|
|
102
|
+
_, data = conn.client.requester.requestJsonAndCheck(
|
|
103
|
+
"PUT", conn.get_org(owner).url + "/memberships/" + user.login
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
return data.get("state") == "pending"
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
@api_request
|
|
110
|
+
def remove(conn, login, *, owner=None):
|
|
111
|
+
"""
|
|
112
|
+
Remove a user from the organization (if they are a member).
|
|
113
|
+
|
|
114
|
+
conn
|
|
115
|
+
:class:`~saltext.github.utils.gh.client.GitHubConnection` to use.
|
|
116
|
+
|
|
117
|
+
login
|
|
118
|
+
User handle to remove.
|
|
119
|
+
|
|
120
|
+
owner
|
|
121
|
+
Organization to target. Defaults to the connection's owner.
|
|
122
|
+
|
|
123
|
+
Raises :class:`~saltext.github.utils.gh.exceptions.GitHubNotFoundError`
|
|
124
|
+
if the user does not exist.
|
|
125
|
+
"""
|
|
126
|
+
user = conn.client.get_user(login)
|
|
127
|
+
|
|
128
|
+
org = conn.get_org(owner)
|
|
129
|
+
if org.has_in_members(user):
|
|
130
|
+
org.remove_from_members(user)
|
|
131
|
+
|
|
132
|
+
return True
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
@api_request
|
|
136
|
+
def list_without_mfa(conn, *, owner=None, ignore_cache=False):
|
|
137
|
+
"""
|
|
138
|
+
Return the logins (lowercase) of all organization members without
|
|
139
|
+
MFA turned on (cached).
|
|
140
|
+
|
|
141
|
+
conn
|
|
142
|
+
:class:`~saltext.github.utils.gh.client.GitHubConnection` to use.
|
|
143
|
+
|
|
144
|
+
owner
|
|
145
|
+
Organization to target. Defaults to the connection's owner.
|
|
146
|
+
|
|
147
|
+
ignore_cache
|
|
148
|
+
Bypass the cached member list.
|
|
149
|
+
"""
|
|
150
|
+
owner = owner or conn.owner
|
|
151
|
+
key = ("members_without_mfa", owner.lower())
|
|
152
|
+
if key not in conn.cache or ignore_cache:
|
|
153
|
+
conn.cache[key] = [
|
|
154
|
+
member.login.lower()
|
|
155
|
+
for member in conn.get_org(owner).get_members(filter_="2fa_disabled")
|
|
156
|
+
]
|
|
157
|
+
return conn.cache[key]
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Operations on GitHub repository milestones.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import logging
|
|
6
|
+
|
|
7
|
+
from saltext.github.utils.gh.exceptions import GitHubNotFoundError
|
|
8
|
+
|
|
9
|
+
log = logging.getLogger(__name__)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def get(conn, repo_name, number, *, owner=None):
|
|
13
|
+
"""
|
|
14
|
+
Return the raw data of a single milestone.
|
|
15
|
+
|
|
16
|
+
conn
|
|
17
|
+
:class:`~saltext.github.utils.gh.client.GitHubConnection` to use.
|
|
18
|
+
|
|
19
|
+
repo_name
|
|
20
|
+
Repository the milestone belongs to.
|
|
21
|
+
|
|
22
|
+
number
|
|
23
|
+
Milestone number to retrieve.
|
|
24
|
+
|
|
25
|
+
owner
|
|
26
|
+
Owner of the repository. Defaults to the connection's owner.
|
|
27
|
+
"""
|
|
28
|
+
return conn.repo_query(owner, repo_name, "milestones", str(number))
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def list_all(
|
|
32
|
+
conn,
|
|
33
|
+
repo_name,
|
|
34
|
+
*,
|
|
35
|
+
state="open",
|
|
36
|
+
sort="due_on",
|
|
37
|
+
direction="asc",
|
|
38
|
+
per_page=None,
|
|
39
|
+
owner=None,
|
|
40
|
+
):
|
|
41
|
+
"""
|
|
42
|
+
Return the raw data of all milestones in a repository matching the
|
|
43
|
+
search options.
|
|
44
|
+
|
|
45
|
+
conn
|
|
46
|
+
:class:`~saltext.github.utils.gh.client.GitHubConnection` to use.
|
|
47
|
+
|
|
48
|
+
repo_name
|
|
49
|
+
Repository whose milestones to list.
|
|
50
|
+
|
|
51
|
+
state
|
|
52
|
+
Filter milestones by their state. Either ``open``, ``closed``,
|
|
53
|
+
or ``all``. Default is ``open``.
|
|
54
|
+
|
|
55
|
+
sort
|
|
56
|
+
Field to sort results by. Either ``due_on`` or ``completeness``.
|
|
57
|
+
Default is ``due_on``.
|
|
58
|
+
|
|
59
|
+
direction
|
|
60
|
+
Sort direction. Either ``asc`` or ``desc``. Default is ``asc``.
|
|
61
|
+
|
|
62
|
+
per_page
|
|
63
|
+
Pagination size, maximum 100.
|
|
64
|
+
|
|
65
|
+
owner
|
|
66
|
+
Owner of the repository. Defaults to the connection's owner.
|
|
67
|
+
"""
|
|
68
|
+
params = {}
|
|
69
|
+
|
|
70
|
+
if per_page:
|
|
71
|
+
params["per_page"] = per_page
|
|
72
|
+
|
|
73
|
+
# Only pass the following API args if they're not the defaults listed.
|
|
74
|
+
if state and state != "open":
|
|
75
|
+
params["state"] = state
|
|
76
|
+
if sort and sort != "due_on":
|
|
77
|
+
params["sort"] = sort
|
|
78
|
+
if direction and direction != "asc":
|
|
79
|
+
params["direction"] = direction
|
|
80
|
+
|
|
81
|
+
return conn.repo_query(owner, repo_name, "milestones", params=params)
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def find_by_title(conn, repo_name, title, *, owner=None):
|
|
85
|
+
"""
|
|
86
|
+
Return a milestone by its title. Since the GitHub API only addresses
|
|
87
|
+
milestones by number, this searches the complete list.
|
|
88
|
+
|
|
89
|
+
conn
|
|
90
|
+
:class:`~saltext.github.utils.gh.client.GitHubConnection` to use.
|
|
91
|
+
|
|
92
|
+
repo_name
|
|
93
|
+
Name of the repository the milestone is part of.
|
|
94
|
+
|
|
95
|
+
title
|
|
96
|
+
Title of the milestone.
|
|
97
|
+
|
|
98
|
+
owner
|
|
99
|
+
Owner of the repository. Defaults to the connection's owner.
|
|
100
|
+
|
|
101
|
+
Raises :class:`~saltext.github.utils.gh.exceptions.GitHubNotFoundError`
|
|
102
|
+
if no milestone carries the title.
|
|
103
|
+
"""
|
|
104
|
+
milestones = list_all(conn, repo_name, state="all", owner=owner)
|
|
105
|
+
for milestone in milestones or []:
|
|
106
|
+
if milestone.get("title") == title:
|
|
107
|
+
return milestone
|
|
108
|
+
raise GitHubNotFoundError(f"Milestone {title} was not found in repository {repo_name}.")
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def format_milestone(milestone):
|
|
112
|
+
"""
|
|
113
|
+
Trim milestone data to the fields that are useful in (CLI) output.
|
|
114
|
+
|
|
115
|
+
milestone
|
|
116
|
+
Milestone to format.
|
|
117
|
+
"""
|
|
118
|
+
return {
|
|
119
|
+
key: value
|
|
120
|
+
for key, value in milestone.items()
|
|
121
|
+
if key not in ("creator", "html_url", "labels_url")
|
|
122
|
+
}
|