Skip to content

Latest commit

 

History

History
112 lines (79 loc) · 8.04 KB

File metadata and controls

112 lines (79 loc) · 8.04 KB

Poisson Consulting package CI system

Centrally-managed, parameterized GitHub Actions for the org's R packages. CI logic lives in reusable workflows here in poissonconsulting/.github; each package carries thin caller workflows that pass its classification. Update a reusable workflow and every package inherits it on the next run.

Components

Reusable workflows (.github/workflows/, workflow_call; callers must use secrets: inherit):

Workflow Inputs Purpose
R-CMD-check.yaml tier, jags, cmdstan, tex, private R CMD check; the tier selects the OS/R matrix and error_on.
test-coverage.yaml cmdstan, tex, private covr + Codecov.
pkgdown.yaml cmdstan, private Build + deploy the docs site to gh-pages.
check-no-suggests.yaml private R CMD check with hard dependencies only (active CRAN packages).

R-hub (workflow-templates/rhub.yaml) is dispatch-triggered and r-hub-owned, so it is vendored into a package as a template rather than invoked as a reusable caller. Active CRAN packages only.

Each package's .github/workflows/ holds matching thin callers (generated by the sync tool), plus the fledge callers (fledge-bump.yaml, fledge-tag-on-merge.yaml) and any bespoke workflows (paper.yaml, slack-check-package.yaml). The sync tool preserves the bespoke workflows and migrates fledge callers to the current .yaml templates (a stale .yml fledge caller is replaced, not preserved). Callers run on pushes to main/master and on pull requests targeting main, master, or dev (pkgdown builds but does not deploy on pull requests).

Tooling:

  • tools/package-tiers.tsv — the tier registry (source of truth for tier).
  • tools/excluded-repos.sh — shared exclude registry (sandboxes/templates), sourced by sync-ci.sh, rollout-fledge-automation.sh, and set-fledge-branch-protection.sh.
  • tools/sync-ci.sh — renders callers from the registry + auto-detection and opens routed PRs.

Classification

Per package, the sync tool resolves:

  • tier: registry entry, else active-on-CRAN -> cran, else unimportant (default).
  • private: from repo visibility -> selects GITHUB_PAT (PRIVATE_ACTIONS_PAT for private repos so private dependencies install; GITHUB_TOKEN otherwise).
  • jags: from DESCRIPTION (rjags|runjags|jagsUI|R2jags, a tidy one-per-line jmbr dependency entry, or a JAGS SystemRequirements) -> adds the macOS/Windows JAGS installs (Linux gets JAGS via setup-r-dependencies system requirements).
  • cmdstan: from DESCRIPTION (a tidy one-per-line cmdstanr or smbr2 dependency entry, or a CmdStan SystemRequirements) -> installs the CmdStan toolchain in the check, coverage, and pkgdown builds.
  • tex: from repo contents (a .Rnw vignette, or an .Rmd/R source targeting a LaTeX output) -> installs TinyTeX.
  • cran: active on CRAN -> also gets the check-no-suggests caller and the vendored rhub.yaml, independent of tier.

Only tier is hand-maintained, and only to promote a non-CRAN package to important (or force a tier). private, jags, cmdstan, tex, and CRAN membership are auto-detected at sync time and never listed in the registry.

CRAN membership

CRAN membership is detected against the src/contrib/PACKAGES index, which lists only currently published packages. Archived packages (removed from CRAN) are therefore not treated as CRAN and resolve to unimportant unless the registry pins them. The per-package web/packages/<pkg>/index.html page is not used for detection because it persists for archived packages.

Tier matrices (set inside R-CMD-check.yaml from the tier input)

tier matrix error_on extra
cran macOS-release, Windows-release, Ubuntu-{devel,release,oldrel-1} warning + check-no-suggests + rhub
important macOS-release, Windows-release, Ubuntu-release, Ubuntu-oldrel-1 warning
unimportant Ubuntu-release error

