Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
3 changes: 2 additions & 1 deletion .claude/skills/devtools-docs/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ Raw HTML in markdown. Always write explicit closing tags; never self-close custo
| `ngmd-workflow` > `ngmd-step` | Ordered steps. | step `title` |
| `ngmd-accordion` > `ngmd-accordion-item` | FAQ. | item `title`, `open` |
| `ngmd-pill-row` > `ngmd-pill` | Related links at the end of a page. | pill `href`, `title` |
| `ngmd-badge` | Status chip next to a heading. | `variant`: new, updated, alpha, beta, stable, deprecated |
| `ngmd-badge` | Status chip next to a heading. | `variant`: new, updated, alpha, beta, stable, deprecated, action, destructive |
| `ngmd-tabs` > `ngmd-tab` | Alternatives a code group can't express. | tab `title`, `icon`, `image` |
| `ngmd-image`, `ngmd-video` | Screenshots, YouTube or Vimeo. | image `src`, `alt`, `caption`, `width`. video `src`, `title` |

Expand All @@ -114,6 +114,7 @@ Rules:
## 6. Code samples

- Always set the language. Put the file path in a comment on the first line: `// src/app/app.config.ts`.
- JSON samples get no path comment: JSON has no comments and the copy button copies the whole block. Name the file in the sentence above the sample instead.
- Highlight lines with `{3}` or `{2,5-7}` after the language. Count the path comment as line 1.
- Install commands use a code group: ` ```bash group="install" name="pnpm" active ` then npm, yarn, bun.
- `file="path#L5-L20"` imports a real file (relative to `apps/docs`, nothing outside it). It is not a title.
Expand Down
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@
*.zip binary
extension/ui/** linguist-generated=true
pnpm-lock.yaml linguist-generated=true
extension/ui/THIRD_PARTY_LICENSES.md -text
92 changes: 89 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,6 @@ jobs:

- uses: nrwl/nx-set-shas@v4

- uses: nrwl/nx-set-shas@v4

- name: Check formatting
run: pnpm format:check

Expand Down Expand Up @@ -66,7 +64,7 @@ jobs:

node-22:
name: Package tests on Node.js 22
# `engines.node` allows 22, while the build job runs the `.nvmrc` version.
# `engines.node` allows 22.12 and later, while the build job runs the `.nvmrc` version.
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
Expand Down Expand Up @@ -96,3 +94,91 @@ jobs:

- name: Check the panel with axe
run: pnpm test:axe

# The e2e jobs below are slow, so they run only when the package, the panel, the SSR demo, the
# tools docs (e2e:mcp reads them) or the scripts and fixtures they use change. A diff that cannot
# be computed (a new branch, a force push) runs them.
changes:
name: Changed paths
runs-on: ubuntu-latest
timeout-minutes: 5
outputs:
e2e: ${{ steps.diff.outputs.e2e }}
steps:
- uses: actions/checkout@v7
with:
fetch-depth: 0
persist-credentials: false

- id: diff
env:
BASE: ${{ github.event_name == 'pull_request' && github.event.pull_request.base.sha || github.event.before }}
run: |
paths=(packages/devtools app e2e src apps/docs/src/content/agents angular.json package.json
scripts/e2e-security.mjs scripts/e2e-mcp.mjs pnpm-lock.yaml .github/workflows/ci.yml)
if git diff --quiet "$BASE" HEAD -- "${paths[@]}"; then
echo "e2e=false" >> "$GITHUB_OUTPUT"
else
echo "e2e=true" >> "$GITHUB_OUTPUT"
fi

e2e-security:
name: Security e2e
needs: changes
if: needs.changes.outputs.e2e == 'true'
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- uses: actions/checkout@v7
with:
persist-credentials: false

- uses: ./.github/actions/setup

# Playwright's own Chromium, as the axe job installs it.
- name: Install Chromium
run: pnpm exec playwright install --with-deps chromium

- name: Build the package
run: pnpm devtools:build-pkg

# Leak corpus, access gates and a production build, on ports 5231 to 5236.
- name: Check redaction and access
run: pnpm e2e:security

- name: Keep the captured channels
if: failure()
uses: actions/upload-artifact@v4
with:
name: e2e-security
path: dist/e2e-security
if-no-files-found: ignore

e2e-mcp:
name: MCP e2e
needs: changes
if: needs.changes.outputs.e2e == 'true'
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- uses: actions/checkout@v7
with:
persist-credentials: false

- uses: ./.github/actions/setup

- name: Install Chromium
run: pnpm exec playwright install --with-deps chromium

# Builds the package and the SSR demo itself, then serves the demo on port 5150 (the variant
# hubs on 5151 to 5154) and checks every tool, resource and prompt, and agents/tools.md.
- name: Check the agent surface
run: pnpm e2e:mcp --report dist/e2e-mcp/report.json

- name: Keep the report
if: always()
uses: actions/upload-artifact@v4
with:
name: e2e-mcp
path: dist/e2e-mcp
if-no-files-found: ignore
169 changes: 169 additions & 0 deletions .github/workflows/e2e.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
name: E2E

# The slow end-to-end checks that do not fit a pull request: every panel view in a real browser,
# multi-tab and lifecycle resilience, and the install matrix from a packed tarball. Pull requests
# run the security and MCP checks (ci.yml), and the release runs a slice of the install matrix on
# the tarball it publishes (release.yml). See apps/docs/src/content/contributing/development.md.
on:
schedule:
# Mondays at 07:00 UTC, an hour after latest.yml and compat.yml.
- cron: '0 7 * * 1'
workflow_dispatch:

permissions:
contents: read

concurrency:
group: ${{ github.workflow }}
cancel-in-progress: false

jobs:
panel:
name: Panel views
runs-on: ubuntu-latest
timeout-minutes: 45
steps:
- uses: actions/checkout@v7
with:
persist-credentials: false

- uses: ./.github/actions/setup

- name: Install Chromium
run: pnpm exec playwright install --with-deps chromium

# The SSR demo serves the panel built into packages/devtools/dist/public.
- name: Build the package and the demo
run: |
pnpm devtools:build-pkg
pnpm build --configuration development

# The demo keeps the one-time code on unless PANGULAR_AUTH is false, and the panel check
# needs a connected panel.
- name: Start the SSR demo on port 4000
run: |
PANGULAR_AUTH=false PORT=4000 node dist/pangular-inspector/server/server.mjs > "$RUNNER_TEMP/demo.log" 2>&1 &
for _ in $(seq 60); do
curl -sf http://localhost:4000/ > /dev/null && exit 0
sleep 1
done
cat "$RUNNER_TEMP/demo.log"
exit 1

# Every tab and sub-view, dark and light, at 1280 and 360 px: axe, overflow and page errors.
- name: Check every panel view
run: pnpm e2e:panel --base http://localhost:4000 --out dist/e2e-panel

- name: Keep the screenshots and results
if: always()
uses: actions/upload-artifact@v4
with:
name: e2e-panel
path: dist/e2e-panel
if-no-files-found: ignore

resilience:
name: Resilience
runs-on: ubuntu-latest
timeout-minutes: 60
steps:
- uses: actions/checkout@v7
with:
persist-credentials: false

- uses: ./.github/actions/setup

- name: Install Chromium
run: pnpm exec playwright install --with-deps chromium

- name: Build the package and the demo
run: |
pnpm devtools:build-pkg
pnpm build --configuration development

# Starts the demo on port 5401 itself. Two checks fail today on open issues and are marked
# as known failures in the script, so they print XFAIL and do not fail the job:
# - expiry: a crashed tab stays listed for about 150 s (#422);
# - stress: the forms collector keeps 100 children per group and does not say so (#423).
# The soak check (`soak --minutes 30`) is manual only.
- name: Check multitab, expiry, lifecycle and stress
run: pnpm e2e:resilience multitab expiry lifecycle stress --json dist/e2e-resilience.json

- name: Keep the results
if: always()
uses: actions/upload-artifact@v4
with:
name: e2e-resilience
path: dist/e2e-resilience.json
if-no-files-found: ignore

install:
name: Install ${{ matrix.name }}
runs-on: ubuntu-latest
timeout-minutes: 90
strategy:
# Every cell reports, so one week's failures are all visible at once.
fail-fast: false
matrix:
include:
- name: angular-cli
args: --scenarios=angular-cli --pm=npm,pnpm --angular=20.3,21,22 --no-audit
- name: angular-cli-serve
args: --scenarios=angular-cli-serve --pm=npm,pnpm --angular=20.3,21,22 --no-audit
- name: angular-cli-nossr
args: --scenarios=angular-cli-nossr --pm=npm,pnpm --angular=20.3,21,22 --no-audit
- name: analog
args: --scenarios=analog --pm=pnpm --no-audit
- name: cli
args: --scenarios=cli --pm=npm,pnpm --no-audit
- name: package-audit
args: --audit-only
steps:
- uses: actions/checkout@v7
with:
persist-credentials: false

- uses: ./.github/actions/setup

- name: Install Chromium
run: pnpm exec playwright install --with-deps chromium

# Packs the package, publishes it to a throwaway local registry (port 4873, the apps on the
# ports after it) and installs it into fresh apps. A failed run keeps only the logs.
- name: Run the cells
run: >-
pnpm e2e:install ${{ matrix.args }}
--report=dist/e2e-install/report.json --logs=dist/e2e-install/logs

- name: Keep the report and the logs
if: always()
uses: actions/upload-artifact@v4
with:
name: e2e-install-${{ matrix.name }}
path: dist/e2e-install
if-no-files-found: ignore

report:
name: Report the failure
needs: [panel, resilience, install]
if: failure() && github.event_name == 'schedule'
runs-on: ubuntu-latest
timeout-minutes: 5
permissions:
# One open issue for the weekly run, found by its title.
issues: write
steps:
- env:
GH_TOKEN: ${{ github.token }}
GH_REPO: ${{ github.repository }}
RUN: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
run: |
title="ci: the weekly e2e run fails"
body="A job of the weekly E2E workflow failed: $RUN. The run's artifacts hold the reports and logs."
number=$(gh issue list --state open --search "\"$title\" in:title" --json number,title \
| jq -r --arg title "$title" 'map(select(.title == $title)) | .[0].number // empty')
if [ -n "$number" ]; then
gh issue comment "$number" --body "Still failing: $RUN"
else
gh issue create --title "$title" --body "$body" --label bug --label 'area: ci'
fi
12 changes: 7 additions & 5 deletions .github/workflows/latest.yml
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
name: Latest versions

# The package declares `@angular/core >=20` and `vite >=5`, and this repository pins the versions
# it tests on, so a new Angular, Analog or Vite release can break users between our releases
# without CI noticing (#100). Each week this makes fresh apps the way users do, on whatever those
# ranges resolve to that day, installs the package from a local registry, wires the documented
# setup, builds it and checks the hub answers. See apps/docs/src/content/contributing/publishing.md.
# The package declares `@angular/core >=12.2.0 <23.0.0` and `vite >=5`, and this repository pins
# the versions it tests on, so a new Angular, Analog or Vite release can break users between our
# releases without CI noticing (#100). Each week this makes fresh apps the way users do, on whatever
# those ranges resolve to that day, installs the package from a local registry, wires the
# documented setup, builds it and checks the hub answers (`pnpm verify:publish`). The release
# runs the same check on the tarball it publishes. See
# apps/docs/src/content/contributing/publishing.md#releasing.
on:
schedule:
# Mondays at 06:00 UTC.
Expand Down
Loading
Loading