Browse Source

Create dependabot changelogs at release time (#15481)

* Ditch dependabot changelog workflow

* Summarise dependabot commits in release script

* Changelog

* Update scripts-dev/release.py
tags/v1.85.0rc1
David Robertson 11 months ago
committed by GitHub
parent
commit
42786d8a47
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 57 additions and 57 deletions
  1. +0
    -49
      .github/workflows/dependabot_changelog.yml
  2. +1
    -0
      changelog.d/15481.misc
  3. +7
    -5
      docs/development/dependencies.md
  4. +49
    -3
      scripts-dev/release.py

+ 0
- 49
.github/workflows/dependabot_changelog.yml 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
- 0
changelog.d/15481.misc View File

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

+ 7
- 5
docs/development/dependencies.md 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?

Synapse uses Dependabot to keep the `poetry.lock` file up-to-date. When it
creates a pull request a GitHub Action will run to automatically create a changelog
file. Ensure that:
Synapse uses Dependabot to keep the `poetry.lock` and `Cargo.lock` file
up-to-date with the latest releases of our dependencies. The changelog check is
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 upstream changelog file (linked in the description) doesn't include any
breaking changes;
* continuous integration passes (due to permissions, the GitHub Actions run on
the changelog commit will fail, look at the initial commit of the pull request);
* continuous integration passes.

In particular, any updates to the type hints (usually packages which start with `types-`)
should be safe to merge if linting passes.


+ 49
- 3
scripts-dev/release.py View File

@@ -27,7 +27,7 @@ import time
import urllib.request
from os import path
from tempfile import TemporaryDirectory
from typing import Any, List, Optional
from typing import Any, List, Match, Optional, Union

import attr
import click
@@ -233,7 +233,7 @@ def _prepare() -> None:
subprocess.check_output(["poetry", "version", new_version])

# Generate changelogs.
generate_and_write_changelog(current_version, new_version)
generate_and_write_changelog(synapse_repo, current_version, new_version)

# Generate debian changelogs
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(
current_version: version.Version, new_version: str
repo: Repo, current_version: version.Version, new_version: str
) -> None:
# We do this by getting a draft so that we can edit it before writing to the
# changelog.
@@ -827,6 +827,10 @@ def generate_and_write_changelog(
new_changes = new_changes.replace(
"No significant changes.", f"No significant changes since {current_version}."
)
new_changes += build_dependabot_changelog(
repo,
current_version,
)

# Prepend changes to changelog
with open("CHANGES.md", "r+") as f:
@@ -841,5 +845,47 @@ def generate_and_write_changelog(
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__":
cli()

Loading…
Cancel
Save