mirror of
https://forgejo.stefka.eu/jiriks74/create-pull-request.git
synced 2025-01-18 16:01:06 +01:00
Unset and restore extraheader config option
This commit is contained in:
parent
c7b64af0a4
commit
d5c5ea3e20
27 changed files with 6526 additions and 181 deletions
227
dist/cpr/create_pull_request.py
vendored
Executable file
227
dist/cpr/create_pull_request.py
vendored
Executable file
|
@ -0,0 +1,227 @@
|
|||
#!/usr/bin/env python3
|
||||
""" Create Pull Request """
|
||||
import base64
|
||||
import common as cmn
|
||||
import create_or_update_branch as coub
|
||||
import create_or_update_pull_request as coupr
|
||||
from git import Repo, GitCommandError
|
||||
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>"
|
||||
)
|
||||
DEFAULT_COMMIT_MESSAGE = "[create-pull-request] automated change"
|
||||
DEFAULT_TITLE = "Changes by create-pull-request action"
|
||||
DEFAULT_BODY = (
|
||||
"Automated changes by "
|
||||
+ "[create-pull-request](https://github.com/peter-evans/create-pull-request) GitHub action"
|
||||
)
|
||||
DEFAULT_BRANCH = "create-pull-request/patch"
|
||||
|
||||
|
||||
def get_git_config_value(repo, name):
|
||||
try:
|
||||
return repo.git.config("--get", name)
|
||||
except GitCommandError:
|
||||
return None
|
||||
|
||||
|
||||
def get_repository_detail(repo):
|
||||
remote_origin_url = get_git_config_value(repo, "remote.origin.url")
|
||||
if remote_origin_url is None:
|
||||
raise ValueError("Failed to fetch 'remote.origin.url' from git config")
|
||||
protocol, github_repository = cmn.parse_github_repository(remote_origin_url)
|
||||
return remote_origin_url, protocol, github_repository
|
||||
|
||||
|
||||
def git_user_config_is_set(repo):
|
||||
name = get_git_config_value(repo, "user.name")
|
||||
email = get_git_config_value(repo, "user.email")
|
||||
|
||||
if name is not None and email is not None:
|
||||
print(f"Git user already configured as '{name} <{email}>'")
|
||||
return True
|
||||
|
||||
committer_name = get_git_config_value(repo, "committer.name")
|
||||
committer_email = get_git_config_value(repo, "committer.email")
|
||||
author_name = get_git_config_value(repo, "author.name")
|
||||
author_email = get_git_config_value(repo, "author.email")
|
||||
|
||||
if (
|
||||
committer_name is not None
|
||||
and committer_email is not None
|
||||
and author_name is not None
|
||||
and author_email is not None
|
||||
):
|
||||
print(
|
||||
f"Git committer already configured as '{committer_name} <{committer_email}>'"
|
||||
)
|
||||
print(f"Git author already configured as '{author_name} <{author_email}>'")
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def set_committer_author(repo, committer, author):
|
||||
# If either committer or author is supplied they will be cross used
|
||||
if committer is None and author is not None:
|
||||
print("Supplied author will also be used as the committer.")
|
||||
committer = author
|
||||
if author is None and committer is not None:
|
||||
print("Supplied committer will also be used as the author.")
|
||||
author = committer
|
||||
|
||||
# If no committer/author has been supplied but user configuration already
|
||||
# exists in git config we can exit and use the existing config as-is.
|
||||
if committer is None and author is None:
|
||||
if git_user_config_is_set(repo):
|
||||
return
|
||||
|
||||
# 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)
|
||||
author_name, author_email = cmn.parse_display_name_email(author)
|
||||
repo.git.update_environment(
|
||||
GIT_COMMITTER_NAME=committer_name,
|
||||
GIT_COMMITTER_EMAIL=committer_email,
|
||||
GIT_AUTHOR_NAME=author_name,
|
||||
GIT_AUTHOR_EMAIL=author_email,
|
||||
)
|
||||
print(f"Configured git committer as '{committer_name} <{committer_email}>'")
|
||||
print(f"Configured git author as '{author_name} <{author_email}>'")
|
||||
|
||||
|
||||
# Get required environment variables
|
||||
github_token = os.environ["GITHUB_TOKEN"]
|
||||
# Get environment variables with defaults
|
||||
path = os.getenv("CPR_PATH", os.getcwd())
|
||||
branch = os.getenv("CPR_BRANCH", DEFAULT_BRANCH)
|
||||
commit_message = os.getenv("CPR_COMMIT_MESSAGE", DEFAULT_COMMIT_MESSAGE)
|
||||
# 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 path
|
||||
repo = Repo(path)
|
||||
|
||||
# Determine the GitHub repository from git config
|
||||
# This will be the target repository for the pull request
|
||||
repo_url, protocol, github_repository = get_repository_detail(repo)
|
||||
print(f"Target repository set to {github_repository}")
|
||||
|
||||
if protocol == "HTTPS":
|
||||
print(f"::debug::Using HTTPS protocol")
|
||||
# Encode and configure the basic credential for HTTPS access
|
||||
basic_credential = base64.b64encode(
|
||||
f"x-access-token:{github_token}".encode("utf-8")
|
||||
).decode("utf-8")
|
||||
# Mask the basic credential in logs and debug output
|
||||
print(f"::add-mask::{basic_credential}")
|
||||
repo.git.set_persistent_git_options(
|
||||
c=f"http.https://github.com/.extraheader=AUTHORIZATION: basic {basic_credential}"
|
||||
)
|
||||
|
||||
# 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 GitCommandError as e:
|
||||
print(f"::debug::{e.stderr}")
|
||||
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)
|
||||
|
||||
# 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"]
|
||||
|
||||
# If there is no longer a diff with the base delete the branch and exit
|
||||
if not result["diff"]:
|
||||
print(f"Branch '{branch}' no longer differs from base branch '{base}'")
|
||||
print(f"Closing pull request and deleting branch '{branch}'")
|
||||
repo.git.push("--delete", "--force", repo_url, f"refs/heads/{branch}")
|
||||
sys.exit()
|
||||
|
||||
# Fetch optional environment variables with default values
|
||||
title = os.getenv("CPR_TITLE", DEFAULT_TITLE)
|
||||
body = os.getenv("CPR_BODY", DEFAULT_BODY)
|
||||
|
||||
# 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"),
|
||||
)
|
Loading…
Add table
Add a link
Reference in a new issue