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
95 changes: 94 additions & 1 deletion .github/workflows/common-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,15 @@ jobs:
npm run typecheck
npm test

# The console job installs ui/'s packages from this cache but does not
# save it, so on main this job fetches them too, and a copy it saves
# holds them.
- name: Fetch the console's packages
if: >-
${{ steps.scope.outputs.needed == 'true' && (github.event_name == 'push' && github.ref == 'refs/heads/main') }}
working-directory: ui
run: npm ci --ignore-scripts --no-fund --no-audit

- name: Report the npm cache
id: report-npm-cache
if: ${{ steps.scope.outputs.needed == 'true' && (always()) }}
Expand All @@ -183,7 +192,7 @@ jobs:
PACKAGE_CACHE: ${{ runner.temp }}/space-ci-helpers/package-cache.py
run: >-
python3 -I "${PACKAGE_CACHE}" trim npm "${HOME}/.npm"
docs/api/package-lock.json scripts/console-loop/package-lock.json
docs/api/package-lock.json scripts/console-loop/package-lock.json ui/package-lock.json

- name: Save the npm cache
if: ${{ steps.scope.outputs.needed == 'true' && (steps.prepare-npm-upload.outcome == 'success') }}
Expand All @@ -192,6 +201,90 @@ jobs:
path: ~/.npm
key: ${{ steps.npm-cache-key.outputs.key }}

# The admin console's unit tests, type check and production build. Two
# console changes can each pass alone and break the console together; this
# catches that before the merge. The build needs no network or secrets: its
# API rewrites default to local addresses.
console:
if: github.repository == 'perplexityai/SPACE'
name: Admin console
runs-on: ubuntu-24.04
timeout-minutes: 10
permissions:
contents: read
env:
NEXT_TELEMETRY_DISABLED: '1'
steps:
- name: Check out SPACE
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false

# Pull CI and the merge queue skip a check the change cannot affect,
# and Main CI, which passes no base, runs it (ci/check-scopes/README.md).
- name: Decide whether this change needs the check
id: scope
shell: bash
env:
SCOPE: console
SCOPE_BASE: ${{ inputs.scope_base }}
# Set only for pull requests, whose change is the synthetic merge
# against its first parent.
PULL_REQUEST_HEAD: ${{ github.event.pull_request.head.sha }}
# Only an explicit answer reaches the gates: anything else fails.
run: |
set -euo pipefail
decision="$(bash ci/scripts/check-needed.sh "${SCOPE}" "${SCOPE_BASE}" "${PULL_REQUEST_HEAD}")"
if [[ ! "${decision}" =~ ^needed=(true|false)($'\n'base=[0-9a-f]{40})?$ ]]; then
echo "check-needed.sh answered '${decision}'" >&2
exit 1
fi
printf '%s\n' "${decision}" >>"${GITHUB_OUTPUT}"

- *copy-package-cache-helper

# The Node version the console image builds with (docker/Dockerfile.ui).
# The SPACE Guide saves the npm cache this job restores.
- name: Set up Node
if: steps.scope.outputs.needed == 'true'
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
with:
node-version: '22.23.3'

- *name-npm-cache

- *restore-npm-cache

- *prepare-npm-cache

- name: Install the console's packages
if: steps.scope.outputs.needed == 'true'
working-directory: ui
run: npm ci --ignore-scripts --no-fund --no-audit

- name: Run the console's unit tests
if: steps.scope.outputs.needed == 'true'
working-directory: ui
run: npm test

# --no-install: without the installed TypeScript, npx would fetch the
# unrelated `tsc` package instead of failing.
- name: Type-check the console
if: steps.scope.outputs.needed == 'true'
working-directory: ui
run: npx --no-install tsc --noEmit -p .

- name: Build the console
if: steps.scope.outputs.needed == 'true'
working-directory: ui
run: npm run build

- name: Report the npm cache
if: ${{ steps.scope.outputs.needed == 'true' && (always()) }}
env:
PACKAGE_CACHE: ${{ runner.temp }}/space-ci-helpers/package-cache.py
run: python3 -I "${PACKAGE_CACHE}" report npm "${HOME}/.npm"

