Skip to content

Commit 0bca5a4

Browse files
authored
Merge pull request #1 from thientrile/chore/sync-upstream-main
chore: sync fork with upstream main
2 parents 010569f + 5df8b04 commit 0bca5a4

516 files changed

Lines changed: 1795812 additions & 472985 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.gitattributes‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,7 @@ internal/cbm/vendored/grammars/**/scanner.c linguist-generated=true diff=false
1111
# the git hooks are extensionless and need explicit entries. (#1272)
1212
scripts/git-hooks/commit-msg text eol=lf
1313
scripts/hooks/pre-commit text eol=lf
14+
15+
# Chialisp grammar corpus: one case asserts CRLF comment termination, so this
16+
# file must keep its exact bytes on every platform (no eol conversion). (#919)
17+
tools/tree-sitter-chialisp/test/corpus/comments.txt -text

‎.github/workflows/_build.yml‎

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ jobs:
9797
9898
- name: Attest release candidate provenance
9999
if: ${{ inputs.attest }}
100-
uses: actions/attest-build-provenance@0f67c3f4856b2e3261c31976d6725780e5e4c373 # v4.1.1
100+
uses: actions/attest-build-provenance@4d101475d8b20a2381f78447822ac1eab6504dd8 # v4.2.2
101101
with:
102102
subject-path: |
103103
release-candidates/${{ matrix.goos }}-${{ matrix.goarch }}/candidate-provenance.tsv
@@ -155,7 +155,7 @@ jobs:
155155
156156
- name: Attest release candidate provenance
157157
if: ${{ inputs.attest }}
158-
uses: actions/attest-build-provenance@0f67c3f4856b2e3261c31976d6725780e5e4c373 # v4.1.1
158+
uses: actions/attest-build-provenance@4d101475d8b20a2381f78447822ac1eab6504dd8 # v4.2.2
159159
with:
160160
subject-path: |
161161
release-candidates/windows-amd64/candidate-provenance.tsv
@@ -217,7 +217,7 @@ jobs:
217217
218218
- name: Attest release candidate provenance
219219
if: ${{ inputs.attest }}
220-
uses: actions/attest-build-provenance@0f67c3f4856b2e3261c31976d6725780e5e4c373 # v4.1.1
220+
uses: actions/attest-build-provenance@4d101475d8b20a2381f78447822ac1eab6504dd8 # v4.2.2
221221
with:
222222
subject-path: |
223223
release-candidates/windows-arm64/candidate-provenance.tsv
@@ -280,7 +280,7 @@ jobs:
280280
281281
- name: Attest release candidate provenance
282282
if: ${{ inputs.attest }}
283-
uses: actions/attest-build-provenance@0f67c3f4856b2e3261c31976d6725780e5e4c373 # v4.1.1
283+
uses: actions/attest-build-provenance@4d101475d8b20a2381f78447822ac1eab6504dd8 # v4.2.2
284284
with:
285285
subject-path: |
286286
release-candidates/linux-${{ matrix.arch }}-portable/candidate-provenance.tsv
@@ -432,7 +432,7 @@ jobs:
432432
433433
- name: Attest selected containers and decision evidence
434434
if: ${{ inputs.attest }}
435-
uses: actions/attest-build-provenance@0f67c3f4856b2e3261c31976d6725780e5e4c373 # v4.1.1
435+
uses: actions/attest-build-provenance@4d101475d8b20a2381f78447822ac1eab6504dd8 # v4.2.2
436436
with:
437437
subject-path: |
438438
release-containers/**/*.tar.gz

‎.github/workflows/_lint.yml‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -68,12 +68,12 @@ jobs:
6868
- name: Install build deps
6969
run: sudo apt-get update && sudo apt-get install -y zlib1g-dev
7070

71-
- name: Install LLVM 22 (pinned analyzer toolchain)
71+
- name: Install LLVM 21 (pinned analyzer toolchain)
7272
run: |
7373
wget -qO- https://apt.llvm.org/llvm-snapshot.gpg.key | sudo tee /etc/apt/trusted.gpg.d/apt.llvm.org.asc
74-
echo "deb http://apt.llvm.org/noble/ llvm-toolchain-noble-22 main" | sudo tee /etc/apt/sources.list.d/llvm-22.list
74+
echo "deb http://apt.llvm.org/noble/ llvm-toolchain-noble-21 main" | sudo tee /etc/apt/sources.list.d/llvm-21.list
7575
sudo apt-get update
76-
sudo apt-get install -y clang-tidy-22
76+
sudo apt-get install -y clang-tidy-21
7777
7878
- name: Memory-analyzer gate
79-
run: scripts/ci/lint-mem.sh clang-tidy-22
79+
run: scripts/ci/lint-mem.sh clang-tidy-21

