From 3caeb5e98f33ce606bd61124089b228e35a35223 Mon Sep 17 00:00:00 2001 From: Alex Date: Sun, 14 Jun 2026 21:52:37 +0800 Subject: [PATCH 1/3] docs: add tested-platforms matrix; standardize CI workflow to ci.yml Replace the stale 'Tested with bash 4.3.48' note with an OS/shell test matrix. Rename the CI workflow to ci.yml (name: CI) to match alexzhangs/xsh and the other xsh-lib repos; CI badge now points at ci.yml. Co-Authored-By: Claude Opus 4.8 (1M context) --- .github/workflows/{test.yml => ci.yml} | 2 +- README.md | 16 ++++++++++++---- 2 files changed, 13 insertions(+), 5 deletions(-) rename .github/workflows/{test.yml => ci.yml} (99%) diff --git a/.github/workflows/test.yml b/.github/workflows/ci.yml similarity index 99% rename from .github/workflows/test.yml rename to .github/workflows/ci.yml index 0b2866c..de2231b 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/ci.yml @@ -1,4 +1,4 @@ -name: Test +name: CI on: push: diff --git a/README.md b/README.md index c6ba598..499d1a1 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ [![GitHub](https://img.shields.io/github/license/xsh-lib/core.svg?style=flat-square)](https://github.com/xsh-lib/core/) [![GitHub last commit](https://img.shields.io/github/last-commit/xsh-lib/core.svg?style=flat-square)](https://github.com/xsh-lib/core/commits/master) -[![Test](https://github.com/xsh-lib/core/actions/workflows/test.yml/badge.svg)](https://github.com/xsh-lib/core/actions/workflows/test.yml) +[![CI](https://github.com/xsh-lib/core/actions/workflows/ci.yml/badge.svg)](https://github.com/xsh-lib/core/actions/workflows/ci.yml) [![GitHub issues](https://img.shields.io/github/issues/xsh-lib/core.svg?style=flat-square)](https://github.com/xsh-lib/core/issues) [![GitHub pull requests](https://img.shields.io/github/issues-pr/xsh-lib/core.svg?style=flat-square)](https://github.com/xsh-lib/core/pulls) @@ -18,10 +18,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. From 6d508c400f2abd88f48c7d24f795d541cd3b033e Mon Sep 17 00:00:00 2001 From: Alex Date: Sun, 14 Jun 2026 23:52:12 +0800 Subject: [PATCH 2/3] =?UTF-8?q?ci:=20add=20kcov=E2=86=92Codecov=20coverage?= =?UTF-8?q?=20(bash-5.x-linux);=20docs:=20codecov=20+=20CodeFactor=20badge?= =?UTF-8?q?s?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Run test.sh directly under kcov (shell collector), scoped to functions/; script utilities run as child bash and aren't instrumentable. The cobertura is normalized to repo-relative, line-only paths. Upload is best-effort (fail_ci_if_error: false) via the xsh-lib CODECOV_TOKEN. Adds codecov + CodeFactor badges. NOTE: Codecov-side report processing is currently failing for this repo (REPORT_EMPTY on every report, incl. a minimal valid one) — coverage measurement is green; the codecov badge will populate once that is resolved. Co-Authored-By: Claude Opus 4.8 (1M context) --- .github/workflows/ci.yml | 56 +++++++++++++++++++++++++++++++++++++++- README.md | 2 ++ codecov.yml | 17 ++++++++++++ 3 files changed, 74 insertions(+), 1 deletion(-) create mode 100644 codecov.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index de2231b..8918826 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -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,48 @@ 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" + cob="$(find "$PWD/coverage" -name cobertura.xml | head -1)" + # Normalize kcov's cobertura for Codecov: + # - -> "." and prefix filenames with functions/ => repo-relative. + # - strip kcov's non-standard branch-* attrs (branches-covered="1.0", etc.) + # that make Codecov reject the report as unusable ("incorrect data format"). + sed -i -E \ + -e 's#[^<]*#.#' \ + -e 's#filename="#filename="functions/#g' \ + -e 's/ branch(es)?-(rate|covered|valid)="[^"]*"//g' \ + "$cob" + cp "$cob" "$PWD/cobertura.xml" + # TEMP ISOLATION TEST: minimal, textbook-valid cobertura referencing one + # real tracked file (single line to stay safe inside the YAML block scalar). + # If this still REPORT_EMPTYs, the fault is Codecov/repo-side, not kcov. + printf '%s' '.' > "$PWD/cobertura.xml" + + - 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; + # skip it (real upload is governed by token presence below). + CC_SKIP_VALIDATION: 'true' + with: + # Sanitized, repo-relative, line-only cobertura. + files: ./cobertura.xml + disable_search: true + token: ${{ secrets.CODECOV_TOKEN }} + # Best-effort: transient Codecov issues shouldn't fail CI. + fail_ci_if_error: false diff --git a/README.md b/README.md index 499d1a1..505ed52 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,8 @@ [![GitHub last commit](https://img.shields.io/github/last-commit/xsh-lib/core.svg?style=flat-square)](https://github.com/xsh-lib/core/commits/master) [![CI](https://github.com/xsh-lib/core/actions/workflows/ci.yml/badge.svg)](https://github.com/xsh-lib/core/actions/workflows/ci.yml) +[![codecov](https://codecov.io/github/xsh-lib/core/graph/badge.svg?token=9N6P7MY18U)](https://codecov.io/github/xsh-lib/core) +[![CodeFactor](https://www.codefactor.io/repository/github/xsh-lib/core/badge)](https://www.codefactor.io/repository/github/xsh-lib/core) [![GitHub issues](https://img.shields.io/github/issues/xsh-lib/core.svg?style=flat-square)](https://github.com/xsh-lib/core/issues) [![GitHub pull requests](https://img.shields.io/github/issues-pr/xsh-lib/core.svg?style=flat-square)](https://github.com/xsh-lib/core/pulls) 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 From f174389fd18753d4dd8f635019356052f45603bf Mon Sep 17 00:00:00 2001 From: Alex Date: Mon, 15 Jun 2026 00:16:35 +0800 Subject: [PATCH 3/3] ci: mirror xsh's working Codecov upload (auto-search, drop disable_search/files) Co-Authored-By: Claude Opus 4.8 (1M context) --- .github/workflows/ci.yml | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8918826..79edf7f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -96,33 +96,25 @@ jobs: # 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)" - # Normalize kcov's cobertura for Codecov: - # - -> "." and prefix filenames with functions/ => repo-relative. - # - strip kcov's non-standard branch-* attrs (branches-covered="1.0", etc.) - # that make Codecov reject the report as unusable ("incorrect data format"). sed -i -E \ -e 's#[^<]*#.#' \ -e 's#filename="#filename="functions/#g' \ -e 's/ branch(es)?-(rate|covered|valid)="[^"]*"//g' \ "$cob" - cp "$cob" "$PWD/cobertura.xml" - # TEMP ISOLATION TEST: minimal, textbook-valid cobertura referencing one - # real tracked file (single line to stay safe inside the YAML block scalar). - # If this still REPORT_EMPTYs, the fault is Codecov/repo-side, not kcov. - printf '%s' '.' > "$PWD/cobertura.xml" + # 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; - # skip it (real upload is governed by token presence below). + # codecov CLI's GPG self-check on its own download fails intermittently. CC_SKIP_VALIDATION: 'true' with: - # Sanitized, repo-relative, line-only cobertura. - files: ./cobertura.xml - disable_search: true + # Mirror alexzhangs/xsh's WORKING setup: let codecov-action auto-discover + # the kcov report (no files:/disable_search:). token: ${{ secrets.CODECOV_TOKEN }} - # Best-effort: transient Codecov issues shouldn't fail CI. fail_ci_if_error: false