Skip to content

SciQLop compatibility smoke #12

SciQLop compatibility smoke

SciQLop compatibility smoke #12

Workflow file for this run

name: SciQLop compatibility smoke
# Verifies each plugin imports cleanly and that its `load(main_window)`
# entry-point runs against a real SciQLopMainWindow built from a
# configurable SciQLop ref. Catches API-contract breakage before a SciQLop
# release ships — e.g. signature changes on CatalogProvider, removal of an
# attribute plugins relied on, etc.
#
# Default: smokes against SciQLop `main`. Use the workflow_dispatch input
# to point it at a specific pre-release (`0.12.0.dev0`), tagged version,
# or commit SHA.
on:
push:
workflow_dispatch:
inputs:
sciqlop_ref:
description: "SciQLop git ref / PyPI version (e.g. main, 0.12.0.dev0, abcdef1)"
default: main
required: true
schedule:
# weekly against main so regressions surface even without a plugin push
- cron: "0 6 * * 1"
jobs:
smoke:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
plugin:
- { dir: sciqlop_albert, pkg: sciqlop_albert }
- { dir: sciqlop_claude, pkg: sciqlop_claude }
- { dir: sciqlop_copilot, pkg: sciqlop_copilot }
- { dir: sciqlop_msa, pkg: sciqlop_msa }
- { dir: sciqlop_radio, pkg: sciqlop_radio }
- { dir: cdf_workbench, pkg: cdf_workbench }
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.13"
- name: Install OS deps
run: |
sudo apt-get update
sudo apt-get install -y xvfb libatomic1 libglx-dev libegl-dev \
libxrandr2 libxss1 libxcursor1 libxcomposite1 libasound2-dev \
libxi6 libxtst6 libglib2.0-bin libdbus-1-3 libxdamage1 \
libxkbcommon-x11-0 libxcb-cursor0 libxcb-icccm4 libxcb-keysyms1 \
libxcb-shape0 libnss3
- name: Install SciQLop @ ${{ github.event.inputs.sciqlop_ref || 'main' }}
run: |
REF="${{ github.event.inputs.sciqlop_ref || 'main' }}"
# Treat anything matching a semver-ish pattern as a PyPI release
# (e.g. "0.12.0", "0.12.0.dev0", "0.11.4"); everything else is a
# git ref against SciQLop/SciQLop.
if [[ "$REF" =~ ^[0-9]+\.[0-9]+\.[0-9]+([a-z0-9.]*)$ ]]; then
pip install "sciqlop==${REF}"
else
pip install "sciqlop @ git+https://github.com/SciQLop/SciQLop@${REF}"
fi
pip install pytest # some plugins import pytest at top level via tests
- name: Install plugin ${{ matrix.plugin.dir }}
run: pip install ./${{ matrix.plugin.dir }}
- name: Install plugin runtime deps from plugin.json
run: |
python - <<'PY'
import json, subprocess, sys, pathlib
mf = pathlib.Path("${{ matrix.plugin.dir }}/${{ matrix.plugin.pkg }}/plugin.json")
if not mf.exists():
print(f"no plugin.json at {mf} — nothing to install")
sys.exit(0)
deps = json.loads(mf.read_text()).get("python_dependencies", [])
if not deps:
print("plugin.json declares no python_dependencies")
sys.exit(0)
print("Installing:", deps)
subprocess.check_call([sys.executable, "-m", "pip", "install", *deps])
PY
- name: Smoke — import and load(main_window)
env:
# SciQLop's MainWindow embeds a QWebEngineView; under xvfb
# Chromium needs these flags or it segfaults at startup. Same
# flags SciQLop's own CI uses (.github/workflows/tests.yml).
QT_QPA_PLATFORM: xcb
QTWEBENGINE_DISABLE_SANDBOX: "1"
QTWEBENGINE_CHROMIUM_FLAGS: "--disable-gpu --no-sandbox --disable-software-rasterizer --disable-dev-shm-usage"
INSIDE_SCIQLOP: "1"
SPEASY_SKIP_INIT_PROVIDERS: "1"
run: |
mkdir -p test-config test-data test-workspace test-cache
export XDG_CONFIG_HOME="$PWD/test-config"
export XDG_DATA_HOME="$PWD/test-data"
export XDG_CACHE_HOME="$PWD/test-cache"
export SCIQLOP_WORKSPACE_DIR="$PWD/test-workspace"
xvfb-run -a --server-args="-screen 0 1280x1024x24" python - <<'PY'
import sys, importlib
from PySide6 import QtCore
QtCore.QCoreApplication.setAttribute(QtCore.Qt.AA_UseDesktopOpenGL, True)
QtCore.QCoreApplication.setAttribute(QtCore.Qt.AA_ShareOpenGLContexts, True)
from SciQLop.core.sciqlop_application import SciQLopApp
app = SciQLopApp(sys.argv)
# Pre-warm tscat to dodge the same thread race SciQLop's own conftest
# works around. Only matters if the plugin pulls in catalogs.
try:
from tscat.base import backend as _b
_b()
except ImportError:
pass
plugin_pkg = "${{ matrix.plugin.pkg }}"
mod = importlib.import_module(plugin_pkg)
assert hasattr(mod, "load"), f"{plugin_pkg} has no load() entry point"
from SciQLop.core.ui.mainwindow import SciQLopMainWindow
mw = SciQLopMainWindow()
result = mod.load(mw)
print(f"OK — {plugin_pkg}.load() returned {type(result).__name__ if result is not None else 'None'}")
PY