diff --git a/.github/actions/setup-mojo/action.yml b/.github/actions/setup-mojo/action.yml new file mode 100644 index 0000000..8ad1c8b --- /dev/null +++ b/.github/actions/setup-mojo/action.yml @@ -0,0 +1,18 @@ +name: Setup Mojo with Pixi +description: Install pixi, activate the Mojo environment, and build the argmojo package + +runs: + using: composite + steps: + - uses: prefix-dev/setup-pixi@v0.9.5 + with: + cache: true + activate-environment: true + - name: Build package (with retry) + shell: bash + run: | + for attempt in 1 2 3; do + if pixi run package; then break; fi + if [ "$attempt" -eq 3 ]; then exit 1; fi + sleep 5 + done diff --git a/.github/workflows/run_tests.yaml b/.github/workflows/run_tests.yaml index a6eed85..57ff7d3 100644 --- a/.github/workflows/run_tests.yaml +++ b/.github/workflows/run_tests.yaml @@ -10,44 +10,34 @@ permissions: contents: read pull-requests: read -jobs: - testing-argmojo: - name: Test with ${{ matrix.os }} - strategy: - fail-fast: false - matrix: - os: ["macos-latest"] - - runs-on: ${{ matrix.os }} - timeout-minutes: 15 - - defaults: - run: - shell: bash - env: - DEBIAN_FRONTEND: noninteractive +defaults: + run: + shell: bash +jobs: + # ── Job 1: Format + Package ──────────────────────────────────────────── + # If this job fails, the later test jobs will be skipped, + # so we can save time by checking formatting and packaging first. + build: + name: Build & Format + runs-on: macos-latest + timeout-minutes: 10 steps: - - name: Checkout repo - uses: actions/checkout@v4 - - - name: Install pixi + - uses: actions/checkout@v4 + - uses: prefix-dev/setup-pixi@v0.9.5 + with: + cache: true + - name: Format check run: | - curl -fsSL https://pixi.sh/install.sh | sh - - - name: Add pixi to PATH - run: | - echo "PIXI_HOME=$HOME/.pixi" >> $GITHUB_ENV - echo "$HOME/.pixi/bin" >> $GITHUB_PATH - - - name: Pixi install - run: | - pixi install - - - name: Build package (with retry for Mojo compiler intermittent crashes) + pixi run format + if ! git diff --exit-code; then + echo "::error::Code is not formatted. Run 'pixi run format' locally." + exit 1 + fi + - name: Build package (with retry) run: | for attempt in 1 2 3; do - echo "=== mojo package attempt $attempt ===" + echo "=== package attempt $attempt ===" if pixi run package; then echo "=== package succeeded on attempt $attempt ===" break @@ -60,11 +50,22 @@ jobs: sleep 5 done - - name: Run tests (with retry for Mojo compiler intermittent crashes) + # ── Job 2: Core parsing tests ────────────────────────────────────────── + test-core: + name: "Test: Core Parsing" + needs: build + runs-on: macos-latest + timeout-minutes: 15 + steps: + - uses: actions/checkout@v4 + - uses: ./.github/actions/setup-mojo + - name: Run core tests (with retry) run: | for attempt in 1 2 3; do echo "=== test attempt $attempt ===" - if pixi run test; then + if mojo run -I src -D ASSERT=all tests/test_parse.mojo \ + && mojo run -I src -D ASSERT=all tests/test_options.mojo \ + && mojo run -I src -D ASSERT=all tests/test_groups.mojo; then echo "=== tests passed on attempt $attempt ===" break fi @@ -76,7 +77,74 @@ jobs: sleep 5 done - - name: Run example binaries in debug mode (catches developer-facing validation errors) + # ── Job 3: Feature tests ─────────────────────────────────────────────── + test-features: + name: "Test: Features" + needs: build + runs-on: macos-latest + timeout-minutes: 15 + steps: + - uses: actions/checkout@v4 + - uses: ./.github/actions/setup-mojo + - name: Run feature tests (with retry) + run: | + for attempt in 1 2 3; do + echo "=== test attempt $attempt ===" + if mojo run -I src -D ASSERT=all tests/test_help.mojo \ + && mojo run -I src -D ASSERT=all tests/test_completion.mojo \ + && mojo run -I src -D ASSERT=all tests/test_interactive.mojo < /dev/null \ + && mojo run -I src -D ASSERT=all tests/test_wrappers.mojo; then + echo "=== tests passed on attempt $attempt ===" + break + fi + if [ "$attempt" -eq 3 ]; then + echo "=== tests failed after 3 attempts ===" + exit 1 + fi + echo "=== test run crashed, retrying in 5s... ===" + sleep 5 + done + + # ── Job 4: Declarative API tests ─────────────────────────────────────── + test-declarative: + name: "Test: Declarative API" + needs: build + runs-on: macos-latest + timeout-minutes: 15 + steps: + - uses: actions/checkout@v4 + - uses: ./.github/actions/setup-mojo + - name: Run declarative tests (with retry) + run: | + for attempt in 1 2 3; do + echo "=== test attempt $attempt ===" + if mojo run -I src -D ASSERT=all tests/test_declarative.mojo \ + && mojo run -I src -D ASSERT=all tests/test_hybrid.mojo \ + && mojo run -I src -D ASSERT=all tests/test_subcommands.mojo \ + && mojo run -I src -D ASSERT=all tests/test_subcommands_declarative.mojo \ + && mojo run -I src -D ASSERT=all tests/test_schema_validation.mojo \ + && bash tests/check_schema_errors.sh; then + echo "=== tests passed on attempt $attempt ===" + break + fi + if [ "$attempt" -eq 3 ]; then + echo "=== tests failed after 3 attempts ===" + exit 1 + fi + echo "=== test run crashed, retrying in 5s... ===" + sleep 5 + done + + # ── Job 5: Example binaries ──────────────────────────────────────────── + test-examples: + name: "Test: Examples" + needs: build + runs-on: macos-latest + timeout-minutes: 15 + steps: + - uses: actions/checkout@v4 + - uses: ./.github/actions/setup-mojo + - name: Run example binaries (with retry) run: | for attempt in 1 2 3; do echo "=== debug attempt $attempt ==="