CI: Force changelog updates

Maxime “pep” Buquet created

Changelog updates are now required in MRs by default. If there is a
match for "\<skip.\?changelog\>" in the commit message, this will be
ignored.

$CI_COMMIT_MESSAGE mangles newlines so it's not possible to require the
string to be on its own line, that means it would also trigger within a
wall of text, which makes it less obvious.

Also, I wasn't able to find a CI variable which has the ref of the
branch the MR is set against, to build a tree-ish than spans over the
whole MR and not just HEAD.

Signed-off-by: Maxime “pep” Buquet <pep@bouah.net>

Change summary

.forgejo/workflows/check-changelog.py | 40 ++++++++++++++++++++++++++++
.gitlab-ci.yml                        | 20 ++++++++++++++
xmpp/ChangeLog                        |  2 +
3 files changed, 62 insertions(+)

Detailed changes

.forgejo/workflows/check-changelog.py 🔗

@@ -0,0 +1,40 @@
+#!/usr/bin/env python3
+# -*- encoding: utf-8 -*-
+# vim: set et ts=4 sts=4 sw=4
+
+import os
+import re
+import subprocess
+import sys
+
+
+if __name__ == '__main__':
+    # Skip this check if instructed
+    if re.search(r'skip.?changelog', os.environ['CI_COMMIT_MESSAGE'], flags=re.I) is not None:
+        print('Changelog skipped.')
+        sys.exit(0)
+
+    treeish = 'main..'
+    if os.environ['CI_PIPELINE_SOURCE'] == 'merge_request_event':
+        treeish = '{}..'.format(os.environ['CI_MERGE_REQUEST_DIFF_BASE_SHA'])
+
+    diff=subprocess.run(
+        ['git', 'diff-tree', '--no-commit-id', '-r', treeish, '--'],
+        capture_output=True,
+    )
+
+    if diff.stderr:
+        print(f'An error occured: {diff.stderr}')
+        sys.exit(1)
+
+    print(f'Files in {treeish}:\n{diff.stdout}')
+
+    # Verify if at least a single changelog file has been added or edited
+    if re.search(rb'[AM]\s+\S*changelog', diff.stdout, flags=re.I) is None:
+        print(
+            'Please update the Changelog. Use "skip-changelog" '
+            'in the commit message to skip this check.',
+        )
+        sys.exit(1)
+
+    print('Changelog has been updated as expected.')

.gitlab-ci.yml 🔗

@@ -68,6 +68,26 @@ rustfmt:
     - if: $CI_PIPELINE_SOURCE == 'merge_request_event'
     - if: $CI_PIPELINE_SOURCE == 'push' && $CI_COMMIT_REF_NAME == 'main'
 
+changelog-update:
+  stage: lint
+  image: alpine:latest
+  # Check in the commit message for "skip.?changelog", if not present
+  # then check for changes in changelogs.
+  # XXX: It looks like $CI_COMMIT_MESSAGE mangles newlines so it's not
+  # possible to require the "skip.?changelog" string to be on its own line,
+  # that means it would also trigger within a wall of text. Not so obvious.
+  # TODO: Check the whole MR for updates in changelogs, not just the last
+  # commit.
+  script:
+    - apk add --no-cache python3 git
+    - python3 --version
+    - git version
+    - git log --oneline "${CI_MERGE_REQUEST_DIFF_BASE_SHA}.." --
+    - python3 .forgejo/workflows/check-changelog.py
+  rules:
+    - if: $CI_PIPELINE_SOURCE == 'merge_request_event'
+    - if: $CI_PIPELINE_SOURCE == 'push' && $CI_COMMIT_REF_NAME == 'main'
+
 stable-test:
   extends:
     - .test

xmpp/ChangeLog 🔗

@@ -24,6 +24,8 @@ XXXX-YY-ZZ [ RELEASER <admin@localhost> ]
       - Agent::wait_for_events now return Vec<Event> and sets inner tokio_xmpp Client
         auto-reconnect to true... It is still aware of Event::Disconnected but should
         no longer have weird hanging state or panic (!436)
+    * CI:
+      - Enforce changelog updates in Gitlab CI.
 
 Version 0.6.0:
 2024-07-27 [ Maxime “pep” Buquet <pep@bouah.net> ]