ci: parallelize CI jobs (#318)

* ci: parallelize CI jobs

- remove the dependency on the lint job from all other jobs
- implement workflow concurrency
- reorder the workflow so that the lint, clippy and coverage jobs are
  scheduled before the test jobs
- run jobs which run for each backend in parallel by calling e.g.
  cargo make test-termion, instead of cargo make test
- add a coverage task to the makefile
- change "cargo-make check" to check all features valid for OS in
  parallel
- run clippy only on the ubuntu-latest runner and check all features
  valid in parallel
- tidy up the workflow file

* ci: simplify Makefile OS detection

Use platform overrides to significantly simplify the Makefile logic
See https://github.com/sagiegurari/cargo-make\#platform-override

* fix(termwiz): skip doc test that requires stdout
This commit is contained in:
Josh McKinney 2023-07-17 03:31:31 -07:00 committed by GitHub
parent 1ff85535c8
commit bb061fdab6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 200 additions and 272 deletions

View file

@ -1,78 +1,30 @@
name: CI
on:
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
push:
branches:
- feat-wrapping
- main
pull_request:
branches:
- main
- feat-wrapping
merge_group:
# ensure that the workflow is only triggered once per PR, subsequent pushes to the PR will cancel
# and restart the workflow. See https://docs.github.com/en/actions/using-jobs/using-concurrency
concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
name: CI
env:
# don't install husky hooks during CI as they are only needed for for pre-push
CARGO_HUSKY_DONT_INSTALL_HOOKS: true
# lint, clippy and coveraget jobs are intentionally early in the workflow to catch simple
# formatting, typos, and missing tests as early as possible. This allows us to fix these and
# resubmit the PR without having to wait for the comprehensive matrix of tests to complete.
jobs:
build:
strategy:
matrix:
os: [ ubuntu-latest, windows-latest, macos-latest ]
toolchain: [ "1.65.0", "stable" ]
runs-on: ${{ matrix.os }}
needs: lint
steps:
- uses: actions/checkout@v3
- name: Install Rust
uses: dtolnay/rust-toolchain@master
with:
toolchain: ${{ matrix.toolchain }}
- name: Install cargo-make
uses: taiki-e/install-action@cargo-make
- name: "Check"
run: cargo make check
env:
RUST_BACKTRACE: full
CARGO_HUSKY_DONT_INSTALL_HOOKS: true
clippy:
name: Clippy
runs-on: ubuntu-latest
needs: lint
steps:
- uses: actions/checkout@v3
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
with:
components: clippy
- name: Install cargo-make
uses: taiki-e/install-action@cargo-make
- name: "Clippy"
run: cargo make clippy
env:
RUST_BACKTRACE: full
CARGO_HUSKY_DONT_INSTALL_HOOKS: true
test:
strategy:
matrix:
os: [ ubuntu-latest, windows-latest, macos-latest ]
toolchain: [ "1.65.0", "stable" ]
runs-on: ${{ matrix.os }}
needs: lint
steps:
- uses: actions/checkout@v3
- name: Install Rust
uses: dtolnay/rust-toolchain@master
with:
toolchain: ${{ matrix.toolchain }}
- name: Install cargo-make
uses: taiki-e/install-action@cargo-make
- name: "Test"
run: cargo make test
env:
RUST_BACKTRACE: full
CARGO_HUSKY_DONT_INSTALL_HOOKS: true
lint:
runs-on: ubuntu-latest
steps:
@ -84,38 +36,116 @@ jobs:
uses: actions/checkout@v3
with:
ref: ${{ github.event.pull_request.head.sha }}
- name: "Check conventional commits"
- name: Check conventional commits
uses: crate-ci/committed@master
with:
args: "-vv"
commits: "HEAD"
- name: "Check typos"
commits: HEAD
- name: Check typos
uses: crate-ci/typos@master
- name: "Lint dependencies"
- name: Lint dependencies
uses: EmbarkStudios/cargo-deny-action@v1
- name: Install Rust
- name: Install Rust nightly
uses: dtolnay/rust-toolchain@nightly
with:
components: rustfmt
- name: "Formatting"
run: cargo fmt --all --check
- name: Install cargo-make
uses: taiki-e/install-action@cargo-make
- name: Check formatting
run: cargo make fmt
clippy:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Install Rust stable
uses: dtolnay/rust-toolchain@stable
with:
components: clippy
- name: Install cargo-make
uses: taiki-e/install-action@cargo-make
- name: Run cargo make clippy-all
run: cargo make clippy
coverage:
runs-on: ubuntu-latest
needs: lint
steps:
- uses: actions/checkout@v3
- name: Install Rust
- name: Checkout
uses: actions/checkout@v3
- name: Install Rust stable
uses: dtolnay/rust-toolchain@stable
with:
components: llvm-tools
- name: cargo install cargo-llvm-cov
uses: taiki-e/install-action@cargo-llvm-cov
- name: cargo llvm-cov
run: cargo llvm-cov --all-features --lcov --output-path lcov.info
env:
CARGO_HUSKY_DONT_INSTALL_HOOKS: true
- name: Install cargo-llvm-cov and cargo-make
uses: taiki-e/install-action@v2
with:
tool: cargo-llvm-cov,cargo-make
- name: Generate coverage
run: cargo make coverage
- name: Upload to codecov.io
uses: codecov/codecov-action@v3
with:
fail_ci_if_error: true
check:
strategy:
matrix:
os: [ ubuntu-latest, windows-latest, macos-latest ]
toolchain: [ "1.65.0", "stable" ]
runs-on: ${{ matrix.os }}
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Install Rust {{ matrix.toolchain }}
uses: dtolnay/rust-toolchain@master
with:
toolchain: ${{ matrix.toolchain }}
- name: Install cargo-make
uses: taiki-e/install-action@cargo-make
- name: Run cargo make check
run: cargo make check
env:
RUST_BACKTRACE: full
test-doc:
strategy:
matrix:
os: [ ubuntu-latest, windows-latest, macos-latest ]
runs-on: ${{ matrix.os }}
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Install Rust stable
uses: dtolnay/rust-toolchain@stable
- name: Install cargo-make
uses: taiki-e/install-action@cargo-make
- name: Test docs
run: cargo make test-doc
env:
RUST_BACKTRACE: full
test:
strategy:
matrix:
os: [ ubuntu-latest, windows-latest, macos-latest ]
toolchain: [ "1.65.0", "stable" ]
backend: [ crossterm, termion, termwiz ]
exclude:
# termion is not supported on windows
- os: windows-latest
backend: termion
runs-on: ${{ matrix.os }}
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Install Rust ${{ matrix.toolchain }}}
uses: dtolnay/rust-toolchain@master
with:
toolchain: ${{ matrix.toolchain }}
- name: Install cargo-make
uses: taiki-e/install-action@cargo-make
- name: Test ${{ matrix.backend }}
run: cargo make test-backend ${{ matrix.backend }}
env:
RUST_BACKTRACE: full

