Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Only run tests when the PR changes test code #433

Merged
merged 19 commits into from
Jul 2, 2024
Merged
63 changes: 63 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,45 @@ concurrency:
group: test-${{github.ref}}
cancel-in-progress: true
jobs:
check-changes:
name: Check for changes
runs-on: ubuntu-latest
outputs:
changed: ${{steps.check-for-changes.outputs.changed}}
steps:
- name: 🛒 Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- id: check-for-changes
name: 🔎 Check for changes
run: |
if [[ -z "$PR_NUMBER" ]]; then
echo "not a PR, assuming changed"
echo changed=yes >>"$GITHUB_OUTPUT"
else
if gh pr diff $PR_NUMBER --name-only |grep '^lenskit.*\.py$'; then
echo "source code changed"
echo changed=yes >>"$GITHUB_OUTPUT"
elif gh pr view $PR_NUMBER --json body -t '{{.body}}' | grep 'tests: force'; then
echo "test run forced from PR text"
echo changed=yes >>"$GITHUB_OUTPUT"
else
echo "source code unchanged"
echo changed=no >>"$GITHUB_OUTPUT"
fi
fi
cat $GITHUB_OUTPUT
env:
GH_TOKEN: ${{ github.token }}
PR_NUMBER: ${{ github.event.number }}
conda:
name: Conda Python ${{matrix.python}} on ${{matrix.platform}}
runs-on: ${{matrix.platform}}
timeout-minutes: 30
needs:
- check-changes
if: needs.check-changes.outputs.changed == 'yes'
defaults:
run:
shell: bash -el {0}
Expand Down Expand Up @@ -71,6 +106,9 @@ jobs:
name: Vanilla Python ${{matrix.python}} on ${{matrix.platform}}
runs-on: ${{matrix.platform}}
timeout-minutes: 30
needs:
- check-changes
if: needs.check-changes.outputs.changed == 'yes'
strategy:
fail-fast: false
matrix:
Expand Down Expand Up @@ -129,6 +167,9 @@ jobs:
name: Non-JIT test coverage
runs-on: ubuntu-latest
timeout-minutes: 30
needs:
- check-changes
if: needs.check-changes.outputs.changed == 'yes'
steps:
- name: 🛒 Checkout
uses: actions/checkout@v4
Expand Down Expand Up @@ -179,6 +220,9 @@ jobs:
name: Minimal dependency tests
runs-on: ubuntu-latest
timeout-minutes: 30
needs:
- check-changes
if: needs.check-changes.outputs.changed == 'yes'
steps:
- name: 🛒 Checkout
uses: actions/checkout@v4
Expand Down Expand Up @@ -226,6 +270,9 @@ jobs:
name: FunkSVD tests on Python ${{matrix.python}}
runs-on: ubuntu-latest
timeout-minutes: 30
needs:
- check-changes
if: needs.check-changes.outputs.changed == 'yes'
defaults:
run:
shell: bash -el {0}
Expand Down Expand Up @@ -281,6 +328,9 @@ jobs:
name: Minimal dependency tests for FunkSVD
runs-on: ubuntu-latest
timeout-minutes: 30
needs:
- check-changes
if: needs.check-changes.outputs.changed == 'yes'
steps:
- name: 🛒 Checkout
uses: actions/checkout@v4
Expand Down Expand Up @@ -328,6 +378,9 @@ jobs:
name: Implicit bridge tests on Python ${{matrix.python}}
runs-on: ubuntu-latest
timeout-minutes: 30
needs:
- check-changes
if: needs.check-changes.outputs.changed == 'yes'
defaults:
run:
shell: bash -el {0}
Expand Down Expand Up @@ -383,6 +436,9 @@ jobs:
name: Minimal dependency tests for Implicit
runs-on: ubuntu-latest
timeout-minutes: 30
needs:
- check-changes
if: needs.check-changes.outputs.changed == 'yes'
steps:
- name: 🛒 Checkout
uses: actions/checkout@v4
Expand Down Expand Up @@ -430,6 +486,9 @@ jobs:
name: HPF bridge tests on Python ${{matrix.python}}
runs-on: ubuntu-latest
timeout-minutes: 30
needs:
- check-changes
if: needs.check-changes.outputs.changed == 'yes'
strategy:
fail-fast: false
matrix:
Expand Down Expand Up @@ -486,6 +545,9 @@ jobs:
defaults:
run:
shell: bash -el {0}
needs:
- check-changes
if: needs.check-changes.outputs.changed == 'yes'
steps:
- name: 🛒 Checkout
uses: actions/checkout@v4
Expand Down Expand Up @@ -592,6 +654,7 @@ jobs:
name: Test suite results
runs-on: ubuntu-latest
needs:
- check-changes
- conda
- vanilla
- nojit
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ dask-worker-space/
.tox/
.vagrant/
.venv/
.uv/
scratch/

