Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
5bb1219
preflight: tiers (fast / lane / module), reach sets, concurrent lanes…
borisbat Sep 5, 2026
0d44741
preflight: the compile sweep splits engine roots onto one serial modu…
borisbat Sep 5, 2026
f8447d0
preflight: lane verdicts parse behind the to_log level prefix, and th…
borisbat Sep 5, 2026
65c6f0c
CI: the job matrices become data, extended_checks splits into two dar…
borisbat Sep 5, 2026
9996f41
tables: a vector or range key hashes the same bytes on every rail, so…
borisbat Sep 5, 2026
4e51770
preflight: a ci-matrix gate runs the workflow matrix test, and the wo…
borisbat Sep 5, 2026
b973a1f
CI: CodeQL stays per PR, the matrix-test rule moves to ci/REVIEW.md, …
borisbat Sep 5, 2026
d869aff
CI: the workflows checklist binds checks, not steps, and the two plat…
borisbat Sep 5, 2026
07de6ca
preflight: the pure predicates move beside their tests, the matrix te…
borisbat Sep 5, 2026
af7f764
tables: KeyHash tells a builtin key from a handled one instead of com…
borisbat Sep 5, 2026
a0b4a1a
review: the workflows, ci and simulate checklists after the exit pass…
borisbat Sep 5, 2026
53eecca
tests-cpp: KeyHash agrees with hash_function for every builtin key ty…
borisbat Sep 5, 2026
d995b23
module cache: the default directory is capped - the oldest records go…
borisbat Sep 5, 2026
5dd1fd3
module cache: the eviction helpers compile only with file IO
borisbat Sep 5, 2026
7c5ef2a
tables: WrapsBuiltinValue's marks live beside the WrapType primary in…
borisbat Sep 5, 2026
199f144
CI: the modules job builds the daslang grammar before the MCP tools test
borisbat Sep 5, 2026
fe1c9a8
CI: the news-region step installs markdown into the interpreter that …
borisbat Sep 5, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 20 additions & 15 deletions .github/workflows/REVIEW.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,26 @@
**Read `REVIEW_COMMON.md` (repo root) first - its contract binds this checklist.**
Architecture doc: `skills/internal/preflight.md` (repo root).

A per-PR gate step is a workflow step that runs on `pull_request` and fails the lane when it
finds a defect; each one enforces its rule automatically, with no reviewer involved
(`skills/internal/preflight.md` sec."doc.yml - the gates", sec."extended_checks.yml").
**A diff that weakens a per-PR check - a step, a matrix cell, or a workflow's `pull_request`
trigger that runs on every pull request and fails the lane when it finds a defect - is a
defect: deleting it, stopping its failure from failing the lane (`continue-on-error`, a
trailing `|| true`, a swallowed exit code), shrinking what it checks, or narrowing its
condition to anything but a `matrix.role` condition that still runs it on every pull request
or the nightly cron.**

**A diff that weakens a per-PR gate step - deletes it, stops its failure failing the lane
(`continue-on-error`, a trailing `|| true`, a swallowed exit code, a narrowed `if:`), or
shrinks what it checks - is a defect; a step the diff adds or changes makes its failure the
lane's failure.**
**A per-PR check the diff adds fails the lane when it finds a defect.**

**A diff that adds or changes a per-PR gate step states a run of the command the diff adds or
changes, on the lane's platform, in its PR body or commit message; a green run of that lane on
the PR's head commit is that evidence.** A step that fails for a non-defect turns a green
branch red for everyone.
**A per-PR check leaves the per-PR path only to the nightly cron (`github.event_name ==
'schedule' || github.event_name == 'workflow_dispatch'`), and the diff either names the
preflight gate - a check `preflight` runs locally before a push - that keeps it per PR
(`skills/internal/preflight.md` sec."extended_checks.yml") or states the platform no per-PR
cell has.** A per-PR job fits 35 minutes; what does not fit moves.

**A diff that adds or changes a step in `pages.yml` that names the deployed games writes
that list as a `for g in <ids>; do` loop.** `examples/games/REVIEW.das` (repo root) reads
the deployed game list from those loops, so a list spelled any other way is one nothing
cross-checks.
**A diff that adds or changes a per-PR check states a run of that check's command, on the
lane's platform, in its PR body or commit message; a green run of that lane on the PR's head
commit is that evidence.** A check that fails for a non-defect turns a green branch red for
everyone.

