This repository was archived by the owner on Jan 18, 2025. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgithub-circleci-trigger.py
140 lines (104 loc) · 4.21 KB
/
github-circleci-trigger.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
import logging
import os
from functools import wraps
import requests
from flask import abort, Flask, request
from flask import logging as flask_logging
from github_webhook import Webhook
from ipaddress import ip_address, ip_network
app = Flask(__name__)
webhook = Webhook(app, endpoint='/postreceive', secret=os.environ.get('GITHUB_WEBHOOK_SECRET'))
def ip_check(func):
@wraps(func)
def with_ip_check(*args, **kwargs):
if int(os.environ.get('DISABLE_IP_CHECK', False)):
return func(*args, **kwargs)
# Store the IP address of the requester
request_ip = ip_address(u'{0}'.format(request.access_route[0]))
# If GHE_ADDRESS is specified, use it as the hook_blocks.
if os.environ.get('GHE_ADDRESS', None):
hook_blocks = [unicode(os.environ.get('GHE_ADDRESS'))]
# Otherwise get the hook address blocks from the API.
else:
hook_blocks = requests.get('https://api.github.com/meta').json()['hooks']
# Support debugging
if os.environ.get('FLASK_DEBUG', 0):
hook_blocks.append(u'127.0.0.0/8')
# Check if the POST request is from github.com or GHE
for block in hook_blocks:
if ip_address(request_ip) in ip_network(block):
break # the remote_addr is within the network range of github.
else:
abort(403)
return func(*args, **kwargs)
return with_ip_check
def circleci_new_build(source_event, payload):
app.logger.info(
"Triggered CircleCI build because of %s associated with %s" % (source_event, payload))
worker_token = os.environ.get('CIRCLECI_TOKEN', None)
if not worker_token:
app.logger.error('CIRCLECI_TOKEN is not set')
return
worker_repo = os.environ.get('CIRCLECI_REPO', None)
if not worker_repo:
app.logger.error('CIRCLECI_REPO is not set')
return
api_url = 'https://circleci.com/api/v1.1/project/github/' + worker_repo
response = requests.post(api_url, params={'circle-token': worker_token}, json={
'build_parameters': {
'SLICER_REPO_PR_NUMBER': source_event.get('number', ''),
'SLICER_REPO_NAME': payload['repo'],
'SLICER_REPO_BRANCH': payload['branch'],
'SLICER_REPO_TAG': payload['tag'],
'SLICER_REPO_REVISION': payload['revision'],
}
})
response.raise_for_status()
@app.route('/')
@ip_check
def hello():
# Todo: List available endpoints and supported GitHub events
return 'Hello World!'
@webhook.hook(event_type='ping')
@ip_check
def on_ping(data):
return 'The impossible exists only until we find a way to make it possible'
@webhook.hook(event_type='pull_request')
@ip_check
def on_pull_request(data):
payload = {
'repo': data['pull_request']['head']['repo']['full_name'],
'branch': data['pull_request']['head']['ref'],
'tag': '',
'revision': data['pull_request']['head']['sha']
}
source_event = {'type': 'pull_request', 'action': data['action'], 'number': data['number']}
if data['action'] not in ['opened', 'edited', 'synchronize']:
app.logger.info("Ignoring %s associated with %s" % (source_event, payload))
return
circleci_new_build(source_event, payload)
@webhook.hook(event_type='push')
@ip_check
def on_push(data):
# Extract repo, branch and tag
repo = data['repository']['full_name']
branch = ''
tag = ''
if data['ref'].startswith('refs/tags/'):
tag = data['ref'].lstrip('refs/tags/')
# branch = data['base_ref'].lstrip('refs/heads/')
elif data['ref'].startswith('refs/heads/'):
branch = data['ref'].lstrip('refs/heads/')
else:
app.logger.error('Unsupported ref: %s' % data['ref'])
abort(500)
source_event = {'type': 'push'}
payload = {'repo': repo, 'branch': branch, 'tag': tag, 'revision': data["head_commit"]["id"]}
# Only consider Push event associated with update to 'main' or `master` branches
# or tags.
if branch not in ['main', 'master'] and not tag:
app.logger.info("Ignoring %s associated with %s" % (source_event, payload))
return
circleci_new_build(source_event, payload)
if __name__ == '__main__':
app.run()