diff --git a/.github/workflows/sublibrary-tests.yml b/.github/workflows/sublibrary-tests.yml deleted file mode 100644 index a1aca87..0000000 --- a/.github/workflows/sublibrary-tests.yml +++ /dev/null @@ -1,126 +0,0 @@ -name: "Reusable Sublibrary CI Workflow" - -# Runs the test suite of each sublibrary under lib/* that is affected by the -# changes in a push/PR, using the shared dependency-graph change detection in -# SciML/.github. Per-sublibrary test config (groups, versions, runner, timeout, -# threads) is read from lib//test/test_groups.toml; see -# scripts/compute_affected_sublibraries.jl for the format and defaults. - -on: - workflow_call: - inputs: - dotgithub-ref: - description: "Ref of SciML/.github to source the affected-sublibrary detection script from" - default: "v1" - required: false - type: string - -jobs: - detect-changes: - runs-on: ubuntu-latest - outputs: - # JSON array of {group, version, runner, timeout, num_threads} objects for matrix include - matrix: ${{ steps.compute.outputs.matrix }} - has_changes: ${{ steps.compute.outputs.has_changes }} - steps: - - uses: actions/checkout@v6 - with: - fetch-depth: 0 - - name: "Checkout SciML/.github for the detection script" - uses: actions/checkout@v6 - with: - repository: SciML/.github - ref: "${{ inputs.dotgithub-ref }}" - path: .sciml-dotgithub - - uses: julia-actions/setup-julia@v3 - with: - version: '1' - - name: "Compute affected sublibraries from dependency graph" - id: compute - run: | - if [ "${{ github.event_name }}" = "push" ]; then - CHANGED=$(git diff --name-only ${{ github.event.before }} ${{ github.sha }} 2>/dev/null || git diff --name-only HEAD~1 HEAD) - else - git fetch origin ${{ github.event.pull_request.base.ref }} - CHANGED=$(git diff --name-only origin/${{ github.event.pull_request.base.ref }}...HEAD) - fi - - MATRIX=$(echo "$CHANGED" | julia .sciml-dotgithub/scripts/compute_affected_sublibraries.jl .) - - echo "Changed files in lib/:" - echo "$CHANGED" | grep "^lib/" || echo "(none)" - echo "" - echo "Matrix entries: $MATRIX" - - echo "matrix=$MATRIX" >> "$GITHUB_OUTPUT" - if [ "$MATRIX" = "[]" ]; then - echo "has_changes=false" >> "$GITHUB_OUTPUT" - else - echo "has_changes=true" >> "$GITHUB_OUTPUT" - fi - - test: - needs: detect-changes - if: needs.detect-changes.outputs.has_changes == 'true' - permissions: - actions: write - contents: read - runs-on: ${{ matrix.runner }} - timeout-minutes: ${{ matrix.timeout }} - strategy: - fail-fast: false - matrix: - include: ${{ fromJson(needs.detect-changes.outputs.matrix) }} - env: - # Pin the depot so the registry refresh below and the subsequent - # julia-actions steps all read/write the same depot on self-hosted - # runners (which may otherwise inject a per-runner depot for some steps - # but not others, hiding the freshly-added General registry from later - # resolves -> "expected package X to be registered" failures). - JULIA_DEPOT_PATH: ~/.julia - steps: - - uses: actions/checkout@v6 - - uses: julia-actions/setup-julia@v3 - with: - version: ${{ matrix.version }} - # Only write the cache from master pushes to avoid the Azure SAS auth - # failure storm during PR matrix uploads. The dynamic matrix shape makes - # a restore-only PR key impractical, so PRs skip the cache; this workflow - # only fires on lib/ changes so the lost PR cache hit is small. - - name: "Cache Julia depot (push only)" - if: github.event_name == 'push' - uses: julia-actions/cache@v3 - continue-on-error: true - with: - cache-compiled: 'false' - - name: "Develop local path deps (Julia < 1.11)" - shell: julia --color=yes --project=. {0} - run: | - using Pkg - if VERSION < v"1.11.0-DEV.0" - toml = Pkg.TOML.parsefile("Project.toml") - if haskey(toml, "sources") - specs = Pkg.PackageSpec[] - for (dep, spec) in toml["sources"] - if spec isa Dict && haskey(spec, "path") && isdir(spec["path"]) - @info "Developing" dep spec["path"] - push!(specs, Pkg.PackageSpec(path=spec["path"])) - end - end - isempty(specs) || Pkg.develop(specs) - end - end - - uses: julia-actions/julia-buildpkg@v1 - - uses: julia-actions/julia-runtest@v1 - with: - coverage: false - check_bounds: auto - env: - GROUP: ${{ matrix.group }} - JULIA_NUM_THREADS: ${{ matrix.num_threads }} - - uses: julia-actions/julia-processcoverage@v1 - - uses: codecov/codecov-action@v6 - with: - token: ${{ secrets.CODECOV_TOKEN }} - files: lcov.info - disable_safe_directory: true diff --git a/README.md b/README.md index 37a3d31..5770577 100644 --- a/README.md +++ b/README.md @@ -28,11 +28,10 @@ Two things live here: [`spellcheck.yml`](#spellcheckyml) · [`benchmark.yml`](#benchmarkyml) · [`major-version-tag.yml`](#major-version-tagyml) - [Monorepos: sublibrary CI](#monorepos-sublibrary-ci) - - [Two execution models](#two-execution-models) + - [How sublibrary tests run](#how-sublibrary-tests-run) - [`test_groups.toml`](#test_groupstoml) - [Dependency-graph change detection](#dependency-graph-change-detection) - - [`sublibrary-tests.yml` (GROUP-dispatch)](#sublibrary-testsyml-group-dispatch) - - [`sublibrary-project-tests.yml` (project model)](#sublibrary-project-testsyml-project-model) + - [`sublibrary-project-tests.yml`](#sublibrary-project-testsyml) - [`sublibrary-downgrade.yml`](#sublibrary-downgradeyml) - [Recommended repository setup](#recommended-repository-setup) - [Secrets](#secrets) @@ -319,22 +318,15 @@ its own `Project.toml` and `test/runtests.jl` (e.g. OrdinaryDiffEq, ModelingToolkit, Optimization, NonlinearSolve). Sublibrary CI runs each sublibrary's tests, and — crucially — only the ones a change actually affects. -### Two execution models +### How sublibrary tests run -Both compute the **affected** sublibraries the same way (see -[change detection](#dependency-graph-change-detection)); they differ in *how* a -sublibrary's tests are executed: - -| | `sublibrary-project-tests.yml` (project model) | `sublibrary-tests.yml` (GROUP-dispatch) | -|---|---|---| -| How a sublib runs | `tests.yml` with `project: lib/X` (runs `lib/X/test/runtests.jl` directly) | Root `test/runtests.jl` with `GROUP=lib-name`, which activates `lib/X` and runs it | -| Needs a root dispatcher? | **No** | **Yes** — root `runtests.jl` must map `GROUP` → activate `lib/` | -| Per-group versions / runners / timeouts | Yes (`test_groups.toml`) | Yes (`test_groups.toml`) | -| Best for | Most monorepos; sublibs with self-contained `test/runtests.jl` | Repos whose root `runtests.jl` already does sophisticated cross-cutting dispatch | - -**Most repos want `sublibrary-project-tests.yml`.** It needs no per-repo root -dispatcher, because `tests.yml` transitively develops the sublibrary's in-repo -`[sources]`. +`sublibrary-project-tests.yml` computes the **affected** sublibraries (see +[change detection](#dependency-graph-change-detection)) and runs each via +`tests.yml` with `project: lib/X` — i.e. `lib/X/test/runtests.jl` directly, +with the test group passed through `group-env-name`. It needs no per-repo root +`runtests.jl` dispatcher, because `tests.yml` transitively develops the +sublibrary's in-repo `[sources]`. Per-sublibrary versions / runners / timeouts +come from each sublib's `test_groups.toml` (below). ### `test_groups.toml` @@ -394,31 +386,14 @@ the changed files: - Changes confined to a sublibrary's `test/` don't propagate to dependents. - Changes outside `lib/` select nothing (the root suite is covered by `CI.yml`). -The script has three output modes: +The script's output modes: | Invocation | Output | Used by | |---|---|---| -| `… ` | `[{group, version, runner, timeout, num_threads}, …]` | `sublibrary-tests.yml` | | `… --projects-matrix` | `[{project, group, version, runner, timeout, num_threads}, …]` | `sublibrary-project-tests.yml` | | `… --projects` | `["lib/A", "lib/B", …]` | simple path listing | -### `sublibrary-tests.yml` (GROUP-dispatch) - -Thin caller; the model is driven by the repo's root `runtests.jl` + each -sublibrary's `test_groups.toml`. - -| Input | Type | Default | Description | -|---|---|---|---| -| `dotgithub-ref` | string | `"v1"` | Ref of `SciML/.github` to source the detection script from. | - -```yaml -jobs: - sublibrary-ci: - uses: "SciML/.github/.github/workflows/sublibrary-tests.yml@v1" - secrets: "inherit" -``` - -### `sublibrary-project-tests.yml` (project model) +### `sublibrary-project-tests.yml` Lists the affected `lib/*` (with change detection) and runs each via `tests.yml` `project: lib/X`, expanding `test_groups.toml`. No root dispatcher