View file

@ -3,33 +3,19 @@
[config]
skip_core_tasks = true
[env]
# all features except the backend ones
ALL_FEATURES = "all-widgets,macros,serde"
[tasks.default]
alias = "ci"
[tasks.ci]
run_task = [
{ name = "ci-unix", condition = { platforms = [
"linux",
"mac",
] } },
{ name = "ci-windows", condition = { platforms = [
"windows",
] } },
]
[tasks.ci-unix]
private = true
dependencies = [
"style-check",
"clippy-unix",
"check-unix",
"test-unix",
]
[tasks.ci-windows]
private = true
dependencies = [
"style-check",
"clippy-windows",
"check-windows",
"test-windows",
"clippy",
"check",
"test",
]
[tasks.style-check]
@ -45,211 +31,123 @@ install_crate = { crate_name = "typos-cli", binary = "typos", test_arg = "--vers
command = "typos"
[tasks.check]
run_task = [
{ name = "check-unix", condition = { platforms = [
"linux",
"mac",
] } },
{ name = "check-windows", condition = { platforms = [
"windows",
] } },
]
[tasks.check-unix]
private = true
dependencies = [
"check-crossterm",
"check-termion",
"check-termwiz",
]
[tasks.check-windows]
private = true
dependencies = [
"check-crossterm",
"check-termwiz",
]
[tasks.check-crossterm]
env = { TUI_FEATURES = "serde,crossterm" }
run_task = "check-backend"
[tasks.check-termion]
env = { TUI_FEATURES = "serde,termion" }
run_task = "check-backend"
[tasks.check-termwiz]
env = { TUI_FEATURES = "serde,termwiz" }
run_task = "check-backend"
[tasks.check-backend]
command = "cargo"
condition = { env_set = ["TUI_FEATURES"] }
args = [
"check",
"--no-default-features",
"--features",
"${TUI_FEATURES}",
"--all-targets",
"--all-features"
]
[tasks.check.windows]
args = [
"check",
"--all-targets",
"--no-default-features", "--features", "${ALL_FEATURES},crossterm,termwiz"
]
[tasks.build]
run_task = [
{ name = "build-unix", condition = { platforms = [
"linux",
"mac",
] } },
{ name = "build-windows", condition = { platforms = [
"windows",
] } },
]
[tasks.build-unix]
private = true
dependencies = [
"build-crossterm",
"build-termion",
"build-termwiz",
]
[tasks.build-windows]
private = true
dependencies = [
"build-crossterm",
"build-termwiz",
]
[tasks.build-crossterm]
env = { TUI_FEATURES = "serde,crossterm" }
run_task = "build-backend"
[tasks.build-termion]
env = { TUI_FEATURES = "serde,termion" }
run_task = "build-backend"
[tasks.build-termwiz]
env = { TUI_FEATURES = "serde,termwiz" }
run_task = "build-backend"
[tasks.build-backend]
command = "cargo"
condition = { env_set = ["TUI_FEATURES"] }
args = [
"build",
"--no-default-features",
"--features",
"${TUI_FEATURES}",
"--all-targets",
"--all-features",
]
[tasks.build.windows]
args = [
"build",
"--all-targets",
"--no-default-features", "--features", "${ALL_FEATURES},crossterm,termwiz"
]
[tasks.clippy]
run_task = [
{ name = "clippy-unix", condition = { platforms = [
"linux",
"mac",
] } },
{ name = "clippy-windows", condition = { platforms = [
"windows",
] } },
]
[tasks.clippy-unix]
private = true
dependencies = [
"clippy-crossterm",
"clippy-termion",
"clippy-termwiz",
]
[tasks.clippy-windows]
private = true
dependencies = [
"clippy-crossterm",
"clippy-termwiz",
]
[tasks.clippy-crossterm]
env = { TUI_FEATURES = "serde,crossterm" }
run_task = "clippy-backend"
[tasks.clippy-termion]
env = { TUI_FEATURES = "serde,termion" }
run_task = "clippy-backend"
[tasks.clippy-termwiz]
env = { TUI_FEATURES = "serde,termwiz" }
run_task = "clippy-backend"
[tasks.clippy-backend]
command = "cargo"
condition = { env_set = ["TUI_FEATURES"] }
args = [
"clippy",
"--all-targets",
"--no-default-features",
"--tests",
"--benches",
"--features",
"${TUI_FEATURES}",
"--all-features",
"--",
"-D",
"warnings",
]
[tasks.clippy.window]
args = [
"clippy",
"--all-targets",
"--tests",
"--benches",
"--no-default-features", "--features", "${ALL_FEATURES},crossterm,termwiz",
"--",
"-D",
"warnings",
]
[tasks.test]
run_task = [
{ name = "test-unix", condition = { platforms = [
"linux",
"mac",
] } },
{ name = "test-windows", condition = { platforms = [
"windows",
] } },
]
[tasks.test-unix]
private = true
dependencies = [
"test-crossterm",
"test-termion",
"test-termwiz",
"test-doc",
]
[tasks.test-windows]
private = true
dependencies = [
"test-crossterm",
"test-termwiz",
"test-doc",
]
[tasks.test-crossterm]
env = { TUI_FEATURES = "serde,crossterm,all-widgets,macros" }
run_task = "test-backend"
[tasks.test-termion]
env = { TUI_FEATURES = "serde,termion,all-widgets,macros" }
run_task = "test-backend"
[tasks.test-termwiz]
env = { TUI_FEATURES = "serde,termwiz,all-widgets,macros" }
run_task = "test-backend"
[tasks.test-backend]
command = "cargo"
condition = { env_set = ["TUI_FEATURES"] }
args = [
"test",
"--no-default-features",
"--features",
"${TUI_FEATURES}",
"--all-targets",
"--all-features",
]
[tasks.test-windows]
dependencies = [
"test-doc",
]
args = [
"test",
"--all-targets",
"--no-default-features", "--features", "${ALL_FEATURES},crossterm,termwiz"
]
[tasks.test-doc]
command = "cargo"
args = ["test", "--doc"]
args = [
"test", "--doc",
"--all-features",
]
[tasks.test-doc.windows]
args = [
"test", "--doc",
"--no-default-features", "--features", "${ALL_FEATURES},crossterm,termwiz"
]
[tasks.test-backend]
# takes a command line parameter to specify the backend to test (e.g. "crossterm")
command = "cargo"
args = [
"test",
"--all-targets",
"--no-default-features", "--features", "${ALL_FEATURES},${@}"
]
[tasks.coverage]
command = "cargo"
args = [
"llvm-cov",
"--lcov",
"--output-path", "target/lcov.info",
"--all-features",
]
[tasks.coverage.windows]
command = "cargo"
args = [
"llvm-cov",
"--lcov",
"--output-path", "target/lcov.info",
"--no-default-features",
"--features", "${ALL_FEATURES},crossterm,termwiz",
]
[tasks.run-example]
private = true

View file

@ -24,7 +24,7 @@ use crate::{
/// Termwiz backend implementation for the [`Backend`] trait.
/// # Example
///
/// ```rust
/// ```rust,no_run
/// use ratatui::backend::{Backend, TermwizBackend};
///
/// # fn main() -> Result<(), Box<dyn std::error::Error>> {