Merge pull request #36 from bhack/issue-35-auto-preset-startup-scope #229
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: CI | |
| on: | |
| push: | |
| branches: | |
| - main | |
| pull_request: | |
| workflow_dispatch: | |
| inputs: | |
| flatpak_runtime_smoke: | |
| description: Run the experimental Flatpak PipeWire routing smoke test | |
| type: boolean | |
| default: false | |
| headless_pipewire_runtime_smoke: | |
| description: Run the headless PipeWire/WirePlumber controller smoke test | |
| type: boolean | |
| default: false | |
| live_ui_runtime_smoke: | |
| description: Run the live GTK/AT-SPI/PipeWire smoke test | |
| type: boolean | |
| default: false | |
| smoke_only: | |
| description: Skip ordinary CI work and run only the requested experimental smoke job | |
| type: boolean | |
| default: false | |
| flatpak_runtime_build: | |
| description: Build and reinstall the local Flatpak before the runtime smoke test | |
| type: boolean | |
| default: true | |
| flatpak_runtime_install_remote: | |
| description: Install the smoke target from Flathub instead of using a local build | |
| type: boolean | |
| default: false | |
| flatpak_runtime_app_ref: | |
| description: Optional Flatpak app ref to run; blank infers the build or install ref | |
| type: string | |
| default: "" | |
| flatpak_runtime_install_ref: | |
| description: Flathub ref to install when flatpak_runtime_install_remote is enabled | |
| type: string | |
| default: io.github.bhack.mini-eq | |
| flatpak_runtime_expected_version: | |
| description: Optional installed Flatpak version expected by the runtime smoke test | |
| type: string | |
| default: "" | |
| permissions: | |
| contents: read | |
| pull-requests: read | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.event_name }}-${{ github.event.pull_request.number || github.ref }} | |
| cancel-in-progress: true | |
| env: | |
| PWG_VERSION: "0.3.9" | |
| PWG_REQUIREMENT: "pipewire-gobject>=0.3.9,<0.4" | |
| jobs: | |
| changes: | |
| runs-on: ubuntu-24.04 | |
| outputs: | |
| flatpak: ${{ steps.filter.outputs.flatpak }} | |
| release_metadata: ${{ steps.filter.outputs.release_metadata }} | |
| test: ${{ steps.filter.outputs.test }} | |
| tooling: ${{ steps.filter.outputs.tooling }} | |
| pwg: ${{ steps.filter.outputs.pwg }} | |
| steps: | |
| - name: Check out repository | |
| uses: actions/checkout@v6 | |
| with: | |
| ref: ${{ github.event_name == 'pull_request' && github.base_ref || github.ref }} | |
| - name: Detect changed files | |
| id: filter | |
| env: | |
| BEFORE: ${{ github.event.before }} | |
| GH_TOKEN: ${{ github.token }} | |
| PR_NUMBER: ${{ github.event.pull_request.number }} | |
| SMOKE_ONLY: ${{ inputs.smoke_only }} | |
| run: | | |
| set -euo pipefail | |
| files="$(mktemp)" | |
| fallback_scopes() { | |
| local value="$1" | |
| { | |
| echo "test=$value" | |
| echo "tooling=$value" | |
| echo "pwg=$value" | |
| echo "flatpak=$value" | |
| echo "release_metadata=$value" | |
| } >> "$GITHUB_OUTPUT" | |
| { | |
| echo "### CI scope" | |
| echo | |
| echo "tools/ci_scope.py is not available in the checked-out base branch; falling back to \`$value\` for every scope." | |
| echo | |
| echo "- test: \`$value\`" | |
| echo "- tooling: \`$value\`" | |
| echo "- pipewire-gobject: \`$value\`" | |
| echo "- flatpak: \`$value\`" | |
| echo "- release metadata: \`$value\`" | |
| } >> "$GITHUB_STEP_SUMMARY" | |
| } | |
| set_scopes() { | |
| if [[ -f tools/ci_scope.py ]]; then | |
| python3 tools/ci_scope.py "$@" \ | |
| --github-output "$GITHUB_OUTPUT" \ | |
| --github-summary "$GITHUB_STEP_SUMMARY" | |
| return | |
| fi | |
| if [[ "${1:-}" == "--none" ]]; then | |
| fallback_scopes false | |
| else | |
| fallback_scopes true | |
| fi | |
| } | |
| case "$GITHUB_EVENT_NAME" in | |
| workflow_dispatch) | |
| if [[ "${SMOKE_ONLY:-false}" == "true" ]]; then | |
| set_scopes --none | |
| exit 0 | |
| fi | |
| set_scopes --all | |
| exit 0 | |
| ;; | |
| pull_request) | |
| gh api --paginate "repos/$GITHUB_REPOSITORY/pulls/$PR_NUMBER/files" --jq '.[].filename' > "$files" | |
| ;; | |
| push) | |
| if [[ -z "${BEFORE:-}" || "$BEFORE" =~ ^0+$ ]]; then | |
| set_scopes --all | |
| exit 0 | |
| fi | |
| gh api "repos/$GITHUB_REPOSITORY/compare/$BEFORE...$GITHUB_SHA" --jq '.files[].filename' > "$files" | |
| ;; | |
| *) | |
| set_scopes --all | |
| exit 0 | |
| ;; | |
| esac | |
| set_scopes "$files" | |
| release-metadata: | |
| needs: changes | |
| if: ${{ always() && !(github.event_name == 'workflow_dispatch' && inputs.smoke_only) }} | |
| runs-on: ubuntu-24.04 | |
| steps: | |
| - name: Require change detection | |
| if: ${{ needs.changes.result != 'success' }} | |
| run: exit 1 | |
| - name: Skip unchanged scope | |
| if: ${{ needs.changes.outputs.release_metadata != 'true' }} | |
| run: echo "No release metadata changes detected; skipping release metadata status check." | |
| - name: Check out repository | |
| if: ${{ needs.changes.outputs.release_metadata == 'true' }} | |
| uses: actions/checkout@v6 | |
| - name: Check local release metadata status | |
| if: ${{ needs.changes.outputs.release_metadata == 'true' }} | |
| run: python3 tools/release_status.py --no-network | |
| tooling: | |
| needs: changes | |
| if: ${{ always() && !(github.event_name == 'workflow_dispatch' && inputs.smoke_only) }} | |
| runs-on: ubuntu-24.04 | |
| steps: | |
| - name: Require change detection | |
| if: ${{ needs.changes.result != 'success' }} | |
| run: exit 1 | |
| - name: Skip unchanged scope | |
| if: ${{ needs.changes.outputs.tooling != 'true' }} | |
| run: echo "No maintainer-tooling changes detected; skipping tooling job work." | |
| - name: Check out repository | |
| if: ${{ needs.changes.outputs.tooling == 'true' }} | |
| uses: actions/checkout@v6 | |
| - name: Cache pip downloads | |
| if: ${{ needs.changes.outputs.tooling == 'true' }} | |
| uses: actions/cache@v5 | |
| with: | |
| path: ~/.cache/pip | |
| key: tooling-pip-${{ runner.os }}-${{ hashFiles('pyproject.toml') }} | |
| restore-keys: tooling-pip-${{ runner.os }}- | |
| - name: Install Python tooling | |
| if: ${{ needs.changes.outputs.tooling == 'true' }} | |
| run: | | |
| python3 -m venv .venv | |
| .venv/bin/python -m pip install --upgrade pip | |
| .venv/bin/python -m pip install ruff | |
| - name: Lint | |
| if: ${{ needs.changes.outputs.tooling == 'true' }} | |
| run: .venv/bin/python -m ruff check . | |
| - name: Check formatting | |
| if: ${{ needs.changes.outputs.tooling == 'true' }} | |
| run: .venv/bin/python -m ruff format --check . | |
| test: | |
| needs: changes | |
| if: ${{ always() && !(github.event_name == 'workflow_dispatch' && inputs.smoke_only) }} | |
| runs-on: ubuntu-24.04 | |
| steps: | |
| - name: Require change detection | |
| if: ${{ needs.changes.result != 'success' }} | |
| run: exit 1 | |
| - name: Skip unchanged scope | |
| if: ${{ needs.changes.outputs.test != 'true' }} | |
| run: echo "No Python/package changes detected; skipping test job work." | |
| - name: Check out repository | |
| if: ${{ needs.changes.outputs.test == 'true' }} | |
| uses: actions/checkout@v6 | |
| - name: Cache pip downloads and wheels | |
| if: ${{ needs.changes.outputs.test == 'true' }} | |
| uses: actions/cache@v5 | |
| with: | |
| path: ~/.cache/pip | |
| key: test-pip-${{ runner.os }}-py3-${{ hashFiles('pyproject.toml') }} | |
| restore-keys: test-pip-${{ runner.os }}-py3- | |
| - name: Install system dependencies | |
| if: ${{ needs.changes.outputs.test == 'true' }} | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y \ | |
| gir1.2-adw-1 \ | |
| gir1.2-gtk-4.0 \ | |
| gobject-introspection \ | |
| libgirepository1.0-dev \ | |
| libglib2.0-dev \ | |
| libpipewire-0.3-dev \ | |
| meson \ | |
| ninja-build \ | |
| pipewire \ | |
| python3-cairo \ | |
| python3-dev \ | |
| python3-gi \ | |
| python3-pip \ | |
| python3-setuptools \ | |
| python3-venv \ | |
| wireplumber | |
| - name: Install Python dependencies | |
| if: ${{ needs.changes.outputs.test == 'true' }} | |
| run: | | |
| python3 -m venv /tmp/mini-eq-pwg-build | |
| /tmp/mini-eq-pwg-build/bin/python -m pip install --upgrade pip | |
| /tmp/mini-eq-pwg-build/bin/python -m pip wheel "$PWG_REQUIREMENT" -w /tmp/mini-eq-wheelhouse | |
| python3 -m venv --system-site-packages .venv | |
| .venv/bin/python -m pip install --upgrade pip | |
| .venv/bin/python -m pip install --no-index --find-links /tmp/mini-eq-wheelhouse "$PWG_REQUIREMENT" | |
| .venv/bin/python -m pip install -e '.[dev]' | |
| - name: Lint | |
| if: ${{ needs.changes.outputs.test == 'true' }} | |
| run: .venv/bin/python -m ruff check . | |
| - name: Check formatting | |
| if: ${{ needs.changes.outputs.test == 'true' }} | |
| run: .venv/bin/python -m ruff format --check . | |
| - name: Test | |
| if: ${{ needs.changes.outputs.test == 'true' }} | |
| run: .venv/bin/python -m pytest -q | |
| - name: Build package | |
| if: ${{ needs.changes.outputs.test == 'true' }} | |
| run: .venv/bin/python -m build | |
| - name: Check package metadata | |
| if: ${{ needs.changes.outputs.test == 'true' }} | |
| run: .venv/bin/python -m twine check dist/* | |
| - name: Smoke-test wheel CLI | |
| if: ${{ needs.changes.outputs.test == 'true' }} | |
| run: | | |
| python3 -m venv --system-site-packages /tmp/mini-eq-wheel-test | |
| /tmp/mini-eq-wheel-test/bin/python -m pip install --upgrade pip | |
| /tmp/mini-eq-wheel-test/bin/python -m pip install --no-index --find-links /tmp/mini-eq-wheelhouse "$PWG_REQUIREMENT" | |
| /tmp/mini-eq-wheel-test/bin/python -m pip install dist/mini_eq-*.whl | |
| /tmp/mini-eq-wheel-test/bin/mini-eq --help | |
| - name: Upload package artifacts | |
| if: ${{ needs.changes.outputs.test == 'true' }} | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: mini-eq-dist | |
| path: dist/* | |
| if-no-files-found: error | |
| flatpak-build: | |
| needs: changes | |
| if: ${{ always() && !(github.event_name == 'workflow_dispatch' && inputs.smoke_only) && needs.changes.result == 'success' && needs.changes.outputs.flatpak == 'true' }} | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 60 | |
| container: | |
| image: ghcr.io/flathub-infra/flatpak-github-actions:gnome-50@sha256:9d3a99bef793cf99f55b0106130e68a781fd0815c8d2954f26e1ac9253b19e57 | |
| options: --privileged | |
| steps: | |
| - name: Check out repository | |
| uses: actions/checkout@v6 | |
| - name: Configure Flathub remote | |
| run: | | |
| flatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo | |
| flatpak --user remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo | |
| - name: Build Flatpak | |
| uses: flatpak/flatpak-github-actions/flatpak-builder@401fe28a8384095fc1531b9d320b292f0ee45adb | |
| with: | |
| bundle: mini-eq.flatpak | |
| manifest-path: io.github.bhack.mini-eq.yaml | |
| upload-artifact: false | |
| - name: Install built Flatpak | |
| run: flatpak --user install -y ./mini-eq.flatpak | |
| - name: Smoke-test Flatpak CLI | |
| run: flatpak run io.github.bhack.mini-eq --help | |
| - name: Check pipewire-gobject GI compatibility | |
| run: | | |
| flatpak run --filesystem="$PWD":ro --command=python3 io.github.bhack.mini-eq \ | |
| "$PWD/tools/check_pipewire_gobject.py" --expect-version "$PWG_VERSION" | |
| - name: Smoke-test Flatpak runtime modules | |
| run: | | |
| flatpak run --command=python3 io.github.bhack.mini-eq - <<'PY' | |
| from pathlib import Path | |
| required_files = [ | |
| "/app/lib/pipewire-0.3/libpipewire-module-filter-chain.so", | |
| "/app/lib/spa-0.2/filter-graph/libspa-filter-graph.so", | |
| "/app/lib/spa-0.2/filter-graph/libspa-filter-graph-plugin-builtin.so", | |
| ] | |
| missing = [path for path in required_files if not Path(path).exists()] | |
| if missing: | |
| raise SystemExit(f"missing Flatpak runtime file(s): {', '.join(missing)}") | |
| PY | |
| flatpak run --command=python3 io.github.bhack.mini-eq - <<'PY' | |
| from pathlib import Path | |
| required_license_files = [ | |
| "/app/share/licenses/io.github.bhack.mini-eq/mini-eq/LICENSE", | |
| "/app/share/licenses/io.github.bhack.mini-eq/pipewire-filter-chain-module/COPYING", | |
| "/app/share/licenses/io.github.bhack.mini-eq/pipewire-filter-chain-module/LICENSE", | |
| "/app/share/licenses/io.github.bhack.mini-eq/pipewire-gobject/LICENSE", | |
| ] | |
| missing = [path for path in required_license_files if not Path(path).exists()] | |
| if missing: | |
| raise SystemExit(f"missing Flatpak license file(s): {', '.join(missing)}") | |
| PY | |
| flatpak run --command=python3 io.github.bhack.mini-eq - <<'PY' | |
| import importlib | |
| required_modules = ["numpy", "pipewire_gobject"] | |
| missing = [] | |
| for name in required_modules: | |
| try: | |
| importlib.import_module(name) | |
| except Exception as exc: | |
| missing.append(f"{name}: {exc}") | |
| if missing: | |
| raise SystemExit(f"missing Python analyzer module(s): {', '.join(missing)}") | |
| PY | |
| flatpak: | |
| needs: | |
| - changes | |
| - flatpak-build | |
| if: ${{ always() && !(github.event_name == 'workflow_dispatch' && inputs.smoke_only) }} | |
| runs-on: ubuntu-24.04 | |
| steps: | |
| - name: Require change detection | |
| if: ${{ needs.changes.result != 'success' }} | |
| run: exit 1 | |
| - name: Skip unchanged scope | |
| if: ${{ needs.changes.outputs.flatpak != 'true' }} | |
| run: echo "No Flatpak-relevant changes detected; skipping Flatpak build." | |
| - name: Require Flatpak build | |
| if: ${{ needs.changes.outputs.flatpak == 'true' && needs['flatpak-build'].result != 'success' }} | |
| run: exit 1 | |
| - name: Confirm Flatpak build | |
| if: ${{ needs.changes.outputs.flatpak == 'true' && needs['flatpak-build'].result == 'success' }} | |
| run: echo "Flatpak build passed." | |
| flatpak-runtime-smoke: | |
| needs: changes | |
| if: ${{ github.event_name == 'workflow_dispatch' && inputs.flatpak_runtime_smoke }} | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 90 | |
| continue-on-error: true | |
| steps: | |
| - name: Require change detection | |
| if: ${{ needs.changes.result != 'success' }} | |
| run: exit 1 | |
| - name: Check out repository | |
| uses: actions/checkout@v6 | |
| - name: Install Flatpak and PipeWire test dependencies | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y \ | |
| dbus-user-session \ | |
| flatpak \ | |
| jq \ | |
| pipewire \ | |
| pipewire-bin \ | |
| wireplumber | |
| - name: Build and run experimental Flatpak runtime smoke | |
| env: | |
| MINI_EQ_FLATPAK_BUILD: ${{ inputs.flatpak_runtime_build && '1' || '0' }} | |
| MINI_EQ_FLATPAK_INSTALL_REMOTE: ${{ inputs.flatpak_runtime_install_remote && '1' || '0' }} | |
| MINI_EQ_FLATPAK_APP_REF: ${{ inputs.flatpak_runtime_app_ref }} | |
| MINI_EQ_FLATPAK_INSTALL_REF: ${{ inputs.flatpak_runtime_install_ref }} | |
| MINI_EQ_FLATPAK_EXPECT_VERSION: ${{ inputs.flatpak_runtime_expected_version }} | |
| run: tools/run_flatpak_runtime_smoke_ci.sh | |
| headless-pipewire-runtime-smoke: | |
| needs: changes | |
| if: ${{ github.event_name == 'workflow_dispatch' && inputs.headless_pipewire_runtime_smoke }} | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 45 | |
| steps: | |
| - name: Require change detection | |
| if: ${{ needs.changes.result != 'success' }} | |
| run: exit 1 | |
| - name: Check out repository | |
| uses: actions/checkout@v6 | |
| - name: Install headless PipeWire runtime dependencies | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y \ | |
| build-essential \ | |
| dbus-user-session \ | |
| gobject-introspection \ | |
| libebur128-1 \ | |
| libgirepository1.0-dev \ | |
| libglib2.0-dev \ | |
| libpipewire-0.3-dev \ | |
| libspa-0.2-modules \ | |
| meson \ | |
| ninja-build \ | |
| pipewire \ | |
| pipewire-bin \ | |
| pkg-config \ | |
| python3 \ | |
| python3-dev \ | |
| python3-gi \ | |
| python3-numpy \ | |
| python3-pip \ | |
| python3-setuptools \ | |
| python3-venv \ | |
| wireplumber | |
| - name: Build source environment and run headless PipeWire smoke | |
| run: tools/run_headless_pipewire_runtime_smoke_ci.sh | |
| live-ui-runtime-smoke: | |
| needs: changes | |
| if: ${{ github.event_name == 'workflow_dispatch' && inputs.live_ui_runtime_smoke }} | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 90 | |
| steps: | |
| - name: Require change detection | |
| if: ${{ needs.changes.result != 'success' }} | |
| run: exit 1 | |
| - name: Check out repository | |
| uses: actions/checkout@v6 | |
| - name: Install live UI runtime dependencies | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y \ | |
| appstream \ | |
| at-spi2-core \ | |
| build-essential \ | |
| dbus-user-session \ | |
| desktop-file-utils \ | |
| gir1.2-adw-1 \ | |
| gir1.2-gtk-4.0 \ | |
| git \ | |
| gnome-shell \ | |
| gobject-introspection \ | |
| libebur128-1 \ | |
| libgirepository1.0-dev \ | |
| libglib2.0-dev \ | |
| libpipewire-0.3-dev \ | |
| libspa-0.2-modules \ | |
| meson \ | |
| ninja-build \ | |
| pipewire \ | |
| pipewire-bin \ | |
| pkg-config \ | |
| python3 \ | |
| python3-cairo \ | |
| python3-dev \ | |
| python3-gi \ | |
| python3-numpy \ | |
| python3-pip \ | |
| python3-pyatspi \ | |
| python3-setuptools \ | |
| python3-venv \ | |
| patchelf \ | |
| wireplumber | |
| - name: Build source environment and run live UI smoke | |
| run: tools/run_live_ui_runtime_smoke_ci.sh |