diff --git a/.github/workflows/pr-limit.yaml b/.github/workflows/pr-limit.yaml new file mode 100644 index 0000000000..ebf95d3499 --- /dev/null +++ b/.github/workflows/pr-limit.yaml @@ -0,0 +1,40 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +name: pr-limit + +# pull_request_target runs in the base repo context, giving the token write +# access even for fork PRs. This is safe here because this workflow never +# checks out or executes code from the PR — it only counts open PRs and +# closes excess ones. Do NOT add a checkout step or run PR-sourced code +# in this workflow to prevent injection attacks. +on: + pull_request_target: + types: [opened, reopened] + +permissions: + pull-requests: write + +jobs: + check-pr-limit: + runs-on: ubuntu-latest + timeout-minutes: 5 + steps: + - name: Check open PR count for author + env: + GH_TOKEN: ${{ github.token }} + AUTHOR: ${{ github.event.pull_request.user.login }} + PR_NUMBER: ${{ github.event.pull_request.number }} + REPO: ${{ github.repository }} + run: | + OPEN_COUNT=$(gh pr list --repo "$REPO" --author "$AUTHOR" --state open --json number --jq 'length') + + echo "Author $AUTHOR has $OPEN_COUNT open PR(s)" + + if [ "$OPEN_COUNT" -gt 10 ]; then + gh pr comment "$PR_NUMBER" --repo "$REPO" --body \ + "This repository limits contributors to 10 open pull requests. Please close or merge existing PRs before opening new ones." + gh pr close "$PR_NUMBER" --repo "$REPO" + echo "::error::PR closed — author $AUTHOR exceeds the 10 open PR limit" + exit 1 + fi diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml new file mode 100644 index 0000000000..936b6ef91f --- /dev/null +++ b/.github/workflows/pr.yaml @@ -0,0 +1,58 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +name: pr + +on: + pull_request: + types: [opened, synchronize, reopened] + +permissions: + contents: read + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + test-unit: + runs-on: ubuntu-latest + timeout-minutes: 10 + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: "22" + cache: npm + + - name: Install root dependencies + run: npm install + + - name: Install and build TypeScript plugin + working-directory: nemoclaw + run: | + npm install + npm run build + + - name: Run root unit tests + run: node --test test/*.test.js + + - name: Run TypeScript unit tests + working-directory: nemoclaw + run: npx vitest run + + test-e2e-sandbox: + runs-on: ubuntu-latest + timeout-minutes: 15 + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Build sandbox test image + run: docker build -f test/Dockerfile.sandbox -t nemoclaw-sandbox-test . + + - name: Run sandbox E2E tests + run: docker run --rm -v "${{ github.workspace }}/test:/opt/test" nemoclaw-sandbox-test /opt/test/e2e-test.sh