‎.github/workflows/_memwaste.yml‎

Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
# Reusable: the waste sanitizer (memory + CPU waste), REPORT-ONLY.
2+
#
3+
# What runs (scripts/memwaste.sh, memwaste-scaling.py, memwaste-ratchet.py):
4+
# mode=pr Linux: the event lane (memory waste + CPU work) indexing this
5+
# repository at the checked-out commit, and the CPU scaling lane
6+
# (src/ replicated 2x against 4x, per-function counter ratios).
7+
# mode=full the same, plus the event lane on macOS and Windows and the access
8+
# lane (read/write verdicts per allocation) on Linux.
9+
#
10+
# The corpus is the repository itself: pinned by the commit, no network, and a
11+
# real mix of C, C++, Python, JavaScript and vendored code.
12+
#
13+
# REPORT-ONLY: every job uploads its report and prints the ratchet comparison
14+
# against scripts/memwaste-baseline.json, but nothing here can turn a PR red --
15+
# the ratchet runs without --enforce and the PR's ci-ok gate does not depend on
16+
# these jobs. A job fails only when the MEASUREMENT is unsound (a table
17+
# overflowed, frees the layer never saw): that is a defect of the tool, and a
18+
# red job is how it gets noticed. Switching the ratchet to --enforce is a
19+
# separate, deliberate change once the numbers have been stable across reruns.
20+
name: Memwaste
21+
22+
on:
23+
workflow_call:
24+
inputs:
25+
mode:
26+
description: "pr (Linux event + scaling) or full (all platforms, access lane)"
27+
type: string
28+
default: pr
29+
30+
permissions:
31+
contents: read
32+
33+
jobs:
34+
event-linux:
35+
runs-on: ubuntu-latest
36+
timeout-minutes: 60
37+
steps:
38+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
39+
- name: Install deps
40+
run: sudo apt-get update && sudo apt-get install -y zlib1g-dev python3 clang llvm
41+
- name: Event lane on this repository
42+
run: |
43+
# `cmd | tee` reports TEE's status: without this a failing lane
44+
# (a missing exec bit, a build error) passes the step and only
45+
# surfaces as the ratchet not finding its JSON.
46+
set -o pipefail
47+
mkdir -p "$RUNNER_TEMP/memwaste-event"
48+
scripts/memwaste.sh "$GITHUB_WORKSPACE" --top 40 --out "$RUNNER_TEMP/memwaste-event" \
49+
| tee "$RUNNER_TEMP/memwaste-event/report.txt"
50+
- name: Ratchet (report-only)
51+
run: python3 scripts/memwaste-ratchet.py --out "$RUNNER_TEMP/memwaste-event" --venue ${{ inputs.mode }}-linux
52+
- name: Upload report
53+
if: ${{ always() }}
54+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
55+
with:
56+
name: memwaste-event-linux-${{ inputs.mode }}
57+
path: |
58+
${{ runner.temp }}/memwaste-event/report.txt
59+
${{ runner.temp }}/memwaste-event/memwaste.json
60+
${{ runner.temp }}/memwaste-event/index.json
61+
if-no-files-found: warn
62+
63+
scaling-linux:
64+
runs-on: ubuntu-latest
65+
timeout-minutes: 60
66+
steps:
67+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
68+
- name: Install deps
69+
run: sudo apt-get update && sudo apt-get install -y zlib1g-dev python3 clang llvm
70+
- name: CPU scaling lane (src/ at 2x against 4x)
71+
# Report-only: the script exits 1 when it flags a super-linear function.
72+
continue-on-error: true
73+
run: |
74+
# `cmd | tee` reports TEE's status: without this a failing lane
75+
# (a missing exec bit, a build error) passes the step and only
76+
# surfaces as the ratchet not finding its JSON.
77+
set -o pipefail
78+
mkdir -p "$RUNNER_TEMP/memwaste-scaling"
79+
python3 scripts/memwaste-scaling.py --corpus src --replicas 2 \
80+
--out "$RUNNER_TEMP/memwaste-scaling" | tee "$RUNNER_TEMP/memwaste-scaling/report.txt"
81+
- name: Upload report
82+
if: ${{ always() }}
83+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
84+
with:
85+
name: memwaste-scaling-linux-${{ inputs.mode }}
86+
path: ${{ runner.temp }}/memwaste-scaling/report.txt
87+
if-no-files-found: warn
88+
89+
access-linux:
90+
if: ${{ inputs.mode == 'full' }}
91+
runs-on: ubuntu-latest
92+
timeout-minutes: 120
93+
steps:
94+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
95+
- name: Install deps
96+
run: sudo apt-get update && sudo apt-get install -y zlib1g-dev python3 clang llvm
97+
- name: Access lane on this repository
98+
run: |
99+
# `cmd | tee` reports TEE's status: without this a failing lane
100+
# (a missing exec bit, a build error) passes the step and only
101+
# surfaces as the ratchet not finding its JSON.
102+
set -o pipefail
103+
mkdir -p "$RUNNER_TEMP/memwaste-access"
104+
scripts/memwaste.sh "$GITHUB_WORKSPACE" --lane access --top 40 --sort untouched \
105+
--out "$RUNNER_TEMP/memwaste-access" | tee "$RUNNER_TEMP/memwaste-access/report.txt"
106+
- name: Upload report
107+
if: ${{ always() }}
108+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
109+
with:
110+
name: memwaste-access-linux-${{ inputs.mode }}
111+
path: |
112+
${{ runner.temp }}/memwaste-access/report.txt
113+
${{ runner.temp }}/memwaste-access/memwaste.json
114+
if-no-files-found: warn
115+
116+
event-macos:
117+
if: ${{ inputs.mode == 'full' }}
118+
runs-on: macos-14
119+
timeout-minutes: 60
120+
steps:
121+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
122+
- name: Event lane on this repository
123+
run: |
124+
# `cmd | tee` reports TEE's status: without this a failing lane
125+
# (a missing exec bit, a build error) passes the step and only
126+
# surfaces as the ratchet not finding its JSON.
127+
set -o pipefail
128+
mkdir -p "$RUNNER_TEMP/memwaste-event"
129+
scripts/memwaste.sh "$GITHUB_WORKSPACE" --top 40 --out "$RUNNER_TEMP/memwaste-event" \
130+
| tee "$RUNNER_TEMP/memwaste-event/report.txt"
131+
- name: Ratchet (report-only)
132+
run: python3 scripts/memwaste-ratchet.py --out "$RUNNER_TEMP/memwaste-event" --venue full-macos
133+
- name: Upload report
134+
if: ${{ always() }}
135+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
136+
with:
137+
name: memwaste-event-macos-${{ inputs.mode }}
138+
path: |
139+
${{ runner.temp }}/memwaste-event/report.txt
140+
${{ runner.temp }}/memwaste-event/memwaste.json
141+
if-no-files-found: warn
142+
143+
event-windows:
144+
if: ${{ inputs.mode == 'full' }}
145+
runs-on: windows-latest
146+
timeout-minutes: 90
147+
steps:
148+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
149+
- uses: msys2/setup-msys2@66cd2cce69caa17b53920067426061ca1de3a884 # v2
150+
with:
151+
msystem: CLANG64
152+
path-type: inherit
153+
install: >-
154+
mingw-w64-clang-x86_64-clang
155+
mingw-w64-clang-x86_64-llvm
156+
mingw-w64-clang-x86_64-zlib
157+
mingw-w64-clang-x86_64-python3
158+
make
159+
git
160+
coreutils
161+
- name: Event lane on this repository
162+
shell: msys2 {0}
163+
run: |
164+
# `cmd | tee` reports TEE's status: without this a failing lane
165+
# (a missing exec bit, a build error) passes the step and only
166+
# surfaces as the ratchet not finding its JSON.
167+
set -o pipefail
168+
out="$(cygpath -u "$RUNNER_TEMP")/memwaste-event"
169+
mkdir -p "$out"
170+
CC=clang CXX=clang++ scripts/memwaste.sh "$(cygpath -u "$GITHUB_WORKSPACE")" --top 40 --out "$out" \
171+
| tee "$out/report.txt"
172+
- name: Ratchet (report-only)
173+
shell: msys2 {0}
174+
run: python3 scripts/memwaste-ratchet.py --out "$(cygpath -u "$RUNNER_TEMP")/memwaste-event" --venue full-windows
175+
- name: Upload report
176+
if: ${{ always() }}
177+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
178+
with:
179+
name: memwaste-event-windows-${{ inputs.mode }}
180+
path: |
181+
${{ runner.temp }}/memwaste-event/report.txt
182+
${{ runner.temp }}/memwaste-event/memwaste.json
183+
if-no-files-found: warn

