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
3 changes: 2 additions & 1 deletion .github/workflows/claude-code-review.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ jobs:
contains(github.event.comment.body, '@claude review')

runs-on: ubuntu-latest
timeout-minutes: 60
permissions:
contents: read
pull-requests: read
Expand All @@ -21,7 +22,7 @@ jobs:

steps:
- name: Checkout repository
uses: actions/checkout@v4
uses: actions/checkout@v6
with:
fetch-depth: 1

Expand Down
3 changes: 2 additions & 1 deletion .github/workflows/claude.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ jobs:
(github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude') && !contains(github.event.review.body, '@claude review')) ||
(github.event_name == 'issues' && (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude')))
runs-on: ubuntu-latest
timeout-minutes: 60
permissions:
contents: read
pull-requests: read
Expand All @@ -26,7 +27,7 @@ jobs:
actions: read # Required for Claude to read CI results on PRs
steps:
- name: Checkout repository
uses: actions/checkout@v4
uses: actions/checkout@v6
with:
fetch-depth: 1

Expand Down
13 changes: 7 additions & 6 deletions .github/workflows/copilot-setup-steps.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,36 +6,37 @@ on:
workflow_dispatch:
push:
paths:
- .github/workflows/copilot-setup-steps.yml
- .github/workflows/copilot-setup-steps.yaml
pull_request:
paths:
- . github/workflows/copilot-setup-steps.yml
- .github/workflows/copilot-setup-steps.yaml

jobs:
# The job MUST be called `copilot-setup-steps` or it will not be picked up by Copilot
copilot-setup-steps:
runs-on: ubuntu-latest
timeout-minutes: 30

# Set the permissions to the lowest permissions possible needed for your steps
permissions:
contents: read

steps:
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@v6

- name: Set up Julia
uses: julia-actions/setup-julia@v2
with:
version: '1.11'
version: '1.11'

- name: Cache Julia packages
uses: julia-actions/cache@v2
uses: julia-actions/cache@v3
with:
cache-name: julia-cache
cache-packages: true
cache-artifacts: true
cache-registries: true

- name: Instantiate Julia environment
- name: Instantiate Julia environment
run: julia --project="." -e "using Pkg; Pkg.instantiate()"
65 changes: 65 additions & 0 deletions .github/workflows/format.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
name: Format and Hygiene

# Runs the repository's pre-commit suite (JuliaFormatter + file hygiene) so that
# contributors who have not run `pre-commit install` locally are still caught.
#
# DISABLED as a pull request gate for now: the repository has pre-existing
# formatting drift that has to be cleaned up first. Until then, run this
# manually from the Actions tab ("Run workflow") to see the current damage.
#
# To enable it as a gate, uncomment the `pull_request` trigger below. If the
# test suite's `Tests` job is a required status check, add `pre-commit` too.
on:
workflow_dispatch:
# pull_request:
# branches:
# - main
# - develop

permissions:
contents: read

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
pre-commit:
name: pre-commit
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- name: Checkout repository
uses: actions/checkout@v6

- name: Set up Python
uses: actions/setup-python@v5
with:
# Matches default_language_version in .pre-commit-config.yaml
python-version: '3.10'

- name: Set up Julia
uses: julia-actions/setup-julia@v2
with:
version: '1.11'

# The julia-formatter hook is `language: system`: it shells out to
# `julia -e 'import JuliaFormatter: format; format(ARGS)'` and therefore
# uses whatever JuliaFormatter lives in the default depot environment.
# Pin it to the same version .pre-commit-config.yaml pins the hook repo
# to, otherwise CI and local pre-commit runs disagree on formatting.
- name: Install JuliaFormatter
run: julia -e 'using Pkg; Pkg.add(PackageSpec(name="JuliaFormatter", version="1.0.62"))'

- name: Cache pre-commit environments
uses: actions/cache@v4
with:
path: ~/.cache/pre-commit
key: pre-commit-${{ runner.os }}-py3.10-${{ hashFiles('.pre-commit-config.yaml') }}
restore-keys: |
pre-commit-${{ runner.os }}-py3.10-

- name: Run pre-commit
run: |
python -m pip install --upgrade pre-commit
pre-commit run --all-files --show-diff-on-failure --color=always
1 change: 1 addition & 0 deletions .github/workflows/make_docs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ jobs:
docs:
name: Documentation
runs-on: ubuntu-latest
timeout-minutes: 60
permissions:
actions: write
contents: write
Expand Down
101 changes: 101 additions & 0 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,83 @@ permissions:
actions: write
contents: read

concurrency:
# One in-flight run per branch/PR. Superseded pull request runs are cancelled;
# runs on main/develop are allowed to finish so every merged commit is verified.
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}

jobs:
changes:
name: Detect Julia changes
runs-on: ubuntu-latest
timeout-minutes: 5
permissions:
contents: read
pull-requests: read
outputs:
julia: ${{ steps.filter.outputs.julia }}
steps:
- name: Check whether the pull request touches Julia code
id: filter
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
REPO: ${{ github.repository }}
PR_NUMBER: ${{ github.event.pull_request.number }}
run: |
set -euo pipefail

# Report the decision to the job log as well as the run summary, so
# `why did/didn't this run?` is answerable from either one.
say() { echo "$1"; echo "$1" >> "$GITHUB_STEP_SUMMARY"; }

# Pushes to main/develop always run: every merged commit gets verified.
if [ "${{ github.event_name }}" != "pull_request" ]; then
echo "julia=true" >> "$GITHUB_OUTPUT"
say "Not a pull request — running the full test suite."
exit 0
fi

files=$(gh api --paginate "repos/${REPO}/pulls/${PR_NUMBER}/files" --jq '.[].filename')

# Allowlist of what test/runtests.jl actually exercises: the package
# itself, the tests and their fixtures, the example decks the tests run
# end-to-end, the dependency set, and this workflow. Anything not listed
# here does not trigger a run, so new untested Julia (benchmarks, docs
# scripts, a future tools/ directory) is excluded by default rather than
# by remembering to exclude it.
tested='(^src/|^test/|^examples/|^Project\.toml$|^\.github/workflows/test\.yaml$)'

relevant=$(printf '%s\n' "$files" | grep -E "$tested" || true)

say "### Julia change detection"
say ""
if [ -n "$relevant" ]; then
say "Running the test suite. Matched files:"
say '```'
say "$relevant"
say '```'
else
say "No Julia code, test data or example decks changed — skipping the test suite."
say ""
say "Files considered:"
say '```'
say "$files"
say '```'
fi

if [ -n "$relevant" ]; then
echo "julia=true" >> "$GITHUB_OUTPUT"
else
echo "julia=false" >> "$GITHUB_OUTPUT"
fi

test:
name: runtests ${{ matrix.version }} - ${{ matrix.os }}
needs: changes
if: needs.changes.outputs.julia == 'true'
runs-on: ${{ matrix.os }}
timeout-minutes: 90
strategy:
fail-fast: false
matrix:
Expand All @@ -43,5 +116,33 @@ jobs:
- name: Build Julia packages
uses: julia-actions/julia-buildpkg@v1

# Coverage instrumentation is off: nothing consumes the .cov files (they are
# gitignored and never uploaded), and instrumenting slows compute-heavy
# numerical code noticeably. Set coverage: true and add a Codecov upload
# step together if coverage reporting is ever wanted.
- name: Run tests
uses: julia-actions/julia-runtest@v1
with:
coverage: false

# Stable check that is present on every pull request, whether or not the suite
# ran. Point branch protection at this job so skipped runs do not block merges.
test-status:
name: Tests
needs: [changes, test]
if: always()
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- name: Report suite result
run: |
set -euo pipefail
if [ "${{ needs.changes.result }}" != "success" ]; then
echo "Change detection failed; cannot tell whether tests were needed."
exit 1
fi
case "${{ needs.test.result }}" in
success) echo "Test suite passed." ;;
skipped) echo "No Julia code changed; test suite intentionally skipped." ;;
*) echo "Test suite result: ${{ needs.test.result }}"; exit 1 ;;
esac
Loading