|
@@ -0,0 +1,128 @@
|
|
1
|
+import requests
|
|
2
|
+from requests.auth import HTTPBasicAuth
|
|
3
|
+from flask import Flask, request, jsonify
|
|
4
|
+
|
|
5
|
+app = Flask(__name__)
|
|
6
|
+
|
|
7
|
+# Config
|
|
8
|
+LOGIN_URL = "http://localhost:7777/user/login"
|
|
9
|
+EDIT_MILESTONE_URL = "http://localhost:7777/setyotontowi/experiments/milestones/1/edit"
|
|
10
|
+USERNAME = "setyotontowi"
|
|
11
|
+PASSWORD = "nasipadang"
|
|
12
|
+
|
|
13
|
+session = requests.Session() # Keep session across requests
|
|
14
|
+
|
|
15
|
+def login():
|
|
16
|
+ """Log in and store session cookies."""
|
|
17
|
+ print("Logging in...")
|
|
18
|
+ payload = {
|
|
19
|
+ "user_name": USERNAME,
|
|
20
|
+ "password": PASSWORD
|
|
21
|
+ }
|
|
22
|
+ response = session.post(LOGIN_URL, data=payload)
|
|
23
|
+
|
|
24
|
+ if response.status_code == 200:
|
|
25
|
+ print("Login successful.")
|
|
26
|
+ return True
|
|
27
|
+ else:
|
|
28
|
+ print(f"Login failed: {response.status_code} - {response.text}")
|
|
29
|
+ return False
|
|
30
|
+
|
|
31
|
+def get_csrf_token():
|
|
32
|
+ """Fetch CSRF token from the edit milestone page."""
|
|
33
|
+ print("Fetching CSRF token...")
|
|
34
|
+
|
|
35
|
+ response = session.get(EDIT_MILESTONE_URL)
|
|
36
|
+ if response.status_code == 200:
|
|
37
|
+ token = extract_csrf_token(response.text)
|
|
38
|
+ if token:
|
|
39
|
+ print(f"CSRF token obtained: {token}")
|
|
40
|
+ return token
|
|
41
|
+ else:
|
|
42
|
+ print("Failed to extract CSRF token.")
|
|
43
|
+ return None
|
|
44
|
+ elif response.status_code == 401: # Unauthorized → Need to re-login
|
|
45
|
+ print("Session expired, re-logging in...")
|
|
46
|
+ if login():
|
|
47
|
+ return get_csrf_token()
|
|
48
|
+ else:
|
|
49
|
+ print("Failed to log in while fetching CSRF token.")
|
|
50
|
+ return None
|
|
51
|
+ else:
|
|
52
|
+ print(f"Failed to get CSRF token: {response.status_code} - {response.text}")
|
|
53
|
+ return None
|
|
54
|
+
|
|
55
|
+def extract_csrf_token(html):
|
|
56
|
+ """Extract CSRF token from HTML using regex."""
|
|
57
|
+ import re
|
|
58
|
+ match = re.search(r'name="_csrf" value="(.*?)"', html)
|
|
59
|
+ if match:
|
|
60
|
+ return match.group(1)
|
|
61
|
+ return None
|
|
62
|
+
|
|
63
|
+def update_milestone(title):
|
|
64
|
+ """Update milestone with PR title using CSRF token."""
|
|
65
|
+ csrf_token = get_csrf_token()
|
|
66
|
+ if not csrf_token:
|
|
67
|
+ print("Failed to get CSRF token.")
|
|
68
|
+ return False
|
|
69
|
+
|
|
70
|
+ payload = {
|
|
71
|
+ "_csrf": csrf_token,
|
|
72
|
+ "title": title,
|
|
73
|
+ "content": "PR updated via webhook",
|
|
74
|
+ "deadline": "2025-03-31"
|
|
75
|
+ }
|
|
76
|
+ headers = {
|
|
77
|
+ "Content-Type": "application/x-www-form-urlencoded"
|
|
78
|
+ }
|
|
79
|
+
|
|
80
|
+ print(f"Sending POST request to update milestone with title: '{title}'...")
|
|
81
|
+ response = session.post(EDIT_MILESTONE_URL, data=payload, headers=headers)
|
|
82
|
+
|
|
83
|
+ if response.status_code == 200:
|
|
84
|
+ print("Milestone updated successfully!")
|
|
85
|
+ return True
|
|
86
|
+ elif response.status_code == 401: # Unauthorized → Need to re-login
|
|
87
|
+ print("Session expired, re-logging in...")
|
|
88
|
+ if login():
|
|
89
|
+ return update_milestone(title)
|
|
90
|
+ else:
|
|
91
|
+ print(f"Failed to update milestone: {response.status_code} - {response.text}")
|
|
92
|
+ return False
|
|
93
|
+
|
|
94
|
+@app.route('/webhook', methods=['POST'])
|
|
95
|
+def handle_webhook():
|
|
96
|
+ if request.method != 'POST':
|
|
97
|
+ return 'Invalid request method', 405
|
|
98
|
+
|
|
99
|
+ try:
|
|
100
|
+ payload = request.get_json()
|
|
101
|
+ if not payload:
|
|
102
|
+ return 'Invalid JSON payload', 400
|
|
103
|
+
|
|
104
|
+ # Handle Pull Request Event
|
|
105
|
+ if 'pull_request' in payload:
|
|
106
|
+ pr = payload.get('pull_request', {})
|
|
107
|
+ pr_title = pr.get('title')
|
|
108
|
+
|
|
109
|
+ print(f"Received PR: {pr_title}")
|
|
110
|
+
|
|
111
|
+ # Update milestone with PR title
|
|
112
|
+ if update_milestone(pr_title):
|
|
113
|
+ print("Milestone updated with PR title.")
|
|
114
|
+ else:
|
|
115
|
+ print("Failed to update milestone.")
|
|
116
|
+
|
|
117
|
+ return jsonify({'status': 'success'}), 200
|
|
118
|
+
|
|
119
|
+ except Exception as e:
|
|
120
|
+ print(f"Error: {e}")
|
|
121
|
+ return 'Internal server error', 500
|
|
122
|
+
|
|
123
|
+if __name__ == '__main__':
|
|
124
|
+ if login(): # Attempt login at startup
|
|
125
|
+ print("Initial login successful.")
|
|
126
|
+ else:
|
|
127
|
+ print("Initial login failed.")
|
|
128
|
+ app.run(port=4001)
|