forked from peter-evans/create-pull-request
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathcreate-pull-request.py
executable file
·155 lines (126 loc) · 5.2 KB
/
create-pull-request.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
144
145
146
147
148
149
150
151
152
153
154
155
#!/usr/bin/env python3
''' Create Pull Request '''
import json
import os
from git import Repo
from github import Github
def get_github_event(github_event_path):
with open(github_event_path) as f:
github_event = json.load(f)
if os.environ.get('DEBUG_EVENT') is not None:
print(json.dumps(github_event, sort_keys=True, indent=2))
return github_event
def ignore_event(github_event):
# Ignore push events on deleted branches
# The event we want to ignore occurs when a PR is created but the repository owner decides
# not to commit the changes. They close the PR and delete the branch. This creates a
# "push" event that we want to ignore, otherwise it will create another branch and PR on
# the same commit.
if "schedule" in github_event:
print("Cron event.")
return False
deleted = "{deleted}".format(**github_event)
if deleted == "True":
print("Ignoring delete branch event.")
return True
ref = "{ref}".format(**github_event)
if not ref.startswith('refs/heads/'):
print("Ignoring events for tags and remotes.")
return True
return False
def pr_branch_exists(repo, branch):
for ref in repo.remotes.origin.refs:
if ref.name == ("origin/%s" % branch):
return True
return False
def get_head_author(github_event):
if "schedule" in github_event:
email = os.environ['AUTHOR_EMAIL']
name = os.environ['AUTHOR_NAME']
else:
email = "{head_commit[author][email]}".format(**github_event)
name = "{head_commit[author][name]}".format(**github_event)
return email, name
def get_head_short_sha1(repo):
return repo.git.rev_parse('--short', 'HEAD')
def set_git_config(git, email, name):
git.config('--global', 'user.email', '"%s"' % email)
git.config('--global', 'user.name', '"%s"' % name)
def set_git_remote_url(git, token, github_repository):
git.remote('set-url', 'origin', "https://%s:[email protected]/%s" % (token, github_repository))
def commit_changes(git, branch, commit_message):
git.checkout('HEAD', b=branch)
git.add('-A')
git.commit(m=commit_message)
return git.push('--set-upstream', 'origin', branch)
def create_pull_request(token, repo, head, base, title, body):
return Github(token).get_repo(repo).create_pull(
title=title,
body=body,
base=base,
head=head)
def process_event(github_event, repo, branch, base):
# Fetch required environment variables
github_token = os.environ['GITHUB_TOKEN']
github_repository = os.environ['GITHUB_REPOSITORY']
repo_access_token = os.environ['REPO_ACCESS_TOKEN']
# Fetch remaining optional environment variables
commit_message = os.getenv(
'COMMIT_MESSAGE',
"Auto-committed changes by create-pull-request action")
title = os.getenv(
'PULL_REQUEST_TITLE',
"Auto-generated by create-pull-request action")
body = os.getenv(
'PULL_REQUEST_BODY', "Auto-generated pull request by "
"[create-pull-request](https://github.com/peter-evans/create-pull-request) GitHub Action")
# Get the HEAD committer's email and name
author_email, author_name = get_head_author(github_event)
# Set git configuration
set_git_config(repo.git, author_email, author_name)
# Update URL for the 'origin' remote
set_git_remote_url(repo.git, repo_access_token, github_repository)
# Commit the repository changes
print("Committing changes.")
commit_result = commit_changes(repo.git, branch, commit_message)
print(commit_result)
# Create the pull request
print("Creating a request to pull %s into %s." % (branch, base))
pull_request = create_pull_request(
github_token,
github_repository,
branch,
base,
title,
body
)
print("Created pull request %d." % pull_request.number)
# Get the JSON event data
github_event = get_github_event(os.environ['GITHUB_EVENT_PATH'])
# Check if this event should be ignored
if not ignore_event(github_event):
# Set the repo to the working directory
repo = Repo(os.getcwd())
# Fetch/Set the branch name
branch = os.getenv('PULL_REQUEST_BRANCH', 'create-pull-request/patch')
# Set the current branch as the target base branch
base = os.environ['GITHUB_REF'][11:]
# Skip if the current branch is a PR branch created by this action
if not base.startswith(branch):
# Suffix with the short SHA1 hash
branch = "%s-%s" % (branch, get_head_short_sha1(repo))
# Check if a PR branch already exists for this HEAD commit
if not pr_branch_exists(repo, branch):
# Check if there are changes to pull request
if repo.is_dirty() or len(repo.untracked_files) > 0:
print("Repository has modified or untracked files.")
process_event(github_event, repo, branch, base)
else:
print("Repository has no modified or untracked files. Skipping.")
else:
print(
"Pull request branch '%s' already exists for this commit. Skipping." %
branch)
else:
print(
"Branch '%s' was created by this action. Skipping." % base)