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
38 changes: 38 additions & 0 deletions .github/actions/ci-scope/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
name: Classify CI changes
description: Check the full PR or push diff; missing history runs all checks.
outputs:
runtime_changed:
description: Whether runtime tests and Python packaging are needed.
value: ${{ steps.scope.outputs.runtime_changed }}
desktop_changed:
description: Whether Desktop or bundled runtime inputs changed.
value: ${{ steps.scope.outputs.desktop_changed }}
runs:
using: composite
steps:
- id: scope
shell: bash
env:
EVENT_NAME: ${{ github.event_name }}
BASE_SHA: ${{ github.event.pull_request.base.sha || github.event.before }}
HEAD_SHA: ${{ github.event.pull_request.head.sha || github.sha }}
run: |
run_all() {
echo "runtime_changed=true" >> "$GITHUB_OUTPUT"
echo "desktop_changed=true" >> "$GITHUB_OUTPUT"
}
if [[ "$EVENT_NAME" != "pull_request" && "$EVENT_NAME" != "push" ]] ||
[[ -z "$BASE_SHA" || "$BASE_SHA" =~ ^0+$ ]] ||
! git cat-file -e "${BASE_SHA}^{commit}" 2>/dev/null ||
! git cat-file -e "${HEAD_SHA}^{commit}" 2>/dev/null; then
run_all
exit 0
fi
if [[ "$EVENT_NAME" == "pull_request" ]]; then
if ! BASE_SHA="$(git merge-base "$BASE_SHA" "$HEAD_SHA")"; then
run_all
exit 0
fi
fi
git diff --no-renames --name-only -z "$BASE_SHA" "$HEAD_SHA" \
| python scripts/ci_scope.py >> "$GITHUB_OUTPUT"
49 changes: 16 additions & 33 deletions .github/workflows/desktop-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ permissions:

concurrency:
group: desktop-ci-${{ github.ref }}
cancel-in-progress: true
cancel-in-progress: ${{ github.event_name == 'pull_request' }}

jobs:
quality:
Expand All @@ -28,37 +28,9 @@ jobs:
with:
fetch-depth: 0

- name: Detect desktop-impacting changes
- name: Classify changes
id: scope
env:
EVENT_NAME: ${{ github.event_name }}
BEFORE_SHA: ${{ github.event.before }}
BASE_SHA: ${{ github.event.pull_request.base.sha }}
HEAD_SHA: ${{ github.event.pull_request.head.sha || github.sha }}
run: |
if [[ "$EVENT_NAME" == "workflow_dispatch" ]]; then
echo "desktop_changed=true" >> "$GITHUB_OUTPUT"
exit 0
fi

if [[ "$EVENT_NAME" == "pull_request" ]]; then
compare_from="$BASE_SHA"
else
compare_from="$BEFORE_SHA"
fi

if [[ -z "$compare_from" || "$compare_from" =~ ^0+$ ]]; then
echo "desktop_changed=true" >> "$GITHUB_OUTPUT"
exit 0
fi

if ! git cat-file -e "${compare_from}^{commit}" 2>/dev/null; then
echo "desktop_changed=true" >> "$GITHUB_OUTPUT"
exit 0
fi

git diff --no-renames --name-only -z "$compare_from" "$HEAD_SHA" \
| python3 scripts/desktop_ci_scope.py >> "$GITHUB_OUTPUT"
uses: ./.github/actions/ci-scope

- name: Skip unaffected Desktop checks
if: steps.scope.outputs.desktop_changed != 'true'
Expand Down Expand Up @@ -128,6 +100,12 @@ jobs:
with:
components: clippy, rustfmt

- name: Cache Rust dependencies
if: steps.scope.outputs.desktop_changed == 'true'
uses: Swatinem/rust-cache@v2
with:
workspaces: desktop/src-tauri

- name: Install frontend dependencies
if: steps.scope.outputs.desktop_changed == 'true'
working-directory: desktop
Expand All @@ -154,8 +132,8 @@ jobs:
working-directory: desktop/src-tauri
run: |
cargo fmt --check
cargo clippy --all-targets -- -D warnings
cargo test --all-targets
cargo clippy --locked --all-targets -- -D warnings
cargo test --locked --all-targets

bundle:
name: Bundle ${{ matrix.name }}
Expand Down Expand Up @@ -254,6 +232,11 @@ jobs:
- name: Set up Rust
uses: dtolnay/rust-toolchain@stable

- name: Cache Rust dependencies
uses: Swatinem/rust-cache@v2
with:
workspaces: desktop/src-tauri

- name: Install frontend dependencies
working-directory: desktop
run: npm ci
Expand Down
21 changes: 17 additions & 4 deletions .github/workflows/linting.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,24 +8,37 @@ on:
branches:
- main

permissions:
contents: read

concurrency:
group: lint-ci-${{ github.ref }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}

jobs:
lint-and-format:
runs-on: ubuntu-latest
runs-on: ubuntu-24.04
timeout-minutes: 15

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

- name: Set up Python
id: python
uses: actions/setup-python@v5
with:
python-version: '3.12'

- name: Install dependencies
- name: Cache pre-commit environments
uses: actions/cache@v4
with:
path: ~/.cache/pre-commit
key: pre-commit-${{ runner.os }}-${{ steps.python.outputs.python-version }}-${{ hashFiles('.pre-commit-config.yaml', 'scripts/ci/requirements.lock') }}

- name: Install pre-commit
run: |
python -m pip install --upgrade pip
pip install pre-commit
python -m pip install -c scripts/ci/requirements.lock pre-commit

