-
Notifications
You must be signed in to change notification settings - Fork 2.1k
140 lines (125 loc) · 4.85 KB
/
Copy pathpr.yml
File metadata and controls
140 lines (125 loc) · 4.85 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
# PR validation: security gates + lint + full test suite. Builds, smoke and
# soak stay maintainer-driven via the dry-run workflow_dispatch. Branch
# protection requires `dco` + `ci-ok` — a single stable summary context that
# fails unless every PR stage succeeded.
name: PR
on:
pull_request:
branches: [main]
permissions:
contents: read
pull-requests: read
# A new push to the PR supersedes the running validation — cancel it
# instead of stacking zombie pipelines.
concurrency:
group: pr-${{ github.event.pull_request.number }}
cancel-in-progress: true
jobs:
security:
uses: ./.github/workflows/_security.yml
secrets: inherit
lint:
uses: ./.github/workflows/_lint.yml
test:
needs: [lint]
if: ${{ !cancelled() && needs.lint.result == 'success' }}
uses: ./.github/workflows/_test.yml
with:
# Perf assertions are timing-sensitive on shared runners; they stay in
# dry runs and releases where a flaky red does not block a merge.
skip_perf: true
# ── Which files changed? Gate the (heavier) build+smoke on product code so
# docs / CI / test-only PRs stay fast. ──
changes:
runs-on: ubuntu-latest
timeout-minutes: 5
outputs:
product: ${{ steps.f.outputs.product }}
steps:
- name: Detect product-code changes
id: f
env:
GH_TOKEN: ${{ github.token }}
PR: ${{ github.event.pull_request.number }}
REPO: ${{ github.repository }}
run: |
FILES=$(gh pr diff "$PR" --repo "$REPO" --name-only)
printf '%s\n' "$FILES"
if printf '%s\n' "$FILES" | grep -qE '^(src/|internal/|scripts/build\.sh|scripts/smoke-test\.sh|scripts/env\.sh|Makefile\.cbm)'; then
echo "product=true" >> "$GITHUB_OUTPUT"
else
echo "product=false" >> "$GITHUB_OUTPUT"
fi
# ── Light smoke: build the PRODUCTION binary and run the core smoke on the
# three RELIABLE NATIVE platforms. Catches built-binary regressions at PR
# time (e.g. the Windows CreateProcess argv-quoting class that previously
# only surfaced in the release dry run). The full broad/emulated smoke stays
# in the dry run. Only product-code PRs pay this; every leg gates.
# SMOKE_DOWNLOAD_URL is intentionally unset — the download/update phases of
# smoke-test.sh self-skip; the core index/search/trace phases still run. ──
pr-smoke:
needs: [changes]
if: ${{ !cancelled() && needs.changes.outputs.product == 'true' }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-14, windows-latest]
runs-on: ${{ matrix.os }}
timeout-minutes: 30
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- name: Install deps (Ubuntu)
if: matrix.os == 'ubuntu-latest'
run: sudo apt-get update && sudo apt-get install -y zlib1g-dev
- uses: msys2/setup-msys2@66cd2cce69caa17b53920067426061ca1de3a884 # v2
if: matrix.os == 'windows-latest'
with:
msystem: CLANG64
path-type: inherit
install: >-
mingw-w64-clang-x86_64-clang
mingw-w64-clang-x86_64-zlib
mingw-w64-clang-x86_64-python3
make
coreutils
- name: Build prod + smoke (Ubuntu)
if: matrix.os == 'ubuntu-latest'
run: |
scripts/build.sh CC=gcc CXX=g++
scripts/smoke-test.sh "$(pwd)/build/c/codebase-memory-mcp"
- name: Build prod + smoke (macOS)
if: matrix.os == 'macos-14'
run: |
scripts/build.sh CC=cc CXX=c++
codesign --sign - --force build/c/codebase-memory-mcp
scripts/smoke-test.sh "$(pwd)/build/c/codebase-memory-mcp"
- name: Build prod + smoke (Windows)
if: matrix.os == 'windows-latest'
shell: msys2 {0}
run: |
scripts/build.sh CC=clang CXX=clang++
BIN="$(pwd)/build/c/codebase-memory-mcp"
[ -f "${BIN}.exe" ] && BIN="${BIN}.exe"
scripts/smoke-test.sh "$BIN"
ci-ok:
# The one required context (besides dco) — fails unless every PR stage
# succeeded, so matrix renames can never silently deadlock merges. `skipped`
# is OK: pr-smoke skips on docs/CI/test-only PRs (changes.product == false).
needs: [security, lint, test, changes, pr-smoke]
if: ${{ always() }}
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- name: All PR stages must have succeeded
env:
RESULTS: ${{ toJSON(needs) }}
run: |
echo "$RESULTS" | python3 -c "
import json, sys
needs = json.load(sys.stdin)
bad = {k: v['result'] for k, v in needs.items() if v['result'] not in ('success', 'skipped')}
if bad:
print('CI NOT OK:', bad)
sys.exit(1)
print('CI OK:', ', '.join(needs))
"