Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 81 additions & 0 deletions .github/workflows/CheckCompatBounds.yml
Original file line number Diff line number Diff line change
@@ -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 }}"
51 changes: 0 additions & 51 deletions .github/workflows/Tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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 }}"
120 changes: 73 additions & 47 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 <workspace-root>
```

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 |
Expand All @@ -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

Expand Down Expand Up @@ -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 <workspace-root>
```

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
Expand Down