Skip to content

CI: fix ModuleNotFoundError: gi by switching to system-site-packages venv #5

CI: fix ModuleNotFoundError: gi by switching to system-site-packages venv

CI: fix ModuleNotFoundError: gi by switching to system-site-packages venv #5

Workflow file for this run

name: Interface Tests
on:
push:
branches: [main]
pull_request:
schedule:
# Nightly drift check at 05:30 UTC — 1.5h after upstream-sync rebases
# the forks at 04:00 UTC. The GUI smoke suite against fresh upstream
# catches Gtk/at-spi/accessibility-tree regressions before a human PR
# lands on them. Staggered 30min after unit-tests.yml to smooth load.
- cron: '30 5 * * *'
workflow_dispatch:
inputs:
gramps_repo:
description: 'gramps repo (owner/name); empty = same-owner fork'
default: ''
gramps_ref:
description: 'gramps branch/tag/sha; empty = matrix defaults'
default: ''
addons_source_repo:
description: 'addons-source repo (owner/name); empty = same-owner fork'
default: ''
addons_ref:
description: 'addons-source branch/tag/sha'
default: 'maintenance/gramps60'
addon_name:
description: 'Single addon to build (empty = all)'
default: ''
jobs:
gui-tests:
runs-on: ubuntu-24.04
timeout-minutes: 30
# Blocking gate. The interface smoke suite is the testbed's primary
# reason to exist (see CLAUDE.md: "Get tests/interface/test_smoke.py
# passing locally and in CI before adding any other tests") — any
# failure must stop a merge. No continue-on-error here, by design.
strategy:
fail-fast: false
matrix:
# Supported Gramps minors. Add new maintenance branches here when
# they exist upstream (e.g. - maintenance/gramps61) — each entry
# produces a parallel job. Kept in sync with unit-tests.yml.
gramps_ref:
- maintenance/gramps60
steps:
- name: Checkout testbed
uses: actions/checkout@v4
with:
path: gramps-testbed
# Repo resolution (in order): workflow input → repository variable
# → same-owner fork (auto-derived from this testbed's owner, so
# forking the testbed to you/gramps-testbed just works if you also
# have you/gramps and you/addons-source). Ref resolution: workflow
# input → matrix cell.
- name: Checkout gramps fork
uses: actions/checkout@v4
with:
repository: ${{ github.event.inputs.gramps_repo || vars.GRAMPS_REPO || format('{0}/gramps', github.repository_owner) }}
ref: ${{ github.event.inputs.gramps_ref || matrix.gramps_ref }}
path: gramps
- name: Checkout addons-source fork
uses: actions/checkout@v4
with:
repository: ${{ github.event.inputs.addons_source_repo || vars.ADDONS_SOURCE_REPO || format('{0}/addons-source', github.repository_owner) }}
ref: ${{ github.event.inputs.addons_ref || vars.ADDONS_SOURCE_REF || 'maintenance/gramps60' }}
path: addons-source
- name: Checkout addons (upstream, publish target for make.py)
uses: actions/checkout@v4
with:
repository: gramps-project/addons
path: addons
- name: Install system dependencies
# python3-venv / python3-pip are installed here so the next step
# can build a venv that inherits python3-gi and python3-pyatspi
# from the system interpreter.
run: |
sudo apt-get update
sudo apt-get install -y --no-install-recommends \
python3 python3-venv python3-pip \
python3-gi python3-gi-cairo python3-cairo python3-pyatspi python3-icu \
gir1.2-gtk-3.0 gir1.2-osmgpsmap-1.0 gir1.2-goocanvas-2.0 gir1.2-gexiv2-0.10 \
libgirepository1.0-dev \
xvfb dbus-x11 at-spi2-core \
xdotool wmctrl \
gettext intltool \
librsvg2-common
- name: Set up Python venv (inherits python3-gi / python3-pyatspi from apt)
# Ubuntu 24.04's apt python3-gi and python3-pyatspi install into
# the system Python's dist-packages only; a fresh interpreter from
# setup-python@v5 can't see those bindings, and gramps.gen imports
# gi on module load — so every gramps-touching command dies with
# ModuleNotFoundError. dogtail (GUI driver) also requires pyatspi
# at the same interpreter. --system-site-packages keeps pip
# installs in the venv but inherits apt-provided bindings.
# Replaces actions/setup-python@v5; pip cache is restored below
# via actions/cache.
run: |
python3 -m venv --system-site-packages .venv
echo "$GITHUB_WORKSPACE/.venv/bin" >> "$GITHUB_PATH"
.venv/bin/python -m pip install --upgrade pip
- name: Restore pip cache
uses: actions/cache@v4
with:
path: ~/.cache/pip
key: pip-${{ runner.os }}-${{ hashFiles('gramps-testbed/requirements-test.txt') }}
restore-keys: |
pip-${{ runner.os }}-
- name: Install Python dependencies
run: |
pip install -r gramps-testbed/requirements-test.txt
pip install -e 'gramps[testing]'
- name: Compile Gramps translations
# pip install -e skips setup.py build, so Gramps' build/mo dir is
# empty. Compile .po → .mo directly with msgfmt so launched Gramps
# finds its translations instead of falling back with a warning.
working-directory: gramps
run: |
for po in po/*.po; do
lang=$(basename "$po" .po)
dest="build/mo/$lang/LC_MESSAGES"
mkdir -p "$dest"
msgfmt "$po" -o "$dest/gramps.mo"
done
# Addons are intentionally not built or installed for the smoke suite:
# make.py mutates tracked .gpr.py files, and installing all 149 addons
# blocks Gramps GUI startup during plugin registration. The addon_name
# workflow input remains reserved for a future addon-aware job.
- name: Seed example database
run: |
gramps -C TestTree -i gramps/example/gramps/example.gramps
- name: Run interface tests
working-directory: gramps-testbed
env:
ARTIFACTS_DIR: ${{ github.workspace }}/artifacts
run: |
mkdir -p test-results "$ARTIFACTS_DIR/screenshots"
xvfb-run -a --server-args="-screen 0 1920x1080x24" \
dbus-run-session -- bash -c '
gsettings set org.gnome.desktop.interface toolkit-accessibility true
/usr/libexec/at-spi-bus-launcher --launch-immediately &
sleep 2
python -m xmlrunner discover \
-s tests -p "test_*.py" \
-o test-results/ \
-v
'
- name: Upload test results
if: always()
uses: actions/upload-artifact@v4
with:
# Matrix-scoped artifact name so parallel cells don't collide.
name: test-results-${{ strategy.job-index }}
path: |
gramps-testbed/test-results/
artifacts/
- name: Publish test report
if: always()
uses: dorny/test-reporter@v1
with:
# working-directory is mandatory here: none of our checkouts
# land at the workflow root (all use `path:` subdirs), so
# dorny's internal `git ls-files` fails with "not a git
# repository" unless we point it at a checkout. The testbed
# itself is the natural anchor; path is resolved relative to
# it, so the glob drops its `gramps-testbed/` prefix.
working-directory: gramps-testbed
name: Interface Tests (${{ matrix.gramps_ref }})
path: test-results/*.xml
reporter: java-junit