diff --git a/.github/workflows/test.yml b/.github/workflows/ci.yml
similarity index 54%
rename from .github/workflows/test.yml
rename to .github/workflows/ci.yml
index 0b2866c..79edf7f 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/ci.yml
@@ -1,4 +1,4 @@
-name: Test
+name: CI
on:
push:
@@ -21,7 +21,7 @@ jobs:
fail-fast: false
matrix:
include:
- - { os: ubuntu-latest, container: '', shell_path: /bin/bash, label: bash-5.x-linux }
+ - { os: ubuntu-latest, container: '', shell_path: /bin/bash, label: bash-5.x-linux, coverage: true }
- { os: macos-latest, container: '', shell_path: /bin/bash, label: bash-3.2-macos }
- { os: macos-latest, container: '', shell_path: brew, label: bash-5.x-macos }
- { os: ubuntu-latest, container: rockylinux:8, shell_path: /bin/bash, label: bash-4.4-linux }
@@ -47,6 +47,17 @@ jobs:
if: matrix.container == '' && runner.os == 'Linux' && contains(matrix.shell_path, 'zsh')
run: sudo apt-get update && sudo apt-get install -y zsh
+ - name: Install kcov (coverage, Linux)
+ if: matrix.coverage
+ run: |
+ sudo apt-get update
+ sudo apt-get install -y cmake binutils-dev libcurl4-openssl-dev libdw-dev libiberty-dev
+ wget -q https://github.com/SimonKagstrom/kcov/archive/refs/tags/v43.tar.gz
+ tar xzf v43.tar.gz
+ (cd kcov-43 && mkdir -p build && cd build && cmake -DCMAKE_INSTALL_PREFIX="$HOME/kcov" .. && make && make install)
+ rm -rf kcov-43 v43.tar.gz
+ echo "$HOME/kcov/bin" >> "$GITHUB_PATH"
+
- name: Install Homebrew bash (macOS bash 5.x)
if: matrix.shell_path == 'brew'
run: |
@@ -70,5 +81,40 @@ jobs:
- name: Run tests (${{ matrix.label }})
# test.sh self-sources ~/.xshrc, so running it under $SHELL_PATH makes
# the utilities execute under that shell (bash, or zsh's ksh emulation).
+ if: matrix.coverage != true
run: |
"$SHELL_PATH" ~/.xsh/repo/xsh-lib/core/test.sh
+
+ - name: Run tests with coverage (${{ matrix.label }})
+ # Pass the script DIRECTLY (not `bash test.sh`): kcov then uses its shell
+ # collector. `bash test.sh` makes kcov trace the bash ELF binary and
+ # record 0 lines. --include-path scopes the report to this lib's function
+ # utilities; script-type utilities run as child `bash` and aren't traced.
+ if: matrix.coverage
+ run: |
+ chmod +x "$HOME/.xsh/repo/xsh-lib/core/test.sh"
+ # Scope to the function utilities (script utilities run as child bash and
+ # aren't instrumentable).
+ kcov --include-path="$HOME/.xsh/repo/xsh-lib/core/functions" "$PWD/coverage" "$HOME/.xsh/repo/xsh-lib/core/test.sh"
+ # Normalize kcov's cobertura to repo-relative, line-only paths.
+ cob="$(find "$PWD/coverage" -name cobertura.xml | head -1)"
+ sed -i -E \
+ -e 's#[^<]*#.#' \
+ -e 's#filename="#filename="functions/#g' \
+ -e 's/ branch(es)?-(rate|covered|valid)="[^"]*"//g' \
+ "$cob"
+ # Keep only the cobertura so codecov-action's auto-search uploads just it
+ # (kcov also writes coverage.json/codecov.json with absolute paths).
+ find "$PWD/coverage" -type f ! -name cobertura.xml -delete
+
+ - name: Upload coverage to Codecov
+ if: matrix.coverage
+ uses: codecov/codecov-action@v5
+ env:
+ # codecov CLI's GPG self-check on its own download fails intermittently.
+ CC_SKIP_VALIDATION: 'true'
+ with:
+ # Mirror alexzhangs/xsh's WORKING setup: let codecov-action auto-discover
+ # the kcov report (no files:/disable_search:).
+ token: ${{ secrets.CODECOV_TOKEN }}
+ fail_ci_if_error: false
diff --git a/README.md b/README.md
index c6ba598..505ed52 100644
--- a/README.md
+++ b/README.md
@@ -4,7 +4,9 @@
[](https://github.com/xsh-lib/core/)
[](https://github.com/xsh-lib/core/commits/master)
-[](https://github.com/xsh-lib/core/actions/workflows/test.yml)
+[](https://github.com/xsh-lib/core/actions/workflows/ci.yml)
+[](https://codecov.io/github/xsh-lib/core)
+[](https://www.codefactor.io/repository/github/xsh-lib/core)
[](https://github.com/xsh-lib/core/issues)
[](https://github.com/xsh-lib/core/pulls)
@@ -18,10 +20,18 @@ About xsh and its libraries, check out [xsh document](https://github.com/alexzha
## Requirements
-Tested with bash:
+`xsh-lib/core` is tested in CI ([GitHub Actions](https://github.com/xsh-lib/core/actions/workflows/ci.yml)) on every push and pull request, across the following shell/OS combinations:
-* 4.3.48 on Linux
-* 3.2.57 on macOS
+| Shell | Version | OS | Tested |
+|-------|---------|-----------------------|:------:|
+| bash | 3.2 | macOS | ✅ |
+| bash | 4.4 | Linux (rockylinux:8) | ✅ |
+| bash | 5.x | Linux (ubuntu-latest) | ✅ |
+| bash | 5.x | macOS (Homebrew) | ✅ |
+| zsh | 5.x | Linux (ubuntu-latest) | ✅ |
+| zsh | 5.x | macOS | ✅ |
+
+zsh utilities run under xsh's ksh emulation and require **xsh ≥ 0.7.0**.
This project is still at version 0.x, and should be considered immature.
diff --git a/codecov.yml b/codecov.yml
new file mode 100644
index 0000000..c9f4b0a
--- /dev/null
+++ b/codecov.yml
@@ -0,0 +1,17 @@
+# Coverage is scoped to the function utilities and the cobertura is rewritten to
+# repo-relative paths (functions/...) in CI, so no path fixes are needed here.
+# Coverage is informational, not a merge gate (only function-type utilities are
+# instrumentable; script utilities run as child processes kcov cannot trace).
+# Coverage is scoped to the function utilities and rewritten to repo-relative
+# paths (functions/...) in CI, so no path fixes/ignores are needed here.
+# Informational only (script utilities aren't instrumentable).
+coverage:
+ status:
+ project:
+ default:
+ informational: true
+ patch:
+ default:
+ informational: true
+
+comment: false