diff --git a/.github/actions/install-taskwarrior/action.yml b/.github/actions/install-taskwarrior/action.yml new file mode 100644 index 00000000..038c2b44 --- /dev/null +++ b/.github/actions/install-taskwarrior/action.yml @@ -0,0 +1,106 @@ +# This action definition may look complicated, but it only builds taskwarrior from the latest source release and installs it. +# The rest of the file is caching of results and checks to avoid ambiguous failure in case taskwarrior changes their release strategy. +name: Install Taskwarrior +description: Builds latests stable taskwarrior release install it +inputs: + secret_gh_token: + description: "GH token used for downloading the release asset" + required: true + rust_toolchain: + description: "Rust toolchain to compile taskwarrior with" + default: stable +runs: + using: "composite" + steps: + - name: Update apt + run: sudo apt-get update + shell: bash + - name: Install libuuid + run: sudo apt-get install uuid-dev uuid-runtime + shell: bash + + - name: Download latest stable taskwarrior source release + # This pattern only matches assets with a [numbers and dots] version suffix + run: gh release download --repo "GothenburgBitFactory/taskwarrior" --pattern "task-[0-9.]*.tar.gz" --dir /tmp/download + shell: bash + env: + GH_TOKEN: ${{ inputs.secret_gh_token }} + - name: Ensure that we only got one release asset + run: | + number_of_assets=$(ls -1 /tmp/download | wc -l) + if [ $number_of_assets -ne 1 ] + then + echo "Expected exactly one release asset, got $number_of_assets instead" + exit 1 + else + echo "Got expected number of release assets" + fi + shell: bash + - name: Move taskwarrior source to task.tar.gz + run: | + cd /tmp/download + find . -name "*.tar.gz" -exec mv {} task.tar.gz \; + shell: bash + + - name: Calculate SHA256 of task.tar.gz source(version cache check) + id: calculate-task-sha256 + run: echo "task_sha256=$(/usr/bin/sha256sum /tmp/download/task.tar.gz | cut -d ' ' -f 1)" >> $GITHUB_OUTPUT + shell: bash + - name: Restore cached taskwarrior build + id: cache-taskwarrior-restore + uses: actions/cache/restore@v4 + with: + path: /tmp/task.deb + key: ${{ runner.os }}-taskwarrior-${{ steps.calculate-task-sha256.outputs.task_sha256 }}-rust-${{ inputs.rust_toolchain }} + + - name: Install rust toolchain and rust cache + if: steps.cache-taskwarrior-restore.outputs.cache-hit != 'true' + uses: actions-rust-lang/setup-rust-toolchain@v1 + with: + toolchain: ${{ inputs.rust_toolchain }} + override: false + - name: Extract taskwarrior source code + if: steps.cache-taskwarrior-restore.outputs.cache-hit != 'true' + run: | + cd /tmp/download + # Remove the version suffix from extracted directory + tar -xf task.tar.gz --transform='s;^task-[0-9.]*/;task/;' + cd /tmp + mv download/task taskwarrior + rm -rf download + shell: bash + - name: Set selected rust toolchain as default for taskwarrior + if: steps.cache-taskwarrior-restore.outputs.cache-hit != 'true' + run: rustup override set ${{ inputs.rust_toolchain }} --path /tmp/taskwarrior + shell: bash + - name: Compile and install taskwarrior + if: steps.cache-taskwarrior-restore.outputs.cache-hit != 'true' + run: | + cd /tmp/taskwarrior + cmake -S . -B build -DCMAKE_BUILD_TYPE=Release . + cmake --build build -j $(nproc) + cd build + # Create a stub debian package. WARNING: This package has no dependencies set + cpack -D CPACK_PACKAGE_CONTACT="stub" -D CPACK_PACKAGE_FILE_NAME="task" -G DEB + mv task.deb /tmp + cd /tmp + rm -rf /tmp/taskwarrior/ + shell: bash + - name: Unset rust toolchain again + if: steps.cache-taskwarrior-restore.outputs.cache-hit != 'true' + run: rustup override unset --path /tmp/taskwarrior + shell: bash + - name: Cache taskwarrior build result + if: steps.cache-taskwarrior-restore.outputs.cache-hit != 'true' + id: cache-taskwarrior-save + uses: actions/cache/save@v4 + with: + path: /tmp/task.deb + key: ${{ steps.cache-taskwarrior-restore.outputs.cache-primary-key }} + + - name: Install taskwarrior + run: sudo dpkg -i /tmp/task.deb + shell: bash + - name: Test if installation worked + run: task --version + shell: bash \ No newline at end of file diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index de2469d1..020bb8c1 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,5 +1,7 @@ name: Build -on: [pull_request] +on: + pull_request: + workflow_call: jobs: build: runs-on: ${{ matrix.os }} @@ -11,9 +13,6 @@ jobs: target: x86_64-apple-darwin rust_flags: '' features: '' - binary_postfix: '' - upx_args: --best - strip: true - os: ubuntu-latest target: x86_64-unknown-linux-gnu rust_flags: '' @@ -54,21 +53,23 @@ jobs: MACOSX_DEPLOYMENT_TARGET: 10.7 steps: - uses: actions/checkout@master - - uses: actions-rs/toolchain@v1 + - uses: actions-rust-lang/setup-rust-toolchain@v1 with: toolchain: stable target: ${{ matrix.target }} - default: true - - uses: actions-rs/cargo@v1 + override: true + - uses: clechasseur/rs-cargo@v2 with: command: build args: --release ${{matrix.features}} --target=${{ matrix.target }} - name: Compress binaries uses: svenstaro/upx-action@v2 with: - file: target/${{ matrix.target }}/release/taskwarrior-tui${{ matrix.binary_postfix }} + files: target/${{ matrix.target }}/release/taskwarrior-tui${{ matrix.binary_postfix }} args: ${{ matrix.upx_args }} strip: ${{ matrix.strip }} + # MacOS Compression disabled due to bug https://github.com/upx/upx/blob/44e4bd0b5454ff8aee1ff3376974dfe6014300d9/NEWS#L31 + if: ${{ matrix.os != 'macOS-latest' }} - name: Packaging binary shell: bash run: | @@ -80,9 +81,9 @@ jobs: shasum -a 256 taskwarrior-tui-${{ matrix.target }}.tar.gz > taskwarrior-tui-${{ matrix.target }}.sha256 fi - name: Upload artifacts - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v4 with: - name: taskwarrior-tui + name: taskwarrior-tui-${{ matrix.target }} path: target/${{ matrix.target }}/release/taskwarrior-tui-${{ matrix.target }}.tar.gz - name: Releasing assets if: startsWith(github.ref, 'refs/tags/') diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml index 01a34539..f1b29e5c 100644 --- a/.github/workflows/cd.yml +++ b/.github/workflows/cd.yml @@ -12,98 +12,10 @@ permissions: jobs: build: - runs-on: ${{ matrix.os }} - strategy: - fail-fast: false - matrix: - include: - - os: macOS-latest - target: x86_64-apple-darwin - rust_flags: "" - features: "" - binary_postfix: "" - upx_args: --best - strip: true - - os: ubuntu-latest - target: x86_64-unknown-linux-gnu - rust_flags: "" - features: "" - binary_postfix: "" - upx_args: --best --lzma - strip: true - - os: ubuntu-latest - target: x86_64-unknown-linux-musl - rust_flags: "" - features: "" - binary: "taskwarrior-tui-x86_64-unknown-linux-musl" - upx_args: --best --lzma - strip: true - - os: windows-latest - target: x86_64-pc-windows-gnu - rust_flags: -C target-feature=+crt-static - features: "" - binary_postfix: ".exe" - upx_args: -9 - strip: false - - os: windows-latest - target: x86_64-pc-windows-msvc - rust_flags: -C target-feature=+crt-static - features: "" - binary_postfix: ".exe" - upx_args: -9 - strip: false - - os: windows-latest - target: i686-pc-windows-msvc - rust_flags: -C target-feature=+crt-static - features: "" - binary_postfix: ".exe" - upx_args: -9 - strip: false - env: - RUSTFLAGS: ${{ matrix.rust_flags }} - MACOSX_DEPLOYMENT_TARGET: 10.7 - steps: - - uses: actions/checkout@master - - uses: actions-rs/toolchain@v1 - with: - toolchain: stable - target: ${{ matrix.target }} - default: true - - uses: actions-rs/cargo@v1 - with: - command: build - args: --release ${{matrix.features}} --target=${{ matrix.target }} - - name: Compress binaries - uses: svenstaro/upx-action@v2 - with: - files: | - target/${{ matrix.target }}/release/taskwarrior-tui${{ matrix.binary_postfix }} - args: ${{ matrix.upx_args }} - strip: ${{ matrix.strip }} - - name: Packaging binary - shell: bash - run: | - cd target/${{ matrix.target }}/release - tar czvf taskwarrior-tui-${{ matrix.target }}.tar.gz taskwarrior-tui${{ matrix.binary_postfix }} - if [[ ${{ runner.os }} == 'Windows' ]]; then - certutil -hashfile taskwarrior-tui-${{ matrix.target }}.tar.gz sha256 | grep -E [A-Fa-f0-9]{64} > taskwarrior-tui-${{ matrix.target }}.sha256 - else - shasum -a 256 taskwarrior-tui-${{ matrix.target }}.tar.gz > taskwarrior-tui-${{ matrix.target }}.sha256 - fi - - name: Upload artifacts - uses: actions/upload-artifact@v2 - with: - name: taskwarrior-tui - path: target/${{ matrix.target }}/release/taskwarrior-tui-${{ matrix.target }}.tar.gz - - name: Releasing assets - if: startsWith(github.ref, 'refs/tags/') - uses: softprops/action-gh-release@v2 - with: - files: | - target/${{ matrix.target }}/release/taskwarrior-tui-${{ matrix.target }}.tar.gz - target/${{ matrix.target }}/release/taskwarrior-tui-${{ matrix.target }}.sha256 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + uses: ./.github/workflows/build.yml + + generate_coverage: + uses: ./.github/workflows/generate_coverage.yml homebrew: name: Bump Homebrew formula @@ -122,7 +34,7 @@ jobs: steps: - name: Check out Git repository uses: actions/checkout@v4 - - uses: actions-rs/cargo@v1 + - uses: clechasseur/rs-cargo@v2 with: command: build args: --release @@ -131,9 +43,9 @@ jobs: - name: Build deb package run: cargo deb -p taskwarrior-tui -o target/debian/taskwarrior-tui.deb - name: Upload artifacts - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v4 with: - name: taskwarrior-tui + name: taskwarrior-tui-deb path: target/debian/taskwarrior-tui.deb - name: Releasing assets if: startsWith(github.ref, 'refs/tags/') @@ -150,7 +62,7 @@ jobs: steps: - name: Check out Git repository uses: actions/checkout@v4 - - uses: actions-rs/cargo@v1 + - uses: clechasseur/rs-cargo@v2 with: command: build args: --release @@ -161,9 +73,9 @@ jobs: - name: Build rpm package run: cargo rpm build - name: Upload artifacts - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v4 with: - name: taskwarrior-tui + name: taskwarrior-tui-rpm path: target/release/rpmbuild/RPMS/x86_64/taskwarrior-tui-*.x86_64.rpm - name: Releasing assets if: startsWith(github.ref, 'refs/tags/') @@ -180,85 +92,11 @@ jobs: steps: - name: Check out Git repository uses: actions/checkout@v4 - - uses: actions-rs/cargo@v1 + - uses: clechasseur/rs-cargo@v2 with: command: build args: --release - name: Install cargo-aur run: cargo install cargo-aur - name: Build aur package - run: cargo aur - - grcov: - runs-on: ubuntu-latest - env: - TASKRC: taskwarrior-testdata/.taskrc - TASKDATA: taskwarrior-testdata/.task - RUST_BACKTRACE: full - steps: - - uses: actions/checkout@v4 - - name: Install toolchain - uses: actions-rs/toolchain@v1 - with: - toolchain: nightly - override: true - profile: minimal - - run: sudo apt-get update - - name: Compile taskwarrior - run: | - cd /tmp - git clone https://github.com/GothenburgBitFactory/taskwarrior - cd taskwarrior - git checkout v3.0.0 - cmake -DCMAKE_BUILD_TYPE=release -DENABLE_SYNC=OFF . - make - sudo make install - - run: | - task --version - - uses: actions/checkout@v4 - with: - repository: kdheepak/taskwarrior-testdata - path: taskwarrior-testdata - - run: | - # prepare taskwarrior, initial setup - task rc.confirmation=off || echo 0 - - name: Execute tests - uses: actions-rs/cargo@v1 - with: - command: test - args: --all - env: - CARGO_INCREMENTAL: 0 - RUSTFLAGS: "-Zprofile -Ccodegen-units=1 -Cinline-threshold=0 -Clink-dead-code -Coverflow-checks=off -Cpanic=abort -Zpanic_abort_tests" - - # Note that `actions-rs/grcov` Action can install `grcov` too, - # but can't use faster installation methods yet. - # As a temporary experiment `actions-rs/install` Action plugged in here. - # Consider **NOT** to copy that into your workflow, - # but use `actions-rs/grcov` only - - name: Pre-installing grcov - uses: actions-rs/install@v0.1 - with: - crate: grcov - use-tool-cache: true - - - name: Gather coverage data - id: coverage - uses: actions-rs/grcov@v0.1 - - - name: Coveralls upload - uses: coverallsapp/github-action@master - with: - github-token: ${{ secrets.GITHUB_TOKEN }} - parallel: true - path-to-lcov: ${{ steps.coverage.outputs.report }} - - grcov_finalize: - runs-on: ubuntu-latest - needs: grcov - steps: - - name: Coveralls finalization - uses: coverallsapp/github-action@master - with: - github-token: ${{ secrets.GITHUB_TOKEN }} - parallel-finished: true + run: cargo aur \ No newline at end of file diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ee66e1e0..7f66c6ae 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -8,65 +8,61 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - uses: actions-rs/toolchain@v1 + - uses: actions-rust-lang/setup-rust-toolchain@v1 with: - profile: minimal toolchain: stable override: true - - uses: actions-rs/cargo@v1 + - uses: clechasseur/rs-cargo@v2 with: command: check test: name: Test Suite runs-on: ubuntu-latest - env: - TASKRC: taskwarrior-testdata/.taskrc - TASKDATA: taskwarrior-testdata/.task - RUST_BACKTRACE: full steps: - uses: actions/checkout@v4 - - uses: actions-rs/toolchain@v1 + - name: Install Taskwarrior + uses: ./.github/actions/install-taskwarrior + with: + secret_gh_token: ${{ secrets.GITHUB_TOKEN }} + - run: | + # prepare taskwarrior, initial setup + task rc.confirmation=off || echo 0 + - uses: actions-rust-lang/setup-rust-toolchain@v1 with: - profile: minimal toolchain: stable override: true - - run: sudo apt-get update - - name: Compile taskwarrior - run: | - cd /tmp - git clone https://github.com/GothenburgBitFactory/taskwarrior - cd taskwarrior - git checkout v3.0.0 - cmake -DCMAKE_BUILD_TYPE=release -DENABLE_SYNC=OFF . - make - sudo make install - - run: | - task --version - - uses: actions/checkout@v4 + - name: Install testdata + uses: actions/checkout@v4 with: repository: kdheepak/taskwarrior-testdata path: taskwarrior-testdata - - run: | - # prepare taskwarrior, initial setup - task rc.confirmation=off || echo 0 - - uses: actions-rs/cargo@v1 + - uses: clechasseur/rs-cargo@v2 with: command: test - args: --all -- --nocapture + args: --workspace -- --nocapture + env: + TASKRC: taskwarrior-testdata/.taskrc + TASKDATA: taskwarrior-testdata/.task + RUST_BACKTRACE: full + + + generate_coverage: + uses: ./.github/workflows/generate_coverage.yml + # Avoid double-compiling taskwarrior if not cached, or wasting CI time if tests fail + needs: test fmt: - name: Rustfmt + name: Rustfm runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - uses: actions-rs/toolchain@v1 + - uses: actions-rust-lang/setup-rust-toolchain@v1 with: - profile: minimal toolchain: nightly override: true - - run: rustup component add rustfmt - - uses: actions-rs/cargo@v1 + components: rustfmt + - uses: clechasseur/rs-cargo@v2 with: command: fmt args: --all -- --check @@ -76,13 +72,12 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - uses: actions-rs/toolchain@v1 + - uses: actions-rust-lang/setup-rust-toolchain@v1 with: - profile: minimal toolchain: stable override: true - - run: rustup component add clippy - - uses: actions-rs/cargo@v1 + components: clippy + - uses: clechasseur/rs-cargo@v2 with: command: clippy - args: -- -D warnings + args: -- -D warnings \ No newline at end of file diff --git a/.github/workflows/generate_coverage.yml b/.github/workflows/generate_coverage.yml new file mode 100644 index 00000000..d0ad46b2 --- /dev/null +++ b/.github/workflows/generate_coverage.yml @@ -0,0 +1,68 @@ +name: generate_coverage + +on: + workflow_call + +jobs: + grcov: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Install Taskwarrior + uses: ./.github/actions/install-taskwarrior + with: + secret_gh_token: ${{ secrets.GITHUB_TOKEN }} + - run: | + # prepare taskwarrior, initial setup + task rc.confirmation=off || echo 0 + + - name: Install Rust toolchain for grcov compilation + uses: actions-rust-lang/setup-rust-toolchain@v1 + with: + toolchain: stable + override: true + - name: Install grcov + uses: clechasseur/rs-cargo@v2 + with: + command: install + args: grcov + + - name: Install Rust toolchain + uses: actions-rust-lang/setup-rust-toolchain@v1 + with: + toolchain: nightly + override: true + components: llvm-tools-preview + - name: Checkout testdata + uses: actions/checkout@v4 + with: + repository: kdheepak/taskwarrior-testdata + path: taskwarrior-testdata + - name: Build taskwarrior-tui with coverage + uses: clechasseur/rs-cargo@v2 + with: + command: build + env: + RUSTFLAGS: "-Cinstrument-coverage" + - name: Run taskwarrior-tui tests in coverage environment + uses: clechasseur/rs-cargo@v2 + with: + command: test + args: --workspace -- --nocapture + env: + TASKRC: taskwarrior-testdata/.taskrc + TASKDATA: taskwarrior-testdata/.task + RUST_BACKTRACE: full + RUSTFLAGS: "-Cinstrument-coverage" + LLVM_PROFILE_FILE: "your_name-%p-%m.profraw" + + - name: Gather coverage data + run: | + mkdir ./target/debug/coverage/ + grcov . -s . --binary-path ./target/debug/ -t lcov --branch --ignore-not-existing -o ./target/debug/coverage/ + shell: bash + - name: Coveralls upload + uses: coverallsapp/github-action@v2 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + file: ./target/debug/coverage/lcov \ No newline at end of file diff --git a/src/app.rs b/src/app.rs index 63850d12..66c36a76 100644 --- a/src/app.rs +++ b/src/app.rs @@ -505,17 +505,14 @@ impl TaskwarriorTui { let virtual_tag_names_in_precedence = &self.config.rule_precedence_color; let mut style = Style::default(); for tag_name in virtual_tag_names_in_precedence.iter().rev() { - match tag_name.as_str() { - "project." => { - let s = self - .config - .color - .get(&format!("color.project.{}", project[0])) - .copied() - .unwrap_or_default(); - style = style.patch(s); - } - &_ => {} + if tag_name.as_str() == "project." { + let s = self + .config + .color + .get(&format!("color.project.{}", project[0])) + .copied() + .unwrap_or_default(); + style = style.patch(s); } } style