name: Distro Test Matrix on: push: branches: [ main, master ] paths: - 'install.sh' - '**/*.sh' - 'scripts/**' - 'pyproject.toml' - 'uv.lock' - 'requirements/**' - 'src/vocalinux/version.py' - 'vocalinux.desktop' - '.github/workflows/distro-test-matrix.yml' pull_request: branches: [ main, master ] paths: - 'install.sh' - '**/*.sh' - 'scripts/**' - 'pyproject.toml' - 'uv.lock' - 'requirements/**' - 'src/vocalinux/version.py' - 'vocalinux.desktop' - '.github/workflows/distro-test-matrix.yml' workflow_dispatch: permissions: contents: read # Six containers a run, on a filter that any shell script matches: a second # push should not leave the first one's matrix running to completion. concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true jobs: # First, because there is no point spending six containers on a script that # does not parse. syntax: name: Shell syntax runs-on: ubuntu-latest steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: bash -n every shell script we ship run: | set -euo pipefail git ls-files -z '*.sh' | xargs -0 -n1 -t bash -n install: name: install.sh on ${{ matrix.container }} runs-on: ubuntu-latest needs: syntax # A real install pulls the distro's whole GTK and build-toolchain closure # before pip sees a single wheel. timeout-minutes: 45 strategy: # Every distro reports independently: one failing arm is a finding about # that distro, not a reason to lose the other five results. fail-fast: false matrix: # Adding a container here means adding a bootstrap arm to # scripts/install-test.sh; tests/test_installer_gate.py holds the two # lists together. container: - ubuntu:24.04 - ubuntu:26.04 - debian:12 - fedora:42 - archlinux:latest - opensuse/tumbleweed steps: - name: Checkout code uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: # The gate takes the tree with `git archive HEAD`, so it needs the # commit's objects. Shallow is enough; the history is not. fetch-depth: 1 # Not `container:` on the job: that would run every step inside the image # as root, and install.sh refuses to run as root. Docker from the runner # lets the gate create an unprivileged user with sudo instead. - name: Run install.sh unattended in ${{ matrix.container }} run: | set -euo pipefail docker run --rm \ -v "$PWD:$PWD:ro" -e REPO="$PWD" \ "${{ matrix.container }}" \ bash "$PWD/scripts/install-test.sh"