-
Notifications
You must be signed in to change notification settings - Fork 36
318 lines (305 loc) · 12.8 KB
/
Copy pathci.yml
File metadata and controls
318 lines (305 loc) · 12.8 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
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
name: CI
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
jobs:
frontend:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
cache-dependency-path: frontend/package-lock.json
- name: Install
run: npm --prefix frontend ci
- name: Type-check + build
run: npm --prefix frontend run build
rust:
strategy:
fail-fast: false
matrix:
os: [ubuntu-24.04, windows-latest, macos-14]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
# The full workspace (engine + duckle-runner + duckle-mcp + apps/desktop
# with two embedded binaries) plus test artifacts can exceed the ~14 GB
# free on a GitHub Linux runner ("No space left on device"). Drop large
# preinstalled toolchains we never use to reclaim ~20 GB.
- name: Free disk space (Linux)
if: runner.os == 'Linux'
shell: bash
run: |
sudo rm -rf /usr/share/dotnet /usr/local/lib/android /opt/ghc \
/opt/hostedtoolcache/CodeQL /usr/local/.ghcup /usr/local/share/boost \
/usr/local/share/powershell /usr/share/swift || true
sudo docker image prune --all --force || true
df -h /
- uses: dtolnay/rust-toolchain@stable
with:
components: clippy, rustfmt
- uses: Swatinem/rust-cache@v2
- name: Install Linux WebView deps (Tauri)
if: runner.os == 'Linux'
run: |
sudo apt-get update
sudo apt-get install -y \
libwebkit2gtk-4.1-dev libgtk-3-dev \
libayatana-appindicator3-dev librsvg2-dev libsoup-3.0-dev
- name: Install DuckDB CLI (for engine tests)
shell: bash
run: |
set -e
ver=1.5.4
case "$RUNNER_OS" in
Linux) asset=duckdb_cli-linux-amd64.zip; exe=duckdb ;;
Windows) asset=duckdb_cli-windows-amd64.zip; exe=duckdb.exe ;;
macOS) asset=duckdb_cli-osx-universal.zip; exe=duckdb ;;
esac
# Use RUNNER_TEMP (a native drive-letter path on Windows) so the
# binary path resolves for the Rust test process; $HOME is an
# MSYS path (/c/...) on the Windows runner and Rust cannot find it.
dest="$RUNNER_TEMP/duckdb"
mkdir -p "$dest"
curl -L -o duckdb.zip "https://github.com/duckdb/duckdb/releases/download/v$ver/$asset"
unzip -o duckdb.zip -d "$dest"
bin="$dest/$exe"
if [ "$RUNNER_OS" = "Windows" ]; then bin="$(cygpath -w "$bin")"; fi
echo "using duckdb at: $bin"
echo "DUCKLE_DUCKDB_BIN=$bin" >> "$GITHUB_ENV"
- name: Pre-install DuckDB extensions
shell: bash
# Install once up front so the per-stage LOAD doesn't race with
# parallel test threads downloading the same extension into the
# shared ~/.duckdb cache.
run: |
"$DUCKLE_DUCKDB_BIN" :memory: -c "INSTALL postgres; INSTALL mysql; INSTALL sqlite; INSTALL excel; INSTALL httpfs; INSTALL iceberg; INSTALL delta; INSTALL ducklake; INSTALL vss; INSTALL fts; INSTALL inet;"
# The desktop crate embeds duckle-runner AND duckle-mcp at compile time
# via build.rs include_bytes!, so both binaries must exist before anything
# that compiles apps/desktop. Build them in the dev profile so the engine
# compilation is shared with the cargo test below.
- name: Build + stage duckle-runner + duckle-mcp (embedded into the desktop app)
shell: bash
run: |
set -e
cargo build -p duckle-runner -p duckle-mcp
mkdir -p apps/desktop/bin
if [ "$RUNNER_OS" = "Windows" ]; then
cp target/debug/duckle-runner.exe apps/desktop/bin/duckle-runner.exe
cp target/debug/duckle-mcp.exe apps/desktop/bin/duckle-mcp.exe
else
cp target/debug/duckle-runner apps/desktop/bin/duckle-runner
cp target/debug/duckle-mcp apps/desktop/bin/duckle-mcp
fi
- name: Test
run: cargo test --workspace
# Style checks are informational - they report problems without
# failing the build.
- name: Format check
continue-on-error: true
run: cargo fmt --all --check
- name: Clippy
continue-on-error: true
run: cargo clippy --workspace --all-targets
# Smoke build of the desktop release binary - the exact same command
# the release workflow runs. Catches feature-flag regressions like
# the v0.0.7 bug where `cargo build --release` (without
# `--features custom-protocol`) silently shipped a binary that loaded
# `http://localhost:5173` inside the Tauri WebView instead of the
# embedded frontend. `cargo test --workspace` never exercises this
# path, so the bug only surfaces when someone downloads + launches
# the published artifact.
desktop-release-build:
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- name: Free disk space
shell: bash
run: |
sudo rm -rf /usr/share/dotnet /usr/local/lib/android /opt/ghc \
/opt/hostedtoolcache/CodeQL /usr/local/.ghcup /usr/local/share/boost \
/usr/local/share/powershell /usr/share/swift || true
sudo docker image prune --all --force || true
df -h /
- uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
cache-dependency-path: frontend/package-lock.json
- name: Install frontend deps
run: npm --prefix frontend ci
- name: Build frontend (embedded into the Rust binary)
run: npm --prefix frontend run build
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- name: Install Linux WebView deps (Tauri)
run: |
sudo apt-get update
sudo apt-get install -y \
libwebkit2gtk-4.1-dev libgtk-3-dev \
libayatana-appindicator3-dev librsvg2-dev libsoup-3.0-dev
# Build + stage duckle-runner + duckle-mcp first: the desktop crate embeds
# both at compile time (build.rs include_bytes!). Release profile so the
# engine build is shared with the desktop release build below.
- name: Build + stage duckle-runner + duckle-mcp (embedded into the desktop app)
run: |
set -e
cargo build --release -p duckle-runner -p duckle-mcp
mkdir -p apps/desktop/bin
cp target/release/duckle-runner apps/desktop/bin/duckle-runner
cp target/release/duckle-mcp apps/desktop/bin/duckle-mcp
- name: Build raw Duckle binary (release workflow command)
run: cargo build --release --manifest-path apps/desktop/Cargo.toml --features custom-protocol
- name: Verify embedded frontend (not devUrl) is in binary
# Grep the built binary for the frontend's main JS chunk filename.
# If tauri-codegen embedded devUrl instead, this string will be
# absent and the check fails - catching the v0.0.7-class bug.
run: |
set -e
asset=$(ls frontend/dist/assets/index-*.js | head -1 | xargs basename)
if grep -q "$asset" target/release/duckle; then
echo "OK: embedded frontend asset '$asset' is present in the binary"
else
echo "FAIL: frontend asset '$asset' NOT found in binary - tauri-codegen likely embedded devUrl"
exit 1
fi
# Live PostgreSQL integration tests. Runs against a real postgres
# service container; engine tests that don't see DUCKLE_PG_HOST in the
# main matrix job skip cleanly, so this is the only place they execute.
postgres-integration:
runs-on: ubuntu-latest
services:
postgres:
image: pgvector/pgvector:pg16
env:
POSTGRES_PASSWORD: pgtest
POSTGRES_DB: postgres
ports: ['5432:5432']
options: >-
--health-cmd "pg_isready -U postgres"
--health-interval 5s
--health-timeout 5s
--health-retries 20
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- name: Install DuckDB CLI
run: |
set -e
curl -L -o duckdb.zip https://github.com/duckdb/duckdb/releases/download/v1.5.4/duckdb_cli-linux-amd64.zip
mkdir -p "$RUNNER_TEMP/duckdb"
unzip -o duckdb.zip -d "$RUNNER_TEMP/duckdb"
echo "DUCKLE_DUCKDB_BIN=$RUNNER_TEMP/duckdb/duckdb" >> "$GITHUB_ENV"
- name: Pre-install postgres extension
run: |
"$DUCKLE_DUCKDB_BIN" :memory: -c "INSTALL postgres;"
- name: Run PostgreSQL integration tests
env:
DUCKLE_PG_HOST: localhost
DUCKLE_PG_PORT: '5432'
DUCKLE_PG_DB: postgres
DUCKLE_PG_USER: postgres
DUCKLE_PG_PASS: pgtest
run: cargo test -p duckle-duckdb-engine --test execution -- pg_
# Live MySQL integration tests (also covers MariaDB, same wire).
mysql-integration:
runs-on: ubuntu-latest
services:
mysql:
image: mysql:8.0
env:
MYSQL_ROOT_PASSWORD: mytest
MYSQL_DATABASE: ducktest
ports: ['3306:3306']
options: >-
--health-cmd "mysqladmin ping -h localhost -p$$MYSQL_ROOT_PASSWORD"
--health-interval 5s
--health-timeout 5s
--health-retries 30
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- name: Install DuckDB CLI
run: |
set -e
curl -L -o duckdb.zip https://github.com/duckdb/duckdb/releases/download/v1.5.4/duckdb_cli-linux-amd64.zip
mkdir -p "$RUNNER_TEMP/duckdb"
unzip -o duckdb.zip -d "$RUNNER_TEMP/duckdb"
echo "DUCKLE_DUCKDB_BIN=$RUNNER_TEMP/duckdb/duckdb" >> "$GITHUB_ENV"
- name: Pre-install mysql extension
run: |
"$DUCKLE_DUCKDB_BIN" :memory: -c "INSTALL mysql;"
- name: Run MySQL integration tests
env:
DUCKLE_MYSQL_HOST: 127.0.0.1
DUCKLE_MYSQL_PORT: '3306'
DUCKLE_MYSQL_DB: ducktest
DUCKLE_MYSQL_USER: root
DUCKLE_MYSQL_PASS: mytest
run: cargo test -p duckle-duckdb-engine --test execution -- mysql_
# Live MinIO integration tests (covers all S3-compatible: MinIO, R2, B2).
# MinIO needs `server /data` as the container command; GitHub Actions
# service containers can't override CMD, so we run it as a step.
minio-integration:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- name: Start MinIO + create bucket
run: |
set -e
docker run -d --name minio -p 9000:9000 -p 9001:9001 \
-e MINIO_ROOT_USER=minioadmin -e MINIO_ROOT_PASSWORD=minioadmin \
minio/minio:latest server /data --console-address ":9001"
for i in $(seq 1 30); do
if curl -fs http://localhost:9000/minio/health/live >/dev/null 2>&1; then
echo "MinIO is up"; break
fi
sleep 2
done
# mc isn't in the minio server image, so use the standalone client.
curl -fsSL https://dl.min.io/client/mc/release/linux-amd64/mc -o /usr/local/bin/mc
chmod +x /usr/local/bin/mc
mc alias set local http://localhost:9000 minioadmin minioadmin
mc mb local/duckle-test
- name: Install DuckDB CLI
run: |
set -e
curl -L -o duckdb.zip https://github.com/duckdb/duckdb/releases/download/v1.5.4/duckdb_cli-linux-amd64.zip
mkdir -p "$RUNNER_TEMP/duckdb"
unzip -o duckdb.zip -d "$RUNNER_TEMP/duckdb"
echo "DUCKLE_DUCKDB_BIN=$RUNNER_TEMP/duckdb/duckdb" >> "$GITHUB_ENV"
- name: Seed MinIO with a test object
run: |
set -e
# Upload a small parquet file to s3://duckle-test/orders.parquet
# via the DuckDB CLI itself, so the source test reads it back.
"$DUCKLE_DUCKDB_BIN" :memory: -c "
INSTALL httpfs; LOAD httpfs;
CREATE OR REPLACE SECRET seed (
TYPE S3,
KEY_ID 'minioadmin',
SECRET 'minioadmin',
REGION 'us-east-1',
ENDPOINT 'localhost:9000',
URL_STYLE 'path',
USE_SSL false
);
COPY (SELECT * FROM (VALUES (1,'alice'),(2,'bob'),(3,'carol')) t(id,name))
TO 's3://duckle-test/orders.parquet' (FORMAT PARQUET);
"
- name: Run MinIO integration tests
env:
DUCKLE_MINIO_HOST: localhost
DUCKLE_MINIO_PORT: '9000'
DUCKLE_MINIO_BUCKET: duckle-test
DUCKLE_MINIO_ACCESS_KEY: minioadmin
DUCKLE_MINIO_SECRET_KEY: minioadmin
run: cargo test -p duckle-duckdb-engine --test execution -- minio_