chore: add smoke test and redesign CI workflow

Add a smoke test that validates the binary links all dependencies
at runtime by instantiating a client without networking. Redesign
CI into separate build and test jobs, with test gated on build.
This commit is contained in:
Patryk Osmaczko 2026-02-12 21:31:17 +01:00
parent 5525f2fb33
commit 66bf357a73
No known key found for this signature in database
GPG Key ID: 6A385380FD275B44
7 changed files with 135 additions and 106 deletions

106
.github/workflows/ci.yml vendored Normal file
View File

@ -0,0 +1,106 @@
name: ci
on:
pull_request:
branches:
- main
paths-ignore:
- "**README.md"
- ".gitignore"
- "LICENSE"
jobs:
build:
strategy:
matrix:
os: [ubuntu-latest, macOS-latest]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v6
with:
submodules: recursive
# Cache the Nim compiler built by nimbus-build-system (NBS).
# Building Nim from source is the slowest part of `make update`.
# Keyed on the NBS submodule commit — auto-invalidates when NBS is bumped.
- id: nbs
run: echo "hash=$(git rev-parse HEAD:vendor/nimbus-build-system)" >> $GITHUB_OUTPUT
- uses: actions/cache@v4
with:
path: vendor/nimbus-build-system/vendor/Nim
key: ${{ runner.os }}-nbs-${{ steps.nbs.outputs.hash }}
- run: make update
- run: make all
test:
needs: build
strategy:
matrix:
os: [ubuntu-latest, macOS-latest]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v6
with:
submodules: recursive
- id: nbs
run: echo "hash=$(git rev-parse HEAD:vendor/nimbus-build-system)" >> $GITHUB_OUTPUT
- uses: actions/cache@v4
with:
path: vendor/nimbus-build-system/vendor/Nim
key: ${{ runner.os }}-nbs-${{ steps.nbs.outputs.hash }}
- run: make update
- run: make tests
test-windows:
needs: build
runs-on: windows-latest
defaults:
run:
shell: msys2 {0}
env:
MSYSTEM: MINGW64
steps:
- uses: actions/checkout@v6
with:
submodules: recursive
- uses: msys2/setup-msys2@v2
with:
update: true
install: >-
git
base-devel
mingw-w64-x86_64-toolchain
make
cmake
upx
mingw-w64-x86_64-rust
mingw-w64-x86_64-postgresql
mingw-w64-x86_64-gcc
mingw-w64-x86_64-gcc-libs
mingw-w64-x86_64-libwinpthread-git
mingw-w64-x86_64-zlib
mingw-w64-x86_64-openssl
mingw-w64-x86_64-python
mingw-w64-x86_64-cmake
mingw-w64-x86_64-llvm
mingw-w64-x86_64-clang
- run: |
echo "/usr/bin:$PATH" >> $GITHUB_PATH
echo "/mingw64/bin:$PATH" >> $GITHUB_PATH
echo "/usr/lib:$PATH" >> $GITHUB_PATH
echo "/mingw64/lib:$PATH" >> $GITHUB_PATH
- run: which upx gcc g++ make cmake cargo rustc python make mingw32-make
- id: nbs
run: echo "hash=$(git rev-parse HEAD:vendor/nimbus-build-system)" >> $GITHUB_OUTPUT
shell: bash
- uses: actions/cache@v4
with:
path: vendor/nimbus-build-system/vendor/Nim
key: ${{ runner.os }}-nbs-${{ steps.nbs.outputs.hash }}
- run: make update
- run: |
cd vendor/nwaku/vendor/nim-nat-traversal/vendor/miniupnp/miniupnpc
make -f Makefile.mingw CC=gcc CXX=g++ libminiupnpc.a V=1
- run: |
cd vendor/nwaku/vendor/nim-nat-traversal/vendor/libnatpmp-upstream
make CC="gcc -fPIC -D_WIN32_WINNT=0x0600 -DNATPMP_STATICLIB" libnatpmp.a V=1
- run: make tests

View File

