Files
json/.github/workflows/check_amalgamation.yml
T
Niels Lohmann 6a28560c87 Clean up CI, CMake, Makefile, and Bazel files
- CMakeLists.txt: avoid VERSION_GREATER_EQUAL, which CMake < 3.7 lacks
- ci.cmake: test JSON_DisableTupleReferenceConversion in ci_cmake_flags,
  remove unused variables and unreachable per-compiler targets, look up
  Clang tools consistently, forward CMAKE_CXX_FLAGS to ci_module_cpp20,
  format json_literals.hpp and remove backups in ci_test_amalgamation
- BUILD.bazel: add json_literals.hpp to the single-header target
- workflows: format json_literals.hpp before copying it, drop the obsolete
  natvis --version plumbing, name natvis and macro_builder in failure
  messages, drop the duplicate amalgamation job, install Valgrind only
  where needed, republish docs on version bumps, fix stale names
- Makefile: complete .PHONY and help, check-amalgamation always restores
  the checked-in files, natvis uses its own venv, macro_builder_check
  installs astyle, clean removes the fuzzer binaries
- remove tools/amalgamate/config_json_view.json (json_view.hpp is not on
  develop yet)

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
2026-10-10 13:27:26 +02:00

181 lines
7.8 KiB
YAML

name: "Check amalgamation"
on:
pull_request:
# also check develop itself: a PR can be merged before its own run of this
# workflow completes (e.g. while it is still queued), leaving single_include
# stale on develop without any failing check
push:
branches:
- develop
concurrency:
group: ${{ github.workflow }}-${{ github.ref || github.run_id }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
permissions:
contents: read
jobs:
save:
if: github.event_name == 'pull_request'
runs-on: ubuntu-latest
steps:
- name: Harden Runner
uses: step-security/harden-runner@e14015d583714f6e62063499dc959a02595150a1 # v2.21.1
with:
egress-policy: audit
- name: Save PR number
run: |
mkdir -p ./pr
echo ${{ github.event.number }} > ./pr/number
echo ${{ github.event.pull_request.user.login }} > ./pr/author
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: pr
path: pr/
check:
runs-on: ubuntu-latest
env:
MAIN_DIR: ${{ github.workspace }}/main
INCLUDE_DIR: ${{ github.workspace }}/main/single_include/nlohmann
TOOL_DIR: ${{ github.workspace }}/tools/tools/amalgamate
NATVIS_TOOL_DIR: ${{ github.workspace }}/tools/tools/generate_natvis
steps:
- name: Harden Runner
uses: step-security/harden-runner@e14015d583714f6e62063499dc959a02595150a1 # v2.21.1
with:
egress-policy: audit
- name: Checkout pull request or pushed commit
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
path: main
ref: ${{ github.event.pull_request.head.sha || github.sha }}
persist-credentials: false
- name: Checkout tools
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
path: tools
ref: develop
persist-credentials: false
- name: Install astyle
run: |
python3 -mvenv venv
venv/bin/pip3 install -r $MAIN_DIR/tools/astyle/requirements.txt
- name: Install generate_natvis dependencies
run: pip3 install -r $NATVIS_TOOL_DIR/requirements.txt
- name: Regenerate the tools/macro_builder tables in macro_scope.hpp
run: |
cd $MAIN_DIR
# Built from this PR's own tools/macro_builder/main.cpp, not a
# develop checkout: unlike amalgamate.py and generate_natvis.py,
# this tool has no other source of truth to check against (its
# own README documents that it must reproduce macro_scope.hpp
# byte for byte), so there is nothing to gain from checking out a
# separate copy, and doing so would make this step fail on a PR
# that adds support for a new dispatch table until that PR itself
# merges to develop.
TMPDIR=$(mktemp -d ./macro_builder_check.XXXXXX)
c++ -std=c++11 tools/macro_builder/main.cpp -o "$TMPDIR/macro_builder"
"$TMPDIR/macro_builder" > "$TMPDIR/paste.hpp"
"$TMPDIR/macro_builder" type_body > "$TMPDIR/type_body.hpp"
# Splice the (still unindented) generated blocks back into
# macro_scope.hpp; the astyle pass below indents their
# continuation lines the same way it does for the rest of
# include/, so a correctly regenerated file comes out unchanged.
awk -v newfile="$TMPDIR/paste.hpp" '
BEGIN { while ((getline line < newfile) > 0) { new = new line "\n" } }
/^#define NLOHMANN_JSON_EXPAND\( x \) x$/ { printf "%s", new; skip=1 }
skip && /^#define NLOHMANN_JSON_DOUBLE_PASTE63\(/ { skip=0; next }
skip { next }
{ print }
' include/nlohmann/detail/macro_scope.hpp > "$TMPDIR/macro_scope_1.hpp"
awk -v newfile="$TMPDIR/type_body.hpp" '
BEGIN { while ((getline line < newfile) > 0) { new = new line "\n" } }
/^#define NLOHMANN_JSON_TYPE_BODY\(Prefix, \.\.\.\)/ { printf "%s", new; skip=1 }
skip && /^[[:space:]]*NLOHMANN_JSON_TYPE_BODY_SENTINEL\)\)$/ { skip=0; next }
skip { next }
{ print }
' "$TMPDIR/macro_scope_1.hpp" > "$TMPDIR/macro_scope_2.hpp"
mv "$TMPDIR/macro_scope_2.hpp" include/nlohmann/detail/macro_scope.hpp
rm -rf "$TMPDIR"
- name: Regenerate amalgamation, formatting, and BUILD.bazel
run: |
cd $MAIN_DIR
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 .
# the header list of the Bazel "json" target must match the files in include/
cmake -P cmake/scripts/gen_bazel_build_file.cmake
${{ github.workspace }}/venv/bin/astyle --project=tools/astyle/.astylerc --suffix=none --quiet \
$INCLUDE_DIR/json.hpp $INCLUDE_DIR/json_fwd.hpp
# fail loudly if a directory is renamed or removed: find would only warn
# about the missing path and silently drop its files from the check
SOURCE_DIRS="docs/mkdocs/docs/examples include tests"
for DIR in $SOURCE_DIRS; do
if [ ! -d "$DIR" ]; then
echo "::error::source directory '$DIR' does not exist"
exit 1
fi
done
${{ github.workspace }}/venv/bin/astyle --project=tools/astyle/.astylerc --suffix=none --quiet \
$(find $SOURCE_DIRS -type f \( -name '*.hpp' -o -name '*.cpp' -o -name '*.cu' \) -not -path 'tests/thirdparty/*' -not -path 'tests/abi/include/nlohmann/*' | sort)
# json_literals.hpp is copied verbatim from the (now formatted) include/
# directory, like `make amalgamate` does
cp include/nlohmann/json_literals.hpp $INCLUDE_DIR/json_literals.hpp
- name: Regenerate nlohmann_json.natvis
run: |
cd $MAIN_DIR
# The template is what this check verifies the committed natvis
# file against, so take it from this PR rather than from the
# develop checkout: generate_natvis.py loads the template from its
# own directory, and with develop's copy a PR that changes the
# template could never pass. Like the macro_builder step above,
# this only renders PR content in a job without credentials.
cp tools/generate_natvis/nlohmann_json.natvis.j2 $NATVIS_TOOL_DIR/
python3 $NATVIS_TOOL_DIR/generate_natvis.py $MAIN_DIR
- 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, or BUILD.bazel, nlohmann_json.natvis, or the macro_builder tables in macro_scope.hpp are out of date ('make amalgamate BUILD.bazel natvis' fixes all but the tables, see tools/macro_builder/README.md). 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