Create dependabot changelogs at release time (#15481)
* Ditch dependabot changelog workflow * Summarise dependabot commits in release script * Changelog * Update scripts-dev/release.pypull/15699/head
parent
626bd75f48
commit
42786d8a47
|
@ -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.
|
|
|
@ -0,0 +1 @@
|
||||||
|
Create dependabot changelogs at release time.
|
|
@ -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.
|
||||||
|
|
|
@ -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()
|
||||||
|
|
Loading…
Reference in New Issue