Skip to content

Commit 7188fcd

Browse files
authored
Merge pull request #45 from chdb-io/feat/engine-release-check
Run the suite against each new chdb-core release
2 parents bc098f2 + 274f8c3 commit 7188fcd

3 files changed

Lines changed: 288 additions & 2 deletions

File tree

Lines changed: 267 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,267 @@
1+
name: Engine release check
2+
3+
# chdb-core publishes an engine and dispatches here; this runs the suite against
4+
# that engine and records the verdict in an issue. It gates nothing — the engine
5+
# has already shipped by the time this starts.
6+
#
7+
# It exists because nothing else notices a C-ABI change. purego resolves symbols
8+
# by name at runtime and the Go-side signatures in chdb-purego are written by
9+
# hand, so a struct that loses a field or a function that gains an argument
10+
# builds and links exactly as before and misreads memory instead. The regular CI
11+
# jobs only ever see the engine this repository already pinned, so they stay
12+
# green until someone bumps it, which can be months after the break landed.
13+
14+
on:
15+
repository_dispatch:
16+
types: [chdb-core-release]
17+
workflow_dispatch:
18+
inputs:
19+
engine_version:
20+
description: "chdb-core release tag, e.g. v26.5.0"
21+
required: true
22+
23+
permissions:
24+
contents: read
25+
26+
jobs:
27+
test:
28+
strategy:
29+
fail-fast: false
30+
matrix:
31+
os: [ubuntu-latest, macos-14]
32+
runs-on: ${{ matrix.os }}
33+
steps:
34+
- uses: actions/checkout@v4
35+
36+
- name: Resolve the engine version
37+
env:
38+
ENGINE_VERSION: ${{ github.event.client_payload.tag || github.event.inputs.engine_version }}
39+
run: |
40+
if [ -z "$ENGINE_VERSION" ]; then
41+
echo "::error::no engine version in the dispatch payload or the manual input"
42+
exit 1
43+
fi
44+
# The version arrives from a dispatch payload or a typed input, then flows
45+
# into a URL, a branch name, a commit message and a sed replacement. Any
46+
# character outside this set belongs to no chdb-core release tag, and an
47+
# & or | reaching sed would quietly rewrite the wrong thing.
48+
case "$ENGINE_VERSION" in
49+
*[!A-Za-z0-9._+-]*)
50+
echo "::error::refusing engine version '$ENGINE_VERSION': letters, digits and . _ + - only"
51+
exit 1 ;;
52+
esac
53+
echo "CHDB_ENGINE_VERSION=$ENGINE_VERSION" >> "$GITHUB_ENV"
54+
echo "Testing against chdb-core $ENGINE_VERSION"
55+
56+
- uses: actions/setup-go@v5
57+
with:
58+
go-version: "1.21"
59+
60+
# Same path as the regular jobs: system-wide, so the CLI finds it too.
61+
# CHDB_ENGINE_VERSION is already in the environment and overrides the pin.
62+
- name: Fetch the published engine
63+
run: make install
64+
65+
- name: Build
66+
run: |
67+
go mod tidy
68+
make build
69+
70+
- name: Test
71+
run: make test
72+
73+
- name: Test with race detector
74+
run: go test -race -timeout=180s ./...
75+
76+
- name: Test main
77+
run: ./chdb-go "SELECT 12345"
78+
79+
# Green means the engine can be adopted, not that it has been. Adoption is a
80+
# one-line change to a pinned version and goes through review like any other
81+
# dependency bump; this only writes the line.
82+
propose_bump:
83+
needs: test
84+
if: needs.test.result == 'success'
85+
runs-on: ubuntu-latest
86+
permissions:
87+
contents: write
88+
pull-requests: write
89+
outputs:
90+
pr: ${{ steps.bump.outputs.pr }}
91+
unproposed: ${{ steps.bump.outputs.unproposed }}
92+
steps:
93+
# The commit the suite actually ran against, not whatever the default branch
94+
# has become since. github.sha is fixed for the whole run, so this is the
95+
# same tree the test job exercised; a default branch that moved during a
96+
# long matrix would otherwise put the new pin on untested code while the
97+
# pull request claims the suite passed.
98+
- uses: actions/checkout@v4
99+
with:
100+
ref: ${{ github.sha }}
101+
102+
- id: bump
103+
name: Open a PR moving the pin to this engine
104+
env:
105+
GH_TOKEN: ${{ github.token }}
106+
DEFAULT_BRANCH: ${{ github.event.repository.default_branch }}
107+
ENGINE_VERSION: ${{ github.event.client_payload.tag || github.event.inputs.engine_version }}
108+
RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
109+
run: |
110+
set -euo pipefail
111+
112+
# test rejects these too, but this is the step that interpolates the
113+
# version into sed replacements and a branch name.
114+
case "$ENGINE_VERSION" in
115+
*[!A-Za-z0-9._+-]*)
116+
echo "::error::refusing engine version '$ENGINE_VERSION'"
117+
exit 1 ;;
118+
esac
119+
120+
# Only when the tested commit is still the tip of the default branch.
121+
# Anything else means merging the bump would adopt commits no run
122+
# exercised against this engine, and the bump carries no CI to catch it.
123+
# Declining and saying why beats a pull request claiming more than the
124+
# run established.
125+
rel=$(gh api "repos/$GITHUB_REPOSITORY/compare/$DEFAULT_BRANCH...$GITHUB_SHA" --jq .status)
126+
if [ "$rel" != identical ]; then
127+
echo "unproposed=The tested commit $GITHUB_SHA is $rel relative to $DEFAULT_BRANCH, so nothing was proposed" >> "$GITHUB_OUTPUT"
128+
echo "declining to propose a bump: $rel"
129+
exit 0
130+
fi
131+
132+
current=$(grep -E '^CHDB_ENGINE_PIN=' update_libchdb.sh | cut -d= -f2)
133+
if [ "$current" = "$ENGINE_VERSION" ]; then
134+
echo "already pinned to $ENGINE_VERSION, nothing to propose"
135+
exit 0
136+
fi
137+
138+
branch="engine-pin-$ENGINE_VERSION"
139+
if [ "$(gh pr list --head "$branch" --state open --json number --jq 'length')" != 0 ]; then
140+
echo "a PR for $ENGINE_VERSION is already open"
141+
exit 0
142+
fi
143+
144+
git switch -c "$branch"
145+
sed -i "s|^CHDB_ENGINE_PIN=.*|CHDB_ENGINE_PIN=$ENGINE_VERSION|" update_libchdb.sh
146+
git -c user.name="github-actions[bot]" \
147+
-c user.email="41898282+github-actions[bot]@users.noreply.github.com" \
148+
commit -am "Move the engine pin from $current to $ENGINE_VERSION"
149+
# The branch can already exist on the remote: a bump PR closed without
150+
# merging leaves it behind, and a plain push is then rejected as a
151+
# non-fast-forward, silently costing the adoption PR. No open PR uses it
152+
# — that was checked above — and its only content is one generated line,
153+
# so replacing it is safe.
154+
if git ls-remote --exit-code --heads origin "$branch" >/dev/null 2>&1; then
155+
echo "$branch is left over from an earlier attempt, replacing it"
156+
git push --force -u origin "$branch"
157+
else
158+
git push -u origin "$branch"
159+
fi
160+
161+
{
162+
echo "The release check ran the suite against \`$ENGINE_VERSION\` on Linux and"
163+
echo "macOS and it passed, so the engine can be adopted. This moves the pin"
164+
echo "$current → \`$ENGINE_VERSION\`; \`make install\` and \`update_libchdb.sh\`"
165+
echo "both read it."
166+
echo
167+
echo "$RUN_URL"
168+
echo
169+
echo "Based on $GITHUB_SHA, the commit that run tested."
170+
echo
171+
echo "No checks will appear here. GitHub does not start workflow runs for"
172+
echo "commits a workflow pushed with \`GITHUB_TOKEN\`, and running CI on this"
173+
echo "branch would exercise the same suite against the same engine the check"
174+
echo "just used."
175+
} > pr-body.md
176+
177+
url=$(gh pr create --base "$DEFAULT_BRANCH" --head "$branch" \
178+
--title "Move the engine pin to $ENGINE_VERSION" \
179+
--body-file pr-body.md)
180+
echo "pr=$url" >> "$GITHUB_OUTPUT"
181+
echo "$url"
182+
183+
report:
184+
needs: [test, propose_bump]
185+
if: always()
186+
runs-on: ubuntu-latest
187+
permissions:
188+
issues: write
189+
steps:
190+
- name: Open an issue with the verdict
191+
env:
192+
GH_TOKEN: ${{ github.token }}
193+
# This job has nothing checked out, and gh does not read
194+
# GITHUB_REPOSITORY. Without this it cannot tell which repository to
195+
# open the issue in and every run reports nothing.
196+
GH_REPO: ${{ github.repository }}
197+
RESULT: ${{ needs.test.result }}
198+
BUMP_PR: ${{ needs.propose_bump.outputs.pr }}
199+
BUMP_RESULT: ${{ needs.propose_bump.result }}
200+
BUMP_UNPROPOSED: ${{ needs.propose_bump.outputs.unproposed }}
201+
ENGINE_VERSION: ${{ github.event.client_payload.tag || github.event.inputs.engine_version }}
202+
RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
203+
run: |
204+
set -euo pipefail
205+
206+
# A green suite whose bump could not be opened is not a green run. Closing
207+
# on needs.test.result alone would file it as "nothing to adopt" and leave
208+
# the broken automation with no signal at all.
209+
bump_broke=0
210+
if [ "$RESULT" != success ]; then
211+
verdict="FAILS"
212+
keep=1
213+
elif [ "$BUMP_RESULT" = failure ] || [ "$BUMP_RESULT" = cancelled ]; then
214+
verdict="passes, bump PR did not open"
215+
keep=1
216+
bump_broke=1
217+
elif [ -n "$BUMP_UNPROPOSED" ]; then
218+
verdict="passes, no bump proposed"
219+
keep=1
220+
else
221+
verdict="passes"
222+
keep=0
223+
fi
224+
225+
{
226+
if [ "$bump_broke" = 1 ]; then
227+
echo "chdb-go passes against chdb-core \`$ENGINE_VERSION\`, but the bump PR did not open."
228+
elif [ -n "$BUMP_UNPROPOSED" ]; then
229+
echo "chdb-go passes against chdb-core \`$ENGINE_VERSION\`, but no bump was proposed."
230+
else
231+
echo "chdb-go $verdict against chdb-core \`$ENGINE_VERSION\`."
232+
fi
233+
echo
234+
echo "$RUN_URL"
235+
if [ -n "$BUMP_PR" ]; then
236+
echo
237+
echo "Adopting it: $BUMP_PR"
238+
elif [ -n "$BUMP_UNPROPOSED" ]; then
239+
echo
240+
echo "$BUMP_UNPROPOSED. The engine is fine and the pin is unchanged; rerun"
241+
echo "the check once the default branch stops moving, or move the pin by hand."
242+
elif [ "$bump_broke" = 1 ]; then
243+
echo
244+
echo "The engine is fine; the automation is not. The pull request moving the"
245+
echo "pin could not be opened, so this issue stays open. The usual cause is"
246+
echo "this repository having \"Allow GitHub Actions to create and approve pull"
247+
echo "requests\" turned off; the other is the branch push being rejected. The"
248+
echo "pin is unchanged either way, and moving it by hand is one line."
249+
fi
250+
if [ "$RESULT" != success ]; then
251+
echo
252+
echo "purego binds by symbol name, so an ABI change does not show up as a"
253+
echo "build error. Compare \`chdb-purego/types.go\` and \`chdb-purego/binding.go\`"
254+
echo "against \`programs/local/chdb.h\` at this tag before looking anywhere else."
255+
fi
256+
echo
257+
echo "cc @auxten @wudidapaopao @ShawnChen-Sirius"
258+
} > body.md
259+
260+
url=$(gh issue create \
261+
--title "Engine check: chdb-core $ENGINE_VERSION — $verdict" \
262+
--body-file body.md)
263+
echo "$url"
264+
265+
if [ "$keep" = 0 ]; then
266+
gh issue close "$url" --comment "Green, closing. The run is linked above."
267+
fi

