mirror of
https://github.com/php-curl-class/php-curl-class.git
synced 2026-08-17 17:05:32 +00:00
261 lines
8.7 KiB
Python
261 lines
8.7 KiB
Python
import json
|
|
import os
|
|
import pprint
|
|
import subprocess
|
|
from copy import copy
|
|
from datetime import datetime
|
|
from datetime import timezone
|
|
from pathlib import Path
|
|
|
|
from git.repo import Repo
|
|
from github import Github
|
|
|
|
# The owner and repository name. For example, octocat/Hello-World.
|
|
GITHUB_REPOSITORY = os.getenv("GITHUB_REPOSITORY", "")
|
|
|
|
GITHUB_TOKEN = os.getenv("GITHUB_TOKEN")
|
|
GITHUB_REF_NAME = os.getenv("GITHUB_REF_NAME")
|
|
|
|
CURRENT_FILE = Path(__file__)
|
|
ROOT = CURRENT_FILE.parents[1]
|
|
CHANGELOG_PATH = ROOT / "CHANGELOG.md"
|
|
LIBRARY_FILE_PATH = ROOT / "src/Curl/Curl.php"
|
|
|
|
|
|
def main():
|
|
# Find most recent tag and timestamp.
|
|
# git for-each-ref --format="%(refname:short) | %(creatordate)" "refs/tags/*"
|
|
local_repo = Repo(ROOT)
|
|
|
|
# Sort the tags by version.
|
|
# git tag --list | sort --reverse --version-sort
|
|
tags = sorted(
|
|
local_repo.tags,
|
|
key=lambda tag: list(map(int, tag.name.split("."))),
|
|
reverse=True,
|
|
)
|
|
|
|
most_recent_tag = tags[0]
|
|
print("most_recent_tag: {}".format(most_recent_tag))
|
|
most_recent_tag_datetime = most_recent_tag.commit.committed_datetime
|
|
print("most_recent_tag_datetime: {}".format(most_recent_tag_datetime))
|
|
|
|
g = Github(login_or_token=GITHUB_TOKEN)
|
|
|
|
# Find merged pull requests since the most recent tag.
|
|
github_repo = g.get_repo(GITHUB_REPOSITORY)
|
|
recent_pulls = github_repo.get_pulls(
|
|
state="closed",
|
|
sort="updated",
|
|
direction="desc",
|
|
)
|
|
|
|
pull_request_changes = []
|
|
|
|
# Group pull requests by semantic version change type.
|
|
pull_request_by_type = {
|
|
"major": [],
|
|
"minor": [],
|
|
"patch": [],
|
|
"cleanup": [],
|
|
"unspecified": [],
|
|
}
|
|
|
|
# Track if any pull request is missing a semantic version change type.
|
|
pulls_missing_semver_label = []
|
|
|
|
for pull in recent_pulls:
|
|
print("-" * 10)
|
|
print("pull.title: {}".format(pull.title))
|
|
print("pull.html_url: {}".format(pull.html_url))
|
|
|
|
# Skip this and remaining pull requests as this one's last update
|
|
# predates the most recent tag. Results are sorted by updated desc, so
|
|
# no later entry in the list could have been merged after the tag
|
|
# either.
|
|
pull_updated_at = copy(pull.updated_at).replace(tzinfo=timezone.utc)
|
|
print("pull_updated_at: {}".format(pull_updated_at))
|
|
if pull_updated_at < most_recent_tag_datetime:
|
|
print("stopping: updated_at predates most recent tag")
|
|
break
|
|
|
|
# Skip this pull request as it's not merged.
|
|
if not pull.merged:
|
|
print("skipping: not merged")
|
|
continue
|
|
|
|
# Skip this pull request as it was merged before the most recent tag.
|
|
pull_merged_at = copy(pull.merged_at).replace(tzinfo=timezone.utc)
|
|
print("pull_merged_at: {}".format(pull_merged_at))
|
|
if pull_merged_at < most_recent_tag_datetime:
|
|
print("skipping: merged prior to last release")
|
|
continue
|
|
|
|
pull_labels = {label.name for label in pull.labels}
|
|
if "major-incompatible-changes" in pull_labels:
|
|
group_name = "major"
|
|
elif "minor-backwards-compatible-added-functionality" in pull_labels:
|
|
group_name = "minor"
|
|
elif "patch-backwards-compatible-bug-fixes" in pull_labels:
|
|
group_name = "patch"
|
|
elif "cleanup-no-release-required" in pull_labels:
|
|
group_name = "cleanup"
|
|
else:
|
|
group_name = "unspecified"
|
|
pulls_missing_semver_label.append(pull)
|
|
pull_request_by_type[group_name].append(pull)
|
|
|
|
# pprint.pprint(pull.title)
|
|
# pprint.pprint('most recent: {}'.format(most_recent_tag_datetime))
|
|
# pprint.pprint('merged at: {}'.format(pull.merged_at))
|
|
# print(pull.html_url)
|
|
|
|
if group_name in ["major", "minor", "patch"]:
|
|
pull_request_changes.append(
|
|
"- {} ([#{}]({}))".format(pull.title, pull.number, pull.html_url)
|
|
)
|
|
|
|
# print('-' * 10)
|
|
|
|
# pprint.pprint(pull_request_changes)
|
|
|
|
# Raise error if any pull request is missing a semantic version change type.
|
|
# Do this check before checking for any pull request changes as all the pull
|
|
# requests changes might be missing semver labels.
|
|
if pulls_missing_semver_label:
|
|
error_message = (
|
|
"Merged pull request(s) found without semantic version label:\n"
|
|
"{}".format(
|
|
"\n".join(
|
|
" {}".format(pull.html_url) for pull in pulls_missing_semver_label
|
|
)
|
|
)
|
|
)
|
|
raise Exception(error_message)
|
|
|
|
if not pull_request_changes:
|
|
print("No merged pull requests since the most recent tag release were found")
|
|
return
|
|
|
|
# pprint.pprint(pull_request_by_type)
|
|
if pull_request_by_type.get("major"):
|
|
highest_semantic_version = "major"
|
|
php_file_path = "scripts/bump_major_version.php"
|
|
elif pull_request_by_type.get("minor"):
|
|
highest_semantic_version = "minor"
|
|
php_file_path = "scripts/bump_minor_version.php"
|
|
elif pull_request_by_type.get("patch"):
|
|
highest_semantic_version = "patch"
|
|
php_file_path = "scripts/bump_patch_version.php"
|
|
else:
|
|
highest_semantic_version = None
|
|
php_file_path = ""
|
|
print("highest_semantic_version: {}".format(highest_semantic_version))
|
|
|
|
# Bump version and get next semantic version.
|
|
command = ["php", php_file_path]
|
|
print("running command: {}".format(command))
|
|
proc = subprocess.Popen(
|
|
command, shell=False, stdout=subprocess.PIPE, stdin=subprocess.PIPE
|
|
)
|
|
stdout, stderr = proc.communicate()
|
|
print("stdout: {}".format(stdout))
|
|
print("stderr: {}".format(stderr))
|
|
result = json.loads(stdout)
|
|
pprint.pprint(result)
|
|
|
|
release_version = result["new_version"]
|
|
today = datetime.today()
|
|
print("today: {} (tzinfo={})".format(today, today.tzinfo))
|
|
today = today.replace(tzinfo=timezone.utc)
|
|
print("today: {} (tzinfo={})".format(today, today.tzinfo))
|
|
release_date = today.strftime("%Y-%m-%d")
|
|
print("release_date: {}".format(release_date))
|
|
release_title = "{} - {}".format(release_version, release_date)
|
|
print("release_title: {}".format(release_title))
|
|
|
|
release_content = "".join(
|
|
[
|
|
"## {}\n",
|
|
"\n",
|
|
"{}",
|
|
]
|
|
).format(release_title, "\n".join(pull_request_changes))
|
|
|
|
old_content = CHANGELOG_PATH.read_text()
|
|
new_content = old_content.replace(
|
|
"<!-- CHANGELOG_PLACEHOLDER -->",
|
|
"<!-- CHANGELOG_PLACEHOLDER -->\n\n{}".format(release_content),
|
|
)
|
|
# print(new_content[:800])
|
|
CHANGELOG_PATH.write_text(new_content)
|
|
|
|
# print('git status before adding files:')
|
|
# print(local_repo.git.status())
|
|
|
|
local_repo.git.add(CHANGELOG_PATH)
|
|
local_repo.git.add(LIBRARY_FILE_PATH)
|
|
|
|
# print('git status after adding files:')
|
|
# print(local_repo.git.status())
|
|
|
|
# print('diff:')
|
|
# git diff --cached --color=always
|
|
# print(local_repo.git.diff(cached=True, color='always'))
|
|
|
|
local_repo.git.commit(
|
|
message=result["message"],
|
|
author="{} <{}>".format(
|
|
local_repo.git.config("--get", "user.name"),
|
|
local_repo.git.config("--get", "user.email"),
|
|
),
|
|
)
|
|
|
|
print("diff after commit:")
|
|
# git log --max-count=1 --patch --color=always
|
|
print(local_repo.git.log(max_count="1", patch=True, color="always"))
|
|
|
|
# Push local changes.
|
|
server = "https://{}@github.com/{}.git".format(GITHUB_TOKEN, GITHUB_REPOSITORY)
|
|
print(
|
|
'pushing changes to branch "{}" of repository "{}"'.format(
|
|
GITHUB_REF_NAME, GITHUB_REPOSITORY
|
|
)
|
|
)
|
|
local_repo.git.push(server, GITHUB_REF_NAME)
|
|
|
|
# Create tag and release.
|
|
tag = result["new_version"]
|
|
tag_message = result["message"]
|
|
release_name = "Release {}".format(release_version)
|
|
release_message = (
|
|
"See [change log]"
|
|
"(https://github.com/php-curl-class/php-curl-class/blob/master/CHANGELOG.md) for changes.\n"
|
|
"\n"
|
|
"https://github.com/php-curl-class/php-curl-class/compare/{}...{}".format(
|
|
result["old_version"],
|
|
result["new_version"],
|
|
)
|
|
)
|
|
commit_sha = local_repo.head.commit.hexsha
|
|
print("tag: {}".format(tag))
|
|
print('tag_message: "{}"'.format(tag_message))
|
|
print('release_name: "{}"'.format(release_name))
|
|
print('release_message: "{}"'.format(release_message))
|
|
print("commit_sha: {}".format(commit_sha))
|
|
|
|
github_repo.create_git_tag_and_release(
|
|
tag=tag,
|
|
tag_message=tag_message,
|
|
release_name=release_name,
|
|
release_message=release_message,
|
|
object=commit_sha,
|
|
type="commit",
|
|
draft=False,
|
|
)
|
|
print("created tag and release")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|