Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,18 @@ jobs:
- name: Every type the header declares has a page and no member is bare
run: ctest --test-dir build -R reference --output-on-failure

# The rules the surface gate rests on, before the gate that rests
# on them. These need neither Doxygen nor the header, and they run
# first because a wrong rule makes the gate below pass rather than
# fail, which is the failure that would not be reported.
- name: What identifies a declaration, and what is only its shape
run: ctest --test-dir build -R surface-cases --output-on-failure

# api/surface.txt is a reviewed file. This is what tells a
# reviewer it should have been in the diff.
- name: The published surface is still what api/surface.txt says
run: ctest --test-dir build -R '^surface$' --output-on-failure

# So that a reviewer can read the page a change to a comment
# produced rather than take the diff's word for it.
- uses: actions/upload-artifact@v4
Expand Down
22 changes: 20 additions & 2 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,23 +39,41 @@ jobs:
- name: Every type the header declares has a page and no member is bare
run: ctest --test-dir build -R reference --output-on-failure

# And the surface, which at a tag is not a review aid any more. A
# release whose api/surface.txt is out of date is a release whose
# published names are not the ones anybody agreed to, and the tag
# is the last moment that can still be found out cheaply.
- name: The published surface is still what api/surface.txt says
run: ctest --test-dir build -R 'surface' --output-on-failure

- name: Pack it
run: |
set -eu
tar -czf "zu-cpp-reference-${GITHUB_REF_NAME}.tar.gz" \
-C build/docs/reference html
cp api/surface.txt "zu-cpp-surface-${GITHUB_REF_NAME}.txt"

- uses: actions/upload-artifact@v4
with:
name: reference
path: zu-cpp-reference-*.tar.gz
path: |
zu-cpp-reference-*.tar.gz
zu-cpp-surface-*.txt
if-no-files-found: error

# Only on a tag. A manual run builds the reference and leaves the
# artifact, which is what somebody checking this file wants, and
# does not attach anything to a release that is not there.
#
# The surface goes up beside the reference and not only inside it.
# It is one text file, and two of them from two releases diff into
# the answer to the question somebody upgrading is actually
# asking, which no amount of generated HTML will give them.
- name: Attach it to the release
if: startsWith(github.ref, 'refs/tags/')
run: gh release upload "$GITHUB_REF_NAME" "zu-cpp-reference-${GITHUB_REF_NAME}.tar.gz" --clobber
run: |
gh release upload "$GITHUB_REF_NAME" \
"zu-cpp-reference-${GITHUB_REF_NAME}.tar.gz" \
"zu-cpp-surface-${GITHUB_REF_NAME}.txt" --clobber
env:
GH_TOKEN: ${{ github.token }}
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,8 @@ lynn
- `cmake/`, `find_package(Zu)` to find the engine and `find_package(zu-cpp)` to find this. vcpkg, Conan and pkg-config packaging come with the first release.
- `docs/`, the API reference, generated from `include/zu.hpp` and published with the release rather than checked in beside the source. `docs/reference.py` is the part worth reading: Doxygen exits 0 on a header it extracted nothing from, so the check counts the types the header declares and fails when the reference does not have them, which is what an empty reference looks like from the outside.

- `api/surface.txt`, every name `include/zu.hpp` publishes and the shape it publishes it in, one per line. It is generated by `docs/surface.py` out of the same Doxygen run as the reference, and a change to the header that moves it fails CI until the file is regenerated, so moving the public surface is a diff a reviewer reads rather than something a user finds out about after upgrading. The check tells apart what went, what arrived and what changed shape, because a name that arrived is a minor release and a name that went is not.

- `scripts/install.sh`, the install a person with nothing on their machine gets, run nightly in a container holding a compiler and nothing else. It installs the wrapper, takes both programs off this page, builds them against the install and diffs what they print against the blocks under them. It is run again three times with a piece taken out of the install, because a build that still works without the header is a build that found one somewhere else.

Four sanitizer jobs run over the suite, because an ABI nine languages depend on should fail loudly rather than corrupt quietly. The whole tree runs under ASan and UBSan; `test/misuse.c` runs again with leak detection on, which it can and the C++ files cannot, because it is the file that gives every handle back by hand; `test/threads.c` runs under TSan; and both C files run under valgrind, which sees what the sanitizers cannot, since libzu is compiled without instrumentation and memcheck does not need any. `test/tsan.supp` records what TSan is unable to be told about a library that takes no pthread lock, and why the reports from inside the engine are dropped rather than read.
Expand All @@ -131,7 +133,7 @@ cmake -B build -DZU_CPP_DOCS=ON
cmake --build build --target docs
```

No engine is needed for that one either.
No engine is needed for that one either. The same option adds the surface gate, and `cmake --build build --target surface-update` rewrites `api/surface.txt` when the header was meant to move.

The wrapper is header-only, so a project that would rather not use CMake needs the include path and nothing else.

Expand Down
Loading
Loading