Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 0 additions & 24 deletions .github/workflows/actions-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,8 @@ permissions:
contents: read

jobs:
changes:
uses: ./.github/workflows/ci-changes.yml

test:
name: Build action suite${{ matrix.node == 26 && ' (Node 26)' || '' }}
needs: changes
if: ${{ needs.changes.outputs.build_action == 'true' }}
runs-on: ubuntu-latest
strategy:
fail-fast: false
Expand All @@ -39,22 +34,3 @@ jobs:
run: cp actions/build/test/fixture/package.json actions/build/test/fixture/package-lock.json actions/build/test/fixture/fixture-build.mjs .
- uses: ./actions/build
if: ${{ matrix.node == 24 }}

result:
name: Replica action tests
needs: [changes, test]
if: ${{ always() }}
runs-on: ubuntu-latest
steps:
- name: Require the selected build-action suite to pass
env:
SELECTION_RESULT: ${{ needs.changes.result }}
SELECTED: ${{ needs.changes.outputs.build_action }}
TEST_RESULT: ${{ needs.test.result }}
run: |
test "$SELECTION_RESULT" = success
case "$SELECTED" in
true) test "$TEST_RESULT" = success ;;
false) test "$TEST_RESULT" = skipped ;;
*) echo "Invalid build-action suite selection" >&2; exit 1 ;;
esac
40 changes: 0 additions & 40 deletions .github/workflows/ci-changes.yml

This file was deleted.

48 changes: 18 additions & 30 deletions .github/workflows/hub-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,19 +13,28 @@ defaults:
working-directory: hub

jobs:
changes:
uses: ./.github/workflows/ci-changes.yml

check:
name: Hub ${{ matrix.command }}${{ matrix.node == 26 && ' (Node 26)' || '' }}
needs: changes
if: ${{ needs.changes.outputs.hub == 'true' }}
name: Hub ${{ matrix.command == 'test' && 'unit tests' || matrix.command == 'test:database' && 'database tests' || matrix.command }}${{ matrix.node == 26 && ' (Node 26)' || '' }}
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
node: [24, 26]
command: [lint, typecheck, test, build, storybook:build, "db:validate"]
command: [lint, typecheck, test, build, storybook:build, "db:validate", "test:database"]
services:
postgres:
image: ${{ matrix.command == 'test:database' && 'postgres:18.6-bookworm' || '' }}
env:
POSTGRES_USER: replica
POSTGRES_PASSWORD: replica
POSTGRES_DB: postgres
ports:
- 5432:5432
options: >-
--health-cmd "pg_isready -h 127.0.0.1 -U replica -d postgres"
--health-interval 5s
--health-timeout 5s
--health-retries 10
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
Expand All @@ -35,11 +44,11 @@ jobs:
cache-dependency-path: hub/package-lock.json
- run: npm ci --engine-strict
- run: npm run ${{ matrix.command }}
env:
TEST_DATABASE_URL: ${{ matrix.command == 'test:database' && 'postgresql://replica:replica@127.0.0.1:5432/postgres' || '' }}

integration:
name: Controls and extension tests${{ matrix.node == 26 && ' (Node 26)' || '' }}
needs: changes
if: ${{ needs.changes.outputs.hub == 'true' }}
runs-on: ubuntu-latest
strategy:
fail-fast: false
Expand Down Expand Up @@ -67,24 +76,3 @@ jobs:
- run: npm run controls:assets:check
- run: npm run controls:schema:check
- run: npm run extension:assets:check

result:
name: Frontend tests
needs: [changes, check, integration]
if: ${{ always() }}
runs-on: ubuntu-latest
steps:
- name: Require the selected Hub suite to pass
working-directory: .
env:
SELECTION_RESULT: ${{ needs.changes.result }}
SELECTED: ${{ needs.changes.outputs.hub }}
CHECK_RESULT: ${{ needs.check.result }}
INTEGRATION_RESULT: ${{ needs.integration.result }}
run: |
test "$SELECTION_RESULT" = success
case "$SELECTED" in
true) test "$CHECK_RESULT" = success && test "$INTEGRATION_RESULT" = success ;;
false) test "$CHECK_RESULT" = skipped && test "$INTEGRATION_RESULT" = skipped ;;
*) echo "Invalid Hub suite selection" >&2; exit 1 ;;
esac
6 changes: 0 additions & 6 deletions .github/workflows/learning-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,8 @@ name: Learning CI

