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
57 changes: 57 additions & 0 deletions .github/workflows/build_release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
name: build and test release

on:
workflow_call:
workflow_dispatch:
inputs:
ref:
description: "Commit, tag or branch to build"
required: false
default: ""
type: string

permissions:
contents: read

jobs:
build-and-test-wheel:
name: wheel install py3.12
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v6
with:
ref: ${{ inputs.ref }}
# Needed for setuptools-scm
fetch-depth: 0

- uses: actions/setup-python@v6
with:
python-version: "3.12"

- name: Install build tooling
run: python -m pip install --upgrade pip build twine setuptools-scm

- name: Show SCM-derived version
run: python -m setuptools_scm

- name: Build and check metadata
run: |
python -m build
python -m twine check --strict dist/*
ls dist

- name: Install the wheel
run: python -m pip install "$(ls dist/*.whl)" "pytest>=8"

- name: Test the wheel outside the source tree
run: |
cp -r tests "$RUNNER_TEMP/wheeltest"
cd "$RUNNER_TEMP"
pytest wheeltest

- uses: actions/upload-artifact@v4
with:
name: dist
path: dist/
if-no-files-found: error
69 changes: 69 additions & 0 deletions .github/workflows/format.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
name: pre-commit (PR only on changed files)

on:
pull_request:
types: [opened, synchronize, reopened]

permissions:
contents: read

jobs:
detect_changes:
runs-on: ubuntu-latest
outputs:
changed: ${{ steps.changed_files.outputs.changed }}

steps:
- name: Checkout full history
uses: actions/checkout@v6
with:
fetch-depth: 0

- name: Detect changed files
id: changed_files
env:
BASE_REF: ${{ github.base_ref }}
run: |
git fetch origin "$BASE_REF"
CHANGED_FILES=$(git diff --name-only --diff-filter=d "origin/$BASE_REF...HEAD")

delimiter="changed_$(openssl rand -hex 16)"
{
echo "changed<<$delimiter"
echo "$CHANGED_FILES"
echo "$delimiter"
} >> "$GITHUB_OUTPUT"

- name: Show changed files
env:
CHANGED_FILES: ${{ steps.changed_files.outputs.changed }}
run: |
echo "Changed files:"
echo "$CHANGED_FILES"

precommit:
needs: detect_changes
runs-on: ubuntu-latest
if: ${{ needs.detect_changes.outputs.changed != '' }}

steps:
- name: Checkout PR branch
uses: actions/checkout@v6
with:
repository: ${{ github.event.pull_request.head.repo.full_name }}
ref: ${{ github.event.pull_request.head.sha }}

- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: "3.12"

- name: Install pre-commit
run: pip install pre-commit

- name: Run pre-commit (CI check-only stage) on changed files
env:
CHANGED_FILES: ${{ needs.detect_changes.outputs.changed }}
run: |
mapfile -t files <<< "$CHANGED_FILES"
pre-commit run --hook-stage manual --files "${files[@]}" --show-diff-on-failure
63 changes: 63 additions & 0 deletions .github/workflows/test_package.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
name: Test suite

on:
push:
branches: [main]
pull_request:
branches: [main]
workflow_dispatch:
workflow_call:

concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}

permissions:
contents: read

jobs:
test:
name: ${{ matrix.os }} py${{ matrix.python-version }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
# Keep in sync w/ DeepLabCut
python-version: ["3.10", "3.11", "3.12"]

steps:
- uses: actions/checkout@v6

- uses: astral-sh/setup-uv@v7
with:
python-version: ${{ matrix.python-version }}
activate-environment: true

- name: Install
run: uv pip install . "pytest>=8"

- name: Test the installed package
run: pytest tests

test-dependency-floor:
name: dependency floor py3.10
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v6

- uses: astral-sh/setup-uv@v7
with:
python-version: "3.10"
activate-environment: true

- name: Install the lowest version each dependency declares
run: uv pip install --resolution lowest-direct . "pytest>=8"

- name: Test
run: pytest tests

build:
if: ${{ !startsWith(github.ref, 'refs/tags/') }}
uses: ./.github/workflows/build_release.yml
107 changes: 107 additions & 0 deletions .github/workflows/weekly_checks.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
name: weekly checks

on:
schedule:
- cron: "0 6 * * 1"
workflow_dispatch:
inputs:
simulate_failure:
description: "Skip the checks, fail on purpose, and open a test tracking issue"
required: false
default: false
type: boolean

permissions:
contents: read

jobs:
dependency-prereleases:
if: ${{ !inputs.simulate_failure }}
name: dependency pre-releases py3.12
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v6

- uses: astral-sh/setup-uv@v7
with:
python-version: "3.12"
activate-environment: true

- name: Install with pre-releases allowed
run: uv pip install --prerelease allow . "pytest>=8"

# `-o filterwarnings`, not `-W`: `-W` matches the module name exactly and would miss every submodule
- name: Test
run: |
pytest tests -o $'filterwarnings=error::DeprecationWarning:dlccore\nerror::FutureWarning:dlccore'

build-release:
if: ${{ !inputs.simulate_failure }}
uses: ./.github/workflows/build_release.yml

simulate-failure:
if: ${{ inputs.simulate_failure }}
runs-on: ubuntu-latest
steps:
- run: exit 1

notify:
# A job of its own: a step-level `if: failure()` never runs when its job dies before reaching it
needs: [dependency-prereleases, build-release, simulate-failure]
if: failure() && (github.event_name == 'schedule' || inputs.simulate_failure)
runs-on: ubuntu-latest
permissions:
contents: read
issues: write

steps:
- name: Open or update the tracking issue
env:
GH_TOKEN: ${{ github.token }}
REPO: ${{ github.repository }}
RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
PRERELEASE_RESULT: ${{ needs['dependency-prereleases'].result }}
BUILD_RESULT: ${{ needs['build-release'].result }}
SIMULATED: ${{ inputs.simulate_failure }}
run: |
set -euo pipefail
if [ "$SIMULATED" = "true" ]; then
title="Weekly checks failing (notification test)"
label="weekly checks test"
banner="> **Test.** Opened by a manual dispatch with *simulate_failure*; nothing is broken. Close it."
else
title="Weekly checks failing"
label="weekly checks"
banner=""
fi
gh label create "$label" --repo "$REPO" --color B60205 \
--description "Tracking issue for the weekly CI checks" --force

summary=$(printf '%s\n' \
"| Check | Result |" \
"| --- | --- |" \
"| dependency pre-releases | $PRERELEASE_RESULT |" \
"| build and test release | $BUILD_RESULT |")

existing=$(gh issue list --repo "$REPO" --state open --label "$label" --json number --jq '.[0].number // empty')
if [ -n "$existing" ]; then
gh issue comment "$existing" --repo "$REPO" --body "$(printf '%s\n' "Still failing: [run $GITHUB_RUN_ID]($RUN_URL)" "" "$summary")"
else
body=$(printf '%s\n' \
"Weekly checks failed: [run $GITHUB_RUN_ID]($RUN_URL)" \
"" \
"$summary" \
"" \
"These run against dependency pre-releases and the built wheel: a failure is usually an upstream change or a packaging problem, not a regression from a PR." \
"" \
"## Resolving" \
"" \
"1. Fix the failing job on a branch." \
"2. Re-run the check on that branch: Actions -> build and test release -> Run workflow, or Actions -> weekly checks -> Run workflow." \
"3. Merge the fix, dispatch Actions -> weekly checks on main, and close this issue. While it is open, later failures are added as comments.")
if [ -n "$banner" ]; then
body=$(printf '%s\n' "$banner" "" "$body")
fi
gh issue create --repo "$REPO" --title "$title" --body "$body" --label "$label"
fi
16 changes: 16 additions & 0 deletions tests/test_package.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#
# DeepLabCut Toolbox (deeplabcut.org)
# © A. & M.W. Mathis Labs
# https://github.com/DeepLabCut/dlccore
#
# Contributors:
# https://github.com/DeepLabCut/dlccore/graphs/contributors
#
# Licensed under GNU Lesser General Public License v3.0
#

import dlccore


def test_version_comes_from_the_installed_distribution() -> None:
assert dlccore.__version__ != "0+unknown"
Loading