‎.github/workflows/_security.yml‎

Lines changed: 52 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -41,20 +41,34 @@ jobs:
4141
codeql-gate:
4242
runs-on: ubuntu-latest
4343
timeout-minutes: 240
44+
# Without security-events:read this job inherits the workflow's
45+
# contents:read, the code-scanning alert API answers 403, and the gate
46+
# below reported "0 alerts" on every run it has ever made. actions:read is
47+
# what the CodeQL-run poll above needs for the same reason.
48+
permissions:
49+
contents: read
50+
security-events: read
51+
actions: read
4452
steps:
45-
- name: Wait for CodeQL on current commit (max 45 min)
53+
- name: Wait for CodeQL on current commit (max 150 min)
4654
env:
4755
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
4856
run: |
4957
# On pull_request events github.sha is the synthetic merge commit;
5058
# CodeQL runs are recorded against the PR head SHA.
5159
CURRENT_SHA="${{ github.event.pull_request.head.sha || github.sha }}"
5260
echo "Waiting for CodeQL to complete on $CURRENT_SHA..."
53-
for attempt in $(seq 1 90); do
61+
# 300 attempts x 30s = 150 min. The previous budget was 90 x 30s = 45 min,
62+
# which is shorter than CodeQL actually takes on this repository: a measured
63+
# run on PR #1426 (head 7b72652a) completed with conclusion=success after
64+
# 124 min, 7 minutes AFTER this gate had already given up. That marked at
65+
# least five contributor PRs red for a scan that passed. The job's own
66+
# timeout-minutes is 240, so 150 still leaves headroom.
67+
for attempt in $(seq 1 300); do
5468
LATEST=$(gh api "repos/${{ github.repository }}/actions/workflows/codeql.yml/runs?head_sha=$CURRENT_SHA&per_page=1" \
5569
--jq '.workflow_runs[] | "\(.conclusion) \(.status)"' 2>/dev/null | head -1 || echo "")
5670
if [ -z "$LATEST" ]; then
57-
echo " $attempt/90: no run yet..."; sleep 30; continue
71+
echo " $attempt/300: no run yet..."; sleep 30; continue
5872
fi
5973
CONCLUSION=$(echo "$LATEST" | cut -d' ' -f1)
6074
STATUS=$(echo "$LATEST" | cut -d' ' -f2)
@@ -63,19 +77,51 @@ jobs:
6377
elif [ "$STATUS" = "completed" ]; then
6478
echo "BLOCKED: CodeQL $CONCLUSION"; exit 1
6579
fi
66-
echo " $attempt/90: $STATUS..."; sleep 30
80+
echo " $attempt/300: $STATUS..."; sleep 30
6781
done
6882
echo "BLOCKED: CodeQL timeout"; exit 1
6983
7084
- name: Check for open code scanning alerts
7185
env:
7286
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
7387
run: |
88+
# FAIL CLOSED. The previous form was `gh api ... 2>/dev/null || echo "0"`,
89+
# which looks defensive and is the opposite. gh writes the API error
90+
# BODY to stdout, so a 403 made ALERTS the string
91+
# {"message":"Resource not accessible by integration",...,"status":"403"}0
92+
# every `[` comparison then failed as non-integer, the `if` took its
93+
# false branch, and the step printed "CodeQL gate passed (0 alerts)"
94+
# and exited 0. That is exactly how a security gate should NEVER fail:
95+
# silently, in the direction of "everything is fine". An unreadable
96+
# alert list is now an error, not a zero.
97+
# NOTE: this runs in a command substitution, so it must `return`, not
98+
# `exit` -- an `exit` here would only end the subshell and let the
99+
# caller continue with an empty count, recreating the very bug this
100+
# replaces. The callers below check the status explicitly.
101+
count_open_alerts() {
102+
local body status
103+
body=$(gh api 'repos/${{ github.repository }}/code-scanning/alerts?state=open' \
104+
--jq 'length' 2>/dev/null)
105+
status=$?
106+
if [ $status -ne 0 ]; then
107+
echo "BLOCKED: cannot read code scanning alerts (gh exit $status)." >&2
108+
echo " Refusing to treat an unreadable alert list as zero." >&2
109+
echo " Most likely cause: the job lacks security-events:read." >&2
110+
return 1
111+
fi
112+
case "$body" in
113+
''|*[!0-9]*)
114+
echo "BLOCKED: alert count was not a number: ${body:-<empty>}" >&2
115+
return 1
116+
;;
117+
esac
118+
printf '%s' "$body"
119+
}
74120
echo "Waiting 60s for alert API to settle..."
75121
sleep 60
76-
ALERTS=$(gh api 'repos/${{ github.repository }}/code-scanning/alerts?state=open' --jq 'length' 2>/dev/null || echo "0")
122+
ALERTS=$(count_open_alerts) || exit 1
77123
sleep 15
78-
ALERTS2=$(gh api 'repos/${{ github.repository }}/code-scanning/alerts?state=open' --jq 'length' 2>/dev/null || echo "0")
124+
ALERTS2=$(count_open_alerts) || exit 1
79125
[ "$ALERTS" -lt "$ALERTS2" ] && ALERTS=$ALERTS2
80126
if [ "$ALERTS" -gt 0 ]; then
81127
echo "BLOCKED: $ALERTS open alert(s)"

0 commit comments

Comments
 (0)