**A step in `pages.yml` that names the deployed games spells the list as a `for g in <ids>; do`
loop, never inline.** `examples/games/REVIEW.das` (repo root) reads the deployed list from
those loops; an inline list beside a surviving loop is one nothing cross-checks.
202 changes: 36 additions & 166 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,16 @@ on:
# Nightly: runs everything the per-PR lanes deliberately skip —
# * the heavy Windows toolchain builds (mingw, clang-cl), gated OFF per-PR
# below (see their `if:`), including their FULL AOT sweeps;
# * the main matrix (Release cells carry the FULL test_aot build + AOT
# suite — "Slow Release Tests"; Debug cells ride along, matrix can't be
# filtered in a job-level `if`). Per-PR CI only builds test_aot_subset
# (tests/language, part of ALL) as a compile+link gate and runs no AOT
# tests at all.
# * the main matrix in its nightly shape (ci/ci_matrix.py): the per-PR
# cells plus the sanitizer cells and windows 64 Debug, each a 40-55
# minute job over the 35-minute PR budget; the Release cells carry the
# FULL test_aot build + AOT suite — "Slow Release Tests". Per-PR CI only
# builds test_aot_subset (tests/language, part of ALL) as a compile+link
# gate and runs no AOT tests at all (preflight --full's tests-aot lane is
# the pre-push AOT sweep).
# bundle_smoke / gcc stay per-PR-only. A manual `workflow_dispatch` runs
# the FULL workflow: every per-PR job, both toolchains, and the full AOT
# suite.
# the FULL workflow: every per-PR job, both toolchains, the nightly cells,
# and the full AOT suite.
# 02:00 UTC: dead time for EU working hours — the nightly is ~12 jobs and
# must not compete with daytime PR lanes for runners.
- cron: '0 2 * * *'
Expand All @@ -38,6 +40,7 @@ jobs:
# Map a step output to a job output
outputs:
should_skip: ${{ steps.skip_check.outputs.should_skip }}
matrix: ${{ steps.matrix.outputs.matrix }}
steps:
- id: skip_check
uses: fkirc/skip-duplicate-actions@v5
Expand All @@ -46,6 +49,17 @@ jobs:
concurrent_skipping: 'same_content'
do_not_skip: '["pull_request", "workflow_dispatch", "release"]'

# The build matrix is data in ci/ci_matrix.py, evaluated per event here (ci/test_ci_matrix.py pins it).
- uses: actions/checkout@v4
with:
sparse-checkout: ci
- id: matrix
# two statements: a substitution inside echo would hide the script's exit code
run: |
set -eu
matrix=$(python3 ci/ci_matrix.py build '${{ github.event_name }}')
echo "matrix=$matrix" >> "$GITHUB_OUTPUT"

- name: Cache LLVM
uses: actions/cache@v3
id: llvm-cache
Expand All @@ -62,13 +76,12 @@ jobs:
# `schedule` cron the matrix runs too — the Release cells carry the full
# AOT suite (see "Slow Release Tests") — unconditionally on the canonical
# repo (no pre_job skip: master unchanged overnight must still produce the
# nightly AOT signal). Debug cells ride along at night without an AOT step;
# `matrix` context is not available in a job-level `if`, so they can't be
# excluded here (actions runs with a matrix clause fail as a workflow-file
# error before any job spawns).
# nightly AOT signal). The cell list is per event - ci/ci_matrix.py, read
# through pre_job - because `matrix` is not available in a job-level `if`.
if: >-
(github.event_name == 'schedule' && github.repository == 'GaijinEntertainment/daScript')
|| (github.event_name != 'schedule' && needs.pre_job.outputs.should_skip != 'true')
name: "build (${{ matrix.target }}, ${{ matrix.architecture }}, ${{ matrix.cmake_preset }}, ${{ matrix.sanitizers }})"
runs-on: ${{ matrix.runner }}
# actions: write needed for `gh cache delete` in the sccache refresh step.
permissions:
Expand All @@ -79,159 +92,14 @@ jobs:
das_llvm_disabled: 'OFF'
strategy:
fail-fast: false
matrix:
target: [linux, linux_arm, darwin15, darwin26, windows]
architecture: [32, 64, arm64]
cmake_preset: [ Debug, Release ]
sanitizers: [none]

include:
- target: linux
release_target: linux
release_arch: x86_64
runner: ubuntu-latest
archive_ext: tar.gz
sanitizers: none

# Sanitizer matrix — Linux + Release + full tests (dastest + test_aot
# + ctest). Release keeps walltime in budget; the previous Debug+ASAN
# was prohibitive for production CI. See issue #2530.
- target: linux
architecture: 64
runner: ubuntu-latest
cmake_preset: Release
sanitizers: asan
build_name: linux_asan
build_system: cmake
cmake_generator: Ninja

