diff --git a/.github/workflows/github-actions.yml b/.github/workflows/github-actions.yml deleted file mode 100644 index d5d5c42..0000000 --- a/.github/workflows/github-actions.yml +++ /dev/null @@ -1,83 +0,0 @@ -name: Ubuntu - -on: - push: - branches: - - develop - - master - - release/* - - main - pull_request: - -jobs: - build_and_test: - runs-on: ubuntu-latest - container: ghcr.io/nlohmann/json-ci:v2.4.0 - steps: - - run: echo "🎉 The job was automatically triggered by a ${{ github.event_name }} event." - - run: echo "🐧 This job is now running on a ${{ runner.os }} server hosted by GitHub." - - run: echo "🔎 Branch name is ${{ github.ref }} and repository is ${{ github.repository }}." - - name: Clone nlohmann json - uses: actions/checkout@master - with: - repository: nlohmann/json - path: nlohmann-json - ref: v3.11.2 - - name: Build and install nlohmann json - run: | - cd nlohmann-json - cmake -S . -B build - cmake --build build --target install -j$(nproc) - cd .. - - name: Clone json-schema-validator - uses: actions/checkout@v2 - - name: cmake - run: cmake -S . -B build - - name: build - run: cmake --build build --target all -j$(nproc) - - name: test - run: cd build && ctest - build_and_test_min_version: - runs-on: ubuntu-latest - container: ghcr.io/nlohmann/json-ci:v2.4.0 - steps: - - run: echo "🎉 The job was automatically triggered by a ${{ github.event_name }} event." - - run: echo "🐧 This job is now running on a ${{ runner.os }} server hosted by GitHub." - - run: echo "🔎 Branch name is ${{ github.ref }} and repository is ${{ github.repository }}." - - name: Clone nlohmann json - uses: actions/checkout@master - with: - repository: nlohmann/json - path: nlohmann-json - ref: v3.8.0 - - name: Build and install nlohmann json - run: | - cd nlohmann-json - cmake -S . -B build - cmake --build build --target install -j$(nproc) - cd .. - - name: Clone json-schema-validator - uses: actions/checkout@v2 - - name: cmake - run: cmake -S . -B build - - name: build - run: cmake --build build --target all -j$(nproc) - - name: test - run: cd build && ctest - build_conan: - runs-on: ubuntu-latest - container: ghcr.io/nlohmann/json-ci:v2.4.0 - steps: - - run: echo "🎉 The job was automatically triggered by a ${{ github.event_name }} event." - - run: echo "🐧 This job is now running on a ${{ runner.os }} server hosted by GitHub." - - run: echo "🔎 Branch name is ${{ github.ref }} and repository is ${{ github.repository }}." - - name: Clone json-schema-validator - uses: actions/checkout@v3 - - uses: actions/setup-python@v4 - with: - python-version: '3.10' - - run: python -m pip install --upgrade conan - - run: conan config init - - run: conan profile update settings.compiler.libcxx=libstdc++11 default - - name: conan create package - run: conan create . diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml new file mode 100644 index 0000000..8897a61 --- /dev/null +++ b/.github/workflows/release.yaml @@ -0,0 +1,31 @@ +name: release +run-name: Release + +on: + push: + tags: + - "v[0-9]+.[0-9]+.[0-9]+" + - "v[0-9]+.[0-9]+.[0-9]+-rc[0-9]+" + +jobs: + tests: + uses: ./.github/workflows/test.yaml + secrets: inherit + + build_conan: + runs-on: ubuntu-latest + container: ghcr.io/nlohmann/json-ci:v2.4.0 + steps: + - run: echo "🎉 The job was automatically triggered by a ${{ github.event_name }} event." + - run: echo "🐧 This job is now running on a ${{ runner.os }} server hosted by GitHub." + - run: echo "🔎 Branch name is ${{ github.ref }} and repository is ${{ github.repository }}." + - name: Clone json-schema-validator + uses: actions/checkout@v3 + - uses: actions/setup-python@v4 + with: + python-version: '3.10' + - run: python -m pip install --upgrade conan + - run: conan config init + - run: conan profile update settings.compiler.libcxx=libstdc++11 default + - name: conan create package + run: conan create . diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml new file mode 100644 index 0000000..0093b92 --- /dev/null +++ b/.github/workflows/test.yaml @@ -0,0 +1,109 @@ +name: test +run-name: Tests + +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] + # Make it able to be used in other workflows + workflow_call: + +defaults: + run: + shell: bash + +jobs: + pre-commit: + name: Check pre-commit + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-python@v4 + - uses: pre-commit/action@v3.0.0 + + test: + name: Run ctests + needs: [ pre-commit ] + continue-on-error: ${{ matrix.experimental }} + strategy: + fail-fast: false + matrix: + toolchain: [ gcc, llvm, intel ] + json_version: [ v3.11.2, v3.8.0 ] + experimental: [ false ] + include: + - toolchain: llvm + compiler_version: 15 + - toolchain: gcc + compiler_version: latest + env: + NLOHMANN_JSON_VERSION: ${{ matrix.json_version }} + runs-on: ubuntu-latest + container: ghcr.io/nlohmann/json-ci:v2.4.0 + steps: + - name: Activate Intel compilers + # Not elegant, it will propagate all environment variable. + # Intel does not provide a way to output the environment variables to a file + # Note: PATH needs to be exported to GITHUB_PATH otherwise it can be overwritten + run: | + source /opt/intel/oneapi/setvars.sh + printenv >> $GITHUB_ENV + echo $PATH >> $GITHUB_PATH + if: matrix.toolchain == 'intel' + - name: Setup gcc toolchain + run: | + update-alternatives --install /usr/bin/g++ g++ $(which g++-${{ matrix.compiler_version }}) 999 + if: matrix.compiler_version && matrix.toolchain == 'gcc' + - name: Setup llvm toolchain + run: | + update-alternatives --install /usr/bin/clang++ clang++ $(which clang++-${{ matrix.compiler_version }}) 999 + if: matrix.compiler_version && matrix.toolchain == 'llvm' + - name: Clone nlohmann json version ${{ matrix.json_version }} + uses: actions/checkout@v3 + with: + repository: nlohmann/json + path: nlohmann-json + ref: ${{ matrix.json_version }} + # TODO: Move to FetchContent managed + - name: Build and install nlohmann json + run: | + cd nlohmann-json + cmake -S . -B build + cmake --build build --target install -j$(nproc) + cd .. + - name: Clone json-schema-validator + uses: actions/checkout@v3 + # container version is < 3.25 which does not have workflows + - name: Get latest cmake version + uses: lukka/get-cmake@latest + - name: Run CMake ${{ matrix.toolchain }}-ci workflow with nlohmann/json version ${{ matrix.json_version }} + uses: lukka/run-cmake@v10.5 + with: + workflowPreset: "${{ matrix.toolchain }}-ci" + coverage: + name: Run coverage tests + needs: [ test ] + runs-on: ubuntu-latest + container: ghcr.io/nlohmann/json-ci:v2.4.0 + # TODO: Temporarily disabled because not implemented + if: ${{ false && (github.event_name == 'push' || github.event_name == 'pull_request') }} + steps: + - uses: actions/checkout@v3 + - name: Get latest cmake version + uses: lukka/get-cmake@latest + - name: Get test coverage + uses: lukka/run-cmake@v10.5 + with: + workflowPreset: ci-coverage + - name: Get lcov data + uses: danielealbano/lcov-action@v3 + with: + # Note lcov-action prepends and appends wild-cards *. Account for those + # https://github.com/danielealbano/lcov-action/issues/11 + remove_patterns: /test/,/cmake-build*/ + - name: Upload coverage to Codecov + uses: codecov/codecov-action@v3 + with: + files: coverage.info + verbose: true diff --git a/.gitignore b/.gitignore index 6b334d3..aceaf81 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ build*/ *.sw? - +cmake-build-* +venv +env +compile_commands.json diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..2eaa1a1 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,32 @@ +repos: + - repo: https://github.com/Takishima/cmake-pre-commit-hooks + rev: v1.8.1 + hooks: + - id: clang-format + args: + - '-i' + - id: clang-tidy + args: + # TODO: Remove when upstream issue is fixed + # https://gitlab.kitware.com/cmake/cmake/-/issues/24827 + # https://github.com/Takishima/cmake-pre-commit-hooks/issues/63 + - '-Bcmake-build-pre-commit' + - '--preset' + - 'pre-commit' + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.4.0 + hooks: + - id: trailing-whitespace + - id: end-of-file-fixer + - id: check-yaml + - repo: https://github.com/executablebooks/mdformat + rev: 0.7.16 + hooks: + - id: mdformat + additional_dependencies: + - mdformat-gfm + - mdformat-tables + - repo: https://github.com/python-jsonschema/check-jsonschema + rev: 0.23.0 + hooks: + - id: check-github-workflows diff --git a/CMakePresets.json b/CMakePresets.json new file mode 100644 index 0000000..51696d4 --- /dev/null +++ b/CMakePresets.json @@ -0,0 +1,7 @@ +{ + "version": 6, + "include": [ + "cmake/CMakePresets-defaults.json", + "cmake/CMakePresets-CI.json" + ] +} diff --git a/README.md b/README.md index 1e930bf..e9b80ed 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,3 @@ - [![Build Status](https://travis-ci.org/pboettch/json-schema-validator.svg?branch=master)](https://travis-ci.org/pboettch/json-schema-validator) # JSON schema validator for JSON for Modern C++ @@ -23,7 +22,7 @@ is rather simple. Although significant changes have been done for the 2nd version (a complete rewrite) the API is compatible with the 1.0.0 release. Except for -the namespace which is now `nlohmann::json_schema. +the namespace which is now `nlohmann::json_schema`. Version **2** supports JSON schema draft 7, whereas 1 was supporting draft 4 only. Please update your schemas. @@ -101,6 +100,7 @@ By default a static library is built. Shared libraries can be generated by using the `BUILD_SHARED_LIBS`-cmake variable: In your initial call to cmake simply add: + ```bash cmake [..] -DBUILD_SHARED_LIBS=ON [..] ``` @@ -151,6 +151,7 @@ and ```CMake target_link_libraries( [..] nlohmann_json_schema_validator) ``` + to build and link. ## Code @@ -298,9 +299,10 @@ json_validator validator(loader, // or nullptr for no loader Supported formats: `date-time, date, time, email, hostname, ipv4, ipv6, uuid, regex` -More formats can be added in `src/string-format-check.cpp`. Please contribute implementions for missing json schema draft formats. +More formats can be added in `src/string-format-check.cpp`. Please contribute implementions for missing json schema draft formats. ## Default value processing + As a result of the validation, the library returns a json patch including the default values of the specified schema. ```C++ @@ -348,15 +350,17 @@ int main() return EXIT_SUCCESS; } ``` + The example above will output the specified default values `{"height":10,"width":20}` to stdout. + > Note that the default value specified in a `$ref` may be overridden by the current instance location. Also note that this behavior will break draft-7, but it is compliant to newer drafts (e.g. `2019-09` or `2020-12`). # Contributing -Before opening a pull request, please apply the coding style given in the -`.clang-format` by running clang-format from the git top-level for all touched -files: +This project uses [`pre-commit`](https://pre-commit.com/) to enforce style-checks. Please install and run it before +creating commits and making pull requests. -```shell -git diff master --name-only | grep '\.[ch]pp$' | xargs -P 3 -I{} clang-format -i {} +```console +$ pip install pre-commit +$ pre-commit install ``` diff --git a/cmake/CMakePresets-CI.json b/cmake/CMakePresets-CI.json new file mode 100644 index 0000000..4dae53c --- /dev/null +++ b/cmake/CMakePresets-CI.json @@ -0,0 +1,253 @@ +{ + "version": 6, + "include": [ + "CMakePresets-defaults.json" + ], + "configurePresets": [ + { + "name": "ci-base", + "hidden": true, + "generator": "Ninja", + "inherits": [ + "default" + ], + "cacheVariables": { + "JSON_VALIDATOR_BUILD_TESTS": { + "type": "BOOL", + "value": true + } + }, + "errors": { + "deprecated": true + } + }, + { + "name": "gcc-ci", + "displayName": "Configure preset for GCC toolchain", + "inherits": [ + "ci-base" + ], + "binaryDir": "cmake-build-release-gcc", + "cacheVariables": { + "CMAKE_CXX_COMPILER": { + "type": "FILEPATH", + "value": "g++" + }, + "CMAKE_LINKER": { + "type": "FILEPATH", + "value": "ld" + } + } + }, + { + "name": "intel-ci", + "displayName": "Configure preset for Intel toolchain", + "inherits": [ + "ci-base" + ], + "binaryDir": "cmake-build-release-intel", + "cacheVariables": { + "CMAKE_CXX_COMPILER": { + "type": "FILEPATH", + "value": "icpx" + } + } + }, + { + "name": "llvm-ci", + "displayName": "Configure preset for LLVM toolchain", + "inherits": [ + "ci-base" + ], + "binaryDir": "cmake-build-release-llvm", + "cacheVariables": { + "CMAKE_CXX_COMPILER": { + "type": "FILEPATH", + "value": "clang++" + }, + "CMAKE_LINKER": { + "type": "FILEPATH", + "value": "lld" + } + } + }, + { + "name": "ci-coverage", + "displayName": "Configure preset for test coverage", + "inherits": [ + "gcc-ci" + ], + "binaryDir": "cmake-build-coverage", + "errors": { + "deprecated": false + } + }, + { + "name": "pre-commit", + "displayName": "Configure preset for pre-commit checks", + "inherits": [ + "default" + ], + "binaryDir": "cmake-build-pre-commit" + } + ], + "buildPresets": [ + { + "name": "ci-base", + "hidden": true, + "inherits": [ + "default" + ], + "cleanFirst": true + }, + { + "name": "ci-coverage", + "displayName": "Build preset for test coverage", + "inherits": [ + "ci-base" + ], + "configurePreset": "ci-coverage" + }, + { + "name": "gcc-ci", + "displayName": "Build preset for GCC toolchain", + "inherits": [ + "ci-base" + ], + "configurePreset": "gcc-ci" + }, + { + "name": "intel-ci", + "displayName": "Build preset for Intel toolchain", + "inherits": [ + "ci-base" + ], + "configurePreset": "intel-ci" + }, + { + "name": "llvm-ci", + "displayName": "Build preset for LLVM toolchain", + "inherits": [ + "ci-base" + ], + "configurePreset": "llvm-ci" + } + ], + "testPresets": [ + { + "name": "ci-base", + "hidden": true, + "inherits": [ + "default" + ], + "output": { + "outputOnFailure": true + } + }, + { + "name": "ci-coverage", + "inherits": [ + "default" + ], + "configurePreset": "ci-coverage" + }, + { + "name": "gcc-ci", + "displayName": "Test preset for GCC toolchain", + "inherits": [ + "ci-base" + ], + "configurePreset": "gcc-ci" + }, + { + "name": "intel-ci", + "displayName": "Test preset for Intel toolchain", + "inherits": [ + "ci-base" + ], + "configurePreset": "intel-ci" + }, + { + "name": "llvm-ci", + "displayName": "Test preset for LLVM toolchain", + "inherits": [ + "ci-base" + ], + "configurePreset": "llvm-ci" + } + ], + "workflowPresets": [ + { + "name": "gcc-ci", + "displayName": "CI test for GCC toolchain", + "steps": [ + { + "type": "configure", + "name": "gcc-ci" + }, + { + "type": "build", + "name": "gcc-ci" + }, + { + "type": "test", + "name": "gcc-ci" + } + ] + }, + { + "name": "intel-ci", + "displayName": "CI test for Intel toolchain", + "steps": [ + { + "type": "configure", + "name": "intel-ci" + }, + { + "type": "build", + "name": "intel-ci" + }, + { + "type": "test", + "name": "intel-ci" + } + ] + }, + { + "name": "llvm-ci", + "displayName": "CI test for LLVM toolchain", + "steps": [ + { + "type": "configure", + "name": "llvm-ci" + }, + { + "type": "build", + "name": "llvm-ci" + }, + { + "type": "test", + "name": "llvm-ci" + } + ] + }, + { + "name": "ci-coverage", + "displayName": "Coverage tests", + "steps": [ + { + "type": "configure", + "name": "ci-coverage" + }, + { + "type": "build", + "name": "ci-coverage" + }, + { + "type": "test", + "name": "ci-coverage" + } + ] + } + ] +} diff --git a/cmake/CMakePresets-defaults.json b/cmake/CMakePresets-defaults.json new file mode 100644 index 0000000..bfc642c --- /dev/null +++ b/cmake/CMakePresets-defaults.json @@ -0,0 +1,50 @@ +{ + "version": 6, + "configurePresets": [ + { + "name": "default", + "displayName": "Default configuration preset", + "binaryDir": "cmake-build-release", + "cacheVariables": { + "CMAKE_BUILD_TYPE": { + "type": "STRING", + "value": "Release" + } + } + } + ], + "buildPresets": [ + { + "name": "default", + "displayName": "Default build preset", + "configurePreset": "default" + } + ], + "testPresets": [ + { + "name": "default", + "displayName": "Default test preset", + "configurePreset": "default" + } + ], + "workflowPresets": [ + { + "name": "default", + "displayName": "Default workflow", + "steps": [ + { + "type": "configure", + "name": "default" + }, + { + "type": "build", + "name": "default" + }, + { + "type": "test", + "name": "default" + } + ] + } + ] +}