on:
pull_request:
paths:
- ".github/workflows/learning-ci.yml"
- "packages/learning/**"
push:
branches: [main]
paths:
- ".github/workflows/learning-ci.yml"
- "packages/learning/**"

permissions:
contents: read
Expand Down
27 changes: 27 additions & 0 deletions .github/workflows/scripts-ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
name: Scripts CI

on:
pull_request:
push:
branches: [main]

permissions:
contents: read

jobs:
check:
name: Scripts ${{ matrix.command }}
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
command: [typecheck, test, "check:workflows"]
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
with:
node-version: 24
cache: npm
cache-dependency-path: scripts/package-lock.json
- run: npm ci --prefix scripts --ignore-scripts --engine-strict
- run: npm run ${{ matrix.command }} --prefix scripts
14 changes: 0 additions & 14 deletions .github/workflows/starter-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,8 @@ name: Starter CI

on:
pull_request:
paths:
- ".github/workflows/starter-ci.yml"
- "starter/**"
- "scripts/create-prototype-repo.sh"
- "scripts/create-prototype-repo.test.mjs"
- "scripts/setup-replica-plugin.test.mjs"
- "scripts/install-starter.sh"
push:
branches: [main]
paths:
- ".github/workflows/starter-ci.yml"
- "starter/**"
- "scripts/create-prototype-repo.sh"
- "scripts/create-prototype-repo.test.mjs"
- "scripts/setup-replica-plugin.test.mjs"
- "scripts/install-starter.sh"

