Skip to content

Commit 9c1d189

Browse files
Gonchik TsymzhitovGonchik Tsymzhitov
authored andcommitted
2 parents 8cdf58c + e19189d commit 9c1d189

File tree

9 files changed

+698
-180
lines changed

9 files changed

+698
-180
lines changed

atlassian/bitbucket.py

Lines changed: 452 additions & 164 deletions
Large diffs are not rendered by default.

atlassian/jira.py

Lines changed: 49 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,16 @@ def user_update_username(self, old_username, new_username):
139139
data = {"name": new_username}
140140
return self.user_update(old_username, data=data)
141141

142+
def user_update_email(self, username, email):
143+
"""
144+
Update user email for new domain changes
145+
:param username:
146+
:param email:
147+
:return:
148+
"""
149+
data = {'name': username, 'emailAddress': email}
150+
return self.user_update(username, data=data)
151+
142152
def user_create(self, username, email, display_name, password=None, notification=None):
143153
"""
144154
Create a user in Jira
@@ -219,16 +229,6 @@ def user_update_or_create_property_through_rest_point(self, username, key, value
219229
params = {'username': username, 'property': key, 'value': value}
220230
return self.get(url, params=params)
221231

222-
def user_update_email(self, username, email):
223-
"""
224-
Update user email for new domain changes
225-
:param username:
226-
:param email:
227-
:return:
228-
"""
229-
data = {'name': username, 'emailAddress': email}
230-
return self.user_update(username, data=data)
231-
232232
def user_deactivate(self, username):
233233
"""
234234
Disable user
@@ -2054,6 +2054,45 @@ def tempo_timesheets_get_worklogs(self, date_from=None, date_to=None, username=N
20542054
url = 'rest/tempo-timesheets/3/worklogs/'
20552055
return self.get(url, params=params)
20562056

2057+
def tempo_4_timesheets_find_worklogs(self, **params):
2058+
"""
2059+
Find existing worklogs with searching parameters.
2060+
NOTE: check if you are using correct types for the parameters!
2061+
:param from: string From Date
2062+
:param to: string To Date
2063+
:param worker: Array of strings
2064+
:param taskId: Array of integers
2065+
:param taskKey: Array of strings
2066+
:param projectId: Array of integers
2067+
:param projectKey: Array of strings
2068+
:param teamId: Array of integers
2069+
:param roleId: Array of integers
2070+
:param accountId: Array of integers
2071+
:param accountKey: Array of strings
2072+
:param filterId: Array of integers
2073+
:param customerId: Array of integers
2074+
:param categoryId: Array of integers
2075+
:param categoryTypeId: Array of integers
2076+
:param epicKey: Array of strings
2077+
:param updatedFrom: string
2078+
:param includeSubtasks: boolean
2079+
:param pageNo: integer
2080+
:param maxResults: integer
2081+
:param offset: integer
2082+
"""
2083+
2084+
url = "rest/tempo-timesheets/4/worklogs/search"
2085+
return self.post(url, data=params)
2086+
2087+
def tempo_timesheets_get_worklogs_by_issue(self, issue):
2088+
"""
2089+
Get Tempo timesheet worklog by issue key or id.
2090+
:param issue: Issue key or Id
2091+
:return:
2092+
"""
2093+
url = "rest/tempo-timesheets/4/worklogs/jira/issue/{issue}".format(issue=issue)
2094+
return self.get(url)
2095+
20572096
def tempo_timesheets_write_worklog(self, worker, started, time_spend_in_seconds, issue_id, comment=None):
20582097
"""
20592098
Log work for user

atlassian/rest_client.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ class AtlassianRestAPI(object):
2222
response = None
2323

2424
def __init__(self, url, username=None, password=None, timeout=60, api_root='rest/api', api_version='latest',
25-
verify_ssl=True, session=None, oauth=None, cookies=None, advanced_mode=None, kerberos=None):
25+
verify_ssl=True, session=None, oauth=None, cookies=None, advanced_mode=None, kerberos=None, standalone=True):
2626
if ('atlassian.net' in url or 'jira.com' in url) \
2727
and '/wiki' not in url \
2828
and self.__class__.__name__ in 'Confluence':

docs/bitbucket.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,9 @@ Groups and admins
100100
# All project administrators
101101
bitbucket.all_project_administrators()
102102
103+
# Get users. Use 'user_filter' parameter to get specific users.
104+
bitbucket.get_users(user_filter="username")
105+
103106
Manage code
104107
-----------
105108

@@ -139,6 +142,9 @@ Manage code
139142
# Add comment into pull request
140143
bitbucket.add_pull_request_comment(project, repository, pull_request_id, text)
141144
145+
# Create a new pull request between two branches.
146+
bitbucket.open_pull_request(source_project, source_repo, dest_project, dest_repo, source_branch, destination_branch, title, description)
147+
142148
# Get tags for related repo
143149
bitbucket.get_tags(project, repository, filter='', limit=99999)
144150

docs/jira.rst

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -188,19 +188,19 @@ Manage issues
188188
189189
# Set issue status by transition_id
190190
jira.set_issue_status_by_transition_id(issue_key, transition_id)
191-
191+
192192
# Get issue status
193193
jira.get_issue_status(issue_key)
194-
194+
195195
# Create or Update Issue Links
196196
jira.create_or_update_issue_remote_links(issue_key, link_url, title, global_id=None, relationship=None)
197-
197+
198198
# Get Issue Link by link ID
199199
jira.get_issue_remote_link_by_id(issue_key, link_id)
200-
200+
201201
# Update Issue Link by link ID
202202
jira.update_issue_remote_link_by_id(issue_key, link_id, url, title, global_id=None, relationship=None)
203-
203+
204204
# Delete Issue Links
205205
jira.delete_issue_remote_link_by_id(issue_key, link_id)
206206
@@ -275,3 +275,38 @@ Issue security schemes
275275
# user has the administrative permission.
276276
# Use only_levels=True for get the only levels entries
277277
jira.get_issue_security_scheme(scheme_id, only_levels=False)
278+
279+
TEMPO
280+
----------------------
281+
.. code-block:: python
282+
283+
# Find existing worklogs with the search parameters.
284+
# Look at the tempo docs for additional information:
285+
# https://www.tempo.io/server-api-documentation/timesheets#operation/searchWorklogs
286+
# NOTE: check if you are using correct types for the parameters!
287+
# :param from: string From Date
288+
# :param to: string To Date
289+
# :param worker: Array of strings
290+
# :param taskId: Array of integers
291+
# :param taskKey: Array of strings
292+
# :param projectId: Array of integers
293+
# :param projectKey: Array of strings
294+
# :param teamId: Array of integers
295+
# :param roleId: Array of integers
296+
# :param accountId: Array of integers
297+
# :param accountKey: Array of strings
298+
# :param filterId: Array of integers
299+
# :param customerId: Array of integers
300+
# :param categoryId: Array of integers
301+
# :param categoryTypeId: Array of integers
302+
# :param epicKey: Array of strings
303+
# :param updatedFrom: string
304+
# :param includeSubtasks: boolean
305+
# :param pageNo: integer
306+
# :param maxResults: integer
307+
# :param offset: integer
308+
jira.tempo_4_timesheets_find_worklogs(**params)
309+
310+
# :PRIVATE:
311+
# Get Tempo timesheet worklog by issue key or id.
312+
jira.tempo_timesheets_get_worklogs_by_issue(issue)

examples/bitbucket-users.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# coding=utf-8
2+
from atlassian import Bitbucket
3+
4+
5+
bitbucket = Bitbucket(
6+
url='http://localhost:7990',
7+
username='admin',
8+
password='admin')
9+
10+
data = bitbucket.get_users(user_filter="username")
11+
print(data)
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# coding=utf-8
2+
from atlassian import Confluence
3+
from datetime import datetime
4+
import logging
5+
6+
7+
confluence = Confluence(
8+
url='http://localhost:8090',
9+
username='admin',
10+
password='admin',
11+
)
12+
13+
logging.basicConfig(level=logging.DEBUG)
14+
15+
filename = "test_file.txt"
16+
with open(filename, "w") as f:
17+
f.write(str(datetime.utcnow()))
18+
19+
confluence.attach_file(filename, page_id="123456789")
20+
21+
link = """<p>
22+
<ac:link>
23+
<ri:attachment ri:filename="{}"/>
24+
</ac:link>
25+
</p>""".format(filename)
26+
27+
confluence.append_page(123456789, "Page Title", link)
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# coding=utf-8
2+
from atlassian import Jira
3+
from pprint import pprint
4+
import logging
5+
6+
jira = Jira(
7+
url='http://localhost:8080',
8+
username='admin',
9+
password='admin',
10+
advanced_mode=True # You can use it without advanced mode.
11+
)
12+
13+
logging.basicConfig(level=logging.DEBUG)
14+
# deprecated_issue_worklog = jira.tempo_timesheets_get_worklogs_by_issue("PROJ-1234")
15+
latest_issue_worklog = jira.tempo_4_timesheets_find_worklogs(taskKey=["PROJ-1234"])
16+
# pprint(deprecated_issue_worklog.json())
17+
pprint(latest_issue_worklog.json())
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
from atlassian import Jira
2+
from atlassian import Stash
3+
from var import config
4+
import logging
5+
import time
6+
7+
PROJECT_KEY = 'PROJ'
8+
REPOS = ['repo1', 'repo2']
9+
ACCEPTED_ISSUE_STATUSES = ["Closed", "Verified"]
10+
EXCLUDE_REPO_RULES = config.exclude_parameters
11+
LAST_COMMIT_CONDITION_IN_DAYS = 75
12+
ATLASSIAN_USER = config.JIRA_LOGIN
13+
ATLASSIAN_PASSWORD = config.JIRA_PASSWORD
14+
15+
logging.basicConfig(level=logging.ERROR)
16+
jira = Jira(
17+
url=config.JIRA_URL,
18+
username=ATLASSIAN_USER,
19+
password=ATLASSIAN_PASSWORD)
20+
21+
stash = Stash(
22+
url=config.STASH_URL,
23+
username=ATLASSIAN_USER,
24+
password=ATLASSIAN_PASSWORD
25+
)
26+
27+
flag = True
28+
time_now = int(time.time()) * 1000
29+
delta_for_time_ms = LAST_COMMIT_CONDITION_IN_DAYS * 24 * 60 * 60 * 1000
30+
commit_info_key = "com.atlassian.bitbucket.server.bitbucket-branch:latest-commit-metadata"
31+
out_going_pull_request = "com.atlassian.bitbucket.server.bitbucket-ref-metadata:outgoing-pull-request-metadata"
32+
branch_related_issues = "com.atlassian.bitbucket.server.bitbucket-jira:branch-list-jira-issues"
33+
34+
35+
def is_can_removed_branch(branch_candidate):
36+
branch_id_name = branch_candidate.get('id')
37+
# Just exclude exist mainstream branches
38+
if any(x in branch_id_name for x in EXCLUDE_REPO_RULES):
39+
print(branch.get('displayId') + " in exclusion list")
40+
return False
41+
# skip default branch maybe DevOps made configs in ui
42+
if branch_candidate.get('isDefault'):
43+
print(branch.get('displayId') + " is default")
44+
return False
45+
pull_request_info = ((branch_candidate.get('metadata') or {}).get(out_going_pull_request) or {})
46+
if pull_request_info.get('pullRequest') is not None or (pull_request_info.get('open') or 0) > 0:
47+
print(branch.get('displayId') + " has open PR")
48+
return False
49+
# skip branches without pull request info
50+
if pull_request_info is None or len(pull_request_info) == 0:
51+
print(branch.get('displayId') + " without pull request info")
52+
# return False
53+
54+
author_time_stamp = branch_candidate.get('metadata').get(commit_info_key).get('authorTimestamp')
55+
# check latest commit info
56+
if time_now - author_time_stamp < delta_for_time_ms:
57+
print(branch.get('displayId') + " is too early to remove")
58+
return False
59+
60+
# check issues statuses
61+
exclude = False
62+
issues_in_metadata = branch_candidate.get('metadata').get(branch_related_issues)
63+
for issue in issues_in_metadata:
64+
if jira.get_issue_status(issue.get('key')) not in ACCEPTED_ISSUE_STATUSES:
65+
print(branch.get('displayId') + " related issue has not Resolution ")
66+
return False
67+
# so branch can be removed
68+
return True
69+
70+
71+
if __name__ == '__main__':
72+
DRY_RUN = False
73+
log = open("candidate_to_remove.csv", "w")
74+
log.write("'Branch name', 'Latest commit', 'Related issues has Resolution'\n")
75+
for repository in REPOS:
76+
step = 0
77+
limit = 10
78+
while flag:
79+
branches = stash.get_branches(PROJECT_KEY, repository, start=step * limit, limit=limit,
80+
order_by='ALPHABETICAL')
81+
if len(branches) == 0:
82+
flag = False
83+
break
84+
for branch in branches:
85+
display_id = branch['displayId']
86+
committer_time_stamp = branch.get('metadata').get(commit_info_key).get('committerTimestamp') / 1000
87+
last_date_commit = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(committer_time_stamp))
88+
if is_can_removed_branch(branch):
89+
if not DRY_RUN:
90+
stash.delete_branch(project=PROJECT_KEY, repository=repository, name=display_id,
91+
end_point=branch['latestCommit'])
92+
log.write("{},{},{}\n".format(display_id, last_date_commit, True))
93+
step += 1
94+
log.close()
95+
print("Done")

0 commit comments

Comments
 (0)