From 972f5cc10bfe4c0baa04c4c4dcf686e525f18cd7 Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Thu, 2 Jul 2026 23:05:00 +0200 Subject: [PATCH] Attach a ready-to-apply patch when the amalgamation check fails (#5229) When a PR is not amalgamated/formatted, the astyle version friction (see the recurring blocker across many PRs) means contributors often struggle to reproduce the exact fix locally. The check now regenerates the amalgamation and formatting, captures the difference as a patch, and uploads it as the `amalgamation-patch` artifact. The failure comment links to that artifact and tells contributors to run `git apply amalgamation.patch`, so they no longer need to install the pinned astyle version themselves. The pass/fail verdict is unchanged: the same PRs fail as before, and a correctly amalgamated PR uploads nothing and passes. Signed-off-by: Niels Lohmann Co-authored-by: Claude Opus 4.8 --- .github/workflows/check_amalgamation.yml | 44 ++++++++++++++----- .../workflows/comment_check_amalgamation.yml | 16 ++++++- 2 files changed, 46 insertions(+), 14 deletions(-) diff --git a/.github/workflows/check_amalgamation.yml b/.github/workflows/check_amalgamation.yml index 480488af7..eb4107371 100644 --- a/.github/workflows/check_amalgamation.yml +++ b/.github/workflows/check_amalgamation.yml @@ -57,22 +57,42 @@ jobs: python3 -mvenv venv venv/bin/pip3 install -r $MAIN_DIR/tools/astyle/requirements.txt - - name: Check amalgamation + - name: Regenerate amalgamation and formatting run: | cd $MAIN_DIR - rm -fr $INCLUDE_DIR/json.hpp~ $INCLUDE_DIR/json_fwd.hpp~ - cp $INCLUDE_DIR/json.hpp $INCLUDE_DIR/json.hpp~ - cp $INCLUDE_DIR/json_fwd.hpp $INCLUDE_DIR/json_fwd.hpp~ - python3 $TOOL_DIR/amalgamate.py -c $TOOL_DIR/config_json.json -s . python3 $TOOL_DIR/amalgamate.py -c $TOOL_DIR/config_json_fwd.json -s . - echo "Format (1)" - ${{ github.workspace }}/venv/bin/astyle --project=tools/astyle/.astylerc --suffix=none --quiet $INCLUDE_DIR/json.hpp $INCLUDE_DIR/json_fwd.hpp - diff $INCLUDE_DIR/json.hpp~ $INCLUDE_DIR/json.hpp - diff $INCLUDE_DIR/json_fwd.hpp~ $INCLUDE_DIR/json_fwd.hpp + ${{ github.workspace }}/venv/bin/astyle --project=tools/astyle/.astylerc --suffix=none --quiet \ + $INCLUDE_DIR/json.hpp $INCLUDE_DIR/json_fwd.hpp - ${{ github.workspace }}/venv/bin/astyle --project=tools/astyle/.astylerc --suffix=orig $(find docs/examples include tests -type f \( -name '*.hpp' -o -name '*.cpp' -o -name '*.cu' \) -not -path 'tests/thirdparty/*' -not -path 'tests/abi/include/nlohmann/*' | sort) - echo Check - find $MAIN_DIR -name '*.orig' -exec false {} \+ + ${{ github.workspace }}/venv/bin/astyle --project=tools/astyle/.astylerc --suffix=none --quiet \ + $(find docs/examples include tests -type f \( -name '*.hpp' -o -name '*.cpp' -o -name '*.cu' \) -not -path 'tests/thirdparty/*' -not -path 'tests/abi/include/nlohmann/*' | sort) + + - name: Build patch and check for differences + id: diff + run: | + cd $MAIN_DIR + mkdir -p ${{ github.workspace }}/patch + git diff --patch --no-color > ${{ github.workspace }}/patch/amalgamation.patch + if [ -s ${{ github.workspace }}/patch/amalgamation.patch ]; then + echo "The source code has not been amalgamated/formatted correctly. Diff:" + cat ${{ github.workspace }}/patch/amalgamation.patch + echo "has_diff=true" >> "$GITHUB_OUTPUT" + else + echo "has_diff=false" >> "$GITHUB_OUTPUT" + fi + + # Uploaded so contributors can fix their PR with `git apply amalgamation.patch` + # instead of installing the pinned astyle version locally. + - name: Upload patch + if: steps.diff.outputs.has_diff == 'true' + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: amalgamation-patch + path: patch/amalgamation.patch + + - name: Fail if not amalgamated/formatted + if: steps.diff.outputs.has_diff == 'true' + run: exit 1 diff --git a/.github/workflows/comment_check_amalgamation.yml b/.github/workflows/comment_check_amalgamation.yml index c49eb2553..6ff9fb1e8 100644 --- a/.github/workflows/comment_check_amalgamation.yml +++ b/.github/workflows/comment_check_amalgamation.yml @@ -24,6 +24,7 @@ jobs: egress-policy: audit - name: 'Download artifact' + id: download uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 with: script: | @@ -43,6 +44,9 @@ jobs: }); var fs = require('fs'); fs.writeFileSync('${{github.workspace}}/pr.zip', Buffer.from(download.data)); + + var hasPatch = artifacts.data.artifacts.some((artifact) => artifact.name == "amalgamation-patch"); + core.setOutput('has_patch', String(hasPatch)); - run: unzip pr.zip - name: 'Comment on PR' @@ -70,12 +74,20 @@ jobs: break } } + const hasPatch = '${{ steps.download.outputs.has_patch }}' === 'true'; + const runUrl = '${{ github.event.workflow_run.html_url }}'; + await github.rest.issues.createComment({ issue_number: issue_number, owner: context.repo.owner, repo: context.repo.repo, - body: '## šŸ”“ Amalgamation check failed! šŸ”“\nThe source code has not been amalgamated.' - + (first ? ' @' + author + ' Please read and follow the [Contribution Guidelines]' + body: '## šŸ”“ Amalgamation check failed! šŸ”“\nThe source code has not been amalgamated and/or formatted correctly.' + + (hasPatch ? '\n\nšŸ“Ž A ready-to-apply patch is attached to the [failed workflow run](' + runUrl + ') as the `amalgamation-patch` artifact.' + + ' Download it, then apply it locally from the repository root with:' + + '\n\n```shell\ngit apply amalgamation.patch\n```\n\n' + + 'This does not require installing astyle yourself.' + : '') + + (first ? '\n\n@' + author + ' Please read and follow the [Contribution Guidelines]' + '(https://github.com/nlohmann/json/blob/develop/.github/CONTRIBUTING.md#files-to-change).' : '') })