-
-
Notifications
You must be signed in to change notification settings - Fork 0
178 lines (164 loc) · 7.02 KB
/
affinescript-canary.yml
File metadata and controls
178 lines (164 loc) · 7.02 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
# SPDX-License-Identifier: MPL-2.0
# Copyright (c) 2026 Jonathan D.A. Jewell (hyperpolymath) <j.d.a.jewell@open.ac.uk>
#
# affinescript-canary.yml — AffineScript Compilation Canary
#
# Compiles every .affine file in the repo using the canonical affinescript
# CLI. ADVISORY (canary) — failures are surfaced via GitHub annotations and
# job summary, but do NOT block merges. Promote to required-for-merge once
# parity with the .res fallback is proven (Burble grade B target).
#
# Companion: every .affine should have a .res sibling for fallback until the
# canary is required. The pairing-audit job warns on unpaired files.
#
# To bump the affinescript version, change AFFINESCRIPT_REF below.
name: AffineScript Canary
on:
pull_request:
branches: ['**']
paths:
- '**.affine'
- '.github/workflows/affinescript-canary.yml'
push:
branches: [main, master]
paths:
- '**.affine'
- '.github/workflows/affinescript-canary.yml'
workflow_dispatch:
permissions:
contents: read
env:
AFFINESCRIPT_REPO: hyperpolymath/affinescript
AFFINESCRIPT_REF: fc37bb5896de24cefe65dbfc5cd657a2d0087df7 # main as of 2026-05-02; bump as needed
OCAML_COMPILER: '5.1'
jobs:
# ---------------------------------------------------------------------------
# Job 1: Compile every .affine file (canary — advisory)
# ---------------------------------------------------------------------------
compile-affinescript:
name: Compile .affine files (canary)
runs-on: ubuntu-latest
continue-on-error: true # canary: surface failures, do not block merges
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Detect .affine files
id: detect
run: |
COUNT=$(find . -name '*.affine' -not -path './node_modules/*' -not -path './_build/*' -not -path './.git/*' | wc -l)
echo "count=$COUNT" >> "$GITHUB_OUTPUT"
echo "Found $COUNT .affine files"
if [ "$COUNT" -eq 0 ]; then
echo "::notice::No .affine files in repo — canary has nothing to do"
fi
- name: Cache affinescript build
if: steps.detect.outputs.count > 0
id: cache-affinescript
uses: actions/cache@d4323d4df104b026a6aa633fdb11d772146be0bf # v4.2.2
with:
path: /usr/local/bin/affinescript
key: affinescript-${{ env.AFFINESCRIPT_REF }}-${{ runner.os }}
- name: Setup OCaml (cache miss only)
if: steps.detect.outputs.count > 0 && steps.cache-affinescript.outputs.cache-hit != 'true'
uses: ocaml/setup-ocaml@e32b06a3e831ff2fbc6f08cf35be2085e3918014 # v3.6.1
with:
ocaml-compiler: ${{ env.OCAML_COMPILER }}
- name: Build affinescript from source (cache miss only)
if: steps.detect.outputs.count > 0 && steps.cache-affinescript.outputs.cache-hit != 'true'
run: |
set -euo pipefail
git clone --depth 1 "https://github.com/${AFFINESCRIPT_REPO}.git" /tmp/affinescript-src
cd /tmp/affinescript-src
git fetch --depth 1 origin "${AFFINESCRIPT_REF}"
git checkout "${AFFINESCRIPT_REF}"
OPAM_SWITCH="$(opam switch show 2>/dev/null || true)"
if [ -z "$OPAM_SWITCH" ]; then
OPAM_SWITCH="$(opam switch list --short | awk -v compiler="$OCAML_COMPILER" 'index($0, compiler) { print; exit }')"
fi
if [ -z "$OPAM_SWITCH" ]; then
OPAM_SWITCH="$(opam switch list --short | awk 'NF { print; exit }')"
fi
if [ -z "$OPAM_SWITCH" ]; then
echo "::error::ocaml/setup-ocaml did not leave an opam switch to activate"
opam switch list || true
exit 50
fi
opam switch set "$OPAM_SWITCH"
eval "$(opam env --switch="$OPAM_SWITCH" --set-switch)"
opam install --yes . --deps-only
opam exec --switch="$OPAM_SWITCH" -- dune build bin/main.exe
sudo cp _build/default/bin/main.exe /usr/local/bin/affinescript
affinescript --help | head -5 || echo "(--help unavailable, binary installed)"
- name: Compile every .affine file
if: steps.detect.outputs.count > 0
id: compile
run: |
set +e
failed=0
total=0
tmp=$(mktemp)
while IFS= read -r f; do
total=$((total+1))
if ! affinescript check "$f" >"$tmp" 2>&1; then
echo "::warning file=$f::affinescript check failed"
echo "--- $f ---"
cat "$tmp"
failed=$((failed+1))
fi
done < <(find . -name '*.affine' -not -path './node_modules/*' -not -path './_build/*' -not -path './.git/*')
rm -f "$tmp"
{
echo ""
echo "## AffineScript Canary Result"
echo ""
echo "| Metric | Value |"
echo "|---|---|"
echo "| Total .affine files | $total |"
echo "| Failed compilation | $failed |"
echo "| AffineScript ref | \`${AFFINESCRIPT_REF}\` |"
} >> "$GITHUB_STEP_SUMMARY"
if [ "$failed" -gt 0 ]; then
{
echo ""
echo "Canary advisory: $failed file(s) failed compilation. This does not block the merge — see annotations for details."
} >> "$GITHUB_STEP_SUMMARY"
exit 1
fi
{
echo ""
echo "All .affine files compiled cleanly."
} >> "$GITHUB_STEP_SUMMARY"
# ---------------------------------------------------------------------------
# Job 2: Pairing audit (.affine ↔ .res fallback)
# ---------------------------------------------------------------------------
# While the canary is advisory, every .affine must have a .res sibling so
# the build can fall back if affinescript miscompiles. Drop this job once
# the canary is promoted to required-for-merge (Burble grade B).
pairing-audit:
name: Pairing audit (.affine ↔ .res)
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Audit .affine ↔ .res pairing
run: |
unpaired=0
while IFS= read -r f; do
res="${f%.affine}.res"
if [ ! -f "$res" ]; then
echo "::warning file=$f::No .res sibling (fallback missing). Drop this rule once the AffineScript canary is required-for-merge."
unpaired=$((unpaired+1))
fi
done < <(find . -name '*.affine' -not -path './node_modules/*' -not -path './_build/*' -not -path './.git/*')
{
echo ""
echo "## .affine ↔ .res Pairing Audit"
echo ""
if [ "$unpaired" -eq 0 ]; then
echo "All .affine files have .res fallbacks."
else
echo "$unpaired .affine file(s) have no .res sibling. See annotations."
fi
} >> "$GITHUB_STEP_SUMMARY"
# Advisory only at canary stage — exit clean
exit 0