-
-
Notifications
You must be signed in to change notification settings - Fork 173
541 lines (527 loc) · 20.7 KB
/
Copy pathci.yml
File metadata and controls
541 lines (527 loc) · 20.7 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
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
name: CI
on:
push:
tags:
- "v*" # Push events to matching v*, i.e. v1.0, v20.15.10
branches:
- "main"
paths-ignore:
- "docs/**"
- "README.md"
- ".github/workflows/release.yml"
- ".github/workflows/official-site.yml"
pull_request:
branches:
- "main"
paths-ignore:
- "docs/**"
- "README.md"
- ".github/workflows/release.yml"
- ".github/workflows/official-site.yml"
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
env:
CARGO_TERM_COLOR: always
HURL_VERSION: 8.0.0
REGISTRY_USERNAME: lovasoa
REGISTRY_IMAGE: lovasoa/sqlpage
jobs:
compile_and_lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- run: npm ci
- run: npm test
- name: Set up cargo cache
uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4
env:
NODE_OPTIONS: --no-deprecation
with:
shared-key: rust-sqlpage-proj-test
save-if: ${{ github.ref == 'refs/heads/main' }}
- run: cargo fmt --all -- --check
- run: cargo clippy --all-targets --all-features -- -D warnings
# The database matrix below runs the same Rust test harnesses against
# different DATABASE_URL values. Package the Linux test executables once
# here so those jobs do not recompile SQLPage or its dependencies.
- name: Package Linux Rust test binaries
run: |
set -euo pipefail
rm -rf target/sqlpage-test-binaries
mkdir -p target/sqlpage-test-binaries
cargo test --features odbc-static --no-run --message-format=json \
| jq -r 'select(.profile.test == true and .executable != null) | .executable' \
| while IFS= read -r test_binary; do
cp -- "$test_binary" target/sqlpage-test-binaries/
done
test -n "$(find target/sqlpage-test-binaries -maxdepth 1 -type f -print -quit)"
tar -C target/sqlpage-test-binaries -czf target/sqlpage-linux-test-binaries.tar.gz .
- name: Build Linux binary
run: cargo build --features odbc-static
- name: Upload Linux Rust test binaries
uses: actions/upload-artifact@v7
with:
name: sqlpage-linux-test-binaries
path: "target/sqlpage-linux-test-binaries.tar.gz"
- name: Upload Linux binary
uses: actions/upload-artifact@v7
with:
name: sqlpage-linux-debug
path: "target/debug/sqlpage"
test:
runs-on: ubuntu-latest
needs: compile_and_lint
strategy:
matrix:
include:
- database: sqlite
container: ""
db_url: "sqlite::memory:"
- database: postgres
container: postgres
db_url: "postgres://root:Password123!@127.0.0.1/sqlpage"
- database: mysql
container: mysql
db_url: "mysql://root:Password123!@127.0.0.1/sqlpage"
- database: mssql
container: mssql
db_url: "mssql://root:Password123!@127.0.0.1/sqlpage"
- database: odbc
container: postgres
db_url: "Driver=PostgreSQL Unicode;Server=127.0.0.1;Port=5432;Database=sqlpage;UID=root;PWD=Password123!"
setup_odbc: true
- database: oracle
container: oracle
db_url: "Driver=Oracle 21 ODBC driver;Dbq=//127.0.0.1:1521/FREEPDB1;Uid=root;Pwd=Password123!"
steps:
- uses: actions/checkout@v6
# Reuse the exact Linux test harnesses produced by compile_and_lint.
# This keeps the DB matrix focused on database behavior instead of
# compiling the same Rust crate five more times.
- name: Download Linux Rust test binaries
uses: actions/download-artifact@v8
with:
name: sqlpage-linux-test-binaries
path: target
- name: Extract Linux Rust test binaries
run: |
mkdir -p target/sqlpage-test-binaries
tar -xzf target/sqlpage-linux-test-binaries.tar.gz -C target/sqlpage-test-binaries
- name: Install PostgreSQL ODBC driver
if: matrix.setup_odbc
run: sudo apt-get install -y odbc-postgresql
- name: Install Oracle ODBC driver
if: matrix.database == 'oracle'
run: |
sudo apt-get install -y alien libaio1t64 libodbcinst2 unixodbc
sudo rpm --import https://yum.oracle.com/RPM-GPG-KEY-oracle-ol8
wget https://yum.oracle.com/repo/OracleLinux/OL8/oracle/instantclient21/x86_64/getPackage/oracle-instantclient-{basic,odbc}-21.21.0.0.0-1.el8.x86_64.rpm
sudo alien -i oracle-instantclient-basic-21.21.0.0.0-1.el8.x86_64.rpm
sudo alien -i oracle-instantclient-odbc-21.21.0.0.0-1.el8.x86_64.rpm
sudo ln -s /usr/lib/x86_64-linux-gnu/libaio.so.1t64 /usr/lib/libaio.so.1
sudo /usr/lib/oracle/21/client64/bin/odbc_update_ini.sh / /usr/lib/oracle/21/client64/lib
echo "LD_LIBRARY_PATH=/usr/lib/oracle/21/client64/lib:$LD_LIBRARY_PATH" >> "$GITHUB_ENV"
- name: Start database container
if: matrix.container != ''
run: docker compose up --wait ${{ matrix.container }}
- name: Show container logs
if: failure() && matrix.container != ''
run: docker compose logs ${{ matrix.container }}
- name: Run tests against ${{ matrix.database }}
timeout-minutes: 5
run: |
set -euo pipefail
shopt -s nullglob
test_binaries=(target/sqlpage-test-binaries/*)
if ((${#test_binaries[@]} == 0)); then
echo "No test binaries were found in target/sqlpage-test-binaries" >&2
exit 1
fi
for test_binary in "${test_binaries[@]}"; do
echo "::group::$(basename "$test_binary")"
"$test_binary"
echo "::endgroup::"
done
env:
DATABASE_URL: ${{ matrix.db_url }}
MALLOC_CHECK_: 3
MALLOC_PERTURB_: 10
windows_test:
runs-on: windows-latest
steps:
- uses: actions/checkout@v6
- name: Set up cargo cache
uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4
env:
NODE_OPTIONS: --no-deprecation
- name: Set up Windows incremental cache
uses: actions/cache@v5
with:
path: |
target/debug/.fingerprint/sqlpage-*
target/debug/build/sqlpage-*
target/debug/deps/libsqlpage-*.rlib
target/debug/deps/libsqlpage-*.rmeta
target/debug/deps/sqlpage-*.d
target/debug/incremental/sqlpage-*
key: windows-incremental-${{ github.event.pull_request.number || github.ref_name }}-${{ github.sha }}
restore-keys: |
windows-incremental-${{ github.event.pull_request.number || github.ref_name }}-
- run: cargo test
env:
CARGO_INCREMENTAL: 1
RUST_BACKTRACE: 1
- name: Upload Windows binary
uses: actions/upload-artifact@v7
with:
name: sqlpage-windows-debug
path: "target/debug/sqlpage.exe"
playwright:
runs-on: ubuntu-latest
timeout-minutes: 10
needs: compile_and_lint
defaults:
run:
working-directory: ./tests/end-to-end
steps:
- uses: actions/checkout@v6
- uses: actions/setup-node@v6
with:
node-version: lts/*
cache: 'npm'
cache-dependency-path: ./tests/end-to-end/package-lock.json
- run: sudo apt-get update && sudo apt-get install -y unixodbc-dev
- run: npm ci && npx playwright install --with-deps chromium
# The browser tests exercise the official site, but they do not need a
# separate Rust build. Reuse the binary compiled and tested above.
- name: Download Linux binary
uses: actions/download-artifact@v8
with:
name: sqlpage-linux-debug
path: ${{ runner.temp }}/sqlpage-bin
- name: Start official site and wait for it to be ready
timeout-minutes: 1
run: |
chmod +x "${{ runner.temp }}/sqlpage-bin/sqlpage"
"${{ runner.temp }}/sqlpage-bin/sqlpage" 2>/tmp/stderrlog &
tail -f /tmp/stderrlog | grep -q "started successfully"
working-directory: ./examples/official-site
- name: Run Playwright tests
run: npx playwright test
- name: show server logs
if: failure()
run: cat /tmp/stderrlog
- uses: actions/upload-artifact@v7
if: always()
with:
name: playwright-report
path: ./tests/end-to-end/playwright-report/
retention-days: 30
docker_build:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
platform:
- linux/amd64
- linux/arm/v7
- linux/arm64
variant:
- minimal
- duckdb
exclude:
# DuckDB ODBC is not available for armv7
- platform: linux/arm/v7
variant: duckdb
# This build is shared with the Hurl example jobs.
- platform: linux/amd64
variant: minimal
steps:
- name: Checkout
uses: actions/checkout@v6
- id: suffix
name: Cache name suffix
run: |
suffix="-$(tr '/' '-' <<< "${{ matrix.platform }}")"
if [[ "${{ matrix.variant }}" != "minimal" ]]; then
suffix="${suffix}-${{ matrix.variant }}"
fi
echo "suffix=${suffix}" >> "$GITHUB_OUTPUT"
- id: cache-scope
name: Docker cache scope
run: |
ref_scope="main"
if [[ "${{ github.event_name }}" == "pull_request" ]]; then
ref_scope="pr-${{ github.event.pull_request.number }}"
fi
recipe_hash="${{ hashFiles('Dockerfile', '.cargo/**', 'Cargo.toml', 'Cargo.lock', 'build.rs', 'scripts/**', 'sqlpage/**') }}"
{
echo "current=sqlpage-${ref_scope}${{ steps.suffix.outputs.suffix }}-${recipe_hash}"
echo "main=sqlpage-main${{ steps.suffix.outputs.suffix }}-${recipe_hash}"
} >> "$GITHUB_OUTPUT"
- name: Docker meta
id: meta
uses: docker/metadata-action@v6
with:
images: ${{ env.REGISTRY_IMAGE }}
flavor: suffix=${{ steps.suffix.outputs.suffix }}
labels: |
org.opencontainers.image.created=1970-01-01T00:00:00Z
- name: Set up QEMU
uses: docker/setup-qemu-action@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4
- name: Login to Docker Hub
if: github.event_name != 'pull_request'
uses: docker/login-action@v4
with:
username: ${{ env.REGISTRY_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build and push by digest
id: build
uses: docker/build-push-action@v7
with:
# Use BuildKit's Git context instead of the mutable runner workspace.
# The dependency cache should be keyed by committed source, not by a
# per-job local context stream.
context: "{{defaultContext}}"
platforms: ${{ matrix.platform }}
target: ${{ matrix.variant }}
labels: ${{ steps.meta.outputs.labels }}
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
cache-from: |
type=gha,scope=${{ steps.cache-scope.outputs.current }}
type=gha,scope=${{ steps.cache-scope.outputs.main }}
type=registry,ref=${{ env.REGISTRY_IMAGE }}:main${{ steps.suffix.outputs.suffix }}
cache-to: type=gha,scope=${{ steps.cache-scope.outputs.current }},mode=max
- name: Export digest
if: github.event_name != 'pull_request'
run: |
mkdir -p /tmp/digests
digest="${{ steps.build.outputs.digest }}"
touch "/tmp/digests/${digest#sha256:}"
- name: Upload digest
uses: actions/upload-artifact@v7
if: github.event_name != 'pull_request'
with:
name: digests-${{ matrix.variant }}${{ steps.suffix.outputs.suffix }}
path: /tmp/digests/*
if-no-files-found: error
retention-days: 1
docker_build_amd64_minimal:
name: docker_build (linux/amd64, minimal)
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Docker meta
id: meta
uses: docker/metadata-action@v6
with:
images: ${{ env.REGISTRY_IMAGE }}
flavor: suffix=-linux-amd64
labels: |
org.opencontainers.image.created=1970-01-01T00:00:00Z
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4
- id: cache-scope
name: Docker cache scope
run: |
ref_scope="main"
if [[ "${{ github.event_name }}" == "pull_request" ]]; then
ref_scope="pr-${{ github.event.pull_request.number }}"
fi
recipe_hash="${{ hashFiles('Dockerfile', '.cargo/**', 'Cargo.toml', 'Cargo.lock', 'build.rs', 'scripts/**', 'sqlpage/**') }}"
{
echo "artifact=sqlpage-${ref_scope}-linux-amd64-hurl-${recipe_hash}"
echo "current=sqlpage-${ref_scope}-linux-amd64-${recipe_hash}"
echo "main=sqlpage-main-linux-amd64-${recipe_hash}"
} >> "$GITHUB_OUTPUT"
- name: Login to Docker Hub
if: github.event_name != 'pull_request'
uses: docker/login-action@v4
with:
username: ${{ env.REGISTRY_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build image for Hurl examples
uses: docker/build-push-action@v7
with:
# Use BuildKit's Git context instead of the mutable runner workspace.
# The dependency cache should be keyed by committed source, not by a
# per-job local context stream.
context: "{{defaultContext}}"
platforms: linux/amd64
target: minimal
labels: ${{ steps.meta.outputs.labels }}
tags: |
${{ steps.meta.outputs.tags }}
${{ env.REGISTRY_IMAGE }}:main
outputs: type=docker,dest=${{ runner.temp }}/sqlpage.tar
cache-from: |
type=gha,scope=${{ steps.cache-scope.outputs.artifact }}
type=gha,scope=${{ steps.cache-scope.outputs.current }}
type=gha,scope=${{ steps.cache-scope.outputs.main }}
type=registry,ref=${{ env.REGISTRY_IMAGE }}:main-linux-amd64
cache-to: type=gha,scope=${{ steps.cache-scope.outputs.artifact }},mode=max
- name: Upload SQLPage image
uses: actions/upload-artifact@v7
with:
name: sqlpage-linux-amd64-minimal-image
path: ${{ runner.temp }}/sqlpage.tar
if-no-files-found: error
retention-days: 1
- name: Build and push by digest
id: build
if: github.event_name != 'pull_request'
uses: docker/build-push-action@v7
with:
# Use BuildKit's Git context instead of the mutable runner workspace.
# The dependency cache should be keyed by committed source, not by a
# per-job local context stream.
context: "{{defaultContext}}"
platforms: linux/amd64
target: minimal
labels: ${{ steps.meta.outputs.labels }}
push: true
tags: ${{ steps.meta.outputs.tags }}
cache-from: |
type=gha,scope=${{ steps.cache-scope.outputs.current }}
type=gha,scope=${{ steps.cache-scope.outputs.main }}
type=registry,ref=${{ env.REGISTRY_IMAGE }}:main-linux-amd64
cache-to: type=gha,scope=${{ steps.cache-scope.outputs.current }},mode=max
- name: Export digest
if: github.event_name != 'pull_request'
run: |
mkdir -p /tmp/digests
digest="${{ steps.build.outputs.digest }}"
touch "/tmp/digests/${digest#sha256:}"
- name: Upload digest
uses: actions/upload-artifact@v7
if: github.event_name != 'pull_request'
with:
name: digests-minimal-linux-amd64
path: /tmp/digests/*
if-no-files-found: error
retention-days: 1
hurl_examples:
runs-on: ubuntu-latest
outputs:
examples: ${{ steps.examples.outputs.examples }}
steps:
- uses: actions/checkout@v6
- id: examples
run: |
examples="$(find examples -mindepth 2 -maxdepth 2 -name test.hurl -print | sed 's#/test.hurl$##' | sort | jq -R -s -c 'split("\n")[:-1]')"
echo "examples=$examples" >> "$GITHUB_OUTPUT"
- name: Restore Hurl archive
id: hurl-cache
uses: actions/cache@v5
with:
path: .cache/hurl
key: hurl-${{ runner.os }}-x86_64-unknown-linux-gnu-${{ env.HURL_VERSION }}
- name: Download Hurl archive
if: steps.hurl-cache.outputs.cache-hit != 'true'
run: |
set -euo pipefail
archive="hurl-${HURL_VERSION}-x86_64-unknown-linux-gnu.tar.gz"
base_url="https://github.com/Orange-OpenSource/hurl/releases/download/${HURL_VERSION}"
mkdir -p .cache/hurl
curl --fail --location --retry 5 --retry-delay 2 --output ".cache/hurl/${archive}" "${base_url}/${archive}"
curl --fail --location --retry 5 --retry-delay 2 --output ".cache/hurl/${archive}.sha256" "${base_url}/${archive}.sha256"
(
cd .cache/hurl
expected_sha="$(tr -d '[:space:]' < "${archive}.sha256")"
actual_sha="$(sha256sum "$archive" | cut -d ' ' -f 1)"
test "$expected_sha" = "$actual_sha"
)
- name: Upload Hurl archive
uses: actions/upload-artifact@v7
with:
name: hurl-${{ env.HURL_VERSION }}-x86_64-unknown-linux-gnu
path: .cache/hurl/*
if-no-files-found: error
retention-days: 1
hurl:
name: hurl (${{ matrix.example }})
runs-on: ubuntu-latest
timeout-minutes: 15
needs:
- docker_build_amd64_minimal
- hurl_examples
strategy:
fail-fast: false
matrix:
example: ${{ fromJSON(needs.hurl_examples.outputs.examples) }}
steps:
- uses: actions/checkout@v6
- name: Download Hurl archive
uses: actions/download-artifact@v8
with:
name: hurl-${{ env.HURL_VERSION }}-x86_64-unknown-linux-gnu
path: ${{ runner.temp }}/hurl
- name: Install Hurl
run: |
set -euo pipefail
archive="hurl-${HURL_VERSION}-x86_64-unknown-linux-gnu.tar.gz"
(
cd "$RUNNER_TEMP/hurl"
expected_sha="$(tr -d '[:space:]' < "${archive}.sha256")"
actual_sha="$(sha256sum "$archive" | cut -d ' ' -f 1)"
test "$expected_sha" = "$actual_sha"
tar xzf "$archive" -C "$RUNNER_TEMP/hurl"
)
echo "$RUNNER_TEMP/hurl/hurl-${HURL_VERSION}-x86_64-unknown-linux-gnu/bin" >> "$GITHUB_PATH"
- name: Download SQLPage image
uses: actions/download-artifact@v8
with:
name: sqlpage-linux-amd64-minimal-image
path: ${{ runner.temp }}/sqlpage-image
- name: Load SQLPage image
run: |
docker load --input "${{ runner.temp }}/sqlpage-image/sqlpage.tar"
docker tag "${{ env.REGISTRY_IMAGE }}:main" "${{ env.REGISTRY_IMAGE }}:latest"
- name: Run example Hurl test
run: scripts/test-examples-hurl.sh "${{ matrix.example }}"
docker_push:
runs-on: ubuntu-latest
if: github.event_name != 'pull_request'
needs:
- docker_build_amd64_minimal
- docker_build
strategy:
matrix:
variant:
- minimal
- duckdb
steps:
- name: Download digests
uses: actions/download-artifact@v8
env:
NODE_OPTIONS: --no-deprecation
with:
pattern: digests-${{ matrix.variant }}*
merge-multiple: true
path: /tmp/digests
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4
- name: Docker meta
id: meta
uses: docker/metadata-action@v6
with:
images: ${{ env.REGISTRY_IMAGE }}
flavor: suffix=${{ matrix.variant != 'minimal' && format('-{0}', matrix.variant) || '' }}
- name: Login to Docker Hub
uses: docker/login-action@v4
with:
username: ${{ env.REGISTRY_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Create manifest list and push
working-directory: /tmp/digests
run: |
docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
$(printf '${{ env.REGISTRY_IMAGE }}@sha256:%s ' *)
- name: Inspect image
run: |
docker buildx imagetools inspect ${{ env.REGISTRY_IMAGE }}:${{ steps.meta.outputs.version }}