From a483569e79a025e7cc8bf7de897690be2c0d2741 Mon Sep 17 00:00:00 2001 From: Neil Date: Sun, 29 Mar 2026 18:11:28 +0800 Subject: [PATCH 1/4] feat(ci): add Woodpecker CI pipelines for PR and develop branch Adds .woodpecker/pr.yaml (PR checks) and .woodpecker/ci.yaml (push to develop checks) with rust-fmt, clippy, cargo-test, and cmake-build-test steps. Updates README with Woodpecker CI badge. --- .woodpecker/ci.yaml | 39 +++++++++++++++++++++++++++++++++++++++ .woodpecker/pr.yaml | 38 ++++++++++++++++++++++++++++++++++++++ README.md | 1 + 3 files changed, 78 insertions(+) create mode 100644 .woodpecker/ci.yaml create mode 100644 .woodpecker/pr.yaml diff --git a/.woodpecker/ci.yaml b/.woodpecker/ci.yaml new file mode 100644 index 000000000..47e3fc249 --- /dev/null +++ b/.woodpecker/ci.yaml @@ -0,0 +1,39 @@ +clone: + git: + image: woodpeckerci/plugin-git + settings: + recursive: true + +when: + - event: push + branch: develop + +steps: + - name: rust-fmt + image: rust:latest + commands: + - rustup component add rustfmt + - cargo fmt --all -- --check + + - name: clippy + image: rust:1.88 + commands: + - rustup component add clippy + - cargo clippy --all-features -- -D warnings + + - name: cargo-test + image: rust:1.88 + commands: + - cargo test + + - name: cmake-build-test + image: debian:bookworm + commands: + - apt-get update && apt-get install -y --no-install-recommends + build-essential cmake git uuid-dev faketime locales + python3 curl ninja-build ca-certificates + - curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain 1.88.0 + - export PATH="/root/.cargo/bin:$$PATH" + - cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Debug + - cmake --build build --target test_runner --target task_executable -j$$(nproc) + - ctest --test-dir build -j$$(nproc) --output-on-failure diff --git a/.woodpecker/pr.yaml b/.woodpecker/pr.yaml new file mode 100644 index 000000000..7f5f62001 --- /dev/null +++ b/.woodpecker/pr.yaml @@ -0,0 +1,38 @@ +clone: + git: + image: woodpeckerci/plugin-git + settings: + recursive: true + +when: + - event: pull_request + +steps: + - name: rust-fmt + image: rust:latest + commands: + - rustup component add rustfmt + - cargo fmt --all -- --check + + - name: clippy + image: rust:1.88 + commands: + - rustup component add clippy + - cargo clippy --all-features -- -D warnings + + - name: cargo-test + image: rust:1.88 + commands: + - cargo test + + - name: cmake-build-test + image: debian:bookworm + commands: + - apt-get update && apt-get install -y --no-install-recommends + build-essential cmake git uuid-dev faketime locales + python3 curl ninja-build ca-certificates + - curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain 1.88.0 + - export PATH="/root/.cargo/bin:$$PATH" + - cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Debug + - cmake --build build --target test_runner --target task_executable -j$$(nproc) + - ctest --test-dir build -j$$(nproc) --output-on-failure diff --git a/README.md b/README.md index 548b89af0..b78dd6fb8 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@

