test(cli): cover sqlite-wasm store with graph-query round-trip #31
Workflow file for this run
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: Test Build | |
| # Pull request and dispatch workflow that exercises the full nightly pipeline | |
| # (shared build matrix + publish + manifest regen + flake check) against an | |
| # ISOLATED, auto-deleted prerelease. It never commits a manifest bump and never | |
| # touches main, so downstream consumers (which read the committed | |
| # data/logseq-nightly.json) cannot pick it up. Design: | |
| # docs/superpowers/specs/2026-06-03-test-build-workflow-design.md | |
| # | |
| # test-build-required is a required status check on main. Pull requests get it | |
| # from this workflow: it passes outright for docs-only change sets (the changes | |
| # job classifies the PR diff paths) and otherwise requires the full | |
| # approval+build+publish chain. Nightly manifest bumps (scheduled or manually | |
| # dispatched with publish_release=true) get the same context from nightly.yml | |
| # after the real publish-release path validates the generated manifest commit. | |
| # The approval job reads the PR labels live from the API instead of the event | |
| # payload, so the maintainer flow after adding | |
| # status(security-review-approved) is "Re-run failed jobs" on this workflow; | |
| # label events deliberately do not re-trigger the pipeline. | |
| on: | |
| pull_request: | |
| types: [opened, synchronize, reopened, ready_for_review] | |
| workflow_dispatch: | |
| inputs: | |
| logseq_branch: | |
| description: "Logseq branch to build" | |
| required: false | |
| default: master | |
| permissions: | |
| actions: read | |
| contents: write | |
| issues: read | |
| pull-requests: read | |
| concurrency: | |
| group: test-build-${{ github.event.pull_request.number || github.ref }} | |
| cancel-in-progress: true | |
| jobs: | |
| changes: | |
| name: changes | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 5 | |
| outputs: | |
| build: ${{ steps.classify.outputs.build }} | |
| steps: | |
| - name: Classify changed paths | |
| id: classify | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| EVENT_NAME: ${{ github.event_name }} | |
| REPO: ${{ github.repository }} | |
| PR_NUMBER: ${{ github.event.pull_request.number }} | |
| run: | | |
| set -euo pipefail | |
| if [ "$EVENT_NAME" != "pull_request" ]; then | |
| # Manual dispatch is an explicit ask for the full build. | |
| echo "build=true" >>"$GITHUB_OUTPUT" | |
| exit 0 | |
| fi | |
| # Relevance comes from the diff path list only; any path outside the | |
| # docs/meta allowlist requires the full build. Unknown new paths | |
| # therefore default to building. Capture the listing first so an API | |
| # failure aborts the job instead of silently classifying as docs-only. | |
| files="$(gh api --paginate "repos/${REPO}/pulls/${PR_NUMBER}/files" --jq '.[].filename')" | |
| build=false | |
| while IFS= read -r file; do | |
| [ -n "$file" ] || continue | |
| case "$file" in | |
| *.md | docs/* | .claude/* | LICENSE | .gitignore | .actrc) ;; | |
| *) | |
| echo "build-relevant change: $file" | |
| build=true | |
| ;; | |
| esac | |
| done <<<"$files" | |
| echo "build=$build" >>"$GITHUB_OUTPUT" | |
| test-build-approval: | |
| name: test-build-approval | |
| needs: changes | |
| if: needs.changes.outputs.build == 'true' | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 5 | |
| steps: | |
| - name: Require security approval label | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| EVENT_NAME: ${{ github.event_name }} | |
| REPO: ${{ github.repository }} | |
| PR_NUMBER: ${{ github.event.pull_request.number }} | |
| run: | | |
| set -euo pipefail | |
| if [ "$EVENT_NAME" != "pull_request" ]; then | |
| exit 0 | |
| fi | |
| # Read labels live instead of from the event payload so a re-run | |
| # picks up a label added after the run first failed. Capture first: | |
| # a pipe into grep -q can mask an API failure under pipefail. | |
| labels="$(gh api "repos/${REPO}/issues/${PR_NUMBER}/labels" --jq '.[].name')" | |
| if grep -qxF 'status(security-review-approved)' <<<"$labels"; then | |
| exit 0 | |
| fi | |
| echo "Missing required label: status(security-review-approved)" >&2 | |
| echo "Add the label, then re-run the failed jobs of this workflow." >&2 | |
| exit 1 | |
| build: | |
| needs: test-build-approval | |
| uses: ./.github/workflows/build-desktop.yml | |
| with: | |
| logseq_ref: ${{ github.event.inputs.logseq_branch || 'master' }} | |
| publish-test: | |
| runs-on: ubuntu-24.04 | |
| needs: build | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| persist-credentials: false | |
| - name: Download packaged builds | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: gh run download "${{ github.run_id }}" --repo "${{ github.repository }}" --dir builds | |
| # Composite defaults cover the isolated test flow: all systems, this | |
| # repo, tag test-<datestring>-<run_id>. | |
| - name: Resolve build metadata (isolated test tag) | |
| uses: ./.github/actions/resolve-build-metadata | |
| - name: Install Nix | |
| uses: cachix/install-nix-action@v31 | |
| with: | |
| extra_nix_config: | | |
| accept-flake-config = true | |
| - name: Setup Cachix (read-only, no push) | |
| uses: cachix/cachix-action@v17 | |
| with: | |
| name: nix-logseq-git-flake | |
| authToken: ${{ secrets.CACHIX_AUTH_TOKEN }} | |
| skipPush: true | |
| # Tag, notes, and assets come from the RELEASE_* env handoff exported | |
| # by resolve-build-metadata; the other defaults already fit a | |
| # disposable test prerelease. | |
| - name: Publish isolated test prerelease | |
| uses: ./.github/actions/publish-release-assets | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Regenerate manifest and CLI hashes | |
| run: bash scripts/update-nightly.sh | |
| - name: Format repository | |
| run: nix fmt | |
| - name: Validate flake against test release | |
| run: nix flake check | |
| - name: Capture regenerated manifest | |
| run: | | |
| set -euo pipefail | |
| mkdir -p test-out | |
| cp data/logseq-nightly.json test-out/logseq-nightly.json | |
| git --no-pager diff -- data/logseq-nightly.json >test-out/logseq-nightly.json.diff || true | |
| - name: Upload regenerated manifest | |
| uses: actions/upload-artifact@v6 | |
| with: | |
| name: test-manifest | |
| path: test-out/* | |
| if-no-files-found: error | |
| - name: Delete isolated test prerelease | |
| if: always() | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| set -euo pipefail | |
| if [ -n "${RELEASE_TAG:-}" ]; then | |
| gh release delete "$RELEASE_TAG" --cleanup-tag -y || true | |
| fi | |
| test-build-required: | |
| name: test-build-required | |
| runs-on: ubuntu-24.04 | |
| needs: [changes, test-build-approval, build, publish-test] | |
| if: always() | |
| steps: | |
| - name: Require successful test build | |
| env: | |
| CHANGES_RESULT: ${{ needs.changes.result }} | |
| BUILD_REQUIRED: ${{ needs.changes.outputs.build }} | |
| APPROVAL_RESULT: ${{ needs.test-build-approval.result }} | |
| BUILD_RESULT: ${{ needs.build.result }} | |
| PUBLISH_TEST_RESULT: ${{ needs.publish-test.result }} | |
| run: | | |
| set -euo pipefail | |
| # A failed classifier must fail the gate; otherwise its empty output | |
| # would read as "build not required" and waive the check. | |
| if [ "$CHANGES_RESULT" != "success" ]; then | |
| echo "changes result: $CHANGES_RESULT" >&2 | |
| exit 1 | |
| fi | |
| if [ "$BUILD_REQUIRED" != "true" ]; then | |
| echo "No build-relevant changes; test build not required." | |
| exit 0 | |
| fi | |
| if [ "$APPROVAL_RESULT" != "success" ] || [ "$BUILD_RESULT" != "success" ] || [ "$PUBLISH_TEST_RESULT" != "success" ]; then | |
| echo "test-build-approval result: $APPROVAL_RESULT" >&2 | |
| echo "build result: $BUILD_RESULT" >&2 | |
| echo "publish-test result: $PUBLISH_TEST_RESULT" >&2 | |
| exit 1 | |
| fi |