Skip to content

ci: skip the gate on doc/.dev-only pushes (paths-ignore) #89

ci: skip the gate on doc/.dev-only pushes (paths-ignore)

ci: skip the gate on doc/.dev-only pushes (paths-ignore) #89

Workflow file for this run

# CI — the host-local gate on the supported OSes (macOS arm64 + Linux x86_64),
# mirroring the local gate. Each matrix leg runs `scripts/ci_gate.sh`, so CI
# verifies exactly what the maintainer runs per host (single source of truth).
#
# Triggers: pull_request (any target) + push to `main` + manual dispatch.
# The gate has no external runtime dependency beyond Zig 0.16.0 and python3
# (preinstalled on GitHub runners); `zig build -Dwasm` fetches the embedded
# zwasm engine + the zlinter dev-dep from git over the network.
#
# Two-tier, matching the local ADR-0107 (smoke per commit, full batched) +
# ADR-0049 (the Linux full gate is batched, not per-commit) disciplines so CI is
# not wasteful:
# push to main / PR → fast CORE (units + F-012 diff oracle, no e2e shell suite).
# nightly schedule / manual dispatch → FULL gate (+ every e2e step).
# The Zig toolchain, the fetched deps (zwasm/zlinter), and the build cache are
# all preserved across runs (actions/cache), so a warm run rebuilds only what
# changed instead of three cold ReleaseSafe builds — the dominant cost.
name: ci
on:
# Skip CI on doc/scaffolding-only pushes (markdown, .dev/ ledger + ADRs + notes):
# they cannot change build/test outcome, so a ~15-min gate on them is pure waste.
# A commit that also touches src / scripts / build.zig* / flake.nix / .github /
# a root data-yaml still runs (paths-ignore skips only when ALL changed files match).
pull_request:
paths-ignore: ['**/*.md', '.dev/**']
push:
branches: [main]
paths-ignore: ['**/*.md', '.dev/**']
workflow_dispatch:
schedule:
# Nightly full gate (03:17 UTC) — the batched Linux full-e2e coverage that
# ADR-0049 keeps off the per-commit path.
- cron: '17 3 * * *'
permissions:
contents: read
concurrency:
group: ci-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
gate:
name: gate (${{ matrix.name }})
runs-on: ${{ matrix.runs-on }}
timeout-minutes: 75
strategy:
fail-fast: false
matrix:
include:
- name: aarch64-macos
runs-on: macos-15
zig-dir: zig-aarch64-macos-0.16.0
- name: x86_64-linux
runs-on: ubuntu-22.04
zig-dir: zig-x86_64-linux-0.16.0
steps:
- name: Checkout
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
with:
ref: ${{ github.sha }}
- name: Cache Zig 0.16.0
id: cache-zig
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
with:
path: ~/.local/zig-0.16.0
key: zig-0.16.0-${{ matrix.name }}
- name: Install Zig 0.16.0
if: steps.cache-zig.outputs.cache-hit != 'true'
shell: bash
run: |
set -euo pipefail
source .github/versions.lock
mkdir -p ~/.local
curl -fsSL "https://ziglang.org/download/${ZIG_VERSION}/${{ matrix.zig-dir }}.tar.xz" -o /tmp/zig.tar.xz
tar -xJf /tmp/zig.tar.xz -C ~/.local
mv "$HOME/.local/${{ matrix.zig-dir }}" "$HOME/.local/zig-0.16.0"
- name: Add Zig to PATH
shell: bash
run: echo "$HOME/.local/zig-0.16.0" >> "$GITHUB_PATH"
- name: Pin Zig global cache dir
shell: bash
run: echo "ZIG_GLOBAL_CACHE_DIR=$HOME/.cache/zig" >> "$GITHUB_ENV"
# Cache the fetched deps (zwasm git dep + zlinter, under the global cache's
# p/) AND the build artifacts (global cache + the repo-local .zig-cache),
# keyed on the manifests. A same-manifest run restores everything; a
# manifest change falls back via restore-keys to the newest prior cache and
# rebuilds incrementally (Zig's cache is content-addressed, so a stale
# restore is safe — it only ever causes a rebuild, never a wrong build).
- name: Cache Zig deps + build
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
with:
path: |
~/.cache/zig
.zig-cache
key: ${{ matrix.name }}-zigbuild-${{ hashFiles('build.zig.zon', 'build.zig') }}
restore-keys: |
${{ matrix.name }}-zigbuild-
# ripgrep is the one gate-script tool not universally preinstalled
# (check_debt_id_refs.sh). Install only if absent (fast no-op when the
# runner image already ships it). The other former gaps are removed at the
# source: check_test_reach uses a portable read loop (not bash-4 mapfile),
# and check_corpus_regression falls back timeout→gtimeout→unbounded.
- name: Install ripgrep if missing (gate dep)
shell: bash
run: |
command -v rg >/dev/null 2>&1 && exit 0
if [ "$RUNNER_OS" = "Linux" ]; then
sudo apt-get update -qq && sudo apt-get install -y -qq ripgrep
else
brew install ripgrep
fi
- name: Verify toolchain
shell: bash
run: |
zig version
python3 --version
rg --version | head -1
- name: ci_gate.sh
shell: bash
env:
# nightly schedule + manual dispatch → full gate; push/PR → fast core.
CLJW_CI_FULL: ${{ (github.event_name == 'schedule' || github.event_name == 'workflow_dispatch') && '1' || '0' }}
run: bash scripts/ci_gate.sh