test: mock importlib.metadata.version in LocaleSync version test #7
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: | |
| branches: [main] | |
| permissions: | |
| contents: read | |
| env: | |
| PYTHON_VERSION: "3.13" | |
| jobs: | |
| lint: | |
| name: Lint & Format | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-python@v5 | |
| with: | |
| python-version: ${{ env.PYTHON_VERSION }} | |
| - name: Install dependencies | |
| run: pip install -e ".[dev]" | |
| - name: Ruff lint | |
| run: python -m ruff check src/ tests/ | |
| - name: Ruff format check | |
| run: python -m ruff format --check src/ tests/ | |
| test: | |
| name: Test (Python ${{ matrix.python-version }}) | |
| runs-on: ubuntu-latest | |
| strategy: | |
| matrix: | |
| python-version: ["3.12", "3.13"] | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-python@v5 | |
| with: | |
| python-version: ${{ matrix.python-version }} | |
| - name: Install dependencies | |
| run: pip install -e ".[dev]" | |
| - name: Run tests | |
| run: python -m pytest tests/ -v --tb=short --junitxml=test-results.xml | |
| - name: Upload test results | |
| if: always() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: test-results-py${{ matrix.python-version }} | |
| path: test-results.xml | |
| validate-config: | |
| name: Validate Configs | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-python@v5 | |
| with: | |
| python-version: ${{ env.PYTHON_VERSION }} | |
| - name: Install dependencies | |
| run: pip install -e ".[dev]" | |
| - name: Validate manifest YAML | |
| run: | | |
| python -c " | |
| from opsportal.config.manifest import load_manifest | |
| from pathlib import Path | |
| m = load_manifest(Path('opsportal.yaml'), Path('.'), Path('work/tools')) | |
| print(f'Manifest OK: {len(m.enabled_tools)} tool(s) registered') | |
| for t in m.enabled_tools: | |
| src = f' [source: {t.source.repository}@{t.source.ref}]' if t.source else '' | |
| print(f' - {t.slug} ({t.integration_mode}){src}') | |
| " | |
| build: | |
| name: Build Package | |
| runs-on: ubuntu-latest | |
| needs: [lint, test] | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-python@v5 | |
| with: | |
| python-version: ${{ env.PYTHON_VERSION }} | |
| - name: Install build tools | |
| run: pip install build | |
| - name: Build wheel | |
| run: python -m build | |
| - name: Upload artifacts | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: dist | |
| path: dist/ | |
| verify-install: | |
| name: Verify Installed Package | |
| runs-on: ubuntu-latest | |
| needs: [build] | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-python@v5 | |
| with: | |
| python-version: ${{ env.PYTHON_VERSION }} | |
| - name: Download built wheel | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: dist | |
| path: dist/ | |
| - name: Install from wheel (not editable) | |
| run: pip install dist/*.whl | |
| - name: Verify CLI entrypoint exists | |
| run: | | |
| which opsportal | |
| opsportal version | |
| - name: Verify package metadata | |
| run: | | |
| python -c " | |
| from importlib.metadata import version, entry_points | |
| v = version('opsportal') | |
| print(f'Installed version: {v}') | |
| eps = [ep for ep in entry_points() if ep.group == 'console_scripts' and ep.name == 'opsportal'] | |
| assert len(eps) == 1, f'Expected 1 opsportal entrypoint, got {len(eps)}' | |
| print(f'Entrypoint: {eps[0]}') | |
| " | |
| - name: Verify static assets are packaged | |
| run: | | |
| python -c " | |
| from pathlib import Path | |
| import opsportal.ui | |
| ui_dir = Path(opsportal.ui.__file__).parent | |
| templates = ui_dir / 'templates' | |
| static = ui_dir / 'static' | |
| assert templates.is_dir(), f'Templates dir missing: {templates}' | |
| assert static.is_dir(), f'Static dir missing: {static}' | |
| assert (templates / 'home.html').is_file(), 'home.html missing' | |
| assert (templates / 'base.html').is_file(), 'base.html missing' | |
| assert (static / 'css' / 'portal-base.css').is_file(), 'portal-base.css missing' | |
| assert (static / 'js' / 'portal.js').is_file(), 'portal.js missing' | |
| print(f'Templates: {list(templates.glob(\"*.html\"))}') | |
| print(f'Static CSS: {list((static / \"css\").glob(\"*\"))}') | |
| print(f'Static JS: {list((static / \"js\").glob(\"*\"))}') | |
| print('All static assets verified') | |
| " | |
| - name: Verify manifest bootstrap | |
| run: | | |
| python -c " | |
| from pathlib import Path | |
| from opsportal.config.manifest import DEFAULT_MANIFEST_YAML, load_manifest | |
| p = Path('/tmp/test-manifest.yaml') | |
| p.write_text(DEFAULT_MANIFEST_YAML) | |
| m = load_manifest(p, Path('/tmp'), Path('/tmp/tools')) | |
| assert len(m.enabled_tools) == 2, f'Expected 2 tools, got {len(m.enabled_tools)}' | |
| slugs = {t.slug for t in m.enabled_tools} | |
| assert 'releasepilot' in slugs, 'releasepilot not found' | |
| assert 'releaseboard' in slugs, 'releaseboard not found' | |
| for t in m.enabled_tools: | |
| assert t.source is not None, f'{t.slug} missing source' | |
| assert t.port is not None, f'{t.slug} missing port' | |
| print('Manifest bootstrap verified') | |
| " | |
| - name: Verify opsportal init command | |
| run: | | |
| cd /tmp | |
| opsportal init test-portal.yaml | |
| test -f test-portal.yaml | |
| echo "Init command verified ✔" | |
| deploy-smoke: | |
| name: Deploy Smoke Test | |
| runs-on: ubuntu-latest | |
| needs: [build] | |
| if: github.ref == 'refs/heads/main' | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-python@v5 | |
| with: | |
| python-version: ${{ env.PYTHON_VERSION }} | |
| - name: Install OpsPortal from source | |
| run: pip install ".[dev]" | |
| - name: Install managed tools from remote sources | |
| run: | | |
| pip install "git+https://github.com/POLPROG-TECH/ReleasePilot.git@v1.1.0[all]" || echo "ReleasePilot install skipped (may not be public)" | |
| pip install "git+https://github.com/POLPROG-TECH/ReleaseBoard.git@v1.1.0" || echo "ReleaseBoard install skipped (may not be public)" | |
| - name: Verify CLI entrypoints | |
| run: | | |
| opsportal version | |
| releasepilot --version || echo "ReleasePilot CLI not available" | |
| releaseboard --version || echo "ReleaseBoard CLI not available" | |
| - name: Verify setup command | |
| run: | | |
| cd /tmp | |
| opsportal setup --manifest /tmp/smoke-test.yaml | |
| test -f /tmp/smoke-test.yaml | |
| echo "Setup command verified ✔" |