name: Continuous Integration on: [push, pull_request] jobs: lint: name: Lint runs-on: ubuntu-20.04 steps: - name: Install run: sudo apt-get install -y clang-format - name: Checkout uses: actions/checkout@v3 - name: Symlinks run: find * -type l -printf "::error::%p is a symlink. This is forbidden by the Arduino Library Specification." -exec false {} + - name: Clang-format run: | find src/ extras/ -name '*.[ch]pp' | xargs clang-format -i --verbose --style=file git diff --exit-code - name: Check URLs run: | grep -hREo "(http|https)://[a-zA-Z0-9./?=_%:-]*" src/ | sort -u | while read -r URL do STATUS=$(curl -s -o /dev/null -I -w "%{http_code}" "$URL") [ "$STATUS" -ge 400 ] && echo "::warning title=HTTP $STATUS::$URL returned $STATUS" done || true gcc: name: GCC needs: lint runs-on: ubuntu-22.04 strategy: fail-fast: false matrix: include: - gcc: "4.4" - gcc: "4.6" - gcc: "4.7" - gcc: "4.8" - gcc: "4.9" - gcc: "5" - gcc: "6" - gcc: "7" cxxflags: -fsanitize=leak -fno-sanitize-recover=all - gcc: "8" cxxflags: -fsanitize=undefined -fno-sanitize-recover=all - gcc: "9" cxxflags: -fsanitize=address -fno-sanitize-recover=all - gcc: "10" cxxflags: -funsigned-char # Issue #1715 - gcc: "11" steps: - name: Install run: | sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 40976EAF437D05B5 3B4FE6ACC0B21F32 sudo add-apt-repository -yn 'deb http://archive.ubuntu.com/ubuntu/ trusty main universe' sudo add-apt-repository -yn 'deb http://archive.ubuntu.com/ubuntu/ xenial main universe' sudo add-apt-repository -yn 'deb http://archive.ubuntu.com/ubuntu/ bionic main universe' sudo add-apt-repository -yn 'deb http://archive.ubuntu.com/ubuntu/ focal main universe' sudo apt-get update sudo apt-get install -y gcc-${{ matrix.gcc }} g++-${{ matrix.gcc }} - name: Checkout uses: actions/checkout@v3 - name: Configure run: cmake -DCMAKE_BUILD_TYPE=Debug . env: CC: gcc-${{ matrix.gcc }} CXX: g++-${{ matrix.gcc }} CXXFLAGS: ${{ matrix.cxxflags }} - name: Build run: cmake --build . - name: Test run: | echo "## CTest output" >> $GITHUB_STEP_SUMMARY echo '```' >> $GITHUB_STEP_SUMMARY ctest --output-on-failure -C Debug . | tee -a $GITHUB_STEP_SUMMARY echo '```' >> $GITHUB_STEP_SUMMARY env: UBSAN_OPTIONS: print_stacktrace=1 clang: name: Clang needs: lint runs-on: ubuntu-20.04 strategy: fail-fast: false matrix: include: - clang: "3.5" cxxflags: "-stdlib=libc++" - clang: "3.6" cxxflags: "-stdlib=libc++" - clang: "3.7" cxxflags: "-stdlib=libc++" - clang: "3.8" cxxflags: "-stdlib=libc++" - clang: "3.9" cxxflags: "-stdlib=libc++" - clang: "4.0" cxxflags: "-stdlib=libc++" - clang: "5.0" - clang: "6.0" - clang: "7" - clang: "8" cxxflags: -fsanitize=leak -fno-sanitize-recover=all - clang: "9" cxxflags: -fsanitize=undefined -fno-sanitize-recover=all - clang: "10" cxxflags: -fsanitize=address -fno-sanitize-recover=all steps: - name: Install run: | sudo add-apt-repository -yn 'deb http://archive.ubuntu.com/ubuntu/ trusty main' sudo add-apt-repository -yn 'deb http://archive.ubuntu.com/ubuntu/ trusty universe' sudo add-apt-repository -yn 'deb http://archive.ubuntu.com/ubuntu/ xenial main' sudo add-apt-repository -yn 'deb http://archive.ubuntu.com/ubuntu/ xenial universe' sudo add-apt-repository -yn 'deb http://archive.ubuntu.com/ubuntu/ bionic main' sudo add-apt-repository -yn 'deb http://archive.ubuntu.com/ubuntu/ bionic universe' sudo apt-get update sudo apt-get install -y clang-${{ matrix.clang }} - name: Checkout uses: actions/checkout@v3 - name: Configure run: cmake -DCMAKE_BUILD_TYPE=Debug . env: CC: clang-${{ matrix.clang }} CXX: clang++-${{ matrix.clang }} CXXFLAGS: >- ${{ matrix.cxxflags }} ${{ contains(matrix.cxxflags, 'libc++') && '-I/usr/lib/llvm-10/include/c++/v1/' || '' }} - name: Build run: cmake --build . - name: Test run: | echo "## CTest output" >> $GITHUB_STEP_SUMMARY echo '```' >> $GITHUB_STEP_SUMMARY ctest --output-on-failure -C Debug . | tee -a $GITHUB_STEP_SUMMARY echo '```' >> $GITHUB_STEP_SUMMARY env: UBSAN_OPTIONS: print_stacktrace=1 conf_test: name: Test configuration on Linux needs: [gcc, clang] runs-on: ubuntu-20.04 steps: - name: Install run: | sudo apt-get update sudo apt-get install -y g++-multilib - name: Checkout uses: actions/checkout@v3 - name: GCC 32-bit run: g++ -std=c++11 -m32 -Isrc extras/conf_test/x86.cpp - name: GCC 64-bit run: g++ -std=c++11 -m64 -Isrc extras/conf_test/x64.cpp - name: Clang 32-bit run: clang++ -std=c++11 -m32 -Isrc extras/conf_test/x86.cpp - name: Clang 64-bit run: clang++ -std=c++11 -m64 -Isrc extras/conf_test/x64.cpp conf_test_windows: name: Test configuration on Windows runs-on: windows-2019 needs: [gcc, clang] steps: - name: Checkout uses: actions/checkout@v3 - name: 32-bit run: | call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars32.bat" cl /Isrc extras/conf_test/x86.cpp shell: cmd - name: 64-bit run: | call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat" cl /Isrc extras/conf_test/x64.cpp shell: cmd xcode: name: XCode needs: clang runs-on: macos-11 strategy: fail-fast: false matrix: include: - xcode: "11.7" - xcode: "12.4" - xcode: "13.2.1" steps: - name: Checkout uses: actions/checkout@v3 - name: Select XCode version run: sudo xcode-select --switch /Applications/Xcode_${{ matrix.xcode }}.app - name: Configure run: cmake -DCMAKE_BUILD_TYPE=Debug . - name: Build run: cmake --build . - name: Test run: ctest --output-on-failure -C Debug . # DISABLED: Running on AppVeyor instead because it supports older versions of the compiler # msvc: # name: Visual Studio # strategy: # fail-fast: false # matrix: # include: # - os: windows-2016 # - os: windows-2019 # runs-on: ${{ matrix.os }} # steps: # - name: Checkout # uses: actions/checkout@v3 # - name: Configure # run: cmake -DCMAKE_BUILD_TYPE=Debug . # - name: Build # run: cmake --build . # - name: Test # run: ctest --output-on-failure -C Debug . arduino: name: Arduino needs: gcc strategy: fail-fast: false matrix: include: - core: arduino:avr board: arduino:avr:uno - core: arduino:samd board: arduino:samd:mkr1000 runs-on: ubuntu-20.04 steps: - name: Checkout uses: actions/checkout@v3 - name: Install arduino-cli run: curl -fsSL https://raw.githubusercontent.com/arduino/arduino-cli/master/install.sh | BINDIR=/usr/local/bin sh - name: Install core run: arduino-cli core install ${{ matrix.core }} - name: Install libraries run: arduino-cli lib install SD Ethernet - name: Build JsonConfigFile run: arduino-cli compile --library . --warnings all -b ${{ matrix.board }} "examples/JsonConfigFile/JsonConfigFile.ino" - name: Build JsonFilterExample run: arduino-cli compile --library . --warnings all -b ${{ matrix.board }} "examples/JsonFilterExample/JsonFilterExample.ino" - name: Build JsonGeneratorExample run: arduino-cli compile --library . --warnings all -b ${{ matrix.board }} "examples/JsonGeneratorExample/JsonGeneratorExample.ino" - name: Build JsonHttpClient run: arduino-cli compile --library . --warnings all -b ${{ matrix.board }} "examples/JsonHttpClient/JsonHttpClient.ino" - name: Build JsonParserExample run: arduino-cli compile --library . --warnings all -b ${{ matrix.board }} "examples/JsonParserExample/JsonParserExample.ino" - name: Build JsonServer run: arduino-cli compile --library . --warnings all -b ${{ matrix.board }} "examples/JsonServer/JsonServer.ino" - name: Build JsonUdpBeacon run: arduino-cli compile --library . --warnings all -b ${{ matrix.board }} "examples/JsonUdpBeacon/JsonUdpBeacon.ino" - name: Build MsgPackParser run: arduino-cli compile --library . --warnings all -b ${{ matrix.board }} "examples/MsgPackParser/MsgPackParser.ino" - name: Build ProgmemExample run: arduino-cli compile --library . --warnings all -b ${{ matrix.board }} "examples/ProgmemExample/ProgmemExample.ino" - name: Build StringExample run: arduino-cli compile --library . --warnings all -b ${{ matrix.board }} "examples/StringExample/StringExample.ino" platformio: name: PlatformIO needs: gcc runs-on: ubuntu-latest strategy: fail-fast: false matrix: include: - platform: atmelavr board: leonardo libraries: - SD - Ethernet conf_test: avr - platform: espressif8266 board: huzzah conf_test: esp8266 - platform: espressif32 board: esp32dev libraries: - Ethernet conf_test: esp8266 - platform: atmelsam board: mkr1000USB libraries: - SD - Ethernet conf_test: esp8266 - platform: teensy board: teensy31 conf_test: esp8266 - platform: ststm32 board: adafruit_feather_f405 libraries: - SD - Ethernet conf_test: esp8266 - platform: nordicnrf52 board: adafruit_feather_nrf52840 libraries: - SD - Ethernet conf_test: esp8266 steps: - name: Checkout uses: actions/checkout@v3 - name: Set up cache for pip uses: actions/cache@v3 with: path: ~/.cache/pip key: ${{ runner.os }}-pip - name: Set up Python 3.x uses: actions/setup-python@v4 with: python-version: "3.x" - name: Install PlatformIO run: pip install platformio - name: Install adafruit-nrfutil if: ${{ matrix.platform == 'nordicnrf52' }} run: pip install adafruit-nrfutil - name: Include Adafruit_TinyUSB.h # https://github.com/adafruit/Adafruit_nRF52_Arduino/issues/653 if: ${{ matrix.platform == 'nordicnrf52' }} run: find examples/ -name '*.ino' -exec sed -i 's/\(#include \)/\1\n#include /' {} + - name: Set up cache for platformio uses: actions/cache@v3 with: path: ~/.platformio key: ${{ runner.os }}-platformio-${{ matrix.platform }} - name: Install platform "${{ matrix.platform }}" run: platformio platform install ${{ matrix.platform }} - name: Install libraries if: ${{ matrix.libraries }} run: platformio lib install arduino-libraries/${{ join(matrix.libraries, ' arduino-libraries/') }} - name: Test configuration run: platformio ci "extras/conf_test/${{ matrix.conf_test }}.cpp" -l '.' -b ${{ matrix.board }} if: ${{ matrix.conf_test }} - name: Build JsonConfigFile run: platformio ci "examples/JsonConfigFile/JsonConfigFile.ino" -l '.' -b ${{ matrix.board }} - name: Build JsonFilterExample run: platformio ci "examples/JsonFilterExample/JsonFilterExample.ino" -l '.' -b ${{ matrix.board }} - name: Build JsonGeneratorExample run: platformio ci "examples/JsonGeneratorExample/JsonGeneratorExample.ino" -l '.' -b ${{ matrix.board }} - name: Build JsonHttpClient run: platformio ci "examples/JsonHttpClient/JsonHttpClient.ino" -l '.' -b ${{ matrix.board }} - name: Build JsonParserExample run: platformio ci "examples/JsonParserExample/JsonParserExample.ino" -l '.' -b ${{ matrix.board }} - name: Build JsonServer if: ${{ matrix.platform != 'espressif32' }} run: platformio ci "examples/JsonServer/JsonServer.ino" -l '.' -b ${{ matrix.board }} - name: Build JsonUdpBeacon run: platformio ci "examples/JsonUdpBeacon/JsonUdpBeacon.ino" -l '.' -b ${{ matrix.board }} - name: Build MsgPackParser run: platformio ci "examples/MsgPackParser/MsgPackParser.ino" -l '.' -b ${{ matrix.board }} - name: Build ProgmemExample run: platformio ci "examples/ProgmemExample/ProgmemExample.ino" -l '.' -b ${{ matrix.board }} - name: Build StringExample run: platformio ci "examples/StringExample/StringExample.ino" -l '.' -b ${{ matrix.board }} - name: PlatformIO prune if: ${{ always() }} run: platformio system prune -f particle: name: Particle needs: gcc runs-on: ubuntu-latest if: github.event_name == 'push' strategy: fail-fast: false matrix: include: - board: argon steps: - name: Checkout uses: actions/checkout@v3 - name: Install Particle CLI run: sudo npm install -g particle-cli - name: Login to Particle run: particle login -t "${{ secrets.PARTICLE_TOKEN }}" - name: Compile run: extras/ci/particle.sh ${{ matrix.board }} arm: name: GCC for ARM processor needs: gcc runs-on: ubuntu-20.04 steps: - name: Install run: | sudo apt-get update sudo apt-get install -y g++-arm-linux-gnueabihf - name: Checkout uses: actions/checkout@v3 - name: Configure run: cmake . env: CC: arm-linux-gnueabihf-gcc CXX: arm-linux-gnueabihf-g++ - name: Build run: cmake --build . coverage: needs: gcc name: Coverage runs-on: ubuntu-20.04 steps: - name: Install run: sudo apt-get install -y lcov ninja-build - name: Checkout uses: actions/checkout@v3 - name: Configure run: cmake -G Ninja -DCOVERAGE=true . - name: Build run: ninja - name: Test run: ctest -LE 'WillFail|Fuzzing' -T test - name: lcov --capture run: lcov --capture --no-external --directory . --output-file coverage.info - name: lcov --remove run: lcov --remove coverage.info "$(pwd)/extras/*" --output-file coverage_filtered.info - name: genhtml run: mkdir coverage && genhtml coverage_filtered.info -o coverage -t ArduinoJson - name: Upload HTML report uses: actions/upload-artifact@v3 with: name: Coverage report path: coverage - name: Upload to Coveralls uses: coverallsapp/github-action@master with: github-token: ${{ secrets.GITHUB_TOKEN }} path-to-lcov: coverage_filtered.info valgrind: needs: gcc name: Valgrind runs-on: ubuntu-20.04 steps: - name: Install run: | sudo apt-get update sudo apt-get install -y valgrind ninja-build - name: Checkout uses: actions/checkout@v3 - name: Configure run: cmake -G Ninja -D MEMORYCHECK_COMMAND_OPTIONS="--error-exitcode=1 --leak-check=full" . - name: Build run: ninja - name: Memcheck run: ctest -LE WillFail -T memcheck id: memcheck - name: MemoryChecker.*.log run: cat Testing/Temporary/MemoryChecker.*.log if: failure() clang-tidy: needs: clang name: Clang-Tidy runs-on: ubuntu-20.04 steps: - name: Install run: sudo apt-get install -y clang-tidy cmake ninja-build - name: Checkout uses: actions/checkout@v3 - name: Configure run: cmake -G Ninja -DCMAKE_CXX_CLANG_TIDY="clang-tidy-10;--warnings-as-errors=*" -DCMAKE_BUILD_TYPE=Debug . env: CC: clang-10 CXX: clang++-10 - name: Check run: cmake --build . -- -k 0 amalgamate-h: needs: gcc name: Amalgamate ArduinoJson.h runs-on: ubuntu-20.04 steps: - name: Checkout uses: actions/checkout@v3 - name: Amalgamate id: amalgamate run: | if [[ $GITHUB_REF == refs/tags/* ]]; then VERSION=${GITHUB_REF#refs/tags/} else VERSION=${GITHUB_SHA::7} fi INPUT=src/ArduinoJson.h OUTPUT=ArduinoJson-$VERSION.h extras/scripts/build-single-header.sh "$INPUT" "$OUTPUT" echo "filename=${OUTPUT}" >> $GITHUB_OUTPUT - name: Smoke test run: | g++ -x c++ - < doc; deserializeJson(doc, "{}"); } END - name: Upload artifact uses: actions/upload-artifact@v3 with: name: Single headers path: ${{ steps.amalgamate.outputs.filename }} amalgamate-hpp: needs: gcc name: Amalgamate ArduinoJson.hpp runs-on: ubuntu-20.04 steps: - name: Checkout uses: actions/checkout@v3 - name: Amalgamate id: amalgamate run: | if [[ $GITHUB_REF == refs/tags/* ]]; then VERSION=${GITHUB_REF#refs/tags/} else VERSION=${GITHUB_SHA::7} fi INPUT=src/ArduinoJson.hpp OUTPUT=ArduinoJson-$VERSION.hpp extras/scripts/build-single-header.sh "$INPUT" "$OUTPUT" echo "filename=${OUTPUT}" >> $GITHUB_OUTPUT - name: Smoke test run: | g++ -x c++ - < doc; deserializeJson(doc, "{}"); } END - name: Upload artifact uses: actions/upload-artifact@v3 with: name: Single headers path: ${{ steps.amalgamate.outputs.filename }} esp-idf: needs: gcc name: ESP-IDF runs-on: ubuntu-latest steps: - name: Setup cache uses: actions/cache@v3 with: path: ~/.espressif key: ${{ runner.os }}-esp-idf - name: Checkout ArduinoJson uses: actions/checkout@v3 - name: Checkout ESP-IDF uses: actions/checkout@v3 with: repository: espressif/esp-idf path: esp-idf submodules: true - name: Install ESP-IDF run: ./esp-idf/install.sh - name: Add component # NOTE: we cannot commit the symlink because the Arduino Library Specification forbids it. run: | mkdir -p extras/ci/espidf/components ln -s $PWD extras/ci/espidf/components/ArduinoJson - name: Build example run: | source esp-idf/export.sh cd extras/ci/espidf idf.py build codeql: name: CodeQL runs-on: ubuntu-20.04 needs: gcc permissions: actions: read contents: read security-events: write steps: - name: Checkout repository uses: actions/checkout@v3 - name: Initialize CodeQL uses: github/codeql-action/init@v2 with: languages: cpp - name: Build run: | cmake -DCMAKE_BUILD_TYPE=Debug . cmake --build . - name: Perform CodeQL Analysis uses: github/codeql-action/analyze@v2 with: category: "/language:cpp"