api_reference:
if: github.repository == 'perplexityai/SPACE'
name: Documentation site
Expand Down
6 changes: 3 additions & 3 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -133,9 +133,9 @@ Pull CI and the merge queue also skip any other check the change cannot
affect: a console-only change runs no Rust or Python checks, and a
documentation change no Rust checks. Each check's scope in
[ci/check-scopes/](ci/check-scopes/README.md) lists the paths it never reads
(for the Go shim, the only paths it reads). A skipped check passes, and its
log says why. Main CI runs every check after the merge, except archcheck,
which runs only for pull requests and merge groups.
(for the Go shim and the admin console, the only paths they read). A skipped
check passes, and its log says why. Main CI runs every check after the merge,
except archcheck, which runs only for pull requests and merge groups.

Run `cargo arch` to check the repository structure rules in
[ARCHITECTURE.toml](ARCHITECTURE.toml); [archcheck](crates/tools/archcheck/README.md)
Expand Down
2 changes: 1 addition & 1 deletion ci/check-scopes/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ What counts as the change:
makes the check run, so an omission costs time, never coverage.
- `<scope>.run` lists the only paths the check reads, and the check runs when
a changed path matches one of them. Use it only for a check whose inputs
are self-contained: today, the Go shim.
are self-contained: today, the Go shim and the admin console.
- `run-all.txt` lists paths that make every check run: the workflows, the CI
scripts, these files and the CI image's inputs.
- The scope `always`, used by the two documentation jobs, has no file: those
Expand Down
5 changes: 5 additions & 0 deletions ci/check-scopes/console.run
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# The admin console check installs, tests, type-checks and builds ui/ from
# its own package.json and package-lock.json. Nothing under ui/ imports,
# reads or generates from outside it, and the Node version it runs on is in
# the workflow, which run-all.txt covers.
ui/**
11 changes: 8 additions & 3 deletions ci/scripts/package-cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,14 @@
FAMILIES = {
"cargo": ("Cargo.lock",),
"go": ("shim/go.mod", "shim/go.sum"),
# The SPACE Guide job installs both: the docs' Mermaid bundle and the
# console loop's checks.
"npm": ("docs/api/package-lock.json", "scripts/console-loop/package-lock.json"),
# The SPACE Guide job, which saves this cache, installs all three: the
# docs' Mermaid bundle, the console loop's checks and, on main, the admin
# console's packages, which the console job installs on every run.
"npm": (
"docs/api/package-lock.json",
"scripts/console-loop/package-lock.json",
"ui/package-lock.json",
),
"uv-python": ("uv.lock", "pyproject.toml", "ci/scripts/run-python-tests.sh"),
"uv-shell": (
"uv.lock",
Expand Down
8 changes: 7 additions & 1 deletion ci/scripts/test-check-needed.sh
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,11 @@ assert_needed true rust shim/env_contract_generated.go
# The shim's commands run without GOWORK=off.
assert_needed true go go.work

# The admin console needs only ui/.
assert_needed true console ui/src/lib/api.ts
assert_needed true console ui/package-lock.json
assert_needed false console crates/l40_api/api/src/lib.rs docs/api/openapi.json scripts/console-loop/src/loop.ts

# Anything not listed as unread runs the check: Rust reads infra/, db/,
# templates/ and scripts/.
assert_needed true rust infra/space/identity/node-identities.sh
Expand Down Expand Up @@ -96,11 +101,12 @@ assert_needed false rust "ui/src/app/café.tsx"
assert_needed false rust "docs/release notes.md"

# A change to CI itself, or to the CI image's inputs, runs every check: the
# Go scope would otherwise skip all of these.
# Go and console scopes would otherwise skip all of these.
assert_needed true go .github/workflows/pull-ci.yml
assert_needed true go ci/scripts/run-shim-checks.sh
assert_needed true go rust-toolchain.toml
assert_needed true go docker/build-btrfs-progs.sh
assert_needed true console .github/workflows/common-ci.yml

# The change is tree to tree: a later console-only commit does not hide an
# earlier Rust one.
Expand Down
Loading