# build outputs
Expand Down
2 changes: 2 additions & 0 deletions lkdev/ghactions.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ def command(cls, args: list[str]):
{
"name": str,
"runs-on": str,
"if": NotRequired[str],
"outputs": NotRequired[dict[str, str]],
"timeout-minutes": NotRequired[int],
"strategy": NotRequired[dict[str, Any]],
"defaults": NotRequired[dict[str, Any]],
Expand Down
50 changes: 46 additions & 4 deletions lkdev/workflows/test.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@


def workflow():
jobs: dict[str, GHJob] = test_jobs()
jobs["results"] = result_job(list(jobs.keys()))
jobs = {"check-changes": job_check_changes()}
jobs.update(jobs_test_matrix())
jobs["results"] = jobs_result(list(jobs.keys()))
return {
"name": "Automatic Tests",
"on": {
Expand Down Expand Up @@ -286,6 +287,8 @@ def test_job(options: JobOptions) -> GHJob:
"name": options.name,
"runs-on": options.vm_platform,
"timeout-minutes": 30,
"needs": ["check-changes"],
"if": "needs.check-changes.outputs.changed == 'yes'",
}
if options.env == "conda":
job["defaults"] = {
Expand All @@ -312,6 +315,8 @@ def test_eval_job() -> GHJob:
"name": opts.name,
"runs-on": opts.vm_platform,
"defaults": {"run": {"shell": "bash -el {0}"}},
"needs": ["check-changes"],
"if": "needs.check-changes.outputs.changed == 'yes'",
"steps": [step_checkout(opts)]
+ steps_setup_conda(opts)
+ steps_mldata(opts, ["ml-100k", "ml-20m"])
Expand Down Expand Up @@ -355,7 +360,44 @@ def test_doc_job() -> GHJob:
}


def test_jobs() -> dict[str, GHJob]:
def job_check_changes() -> GHJob:
return {
"name": "Check for changes",
"runs-on": "ubuntu-latest",
"outputs": {"changed": "${{steps.check-for-changes.outputs.changed}}"},
"steps": [
step_checkout(),
{
"id": "check-for-changes",
"name": "🔎 Check for changes",
"run": script("""
if [[ -z "$PR_NUMBER" ]]; then
echo "not a PR, assuming changed"
echo changed=yes >>"$GITHUB_OUTPUT"
else
if gh pr diff $PR_NUMBER --name-only |grep '^lenskit.*\\.py$'; then
echo "source code changed"
echo changed=yes >>"$GITHUB_OUTPUT"
elif gh pr view $PR_NUMBER --json body -t '{{.body}}' | grep 'tests: force'; then
echo "test run forced from PR text"
echo changed=yes >>"$GITHUB_OUTPUT"
else
echo "source code unchanged"
echo changed=no >>"$GITHUB_OUTPUT"
fi
fi
cat $GITHUB_OUTPUT
"""), # noqa: E501
"env": {
"GH_TOKEN": "${{ github.token }}",
"PR_NUMBER": "${{ github.event.number }}",
},
},
],
}


def jobs_test_matrix() -> dict[str, GHJob]:
return {
"conda": test_job(
JobOptions(
Expand Down Expand Up @@ -436,7 +478,7 @@ def test_jobs() -> dict[str, GHJob]:
}


def result_job(deps: list[str]) -> GHJob:
def jobs_result(deps: list[str]) -> GHJob:
return {
"name": "Test suite results",
"runs-on": "ubuntu-latest",
Expand Down
Loading