‎Makefile‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,14 @@
33
update_libchdb:
44
./update_libchdb.sh
55

6+
# lib.chdb.io installs system-wide, which is what the CLI needs; update_libchdb.sh
7+
# only drops the engine in the repository root. Both read the same pin, so the two
8+
# cannot end up on different builds — left to itself the installer takes whatever
9+
# chdb-core released most recently, which made an unrelated commit's CI go red on
10+
# the day of a release.
611
install:
12+
@export INSTALL_VERSION="$${CHDB_ENGINE_VERSION:-$$(grep -E '^CHDB_ENGINE_PIN=' update_libchdb.sh | cut -d= -f2)}"; \
13+
echo "installing libchdb $$INSTALL_VERSION"; \
714
curl -sL https://lib.chdb.io | bash
815

916
test:

‎update_libchdb.sh‎

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,20 @@
11

22
#!/bin/bash
33

4-
# Get the newest release version
5-
LATEST_RELEASE=$(curl --silent "https://api.github.com/repos/chdb-io/chdb-core/releases/latest" | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/')
4+
# The engine this repository is built and tested against. `make install` reads
5+
# it too, so both ways of fetching libchdb land on the same build. Keep it on
6+
# its own line and literal: the release check greps for it when it proposes a
7+
# bump, and the Makefile cuts the value out of it.
8+
CHDB_ENGINE_PIN=v26.5.0
9+
10+
# CHDB_ENGINE_VERSION overrides the pin, which is how the release check runs the
11+
# suite against an engine this repository has not adopted yet.
12+
LATEST_RELEASE="${CHDB_ENGINE_VERSION:-$CHDB_ENGINE_PIN}"
13+
14+
if [ -z "$LATEST_RELEASE" ]; then
15+
echo "No chdb-core release to download. Set CHDB_ENGINE_VERSION or fix CHDB_ENGINE_PIN." >&2
16+
exit 1
17+
fi
618

719
# Download the correct version based on the platform
820
case "$(uname -s)" in

0 commit comments

Comments
 (0)