Create dependabot changelogs at release time (#15481)

* Ditch dependabot changelog workflow

* Summarise dependabot commits in release script

* Changelog

* Update scripts-dev/release.py
This commit is contained in:
David Robertson 2023-05-30 13:54:50 +01:00 committed by GitHub
parent 626bd75f48
commit 42786d8a47
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 57 additions and 57 deletions

View file

@ -1,49 +0,0 @@
name: Write changelog for dependabot PR
on:
pull_request:
types:
- opened
- reopened # For debugging!
permissions:
# Needed to be able to push the commit. See
# https://docs.github.com/en/code-security/dependabot/working-with-dependabot/automating-dependabot-with-github-actions#enable-auto-merge-on-a-pull-request
# for a similar example
contents: write
jobs:
add-changelog:
runs-on: 'ubuntu-latest'
if: ${{ github.actor == 'dependabot[bot]' }}
steps:
- uses: actions/checkout@v3
with:
ref: ${{ github.event.pull_request.head.ref }}
- name: Write, commit and push changelog
env:
PR_TITLE: ${{ github.event.pull_request.title }}
PR_NUMBER: ${{ github.event.pull_request.number }}
run: |
echo "${PR_TITLE}." > "changelog.d/${PR_NUMBER}".misc
git add changelog.d
git config user.email "github-actions[bot]@users.noreply.github.com"
git config user.name "GitHub Actions"
git commit -m "Changelog"
git push
shell: bash
# The `git push` above does not trigger CI on the dependabot PR.
#
# By default, workflows can't trigger other workflows when they're just using the
# default `GITHUB_TOKEN` access token. (This is intended to stop you from writing
# recursive workflow loops by accident, because that'll get very expensive very
# quickly.) Instead, you have to manually call out to another workflow, or else
# make your changes (i.e. the `git push` above) using a personal access token.
# See
# https://docs.github.com/en/actions/using-workflows/triggering-a-workflow#triggering-a-workflow-from-a-workflow
#
# I have tried and failed to find a way to trigger CI on the "merge ref" of the PR.
# See git commit history for previous attempts. If anyone desperately wants to try
# again in the future, make a matrix-bot account and use its access token to git push.
# THIS WORKFLOW HAS WRITE PERMISSIONS---do not add other jobs here unless they
# are sufficiently locked down to dependabot only as above.

1
changelog.d/15481.misc Normal file
View file

@ -0,0 +1 @@
Create dependabot changelogs at release time.

View file

@ -260,15 +260,17 @@ doesn't require poetry. (It's what we use in CI too). However, you could try
## ...handle a Dependabot pull request? ## ...handle a Dependabot pull request?
Synapse uses Dependabot to keep the `poetry.lock` file up-to-date. When it Synapse uses Dependabot to keep the `poetry.lock` and `Cargo.lock` file
creates a pull request a GitHub Action will run to automatically create a changelog up-to-date with the latest releases of our dependencies. The changelog check is
file. Ensure that: omitted for Dependabot PRs; the release script will include them in the
changelog.
When reviewing a dependabot PR, ensure that:
* the lockfile changes look reasonable; * the lockfile changes look reasonable;
* the upstream changelog file (linked in the description) doesn't include any * the upstream changelog file (linked in the description) doesn't include any
breaking changes; breaking changes;
* continuous integration passes (due to permissions, the GitHub Actions run on * continuous integration passes.
the changelog commit will fail, look at the initial commit of the pull request);
In particular, any updates to the type hints (usually packages which start with `types-`) In particular, any updates to the type hints (usually packages which start with `types-`)
should be safe to merge if linting passes. should be safe to merge if linting passes.

View file

@ -27,7 +27,7 @@ import time
import urllib.request import urllib.request
from os import path from os import path
from tempfile import TemporaryDirectory from tempfile import TemporaryDirectory
from typing import Any, List, Optional from typing import Any, List, Match, Optional, Union
import attr import attr
import click import click
@ -233,7 +233,7 @@ def _prepare() -> None:
subprocess.check_output(["poetry", "version", new_version]) subprocess.check_output(["poetry", "version", new_version])
# Generate changelogs. # Generate changelogs.
generate_and_write_changelog(current_version, new_version) generate_and_write_changelog(synapse_repo, current_version, new_version)
# Generate debian changelogs # Generate debian changelogs
if parsed_new_version.pre is not None: if parsed_new_version.pre is not None:
@ -814,7 +814,7 @@ def get_changes_for_version(wanted_version: version.Version) -> str:
def generate_and_write_changelog( def generate_and_write_changelog(
current_version: version.Version, new_version: str repo: Repo, current_version: version.Version, new_version: str
) -> None: ) -> None:
# We do this by getting a draft so that we can edit it before writing to the # We do this by getting a draft so that we can edit it before writing to the
# changelog. # changelog.
@ -827,6 +827,10 @@ def generate_and_write_changelog(
new_changes = new_changes.replace( new_changes = new_changes.replace(
"No significant changes.", f"No significant changes since {current_version}." "No significant changes.", f"No significant changes since {current_version}."
) )
new_changes += build_dependabot_changelog(
repo,
current_version,
)
# Prepend changes to changelog # Prepend changes to changelog
with open("CHANGES.md", "r+") as f: with open("CHANGES.md", "r+") as f:
@ -841,5 +845,47 @@ def generate_and_write_changelog(
os.remove(filename) os.remove(filename)
def build_dependabot_changelog(repo: Repo, current_version: version.Version) -> str:
"""Summarise dependabot commits between `current_version` and `release_branch`.
Returns an empty string if there have been no such commits; otherwise outputs a
third-level markdown header followed by an unordered list."""
last_release_commit = repo.tag("v" + str(current_version)).commit
rev_spec = f"{last_release_commit.hexsha}.."
commits = list(git.objects.Commit.iter_items(repo, rev_spec))
messages = []
for commit in reversed(commits):
if commit.author.name == "dependabot[bot]":
message: Union[str, bytes] = commit.message
if isinstance(message, bytes):
message = message.decode("utf-8")
messages.append(message.split("\n", maxsplit=1)[0])
if not messages:
print(f"No dependabot commits in range {rev_spec}", file=sys.stderr)
return ""
messages.sort()
def replacer(match: Match[str]) -> str:
desc = match.group(1)
number = match.group(2)
return f"* {desc}. ([\\#{number}](https://github.com/matrix-org/synapse/issues/{number}))"
for i, message in enumerate(messages):
messages[i] = re.sub(r"(.*) \(#(\d+)\)$", replacer, message)
messages.insert(0, "### Updates to locked dependencies\n")
return "\n".join(messages)
@cli.command()
@click.argument("since")
def test_dependabot_changelog(since: str) -> None:
"""Test building the dependabot changelog.
Summarises all dependabot commits between the SINCE tag and the current git HEAD."""
print(build_dependabot_changelog(git.Repo("."), version.Version(since)))
if __name__ == "__main__": if __name__ == "__main__":
cli() cli()