@ -1,76 +0,0 @@
name: test-windows
on:
pull_request:
branches:
- main
paths-ignore:
- '**README.md'
- '.gitignore'
- 'LICENSE'
jobs:
tests-tasks:
runs-on: windows-latest
defaults:
run:
shell: msys2 {0}
env:
MSYSTEM: MINGW64
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Setup MSYS2
uses: msys2/setup-msys2@v2
with:
update: true
install: >-
git
base-devel
mingw-w64-x86_64-toolchain
make
cmake
upx
mingw-w64-x86_64-rust
mingw-w64-x86_64-postgresql
mingw-w64-x86_64-gcc
mingw-w64-x86_64-gcc-libs
mingw-w64-x86_64-libwinpthread-git
mingw-w64-x86_64-zlib
mingw-w64-x86_64-openssl
mingw-w64-x86_64-python
mingw-w64-x86_64-cmake
mingw-w64-x86_64-llvm
mingw-w64-x86_64-clang
- name: Add UPX to PATH
run: |
echo "/usr/bin:$PATH" >> $GITHUB_PATH
echo "/mingw64/bin:$PATH" >> $GITHUB_PATH
echo "/usr/lib:$PATH" >> $GITHUB_PATH
echo "/mingw64/lib:$PATH" >> $GITHUB_PATH
- name: Verify dependencies
run: |
which upx gcc g++ make cmake cargo rustc python make mingw32-make
- name: Update
run: make update
- name: Building miniupnpc
run: |
cd vendor/nwaku/vendor/nim-nat-traversal/vendor/miniupnp/miniupnpc
make -f Makefile.mingw CC=gcc CXX=g++ libminiupnpc.a V=1
cd ../../../../../../..
- name: Building libnatpmp
run: |
cd vendor/nwaku/vendor/nim-nat-traversal/vendor/libnatpmp-upstream
make CC="gcc -fPIC -D_WIN32_WINNT=0x0600 -DNATPMP_STATICLIB" libnatpmp.a V=1
cd ../../../../../../
- name: Tests
run: make tests

View File

@ -1,23 +0,0 @@
name: test
on:
pull_request:
branches:
- main
paths-ignore:
- '**README.md'
- '.gitignore'
- 'LICENSE'
jobs:
tests-tasks:
strategy:
matrix:
os: [ubuntu-latest, macOS-latest]
runs-on: ${{ matrix.os }}
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Update
run: make update
- name: Tests
run: make tests

View File

@ -34,7 +34,7 @@ endif
.PHONY: all update clean
# default target, because it's the first one that doesn't start with '.'
all: | bot_echo pingpong
all: | bot_echo pingpong liblogoschat
test_file := $(word 2,$(MAKECMDGOALS))
define test_name

View File

@ -1,7 +1,7 @@
import ffi
import src/chat/client
declareLibrary("chat")
declareLibrary("logoschat")
proc set_event_callback(
ctx: ptr FFIContext[ChatClient],

View File

@ -39,17 +39,17 @@ proc buildLibrary(name: string, srcDir = "library/", params = "", lang = "c") =
## Build a shared library (.so on Linux, .dylib on macOS, .dll on Windows)
if not dirExists "build":
mkDir "build"
# Determine library extension based on OS
let libExt = when defined(macosx): "dylib"
elif defined(windows): "dll"
else: "so"
var extra_params = params
for i in 2 ..< paramCount():
extra_params &= " " & paramStr(i)
exec "nim " & lang & " --app:lib --out:build/lib" & name & "." & libExt &
exec "nim " & lang & " --app:lib --out:build/lib" & name & "." & libExt &
" --mm:refc --nimMainPrefix:lib" & name & " " & extra_params & " " &
srcDir & "lib" & name & ".nim"
@ -59,6 +59,7 @@ proc test(name: string, params = "-d:chronicles_log_level=DEBUG", lang = "c") =
task tests, "Build & run tests":
test "all_tests", "-d:chronicles_log_level=ERROR -d:chronosStrictException"
test "smoke_test", "-d:chronicles_log_level=ERROR"
task waku_example, "Build Waku based simple example":
let name = "waku_example"
@ -77,5 +78,5 @@ task pingpong, "Build the Pingpong example":
buildBinary name, "examples/", "-d:chronicles_log_level='INFO' -d:chronicles_disabled_topics='waku node' "
task liblogoschat, "Build the Chat SDK shared library (C bindings)":
buildLibrary "logoschat", "library/",
buildLibrary "logoschat", "library/",
"-d:chronicles_log_level='INFO' -d:chronicles_enabled=on --path:src --path:vendor/nim-ffi"

21
tests/smoke_test.nim Normal file
View File

@ -0,0 +1,21 @@
# Smoke test: validates that the binary links all dependencies at runtime.
# No networking, no start(), no message exchange — just instantiation.
import ../src/chat
proc main() =
try:
let waku = initWakuClient(DefaultConfig())
let ident = createIdentity("SmokeTest")
var client = newClient(waku, ident)
if client.isNil:
raise newException(CatchableError, "newClient returned nil")
let id = client.getId()
echo "smoke_test: OK (client id: " & id & ")"
quit(QuitSuccess)
except CatchableError as e:
echo "smoke_test: FAILED — " & e.msg
quit(QuitFailure)
when isMainModule:
main()