name: PR Build Validation on: pull_request: types: - opened - edited - synchronize - reopened - ready_for_review permissions: contents: read actions: write concurrency: group: pr-build-${{ github.event.pull_request.number }} cancel-in-progress: true jobs: authorize: runs-on: ubuntu-latest outputs: allowed: ${{ steps.auth.outputs.allowed }} env: ALLOWED_ACTORS: ${{ vars.ALLOWED_NON_DEV_PR_ACTORS }} PR_AUTHOR: ${{ github.event.pull_request.user.login }} BASE_REF: ${{ github.event.pull_request.base.ref }} steps: - name: Check PR authorization id: auth shell: bash run: | set -euo pipefail if [ "$BASE_REF" = "dev" ]; then echo "allowed=true" >> "$GITHUB_OUTPUT" exit 0 fi normalized=",${ALLOWED_ACTORS}," if [[ "$normalized" == *",${PR_AUTHOR},"* ]]; then echo "allowed=true" >> "$GITHUB_OUTPUT" else echo "allowed=false" >> "$GITHUB_OUTPUT" echo "Skipping builds for PR by unauthorized author targeting $BASE_REF" >&2 fi build: needs: - authorize - tests - tests-tauri-windows if: ${{ needs.authorize.outputs.allowed == 'true' && !github.event.pull_request.draft }} uses: ./.github/workflows/build-and-upload.yml with: ref: ${{ github.event.pull_request.head.sha }} upload: false upload_actions_artifacts: true actions_artifacts_retention_days: 7 actions_artifacts_name_prefix: pr-${{ github.event.pull_request.number }}-${{ github.event.pull_request.head.sha }}- set_versions: false tests: needs: authorize if: ${{ needs.authorize.outputs.allowed == 'true' && !github.event.pull_request.draft }} runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 with: ref: ${{ github.event.pull_request.head.sha }} - name: Setup Node uses: actions/setup-node@v4 with: node-version: 22 cache: npm - name: Setup Rust uses: dtolnay/rust-toolchain@stable - name: Install Linux test dependencies (Tauri) run: | sudo apt-get update sudo apt-get install -y \ build-essential \ pkg-config \ libgtk-3-dev \ libglib2.0-dev \ libwebkit2gtk-4.1-dev \ libsoup-3.0-dev \ libayatana-appindicator3-dev \ librsvg2-dev - name: Install dependencies run: npm ci - name: Typecheck desktop clients run: npm run typecheck - name: Test Electron client state run: npm run test:native --workspace @neuralnomads/codenomad-electron-app - name: Test changed runnable UI behavior run: >- node --import tsx --test packages/ui/src/components/session-list-visibility.test.ts packages/ui/src/lib/hooks/use-app-session-capture.test.ts packages/ui/src/lib/message-selection-position.test.ts packages/ui/src/lib/trailing-resync.test.ts packages/ui/src/stores/abort-created-workspace-cleanup.test.ts packages/ui/src/stores/app-session-reconciliation.test.ts packages/ui/src/stores/app-session-restore-gate.test.ts packages/ui/src/stores/app-session-restore-queue.test.ts packages/ui/src/stores/app-session-restore-timeout.test.ts packages/ui/src/stores/app-session-snapshot-merge.test.ts packages/ui/src/stores/restore-workspace-commit-gates.test.ts packages/ui/src/stores/client-state-codec.test.ts packages/ui/src/stores/client-state.test.ts packages/ui/src/stores/instances-restore-cancellation.test.ts packages/ui/src/stores/message-v2/message-hydration-authority.test.ts packages/ui/src/stores/session-generation-recovery.test.ts packages/ui/src/stores/session-metadata.test.ts packages/ui/src/stores/session-pagination.test.ts packages/ui/src/stores/workspace-list-reconciliation-fence.test.ts - name: Test restore ownership integration run: >- node --conditions=browser --import tsx --test --test-force-exit packages/ui/src/stores/instances-restore-ownership.test.ts packages/ui/src/stores/permission-lifecycle.test.ts - name: Test server run: node --import tsx --test "packages/server/src/**/*.test.ts" - name: Prepare Tauri test resources run: >- npm run dev:prep --workspace @codenomad/tauri-app && node -e "require('fs').mkdirSync('packages/tauri-app/src-tauri/resources/server',{recursive:true})" - name: Test Tauri crate working-directory: packages/tauri-app/src-tauri run: cargo test --locked tests-tauri-windows: needs: authorize if: ${{ needs.authorize.outputs.allowed == 'true' && !github.event.pull_request.draft }} runs-on: windows-latest steps: - name: Checkout uses: actions/checkout@v4 with: ref: ${{ github.event.pull_request.head.sha }} - name: Setup Node uses: actions/setup-node@v4 with: node-version: 22 cache: npm - name: Setup Rust uses: dtolnay/rust-toolchain@stable - name: Install dependencies run: npm ci - name: Test Windows server spawn behavior run: node --import tsx --test packages/server/src/workspaces/__tests__/spawn.test.ts - name: Prepare Tauri test resources run: >- npm run dev:prep --workspace @codenomad/tauri-app && node -e "require('fs').mkdirSync('packages/tauri-app/src-tauri/resources/server',{recursive:true})" - name: Test Tauri crate on Windows working-directory: packages/tauri-app/src-tauri run: cargo test --locked