Skip to content

ci: modernise workflows; fix gcc-ASAN - #206

Merged
ms609-agent merged 11 commits into
mainfrom
ci/modernise-workflows
Sep 21, 2026
Merged

ms609-agent merged 11 commits into
mainfrom
ci/modernise-workflows

Conversation

@ms609-agent

@ms609-agent ms609-agent commented Sep 21, 2026 •

Copy link
Copy Markdown
Collaborator

Brings TreeDist's GitHub Actions up to the model now used in Coreset, TreeTools, ConsTree and TreeSearch, and fixes gcc-ASAN. That workflow has failed on every main commit since 2026-09-11, so no sanitizer check has run in that time.

gcc-ASAN

  • It now calls ms609/actions/asan@main inside ghcr.io/r-hub/containers/gcc-asan on x86, since the image has no arm64 variant. This replaces the hand-rolled rocker/r-devel-san job, which had three stacked faults:
    • fs could not find libuv. The job set FS_USE_BUNDLED_LIBUV, but fs's configure reads USE_BUNDLED_LIBUV.
    • A stray -e 'remotes::install_local()' line had no continuation before it.
    • It ran sudo sysctl inside an unprivileged container.
  • Rogue is excluded because its hard import Rfast takes about 30 minutes to build from source under ASAN. Its vignette use is guarded.
  • TreeDistData now resolves from Additional_repositories through asan: make Additional_repositories reach the dependency install actions#6 (merged), with no pre-install needed.
  • Each leg now has its own concurrency group, so a new push cancels superseded runs.

Sanitizer results: clean. No AddressSanitizer or UBSan reports on any leg.

  • tests: FAIL 0 | SKIP 19 | PASS 1952
  • examples: all topics run
  • vignettes: all 9 articles build

One real test bug surfaced along the way and is fixed here. test-tree_distance_spr.R called TBRDist::USPRDist() unconditionally, though TBRDist is only in Suggests; CRAN's no-Suggests check would hit it too.

