Repository navigation
build #1836
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: build | |
| on: | |
| push: | |
| branches: | |
| - main | |
| pull_request: | |
| schedule: | |
| - cron: "15 2,10,18 * * *" | |
| # GitHub disables a scheduled workflow after 60 days of repository | |
| # inactivity, which stops it running on pull requests too. Dispatch is | |
| # how to re-run it after that without pushing to a branch. | |
| workflow_dispatch: | |
| jobs: | |
| test: | |
| name: Build with Node.js ${{ matrix.node-version }} | |
| runs-on: ubuntu-latest | |
| strategy: | |
| matrix: | |
| node-version: [20, 22, latest] | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| with: | |
| submodules: recursive | |
| - name: Setup node | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: ${{ matrix.node-version }} | |
| - uses: pnpm/action-setup@v4 | |
| with: | |
| version: 10.12.4 | |
| run_install: true | |
| - name: Linting | |
| run: pnpm eslint | |
| # `pnpm format` writes; nothing verified the result, so formatting drifted | |
| # into files no other gate reads. | |
| - name: Formatting | |
| run: pnpm format:check | |
| - name: Type-checking | |
| run: pnpm typecheck | |
| # This contract uses DOM libraries with no @types/node and covers only | |
| # the source graph shipped in @questdb/browser-client. | |
| - name: Type-checking (browser) | |
| run: pnpm typecheck:qwp-browser | |
| # `pnpm typecheck` covers src plus a single contract file, so nothing | |
| # type-checked test/** at all: a test could reference a deleted export | |
| # and still pass, because vitest strips types without checking them. | |
| - name: Type-checking (tests) | |
| run: pnpm typecheck:test | |
| - name: Type-checking (benchmarks) | |
| run: pnpm typecheck:bench | |
| - name: Linting (benchmarks) | |
| run: pnpm lint:bench | |
| - name: Tests | |
| run: pnpm test | |
| # Loads the built bundles through package.json `exports`, the way a | |
| # consumer does, and verifies the two npm package boundaries. | |
| - name: Built package tests | |
| run: pnpm test:dist | |
| # test:dist asserts runtime behaviour only. The compiled writers promise | |
| # per-column row typing, which lives entirely in the emitted .d.ts files | |
| # and is therefore invisible to source-level tests, where the public | |
| # entries share one private-core module instance. | |
| - name: Type-checking (built package consumer) | |
| run: pnpm typecheck:dist | |
| # The same gate publish.yml runs. Keeping it here too means a chunk that | |
| # escapes `files`, or a regression in the check itself, fails a pull | |
| # request instead of first being discovered during a release. | |
| - name: Check for build artifacts | |
| run: node scripts/check-build-artifacts.mjs | |
| # Drives the built browser bundle in real Chromium against a local mock | |
| # server. Tests that need a live QuestDB belong in the server repositories, | |
| # where the topology and authentication fixtures already exist. | |
| qwp-browser: | |
| name: QWP browser bundle | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 10 | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| - name: Setup node | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: 20 | |
| - uses: pnpm/action-setup@v4 | |
| with: | |
| version: 10.12.4 | |
| run_install: true | |
| - name: Install Chromium | |
| run: pnpm exec playwright install --with-deps chromium | |
| - name: Browser bundle tests | |
| run: pnpm test:qwp-browser | |
| enterprise-qwp-e2e: | |
| name: Dispatch Enterprise QWP E2E | |
| runs-on: ubuntu-latest | |
| # Azure credentials are not exposed to fork PRs. The repository variable | |
| # keeps this dormant until the Enterprise pipeline and PAT are configured. | |
| if: >- | |
| vars.ENTERPRISE_E2E_ENABLED == 'true' && | |
| (github.event_name != 'pull_request' || | |
| github.event.pull_request.head.repo.full_name == github.repository) | |
| steps: | |
| - name: Queue Enterprise TypeScript-client E2E | |
| env: | |
| ENT_DISPATCH_PAT: ${{ secrets.ENT_DISPATCH_PAT }} | |
| CLIENT_COMMIT: ${{ github.event.pull_request.head.sha || github.sha }} | |
| CLIENT_PR_NUMBER: ${{ github.event.pull_request.number || '' }} | |
| CLIENT_BRANCH: ${{ github.head_ref || github.ref_name }} | |
| run: | | |
| set -euo pipefail | |
| if [ -z "${ENT_DISPATCH_PAT:-}" ]; then | |
| echo "ENT_DISPATCH_PAT is not configured" >&2 | |
| exit 1 | |
| fi | |
| ORG_URL="https://dev.azure.com/questdb/" | |
| PROJECT="questdb-enterprise" | |
| PIPELINE_NAME="build-and-test-e2e-javascript-client" | |
| # Azure explains a rejection in the response body. --fail-with-body | |
| # keeps it, but on stdout, which $(...) captures; under set -e the | |
| # step would exit before anything printed it. Each call therefore | |
| # reports the captured body itself when curl fails: Azure's JSON | |
| # `message` when it is a non-empty string, otherwise the start of the | |
| # body. The filter outputs nothing for anything else, so jq -e fails | |
| # without first printing `null` or another non-string value. | |
| # An empty body means curl failed before Azure answered (DNS, TLS, | |
| # connection) or Azure sent no explanation; curl's own -sS line | |
| # above then names the cause, so don't blame Azure for it. | |
| azure_failure() { | |
| if [ -z "$2" ]; then | |
| echo "The Azure DevOps $1 failed without a response body; see curl's error above." >&2 | |
| else | |
| echo "Azure DevOps rejected the $1: $( | |
| jq -er '.message | strings | select(length > 0)' <<<"$2" 2>/dev/null || | |
| head -c 500 <<<"$2" | |
| )" >&2 | |
| fi | |
| } | |
| if ! PIPELINES=$(curl --fail-with-body -sS -u ":${ENT_DISPATCH_PAT}" \ | |
| "${ORG_URL}${PROJECT}/_apis/pipelines?api-version=7.0"); then | |
| azure_failure "pipeline lookup" "$PIPELINES" | |
| exit 1 | |
| fi | |
| PIPELINE_ID=$(echo "$PIPELINES" | jq -r --arg name "$PIPELINE_NAME" \ | |
| '.value[] | select(.name == $name) | .id' | head -1) | |
| if [ -z "$PIPELINE_ID" ] || [ "$PIPELINE_ID" = "null" ]; then | |
| echo "Enterprise pipeline '$PIPELINE_NAME' is not registered" >&2 | |
| exit 1 | |
| fi | |
| BODY=$(jq -n \ | |
| --arg commit "$CLIENT_COMMIT" \ | |
| --arg pr "$CLIENT_PR_NUMBER" \ | |
| --arg branch "$CLIENT_BRANCH" \ | |
| '{ | |
| templateParameters: ( | |
| { | |
| javascriptClientCommit: $commit, | |
| clientBranch: $branch | |
| } | |
| # Azure rejects an empty string for a string parameter | |
| # ("is not a valid String", HTTP 400), which broke every | |
| # push, schedule and workflow_dispatch run. Omitting it | |
| # applies the pipeline default, which skips the GitHub | |
| # status post. | |
| + (if $pr == "" then {} else {javascriptClientPrNumber: $pr} end) | |
| ) | |
| }') | |
| if ! RESPONSE=$(curl --fail-with-body -sS -u ":${ENT_DISPATCH_PAT}" \ | |
| -H "Content-Type: application/json" \ | |
| -X POST \ | |
| -d "$BODY" \ | |
| "${ORG_URL}${PROJECT}/_apis/pipelines/${PIPELINE_ID}/runs?api-version=7.0"); then | |
| azure_failure "dispatch" "$RESPONSE" | |
| exit 1 | |
| fi | |
| echo "Enterprise E2E queued: $(echo "$RESPONSE" | jq -r '._links.web.href')" |