|
@@ -60,25 +60,30 @@ def extract_csrf_token(html):
|
60
|
60
|
return match.group(1)
|
61
|
61
|
return None
|
62
|
62
|
|
63
|
|
-def update_milestone(title):
|
|
63
|
+def update_milestone(pr_data):
|
|
64
|
+ login()
|
64
|
65
|
"""Update milestone with PR title using CSRF token."""
|
65
|
66
|
csrf_token = get_csrf_token()
|
66
|
67
|
if not csrf_token:
|
67
|
68
|
print("Failed to get CSRF token.")
|
68
|
69
|
return False
|
69
|
70
|
|
|
71
|
+ content = create_milestone_content(pr_data)
|
|
72
|
+
|
|
73
|
+ with open("content.md", "w") as file:
|
|
74
|
+ file.write(content)
|
|
75
|
+
|
70
|
76
|
payload = {
|
71
|
77
|
"_csrf": csrf_token,
|
72
|
|
- "title": title,
|
73
|
|
- "content": "PR updated via webhook",
|
|
78
|
+ "content": content,
|
74
|
79
|
"deadline": "2025-03-31"
|
75
|
80
|
}
|
76
|
81
|
headers = {
|
77
|
82
|
"Content-Type": "application/x-www-form-urlencoded"
|
78
|
83
|
}
|
79
|
84
|
|
80
|
|
- print(f"Sending POST request to update milestone with title: '{title}'...")
|
81
|
85
|
response = session.post(EDIT_MILESTONE_URL, data=payload, headers=headers)
|
|
86
|
+ print("Response:", payload)
|
82
|
87
|
|
83
|
88
|
if response.status_code == 200:
|
84
|
89
|
print("Milestone updated successfully!")
|
|
@@ -86,11 +91,59 @@ def update_milestone(title):
|
86
|
91
|
elif response.status_code == 401: # Unauthorized → Need to re-login
|
87
|
92
|
print("Session expired, re-logging in...")
|
88
|
93
|
if login():
|
89
|
|
- return update_milestone(title)
|
|
94
|
+ return update_milestone(pr_data)
|
90
|
95
|
else:
|
91
|
96
|
print(f"Failed to update milestone: {response.status_code} - {response.text}")
|
92
|
97
|
return False
|
93
|
98
|
|
|
99
|
+def create_milestone_content(pr_data):
|
|
100
|
+ content = get_milestone()
|
|
101
|
+ if content:
|
|
102
|
+ content['content'] = append_item_to_identifier(content['content'], 'feature_sigma', pr_data)
|
|
103
|
+ return f"{content['content']}\n- [x] {pr_data['title']}"
|
|
104
|
+ else:
|
|
105
|
+ return f"- [] {pr_data['title']}"
|
|
106
|
+
|
|
107
|
+def get_milestone():
|
|
108
|
+ import re
|
|
109
|
+ response = session.get(EDIT_MILESTONE_URL)
|
|
110
|
+ if response.status_code == 200:
|
|
111
|
+ title_match = re.search(r'<input[^>]*name=["\']title["\'][^>]*value=["\'](.*?)["\']', response.text, re.IGNORECASE)
|
|
112
|
+ content_match = re.search(r'<textarea[^>]*name=["\']content["\'][^>]*>(.*?)</textarea>', response.text, re.IGNORECASE | re.DOTALL)
|
|
113
|
+ title = title_match.group(1) if title_match else None
|
|
114
|
+ content = content_match.group(1).strip() if content_match else None
|
|
115
|
+ return {'title': title, 'content': content}
|
|
116
|
+ else:
|
|
117
|
+
|
|
118
|
+ return None
|
|
119
|
+
|
|
120
|
+def append_item_to_identifier(encoded_content, identifier, new_item):
|
|
121
|
+ # Extract the block delimited by the identifier markers
|
|
122
|
+ import re
|
|
123
|
+ import html
|
|
124
|
+ content = html.unescape(encoded_content)
|
|
125
|
+ block_pattern = rf'(<!--\s*{identifier}\s*-->)(.*?)(<!--\s*/{identifier}\s*-->)'
|
|
126
|
+ block_match = re.search(block_pattern, content, re.DOTALL)
|
|
127
|
+ if not block_match:
|
|
128
|
+ print(f"Block with identifier '{identifier}' not found.")
|
|
129
|
+ return False
|
|
130
|
+
|
|
131
|
+ # Extract the parts of the block
|
|
132
|
+ start_marker = block_match.group(1)
|
|
133
|
+ block_content = block_match.group(2).strip()
|
|
134
|
+ end_marker = block_match.group(3)
|
|
135
|
+
|
|
136
|
+ # Append the new item to the block content
|
|
137
|
+ formatted_item = f"- [x] {new_item['username']}: [{new_item['title']}]({new_item['branch']})"
|
|
138
|
+ updated_block_content = f"{block_content}\n{formatted_item}"
|
|
139
|
+
|
|
140
|
+ # Reconstruct the content with the updated block
|
|
141
|
+ updated_content = f"{start_marker}\n{updated_block_content}\n{end_marker}"
|
|
142
|
+ content = content.replace(block_match.group(0), updated_content)
|
|
143
|
+
|
|
144
|
+ print(f"New item appended to '{identifier}' block.")
|
|
145
|
+ return content
|
|
146
|
+
|
94
|
147
|
@app.route('/webhook', methods=['POST'])
|
95
|
148
|
def handle_webhook():
|
96
|
149
|
if request.method != 'POST':
|
|
@@ -104,12 +157,20 @@ def handle_webhook():
|
104
|
157
|
# Handle Pull Request Event
|
105
|
158
|
if 'pull_request' in payload:
|
106
|
159
|
pr = payload.get('pull_request', {})
|
|
160
|
+
|
107
|
161
|
pr_title = pr.get('title')
|
|
162
|
+ pr_username = pr.get('user').get('username')
|
|
163
|
+ pr_branch = pr.get('head_branch')
|
|
164
|
+ pr_data = {
|
|
165
|
+ 'title': pr_title,
|
|
166
|
+ 'username': pr_username,
|
|
167
|
+ 'branch': pr_branch
|
|
168
|
+ }
|
108
|
169
|
|
109
|
170
|
print(f"Received PR: {pr_title}")
|
110
|
171
|
|
111
|
172
|
# Update milestone with PR title
|
112
|
|
- if update_milestone(pr_title):
|
|
173
|
+ if update_milestone(pr_data):
|
113
|
174
|
print("Milestone updated with PR title.")
|
114
|
175
|
else:
|
115
|
176
|
print("Failed to update milestone.")
|
|
@@ -123,6 +184,8 @@ def handle_webhook():
|
123
|
184
|
if __name__ == '__main__':
|
124
|
185
|
if login(): # Attempt login at startup
|
125
|
186
|
print("Initial login successful.")
|
|
187
|
+ milestone = get_milestone()
|
|
188
|
+ print(milestone)
|
126
|
189
|
else:
|
127
|
190
|
print("Initial login failed.")
|
128
|
191
|
app.run(port=4001)
|