Add per-user agent runtime binding #9555
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: CI | |
| on: | |
| push: | |
| branches: [main] | |
| pull_request: | |
| branches: [main] | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} | |
| cancel-in-progress: true | |
| jobs: | |
| # Decides whether the (heavy, ~6min) frontend job has anything to do. | |
| # The frontend job validates the web/desktop apps, the shared packages, | |
| # the install graph, and the selfhost / reserved-slugs scripts it runs; | |
| # a pure backend-only or docs-only PR touches none of those and gains | |
| # nothing from a full web build. This job emits a single `frontend` | |
| # output consumed by the frontend job below. | |
| changes: | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| pull-requests: read | |
| outputs: | |
| frontend: ${{ steps.decide.outputs.frontend }} | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v6 | |
| - name: Filter paths | |
| id: filter | |
| uses: dorny/paths-filter@v3 | |
| with: | |
| # apps/docs is excluded from the frontend turbo run, so a | |
| # docs-only change does not need this job. apps/mobile has its | |
| # own mobile-verify workflow. Everything else the frontend job | |
| # touches is listed here; bias toward over-matching since a | |
| # missed path silently skips validation. | |
| filters: | | |
| frontend: | |
| - 'apps/web/**' | |
| - 'apps/desktop/**' | |
| - 'packages/**' | |
| - 'package.json' | |
| - '.npmrc' | |
| - 'pnpm-lock.yaml' | |
| - 'pnpm-workspace.yaml' | |
| - 'turbo.json' | |
| - '.github/workflows/ci.yml' | |
| - 'scripts/generate-reserved-slugs.mjs' | |
| - 'server/internal/handler/reserved_slugs.json' | |
| - 'scripts/selfhost-config.test.sh' | |
| - 'scripts/check.sh' | |
| - 'scripts/dev.sh' | |
| - 'scripts/local-env.sh' | |
| - '.env.example' | |
| - 'docker-compose.selfhost.yml' | |
| - name: Decide | |
| id: decide | |
| # Always run the frontend job on push to main (full validation); | |
| # on pull_request, run only when frontend-relevant paths changed. | |
| # The frontend job itself always runs and reports success — its | |
| # steps are gated on this output rather than the job being skipped | |
| # — so the required "frontend" status check is satisfied with a | |
| # genuine green instead of being left pending on filtered PRs. | |
| env: | |
| EVENT_NAME: ${{ github.event_name }} | |
| FRONTEND_CHANGED: ${{ steps.filter.outputs.frontend }} | |
| run: | | |
| if [ "$EVENT_NAME" != "pull_request" ] || [ "$FRONTEND_CHANGED" = "true" ]; then | |
| echo "frontend=true" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "frontend=false" >> "$GITHUB_OUTPUT" | |
| fi | |
| frontend: | |
| needs: changes | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout | |
| if: ${{ needs.changes.outputs.frontend == 'true' }} | |
| uses: actions/checkout@v6 | |
| - name: Setup pnpm | |
| if: ${{ needs.changes.outputs.frontend == 'true' }} | |
| uses: pnpm/action-setup@v4 | |
| - name: Setup Node.js | |
| if: ${{ needs.changes.outputs.frontend == 'true' }} | |
| uses: actions/setup-node@v6 | |
| with: | |
| node-version: 22 | |
| cache: pnpm | |
| - name: Install dependencies | |
| if: ${{ needs.changes.outputs.frontend == 'true' }} | |
| run: pnpm install | |
| - name: Test self-host env derivation | |
| if: ${{ needs.changes.outputs.frontend == 'true' }} | |
| run: bash scripts/selfhost-config.test.sh | |
| - name: Verify reserved-slugs.ts is up to date | |
| if: ${{ needs.changes.outputs.frontend == 'true' }} | |
| # Re-runs the generator and fails on any drift from the | |
| # checked-in TypeScript output. The Go side embeds the JSON | |
| # source directly, so a passing diff here proves both sides | |
| # share one source of truth. | |
| run: | | |
| pnpm generate:reserved-slugs | |
| git diff --exit-code -- packages/core/paths/reserved-slugs.ts | |
| - name: Build, type check, lint, and test | |
| if: ${{ needs.changes.outputs.frontend == 'true' }} | |
| # Mobile lives in a parallel mobile-verify workflow (path-filtered | |
| # to apps/mobile/** + packages/core/**) so it doesn't add | |
| # ~50s of expo-lint + tsc to every web/desktop PR. Keep this | |
| # filter in sync with the root package.json scripts, which also | |
| # exclude @multica/mobile. | |
| run: pnpm exec turbo build typecheck lint test --filter='!@multica/docs' --filter='!@multica/mobile' | |
| backend: | |
| runs-on: ubuntu-latest | |
| services: | |
| postgres: | |
| image: pgvector/pgvector:pg17 | |
| env: | |
| POSTGRES_DB: multica | |
| POSTGRES_USER: multica | |
| POSTGRES_PASSWORD: multica | |
| ports: | |
| - 5432:5432 | |
| options: >- | |
| --health-cmd "pg_isready -U multica -d multica" | |
| --health-interval 5s | |
| --health-timeout 5s | |
| --health-retries 20 | |
| redis: | |
| image: redis:7-alpine | |
| ports: | |
| - 6379:6379 | |
| options: >- | |
| --health-cmd "redis-cli ping" | |
| --health-interval 5s | |
| --health-timeout 5s | |
| --health-retries 10 | |
| env: | |
| DATABASE_URL: postgres://multica:multica@localhost:5432/multica?sslmode=disable | |
| # Wires up the RedisLocalSkill*_test.go suite. Distinct from REDIS_URL | |
| # (which would flip the server binary itself onto the Redis-backed | |
| # realtime relay + request stores); the tests talk to this Redis | |
| # directly so they run alongside the Postgres-backed suite. | |
| REDIS_TEST_URL: redis://localhost:6379/1 | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v6 | |
| - name: Setup Go | |
| uses: actions/setup-go@v5 | |
| with: | |
| go-version: "1.26.1" | |
| cache-dependency-path: server/go.sum | |
| - name: Build | |
| run: cd server && go build ./... | |
| - name: Run migrations | |
| run: cd server && go run ./cmd/migrate up | |
| - name: Test | |
| run: cd server && go test -race ./... | |
| installer: | |
| # Stub-driven shell tests for scripts/install.sh. Kept off the heavy | |
| # backend job so installer regressions surface independently, and | |
| # exercised on macOS too because the installer targets macOS/Homebrew | |
| # and `tar` / `sed` / `mktemp` differ between BSD and GNU userlands. | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| os: [ubuntu-latest, macos-latest] | |
| runs-on: ${{ matrix.os }} | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v6 | |
| - name: Test shell installers | |
| run: bash scripts/install.test.sh |