/
archive_issues.py
143 lines (123 loc) · 6.06 KB
/
archive_issues.py
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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
# OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
from api import StreamClient, ObjCode, AtTaskObject
class MoveIssues(object):
def __init__(self, api_key: str, api_path: str, move_from: str, move_to: str, age: int):
"""
Move Issues Init
:param api_key: The api key for auth user
:param api_path: Path to the api
:param move_from: ID string of project to move tasks from
:param move_to: ID string of project to move tasks from
:param age: Find issues with an actual completion date greater than this value in months.
"""
self.api_key = api_key
self.api_path = api_path
self.move_from = move_from
self.move_to = move_to
self.age = age
# Can't bluk move more than 100 elements as per API restrictions
self.max_results = 100
self.completion_date_str = "$$TODAY-{age}m".format(age=self.age)
self.client = StreamClient(self.api_path, self.api_key)
def go(self):
"""
Starts the moving process.
"""
results_len = 1 # Just something to get us started
while results_len > 0:
issues = self.find_issues()
results_len = len(issues)
iss_move_count = self.move_issues(issues)
if results_len > 0:
results_str = "Moved {result_count} items".format(result_count=iss_move_count)
print(results_str)
print("Operation complete")
def find_issues(self):
"""
Finds issues in 'from' project to be moved.
:return: a list of issues that meet the criteria
"""
params = {
"$$LIMIT": self.max_results,
"projectID": self.move_from,
"projectID_Mod": "in",
"actualCompletionDate": self.completion_date_str,
"actualCompletionDate_Mod": "lte"
}
fields = {}
results = AtTaskObject(self.client.search(ObjCode.ISSUE, params, fields))
return results.data
def move_issues(self, data) -> int:
"""
Moves issues between projects
:param data: list of issues
:return: count of issues moved
"""
counter = 0
for item in data:
# Get the ID number
uid = item['ID']
params = {'projectID': self.move_to}
AtTaskObject(self.client.action(ObjCode.ISSUE, 'move', params, objid=uid))
print(".", end="", flush=True)
counter += 1
return counter
def get_proj_name(self, proj_id: str):
"""
Gets the name of a project from ID
:param proj_id: ID number of the project to get the name of
:return: Name of the project
"""
results = AtTaskObject(self.client.get(ObjCode.PROJECT, proj_id))
return results.data['name']
def get_number_of_issues_to_move(self):
"""
Get's a count of the number of issues to be moved
:return: a count of the number of issues to be moved
"""
params = {
"projectID": self.move_from,
"projectID_Mod": "in",
"actualCompletionDate": self.completion_date_str,
"actualCompletionDate_Mod": "lte"
}
results = AtTaskObject(self.client.report(ObjCode.ISSUE, params, 'sum'))
return results.data['dcount_ID']
user_agreement = 'THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE \n' \
'WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR \n' \
'COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR \n' \
'OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE \n.' \
'AGREE? (Y / N)'
ua = str(input(user_agreement)).lower()
if ua == "y":
sub_domain = input("Enter the sub domain: ")
live_server = 'https://{sub_domain}.attask-ondemand.com/attask/api/v4.0/'.format(sub_domain=sub_domain)
sandbox = 'https://{sub_domain}.attasksandbox.com/attask/api/v4.0/'.format(sub_domain=sub_domain)
api_path = live_server if input("Select 's' for sandbox or 'l' for live: ") == "l" else sandbox
api_key = input("Enter API Key: ")
age = int(input("Archive issues older than ___ months (whole months only): "))
move_from = input("Enter ID number of queue to move from: ")
move_to = input("Enter ID number of queue to move to: ")
if api_key != "" and api_path != "" and age > 0 and move_to != "" and move_from != "":
mv = MoveIssues(api_key, api_path, move_from, move_to, age)
from_name = mv.get_proj_name(move_from)
to_name = mv.get_proj_name(move_to)
iss_count = mv.get_number_of_issues_to_move()
ready_msg = "*********************************************\n\n" \
"NOTICE: This operation will move {iss_count} issues.\n\n" \
"I'm ready to start moving issues older than {age} months \n" \
"from project {from_name} to {to_name}. \n" \
"Should I proceed? (y/n)".format(iss_count=iss_count,
age=age,
from_name=from_name,
to_name=to_name)
make_it_happen = str(input(ready_msg)).lower()
if make_it_happen == "y":
mv.go()
else:
print("Exiting...")
else:
print('You missed an input. Please run the program again.')