R-CMD-check (Coreset's wave model)

  • codemeta (PRs only): ms609/actions/update-codemeta, replacing codemeta.yml, which pushed straight to main.
  • sense-check: ubuntu-24.04-arm release, never cancelled.
  • core (Windows + codecov, R 4.1, R devel) and benchmark: run only if sense-check passes.
  • full (ubuntu-24.04 release, macOS Intel, macOS arm) and a revdepcheck matrix with one leg per dependency type: run only if core passes.
  • Per-leg concurrency groups, a timeout on every job, and apt transfer timeouts.
  • Push triggers are limited to main/master. Other branches get CI through PRs or workflow_dispatch.
  • Benchmark: measures PR, base, PR, base, using Coreset's _compare_results.R. It now installs from the PR checkout (working-directory: pr). Previously pak scanned scripts and installed CRAN TreeDist, which tripped benchmark-step's guard. DESCRIPTION gains Config/Needs/benchmark: bench, phangorn, testthat.
  • macOS, temporary: dependencies are installed without pak, because pak cannot extract CRAN's new zstd-compressed macOS binaries (Support zstd-compressed package archives: CRAN's current macOS binaries fail with "unknown archive type" r-lib/pkgdepends#485, unknown archive type error on macOS r-lib/pak#915). That step pins CRAN's own repository. P3M's macOS binaries of TreeDist 2.15.0 (sonoma-arm64 and big-sur-x86_64) are compiled with OpenMP but link neither libomp nor libR, so they fail to load (symbol not found '___kmpc_dispatch_init_4'). This is a P3M toolchain defect, not a TreeDist Makevars problem: CRAN's binaries load fine. The workaround comes from the Hoist canonical split forms out of the pairwise loop (CID/MSD/IRF/JRF 40-76% faster) #205 branch, which will drop its copy after rebasing.

Permissions and smaller refreshes

  • Every workflow now declares least-privilege permissions, addressing code scanning's "Workflow does not contain permissions". Write scopes appear only where a job writes: update-csl pushes (contents), R-CMD-check's failure notifier edits CI build failure #164 (issues), and RcppDeepState comments on PRs (pull-requests).
  • memcheck, update-csl and copilot-setup-steps run on arm, as in TreeTools.
  • pkgdown gets contents: write and replaces dev/ with redirects after a release.
  • RcppDeepState also runs on PRs and uses actions/checkout@v6.
  • codemeta.json is regenerated with the update-codemeta generator. The differences from codemetar's output are deliberate and known.

Needs the maintainer

  • The codemeta job can push a refreshed codemeta.json only once the codemeta-writer App is installed on ms609/TreeDist and CODEMETA_APP_ID (variable) and CODEMETA_APP_KEY (secret) are set. Until then, a stale file fails the job and shows the diff to commit.
  • mem-check and RcppDeepState are disabled_manually in this repository, so their edits here are unvalidated.

🤖 Generated with Claude Code

ms609-agent and others added 4 commits September 21, 2026 08:52
gcc-ASAN has failed on every main commit since 2026-09-11, dying in
dependency installation before any sanitizer run. The hand-rolled
rocker/r-devel-san job had three stacked faults: fs could not find
libuv (FS_USE_BUNDLED_LIBUV is not the variable fs's configure reads;
it wants USE_BUNDLED_LIBUV), a stray `-e 'remotes::install_local()'`
line with no preceding continuation, and `sudo sysctl` inside an
unprivileged container.

Follow TreeTools / Coreset / ConsTree / TreeSearch in delegating to
ms609/actions/asan, which installs hard deps with pak (sysreqs
resolved for the Fedora image), immediate Suggests only on the
vignettes leg, and Config/Needs/memcheck. Rogue is excluded to avoid
Rfast's ~30-min ASAN source build; its vignette use is guarded.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The action's Suggests install cannot see Additional_repositories, so
the vignettes leg failed its dependency solve on TreeDistData. Install
it from GitHub first, as ConsTree does for TreeSearch, and exclude it
from the action's own solve.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
R-CMD-check moves to Coreset's wave structure:
- codemeta (PRs only) via ms609/actions/update-codemeta, replacing the
  standalone codemeta.yml that pushed straight to main;
- sense-check on ubuntu-24.04-arm, never cancelled, as the fast signal;
- core (Windows + codecov, R 4.1, R devel) and benchmark gated on it;
- full (macOS x2, ubuntu-24.04 release) and a per-dependency-type
  revdepcheck matrix gated on core.
Expensive legs get per-leg concurrency groups and every job a timeout;
apt gets transfer timeouts so a stalled mirror retries instead of
burning six hours. Push triggers are limited to main/master (PRs and
workflow_dispatch cover branches). The scheduled-failure notifier is
shared through a YAML anchor.

The benchmark now measures both trees twice (PR, base, PR, base) and
benchmark/_compare_results.R is Coreset's, which sizes the noise band
from both replicate pairs and ignores sub-0.2 ms differences.

Smaller refreshes: memcheck, update-csl and copilot-setup-steps run on
arm (as TreeTools); pkgdown gains contents: write and replaces dev/ with
redirects after a release; RcppDeepState also runs on PRs and uses
actions/checkout@v6.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The PR-time codemeta job uses ms609/actions/update-codemeta's stdlib
Python port of write_codemeta(). Its output differs from codemetar's in
known, deliberate ways (no runtimePlatform or fileSize;
softwareRequirements as an array), so regenerate once here rather than
have the first PR flagged stale.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@ms609-agent
ms609-agent requested a review from ms609 September 21, 2026 07:58
Comment thread .github/workflows/ASan.yml Fixed
Comment thread .github/workflows/R-CMD-check.yml Fixed
Comment thread .github/workflows/R-CMD-check.yml Fixed
Comment thread .github/workflows/R-CMD-check.yml Fixed
ms609/actions branch asan-persist-repos makes the action's
Additional_repositories setting persist into its pak install, so
TreeDistData resolves from https://ms609.github.io/packages/ without a
pre-install. Pinned to that branch for validation; revert to @main once
it merges.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Comment thread .github/workflows/ASan.yml Fixed
ms609-agent and others added 4 commits September 21, 2026 09:10
CRAN's macOS binaries are now partly zstd-compressed, which pak cannot
extract ("Cannot extract ... knitr_1.52.tgz, unknown archive type";
r-lib/pkgdepends#485, r-lib/pak#915). Base R's untar() reads zstd, so
the macOS legs of the `full` wave install through install.packages() /
remotes, fail explicitly on anything missing (install.packages() only
warns), and set up pandoc, which setup-r-dependencies provides
elsewhere.

Ported from perf/hoist-canonical-splits (d2418b2, 11e9893), green on
both macOS legs there, so the workflow has a single owner and that
branch can drop its CI commits.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The benchmark job installs `needs: benchmark` from the PR checkout.
TreeDist declared no such field, so bench was never installed ("there
is no package called 'bench'"). The job only worked before because it
ran setup-r-dependencies from a root with no DESCRIPTION, where pak
scans scripts instead, which also pulled in CRAN TreeDist and tripped
benchmark-step's installed-package guard. List what benchmark/ loads,
as TreeTools does.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The test's expect_exact() helper called TBRDist::USPRDist()
unconditionally, though TBRDist is only in Suggests. Surfaced by the
gcc-ASAN tests leg, which installs hard dependencies only
("there is no package called 'TBRDist'"); CRAN's no-Suggests check
would hit it too. The helper, and the expect_failure() wrapped around
it, now run only when TBRDist is available, so the fixed-value
.SPRRogue() expectations in the same test still run everywhere.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Addresses code scanning's "Workflow does not contain permissions" on
every workflow that lacked a block. Read-only (contents: read) for
gcc-ASAN, mem-check, R-hub, rev-dep-check and wasm-build. Write scopes
only where a job writes:
- update-csl pushes the refreshed CSL file (contents: write);
- R-CMD-check's scheduled-failure notifier comments on and reopens
  issue #164 (issues: write); codemeta and benchmark keep their
  job-level blocks, which override this;
- RcppDeepState posts its results to the PR (pull-requests: write).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@github-actions

This comment has been minimized.

@codecov

codecov Bot commented Sep 21, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 95.55%. Comparing base (fb0039e) to head (178ebfc).

Additional details and impacted files
@@           Coverage Diff           @@
##             main     #206   +/-   ##
=======================================
  Coverage   95.55%   95.55%           
=======================================
  Files          56       56           
  Lines        5041     5041           
=======================================
  Hits         4817     4817           
  Misses        224      224           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

ms609-agent and others added 2 commits September 21, 2026 09:52
Both macOS legs of the full wave failed to install TreeDistData: the
TreeDist it depends on came from P3M
(packagemanager.posit.co/cran/latest, sonoma-arm64 and big-sur-x86_64
TreeDist_2.15.0.tgz), whose binary references libomp's __kmpc_*
symbols without linking libomp, so dyn.load() fails with "symbol not
found in flat namespace '___kmpc_dispatch_init_4'". The same step
passed on perf/hoist-canonical-splits, where install.packages() drew
TreeDist from CRAN's own binaries. Set the repos explicitly rather than
inheriting whichever setup-r chose.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
ms609/actions#6 (Additional_repositories now reach the dependency
install) is merged, so drop the validation pin. Validated on run
35575870744: TreeDistData resolved from the ms609 repo and all nine
articles built under ASan/UBSan with no reports.

Each leg runs for up to an hour, and on pull requests every push
re-triggers all three. Per-leg concurrency cancels the stale runs.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@github-actions

This comment has been minimized.

@github-actions

Copy link
Copy Markdown

Performance benchmark results

Call Status Change Time (ms)
ClusteringInfoDistance(tr200) ⚪ NSD -1.83% 14.9, 15 →
15.2, 15.2
ClusteringInfoDistance(tr50) ⚪ NSD -2.77% 11.5, 11.4 →
11.8, 11.5
LAPJV(test2000) ⚪ NSD -0.29% 95, 95.5 →
97.4, 93.3
LAPJV(test40) ⚪ NSD 3.79% 0.0185, 0.0185 →
0.0178, 0.0178
LAPJV(test400) ⚪ NSD 0.05% 3.21, 3.2 →
3.21, 3.21
MutualClusteringInfo(tr200) ⚪ NSD -0.36% 21.8, 22.1 →
21.8, 22
MutualClusteringInfo(tr50) ⚪ NSD -0.94% 23.1, 23.5 →
23.8, 23.2
PathDist(postTrees) ⚪ NSD -0.64% 3.34, 3.5 →
3.38, 3.45
PhylogeneticInfoDistance(tr200) ⚪ NSD 0.38% 231, 231 →
230, 230
PhylogeneticInfoDistance(tr50) ⚪ NSD 0.11% 81.1, 81.9 →
81.6, 81.7
RobinsonFoulds(tr200) ⚪ NSD -0.38% 2.9, 2.9 →
2.9, 2.92
RobinsonFoulds(tr200) ⚪ NSD -0.04% 2.74, 2.75 →
2.74, 2.77
RobinsonFoulds(tr50) ⚪ NSD 0.23% 4.53, 4.57 →
4.57, 4.53

@ms609
ms609 marked this pull request as ready for review September 21, 2026 09:42
@ms609-agent
ms609-agent merged commit 4ef39fc into main Sep 21, 2026
24 of 25 checks passed
@ms609
ms609 deleted the ci/modernise-workflows branch September 21, 2026 10:17
ms609 pushed a commit that referenced this pull request Sep 21, 2026
Both jobs had `needs: core` and no `if:`, so they took the implicit
success(), which is false whenever any job upstream was skipped, even
transitively. codemeta runs only on pull_request, so on push to main,
the weekly schedule and workflow_dispatch the macOS / ubuntu-release
backstop and every revdepcheck leg were skipped, though core passed.
First seen on the #206 merge commit (4ef39fc).

Gate on core's result explicitly, as core itself does on sense-check.

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants