From 54c6ca3bf3c2bf7d7766ef0eef75ae388a1f6980 Mon Sep 17 00:00:00 2001 From: Brooke Storm Date: Tue, 9 Jun 2026 15:18:12 -0700 Subject: [PATCH 1/2] ci: move the studio CI tests into ci.yaml so that they can be required Signed-off-by: Brooke Storm --- .github/CI_README.md | 21 ++-- .github/actions/changes/action.yaml | 6 +- .github/workflows/ci.yaml | 177 ++++++++++++++++++++++++++++ .github/workflows/studio-ci.yaml | 168 -------------------------- 4 files changed, 191 insertions(+), 181 deletions(-) delete mode 100644 .github/workflows/studio-ci.yaml diff --git a/.github/CI_README.md b/.github/CI_README.md index 1254169349..634f7a075d 100644 --- a/.github/CI_README.md +++ b/.github/CI_README.md @@ -20,15 +20,18 @@ reusable actions, and supporting docs. - `ci.yaml` Main source validation workflow. It runs linting, OPA policy WASM build, - Python unit tests, Python integration tests, OPA policy tests, and PR - coverage comments. It runs on pushes to `main`, pull requests to `main`, - merge queue checks, and manual dispatch. On successful `main` pushes, it - also sends a completion event to an external CI consumer. - -- `studio-ci.yaml` - Frontend/Studio workflow. It runs Studio type checks, tests, formatting, - linting, dependency checks, and scripts checks for relevant web changes. - Studio UI E2E tests run only on manual dispatch. + Python unit tests, Python integration tests, OPA policy tests, Studio web + checks for relevant web changes, and PR coverage comments. It runs on pushes + to `main`, pull requests to `main`, merge queue checks, and manual dispatch. + On successful `main` pushes, it also sends a completion event to an external + CI consumer. + + The final `ci-status` job is the merge gate for this workflow. Repository + branch protection or rulesets should require `CI status`, not the individual + test jobs. The job checks every job listed in its `needs` and passes only + when each one is `success` or `skipped`, which lets path-filtered jobs remain + optional. When adding a new CI job that should block merges, add it to + `ci-status.needs`. - `security.yaml` Security workflow. It runs TruffleHog secrets scanning and CodeQL analysis on diff --git a/.github/actions/changes/action.yaml b/.github/actions/changes/action.yaml index f697bd15b6..16e1d632db 100644 --- a/.github/actions/changes/action.yaml +++ b/.github/actions/changes/action.yaml @@ -23,7 +23,7 @@ outputs: description: "'true' if any files under tools/ changed" value: ${{ steps.filter.outputs.tools }} web-studio: - description: "'true' if any Studio, common, or SDK package files changed" + description: "'true' if any web files changed" value: ${{ steps.filter.outputs.web-studio }} runs: @@ -54,6 +54,4 @@ runs: tools: - 'tools/**' web-studio: - - 'web/packages/studio/**' - - 'web/packages/common/**' - - 'web/packages/sdk/**' + - 'web/**' diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 804e924eab..4ef98c39d5 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -392,6 +392,177 @@ jobs: report.xml ${{ runner.temp }}/e2e-services-logs/ + web-typecheck: + name: Web typecheck + needs: [changes] + if: > + always() && ( + github.event_name == 'workflow_dispatch' || + needs.changes.outputs.web-studio == 'true' + ) + runs-on: ubuntu-latest + defaults: + run: + working-directory: web + shell: bash + steps: + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 + with: + node-version: "22" + - name: Install pnpm via corepack + run: npm i -g corepack@0.31.0 && corepack enable pnpm + - name: Install dependencies + run: pnpm install --frozen-lockfile + - name: Typecheck changed packages + run: | + if [ "${{ github.event_name }}" = "pull_request" ]; then + git fetch origin "${{ github.base_ref }}" --depth=1 + pnpm --filter="...[origin/${{ github.base_ref }}]" run --parallel --if-present typecheck + else + pnpm run --recursive --parallel --if-present typecheck + fi + + web-test: + name: Web tests + needs: [changes] + if: > + always() && ( + github.event_name == 'workflow_dispatch' || + needs.changes.outputs.web-studio == 'true' + ) + runs-on: ubuntu-latest + defaults: + run: + working-directory: web + shell: bash + steps: + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 + with: + node-version: "22" + - name: Install pnpm via corepack + run: npm i -g corepack@0.31.0 && corepack enable pnpm + - name: Install dependencies + run: pnpm install --frozen-lockfile + - name: Test changed packages + run: | + if [ "${{ github.event_name }}" = "pull_request" ]; then + git fetch origin "${{ github.base_ref }}" --depth=1 + pnpm --filter="...[origin/${{ github.base_ref }}]" run --parallel --if-present test:ci + else + pnpm run --recursive --parallel --if-present test:ci + fi + + web-format: + name: Web format check + needs: [changes] + if: > + always() && ( + github.event_name == 'workflow_dispatch' || + needs.changes.outputs.web-studio == 'true' + ) + runs-on: ubuntu-latest + defaults: + run: + working-directory: web + shell: bash + steps: + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 + with: + node-version: "22" + - name: Install pnpm via corepack + run: npm i -g corepack@0.31.0 && corepack enable pnpm + - name: Install dependencies + run: pnpm install --frozen-lockfile + - name: Check formatting + run: pnpm format + + web-lint: + name: Web lint + needs: [changes] + if: > + always() && ( + github.event_name == 'workflow_dispatch' || + needs.changes.outputs.web-studio == 'true' + ) + runs-on: ubuntu-latest + defaults: + run: + working-directory: web + shell: bash + steps: + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 + with: + node-version: "22" + - name: Install pnpm via corepack + run: npm i -g corepack@0.31.0 && corepack enable pnpm + - name: Install dependencies + run: pnpm install --frozen-lockfile + - name: Lint + run: pnpm lint + + web-studio-deps: + name: Web studio deps check + needs: [changes] + if: > + always() && ( + github.event_name == 'workflow_dispatch' || + needs.changes.outputs.web-studio == 'true' + ) + runs-on: ubuntu-latest + defaults: + run: + working-directory: web + shell: bash + steps: + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 + with: + node-version: "22" + - name: Install pnpm via corepack + run: npm i -g corepack@0.31.0 && corepack enable pnpm + - name: Install dependencies + run: pnpm install --frozen-lockfile + - name: Check studio deps + run: pnpm deps:studio + + web-studio-e2e: + name: Studio UI E2E tests + needs: [changes] + if: > + always() && ( + github.event_name == 'workflow_dispatch' || + needs.changes.outputs.web-studio == 'true' + ) + runs-on: ubuntu-latest + defaults: + run: + working-directory: web + shell: bash + steps: + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 + with: + node-version: "22" + - name: Install pnpm via corepack + run: npm i -g corepack@0.31.0 && corepack enable pnpm + - name: Install dependencies + run: pnpm install --frozen-lockfile + - name: Install Playwright browsers + run: pnpm --filter nemo-studio-ui exec playwright install --with-deps + - name: Run E2E tests + run: CI=1 pnpm --filter nemo-studio-ui test:e2e + - name: Upload E2E artifacts + if: always() + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: studio-e2e-results + retention-days: 7 + path: web/packages/studio/playwright-report/ + benchmark-guardrails: name: Guardrails plugin benchmark if: github.event_name == 'workflow_dispatch' @@ -569,6 +740,12 @@ jobs: - wheel-build - wheel-test - python-e2e-test + - web-typecheck + - web-test + - web-format + - web-lint + - web-studio-deps + - web-studio-e2e - benchmark-guardrails - opa-policy-test if: always() diff --git a/.github/workflows/studio-ci.yaml b/.github/workflows/studio-ci.yaml deleted file mode 100644 index be107a05c7..0000000000 --- a/.github/workflows/studio-ci.yaml +++ /dev/null @@ -1,168 +0,0 @@ -name: Studio CI - -on: - push: - branches: [main] - pull_request: - branches: [main] - paths: - - "web/**" - - ".github/workflows/studio-ci.yaml" - workflow_dispatch: - -concurrency: - group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} - cancel-in-progress: ${{ github.event_name == 'pull_request' }} - -jobs: - changes: - name: Detect path changes - runs-on: ubuntu-latest - outputs: - studio: ${{ steps.changes.outputs.web-studio }} - steps: - - uses: actions/checkout@v6 - - uses: ./.github/actions/changes - id: changes - - web-typecheck: - name: Web typecheck - runs-on: ubuntu-latest - defaults: - run: - working-directory: web - shell: bash - steps: - - uses: actions/checkout@v6 - - uses: actions/setup-node@v4 - with: - node-version: "22" - - name: Install pnpm via corepack - run: npm i -g corepack@0.31.0 && corepack enable pnpm - - name: Install dependencies - run: pnpm install --frozen-lockfile - - name: Typecheck changed packages - run: | - if [ "${{ github.event_name }}" = "pull_request" ]; then - git fetch origin "${{ github.base_ref }}" --depth=1 - pnpm --filter="...[origin/${{ github.base_ref }}]" run --parallel --if-present typecheck - else - pnpm run --recursive --parallel --if-present typecheck - fi - - web-test: - name: Web tests - runs-on: ubuntu-latest - defaults: - run: - working-directory: web - shell: bash - steps: - - uses: actions/checkout@v6 - - uses: actions/setup-node@v4 - with: - node-version: "22" - - name: Install pnpm via corepack - run: npm i -g corepack@0.31.0 && corepack enable pnpm - - name: Install dependencies - run: pnpm install --frozen-lockfile - - name: Test changed packages - run: | - if [ "${{ github.event_name }}" = "pull_request" ]; then - git fetch origin "${{ github.base_ref }}" --depth=1 - pnpm --filter="...[origin/${{ github.base_ref }}]" run --parallel --if-present test:ci - else - pnpm run --recursive --parallel --if-present test:ci - fi - - web-format: - name: Web format check - runs-on: ubuntu-latest - defaults: - run: - working-directory: web - shell: bash - steps: - - uses: actions/checkout@v6 - - uses: actions/setup-node@v4 - with: - node-version: "22" - - name: Install pnpm via corepack - run: npm i -g corepack@0.31.0 && corepack enable pnpm - - name: Install dependencies - run: pnpm install --frozen-lockfile - - name: Check formatting - run: pnpm format - - web-lint: - name: Web lint - runs-on: ubuntu-latest - defaults: - run: - working-directory: web - shell: bash - steps: - - uses: actions/checkout@v6 - - uses: actions/setup-node@v4 - with: - node-version: "22" - - name: Install pnpm via corepack - run: npm i -g corepack@0.31.0 && corepack enable pnpm - - name: Install dependencies - run: pnpm install --frozen-lockfile - - name: Lint - run: pnpm lint - - web-studio-deps: - name: Web studio deps check - needs: changes - if: > - always() && ( - github.event_name == 'workflow_dispatch' || - needs.changes.outputs.studio == 'true' - ) - runs-on: ubuntu-latest - defaults: - run: - working-directory: web - shell: bash - steps: - - uses: actions/checkout@v6 - - uses: actions/setup-node@v4 - with: - node-version: "22" - - name: Install pnpm via corepack - run: npm i -g corepack@0.31.0 && corepack enable pnpm - - name: Install dependencies - run: pnpm install --frozen-lockfile - - name: Check studio deps - run: pnpm deps:studio - - web-studio-e2e: - name: Studio UI E2E tests - if: github.event_name == 'workflow_dispatch' - runs-on: ubuntu-latest - defaults: - run: - working-directory: web - shell: bash - steps: - - uses: actions/checkout@v6 - - uses: actions/setup-node@v4 - with: - node-version: "22" - - name: Install pnpm via corepack - run: npm i -g corepack@0.31.0 && corepack enable pnpm - - name: Install dependencies - run: pnpm install --frozen-lockfile - - name: Install Playwright browsers - run: pnpm --filter nemo-studio-ui exec playwright install --with-deps - - name: Run E2E tests - run: CI=1 pnpm --filter nemo-studio-ui test:e2e - - name: Upload E2E artifacts - if: always() - uses: actions/upload-artifact@v6 - with: - name: studio-e2e-results - retention-days: 7 - path: web/packages/studio/playwright-report/ From 8510944b422c4ba4eabcdc2b6a40c06f1c01bb33 Mon Sep 17 00:00:00 2001 From: Brooke Storm Date: Tue, 9 Jun 2026 15:28:56 -0700 Subject: [PATCH 2/2] ci: fix critical issue with the nvskills check Signed-off-by: Brooke Storm --- .github/workflows/ci.yaml | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 4ef98c39d5..4a4bc8933b 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -116,7 +116,7 @@ jobs: name: Python unit tests (tools) needs: [changes] if: > - always() && ( + !cancelled() && ( github.event_name == 'workflow_dispatch' || needs.changes.outputs.tools == 'true' ) @@ -396,7 +396,7 @@ jobs: name: Web typecheck needs: [changes] if: > - always() && ( + !cancelled() && ( github.event_name == 'workflow_dispatch' || needs.changes.outputs.web-studio == 'true' ) @@ -427,7 +427,7 @@ jobs: name: Web tests needs: [changes] if: > - always() && ( + !cancelled() && ( github.event_name == 'workflow_dispatch' || needs.changes.outputs.web-studio == 'true' ) @@ -458,7 +458,7 @@ jobs: name: Web format check needs: [changes] if: > - always() && ( + !cancelled() && ( github.event_name == 'workflow_dispatch' || needs.changes.outputs.web-studio == 'true' ) @@ -483,7 +483,7 @@ jobs: name: Web lint needs: [changes] if: > - always() && ( + !cancelled() && ( github.event_name == 'workflow_dispatch' || needs.changes.outputs.web-studio == 'true' ) @@ -508,7 +508,7 @@ jobs: name: Web studio deps check needs: [changes] if: > - always() && ( + !cancelled() && ( github.event_name == 'workflow_dispatch' || needs.changes.outputs.web-studio == 'true' ) @@ -533,7 +533,7 @@ jobs: name: Studio UI E2E tests needs: [changes] if: > - always() && ( + !cancelled() && ( github.event_name == 'workflow_dispatch' || needs.changes.outputs.web-studio == 'true' ) @@ -676,6 +676,7 @@ jobs: require-nvskills: runs-on: ubuntu-latest + if: github.event_name == 'pull_request' steps: - name: Require trusted NVSkills signature for skills changes uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0