- name: Run pre-commit
run: pre-commit run --all-files --show-diff-on-failure
13 changes: 13 additions & 0 deletions .github/workflows/pypi-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,19 @@ jobs:
python-version: "3.12"
cache: pip

- name: Set up Node for packaged web assets
uses: actions/setup-node@v4
with:
node-version: "22"
cache: npm
cache-dependency-path: desktop/package-lock.json

- name: Build packaged browser client
working-directory: desktop
run: |
npm ci
npm run build:web

- name: Build release distributions
run: |
python -m pip install --upgrade pip build packaging twine
Expand Down
97 changes: 86 additions & 11 deletions .github/workflows/python-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,13 @@ on:
permissions:
contents: read

concurrency:
group: python-ci-${{ github.ref }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}

jobs:
test:
runs-on: ubuntu-latest
runs-on: ubuntu-24.04
timeout-minutes: 30
strategy:
fail-fast: false
Expand All @@ -21,22 +25,40 @@ jobs:
steps:
- name: Check out repository
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Classify changes
id: scope
uses: ./.github/actions/ci-scope

- name: Set up Python
if: steps.scope.outputs.runtime_changed == 'true'
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
cache: pip
cache-dependency-path: scripts/ci/requirements.lock

- name: Install package and test tools
if: steps.scope.outputs.runtime_changed == 'true'
run: |
python -m pip install --upgrade pip
python -m pip install -e ".[test]"
python -m pip install -r scripts/ci/requirements.lock
python -m pip install --no-deps --no-build-isolation -e ".[test]"

- name: Run tests
if: steps.scope.outputs.runtime_changed == 'true'
run: |
python -m pip check
python -m pytest -q
python -m pytest -q --durations=10 --junitxml=test-results/python.xml

- name: Upload test results
if: always() && steps.scope.outputs.runtime_changed == 'true'
uses: actions/upload-artifact@v4
with:
name: python-${{ matrix.python-version }}-results
path: test-results/
retention-days: 7

windows-lifecycle:
name: Windows lifecycle locks and platform isolation
Expand All @@ -46,21 +68,33 @@ jobs:
steps:
- name: Check out repository
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Classify changes
id: scope
uses: ./.github/actions/ci-scope

- name: Set up Python
if: steps.scope.outputs.runtime_changed == 'true'
uses: actions/setup-python@v5
with:
python-version: "3.12"
cache: pip
cache-dependency-path: scripts/ci/requirements.lock

- name: Install package and test tools
if: steps.scope.outputs.runtime_changed == 'true'
shell: bash
run: |
python -m pip install --upgrade pip
python -m pip install -e ".[test]"
python -m pip install -r scripts/ci/requirements.lock
python -m pip install --no-deps --no-build-isolation -e ".[test]"
python -m pip check

- name: Verify shared leases, startup recovery, and scheduler leadership
if: steps.scope.outputs.runtime_changed == 'true'
run: >-
python -m pytest -q
python -m pytest -q --durations=10 --junitxml=test-results/windows-lifecycle.xml
tests/application/test_application_lease.py
tests/application/test_automation_scheduler_leadership.py
tests/application/test_session_deletion_service.py
Expand All @@ -70,36 +104,77 @@ jobs:
# backend) that the ubuntu job can only skip. This is the sole place
# they actually execute.
- name: Verify Windows ACLs and Job Object sandbox
if: steps.scope.outputs.runtime_changed == 'true'
run: >-
python -m pytest -q
python -m pytest -q --durations=10 --junitxml=test-results/windows-platform.xml
tests/test_private_storage_windows.py
tests/test_harness_sandbox.py
tests/test_exec_sandbox_wiring.py
tests/app_server/test_windows_task.py
tests/app_server/test_state_backup.py
tests/test_provider_oauth.py
tests/test_provider_protocols.py
tests/app_server/test_service.py
tests/app_server/test_service_discovery.py

- name: Upload test results
if: always() && steps.scope.outputs.runtime_changed == 'true'
uses: actions/upload-artifact@v4
with:
name: windows-lifecycle-results
path: test-results/
retention-days: 7

package:
runs-on: ubuntu-latest
runs-on: ubuntu-24.04
timeout-minutes: 20

steps:
- name: Check out repository
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Classify changes
id: scope
uses: ./.github/actions/ci-scope

- name: Set up Python
if: steps.scope.outputs.runtime_changed == 'true'
uses: actions/setup-python@v5
with:
python-version: "3.12"
cache: pip
cache-dependency-path: scripts/ci/requirements.lock

- name: Set up Node for packaged web assets
if: steps.scope.outputs.runtime_changed == 'true'
uses: actions/setup-node@v4
with:
node-version: "22"
cache: npm
cache-dependency-path: desktop/package-lock.json

- name: Build packaged browser client
if: steps.scope.outputs.runtime_changed == 'true'
working-directory: desktop
run: |
npm ci
npm run build:web

- name: Build distributions
if: steps.scope.outputs.runtime_changed == 'true'
run: |
python -m pip install --upgrade pip build packaging twine
python -m build
python -m pip install -r scripts/ci/requirements.lock
python -m build --no-isolation
python -m twine check dist/*

- name: Verify distribution metadata and installed runtime
if: steps.scope.outputs.runtime_changed == 'true'
run: python scripts/verify_python_distribution.py --dist-dir dist

- name: Upload distributions
if: steps.scope.outputs.runtime_changed == 'true'
uses: actions/upload-artifact@v4
with:
name: python-distributions
Expand Down
Loading
Loading