+[![CI](https://ci.guion.io/api/badges/GuionAI/taskwarrior/status.svg)](https://ci.guion.io/GuionAI/taskwarrior) [![GitHub Actions build status](https://github.com/GothenburgBitFactory/taskwarrior/workflows/tests/badge.svg?branch=develop)](https://github.com/GothenburgBitFactory/taskwarrior/actions) [![Coverage Status](https://coveralls.io/repos/github/GothenburgBitFactory/taskwarrior/badge.svg?branch=develop)](https://coveralls.io/github/GothenburgBitFactory/taskwarrior?branch=develop) [![Release](https://img.shields.io/github/v/release/GothenburgBitFactory/taskwarrior)](https://github.com/GothenburgBitFactory/taskwarrior/releases/latest) From 1ed64f5adea137885d9acf03ebf1c2e05913a108 Mon Sep 17 00:00:00 2001 From: Neil Date: Sun, 29 Mar 2026 18:12:32 +0800 Subject: [PATCH 2/4] feat(build): add Makefile wrapping cmake commands Adds make build/install/test/clean targets. BUILD_TYPE defaults to Release; test target forces Debug for ctest. NPROC auto-detected via nproc/sysctl with fallback to 4. --- Makefile | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 Makefile diff --git a/Makefile b/Makefile new file mode 100644 index 000000000..b4e3cedc4 --- /dev/null +++ b/Makefile @@ -0,0 +1,22 @@ +BUILD_DIR := build +BUILD_TYPE ?= Release +NPROC := $(shell nproc 2>/dev/null || sysctl -n hw.ncpu 2>/dev/null || echo 4) + +.PHONY: build install test clean + +build: + cmake -S . -B $(BUILD_DIR) -DCMAKE_BUILD_TYPE=$(BUILD_TYPE) + cmake --build $(BUILD_DIR) -j$(NPROC) + +# Installs task binary, man pages, and docs per CMakeLists.txt install() rules. +# Use CMAKE_INSTALL_PREFIX to control destination (default: /usr/local). +install: build + cmake --install $(BUILD_DIR) + +test: + cmake -S . -B $(BUILD_DIR) -DCMAKE_BUILD_TYPE=Debug + cmake --build $(BUILD_DIR) --target test_runner --target task_executable -j$(NPROC) + ctest --test-dir $(BUILD_DIR) -j$(NPROC) --output-on-failure + +clean: + rm -rf $(BUILD_DIR) From 34fcd43cbf6d31a079e1da3b43ce096299fe0db1 Mon Sep 17 00:00:00 2001 From: Neil Date: Sun, 29 Mar 2026 18:14:54 +0800 Subject: [PATCH 3/4] feat(lint): add qlty for unified linting, formatting, and secret scanning Adds .qlty/qlty.toml with clippy, rustfmt, trufflehog, and osv-scanner plugins. Excludes build/, target/, libshared/, and corrosion/ from scanning. Includes pre-commit (fmt) and pre-push (check) hook scripts. --- .qlty/hooks/pre-commit.sh | 2 ++ .qlty/hooks/pre-push.sh | 6 ++++++ .qlty/qlty.toml | 39 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 47 insertions(+) create mode 100755 .qlty/hooks/pre-commit.sh create mode 100755 .qlty/hooks/pre-push.sh create mode 100644 .qlty/qlty.toml diff --git a/.qlty/hooks/pre-commit.sh b/.qlty/hooks/pre-commit.sh new file mode 100755 index 000000000..d2489ddbc --- /dev/null +++ b/.qlty/hooks/pre-commit.sh @@ -0,0 +1,2 @@ +#\!/bin/sh +qlty fmt --trigger pre-commit --index-file="$GIT_INDEX_FILE" diff --git a/.qlty/hooks/pre-push.sh b/.qlty/hooks/pre-push.sh new file mode 100755 index 000000000..b1b3184c8 --- /dev/null +++ b/.qlty/hooks/pre-push.sh @@ -0,0 +1,6 @@ +#\!/bin/sh +qlty check \ + --trigger pre-push \ + --upstream-from-pre-push \ + --no-formatters \ + --skip-errored-plugins diff --git a/.qlty/qlty.toml b/.qlty/qlty.toml new file mode 100644 index 000000000..ca9fde907 --- /dev/null +++ b/.qlty/qlty.toml @@ -0,0 +1,39 @@ +config_version = "0" + +exclude_patterns = [ + "build/**", + "target/**", + "src/libshared/**", + "src/taskchampion-cpp/corrosion/**", +] + +test_patterns = [ + "test/**", +] + +[smells] +mode = "comment" + +[[source]] +name = "default" +default = true + +# Rust linting via clippy +[[plugin]] +name = "clippy" +mode = "block" + +# Rust formatting via rustfmt +[[plugin]] +name = "rustfmt" +mode = "block" + +# Secret scanning — catches leaked API keys, credentials +[[plugin]] +name = "trufflehog" +mode = "block" + +# Dependency vulnerability scanning (scans Cargo.lock) +[[plugin]] +name = "osv-scanner" +mode = "block" From b586c6b8e95987721580926f23280f08e217dcb6 Mon Sep 17 00:00:00 2001 From: Neil Date: Sun, 29 Mar 2026 18:20:26 +0800 Subject: [PATCH 4/4] =?UTF-8?q?fix(ci):=20address=20review=20issues=20?= =?UTF-8?q?=E2=80=94=20pin=20rust=20version,=20remove=20curl|sh,=20dedupli?= =?UTF-8?q?cate=20pipelines?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Pin rust-fmt step to rust:1.88 (was rust:latest — floating tag causes inconsistent fmt results against pinned MSRV) - Merge pr.yaml into ci.yaml with combined when block (eliminates byte-for-byte duplication and future drift risk) - Switch cmake-build-test from debian:bookworm+curl|sh to rust:1.88 base image (Rust already present, no supply-chain risk from piped shell scripts) - Use `make test` in CI cmake-build-test step (Makefile is now SSOT for local and CI builds) - Makefile: use BUILD_DIR_TEST := build-test for test target so `make build && make test` never silently reconfigures the release dir --- .woodpecker/ci.yaml | 13 +++++-------- .woodpecker/pr.yaml | 38 -------------------------------------- Makefile | 16 +++++++++------- 3 files changed, 14 insertions(+), 53 deletions(-) delete mode 100644 .woodpecker/pr.yaml diff --git a/.woodpecker/ci.yaml b/.woodpecker/ci.yaml index 47e3fc249..ddbb4f8f5 100644 --- a/.woodpecker/ci.yaml +++ b/.woodpecker/ci.yaml @@ -5,12 +5,13 @@ clone: recursive: true when: + - event: pull_request - event: push branch: develop steps: - name: rust-fmt - image: rust:latest + image: rust:1.88 commands: - rustup component add rustfmt - cargo fmt --all -- --check @@ -27,13 +28,9 @@ steps: - cargo test - name: cmake-build-test - image: debian:bookworm + image: rust:1.88 commands: - apt-get update && apt-get install -y --no-install-recommends build-essential cmake git uuid-dev faketime locales - python3 curl ninja-build ca-certificates - - curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain 1.88.0 - - export PATH="/root/.cargo/bin:$$PATH" - - cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Debug - - cmake --build build --target test_runner --target task_executable -j$$(nproc) - - ctest --test-dir build -j$$(nproc) --output-on-failure + python3 ninja-build ca-certificates make + - make test diff --git a/.woodpecker/pr.yaml b/.woodpecker/pr.yaml deleted file mode 100644 index 7f5f62001..000000000 --- a/.woodpecker/pr.yaml +++ /dev/null @@ -1,38 +0,0 @@ -clone: - git: - image: woodpeckerci/plugin-git - settings: - recursive: true - -when: - - event: pull_request - -steps: - - name: rust-fmt - image: rust:latest - commands: - - rustup component add rustfmt - - cargo fmt --all -- --check - - - name: clippy - image: rust:1.88 - commands: - - rustup component add clippy - - cargo clippy --all-features -- -D warnings - - - name: cargo-test - image: rust:1.88 - commands: - - cargo test - - - name: cmake-build-test - image: debian:bookworm - commands: - - apt-get update && apt-get install -y --no-install-recommends - build-essential cmake git uuid-dev faketime locales - python3 curl ninja-build ca-certificates - - curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain 1.88.0 - - export PATH="/root/.cargo/bin:$$PATH" - - cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Debug - - cmake --build build --target test_runner --target task_executable -j$$(nproc) - - ctest --test-dir build -j$$(nproc) --output-on-failure diff --git a/Makefile b/Makefile index b4e3cedc4..7ab31973e 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,7 @@ -BUILD_DIR := build -BUILD_TYPE ?= Release -NPROC := $(shell nproc 2>/dev/null || sysctl -n hw.ncpu 2>/dev/null || echo 4) +BUILD_DIR := build +BUILD_DIR_TEST := build-test +BUILD_TYPE ?= Release +NPROC := $(shell nproc 2>/dev/null || sysctl -n hw.ncpu 2>/dev/null || echo 4) .PHONY: build install test clean @@ -13,10 +14,11 @@ build: install: build cmake --install $(BUILD_DIR) +# Uses a separate build-test dir (Debug) so it never clobbers the release build. test: - cmake -S . -B $(BUILD_DIR) -DCMAKE_BUILD_TYPE=Debug - cmake --build $(BUILD_DIR) --target test_runner --target task_executable -j$(NPROC) - ctest --test-dir $(BUILD_DIR) -j$(NPROC) --output-on-failure + cmake -S . -B $(BUILD_DIR_TEST) -DCMAKE_BUILD_TYPE=Debug + cmake --build $(BUILD_DIR_TEST) --target test_runner --target task_executable -j$(NPROC) + ctest --test-dir $(BUILD_DIR_TEST) -j$(NPROC) --output-on-failure clean: - rm -rf $(BUILD_DIR) + rm -rf $(BUILD_DIR) $(BUILD_DIR_TEST)