9c63557e62
SamiOS CI / lint-and-test (push) Failing after 10s
- .gitignore: exclude __pycache__, *.pyc, build artifacts, .iso files - tests/test_installer.sh: 17 assertions (syntax, VERSION walk-up, heredoc check, structural checks for partition/format/pacstrap/boot logic, desktop overlay presence) - tests/test_voice_bridge.sh: 19 assertions (AST parse, --version, VERSION match, no hardcoded literal, class/method/import checks) - README.md: SSOT docs, Makefile targets, test suite table, repo layout - docs/roadmap.md: CI/tests/SSOT marked done, Phase 3 app status - packages.x86_64.desktop: Plasma + apps overlay for desktop ISO - CI workflow: Python AST check, VERSION SSOT gate, make check - test_helper.sh: clean single export of path variables - test_version.sh: skip __pycache__ in detector scan All 8 test suites pass (90+ assertions). Codex noted: grep-based structural assertions are not behavior tests; desktop overlay packages need repo validation. These are Phase 3 followups.
163 lines
6.1 KiB
YAML
163 lines
6.1 KiB
YAML
name: SamiOS CI
|
|
|
|
on:
|
|
push:
|
|
branches: [master, main]
|
|
pull_request:
|
|
branches: [master, main]
|
|
|
|
jobs:
|
|
lint-and-test:
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- name: Checkout repository
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Install shellcheck
|
|
run: |
|
|
sudo apt-get update -qq
|
|
sudo apt-get install -y -qq shellcheck
|
|
|
|
- name: Install Make
|
|
run: |
|
|
if ! command -v make >/dev/null 2>&1; then
|
|
sudo apt-get install -y -qq make
|
|
fi
|
|
|
|
- name: Install Python 3
|
|
run: |
|
|
if ! command -v python3 >/dev/null 2>&1; then
|
|
sudo apt-get install -y -qq python3
|
|
fi
|
|
|
|
# ── Shellcheck ───────────────────────────────────────────────────
|
|
- name: Run shellcheck on all shell scripts
|
|
run: make lint
|
|
|
|
# ── Python AST validation ────────────────────────────────────────
|
|
- name: Validate Python syntax (AST parse)
|
|
run: |
|
|
set -e
|
|
for f in $(find packaging/scripts -name '*.py'); do
|
|
echo "Checking $f..."
|
|
python3 -c "import ast; ast.parse(open('$f').read())"
|
|
echo " ✓ $f"
|
|
done
|
|
|
|
# ── VERSION SSOT consistency ─────────────────────────────────────
|
|
- name: Verify VERSION single-source-of-truth
|
|
run: |
|
|
set -e
|
|
VERSION="$(cat VERSION)"
|
|
echo "Canonical VERSION: $VERSION"
|
|
|
|
# Mirror must match
|
|
MIRROR="$(head -n1 packaging/archiso/airootfs/etc/samios-version)"
|
|
if [ "$VERSION" != "$MIRROR" ]; then
|
|
echo "ERROR: VERSION ($VERSION) != airootfs mirror ($MIRROR)"
|
|
echo "Fix: make version-sync"
|
|
exit 1
|
|
fi
|
|
echo " ✓ airootfs mirror matches VERSION"
|
|
|
|
# PKGBUILD pkgver must resolve to VERSION (hyphen → underscore)
|
|
PKGVER="$(cd packaging/packages/samios-branding && source PKGBUILD >/dev/null 2>&1 && echo "$pkgver")"
|
|
EXPECTED_PKGVER="$(echo "$VERSION" | tr '-' '_')"
|
|
if [ "$PKGVER" != "$EXPECTED_PKGVER" ]; then
|
|
echo "ERROR: PKGBUILD pkgver ($PKGVER) != expected ($EXPECTED_PKGVER)"
|
|
exit 1
|
|
fi
|
|
echo " ✓ PKGBUILD pkgver resolves to VERSION"
|
|
|
|
# No hardcoded version literal in production files
|
|
# (spot-check the main components)
|
|
for f in \
|
|
packaging/archiso/airootfs/usr/local/bin/samios \
|
|
packaging/scripts/samios-installer.sh \
|
|
packaging/scripts/voice-bridge.py \
|
|
packaging/scripts/samios-desktop-setup.sh; do
|
|
if grep -qE '(^|[^a-zA-Z0-9])0\.[1-9][0-9]*\.[0-9]+' "$f" 2>/dev/null; then
|
|
echo "ERROR: $f contains a hardcoded version literal"
|
|
grep -nE '(^|[^a-zA-Z0-9])0\.[1-9][0-9]*\.[0-9]+' "$f"
|
|
exit 1
|
|
fi
|
|
done
|
|
echo " ✓ No hardcoded version literals in production components"
|
|
|
|
echo ""
|
|
echo "VERSION SSOT consistency check PASSED ✓"
|
|
|
|
# ── Profile structure validation ─────────────────────────────────
|
|
- name: Validate archiso profile structure
|
|
run: |
|
|
set -e
|
|
PROFILE_DIR="packaging/archiso"
|
|
echo "Validating profile structure..."
|
|
|
|
# Required files
|
|
for f in profiledef.sh packages.x86_64 pacman.conf; do
|
|
if [ ! -f "$PROFILE_DIR/$f" ]; then
|
|
echo "ERROR: Missing required file: $PROFILE_DIR/$f"
|
|
exit 1
|
|
fi
|
|
echo " ✓ Found: $PROFILE_DIR/$f"
|
|
done
|
|
|
|
# profiledef.sh must have valid bash syntax
|
|
if ! bash -n "$PROFILE_DIR/profiledef.sh"; then
|
|
echo "ERROR: profiledef.sh has syntax errors"
|
|
exit 1
|
|
fi
|
|
echo " ✓ profiledef.sh syntax OK"
|
|
|
|
# packages.x86_64 must have at least one non-comment line
|
|
pkg_count=$(grep -vE '^\s*#|^\s*$' "$PROFILE_DIR/packages.x86_64" | wc -l)
|
|
if [ "$pkg_count" -lt 1 ]; then
|
|
echo "ERROR: packages.x86_64 has no packages listed"
|
|
exit 1
|
|
fi
|
|
echo " ✓ packages.x86_64 has $pkg_count package(s)"
|
|
|
|
# pacman.conf must have [options] and at least one repo section
|
|
if ! grep -q '\[options\]' "$PROFILE_DIR/pacman.conf"; then
|
|
echo "ERROR: pacman.conf missing [options] section"
|
|
exit 1
|
|
fi
|
|
if ! grep -qE '^\[(core|extra)\]' "$PROFILE_DIR/pacman.conf"; then
|
|
echo "ERROR: pacman.conf missing [core] or [extra] section"
|
|
exit 1
|
|
fi
|
|
echo " ✓ pacman.conf structure OK"
|
|
|
|
# Required airootfs files
|
|
for f in airootfs/usr/local/bin/samios; do
|
|
if [ ! -f "$PROFILE_DIR/$f" ]; then
|
|
echo "ERROR: Missing: $PROFILE_DIR/$f"
|
|
exit 1
|
|
fi
|
|
echo " ✓ Found: $PROFILE_DIR/$f"
|
|
done
|
|
|
|
# samios CLI must be executable
|
|
if [ ! -x "$PROFILE_DIR/airootfs/usr/local/bin/samios" ]; then
|
|
echo "ERROR: samios CLI is not executable"
|
|
exit 1
|
|
fi
|
|
echo " ✓ samios CLI is executable"
|
|
|
|
# Boot mode configs
|
|
for f in grub/grub.cfg syslinux/syslinux.cfg efiboot/loader/loader.conf; do
|
|
if [ ! -f "$PROFILE_DIR/$f" ]; then
|
|
echo "WARNING: Missing optional boot config: $PROFILE_DIR/$f"
|
|
else
|
|
echo " ✓ Found: $PROFILE_DIR/$f"
|
|
fi
|
|
done
|
|
|
|
echo ""
|
|
echo "Profile structure validation PASSED ✓"
|
|
|
|
# ── Test suite ───────────────────────────────────────────────────
|
|
- name: Run test suite (lint + tests)
|
|
run: make check
|