mirror of
https://github.com/threeal/cmake-action.git
synced 2025-12-15 12:55:13 +00:00
Compare commits
No commits in common. "main" and "v1.1.0" have entirely different histories.
2
.gitattributes
vendored
2
.gitattributes
vendored
@ -1,2 +0,0 @@
|
|||||||
dist/** -diff linguist-generated
|
|
||||||
pnpm-lock.yaml -diff linguist-generated
|
|
||||||
18
.github/dependabot.yaml
vendored
18
.github/dependabot.yaml
vendored
@ -1,18 +0,0 @@
|
|||||||
version: 2
|
|
||||||
updates:
|
|
||||||
- package-ecosystem: github-actions
|
|
||||||
directory: /
|
|
||||||
schedule:
|
|
||||||
interval: daily
|
|
||||||
commit-message:
|
|
||||||
prefix: chore
|
|
||||||
labels: []
|
|
||||||
|
|
||||||
- package-ecosystem: npm
|
|
||||||
directory: /
|
|
||||||
schedule:
|
|
||||||
interval: daily
|
|
||||||
commit-message:
|
|
||||||
prefix: chore
|
|
||||||
labels: []
|
|
||||||
versioning-strategy: increase
|
|
||||||
6
.github/dependabot.yml
vendored
Normal file
6
.github/dependabot.yml
vendored
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
version: 2
|
||||||
|
updates:
|
||||||
|
- package-ecosystem: github-actions
|
||||||
|
directory: /
|
||||||
|
schedule:
|
||||||
|
interval: daily
|
||||||
34
.github/workflows/build.yaml
vendored
34
.github/workflows/build.yaml
vendored
@ -1,34 +0,0 @@
|
|||||||
name: Build
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
pull_request:
|
|
||||||
push:
|
|
||||||
branches: [main]
|
|
||||||
jobs:
|
|
||||||
build-action:
|
|
||||||
name: Build Action
|
|
||||||
runs-on: ubuntu-24.04
|
|
||||||
steps:
|
|
||||||
- name: Checkout Project
|
|
||||||
uses: actions/checkout@v5.0.0
|
|
||||||
|
|
||||||
- name: Setup pnpm
|
|
||||||
uses: threeal/setup-pnpm-action@v1.0.0
|
|
||||||
|
|
||||||
- name: Install Dependencies
|
|
||||||
run: pnpm install
|
|
||||||
|
|
||||||
- name: Check Types
|
|
||||||
run: pnpm tsc
|
|
||||||
|
|
||||||
- name: Test Action
|
|
||||||
run: pnpm test
|
|
||||||
|
|
||||||
- name: Check Formatting
|
|
||||||
run: pnpm prettier --check .
|
|
||||||
|
|
||||||
- name: Check Lint
|
|
||||||
run: pnpm eslint
|
|
||||||
|
|
||||||
- name: Build Action
|
|
||||||
run: pnpm rollup -c && git diff --exit-code dist
|
|
||||||
149
.github/workflows/test.yaml
vendored
149
.github/workflows/test.yaml
vendored
@ -1,149 +0,0 @@
|
|||||||
name: Test
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
pull_request:
|
|
||||||
push:
|
|
||||||
branches: [main]
|
|
||||||
jobs:
|
|
||||||
test-action:
|
|
||||||
name: Test Action
|
|
||||||
runs-on: ${{ matrix.os }}
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
os: [ubuntu-24.04, macos-14, windows-2022]
|
|
||||||
steps:
|
|
||||||
- name: Checkout Sample Project
|
|
||||||
uses: actions/checkout@v5.0.0
|
|
||||||
with:
|
|
||||||
repository: threeal/cpp-starter
|
|
||||||
ref: v1.0.0
|
|
||||||
|
|
||||||
- name: Checkout Action
|
|
||||||
uses: actions/checkout@v5.0.0
|
|
||||||
with:
|
|
||||||
path: cmake-action
|
|
||||||
sparse-checkout: |
|
|
||||||
action.yml
|
|
||||||
dist
|
|
||||||
sparse-checkout-cone-mode: false
|
|
||||||
|
|
||||||
- name: Build Sample Project
|
|
||||||
id: cmake-action
|
|
||||||
uses: ./cmake-action
|
|
||||||
|
|
||||||
- name: Run Sample Project
|
|
||||||
run: ${{ steps.cmake-action.outputs.build-dir }}/${{ matrix.os == 'windows-2022' && 'Debug/generate_sequence.exe' || 'generate_sequence' }} 5
|
|
||||||
|
|
||||||
test-action-with-specified-dirs:
|
|
||||||
name: Test Action With Specified Directories
|
|
||||||
runs-on: ubuntu-24.04
|
|
||||||
steps:
|
|
||||||
- name: Checkout Sample Project
|
|
||||||
uses: actions/checkout@v5.0.0
|
|
||||||
with:
|
|
||||||
repository: threeal/cpp-starter
|
|
||||||
ref: v1.0.0
|
|
||||||
path: project
|
|
||||||
|
|
||||||
- name: Checkout Action
|
|
||||||
uses: actions/checkout@v5.0.0
|
|
||||||
with:
|
|
||||||
path: cmake-action
|
|
||||||
sparse-checkout: |
|
|
||||||
action.yml
|
|
||||||
dist
|
|
||||||
sparse-checkout-cone-mode: false
|
|
||||||
|
|
||||||
- name: Build Sample Project
|
|
||||||
id: cmake-action
|
|
||||||
uses: ./cmake-action
|
|
||||||
with:
|
|
||||||
source-dir: project
|
|
||||||
build-dir: output
|
|
||||||
|
|
||||||
- name: Run Sample Project
|
|
||||||
run: output/generate_sequence 5
|
|
||||||
|
|
||||||
test-action-without-run-build:
|
|
||||||
name: Test Action Without Run Build
|
|
||||||
runs-on: ubuntu-24.04
|
|
||||||
steps:
|
|
||||||
- name: Checkout Sample Project
|
|
||||||
uses: actions/checkout@v5.0.0
|
|
||||||
with:
|
|
||||||
repository: threeal/cpp-starter
|
|
||||||
ref: v1.0.0
|
|
||||||
|
|
||||||
- name: Checkout Action
|
|
||||||
uses: actions/checkout@v5.0.0
|
|
||||||
with:
|
|
||||||
path: cmake-action
|
|
||||||
sparse-checkout: |
|
|
||||||
action.yml
|
|
||||||
dist
|
|
||||||
sparse-checkout-cone-mode: false
|
|
||||||
|
|
||||||
- name: Modify Sample Project
|
|
||||||
run: echo 'invalid' >> src/main.cpp
|
|
||||||
|
|
||||||
- name: Configure Sample Project
|
|
||||||
uses: ./cmake-action
|
|
||||||
with:
|
|
||||||
run-build: false
|
|
||||||
|
|
||||||
test-action-with-additional-options:
|
|
||||||
name: Test Action With Additional Options
|
|
||||||
runs-on: ubuntu-24.04
|
|
||||||
steps:
|
|
||||||
- name: Checkout Sample Project
|
|
||||||
uses: actions/checkout@v5.0.0
|
|
||||||
with:
|
|
||||||
repository: threeal/cpp-starter
|
|
||||||
ref: v1.0.0
|
|
||||||
|
|
||||||
- name: Checkout Action
|
|
||||||
uses: actions/checkout@v5.0.0
|
|
||||||
with:
|
|
||||||
path: cmake-action
|
|
||||||
sparse-checkout: |
|
|
||||||
action.yml
|
|
||||||
dist
|
|
||||||
sparse-checkout-cone-mode: false
|
|
||||||
|
|
||||||
- name: Build Sample Project
|
|
||||||
uses: ./cmake-action
|
|
||||||
with:
|
|
||||||
options: BUILD_TESTING=ON
|
|
||||||
|
|
||||||
- name: Test Sample Project
|
|
||||||
uses: threeal/ctest-action@v1.1.0
|
|
||||||
|
|
||||||
test-action-with-custom-generator:
|
|
||||||
name: Test Action With Custom Generator
|
|
||||||
runs-on: ubuntu-24.04
|
|
||||||
steps:
|
|
||||||
- name: Checkout Sample Project
|
|
||||||
uses: actions/checkout@v5.0.0
|
|
||||||
with:
|
|
||||||
repository: threeal/cpp-starter
|
|
||||||
ref: v1.0.0
|
|
||||||
|
|
||||||
- name: Checkout Action
|
|
||||||
uses: actions/checkout@v5.0.0
|
|
||||||
with:
|
|
||||||
path: cmake-action
|
|
||||||
sparse-checkout: |
|
|
||||||
action.yml
|
|
||||||
dist
|
|
||||||
sparse-checkout-cone-mode: false
|
|
||||||
|
|
||||||
- name: Configure Sample Project
|
|
||||||
id: cmake-action
|
|
||||||
uses: ./cmake-action
|
|
||||||
with:
|
|
||||||
generator: Ninja
|
|
||||||
run-build: false
|
|
||||||
|
|
||||||
- name: Build Sample Project
|
|
||||||
run: ninja -C ${{ steps.cmake-action.outputs.build-dir }}
|
|
||||||
97
.github/workflows/test.yml
vendored
Normal file
97
.github/workflows/test.yml
vendored
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
name: test
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
push:
|
||||||
|
jobs:
|
||||||
|
default-usage:
|
||||||
|
runs-on: ${{ matrix.os }}-latest
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
os: [windows, ubuntu, macos]
|
||||||
|
steps:
|
||||||
|
- name: Check out this repository
|
||||||
|
uses: actions/checkout@v3.3.0
|
||||||
|
|
||||||
|
- name: Move test project to the working directory
|
||||||
|
run: mv test/* .
|
||||||
|
|
||||||
|
- name: Use this action
|
||||||
|
uses: ./
|
||||||
|
|
||||||
|
- name: Run the build result
|
||||||
|
run: ${{ matrix.os == 'windows' && 'build\Debug\hello_world.exe' || 'build/hello_world' }}
|
||||||
|
|
||||||
|
specified-dir-usage:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Check out this repository
|
||||||
|
uses: actions/checkout@v3.3.0
|
||||||
|
|
||||||
|
- name: Use this action with specified directories
|
||||||
|
uses: ./
|
||||||
|
with:
|
||||||
|
source-dir: test
|
||||||
|
build-dir: output
|
||||||
|
run-test: true
|
||||||
|
test-args: -R hello_world
|
||||||
|
|
||||||
|
- name: Check if the default build directory does not exist
|
||||||
|
run: test ! -d build && test ! -d test/build
|
||||||
|
|
||||||
|
additional-flags-usage:
|
||||||
|
runs-on: ${{ matrix.compiler == 'msvc' && 'windows' || 'ubuntu' }}-latest
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
compiler: [gcc, msvc]
|
||||||
|
steps:
|
||||||
|
- name: Check out this repository
|
||||||
|
uses: actions/checkout@v3.3.0
|
||||||
|
|
||||||
|
- name: Use this action with additional compiler flags
|
||||||
|
uses: ./
|
||||||
|
with:
|
||||||
|
source-dir: test
|
||||||
|
targets: test_c test_cpp
|
||||||
|
run-test: true
|
||||||
|
c-flags: ${{ matrix.compiler == 'msvc' && '/w /WX-' || '-Wno-unused-variable' }}
|
||||||
|
cxx-flags: ${{ matrix.compiler == 'msvc' && '/w /WX-' || '-Wno-unused-variable' }}
|
||||||
|
args: -D CHECK_SURPASS_WARNING=ON
|
||||||
|
test-args: -R test ${{ matrix.compiler == 'msvc' && '-C Debug' || '' }}
|
||||||
|
|
||||||
|
specified-compiler-usage:
|
||||||
|
runs-on: ${{ matrix.os }}-latest
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
os: [windows, ubuntu, macos]
|
||||||
|
steps:
|
||||||
|
- name: Check out this repository
|
||||||
|
uses: actions/checkout@v3.3.0
|
||||||
|
|
||||||
|
- name: Use this action with specified compilers
|
||||||
|
uses: ./
|
||||||
|
with:
|
||||||
|
source-dir: test
|
||||||
|
targets: test_c test_cpp
|
||||||
|
run-test: true
|
||||||
|
generator: Ninja
|
||||||
|
c-compiler: clang
|
||||||
|
cxx-compiler: clang++
|
||||||
|
args: -D CHECK_USING_CLANG=ON
|
||||||
|
test-args: -R test
|
||||||
|
|
||||||
|
specified-generator-usage:
|
||||||
|
runs-on: ${{ matrix.os }}-latest
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
os: [windows, ubuntu, macos]
|
||||||
|
steps:
|
||||||
|
- name: Check out this repository
|
||||||
|
uses: actions/checkout@v3.3.0
|
||||||
|
|
||||||
|
- name: Use this action with a specified generator
|
||||||
|
uses: ./
|
||||||
|
with:
|
||||||
|
source-dir: test
|
||||||
|
run-test: true
|
||||||
|
generator: Ninja
|
||||||
|
test-args: -R hello_world
|
||||||
7
.gitignore
vendored
7
.gitignore
vendored
@ -1,6 +1 @@
|
|||||||
.*
|
build
|
||||||
!.git*
|
|
||||||
!.npmrc
|
|
||||||
!.prettier*
|
|
||||||
|
|
||||||
node_modules/
|
|
||||||
|
|||||||
@ -1,3 +0,0 @@
|
|||||||
dist
|
|
||||||
pnpm-lock.yaml
|
|
||||||
README.md
|
|
||||||
@ -1,3 +0,0 @@
|
|||||||
{
|
|
||||||
"plugins": ["prettier-plugin-organize-imports"]
|
|
||||||
}
|
|
||||||
2
LICENSE
2
LICENSE
@ -1,6 +1,6 @@
|
|||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2023-2025 Alfi Maulana
|
Copyright (c) 2023 Alfi Maulana
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|||||||
136
README.md
136
README.md
@ -1,103 +1,107 @@
|
|||||||
# CMake Action
|
# CMake Action
|
||||||
|
|
||||||
Configure and build [CMake](https://cmake.org/) projects on [GitHub Actions](https://github.com/features/actions).
|
[](https://github.com/threeal/cmake-action/releases/)
|
||||||
|
[](./LICENSE)
|
||||||
|
[](https://github.com/threeal/cmake-action/actions/workflows/test.yml)
|
||||||
|
|
||||||
This action wraps the [`cmake`](https://cmake.org/cmake/help/latest/manual/cmake.1.html) command for configuring and building CMake projects. It provides a more streamlined syntax for specifying build options compared to calling the `cmake` command directly.
|
Configure, build, and test a [CMake](https://cmake.org/) project on [GitHub Actions](https://github.com/features/actions).
|
||||||
|
Use this action to simplify the workflow run of your CMake project.
|
||||||
|
This action will configure a build environment for your project using the `cmake` command,
|
||||||
|
then it will build your project by running a `cmake --build` command,
|
||||||
|
and last it could test your project using the `ctest` command.
|
||||||
|
|
||||||
## Available Inputs
|
## Features
|
||||||
|
|
||||||
|
- Configure and build a project using the [cmake](https://cmake.org/cmake/help/latest/manual/cmake.1.html) command.
|
||||||
|
- Optionally test a project using the [ctest](https://cmake.org/cmake/help/latest/manual/ctest.1.html) command.
|
||||||
|
- Auto-detect and install required dependencies.
|
||||||
|
- Specify multiple CMake options directly from the Action inputs.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
For more information, see [action.yml](./action.yml) and [GitHub Actions guide](https://docs.github.com/en/actions/learn-github-actions/understanding-github-actions).
|
||||||
|
|
||||||
|
### Inputs
|
||||||
|
|
||||||
| Name | Value Type | Description |
|
| Name | Value Type | Description |
|
||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
| `source-dir` | Path | The source directory of the CMake project. Defaults to the current working directory. |
|
| `source-dir` | Path | Source directory of the CMake project. Defaults to current directory. |
|
||||||
| `build-dir` | Path | The build directory of the CMake project. Defaults to the `build` directory inside the source directory. |
|
| `build-dir` | Path | Build directory of the CMake project. Defaults to `build` directory inside the source directory. |
|
||||||
| `generator` | String | The build system generator for the CMake project. Equivalent to setting the `-G` option. |
|
| `targets` | Multiple strings | List of build targets. |
|
||||||
| `c-compiler` | String | The preferred executable for compiling C language files. Equivalent to defining the `CMAKE_C_COMPILER` variable. |
|
| `run-test` | `true` or `false` | If enabled, run testing using [CTest](https://cmake.org/cmake/help/latest/manual/ctest.1.html). Defaults to `false`. |
|
||||||
| `cxx-compiler` | String | The preferred executable for compiling C++ language files. Equivalent to defining the `CMAKE_CXX_COMPILER` variable. |
|
| `generator` | String | Build system generator of the CMake project. |
|
||||||
| `c-flags` | Multiple strings | Additional flags to pass when compiling C language files. Equivalent to defining the `CMAKE_C_FLAGS` variable. |
|
| `c-compiler` | String | Preferred executable for compiling C language files. |
|
||||||
| `cxx-flags` | Multiple strings | Additional flags to pass when compiling C++ language files. Equivalent to defining the `CMAKE_CXX_FLAGS` variable. |
|
| `cxx-compiler` | String | Preferred executable for compiling C++ language files. |
|
||||||
| `options` | Multiple strings | Additional options to pass during the CMake configuration. Equivalent to setting the `-D` option. |
|
| `c-flags` | Multiple strings | Additional flags passed when compiling C language files. |
|
||||||
| `args` | Multiple strings | Additional arguments to pass during the CMake configuration. |
|
| `cxx-flags` | Multiple strings | Additional flags passed when compiling C++ language files. |
|
||||||
| `run-build` | `true` or `false` | If enabled, builds the project using CMake. Defaults to `true`. |
|
| `args` | Multiple strings | Additional arguments passed during the CMake configuration. |
|
||||||
| `build-args` | Multiple strings | Additional arguments to pass during the CMake build. |
|
| `test-args` | Multiple strings | Additional arguments passed during the CTest run. |
|
||||||
|
|
||||||
## Available Outputs
|
> Note: Multiple strings mean that the input could be specified with more than one value. Separate each value with a space or a new line.
|
||||||
|
|
||||||
| Name | Value Type | Description |
|
> Note: All inputs are optional.
|
||||||
| --- | --- | --- |
|
|
||||||
| `build-dir` | Path | The build directory of the CMake project. |
|
|
||||||
|
|
||||||
## Example Usages
|
### Examples
|
||||||
|
|
||||||
This example demonstrates how to use this action to configure and build a CMake project in a GitHub Actions workflow:
|
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
name: Build
|
name: build
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
jobs:
|
jobs:
|
||||||
build-project:
|
build-project:
|
||||||
name: Build Project
|
runs-on: ubuntu-latest
|
||||||
runs-on: ubuntu-24.04
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout Project
|
- name: Check out this repository
|
||||||
uses: actions/checkout@v4.2.2
|
uses: actions/checkout@v3.3.0
|
||||||
|
|
||||||
- name: Build Project
|
- name: Configure and build this project
|
||||||
uses: threeal/cmake-action@v2.1.0
|
uses: threeal/cmake-action@latest
|
||||||
```
|
```
|
||||||
|
|
||||||
### Specify the Source and Build Directories
|
> Note: You can replace `@latest` with any version you like. See [this](https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsuses).
|
||||||
|
|
||||||
By default, this action uses the current working directory as the source directory and the `build` directory inside the source directory as the build directory. To use different directories, set the `source-dir` and/or `build-dir` inputs:
|
#### Specify the Source and the Build Directories
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
- name: Build Project
|
- name: Configure and build this project
|
||||||
uses: threeal/cmake-action@v2.1.0
|
uses: threeal/cmake-action@latest
|
||||||
with:
|
with:
|
||||||
source-dir: source
|
source-dir: submodules
|
||||||
build-dir: output
|
build-dir: submodules/out
|
||||||
```
|
```
|
||||||
|
|
||||||
### Specify Build System Generator and Compiler
|
#### Specify the Build Targets
|
||||||
|
|
||||||
The following example demonstrates how to use this action to configure and build the project using [Ninja](https://ninja-build.org/) as the build system generator and [Clang](https://clang.llvm.org/) as the compiler:
|
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
- name: Build Project
|
- name: Configure and build this project
|
||||||
uses: threeal/cmake-action@v2.1.0
|
uses: threeal/cmake-action@latest
|
||||||
|
with:
|
||||||
|
targets: hello_mars hello_sun
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Run Unit Tests After Build
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- name: Configure, build, and test this project
|
||||||
|
uses: threeal/cmake-action@latest
|
||||||
|
with:
|
||||||
|
args: -DBUILD_TESTING=ON
|
||||||
|
run-test: true
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Using Ninja as the Generator and Clang as the Compiler
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- name: Configure and build this project
|
||||||
|
uses: threeal/cmake-action@latest
|
||||||
with:
|
with:
|
||||||
generator: Ninja
|
generator: Ninja
|
||||||
|
c-compiler: clang
|
||||||
cxx-compiler: clang++
|
cxx-compiler: clang++
|
||||||
```
|
```
|
||||||
|
|
||||||
### Specify Additional Options
|
|
||||||
|
|
||||||
Use the `options` input to specify additional options for configuring a project:
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
- name: Build Project
|
|
||||||
uses: threeal/cmake-action@v2.1.0
|
|
||||||
with:
|
|
||||||
options: |
|
|
||||||
BUILD_TESTS=ON
|
|
||||||
BUILD_EXAMPLES=ON
|
|
||||||
```
|
|
||||||
|
|
||||||
The above example is equivalent to calling the `cmake` command with the `-DBUILD_TESTS=ON` and `-DBUILD_EXAMPLES=ON` arguments.
|
|
||||||
|
|
||||||
### Configure Project Without Building
|
|
||||||
|
|
||||||
By default, this action builds the project after configuration. To skip the build process, set the `run-build` option to `false`:
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
- name: Configure Project
|
|
||||||
uses: threeal/cmake-action@v2.1.0
|
|
||||||
with:
|
|
||||||
run-build: false
|
|
||||||
```
|
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
This project is licensed under the terms of the [MIT License](./LICENSE).
|
This project is licensed under the terms of the [MIT License](./LICENSE).
|
||||||
|
|
||||||
Copyright © 2023-2025 [Alfi Maulana](https://github.com/threeal/)
|
Copyright © 2023 [Alfi Maulana](https://github.com/threeal/)
|
||||||
|
|||||||
121
action.yml
121
action.yml
@ -1,37 +1,114 @@
|
|||||||
name: CMake Action
|
name: CMake Action
|
||||||
description: Configure and build CMake projects
|
description: Configure, build, and test a CMake project
|
||||||
author: Alfi Maulana
|
author: Alfi Maulana
|
||||||
branding:
|
branding:
|
||||||
color: gray-dark
|
color: gray-dark
|
||||||
icon: terminal
|
icon: terminal
|
||||||
inputs:
|
inputs:
|
||||||
source-dir:
|
source-dir:
|
||||||
description: The source directory of the CMake project
|
description: Source directory of the CMake project
|
||||||
|
required: false
|
||||||
build-dir:
|
build-dir:
|
||||||
description: The build directory of the CMake project
|
description: Build directory of the CMake project
|
||||||
|
required: false
|
||||||
|
targets:
|
||||||
|
description: List of build targets
|
||||||
|
required: false
|
||||||
|
run-test:
|
||||||
|
description: If enabled, run testing using CTest (true/false)
|
||||||
|
required: false
|
||||||
|
default: false
|
||||||
generator:
|
generator:
|
||||||
description: The build system generator for the CMake project
|
description: Build system generator of the CMake project
|
||||||
|
required: false
|
||||||
c-compiler:
|
c-compiler:
|
||||||
description: The preferred executable for compiling C language files
|
description: Preferred executable for compiling C language files
|
||||||
|
required: false
|
||||||
cxx-compiler:
|
cxx-compiler:
|
||||||
description: The preferred executable for compiling C++ language files
|
description: Preferred executable for compiling C++ language files
|
||||||
|
required: false
|
||||||
c-flags:
|
c-flags:
|
||||||
description: Additional flags to pass when compiling C language files
|
description: Additional flags passed when compiling C language files
|
||||||
|
required: false
|
||||||
cxx-flags:
|
cxx-flags:
|
||||||
description: Additional flags to pass when compiling C++ language files
|
description: Additional flags passed when compiling C++ language files
|
||||||
options:
|
required: false
|
||||||
description: Additional options to pass during the CMake configuration
|
|
||||||
args:
|
args:
|
||||||
description: Additional arguments to pass during the CMake configuration
|
description: Additional arguments passed during the CMake configuration
|
||||||
run-build:
|
required: false
|
||||||
description: If enabled, builds the project using CMake
|
test-args:
|
||||||
default: true
|
description: Additional arguments passed during the CTest run
|
||||||
build-args:
|
required: false
|
||||||
description: Additional arguments to pass during the CMake build
|
|
||||||
outputs:
|
|
||||||
build-dir:
|
|
||||||
description: The build directory of the CMake project
|
|
||||||
value: ${{ steps.process-inputs.outputs.build-dir }}
|
|
||||||
runs:
|
runs:
|
||||||
using: node24
|
using: composite
|
||||||
main: dist/action.mjs
|
steps:
|
||||||
|
- name: Process the inputs
|
||||||
|
id: process_inputs
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
SOURCE_DIR="."
|
||||||
|
if [ -n '${{ inputs.source-dir }}' ]; then
|
||||||
|
SOURCE_DIR="${{ inputs.source-dir }}"
|
||||||
|
fi
|
||||||
|
BUILD_DIR="build"
|
||||||
|
if [ -n '${{ inputs.build-dir }}' ]; then
|
||||||
|
BUILD_DIR="${{ inputs.build-dir }}"
|
||||||
|
elif [ -n "${{ inputs.source-dir }}" ]; then
|
||||||
|
BUILD_DIR="${{ inputs.source-dir }}/build"
|
||||||
|
fi
|
||||||
|
ARGS="'$SOURCE_DIR' -B '$BUILD_DIR'"
|
||||||
|
BUILD_ARGS="--build '$BUILD_DIR'"
|
||||||
|
TEST_ARGS=""
|
||||||
|
if [ -n '${{ inputs.targets }}' ]; then
|
||||||
|
BUILD_ARGS="$BUILD_ARGS --target ${{ inputs.targets }}"
|
||||||
|
fi
|
||||||
|
if [ '${{ inputs.run-test }}' == 'true' ]; then
|
||||||
|
TEST_ARGS="--test-dir '$BUILD_DIR' --output-on-failure --no-tests=error"
|
||||||
|
fi
|
||||||
|
if [ -n '${{ inputs.generator }}' ]; then
|
||||||
|
ARGS="$ARGS -G '${{ inputs.generator }}'"
|
||||||
|
fi
|
||||||
|
if [ -n '${{ inputs.c-compiler }}' ]; then
|
||||||
|
ARGS="$ARGS -D CMAKE_C_COMPILER='${{ inputs.c-compiler }}'"
|
||||||
|
fi
|
||||||
|
if [ -n '${{ inputs.cxx-compiler }}' ]; then
|
||||||
|
ARGS="$ARGS -D CMAKE_CXX_COMPILER='${{ inputs.cxx-compiler }}'"
|
||||||
|
fi
|
||||||
|
if [ -n '${{ inputs.c-flags }}' ]; then
|
||||||
|
ARGS="$ARGS -D CMAKE_C_FLAGS='${{ inputs.c-flags }}'"
|
||||||
|
fi
|
||||||
|
if [ -n '${{ inputs.cxx-flags }}' ]; then
|
||||||
|
ARGS="$ARGS -D CMAKE_CXX_FLAGS='${{ inputs.cxx-flags }}'"
|
||||||
|
fi
|
||||||
|
if [ -n '${{ inputs.args }}' ]; then
|
||||||
|
ARGS="$ARGS ${{ inputs.args }}"
|
||||||
|
fi
|
||||||
|
if [ -n '${{ inputs.test-args }}' ]; then
|
||||||
|
TEST_ARGS="$TEST_ARGS ${{ inputs.test-args }}"
|
||||||
|
fi
|
||||||
|
echo "cmake_args=${ARGS//[$'\t\r\n']}" >> $GITHUB_OUTPUT
|
||||||
|
echo "cmake_build_args=${BUILD_ARGS//[$'\t\r\n']}" >> $GITHUB_OUTPUT
|
||||||
|
echo "cmake_test_args=${TEST_ARGS//[$'\t\r\n']}" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
|
- name: Install Ninja
|
||||||
|
if: ${{ inputs.generator == 'Ninja' }}
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
case "$OSTYPE" in
|
||||||
|
darwin*) brew install ninja ;;
|
||||||
|
linux*) sudo apt install -y ninja-build ;;
|
||||||
|
*) choco install ninja ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
- name: Configure the CMake project
|
||||||
|
shell: ${{ runner.os == 'Windows' && 'pwsh' || 'bash' }}
|
||||||
|
run: cmake ${{ steps.process_inputs.outputs.cmake_args }}
|
||||||
|
|
||||||
|
- name: Build targets
|
||||||
|
shell: ${{ runner.os == 'Windows' && 'pwsh' || 'bash' }}
|
||||||
|
run: cmake ${{ steps.process_inputs.outputs.cmake_build_args }}
|
||||||
|
|
||||||
|
- name: Run tests
|
||||||
|
if: steps.process_inputs.outputs.cmake_test_args != ''
|
||||||
|
shell: ${{ runner.os == 'Windows' && 'pwsh' || 'bash' }}
|
||||||
|
run: ctest ${{ steps.process_inputs.outputs.cmake_test_args }}
|
||||||
|
|||||||
193
dist/action.mjs
vendored
193
dist/action.mjs
vendored
@ -1,193 +0,0 @@
|
|||||||
import 'node:fs';
|
|
||||||
import fsPromises from 'node:fs/promises';
|
|
||||||
import os from 'node:os';
|
|
||||||
import path from 'node:path';
|
|
||||||
import { spawn } from 'node:child_process';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @internal
|
|
||||||
* Retrieves the value of an environment variable.
|
|
||||||
*
|
|
||||||
* @param name - The name of the environment variable.
|
|
||||||
* @returns The value of the environment variable.
|
|
||||||
* @throws Error if the environment variable is not defined.
|
|
||||||
*/
|
|
||||||
function mustGetEnvironment(name) {
|
|
||||||
const value = process.env[name];
|
|
||||||
if (value === undefined) {
|
|
||||||
throw new Error(`the ${name} environment variable must be defined`);
|
|
||||||
}
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Retrieves the value of a GitHub Actions input.
|
|
||||||
*
|
|
||||||
* @param name - The name of the GitHub Actions input.
|
|
||||||
* @returns The value of the GitHub Actions input, or an empty string if not found.
|
|
||||||
*/
|
|
||||||
function getInput(name) {
|
|
||||||
const value = process.env[`INPUT_${name.toUpperCase()}`] ?? "";
|
|
||||||
return value.trim();
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Sets the value of a GitHub Actions output.
|
|
||||||
*
|
|
||||||
* @param name - The name of the GitHub Actions output.
|
|
||||||
* @param value - The value to set for the GitHub Actions output.
|
|
||||||
* @returns A promise that resolves when the value is successfully set.
|
|
||||||
*/
|
|
||||||
async function setOutput(name, value) {
|
|
||||||
const filePath = mustGetEnvironment("GITHUB_OUTPUT");
|
|
||||||
await fsPromises.appendFile(filePath, `${name}=${value}${os.EOL}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Logs an error message in GitHub Actions.
|
|
||||||
*
|
|
||||||
* @param err - The error, which can be of any type.
|
|
||||||
*/
|
|
||||||
function logError(err) {
|
|
||||||
const message = err instanceof Error ? err.message : String(err);
|
|
||||||
process.stdout.write(`::error::${message}${os.EOL}`);
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Logs a command along with its arguments in GitHub Actions.
|
|
||||||
*
|
|
||||||
* @param command - The command to log.
|
|
||||||
* @param args - The arguments of the command.
|
|
||||||
*/
|
|
||||||
function logCommand(command, ...args) {
|
|
||||||
const message = [command, ...args].join(" ");
|
|
||||||
process.stdout.write(`[command]${message}${os.EOL}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Executes a command with the given arguments.
|
|
||||||
*
|
|
||||||
* The command is executed with `stdin` ignored and both `stdout` and `stderr` inherited by the parent process.
|
|
||||||
*
|
|
||||||
* @param command The command to execute.
|
|
||||||
* @param args The arguments to pass to the command.
|
|
||||||
* @returns A promise that resolves when the command exits successfully or rejects if it exits with a non-zero status code or encounters an error.
|
|
||||||
*/
|
|
||||||
async function exec(command, args) {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
const proc = spawn(command, args, {
|
|
||||||
stdio: ["ignore", "inherit", "inherit"],
|
|
||||||
});
|
|
||||||
logCommand(proc.spawnfile, ...proc.spawnargs.splice(1));
|
|
||||||
proc.on("error", reject);
|
|
||||||
proc.on("close", (code) => {
|
|
||||||
if (code === 0) {
|
|
||||||
resolve();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
reject(new Error(`Command exited with status code ${code.toString()}`));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Configures the build system for a CMake project.
|
|
||||||
*
|
|
||||||
* Constructs and runs the `cmake` command to configure the project with the specified
|
|
||||||
* source directory, build directory, generator, options, and additional arguments.
|
|
||||||
*
|
|
||||||
* @param context - The action context containing configuration details.
|
|
||||||
* @returns A promise that resolves when the build system is successfully configured.
|
|
||||||
*/
|
|
||||||
async function configureProject(context) {
|
|
||||||
const configureArgs = [];
|
|
||||||
if (context.sourceDir) {
|
|
||||||
configureArgs.push(context.sourceDir);
|
|
||||||
}
|
|
||||||
configureArgs.push("-B", context.buildDir);
|
|
||||||
if (context.configure.generator) {
|
|
||||||
configureArgs.push("-G", context.configure.generator);
|
|
||||||
}
|
|
||||||
configureArgs.push(...context.configure.options.map((opt) => "-D" + opt));
|
|
||||||
configureArgs.push(...context.configure.args);
|
|
||||||
await exec("cmake", configureArgs);
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Builds a CMake project.
|
|
||||||
*
|
|
||||||
* Runs the `cmake --build` command to build the project using the specified
|
|
||||||
* build directory and additional arguments.
|
|
||||||
*
|
|
||||||
* @param context - The action context containing build details.
|
|
||||||
* @returns A promise that resolves when the project is successfully built.
|
|
||||||
*/
|
|
||||||
async function buildProject(context) {
|
|
||||||
await exec("cmake", ["--build", context.buildDir, ...context.build.args]);
|
|
||||||
}
|
|
||||||
|
|
||||||
const regex = /"([^"]*)"|'([^']*)'|`([^`]*)`|(\S+)/g;
|
|
||||||
/**
|
|
||||||
* Converts a space-separated string into a list of arguments.
|
|
||||||
*
|
|
||||||
* This function parses the provided string, which contains arguments separated by spaces and possibly enclosed in quotes, into a list of arguments.
|
|
||||||
*
|
|
||||||
* @param str - The space-separated string to parse.
|
|
||||||
* @returns A list of arguments.
|
|
||||||
*/
|
|
||||||
function parse(str) {
|
|
||||||
const args = [];
|
|
||||||
let match;
|
|
||||||
while ((match = regex.exec(str)) !== null) {
|
|
||||||
args.push(match[1] || match[2] || match[3] || match[4]);
|
|
||||||
}
|
|
||||||
return args;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getContext() {
|
|
||||||
const sourceDir = getInput("source-dir");
|
|
||||||
const options = [];
|
|
||||||
let input = getInput("c-compiler");
|
|
||||||
if (input)
|
|
||||||
options.push(`CMAKE_C_COMPILER=${input}`);
|
|
||||||
input = getInput("cxx-compiler");
|
|
||||||
if (input)
|
|
||||||
options.push(`CMAKE_CXX_COMPILER=${input}`);
|
|
||||||
input = getInput("c-flags");
|
|
||||||
if (input) {
|
|
||||||
const flags = input.replaceAll(/\s+/g, " ");
|
|
||||||
options.push(`CMAKE_C_FLAGS=${flags}`);
|
|
||||||
}
|
|
||||||
input = getInput("cxx-flags");
|
|
||||||
if (input) {
|
|
||||||
const flags = input.replaceAll(/\s+/g, " ");
|
|
||||||
options.push(`CMAKE_CXX_FLAGS=${flags}`);
|
|
||||||
}
|
|
||||||
input = getInput("options");
|
|
||||||
if (input) {
|
|
||||||
options.push(...parse(input).map((opt) => opt));
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
sourceDir,
|
|
||||||
buildDir: getInput("build-dir") || path.join(sourceDir, "build"),
|
|
||||||
configure: {
|
|
||||||
generator: getInput("generator"),
|
|
||||||
options,
|
|
||||||
args: parse(getInput("args")).map((arg) => arg),
|
|
||||||
},
|
|
||||||
build: {
|
|
||||||
enabled: getInput("run-build") == "true",
|
|
||||||
args: parse(getInput("build-args")).map((arg) => arg),
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
const context = getContext();
|
|
||||||
await configureProject(context);
|
|
||||||
await setOutput("build-dir", context.buildDir);
|
|
||||||
if (context.build.enabled) {
|
|
||||||
await buildProject(context);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (err) {
|
|
||||||
logError(err);
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
@ -1,20 +0,0 @@
|
|||||||
import eslint from "@eslint/js";
|
|
||||||
import { defineConfig, globalIgnores } from "eslint/config";
|
|
||||||
import tseslint from "typescript-eslint";
|
|
||||||
|
|
||||||
export default defineConfig(
|
|
||||||
globalIgnores(["dist"]),
|
|
||||||
eslint.configs.recommended,
|
|
||||||
tseslint.configs.strictTypeChecked,
|
|
||||||
tseslint.configs.stylisticTypeChecked,
|
|
||||||
{
|
|
||||||
languageOptions: {
|
|
||||||
parserOptions: {
|
|
||||||
projectService: {
|
|
||||||
allowDefaultProject: ["rollup.config.js"],
|
|
||||||
},
|
|
||||||
tsconfigRootDir: import.meta.dirname,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
);
|
|
||||||
@ -1,20 +0,0 @@
|
|||||||
pre-commit:
|
|
||||||
piped: true
|
|
||||||
jobs:
|
|
||||||
- name: install dependencies
|
|
||||||
run: pnpm install
|
|
||||||
|
|
||||||
- name: check types
|
|
||||||
run: pnpm tsc
|
|
||||||
|
|
||||||
- name: fix formatting
|
|
||||||
run: pnpm prettier --write .
|
|
||||||
|
|
||||||
- name: fix lint
|
|
||||||
run: pnpm eslint --fix
|
|
||||||
|
|
||||||
- name: build action
|
|
||||||
run: pnpm rollup -c
|
|
||||||
|
|
||||||
- name: check diff
|
|
||||||
run: git diff --exit-code dist pnpm-lock.yaml {staged_files}
|
|
||||||
28
package.json
28
package.json
@ -1,28 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "root",
|
|
||||||
"private": true,
|
|
||||||
"type": "module",
|
|
||||||
"scripts": {
|
|
||||||
"test": "vitest run"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"gha-utils": "^0.4.1"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"@eslint/js": "^9.35.0",
|
|
||||||
"@rollup/plugin-node-resolve": "^16.0.1",
|
|
||||||
"@rollup/plugin-typescript": "^12.1.4",
|
|
||||||
"@tsconfig/node24": "^24.0.1",
|
|
||||||
"@types/node": "^24.3.0",
|
|
||||||
"@vitest/coverage-v8": "^3.1.4",
|
|
||||||
"eslint": "^9.34.0",
|
|
||||||
"jiti": "^2.5.1",
|
|
||||||
"lefthook": "^1.12.3",
|
|
||||||
"prettier": "^3.6.2",
|
|
||||||
"prettier-plugin-organize-imports": "^4.2.0",
|
|
||||||
"rollup": "^4.46.2",
|
|
||||||
"typescript": "^5.9.2",
|
|
||||||
"typescript-eslint": "^8.42.0",
|
|
||||||
"vitest": "^3.1.4"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
2574
pnpm-lock.yaml
2574
pnpm-lock.yaml
File diff suppressed because it is too large
Load Diff
@ -1,6 +0,0 @@
|
|||||||
packages:
|
|
||||||
- .
|
|
||||||
|
|
||||||
onlyBuiltDependencies:
|
|
||||||
- esbuild
|
|
||||||
- lefthook
|
|
||||||
@ -1,11 +0,0 @@
|
|||||||
import { nodeResolve } from "@rollup/plugin-node-resolve";
|
|
||||||
import typescript from "@rollup/plugin-typescript";
|
|
||||||
|
|
||||||
export default {
|
|
||||||
input: "src/action.ts",
|
|
||||||
output: {
|
|
||||||
dir: "dist",
|
|
||||||
entryFileNames: "[name].mjs",
|
|
||||||
},
|
|
||||||
plugins: [nodeResolve(), typescript()],
|
|
||||||
};
|
|
||||||
@ -1,18 +0,0 @@
|
|||||||
import { logError, setOutput } from "gha-utils";
|
|
||||||
import { buildProject, configureProject } from "./cmake.js";
|
|
||||||
import { getContext } from "./context.js";
|
|
||||||
|
|
||||||
try {
|
|
||||||
const context = getContext();
|
|
||||||
|
|
||||||
await configureProject(context);
|
|
||||||
|
|
||||||
await setOutput("build-dir", context.buildDir);
|
|
||||||
|
|
||||||
if (context.build.enabled) {
|
|
||||||
await buildProject(context);
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
logError(err);
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
@ -1,152 +0,0 @@
|
|||||||
import { describe, expect, it, vi } from "vitest";
|
|
||||||
import { buildProject, configureProject } from "./cmake.js";
|
|
||||||
import type { Context } from "./context.js";
|
|
||||||
import { exec } from "./exec.js";
|
|
||||||
|
|
||||||
interface TestCase {
|
|
||||||
name: string;
|
|
||||||
context?: Partial<Context>;
|
|
||||||
expectedArgs: string[];
|
|
||||||
}
|
|
||||||
|
|
||||||
const defaultContext: Context = {
|
|
||||||
sourceDir: "",
|
|
||||||
buildDir: "build",
|
|
||||||
configure: {
|
|
||||||
generator: "",
|
|
||||||
options: [],
|
|
||||||
args: [],
|
|
||||||
},
|
|
||||||
build: {
|
|
||||||
enabled: true,
|
|
||||||
args: [],
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
vi.mock("./exec.js", () => ({ exec: vi.fn() }));
|
|
||||||
|
|
||||||
describe("configure a CMake project", () => {
|
|
||||||
const testCases: TestCase[] = [
|
|
||||||
{
|
|
||||||
name: "with nothing specified",
|
|
||||||
expectedArgs: ["-B", "build"],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "with source directory specified",
|
|
||||||
context: { sourceDir: "project" },
|
|
||||||
expectedArgs: ["project", "-B", "build"],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "with build directory specified",
|
|
||||||
context: { buildDir: "output" },
|
|
||||||
expectedArgs: ["-B", "output"],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "with generator specified",
|
|
||||||
context: { configure: { generator: "Ninja", options: [], args: [] } },
|
|
||||||
expectedArgs: ["-B", "build", "-G", "Ninja"],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "with additional options specified",
|
|
||||||
context: {
|
|
||||||
configure: {
|
|
||||||
generator: "",
|
|
||||||
options: ["BUILD_TESTING=ON", "BUILD_EXAMPLES=ON"],
|
|
||||||
args: [],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
expectedArgs: [
|
|
||||||
"-B",
|
|
||||||
"build",
|
|
||||||
"-DBUILD_TESTING=ON",
|
|
||||||
"-DBUILD_EXAMPLES=ON",
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "with additional arguments specified",
|
|
||||||
context: {
|
|
||||||
configure: {
|
|
||||||
generator: "",
|
|
||||||
options: [],
|
|
||||||
args: ["-Wdev", "-Wdeprecated"],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
expectedArgs: ["-B", "build", "-Wdev", "-Wdeprecated"],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "with all specified",
|
|
||||||
context: {
|
|
||||||
sourceDir: "project",
|
|
||||||
buildDir: "output",
|
|
||||||
configure: {
|
|
||||||
generator: "Ninja",
|
|
||||||
options: ["BUILD_TESTING=ON", "BUILD_EXAMPLES=ON"],
|
|
||||||
args: ["-Wdev", "-Wdeprecated"],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
expectedArgs: [
|
|
||||||
"project",
|
|
||||||
"-B",
|
|
||||||
"output",
|
|
||||||
"-G",
|
|
||||||
"Ninja",
|
|
||||||
"-DBUILD_TESTING=ON",
|
|
||||||
"-DBUILD_EXAMPLES=ON",
|
|
||||||
"-Wdev",
|
|
||||||
"-Wdeprecated",
|
|
||||||
],
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
for (const testCase of testCases) {
|
|
||||||
it(`should execute the correct command ${testCase.name}`, async () => {
|
|
||||||
vi.mocked(exec).mockReset();
|
|
||||||
|
|
||||||
await configureProject({ ...defaultContext, ...testCase.context });
|
|
||||||
|
|
||||||
expect(exec).toHaveBeenCalledTimes(1);
|
|
||||||
expect(exec).toHaveBeenLastCalledWith("cmake", testCase.expectedArgs);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("build a CMake project", () => {
|
|
||||||
const testCases: TestCase[] = [
|
|
||||||
{
|
|
||||||
name: "with nothing specified",
|
|
||||||
expectedArgs: ["--build", "build"],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "with build directory specified",
|
|
||||||
context: { buildDir: "output" },
|
|
||||||
expectedArgs: ["--build", "output"],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "with additional arguments specified",
|
|
||||||
context: { build: { enabled: true, args: ["--target", "foo"] } },
|
|
||||||
expectedArgs: ["--build", "build", "--target", "foo"],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "with all specified",
|
|
||||||
context: {
|
|
||||||
buildDir: "output",
|
|
||||||
build: {
|
|
||||||
enabled: true,
|
|
||||||
args: ["--target", "foo"],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
expectedArgs: ["--build", "output", "--target", "foo"],
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
for (const testCase of testCases) {
|
|
||||||
it(`should execute the correct command ${testCase.name}`, async () => {
|
|
||||||
vi.mocked(exec).mockReset();
|
|
||||||
|
|
||||||
await buildProject({ ...defaultContext, ...testCase.context });
|
|
||||||
|
|
||||||
expect(exec).toHaveBeenCalledTimes(1);
|
|
||||||
expect(exec).toHaveBeenLastCalledWith("cmake", testCase.expectedArgs);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
43
src/cmake.ts
43
src/cmake.ts
@ -1,43 +0,0 @@
|
|||||||
import type { Context } from "./context.js";
|
|
||||||
import { exec } from "./exec.js";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Configures the build system for a CMake project.
|
|
||||||
*
|
|
||||||
* Constructs and runs the `cmake` command to configure the project with the specified
|
|
||||||
* source directory, build directory, generator, options, and additional arguments.
|
|
||||||
*
|
|
||||||
* @param context - The action context containing configuration details.
|
|
||||||
* @returns A promise that resolves when the build system is successfully configured.
|
|
||||||
*/
|
|
||||||
export async function configureProject(context: Context): Promise<void> {
|
|
||||||
const configureArgs = [];
|
|
||||||
|
|
||||||
if (context.sourceDir) {
|
|
||||||
configureArgs.push(context.sourceDir);
|
|
||||||
}
|
|
||||||
|
|
||||||
configureArgs.push("-B", context.buildDir);
|
|
||||||
|
|
||||||
if (context.configure.generator) {
|
|
||||||
configureArgs.push("-G", context.configure.generator);
|
|
||||||
}
|
|
||||||
|
|
||||||
configureArgs.push(...context.configure.options.map((opt) => "-D" + opt));
|
|
||||||
configureArgs.push(...context.configure.args);
|
|
||||||
|
|
||||||
await exec("cmake", configureArgs);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Builds a CMake project.
|
|
||||||
*
|
|
||||||
* Runs the `cmake --build` command to build the project using the specified
|
|
||||||
* build directory and additional arguments.
|
|
||||||
*
|
|
||||||
* @param context - The action context containing build details.
|
|
||||||
* @returns A promise that resolves when the project is successfully built.
|
|
||||||
*/
|
|
||||||
export async function buildProject(context: Context): Promise<void> {
|
|
||||||
await exec("cmake", ["--build", context.buildDir, ...context.build.args]);
|
|
||||||
}
|
|
||||||
@ -1,205 +0,0 @@
|
|||||||
import path from "node:path";
|
|
||||||
import { describe, expect, it, vi } from "vitest";
|
|
||||||
import type { Context } from "./context.js";
|
|
||||||
|
|
||||||
vi.mock("gha-utils", () => ({ getInput: vi.fn() }));
|
|
||||||
|
|
||||||
describe("get action context", () => {
|
|
||||||
interface TestCase {
|
|
||||||
name: string;
|
|
||||||
inputs?: Record<string, string>;
|
|
||||||
expectedContext?: Partial<Context>;
|
|
||||||
}
|
|
||||||
|
|
||||||
const testCases: TestCase[] = [
|
|
||||||
{
|
|
||||||
name: "with nothing specified",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "with source directory specified",
|
|
||||||
inputs: { "source-dir": "project" },
|
|
||||||
expectedContext: {
|
|
||||||
sourceDir: "project",
|
|
||||||
buildDir: path.join("project", "build"),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "with build directory specified",
|
|
||||||
inputs: { "build-dir": "output" },
|
|
||||||
expectedContext: { buildDir: "output" },
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "with source and build directories specified",
|
|
||||||
inputs: {
|
|
||||||
"source-dir": "project",
|
|
||||||
"build-dir": "output",
|
|
||||||
},
|
|
||||||
expectedContext: {
|
|
||||||
sourceDir: "project",
|
|
||||||
buildDir: "output",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "with generator specified",
|
|
||||||
inputs: { generator: "Ninja" },
|
|
||||||
expectedContext: {
|
|
||||||
configure: {
|
|
||||||
generator: "Ninja",
|
|
||||||
options: [],
|
|
||||||
args: [],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "with C compiler specified",
|
|
||||||
inputs: { "c-compiler": "clang" },
|
|
||||||
expectedContext: {
|
|
||||||
configure: {
|
|
||||||
generator: "",
|
|
||||||
options: ["CMAKE_C_COMPILER=clang"],
|
|
||||||
args: [],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "with C++ compiler specified",
|
|
||||||
inputs: { "cxx-compiler": "clang++" },
|
|
||||||
expectedContext: {
|
|
||||||
configure: {
|
|
||||||
generator: "",
|
|
||||||
options: ["CMAKE_CXX_COMPILER=clang++"],
|
|
||||||
args: [],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "with C flags specified",
|
|
||||||
inputs: { "c-flags": "-Werror -Wall\n-Wextra" },
|
|
||||||
expectedContext: {
|
|
||||||
configure: {
|
|
||||||
generator: "",
|
|
||||||
options: ["CMAKE_C_FLAGS=-Werror -Wall -Wextra"],
|
|
||||||
args: [],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "with C++ flags specified",
|
|
||||||
inputs: { "cxx-flags": "-Werror -Wall\n-Wextra -Wpedantic" },
|
|
||||||
expectedContext: {
|
|
||||||
configure: {
|
|
||||||
generator: "",
|
|
||||||
options: ["CMAKE_CXX_FLAGS=-Werror -Wall -Wextra -Wpedantic"],
|
|
||||||
args: [],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "with additional options specified",
|
|
||||||
inputs: {
|
|
||||||
options: `BUILD_TESTING=ON BUILD_EXAMPLES=ON\nBUILD_DOCS=ON "FOO=BAR BAZ"`,
|
|
||||||
},
|
|
||||||
expectedContext: {
|
|
||||||
configure: {
|
|
||||||
generator: "",
|
|
||||||
options: [
|
|
||||||
"BUILD_TESTING=ON",
|
|
||||||
"BUILD_EXAMPLES=ON",
|
|
||||||
"BUILD_DOCS=ON",
|
|
||||||
"FOO=BAR BAZ",
|
|
||||||
],
|
|
||||||
args: [],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "with additional arguments specified",
|
|
||||||
inputs: { args: `-Wdev -Wdeprecated\n--fresh --foo "bar baz"` },
|
|
||||||
expectedContext: {
|
|
||||||
configure: {
|
|
||||||
generator: "",
|
|
||||||
options: [],
|
|
||||||
args: ["-Wdev", "-Wdeprecated", "--fresh", "--foo", "bar baz"],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "with run build specified",
|
|
||||||
inputs: { "run-build": "true" },
|
|
||||||
expectedContext: { build: { enabled: true, args: [] } },
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "with additional build arguments specified",
|
|
||||||
inputs: { "build-args": `--target foo\n--parallel 8 --foo "bar baz"` },
|
|
||||||
expectedContext: {
|
|
||||||
build: {
|
|
||||||
enabled: false,
|
|
||||||
args: ["--target", "foo", "--parallel", "8", "--foo", "bar baz"],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "with all specified",
|
|
||||||
inputs: {
|
|
||||||
"source-dir": "project",
|
|
||||||
"build-dir": "output",
|
|
||||||
generator: "Ninja",
|
|
||||||
"c-compiler": "clang",
|
|
||||||
"cxx-compiler": "clang++",
|
|
||||||
"c-flags": "-Werror -Wall\n-Wextra",
|
|
||||||
"cxx-flags": "-Werror -Wall\n-Wextra -Wpedantic",
|
|
||||||
options: `BUILD_TESTING=ON BUILD_EXAMPLES=ON\nBUILD_DOCS=ON "FOO=BAR BAZ"`,
|
|
||||||
args: `-Wdev -Wdeprecated\n--fresh --foo "bar baz"`,
|
|
||||||
"run-build": "true",
|
|
||||||
"build-args": `--target foo\n--parallel 8 --foo "bar baz"`,
|
|
||||||
},
|
|
||||||
expectedContext: {
|
|
||||||
sourceDir: "project",
|
|
||||||
buildDir: "output",
|
|
||||||
configure: {
|
|
||||||
generator: "Ninja",
|
|
||||||
options: [
|
|
||||||
"CMAKE_C_COMPILER=clang",
|
|
||||||
"CMAKE_CXX_COMPILER=clang++",
|
|
||||||
"CMAKE_C_FLAGS=-Werror -Wall -Wextra",
|
|
||||||
"CMAKE_CXX_FLAGS=-Werror -Wall -Wextra -Wpedantic",
|
|
||||||
"BUILD_TESTING=ON",
|
|
||||||
"BUILD_EXAMPLES=ON",
|
|
||||||
"BUILD_DOCS=ON",
|
|
||||||
"FOO=BAR BAZ",
|
|
||||||
],
|
|
||||||
args: ["-Wdev", "-Wdeprecated", "--fresh", "--foo", "bar baz"],
|
|
||||||
},
|
|
||||||
build: {
|
|
||||||
enabled: true,
|
|
||||||
args: ["--target", "foo", "--parallel", "8", "--foo", "bar baz"],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
for (const testCase of testCases) {
|
|
||||||
it(`should get the action context ${testCase.name}`, async () => {
|
|
||||||
const { getInput } = await import("gha-utils");
|
|
||||||
const { getContext } = await import("./context.js");
|
|
||||||
|
|
||||||
const inputs = testCase.inputs ?? {};
|
|
||||||
vi.mocked(getInput).mockImplementation((name) => inputs[name] ?? "");
|
|
||||||
|
|
||||||
expect(getContext()).toStrictEqual({
|
|
||||||
sourceDir: "",
|
|
||||||
buildDir: "build",
|
|
||||||
configure: {
|
|
||||||
generator: "",
|
|
||||||
options: [],
|
|
||||||
args: [],
|
|
||||||
},
|
|
||||||
build: {
|
|
||||||
enabled: false,
|
|
||||||
args: [],
|
|
||||||
},
|
|
||||||
...testCase.expectedContext,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
@ -1,59 +0,0 @@
|
|||||||
import { getInput } from "gha-utils";
|
|
||||||
import path from "node:path";
|
|
||||||
import { parse } from "./utils.js";
|
|
||||||
|
|
||||||
export interface Context {
|
|
||||||
sourceDir: string;
|
|
||||||
buildDir: string;
|
|
||||||
configure: {
|
|
||||||
generator: string;
|
|
||||||
options: string[];
|
|
||||||
args: string[];
|
|
||||||
};
|
|
||||||
build: {
|
|
||||||
enabled: boolean;
|
|
||||||
args: string[];
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getContext(): Context {
|
|
||||||
const sourceDir = getInput("source-dir");
|
|
||||||
const options: string[] = [];
|
|
||||||
|
|
||||||
let input = getInput("c-compiler");
|
|
||||||
if (input) options.push(`CMAKE_C_COMPILER=${input}`);
|
|
||||||
|
|
||||||
input = getInput("cxx-compiler");
|
|
||||||
if (input) options.push(`CMAKE_CXX_COMPILER=${input}`);
|
|
||||||
|
|
||||||
input = getInput("c-flags");
|
|
||||||
if (input) {
|
|
||||||
const flags = input.replaceAll(/\s+/g, " ");
|
|
||||||
options.push(`CMAKE_C_FLAGS=${flags}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
input = getInput("cxx-flags");
|
|
||||||
if (input) {
|
|
||||||
const flags = input.replaceAll(/\s+/g, " ");
|
|
||||||
options.push(`CMAKE_CXX_FLAGS=${flags}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
input = getInput("options");
|
|
||||||
if (input) {
|
|
||||||
options.push(...parse(input).map((opt) => opt));
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
sourceDir,
|
|
||||||
buildDir: getInput("build-dir") || path.join(sourceDir, "build"),
|
|
||||||
configure: {
|
|
||||||
generator: getInput("generator"),
|
|
||||||
options,
|
|
||||||
args: parse(getInput("args")).map((arg) => arg),
|
|
||||||
},
|
|
||||||
build: {
|
|
||||||
enabled: getInput("run-build") == "true",
|
|
||||||
args: parse(getInput("build-args")).map((arg) => arg),
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@ -1,29 +0,0 @@
|
|||||||
import { logCommand } from "gha-utils";
|
|
||||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
||||||
import { exec } from "./exec.js";
|
|
||||||
|
|
||||||
describe("execute commands", () => {
|
|
||||||
vi.mock("gha-utils", () => ({
|
|
||||||
logCommand: vi.fn<(command: string, ...args: string[]) => void>(),
|
|
||||||
}));
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
vi.mocked(logCommand).mockClear();
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should successfully execute a command", async () => {
|
|
||||||
await exec("node", ["--version"]);
|
|
||||||
|
|
||||||
expect(logCommand).toHaveBeenCalledTimes(1);
|
|
||||||
expect(logCommand).toHaveBeenCalledWith("node", "--version");
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should fail to execute a command", async () => {
|
|
||||||
await expect(exec("node", ["--invalid"])).rejects.toThrow(
|
|
||||||
"Command exited with status code 9",
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(logCommand).toHaveBeenCalledTimes(1);
|
|
||||||
expect(logCommand).toHaveBeenCalledWith("node", "--invalid");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
28
src/exec.ts
28
src/exec.ts
@ -1,28 +0,0 @@
|
|||||||
import { logCommand } from "gha-utils";
|
|
||||||
import { spawn } from "node:child_process";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Executes a command with the given arguments.
|
|
||||||
*
|
|
||||||
* The command is executed with `stdin` ignored and both `stdout` and `stderr` inherited by the parent process.
|
|
||||||
*
|
|
||||||
* @param command The command to execute.
|
|
||||||
* @param args The arguments to pass to the command.
|
|
||||||
* @returns A promise that resolves when the command exits successfully or rejects if it exits with a non-zero status code or encounters an error.
|
|
||||||
*/
|
|
||||||
export async function exec(command: string, args: string[]): Promise<void> {
|
|
||||||
return new Promise<void>((resolve, reject) => {
|
|
||||||
const proc = spawn(command, args, {
|
|
||||||
stdio: ["ignore", "inherit", "inherit"],
|
|
||||||
});
|
|
||||||
logCommand(proc.spawnfile, ...proc.spawnargs.splice(1));
|
|
||||||
proc.on("error", reject);
|
|
||||||
proc.on("close", (code: number) => {
|
|
||||||
if (code === 0) {
|
|
||||||
resolve();
|
|
||||||
} else {
|
|
||||||
reject(new Error(`Command exited with status code ${code.toString()}`));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
18
src/utils.ts
18
src/utils.ts
@ -1,18 +0,0 @@
|
|||||||
const regex = /"([^"]*)"|'([^']*)'|`([^`]*)`|(\S+)/g;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts a space-separated string into a list of arguments.
|
|
||||||
*
|
|
||||||
* This function parses the provided string, which contains arguments separated by spaces and possibly enclosed in quotes, into a list of arguments.
|
|
||||||
*
|
|
||||||
* @param str - The space-separated string to parse.
|
|
||||||
* @returns A list of arguments.
|
|
||||||
*/
|
|
||||||
export function parse(str: string): string[] {
|
|
||||||
const args: string[] = [];
|
|
||||||
let match: RegExpExecArray | null;
|
|
||||||
while ((match = regex.exec(str)) !== null) {
|
|
||||||
args.push(match[1] || match[2] || match[3] || match[4]);
|
|
||||||
}
|
|
||||||
return args;
|
|
||||||
}
|
|
||||||
32
test/CMakeLists.txt
Normal file
32
test/CMakeLists.txt
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.0)
|
||||||
|
project(test)
|
||||||
|
|
||||||
|
option(CHECK_USING_CLANG "check if target is compiled using Clang" OFF)
|
||||||
|
option(CHECK_SURPASS_WARNING "check if target could surpass a compiler warning" OFF)
|
||||||
|
|
||||||
|
if(CHECK_SURPASS_WARNING)
|
||||||
|
if(MSVC)
|
||||||
|
set(CMAKE_C_FLAGS "/WX /W4 ${CMAKE_C_FLAGS}")
|
||||||
|
set(CMAKE_CXX_FLAGS "/WX /W4 ${CMAKE_CXX_FLAGS}")
|
||||||
|
else()
|
||||||
|
set(CMAKE_C_FLAGS "-Werror -Wunused-variable ${CMAKE_C_FLAGS}")
|
||||||
|
set(CMAKE_CXX_FLAGS "-Werror -Wunused-variable ${CMAKE_CXX_FLAGS}")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
enable_testing()
|
||||||
|
add_executable(hello_world hello_world.cpp)
|
||||||
|
add_test(NAME hello_world COMMAND $<TARGET_FILE:hello_world>)
|
||||||
|
|
||||||
|
list(APPEND LANGS c cpp)
|
||||||
|
foreach(LANG ${LANGS})
|
||||||
|
configure_file(test.in ${CMAKE_CURRENT_BINARY_DIR}/test.${LANG})
|
||||||
|
add_executable(test_${LANG} EXCLUDE_FROM_ALL ${CMAKE_CURRENT_BINARY_DIR}/test.${LANG})
|
||||||
|
target_compile_definitions(
|
||||||
|
test_${LANG} PRIVATE
|
||||||
|
$<$<STREQUAL:"${LANG}","c">:IS_C>
|
||||||
|
$<$<BOOL:${CHECK_USING_CLANG}>:CHECK_USING_CLANG>
|
||||||
|
$<$<BOOL:${CHECK_SURPASS_WARNING}>:CHECK_SURPASS_WARNING>
|
||||||
|
)
|
||||||
|
add_test(NAME test_${LANG} COMMAND $<TARGET_FILE:test_${LANG}>)
|
||||||
|
endforeach()
|
||||||
6
test/hello_world.cpp
Normal file
6
test/hello_world.cpp
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
std::cout << "Hello world!" << std::endl;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
19
test/test.in
Normal file
19
test/test.in
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
#ifdef IS_C
|
||||||
|
#include <stdio.h>
|
||||||
|
#define PRINT(STR) printf(STR); printf("\n")
|
||||||
|
#else
|
||||||
|
#include <iostream>
|
||||||
|
#define PRINT(STR) std::cout << STR << std::endl
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
#ifdef CHECK_SURPASS_WARNING
|
||||||
|
int unused;
|
||||||
|
#endif
|
||||||
|
#if defined(CHECK_USING_CLANG) && !defined(__clang__)
|
||||||
|
PRINT("compiler is not clang");
|
||||||
|
return 1;
|
||||||
|
#endif
|
||||||
|
PRINT("all ok");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@ -1,7 +0,0 @@
|
|||||||
{
|
|
||||||
"extends": "@tsconfig/node24",
|
|
||||||
"compilerOptions": {
|
|
||||||
"module": "node16",
|
|
||||||
"noEmit": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,12 +0,0 @@
|
|||||||
import { defineConfig } from "vitest/config";
|
|
||||||
|
|
||||||
export default defineConfig({
|
|
||||||
test: {
|
|
||||||
coverage: {
|
|
||||||
all: false,
|
|
||||||
enabled: true,
|
|
||||||
reporter: ["text"],
|
|
||||||
thresholds: { 100: true },
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
Loading…
Reference in New Issue
Block a user