- target: linux
architecture: 64
runner: ubuntu-latest
cmake_preset: Release
sanitizers: tsan
build_name: linux_tsan
build_system: cmake
cmake_generator: Ninja

- target: linux
architecture: 64
runner: ubuntu-latest
cmake_preset: Release
sanitizers: ubsan
build_name: linux_ubsan
build_system: cmake
cmake_generator: Ninja

- target: linux_arm
release_target: linux
release_arch: arm64
runner: ubuntu-24.04-arm
archive_ext: tar.gz

- target: darwin15
architecture: arm64
release_target: darwin15
release_arch: arm64
runner: macos-15 # Apple Silicon arm64, M2
architecture_string: arm64
archive_ext: tar.gz

- target: darwin26
release_target: darwin26
release_arch: arm64
runner: macos-26 # Apple Silicon arm64, M2
architecture_string: arm64
archive_ext: tar.gz

- target: windows
runner: windows-latest
archive_ext: zip

- target: windows
build_system: cmake
cmake_generator: Ninja

- target: darwin15
build_system: cmake
cmake_generator: Ninja

- target: darwin26
build_system: cmake
cmake_generator: Ninja

- target: linux
build_system: cmake
cmake_generator: Ninja

- target: linux_arm
build_system: cmake
cmake_generator: Ninja

- target: windows
release_target: windows
release_arch: x86
architecture: 32
architecture_string: Win32

- target: windows
release_target: windows
release_arch: x86_64
architecture: 64
architecture_string: x64

# The regular Win64 Release lane is the fast MSVC compile/interpreter
# gate. LLVM + the JIT sweep are preserved by the nightly copy below.
- target: windows
architecture: 64
cmake_preset: Release
llvm_disabled: 'ON'
jit_disabled: 'ON'

# Debug Win64 also skips JIT. RelWithDebInfo is a separate
# nightly-only memory/leak diagnostic.
- target: windows
architecture: 64
cmake_preset: Debug
jit_disabled: 'ON'

exclude:
# macOS Intel (darwin15 x86_64) has no prebuilt LLVM.dll (the
# llvm-release workflow doesn't build one) and Apple no longer makes
# new Intel macOS runners worth gating on. Drop entirely.
- target: darwin15
architecture: 64

- target: darwin15
architecture: 32

- target: darwin26
architecture: 32

- target: darwin26
architecture: 64

- target: linux
architecture: 32

- target: linux
architecture: arm64

- target: linux_arm
architecture: 32

- target: linux_arm
architecture: arm64 # todo

- target: windows
architecture: arm64 # todo https://github.com/actions/partner-runner-images/tree/main?tab=readme-ov-file#available-images

# win32 Debug outgrew its test budgets (the interpreter sweep double-times-out at
# 1800s + 5400s on master's own scheduled runs, ~2.5h wall before failing) and the
# 32-bit rail is legacy — win32 Release stays as the 32-bit compile+test gate.
- target: windows
architecture: 32
cmake_preset: Debug
# ci/ci_matrix.py build <event>: Release + Debug on linux, linux_arm, darwin15,
# darwin26; windows 32 Release (the 32-bit compile+test gate - win32 Debug outgrew
# its test budgets) and windows 64 Release (the fast MSVC gate, LLVM and JIT off;
# build_windows_release_llvm_nightly keeps the JIT sweep). The nightly cron and a
# manual dispatch add the sanitizer cells (linux Release asan/tsan/ubsan, full
# tests) and windows 64 Debug, tagged nightly_only. No darwin x86_64: no prebuilt
# LLVM.dll for it, and no Intel runner worth gating on.
matrix: ${{ fromJSON(needs.pre_job.outputs.matrix) }}

steps:
- name: "SCM Checkout"
Expand Down Expand Up @@ -440,14 +308,16 @@ jobs:
;;
esac

# A nightly-only cell saves no slot: nothing restores it (the cron does not
# restore, and no PR lane runs the cell), so the tarball would only hold quota.
- name: "Refresh sccache slot"
if: github.ref == 'refs/heads/master'
if: github.ref == 'refs/heads/master' && matrix.nightly_only != 'ON'
env:
GH_TOKEN: ${{ github.token }}
SCKEY: sccache-${{ matrix.target }}-${{ matrix.architecture }}-${{ matrix.cmake_preset }}-${{ matrix.sanitizers }}
run: gh cache delete "$SCKEY" -R ${{ github.repository }} || true
- name: "Save sccache objects"
if: github.ref == 'refs/heads/master'
if: github.ref == 'refs/heads/master' && matrix.nightly_only != 'ON'
uses: actions/cache/save@v4
with:
path: ${{ runner.temp }}/sccache
Expand Down
Loading
Loading