Switch template to calendar versioning & automate releases (#3415)

This commit is contained in:
Bruno Alla 2021-11-18 09:36:42 +00:00 committed by GitHub
parent f49141d333
commit 183ca2088a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 100 additions and 82 deletions

View File

@ -1,4 +1,3 @@
## [{{merge_date.strftime('%Y-%m-%d')}}]
{%- for change_type, pulls in grouped_pulls.items() %}
{%- if pulls %}
### {{ change_type }}

View File

@ -1,29 +0,0 @@
categories:
- title: 'Breaking Changes'
labels:
- 'breaking'
- title: 'Major Changes'
labels:
- 'major'
- title: 'Minor Changes'
labels:
- 'enhancement'
- title: 'Bugfixes'
labels:
- 'bug'
- title: 'Removals'
labels:
- 'removed'
- title: 'Documentation updates'
labels:
- 'docs'
exclude-labels:
- 'skip-changelog'
- 'update'
- 'project infrastructure'
template: |
## Changes
$CHANGES

View File

@ -1,14 +0,0 @@
name: Release Drafter
on:
push:
branches:
- master
jobs:
release_notes:
runs-on: ubuntu-latest
steps:
- uses: release-drafter/release-drafter@v5
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@ -8,7 +8,10 @@ on:
workflow_dispatch:
jobs:
build:
release:
# Disables this workflow from running in a repository that is not part of the indicated organization/user
if: github.repository_owner == 'cookiecutter'
runs-on: ubuntu-latest
steps:
@ -22,13 +25,11 @@ jobs:
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
- name: Set git details
run: |
git config --global user.name "github-actions"
git config --global user.email "action@github.com"
- name: Update list
run: python scripts/update_changelog.py
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Commit changes
uses: stefanzweifel/git-auto-commit-action@v4.12.0
with:
commit_message: Update Changelog
file_pattern: CHANGELOG.md

View File

@ -21,5 +21,6 @@ pyyaml==6.0
# Scripting
# ------------------------------------------------------------------------------
PyGithub==1.55
gitpython==3.1.24
jinja2==3.0.3
requests==2.26.0

View File

@ -1,26 +1,31 @@
import datetime as dt
import os
import re
from pathlib import Path
from typing import Iterable
from github import Github
import git
import github.PullRequest
import github.Repository
from github import Github
from jinja2 import Template
CURRENT_FILE = Path(__file__)
ROOT = CURRENT_FILE.parents[1]
GITHUB_TOKEN = os.getenv("GITHUB_TOKEN", None)
GITHUB_REPO = os.getenv("GITHUB_REPOSITORY", None)
# Generate changelog for PRs merged yesterday
MERGED_DATE = dt.date.today() - dt.timedelta(days=1)
GITHUB_TOKEN = os.getenv("GITHUB_TOKEN")
GITHUB_REPO = os.getenv("GITHUB_REPOSITORY")
GIT_BRANCH = os.getenv("GITHUB_REF_NAME")
def main() -> None:
"""
Script entry point.
"""
merged_pulls = list(iter_pulls())
# Generate changelog for PRs merged yesterday
merged_date = dt.date.today() - dt.timedelta(days=1)
repo = Github(login_or_token=GITHUB_TOKEN).get_repo(GITHUB_REPO)
merged_pulls = list(iter_pulls(repo, merged_date))
print(f"Merged pull requests: {merged_pulls}")
if not merged_pulls:
print("Nothing was merged, existing.")
return
@ -29,26 +34,44 @@ def main() -> None:
grouped_pulls = group_pulls_by_change_type(merged_pulls)
# Generate portion of markdown
rendered_content = generate_md(grouped_pulls)
release_changes_summary = generate_md(grouped_pulls)
print(f"Summary of changes: {release_changes_summary}")
# Update CHANGELOG.md file
file_path = ROOT / "CHANGELOG.md"
old_content = file_path.read_text()
updated_content = old_content.replace(
"<!-- GENERATOR_PLACEHOLDER -->",
f"<!-- GENERATOR_PLACEHOLDER -->\n\n{rendered_content}",
release = f"{merged_date:%Y.%m.%d}"
changelog_path = ROOT / "CHANGELOG.md"
write_changelog(changelog_path, release, release_changes_summary)
print(f"Wrote {changelog_path}")
# Update version
setup_py_path = ROOT / "setup.py"
update_version(setup_py_path, release)
print(f"Updated version in {setup_py_path}")
# Commit changes, create tag and push
update_git_repo([changelog_path, setup_py_path], release)
# Create GitHub release
github_release = repo.create_git_release(
tag=release,
name=release,
message=release_changes_summary,
)
file_path.write_text(updated_content)
print(f"Created release on GitHub {github_release}")
def iter_pulls() -> Iterable[github.PullRequest.PullRequest]:
def iter_pulls(
repo: github.Repository.Repository,
merged_date: dt.date,
) -> Iterable[github.PullRequest.PullRequest]:
"""Fetch merged pull requests at the date we're interested in."""
repo = Github(login_or_token=GITHUB_TOKEN).get_repo(GITHUB_REPO)
recent_pulls = repo.get_pulls(
state="closed", sort="updated", direction="desc"
state="closed",
sort="updated",
direction="desc",
).get_page(0)
for pull in recent_pulls:
if pull.merged and pull.merged_at.date() == MERGED_DATE:
if pull.merged and pull.merged_at.date() == merged_date:
yield pull
@ -77,7 +100,50 @@ def generate_md(grouped_pulls: dict[str, list[github.PullRequest.PullRequest]])
"""Generate markdown file from Jinja template."""
changelog_template = ROOT / ".github" / "changelog-template.md"
template = Template(changelog_template.read_text(), autoescape=True)
return template.render(merge_date=MERGED_DATE, grouped_pulls=grouped_pulls)
return template.render(grouped_pulls=grouped_pulls)
def write_changelog(file_path: Path, release: str, content: str) -> None:
"""Write Release details to the changelog file."""
content = f"## {release}\n{content}"
old_content = file_path.read_text()
updated_content = old_content.replace(
"<!-- GENERATOR_PLACEHOLDER -->",
f"<!-- GENERATOR_PLACEHOLDER -->\n\n{content}",
)
file_path.write_text(updated_content)
def update_version(file_path: Path, release: str) -> None:
"""Update template version in setup.py."""
old_content = file_path.read_text()
updated_content = re.sub(
r'\nversion = "\d+\.\d+\.\d+"\n',
f'\nversion = "{release}"\n',
old_content,
)
file_path.write_text(updated_content)
def update_git_repo(paths: list[Path], release: str) -> None:
"""Commit, tag changes in git repo and push to origin."""
repo = git.Repo(ROOT)
for path in paths:
repo.git.add(path)
message = f"Release {release}"
user = repo.git.config("--get", "user.name")
email = repo.git.config("--get", "user.email")
repo.git.commit(
m=message,
author=f"{user} <{email}>",
)
repo.git.tag("-a", release, m=message)
server = f"https://{GITHUB_TOKEN}@github.com/{GITHUB_REPO}.git"
print(f"Pushing changes to {GIT_BRANCH} branch of {GITHUB_REPO}")
repo.git.push(server, GIT_BRANCH)
repo.git.push("--tags", server, GIT_BRANCH)
if __name__ == "__main__":
@ -85,4 +151,8 @@ if __name__ == "__main__":
raise RuntimeError(
"No github repo, please set the environment variable GITHUB_REPOSITORY"
)
if GIT_BRANCH is None:
raise RuntimeError(
"No git branch set, please set the GITHUB_REF_NAME environment variable"
)
main()

View File

@ -1,21 +1,11 @@
#!/usr/bin/env python
import os
import sys
try:
from setuptools import setup
except ImportError:
from distutils.core import setup
# Our version ALWAYS matches the version of Django we support
# If Django has a new release, we branch, tag, then update this setting after the tag.
version = "3.1.13-01"
if sys.argv[-1] == "tag":
os.system(f'git tag -a {version} -m "version {version}"')
os.system("git push --tags")
sys.exit()
# We use calendar versioning
version = "2021.11.17"
with open("README.rst") as readme_file:
long_description = readme_file.read()