Registry

tools/package-tiers.tsv, one <package> <tier> per line (# comments). List only packages to promote to important or to force a tier; everything else defaults to unimportant, and active CRAN packages auto-resolve to cran.

Sync tool

tools/sync-ci.sh                    # dry run: classify every package + planned action
tools/sync-ci.sh --apply            # render callers + open routed PRs
tools/sync-ci.sh --apply pkgA pkgB  # restrict to named packages (piloting)
tools/sync-ci.sh --close-old        # close the prior f-standardize-actions PRs/issues/branches
ENGINE_REF=branch tools/sync-ci.sh --apply pkgA   # pin callers to a branch instead of @v1

Routing follows the CODEOWNER: a normal PR when Joe owns the repo, otherwise an issue plus a PR assigned to the owner with review requested. The tool is dry-run by default, throttled, and isolates per-repo failures so one transient does not abort the batch. On --apply, if the CI system already has an open PR for a repo (its f-ci branch), it closes that PR (and its linked tracking issue) and opens a fresh one, so a re-run always reflects the current classification.

Note: a very high burst of API calls can trip GitHub's secondary rate limiter, which makes a dry run under-report (packages drop based on the throttle window). It clears within minutes; re-run and it converges.

Important-tier candidate gate

A package whose deployed R-CMD-check caller says tier: important, but which is neither in the registry nor active on CRAN, would otherwise be silently downgraded to unimportant on the next sync. Before any rollout, a pre-flight surfaces these candidates:

  • dry run lists them (CANDIDATE <pkg> (deployed=important, computed=unimportant)), no prompt and no change.
  • --apply with a terminal (TTY) asks per candidate whether to add it to the registry: answering yes appends <pkg> important to the local tools/package-tiers.tsv (kept important for this run) and answering no downgrades it.
  • --apply without a TTY (CI, pipes, the Claude Code ! prefix, agent tools) skips candidates (no PR) so a batch run can never silently downgrade a manually promoted package.

The prompt only appears in an interactive terminal, so run tools/sync-ci.sh --apply <pkg> from a real shell to answer it. When you keep a candidate important, commit the one-line tools/package-tiers.tsv change and open a PR to .github so the registry matches; otherwise the next sync re-flags it.

Common tasks

  • Promote a package to important: add <pkg> important to tools/package-tiers.tsv, then tools/sync-ci.sh --apply <pkg>.
  • Roll out a reusable-workflow change: merge it into main, move the v1 tag forward (git tag -f v1 && git push -f origin v1), and the change propagates to every package on its next run.
  • Re-sync a package after a classification change (e.g. CRAN archival): tools/sync-ci.sh --apply <pkg>; any open f-ci PR is closed and replaced automatically.
  • Add CI to a new package: tools/sync-ci.sh --apply <pkg>; the package must have a DESCRIPTION and (for the full sweep) a fledge-managed NEWS.md.

The one-time go-live sequence and rollout status are recorded in GO-LIVE.md and CI-ROLLOUT-STATUS.md; fledge version-bump automation is documented in fledge-automation.md.

Prerequisites

  • gh authenticated (with workflow scope for --apply), git (SSH), and curl.
  • PRIVATE_ACTIONS_PAT, CODECOV_TOKEN, and GOOGLE_MAPS_ELEVATION_API_KEY org secrets available to the package repos (the last is passed into the check and coverage environments for packages whose tests call the elevation API).
  • Callers pin the reusable workflows at @v1; keep the v1 tag pointing at the current .github main.

Notes

  • Moving v1 also moves the fledge callers' pin, but the fledge reusable workflows are unchanged, so they keep working.
  • A genuine package failure (e.g. tests needing live API credentials) stays red regardless of tier; that is a real bug to fix in the package, not a CI issue.
  • The reusable-workflow matrix is built with fromJSON(needs.matrix.outputs.config), a standard supported pattern.