From e9b79ca457d04e62b2ca3ff35d1309309a47a4d4 Mon Sep 17 00:00:00 2001 From: mtfishman Date: Wed, 22 Apr 2026 12:56:20 -0400 Subject: [PATCH] CheckCompatBounds: extract compat-bounds check into its own workflow Move the compat-bounds check out of Tests.yml into a new reusable workflow CheckCompatBounds.yml. The check no longer runs once per Tests-matrix cell; instead callers invoke CheckCompatBounds.yml as a separate, unmatrixed workflow and get a single clean status per PR. - Add .github/workflows/CheckCompatBounds.yml (reusable workflow). - Remove the `check-compat-bounds` job and its two inputs (`check-compat-bounds`, `check-compat-bounds-mode`) from Tests.yml. A search across ITensor-org callers found no workflows that set either input, so this is a safe removal. - Rework the README: drop the "Compat upper-bound check" subsection under Tests, and add a new top-level "Check Compat Bounds" section documenting the new workflow and its inputs. Rolling out to callers (new per-repo workflow + ITensorPkgSkeleton template) will follow via ITensorOrgPatches. --- .github/workflows/CheckCompatBounds.yml | 81 ++++++++++++++++ .github/workflows/Tests.yml | 51 ---------- README.md | 120 ++++++++++++++---------- 3 files changed, 154 insertions(+), 98 deletions(-) create mode 100644 .github/workflows/CheckCompatBounds.yml diff --git a/.github/workflows/CheckCompatBounds.yml b/.github/workflows/CheckCompatBounds.yml new file mode 100644 index 0000000..f2207ab --- /dev/null +++ b/.github/workflows/CheckCompatBounds.yml @@ -0,0 +1,81 @@ +name: "Reusable Check Compat Bounds Workflow" + +on: + workflow_call: + inputs: + julia-version: + description: "Julia version used to instantiate the workspace and run the check." + default: "1" + required: false + type: string + project: + description: "The value is passed to Julia's `--project` flag during buildpkg." + default: '@.' + required: false + type: string + cache: + description: "Use the julia-actions/cache action for caching." + default: true + required: false + type: boolean + buildpkg: + description: "Use the julia-actions/julia-buildpkg action to instantiate before the check." + default: true + required: false + type: boolean + localregistry: + description: "Add local registries hosted on GitHub. Specified by providing the url (https/ssh) to the repositories as a newline (\n) separated list." + default: "" + required: false + type: string + timeout-minutes: + description: "The maximum time in minutes that the job can run." + default: 30 + required: false + type: number + run-on-draft: + description: "When true, run the check even on draft PRs." + default: false + required: false + type: boolean + mode: + description: "When to run the check: 'always' (every invocation), 'never' (skip), or 'auto' (run only when the PR author is CompatHelper or Dependabot). Matches julia-actions/julia-runtest's 'force_latest_compatible_version: auto' semantics." + default: "always" + required: false + type: string + workspace-root: + description: "Path to the workspace root (containing Project.toml and Manifest.toml)." + default: "." + required: false + type: string + +jobs: + check-compat-bounds: + name: "Check compat bounds" + if: "${{ !github.event.pull_request.draft || inputs.run-on-draft }}" + runs-on: "ubuntu-latest" + timeout-minutes: ${{ inputs.timeout-minutes }} + steps: + - uses: actions/checkout@v4 + + - name: "Setup Julia ${{ inputs.julia-version }}" + uses: julia-actions/setup-julia@v2 + with: + version: "${{ inputs.julia-version }}" + + - uses: julia-actions/cache@v2 + if: "${{ inputs.cache }}" + with: + token: "${{ secrets.GITHUB_TOKEN }}" + + - uses: julia-actions/julia-buildpkg@v1 + if: "${{ inputs.buildpkg }}" + with: + localregistry: "${{ inputs.localregistry }}" + project: "${{ inputs.project }}" + + - name: "Check compat upper bounds" + uses: ITensor/ITensorActions/.github/actions/check-compat-bounds@main + with: + workspace-root: "${{ inputs.workspace-root }}" + mode: "${{ inputs.mode }}" diff --git a/.github/workflows/Tests.yml b/.github/workflows/Tests.yml index 2587a2d..b7674a8 100644 --- a/.github/workflows/Tests.yml +++ b/.github/workflows/Tests.yml @@ -101,16 +101,6 @@ on: default: "" required: false type: string - check-compat-bounds: - description: "After instantiating, fail if any workspace compat entry is resolved to a version below its compat upper bound (indicates a transitive dependency is holding the workspace back from its declared bound)." - default: true - required: false - type: boolean - check-compat-bounds-mode: - description: "When to run the compat-bounds check: 'always' (every invocation), 'never' (skip), or 'auto' (run only when the PR author is CompatHelper or Dependabot). Matches julia-actions/julia-runtest's 'force_latest_compatible_version: auto' semantics." - default: "always" - required: false - type: string secrets: CODECOV_TOKEN: required: true @@ -186,44 +176,3 @@ jobs: files: lcov.info token: "${{ secrets.CODECOV_TOKEN }}" fail_ci_if_error: false - - check-compat-bounds: - name: "Check compat bounds" - # Runs in parallel with `tests` so a compat-bound failure does not prevent - # the test matrix from executing. The caller's gate job (which `needs:` the - # reusable-workflow call) still aggregates both jobs, so a failure here - # blocks auto-merge. - # - # The check is platform-independent, so when the caller invokes this - # reusable workflow via a matrix (typical), we only run it on the canonical - # (ubuntu-latest, julia=1) cell to avoid running it N times. - if: >- - inputs.check-compat-bounds - && inputs.os == 'ubuntu-latest' - && inputs.julia-version == '1' - && (!github.event.pull_request.draft || inputs.run-all-on-draft) - runs-on: "ubuntu-latest" - timeout-minutes: ${{ inputs.timeout-minutes }} - steps: - - uses: actions/checkout@v4 - - - name: "Setup Julia" - uses: julia-actions/setup-julia@v2 - with: - version: "1" - - - uses: julia-actions/cache@v2 - if: "${{ inputs.cache }}" - with: - token: "${{ secrets.GITHUB_TOKEN }}" - - - uses: julia-actions/julia-buildpkg@v1 - if: "${{ inputs.buildpkg }}" - with: - localregistry: "${{ inputs.localregistry }}" - - - name: "Check compat upper bounds" - uses: ITensor/ITensorActions/.github/actions/check-compat-bounds@main - with: - workspace-root: "." - mode: "${{ inputs.check-compat-bounds-mode }}" diff --git a/README.md b/README.md index 31ca674..aab7835 100644 --- a/README.md +++ b/README.md @@ -99,51 +99,6 @@ the full matrix even on draft PRs, set it to `true`: # ... ``` -### Compat upper-bound check - -After `julia-actions/julia-buildpkg` instantiates the package, the Tests -workflow inspects the resolved `Manifest.toml` and fails if any workspace -compat entry is resolved to a version below its compat upper bound. This -flags the situation where a transitive dependency is holding the workspace -back from a compat upper bound the maintainer believes is being tested — -for example, a CompatHelper PR that bumps `[compat]` to a newer version -but the resolver cannot actually pick that version because another -dependency constrains it. - -The check is enabled by default and walks the root `Project.toml` plus -every path listed in `[workspace].projects`. Standard library packages, -unregistered `[sources]` dependencies, and `[extras]`-only entries not in -the manifest are skipped. - -| Input | Default | Description | -|---|---|---| -| `check-compat-bounds` | `true` | Enable or disable the check entirely. | -| `check-compat-bounds-mode` | `"always"` | `"always"` runs on every invocation. `"never"` skips the check. `"auto"` runs only when `$GITHUB_ACTOR` is a known dependency-update bot (`github-actions[bot]`, `dependabot[bot]`). | - -Example — restrict the check to CompatHelper/Dependabot PRs only: - -```yaml - uses: "ITensor/ITensorActions/.github/workflows/Tests.yml@main" - with: - check-compat-bounds-mode: auto -``` - -#### Using the check outside GitHub Actions - -The underlying script is a standalone Julia script; it can be invoked from -Jenkins or any other CI after the workspace is instantiated: - -```bash -curl -sSL https://raw.githubusercontent.com/ITensor/ITensorActions/main/.github/actions/check-compat-bounds/check_compat_bounds.jl \ - -o check_compat_bounds.jl -julia --color=yes check_compat_bounds.jl -``` - -Exit code `0` means every workspace compat entry is resolved to its maximum -allowed version; exit code `1` means at least one entry is outdated, with a -per-entry message identifying the package, resolved version, and allowed -ceiling. - ### Inputs | Input | Type | Default | Description | @@ -168,8 +123,6 @@ ceiling. | `test-prefix` | string | `""` | Prefix inserted in front of the `julia` invocation that runs the tests. Example: `xvfb-run -a -s "-screen 0 1024x768x24" ` for GUI-dependent tests. | | `extra-env` | string | `""` | Multi-line `KEY=VALUE` pairs exported into the job's environment (via `$GITHUB_ENV`) before the test step. | | `upload-artifacts-path` | string | `""` | When set, uploads the given file or directory as a per-matrix-cell artifact after tests run (on success or failure). | -| `check-compat-bounds` | bool | `true` | Enable or disable the compat upper-bound check (see above). | -| `check-compat-bounds-mode` | string | `"always"` | Mode of the compat upper-bound check: `"always"`, `"never"`, or `"auto"` (bots only). | ### Secrets @@ -555,6 +508,79 @@ jobs: The check is automatically skipped on PRs classified as non-substantive (changes limited to `.github/**`, `.pre-commit-config.yaml`, `.gitignore`, or `LICENSE`); those PRs pass without requiring a version bump. +## Check Compat Bounds + +The `CheckCompatBounds` workflow instantiates the package and fails if any +workspace compat entry is resolved to a version below its compat upper +bound. This flags the situation where a transitive dependency is holding +the workspace back from a compat upper bound the maintainer believes is +being tested — for example, a CompatHelper PR that bumps `[compat]` to a +newer version but the resolver cannot actually pick that version because +another dependency constrains it. + +The check walks the root `Project.toml` plus every path listed in +`[workspace].projects`. Standard library packages, unregistered +`[sources]` dependencies, and `[extras]`-only entries not in the +manifest are skipped. A compat entry referring to a workspace project's +own package is checked against the workspace version, not only the +registry, so a PR bumping the root `version` does not spuriously fail +because the new version is not yet registered. + +The workflow runs once per PR on `ubuntu-latest` and produces its own +status check, independent of the `Tests` workflow. + +```yaml +name: "Check Compat Bounds" + +on: + pull_request: + +jobs: + check-compat-bounds: + name: "Check Compat Bounds" + uses: "ITensor/ITensorActions/.github/workflows/CheckCompatBounds.yml@main" + with: + localregistry: https://github.com/ITensor/ITensorRegistry.git +``` + +### Inputs + +| Input | Type | Default | Description | +|---|---|---|---| +| `julia-version` | string | `"1"` | Julia version passed to `julia-actions/setup-julia`. | +| `project` | string | `"@."` | Value passed to Julia's `--project` flag during `julia-actions/julia-buildpkg`. | +| `cache` | bool | `true` | Use `julia-actions/cache`. | +| `buildpkg` | bool | `true` | Run `julia-actions/julia-buildpkg` before the check. Disable only if the workspace is instantiated some other way. | +| `localregistry` | string | `""` | Newline-separated list of extra registry URLs to add before resolving (forwarded to `julia-actions/julia-buildpkg`). | +| `timeout-minutes` | number | `30` | Maximum job runtime. | +| `run-on-draft` | bool | `false` | Run the check on draft PRs. | +| `mode` | string | `"always"` | `"always"` runs on every invocation. `"never"` skips the check. `"auto"` runs only when `$GITHUB_ACTOR` is a known dependency-update bot (`github-actions[bot]`, `dependabot[bot]`). | +| `workspace-root` | string | `"."` | Path to the workspace root (containing `Project.toml` and `Manifest.toml`). | + +Example — restrict the check to CompatHelper/Dependabot PRs only: + +```yaml + uses: "ITensor/ITensorActions/.github/workflows/CheckCompatBounds.yml@main" + with: + mode: auto +``` + +### Using the check outside GitHub Actions + +The underlying script is a standalone Julia script; it can be invoked from +Jenkins or any other CI after the workspace is instantiated: + +```bash +curl -sSL https://raw.githubusercontent.com/ITensor/ITensorActions/main/.github/actions/check-compat-bounds/check_compat_bounds.jl \ + -o check_compat_bounds.jl +julia --color=yes check_compat_bounds.jl +``` + +Exit code `0` means every workspace compat entry is resolved to its maximum +allowed version; exit code `1` means at least one entry is outdated, with a +per-entry message identifying the package, resolved version, and allowed +ceiling. + ## Registrator The Registrator workflow registers a new package version whenever the version in