permissions:
contents: read
Expand Down
2 changes: 1 addition & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ Follow the [commit and PR conventions](CONTRIBUTING.md#commits-and-pull-requests

## Project boundaries

- `hub/` starts a TypeScript Express API and React + Vite frontend. Hosting and review features are not implemented. Database, sign-in, and deployment choices are not decided. Shared canvas and Controls source stays under `hub/app/javascript/`. Read `hub/AGENTS.md` and [Hub architecture](hub/docs/architecture.md) before changing it.
- `hub/` starts a TypeScript Express API and React + Vite frontend, with PostgreSQL and Prisma for database development. Hosting and review features are not implemented. Sign-in and deployment choices are not decided. Shared canvas and Controls source stays under `hub/app/javascript/`. Read `hub/AGENTS.md` and [Hub architecture](hub/docs/architecture.md) before changing it.
- `starter/` is the single source for the Vite + React app, `.agents/skills/`, and `.agents/context-templates/`. Product- and design-system-specific guidance belongs in consuming repositories.
- `actions/build/` owns the artifact contract between prototype repositories and Hub.
- `packages/learning/` owns the learning contracts, the memory provider and consolidator interfaces, the reference providers and consolidators, the conformance suite, and the `replica-learning` command. It is private repository source with no release yet. Read its `README.md` and [ADR 0001](docs/adr/0001-learning-extension-architecture.md) before changing it.
Expand Down
3 changes: 2 additions & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,8 @@ npm run build
npm run storybook:build
```

Run `npm run test:database` for server cases that save records. Follow the [database test setup](hub/docs/testing-and-operations.md#parallel-database-tests) to prepare isolated databases. `npm test` does not require PostgreSQL.

Useful focused commands include:

| Goal | Command |
Expand All @@ -124,7 +126,6 @@ Repository workflow and dependency checks have their own small npm project:
npm ci --prefix scripts --ignore-scripts --engine-strict
npm run typecheck --prefix scripts
npm test --prefix scripts
node --test scripts/select-ci-suites.test.mjs
node scripts/check-ci-workflows/index.ts
node scripts/check-dependency-age/index.ts
```
Expand Down
28 changes: 8 additions & 20 deletions docs/testing-and-review.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,31 +40,19 @@ Project commands define the check. GitHub Actions should prepare the required en

When a command gains a dependency or build prerequisite, update its local setup and affected workflow in the same change. A green local suite does not prove that CI installed the same dependencies, so inspect both paths.

### Select affected CI suites
### Run independent CI checks

Hub and build-action workflows start on every pull request, but run their expensive jobs only when the change can affect that suite. Pushes to `main` run both complete suites. Local project commands still run their complete checks; selection changes when CI calls them, not what they do. Dependency-age checks remain unconditional, and Starter and Learning CI retain their own path filters.
All CI workflows run on every pull request and push to `main`. Do not skip checks based on changed paths or add jobs that only combine other jobs' results. Configure branch protection to require the individual checks.

The [shared selection workflow](../.github/workflows/ci-changes.yml) calls [the selector](../scripts/select-ci-suites.mjs). For pull requests, it compares the merge base with the PR head using Git rather than the size-limited changed-files API. Deletions and both sides of renames count as changes.
Hub reports lint, types, unit tests, database tests, the frontend/API build, Storybook, and Controls/extension checks separately. Only the database test command starts PostgreSQL. The new Hub has no production-image or release jobs.

| Changed area | Selected suites |
| --- | --- |
| Hub code and configuration | Hub |
| Shared Controls runtime, schema, fixtures, and capture adapter under `hub/app/javascript/utils/prototype-controls/` | Hub and build action |
| `actions/build/` | Hub and build action; Controls and extension integration use its pinned browser |
| Copilot extension and plugin catalog | Hub |
| `packages/learning/` | Hub; its shared lint and retained integration consume the package |
| `starter/` | Hub; retained Storybook fixtures and Controls checks consume starter files. Starter CI still runs separately |
| Existing installer scripts | Neither; Starter CI covers them |
| Root contributor documents, shared and Hub guides, skills, and documentation assets | Neither |
| Workflow changes, selector changes, and unclassified paths | Both |
Maintainers must update branch rules when required checks change. Editing a workflow does not update those rules.

The `Frontend tests` and `Replica action tests` result jobs always run, so skipping an entire workflow cannot leave these checks pending. They accept skipped work only when the selector succeeded and said it was unnecessary. Hub's result covers lint, types, Vitest, the frontend/API build, Storybook, and Controls/extension checks on every supported Node major. A failed selector, invalid output, or failed selected check makes the result fail. The new Hub has no production-image, database, or release jobs; branch protection must not require removed jobs.
[Scripts CI](../.github/workflows/scripts-ci.yml) runs type checks, tests, and workflow checks for the maintenance scripts under `scripts/`. Use the [contributor commands](../CONTRIBUTING.md#verify-the-change) to run them locally. The workflow checker rejects jobs that combine results, conditional jobs, path filters, and missing required commands. Keep TypeScript checks in function directories with colocated Vitest tests. Check changed workflows with `actionlint` when available, then inspect their check results on GitHub after publishing.

When adding a shared dependency or a new project, update the selector and its behavioral tests together. Unknown paths deliberately run both suites until their dependencies are known. Install tooling with `npm ci --prefix scripts --ignore-scripts --engine-strict`, then run `node --test scripts/select-ci-suites.test.mjs`, `npm run typecheck --prefix scripts`, `npm test --prefix scripts`, and `node scripts/check-ci-workflows/index.ts` from the repository root. Keep the TypeScript checks in function directories with colocated Vitest tests. The workflow checker reads the result-check scripts and tests them with success, failure, cancellation, and missing outputs. These checks run before CI selects suites. Check changed workflows with `actionlint` when available. Actual job skipping and check reporting still need verification on GitHub after publishing.
Hub, Starter, build-action, and Learning CI test both Node.js majors supported by each project's `engines.node`. The workflow matrices define the versions and distinguish their check names. A failure on one version does not cancel checks on the other. npm installation enforces dependency engines. The workflow checker verifies that the manifests, lockfiles, and matrices agree.

Node-dependent jobs in Hub, Starter, build-action, and Learning CI use a Node 24 and 26 matrix rather than a separate compatibility workflow. Each check adds a `(Node 26)` suffix on Node 26. A failure does not cancel the other version. npm installation enforces dependency engines, and `scripts/check-ci-workflows/index.ts` checks the supported ranges, matching lockfile metadata, and matrix wiring. These checks track the supported majors, not their exact minimum patch releases.

CI selection and dependency-age tooling run on Node 24. The build-action suite tests its JavaScript and browser capture on both Node versions, but runs the composite-action smoke test only on Node 24: the composite action pins that runtime itself and uploads a single named artifact.
Scripts CI and dependency-age checks use the Node.js version specified in their workflows. The build-action suite tests JavaScript and browser capture on both supported majors. It runs the composite-action smoke test only on the action's pinned runtime to avoid duplicate artifact uploads.

## Update dependencies

Expand All @@ -74,7 +62,7 @@ From the repository root, `node scripts/check-dependency-age/index.ts` verifies

CI does not run `npm audit`: a newly published security fix could otherwise make the audit fail while the age check rejects the fixed version. Dependabot checks dependencies for known vulnerabilities. Organization-managed CodeQL scans application code on GitHub.

When a dependency is too new, select an older compatible version or wait until the seven-day window ends. See [Hub testing and operations](../hub/docs/testing-and-operations.md#update-dependencies) for Hub-specific tooling.
When a dependency is too new, select an older compatible version or wait until the seven-day window ends. See [Hub testing and operations](../hub/docs/testing-and-operations.md) for Hub-specific tooling.

## Copilot code review

Expand Down
1 change: 1 addition & 0 deletions hub/.devcontainer/compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ services:
- ../..:/workspaces/replica:cached
environment:
DATABASE_URL: postgresql://replica:replica@db:5432/replica
TEST_DATABASE_URL: postgresql://replica:replica@db:5432/postgres
depends_on:
db:
condition: service_healthy
Expand Down
3 changes: 3 additions & 0 deletions hub/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,6 @@ PORT=3001

# Local development only. The devcontainer supplies its own database hostname.
DATABASE_URL=postgresql://replica:replica@127.0.0.1:5432/replica

# Only database-enabled tests require this URL and CREATEDB permission.
TEST_DATABASE_URL=postgresql://replica:replica@127.0.0.1:5432/postgres
2 changes: 2 additions & 0 deletions hub/AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ Hub is being rebuilt in TypeScript. The app starts locally, but its product feat

Run Node commands from `hub/`, locally or inside the devcontainer. PostgreSQL and Prisma are configured without product models. Agree on the design before adding models, sign-in, deployment, or product API routes.

`npm test` does not require PostgreSQL. Use `npm run test:database` for `.db.test.ts` and `.db.test.tsx` cases in Node.js or jsdom. Follow the database isolation and reset rules in [testing](docs/testing-and-operations.md).

Keep the top-level `HubThemeProvider` around Hub and Storybook content. It synchronizes the resolved light/dark mode to `<html data-color-mode>` so portals inherit Brand and `--hub-*` tokens. Do not add a fixed light theme to an overlay.

Preserve the shared canvas and Controls source paths under `app/javascript/`; the prototype extension and build action consume them independently of the Hub API.
4 changes: 3 additions & 1 deletion hub/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

Hub is being rebuilt on `build/hub/new` using TypeScript, Express, React, Vite, and Vitest. This branch lets contributors start the new app locally. It is not ready to replace the existing Hub.

The API has one route: `GET /api/health`. The frontend displays the existing Replica logo and supports light and dark themes. Existing components, features, and pages are kept in Storybook, but they are not connected to the new API. PostgreSQL, Prisma, and a slim-based devcontainer provide a development foundation without product models. The old backend, sign-in, saved data, live updates, background jobs, and deployment setup have been removed without replacements.
The API has one route: `GET /api/health`. The frontend displays the existing Replica logo and supports light and dark themes. Existing components, features, and pages are kept in Storybook, but they are not connected to the new API.

Contributors can use PostgreSQL and Prisma locally or in the devcontainer. The database has no product models yet. Sign-in, saved data, live updates, background jobs, and deployment are not implemented.

Use [Development](docs/development.md) to start the API and frontend. Review [Architecture](docs/architecture.md), [code architecture conventions](docs/backend-architecture.md), and [coding conventions](docs/coding-conventions.md) before adding behavior.

Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,9 @@
import { fireEvent, render, screen, waitFor, within } from "@testing-library/react"
import { afterEach, describe, expect, it, vi } from "vitest"
import { describe, expect, it, vi } from "vitest"

import { HubThemeProvider } from "@hooks/use-hub-theme"
import story from "./stories"

afterEach(() => {
vi.unstubAllGlobals()
vi.restoreAllMocks()
})

describe("PublicationDemo()", () => {
it("shows the updated comments in the complete canvas sidebar without contacting Hub", async () => {
const externalFetch = vi.fn(() => Promise.reject(new Error("Unexpected external request.")))
Expand Down
Loading
Loading