167 lines
5.9 KiB
Python
167 lines
5.9 KiB
Python
|
#!/usr/bin/env python3
|
||
|
""" Create Pull Request """
|
||
|
import common as cmn
|
||
|
import create_or_update_branch as coub
|
||
|
import create_or_update_pull_request as coupr
|
||
|
from git import Repo
|
||
|
import json
|
||
|
import os
|
||
|
import sys
|
||
|
import time
|
||
|
|
||
|
|
||
|
# Default the committer and author to the GitHub Actions bot
|
||
|
DEFAULT_COMMITTER = "GitHub <noreply@github.com>"
|
||
|
DEFAULT_AUTHOR = (
|
||
|
"github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>"
|
||
|
)
|
||
|
|
||
|
|
||
|
def set_committer_author(repo, committer, author):
|
||
|
# When the user intends for the committer and author to be the same,
|
||
|
# ideally, just the committer should be supplied. When just the author
|
||
|
# is supplied, the same user intention is assumed.
|
||
|
if committer is None and author is not None:
|
||
|
print("Supplied author will also be used as the committer.")
|
||
|
committer = author
|
||
|
|
||
|
# TODO Get committer and author from git config
|
||
|
# If just a committer exists, only set committer
|
||
|
# If just author exists also use for the committer
|
||
|
|
||
|
# Set defaults if no committer/author has been supplied
|
||
|
if committer is None and author is None:
|
||
|
committer = DEFAULT_COMMITTER
|
||
|
author = DEFAULT_AUTHOR
|
||
|
|
||
|
# Set git environment. This will not persist after the action completes.
|
||
|
committer_name, committer_email = cmn.parse_display_name_email(committer)
|
||
|
print(f"Configuring git committer as '{committer_name} <{committer_email}>'")
|
||
|
if author is not None:
|
||
|
author_name, author_email = cmn.parse_display_name_email(author)
|
||
|
print(f"Configuring git author as '{author_name} <{author_email}>'")
|
||
|
repo.git.update_environment(
|
||
|
GIT_COMMITTER_NAME=committer_name,
|
||
|
GIT_COMMITTER_EMAIL=committer_email,
|
||
|
GIT_AUTHOR_NAME=author_name,
|
||
|
GIT_AUTHOR_EMAIL=author_email,
|
||
|
)
|
||
|
else:
|
||
|
repo.git.update_environment(
|
||
|
GIT_COMMITTER_NAME=committer_name, GIT_COMMITTER_EMAIL=committer_email,
|
||
|
)
|
||
|
|
||
|
|
||
|
# Get required environment variables
|
||
|
github_token = os.environ["GITHUB_TOKEN"]
|
||
|
github_repository = os.environ["GITHUB_REPOSITORY"]
|
||
|
# Get environment variables with defaults
|
||
|
branch = os.getenv("CPR_BRANCH", "create-pull-request/patch")
|
||
|
commit_message = os.getenv(
|
||
|
"CPR_COMMIT_MESSAGE", "Changes by create-pull-request action"
|
||
|
)
|
||
|
# Get environment variables with a default of 'None'
|
||
|
committer = os.environ.get("CPR_COMMITTER")
|
||
|
author = os.environ.get("CPR_AUTHOR")
|
||
|
base = os.environ.get("CPR_BASE")
|
||
|
|
||
|
# Set the repo to the working directory
|
||
|
repo = Repo(os.getcwd())
|
||
|
|
||
|
# Determine if the checked out ref is a valid base for a pull request
|
||
|
# The action needs the checked out HEAD ref to be a branch
|
||
|
# This check will fail in the following cases:
|
||
|
# - HEAD is detached
|
||
|
# - HEAD is a merge commit (pull_request events)
|
||
|
# - HEAD is a tag
|
||
|
try:
|
||
|
working_base = repo.git.symbolic_ref("HEAD", "--short")
|
||
|
except:
|
||
|
print(f"::debug::{working_base}")
|
||
|
print(
|
||
|
f"::error::The checked out ref is not a valid base for a pull request. "
|
||
|
+ "Unable to continue. Exiting."
|
||
|
)
|
||
|
sys.exit(1)
|
||
|
|
||
|
# Exit if the working base is a PR branch created by this action.
|
||
|
# This may occur when using a PAT instead of GITHUB_TOKEN because
|
||
|
# a PAT allows workflow actions to trigger further events.
|
||
|
if working_base.startswith(branch):
|
||
|
print(
|
||
|
f"::error::Working base branch '{working_base}' was created by this action. "
|
||
|
+ "Unable to continue. Exiting."
|
||
|
)
|
||
|
sys.exit(1)
|
||
|
|
||
|
# Fetch an optional environment variable to determine the branch suffix
|
||
|
branch_suffix = os.environ.get("CPR_BRANCH_SUFFIX")
|
||
|
if branch_suffix is not None:
|
||
|
if branch_suffix == "short-commit-hash":
|
||
|
# Suffix with the short SHA1 hash
|
||
|
branch = "{}-{}".format(branch, repo.git.rev_parse("--short", "HEAD"))
|
||
|
elif branch_suffix == "timestamp":
|
||
|
# Suffix with the current timestamp
|
||
|
branch = "{}-{}".format(branch, int(time.time()))
|
||
|
elif branch_suffix == "random":
|
||
|
# Suffix with a 7 character random string
|
||
|
branch = "{}-{}".format(branch, cmn.get_random_string())
|
||
|
else:
|
||
|
print(
|
||
|
f"::error::Branch suffix '{branch_suffix}' is not a valid value. "
|
||
|
+ "Unable to continue. Exiting."
|
||
|
)
|
||
|
sys.exit(1)
|
||
|
|
||
|
# Output head branch
|
||
|
print(f"Pull request branch to create or update set to '{branch}'")
|
||
|
|
||
|
# Set the committer and author
|
||
|
try:
|
||
|
set_committer_author(repo, committer, author)
|
||
|
except ValueError as e:
|
||
|
print(f"::error::{e} " + "Unable to continue. Exiting.")
|
||
|
sys.exit(1)
|
||
|
|
||
|
# Set the repository URL
|
||
|
repo_url = f"https://x-access-token:{github_token}@github.com/{github_repository}"
|
||
|
|
||
|
# Create or update the pull request branch
|
||
|
result = coub.create_or_update_branch(repo, repo_url, commit_message, base, branch)
|
||
|
|
||
|
if result["action"] in ["created", "updated"]:
|
||
|
# The branch was created or updated
|
||
|
print(f"Pushing pull request branch to 'origin/{branch}'")
|
||
|
repo.git.push("--force", repo_url, f"HEAD:refs/heads/{branch}")
|
||
|
|
||
|
# Set the base. It would have been 'None' if not specified as an input
|
||
|
base = result["base"]
|
||
|
|
||
|
# TODO Figure out what to do when there is no diff with the base anymore
|
||
|
# if not result["diff"]:
|
||
|
|
||
|
# Fetch optional environment variables with default values
|
||
|
title = os.getenv("CPR_TITLE", "Auto-generated by create-pull-request action")
|
||
|
body = os.getenv(
|
||
|
"CPR_BODY",
|
||
|
"Auto-generated pull request by "
|
||
|
"[create-pull-request](https://github.com/peter-evans/create-pull-request) GitHub Action",
|
||
|
)
|
||
|
|
||
|
# Create or update the pull request
|
||
|
coupr.create_or_update_pull_request(
|
||
|
github_token,
|
||
|
github_repository,
|
||
|
branch,
|
||
|
base,
|
||
|
title,
|
||
|
body,
|
||
|
os.environ.get("CPR_LABELS"),
|
||
|
os.environ.get("CPR_ASSIGNEES"),
|
||
|
os.environ.get("CPR_MILESTONE"),
|
||
|
os.environ.get("CPR_REVIEWERS"),
|
||
|
os.environ.get("CPR_TEAM_REVIEWERS"),
|
||
|
os.environ.get("CPR_PROJECT_NAME"),
|
||
|
os.environ.get("CPR_PROJECT_COLUMN_NAME"),
|
||
|
)
|