From 09a8fabb8ecaf6764fd6282154a3ba383da338a0 Mon Sep 17 00:00:00 2001 From: Marvin Froeder Date: Thu, 14 May 2026 09:57:31 -0300 Subject: [PATCH 1/4] ci: Validate datasqrl-examples against snapshot images and auto-bump on release Signed-off-by: Marvin Froeder --- .circleci/config.yml | 10 ++- .github/workflows/build.yml | 78 +++++++++++++++++++ .github/workflows/bump-examples-version.yml | 84 +++++++++++++++++++++ 3 files changed, 168 insertions(+), 4 deletions(-) create mode 100644 .github/workflows/bump-examples-version.yml diff --git a/.circleci/config.yml b/.circleci/config.yml index 4379248b4..be723e466 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -400,10 +400,12 @@ jobs: name: Skip image generation command: | set -x - - # Push to Docker Hub for tagged releases and main=:dev. - if [ "$IS_RELEASE" != "true" ] && [ "$TAG_SUFFIX" != "dev" ]; then - echo "Skipping image publishing for TAG_SUFFIX=$TAG_SUFFIX (only tagged releases and main=:dev are published)." + + # Push to Docker Hub for tagged releases (datasqrl/*) and main=:dev (datasqrl/*). + # Push PR images to ghcr.io/datasqrl/* so downstream CI (e.g. datasqrl-examples) can + # validate examples against the snapshot built from this PR. + if [ "$IS_RELEASE" != "true" ] && [ "$TAG_SUFFIX" != "dev" ] && [[ "$TAG_SUFFIX" != pr-* ]]; then + echo "Skipping image publishing for TAG_SUFFIX=$TAG_SUFFIX (only tagged releases, main=:dev, and pr-* are published)." circleci step halt fi - restore_cache: diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index fc822ac7f..01ce19f41 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -141,3 +141,81 @@ jobs: echo "----------------------------------------" sleep 20 done + + examples-validation: + needs: [check-changes, build] + if: needs.check-changes.outputs.has-code == 'true' + runs-on: ubuntu-latest + timeout-minutes: 60 + steps: + - name: Determine SQRL image to validate + id: image + run: | + if [ "${{ github.event_name }}" = "pull_request" ]; then + IMAGE="ghcr.io/datasqrl/cmd:pr-${{ github.event.pull_request.number }}" + else + IMAGE="datasqrl/cmd:dev" + fi + echo "image=$IMAGE" + echo "image=$IMAGE" >> "$GITHUB_OUTPUT" + + - name: Trigger datasqrl-examples build + id: dispatch + env: + GH_TOKEN: ${{ secrets.BOT_PAT }} + SQRL_IMAGE: ${{ steps.image.outputs.image }} + CORRELATION_ID: ${{ github.repository }}-${{ github.run_id }}-${{ github.run_attempt }} + run: | + set -euo pipefail + echo "Dispatching datasqrl-examples build with image=$SQRL_IMAGE correlation_id=$CORRELATION_ID" + + gh workflow run build.yml \ + --repo DataSQRL/datasqrl-examples \ + --ref main \ + --field sqrl_image="$SQRL_IMAGE" \ + --field correlation_id="$CORRELATION_ID" + + echo "correlation_id=$CORRELATION_ID" >> "$GITHUB_OUTPUT" + + - name: Locate dispatched run + id: locate + env: + GH_TOKEN: ${{ secrets.BOT_PAT }} + CORRELATION_ID: ${{ steps.dispatch.outputs.correlation_id }} + run: | + set -euo pipefail + + # The workflow_dispatch endpoint is asynchronous and does not return a run id, + # so we look it up by the run-name we encoded in datasqrl-examples build.yml: + # run-name: examples build [] + EXPECTED_NAME="examples build [${CORRELATION_ID}]" + + for attempt in $(seq 1 30); do + RUN_ID=$(gh api \ + "/repos/DataSQRL/datasqrl-examples/actions/workflows/build.yml/runs?event=workflow_dispatch&per_page=20" \ + --jq ".workflow_runs[] | select(.display_title == \"${EXPECTED_NAME}\") | .id" \ + | head -n1) + + if [ -n "$RUN_ID" ]; then + echo "Found run id: $RUN_ID" + echo "run_id=$RUN_ID" >> "$GITHUB_OUTPUT" + exit 0 + fi + + echo "Run not yet visible (attempt $attempt/30); waiting 10s..." + sleep 10 + done + + echo "Could not locate the dispatched workflow run with title '${EXPECTED_NAME}'" >&2 + exit 1 + + - name: Wait for datasqrl-examples build to finish + env: + GH_TOKEN: ${{ secrets.BOT_PAT }} + RUN_ID: ${{ steps.locate.outputs.run_id }} + run: | + set -euo pipefail + echo "Watching datasqrl-examples run https://github.com/DataSQRL/datasqrl-examples/actions/runs/${RUN_ID}" + gh run watch "$RUN_ID" \ + --repo DataSQRL/datasqrl-examples \ + --exit-status diff --git a/.github/workflows/bump-examples-version.yml b/.github/workflows/bump-examples-version.yml new file mode 100644 index 000000000..91e39b719 --- /dev/null +++ b/.github/workflows/bump-examples-version.yml @@ -0,0 +1,84 @@ +name: Bump SQRL version in datasqrl-examples + +on: + release: + types: [published] + workflow_dispatch: + inputs: + version: + description: "SQRL version to set in datasqrl-examples (without leading v)" + required: true + +jobs: + open-bump-pr: + runs-on: ubuntu-latest + timeout-minutes: 10 + steps: + - name: Resolve version + id: version + run: | + if [ -n "${{ inputs.version }}" ]; then + RAW="${{ inputs.version }}" + else + RAW="${{ github.event.release.tag_name }}" + fi + VERSION="${RAW#v}" + if [ -z "$VERSION" ]; then + echo "Empty version, aborting." >&2 + exit 1 + fi + echo "version=$VERSION" >> "$GITHUB_OUTPUT" + + - name: Checkout datasqrl-examples + uses: actions/checkout@v4 + with: + repository: DataSQRL/datasqrl-examples + token: ${{ secrets.BOT_PAT }} + path: datasqrl-examples + + - name: Bump SQRL_VERSION and open PR + working-directory: datasqrl-examples + env: + GH_TOKEN: ${{ secrets.BOT_PAT }} + VERSION: ${{ steps.version.outputs.version }} + run: | + set -euo pipefail + + BRANCH="bump-sqrl-${VERSION}" + + git config user.name "datasqrl-bot" + git config user.email "bot@datasqrl.com" + + # If a PR for this version already exists, do nothing. + if gh pr list --state open --head "$BRANCH" --json number --jq 'length' | grep -q '^[1-9]'; then + echo "PR for branch $BRANCH already open; nothing to do." + exit 0 + fi + + # Recreate the branch fresh from default branch. + DEFAULT_BRANCH=$(gh repo view --json defaultBranchRef --jq '.defaultBranchRef.name') + git fetch origin "$DEFAULT_BRANCH" + git checkout -B "$BRANCH" "origin/${DEFAULT_BRANCH}" + + # Idempotent sed against the CI workflow env block. + sed -i -E "s/^( SQRL_VERSION: ).*/\1'${VERSION}'/" .github/workflows/build.yml + + if git diff --quiet .github/workflows/build.yml; then + echo "SQRL_VERSION already set to ${VERSION}; nothing to do." + exit 0 + fi + + git add .github/workflows/build.yml + git commit -s -m "Bump SQRL version to ${VERSION}" + git push --force-with-lease -u origin "$BRANCH" + + gh pr create \ + --title "Bump SQRL version to ${VERSION}" \ + --body "## Summary + - Bump \`SQRL_VERSION\` in CI workflow from previous value to \`${VERSION}\` + + Triggered automatically by the release of [\`${VERSION}\`](https://github.com/DataSQRL/sqrl/releases/tag/${VERSION}) in DataSQRL/sqrl. + + ## Test plan + - [ ] CI build matrix passes against \`datasqrl/cmd:${VERSION}\`" \ + --head "$BRANCH" From 3a0d4a72964cc5a1ffa45ba3032dbae0e42c1906 Mon Sep 17 00:00:00 2001 From: Marvin Froeder Date: Thu, 14 May 2026 12:34:44 -0300 Subject: [PATCH 2/4] ci: Switch examples cross-repo secret to EXAMPLES_BOT_PAT Signed-off-by: Marvin Froeder --- .github/workflows/build.yml | 6 +++--- .github/workflows/bump-examples-version.yml | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 01ce19f41..fb79b2227 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -162,7 +162,7 @@ jobs: - name: Trigger datasqrl-examples build id: dispatch env: - GH_TOKEN: ${{ secrets.BOT_PAT }} + GH_TOKEN: ${{ secrets.EXAMPLES_BOT_PAT }} SQRL_IMAGE: ${{ steps.image.outputs.image }} CORRELATION_ID: ${{ github.repository }}-${{ github.run_id }}-${{ github.run_attempt }} run: | @@ -180,7 +180,7 @@ jobs: - name: Locate dispatched run id: locate env: - GH_TOKEN: ${{ secrets.BOT_PAT }} + GH_TOKEN: ${{ secrets.EXAMPLES_BOT_PAT }} CORRELATION_ID: ${{ steps.dispatch.outputs.correlation_id }} run: | set -euo pipefail @@ -211,7 +211,7 @@ jobs: - name: Wait for datasqrl-examples build to finish env: - GH_TOKEN: ${{ secrets.BOT_PAT }} + GH_TOKEN: ${{ secrets.EXAMPLES_BOT_PAT }} RUN_ID: ${{ steps.locate.outputs.run_id }} run: | set -euo pipefail diff --git a/.github/workflows/bump-examples-version.yml b/.github/workflows/bump-examples-version.yml index 91e39b719..270512ed7 100644 --- a/.github/workflows/bump-examples-version.yml +++ b/.github/workflows/bump-examples-version.yml @@ -33,13 +33,13 @@ jobs: uses: actions/checkout@v4 with: repository: DataSQRL/datasqrl-examples - token: ${{ secrets.BOT_PAT }} + token: ${{ secrets.EXAMPLES_BOT_PAT }} path: datasqrl-examples - name: Bump SQRL_VERSION and open PR working-directory: datasqrl-examples env: - GH_TOKEN: ${{ secrets.BOT_PAT }} + GH_TOKEN: ${{ secrets.EXAMPLES_BOT_PAT }} VERSION: ${{ steps.version.outputs.version }} run: | set -euo pipefail From 46b6f994d3db7cfb89e9bb06b80cabd1fff999bf Mon Sep 17 00:00:00 2001 From: Marvin Froeder Date: Thu, 14 May 2026 12:40:40 -0300 Subject: [PATCH 3/4] ci: Move examples-validation dispatch+wait from GitHub Actions into CircleCI Signed-off-by: Marvin Froeder --- .circleci/config.yml | 73 ++++++++++++++++++++++++++++++++++ .github/workflows/build.yml | 79 +------------------------------------ 2 files changed, 74 insertions(+), 78 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index be723e466..0d5ebb51d 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -555,6 +555,75 @@ jobs: -f sqrl-cli/Dockerfile.base \ sqrl-cli + examples-validation: + docker: + - image: cimg/base:current + steps: + - skip-if-docs-only + - determine-version + - run: + name: Install GitHub CLI + command: | + type -p gh >/dev/null && exit 0 + curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg \ + | sudo dd of=/usr/share/keyrings/githubcli-archive-keyring.gpg + sudo chmod go+r /usr/share/keyrings/githubcli-archive-keyring.gpg + echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" \ + | sudo tee /etc/apt/sources.list.d/github-cli.list > /dev/null + sudo apt-get update -qq + sudo apt-get install -y gh + - run: + name: Dispatch datasqrl-examples build against this image and wait + command: | + set -euo pipefail + + # Resolve which image the downstream build should pull. Mirrors the + # logic in determine-version: PRs => ghcr.io/datasqrl/cmd:pr-N, + # main => datasqrl/cmd:dev, tags => datasqrl/cmd:. + if [ "$IS_RELEASE" = "true" ]; then + IMAGE="datasqrl/cmd:${CIRCLE_TAG}" + elif [ "$TAG_SUFFIX" = "dev" ]; then + IMAGE="datasqrl/cmd:dev" + else + IMAGE="ghcr.io/datasqrl/cmd:${TAG_SUFFIX}" + fi + + CORRELATION_ID="sqrl-${CIRCLE_BUILD_NUM}-${CIRCLE_WORKFLOW_ID:0:8}" + EXPECTED_NAME="examples build [${CORRELATION_ID}]" + + export GH_TOKEN="$EXAMPLES_BOT_PAT" + + echo "Dispatching datasqrl-examples build:" + echo " image=$IMAGE" + echo " correlation_id=$CORRELATION_ID" + + gh workflow run build.yml \ + --repo DataSQRL/datasqrl-examples \ + --ref main \ + --field sqrl_image="$IMAGE" \ + --field correlation_id="$CORRELATION_ID" + + # workflow_dispatch is async and returns no run id, so locate by + # the run-name datasqrl-examples sets: "examples build []". + RUN_ID="" + for attempt in $(seq 1 30); do + RUN_ID=$(gh api \ + "/repos/DataSQRL/datasqrl-examples/actions/workflows/build.yml/runs?event=workflow_dispatch&per_page=20" \ + --jq ".workflow_runs[] | select(.display_title == \"${EXPECTED_NAME}\") | .id" \ + | head -n1) + [ -n "$RUN_ID" ] && break + echo "Run not yet visible (attempt $attempt/30); sleeping 10s..." + sleep 10 + done + + if [ -z "$RUN_ID" ]; then + echo "Could not locate dispatched run for '${EXPECTED_NAME}'" >&2 + exit 1 + fi + + echo "Watching https://github.com/DataSQRL/datasqrl-examples/actions/runs/${RUN_ID}" + gh run watch "$RUN_ID" --repo DataSQRL/datasqrl-examples --exit-status + docker-build-mcp-inspector: machine: image: ubuntu-2404:current @@ -639,6 +708,10 @@ workflows: - download-maven-dependencies - docker-build-duckdb-extensions - docker-build-base-image + - examples-validation: + <<: *job-defaults + requires: + - build-images - deploy: <<: *job-defaults requires: diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index fb79b2227..6d91e3283 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -87,6 +87,7 @@ jobs: "ci/circleci: integration-tests-1-2" "ci/circleci: container-e2e-test" "ci/circleci: build-images" + "ci/circleci: examples-validation" "ci/circleci: deploy" ) @@ -141,81 +142,3 @@ jobs: echo "----------------------------------------" sleep 20 done - - examples-validation: - needs: [check-changes, build] - if: needs.check-changes.outputs.has-code == 'true' - runs-on: ubuntu-latest - timeout-minutes: 60 - steps: - - name: Determine SQRL image to validate - id: image - run: | - if [ "${{ github.event_name }}" = "pull_request" ]; then - IMAGE="ghcr.io/datasqrl/cmd:pr-${{ github.event.pull_request.number }}" - else - IMAGE="datasqrl/cmd:dev" - fi - echo "image=$IMAGE" - echo "image=$IMAGE" >> "$GITHUB_OUTPUT" - - - name: Trigger datasqrl-examples build - id: dispatch - env: - GH_TOKEN: ${{ secrets.EXAMPLES_BOT_PAT }} - SQRL_IMAGE: ${{ steps.image.outputs.image }} - CORRELATION_ID: ${{ github.repository }}-${{ github.run_id }}-${{ github.run_attempt }} - run: | - set -euo pipefail - echo "Dispatching datasqrl-examples build with image=$SQRL_IMAGE correlation_id=$CORRELATION_ID" - - gh workflow run build.yml \ - --repo DataSQRL/datasqrl-examples \ - --ref main \ - --field sqrl_image="$SQRL_IMAGE" \ - --field correlation_id="$CORRELATION_ID" - - echo "correlation_id=$CORRELATION_ID" >> "$GITHUB_OUTPUT" - - - name: Locate dispatched run - id: locate - env: - GH_TOKEN: ${{ secrets.EXAMPLES_BOT_PAT }} - CORRELATION_ID: ${{ steps.dispatch.outputs.correlation_id }} - run: | - set -euo pipefail - - # The workflow_dispatch endpoint is asynchronous and does not return a run id, - # so we look it up by the run-name we encoded in datasqrl-examples build.yml: - # run-name: examples build [] - EXPECTED_NAME="examples build [${CORRELATION_ID}]" - - for attempt in $(seq 1 30); do - RUN_ID=$(gh api \ - "/repos/DataSQRL/datasqrl-examples/actions/workflows/build.yml/runs?event=workflow_dispatch&per_page=20" \ - --jq ".workflow_runs[] | select(.display_title == \"${EXPECTED_NAME}\") | .id" \ - | head -n1) - - if [ -n "$RUN_ID" ]; then - echo "Found run id: $RUN_ID" - echo "run_id=$RUN_ID" >> "$GITHUB_OUTPUT" - exit 0 - fi - - echo "Run not yet visible (attempt $attempt/30); waiting 10s..." - sleep 10 - done - - echo "Could not locate the dispatched workflow run with title '${EXPECTED_NAME}'" >&2 - exit 1 - - - name: Wait for datasqrl-examples build to finish - env: - GH_TOKEN: ${{ secrets.EXAMPLES_BOT_PAT }} - RUN_ID: ${{ steps.locate.outputs.run_id }} - run: | - set -euo pipefail - echo "Watching datasqrl-examples run https://github.com/DataSQRL/datasqrl-examples/actions/runs/${RUN_ID}" - gh run watch "$RUN_ID" \ - --repo DataSQRL/datasqrl-examples \ - --exit-status From 56f8276d23ff1851fcb76913f8ccb0c783b594a1 Mon Sep 17 00:00:00 2001 From: Ferenc Csaky Date: Thu, 21 May 2026 13:48:30 +0200 Subject: [PATCH 4/4] Trigger the examples validation manually and detach it from circleci --- .circleci/config.yml | 74 ------------------- .github/workflows/build.yml | 1 - .github/workflows/validate-examples.yml | 94 +++++++++++++++++++++++++ 3 files changed, 94 insertions(+), 75 deletions(-) create mode 100644 .github/workflows/validate-examples.yml diff --git a/.circleci/config.yml b/.circleci/config.yml index 0d5ebb51d..e4a23a266 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -555,75 +555,6 @@ jobs: -f sqrl-cli/Dockerfile.base \ sqrl-cli - examples-validation: - docker: - - image: cimg/base:current - steps: - - skip-if-docs-only - - determine-version - - run: - name: Install GitHub CLI - command: | - type -p gh >/dev/null && exit 0 - curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg \ - | sudo dd of=/usr/share/keyrings/githubcli-archive-keyring.gpg - sudo chmod go+r /usr/share/keyrings/githubcli-archive-keyring.gpg - echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" \ - | sudo tee /etc/apt/sources.list.d/github-cli.list > /dev/null - sudo apt-get update -qq - sudo apt-get install -y gh - - run: - name: Dispatch datasqrl-examples build against this image and wait - command: | - set -euo pipefail - - # Resolve which image the downstream build should pull. Mirrors the - # logic in determine-version: PRs => ghcr.io/datasqrl/cmd:pr-N, - # main => datasqrl/cmd:dev, tags => datasqrl/cmd:. - if [ "$IS_RELEASE" = "true" ]; then - IMAGE="datasqrl/cmd:${CIRCLE_TAG}" - elif [ "$TAG_SUFFIX" = "dev" ]; then - IMAGE="datasqrl/cmd:dev" - else - IMAGE="ghcr.io/datasqrl/cmd:${TAG_SUFFIX}" - fi - - CORRELATION_ID="sqrl-${CIRCLE_BUILD_NUM}-${CIRCLE_WORKFLOW_ID:0:8}" - EXPECTED_NAME="examples build [${CORRELATION_ID}]" - - export GH_TOKEN="$EXAMPLES_BOT_PAT" - - echo "Dispatching datasqrl-examples build:" - echo " image=$IMAGE" - echo " correlation_id=$CORRELATION_ID" - - gh workflow run build.yml \ - --repo DataSQRL/datasqrl-examples \ - --ref main \ - --field sqrl_image="$IMAGE" \ - --field correlation_id="$CORRELATION_ID" - - # workflow_dispatch is async and returns no run id, so locate by - # the run-name datasqrl-examples sets: "examples build []". - RUN_ID="" - for attempt in $(seq 1 30); do - RUN_ID=$(gh api \ - "/repos/DataSQRL/datasqrl-examples/actions/workflows/build.yml/runs?event=workflow_dispatch&per_page=20" \ - --jq ".workflow_runs[] | select(.display_title == \"${EXPECTED_NAME}\") | .id" \ - | head -n1) - [ -n "$RUN_ID" ] && break - echo "Run not yet visible (attempt $attempt/30); sleeping 10s..." - sleep 10 - done - - if [ -z "$RUN_ID" ]; then - echo "Could not locate dispatched run for '${EXPECTED_NAME}'" >&2 - exit 1 - fi - - echo "Watching https://github.com/DataSQRL/datasqrl-examples/actions/runs/${RUN_ID}" - gh run watch "$RUN_ID" --repo DataSQRL/datasqrl-examples --exit-status - docker-build-mcp-inspector: machine: image: ubuntu-2404:current @@ -708,10 +639,6 @@ workflows: - download-maven-dependencies - docker-build-duckdb-extensions - docker-build-base-image - - examples-validation: - <<: *job-defaults - requires: - - build-images - deploy: <<: *job-defaults requires: @@ -725,4 +652,3 @@ workflows: ignore: /.*/ requires: - download-maven-dependencies - diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 6d91e3283..fc822ac7f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -87,7 +87,6 @@ jobs: "ci/circleci: integration-tests-1-2" "ci/circleci: container-e2e-test" "ci/circleci: build-images" - "ci/circleci: examples-validation" "ci/circleci: deploy" ) diff --git a/.github/workflows/validate-examples.yml b/.github/workflows/validate-examples.yml new file mode 100644 index 000000000..7428ad7f0 --- /dev/null +++ b/.github/workflows/validate-examples.yml @@ -0,0 +1,94 @@ +name: Validate datasqrl-examples + +on: + workflow_dispatch: + inputs: + sqrl_image: + description: "Full SQRL CLI image reference to validate, for example ghcr.io/datasqrl/cmd:pr-123 or datasqrl/cmd:dev" + required: false + default: datasqrl/cmd:dev + examples_ref: + description: "The datasqrl-examples ref to run" + required: false + default: main + correlation_id: + description: "Optional correlation ID for the dispatched datasqrl-examples run" + required: false + default: "" + +jobs: + validate-examples: + runs-on: ubuntu-latest + timeout-minutes: 60 + permissions: + contents: read + steps: + - name: Dispatch datasqrl-examples build and wait + env: + GH_TOKEN: ${{ secrets.EXAMPLES_BOT_PAT }} + SQRL_IMAGE: ${{ inputs.sqrl_image }} + EXAMPLES_REF: ${{ inputs.examples_ref }} + INPUT_CORRELATION_ID: ${{ inputs.correlation_id }} + run: | + set -euo pipefail + + if [ -z "$GH_TOKEN" ]; then + echo "EXAMPLES_BOT_PAT is required to dispatch datasqrl-examples" >&2 + exit 1 + fi + + if [ -z "$SQRL_IMAGE" ]; then + echo "sqrl_image is required" >&2 + exit 1 + fi + + if [ -z "$EXAMPLES_REF" ]; then + echo "examples_ref is required" >&2 + exit 1 + fi + + if [ -n "$INPUT_CORRELATION_ID" ]; then + CORRELATION_ID="$INPUT_CORRELATION_ID" + else + CORRELATION_ID="sqrl-gha-${GITHUB_RUN_ID}-${GITHUB_RUN_ATTEMPT}" + fi + + if [[ ! "$CORRELATION_ID" =~ ^[A-Za-z0-9._:-]+$ ]]; then + echo "correlation_id may only contain letters, numbers, '.', '_', ':', and '-'" >&2 + exit 1 + fi + + EXPECTED_NAME="examples build [${CORRELATION_ID}]" + + echo "Dispatching datasqrl-examples build:" + echo " sqrl_image=$SQRL_IMAGE" + echo " examples_ref=$EXAMPLES_REF" + echo " correlation_id=$CORRELATION_ID" + + gh workflow run build.yml \ + --repo DataSQRL/datasqrl-examples \ + --ref "$EXAMPLES_REF" \ + --field sqrl_image="$SQRL_IMAGE" \ + --field correlation_id="$CORRELATION_ID" + + # workflow_dispatch is async and returns no run id, so locate by the + # run-name datasqrl-examples sets: "examples build []". + RUN_ID="" + for attempt in $(seq 1 30); do + RUN_ID=$(gh api \ + "/repos/DataSQRL/datasqrl-examples/actions/workflows/build.yml/runs?event=workflow_dispatch&per_page=100" \ + --jq "[.workflow_runs[] | select(.display_title == \"${EXPECTED_NAME}\") | .id][0] // \"\"") + + [ -n "$RUN_ID" ] && break + + echo "Run not yet visible (attempt $attempt/30); sleeping 10s..." + sleep 10 + done + + if [ -z "$RUN_ID" ]; then + echo "Could not locate dispatched run for '${EXPECTED_NAME}'" >&2 + exit 1 + fi + + echo "Watching https://github.com/DataSQRL/datasqrl-examples/actions/runs/${RUN_ID}" + gh run watch "$RUN_ID" --repo DataSQRL/datasqrl-examples --exit-status