feat(backup): backup stacklet v1: append-only sync to attached APFS disk #2
Workflow file for this run
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
| # Tier 1 of the release gate (docs/agent/dev.md, "Releases"): the checks | |
| # that need no Docker and no macOS. Runs on every push/PR; on version | |
| # tags it additionally enforces that the tag, the CLI VERSION, and | |
| # pyproject.toml all agree. Tiers 2 (integration suite) and 3 (fresh | |
| # install, ai stacklet) stay manual — see docs/cleanup-backlog.md. | |
| name: CI | |
| on: | |
| push: | |
| branches: [main] | |
| tags: ["v*"] | |
| pull_request: | |
| jobs: | |
| checks: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: astral-sh/setup-uv@v5 | |
| - name: Lint (ruff) | |
| run: uvx ruff check . | |
| - name: Lockfile in sync with pyproject.toml | |
| run: uv lock --check | |
| - name: Version consistency | |
| env: | |
| GITHUB_REF: ${{ github.ref }} | |
| run: | | |
| uv run python - <<'EOF' | |
| import os, re, sys, tomllib | |
| def normalize(v: str) -> str: | |
| """PEP-440-ish: v0.3.0-beta.1 / 0.3.0b1 -> 0.3.0b1""" | |
| v = v.strip().lstrip("v").lower() | |
| v = re.sub(r"[-.]?beta[-.]?", "b", v) | |
| v = re.sub(r"[-.]?alpha[-.]?", "a", v) | |
| v = re.sub(r"[-.]?rc[-.]?", "rc", v) | |
| return v | |
| cli = re.search( | |
| r'^VERSION = "([^"]+)"', | |
| open("lib/stack/cli.py").read(), re.M, | |
| ).group(1) | |
| pyproject = tomllib.load(open("pyproject.toml", "rb"))["project"]["version"] | |
| versions = {"lib/stack/cli.py": cli, "pyproject.toml": pyproject} | |
| ref = os.environ.get("GITHUB_REF", "") | |
| if ref.startswith("refs/tags/v"): | |
| versions["tag"] = ref.removeprefix("refs/tags/") | |
| normalized = {src: normalize(v) for src, v in versions.items()} | |
| if len(set(normalized.values())) != 1: | |
| print("Version mismatch:") | |
| for src, v in versions.items(): | |
| print(f" {src}: {v} (normalized: {normalized[src]})") | |
| sys.exit(1) | |
| print("Versions agree:", ", ".join(f"{s}={v}" for s, v in versions.items())) | |
| EOF | |
| - name: Framework tests | |
| run: uv run --extra test pytest tests/framework/ --ignore=tests/framework/test_config_to_container.py -q | |
| - name: Stacklet tests | |
| run: uv run --extra test pytest tests/stacklets/ -q |