This repository has been archived by the owner on Feb 7, 2023. It is now read-only.
/
github_empty_pr.py
143 lines (116 loc) · 4.88 KB
/
github_empty_pr.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
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os
import subprocess
import shlex
import datetime
import logging
from apscheduler.schedulers.blocking import BlockingScheduler
logger = logging.getLogger('github_empty_pr')
logger.setLevel(logging.DEBUG)
_THIS_DIR = os.path.dirname(os.path.abspath(__file__))
HUB = os.path.join(_THIS_DIR, 'hub')
class GitHubRepo(object):
def __init__(self, owner, repo):
logger.info('initializing')
self.owner = owner
self.repo = repo
self.empty_prs = []
self.clone(cwd=_THIS_DIR)
self.repo_dir = os.path.join(_THIS_DIR, repo)
self.default_branch = self.get_current_branch()
self.github_user = os.environ['GITHUB_USER']
self.github_token = os.environ['GITHUB_TOKEN']
self.setup_remote()
logger.info('initialization done')
def clone(self, cwd):
cmd = 'git clone https://github.com/{0}/{1}.git'\
.format(self.owner, self.repo)
subprocess.call(shlex.split(cmd), cwd=cwd)
def get_current_branch(self):
cmd = 'git branch'
output = subprocess.check_output(
shlex.split(cmd), cwd=self.repo_dir).strip()
for br in output.splitlines():
if br.startswith('*'):
return br.split()[-1]
def setup_remote(self):
url = 'https://{token}@github.com/{user}/{repo}.git'.format(
user=self.github_user, token=self.github_token, repo=self.repo)
cmd = 'git remote add {user} {url}'\
.format(user=self.github_user, url=url)
subprocess.call(shlex.split(cmd), cwd=self.repo_dir)
def check_ci_status(self, commit_sha):
cmd = '{0} ci-status {1}'.format(HUB, commit_sha)
output = subprocess.check_output(
shlex.split(cmd), cwd=self.repo_dir).strip()
return output
def fetch_all(self):
cmd = 'git fetch --all'
subprocess(shlex.split(cmd), cwd=self.repo_dir)
def commit_empty(self, branch, commit_msg):
cmd = 'git checkout -b {0}'.format(branch)
subprocess.call(shlex.split(cmd), cwd=self.repo_dir)
cmd = 'git commit --allow-empty -m "{0}"'.format(commit_msg)
subprocess.call(shlex.split(cmd), cwd=self.repo_dir)
self.check_commit_sha()
def check_commit_sha(self):
cmd = 'git log -1 --format="%H"'
commit_sha = subprocess.check_output(
shlex.split(cmd), cwd=self.repo_dir).strip()
return commit_sha
def send_empty_pr(self):
timestamp = datetime.datetime.now().strftime('%Y-%m-%d-%H-%M-%S')
logger.debug('timestamp: {0}'.format(timestamp))
# update cached remote branch
logger.info('fetching all')
self.fetch_all()
cmd = 'git checkout origin/{0}'.format(self.default_branch)
subprocess.call(shlex.split(cmd), cwd=self.repo_dir)
# empty commit
logger.info('empty committing')
branch = 'empty-commit-{0}'.format(timestamp)
commit_msg = 'Empty commit for Travis test at {0}'.format(timestamp)
commit_sha = self.commit_empty(branch, commit_msg)
# push
logger.info('pushing to remote')
cmd = 'git push {0} {1}'.format(self.github_user, branch)
subprocess.call(shlex.split(cmd), cwd=self.repo_dir)
# send pull request
logger.info('sending pull request')
cmd = '{0} pull-request -m "{1}" -h {2}:{3} -b {4}:{5}'\
.format(HUB, commit_msg, self.github_user, branch,
self.owner, self.default_branch)
subprocess.call(shlex.split(cmd), cwd=self.repo_dir)
self.empty_prs.append((branch, commit_sha))
logger.info('send_empty_pr done')
def close_ci_success_empty_pr(self):
for br, sha in self.empty_prs:
if self.check_ci_status(sha) == 'success':
logger.info('closing {0}'.format(br))
cmd = 'git push {0} {1} --delete'.format(self.github_user, br)
subprocess.call(shlex.split(cmd), cwd=self.repo_dir)
class GitHubReposHandler(object):
def __init__(self, repo_slugs):
self.gh_repos = []
for slug in repo_slugs:
owner, repo = slug.split('/')
self.gh_repos.append(GitHubRepo(owner, repo))
def send_empty_pr(self):
for repo in self.gh_repos:
repo.send_empty_pr()
def close_ci_success_empty_pr(self):
for repo in self.gh_repos:
repo.close_ci_success_empty_pr()
def main():
repo_slugs = ['start-jsk/jsk_apc']
gh_repos_handler = GitHubReposHandler(repo_slugs)
scheduler = BlockingScheduler(logger=logger)
scheduler.add_job(gh_repos_handler.send_empty_pr,
trigger='interval', minutes=5)
scheduler.add_job(gh_repos_handler.close_ci_success_empty_pr,
trigger='interval', minutes=5)
scheduler.print_jobs()
scheduler.start()
if __name__ == '__main__':
main()