Skip to content

Conversation

Murderlon
Copy link
Member

No description provided.

@Murderlon Murderlon self-assigned this Sep 23, 2025
Copy link

changeset-bot bot commented Sep 23, 2025

⚠️ No Changeset found

Latest commit: f741627

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

Copy link

coderabbitai bot commented Sep 23, 2025

Walkthrough

Reworks the GitHub Actions CI workflow to replace pull_request_target label gating with environment-protected external-PR handling, restructures triggers, permissions, jobs, checkout and Node setup, and removes a single bug-bounty notice line from bb.test.

Changes

Cohort / File(s) Summary of changes
CI workflow gating, triggers & jobs
.github/workflows/ci.yml
Replaced safe-to-test / pull_request_target label gating with environment-protected external-PR handling; adjusted pull_request/pull_request_target event types; added basic-validation job (build & lint) running without secrets; added tests job that runs with secrets for internal PRs and uses an external-testing environment for external PRs; added environment annotation for external contributors; improved concurrency grouping and cancel-in-progress behavior; reduced permissions to contents: read and pull-requests: read.
Checkout, Node setup, install & test steps
.github/workflows/ci.yml
Overhauled checkout usage to use trusted base for external PRs with explanatory comments; standardized actions/setup-node to v4 and Node.js version to 20.x across jobs; added explicit checkout, Node setup (v4) with caching, dependency install, build, format-check, and lint steps in basic-validation; updated tests job to use decrypted secrets step, removed duplicate format/lint from test sequence, and kept npm run test execution.
Test file cleanup
bb.test
Removed a single line containing a bug-bounty notice; no code, interface, or logic changes.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Pre-merge checks and finishing touches

❌ Failed checks (1 inconclusive)
Check name Status Explanation Resolution
Description Check ❓ Inconclusive No pull request description was provided, so there is no author-supplied context to verify against the changeset; the raw summary shows the CI workflow changes but that information comes from the diff rather than a PR description. Because the description is missing, this check cannot confirm whether the author documented intent, risk, or reviewer guidance. Please add a brief PR description summarizing the intent and scope (use of environments, key workflow/job changes, and permission updates) and note any reviewer actions or security rationale so reviewers can quickly assess scope and risk.
✅ Passed checks (2 passed)
Check name Status Explanation
Title Check ✅ Passed The title "Use environments to protect CI" is concise and accurately captures the primary change in the diff, which migrates CI gating to GitHub environments and adds environment-protected handling in .github/workflows/ci.yml (including an external-testing environment and related job/permission updates). It is a single clear sentence that highlights the most important change and is suitable for history scanning.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.
✨ Finishing touches
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch ci-environments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (4)
.github/workflows/ci.yml (4)

23-25: Tighten permissions to least privilege.

Unless a step writes to PRs, set pull-requests: read. Safer for pull_request_target.

 permissions:
-  contents: read
-  pull-requests: write
+  contents: read
+  pull-requests: read

54-56: Use setup-node v4 and a maintained Node version spec.

Update action to v4 and prefer 20.x (or lts/*) to avoid pinning an invalid patch.

-        uses: actions/setup-node@v3
+        uses: actions/setup-node@v4
         with:
-          node-version: 20.19
+          node-version: 20.x

58-60: Optional: Block postinstall scripts for untrusted contexts.

If you keep a single job for all contexts, add --ignore-scripts when running on external PRs to reduce supply‑chain risk.

Example (conditional flag):

      - name: Install dependencies
        run: npm ci --no-fund --no-audit ${{ (github.event_name == 'pull_request_target' && github.event.pull_request.head.repo.full_name != github.repository) && '--ignore-scripts' || '' }}

21-21: Optional: Enable cancel-in-progress to save runners.

Typical CI behavior cancels superseded runs on new commits.

-concurrency: ${{ github.workflow }}--${{ github.ref }}
+concurrency:
+  group: ${{ github.workflow }}--${{ github.ref }}
+  cancel-in-progress: true
📜 Review details

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3a36643 and 23eee4f.

📒 Files selected for processing (2)
  • .github/workflows/ci.yml (2 hunks)
  • bb.test (0 hunks)
💤 Files with no reviewable changes (1)
  • bb.test
🔇 Additional comments (1)
.github/workflows/ci.yml (1)

17-19: PR trigger runs only when ci.yml changes. Is this intended?

With paths: [.github/workflows/ci.yml], regular same-repo PRs won’t run this workflow via pull_request. Coverage then relies entirely on pull_request_target. Confirm this is intentional to avoid double runs; otherwise, drop the path filter.

If you want standard PR CI, change to:

-  pull_request:
-    types: [opened, synchronize, reopened]
-    paths:
-      - .github/workflows/ci.yml
+  pull_request:
+    types: [opened, synchronize, reopened]

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (4)
.github/workflows/ci.yml (4)

11-20: Avoid double-triggering the workflow for same-repo PRs.

You trigger both pull_request and pull_request_target. Same-repo PRs will fire both, and your tests job currently matches both, causing duplicate runs.

Options:

  • Prefer pull_request for same-repo PRs; reserve pull_request_target only for forked PRs (enforce via job if).
  • Or drop pull_request_target and use a separate workflow for gated external tests.

22-24: Concurrency key may collide on pull_request_target.

github.ref for pull_request_target is the base branch (e.g., refs/heads/main), so multiple forked PR runs can cancel each other.

Consider:

-  group: ${{ github.workflow }}--${{ github.ref }}
+  group: ${{ github.workflow }}--${{ github.event_name == 'pull_request_target' && format('pr#{0}', github.event.pull_request.number) || github.ref }}

31-57: Basic validation job looks good; add npm cache for speed.

       - name: Install Node.js
         uses: actions/setup-node@v4
         with:
           node-version: 20.x
+          cache: npm
+          cache-dependency-path: package-lock.json

79-83: Run scripts with strict shell flags.

Harden the decrypt step.

-      - name: Decrypt keyfile
-        run: ./.github/scripts/decrypt_secret.sh
+      - name: Decrypt keyfile
+        shell: bash
+        run: set -euo pipefail; ./.github/scripts/decrypt_secret.sh
📜 Review details

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 23eee4f and e00d780.

📒 Files selected for processing (1)
  • .github/workflows/ci.yml (2 hunks)
🔇 Additional comments (4)
.github/workflows/ci.yml (4)

26-29: Permissions tightened appropriately.


62-67: Do not set a dynamic environment; empty string is invalid and property access can break on push.

Using environment: ${{ ... || '' }} is invalid (empty env name), and github.event.pull_request.* is undefined on push. Split jobs instead: one trusted job without environment, one gated job for external PRs with environment: external-testing.

Apply this refactor:

-  tests:
+  tests:
     name: Tests
     runs-on: ubuntu-latest
-    # SECURITY: Use environment protection for external contributors
-    environment: ${{ github.event.pull_request.head.repo.full_name != github.repository && 'external-testing' || '' }}
-    # Run tests with secrets for:
-    # 1. Push to main (trusted), OR
-    # 2. PR from same repository (trusted)
-    # For external PRs: environment protection requires manual approval
+    # Trusted contexts only (no environment gating here)
     if: |
-      github.event_name == 'push' ||
-      github.event.pull_request.head.repo.full_name == github.repository
+      github.event_name == 'push' ||
+      (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository)
@@
       - name: Checkout sources
         uses: actions/checkout@v4
         with:
-          # Environment protection provides security - we can safely checkout PR code
-          ref: ${{ github.event.pull_request.head.sha || github.sha }}
+          ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }}
@@
           AWS_REGION: ${{secrets.AWS_REGION}}
+
+  tests-external:
+    name: Tests (external, gated)
+    runs-on: ubuntu-latest
+    if: github.event_name == 'pull_request_target' && github.event.pull_request.head.repo.full_name != github.repository
+    environment: external-testing
+    permissions:
+      contents: read
+      pull-requests: read
+    steps:
+      - name: Checkout PR head (approved via environment)
+        uses: actions/checkout@v4
+        with:
+          ref: ${{ github.event.pull_request.head.sha }}
+      - name: Install Node.js
+        uses: actions/setup-node@v4
+        with:
+          node-version: 20.x
+      - name: Install dependencies
+        run: npm ci --no-fund --no-audit
+      - name: Build
+        run: npm run build
+      - name: Decrypt keyfile
+        run: ./.github/scripts/decrypt_secret.sh
+        env:
+          KEYFILE_PASSPHRASE: ${{secrets.KEYFILE_PASSPHRASE}}
+      - name: Run tests
+        run: npm run test
+        env:
+          AWS_BUCKET: ${{secrets.AWS_BUCKET}}
+          AWS_ACCESS_KEY_ID: ${{secrets.AWS_ACCESS_KEY_ID}}
+          AWS_SECRET_ACCESS_KEY: ${{secrets.AWS_SECRET_ACCESS_KEY}}
+          AZURE_ACCOUNT_ID: ${{secrets.AZURE_ACCOUNT_ID}}
+          AZURE_ACCOUNT_KEY: ${{secrets.AZURE_ACCOUNT_KEY}}
+          AZURE_CONTAINER_NAME: ${{secrets.AZURE_CONTAINER_NAME}}
+          AWS_REGION: ${{secrets.AWS_REGION}}

68-71: External PRs never start this job; environment approval is unreachable.

The if excludes forked PRs, so the gated path can’t run. Allow pull_request_target for forks or split jobs as suggested.

Minimal fix if you keep a single job:

     if: |
-      github.event_name == 'push' ||
-      github.event.pull_request.head.repo.full_name == github.repository
+      github.event_name == 'push' ||
+      (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository) ||
+      (github.event_name == 'pull_request_target' && github.event.pull_request.head.repo.full_name != github.repository)

Note: This still leaves the invalid dynamic environment (see prior comment). Splitting jobs is safer.


73-78: Guard PR-only context in ref expression.

github.event.pull_request.head.sha is undefined on push; guard by event name to avoid expression pitfalls.

-          ref: ${{ github.event.pull_request.head.sha || github.sha }}
+          ref: ${{ (github.event_name == 'pull_request' || github.event_name == 'pull_request_target') && github.event.pull_request.head.sha || github.sha }}

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
.github/workflows/ci.yml (2)

22-24: Unify PR concurrency grouping across pull_request and pull_request_target.

Currently only targets pull_request_target. Group both by PR number.

-  group: ${{ github.workflow }}--${{ github.event_name == 'pull_request_target' && format('pr#{0}', github.event.pull_request.number) || github.ref }}
+  group: ${{ github.workflow }}--${{ (github.event_name == 'pull_request' || github.event_name == 'pull_request_target') && format('pr#{0}', github.event.pull_request.number) || github.ref }}

11-15: Trigger hygiene: pull_request_target is configured but no job runs for it.

Either add the gated external job (preferred) or drop this trigger to avoid no-op runs.

📜 Review details

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e00d780 and f741627.

📒 Files selected for processing (1)
  • .github/workflows/ci.yml (2 hunks)
🔇 Additional comments (4)
.github/workflows/ci.yml (4)

78-80: Guard checkout ref selection for non‑PR events.

Avoid unguarded access to github.event.pull_request.* on push.

-          ref: ${{ github.event.pull_request.head.sha || github.sha }}
+          ref: ${{ (github.event_name == 'pull_request' || github.event_name == 'pull_request_target') && github.event.pull_request.head.sha || github.sha }}

26-29: Permissions tightened appropriately.

contents: read and pull-requests: read are good defaults for these jobs.


65-65: Dynamic environment is invalid (empty string) and dereferences PR fields on push. Split jobs.

environment: '' is not allowed, and the expression touches github.event.pull_request.* even on push, which can break the run. Remove the dynamic environment and create a separate gated job for external PRs.

Apply this diff to remove the invalid dynamic environment on the trusted job:

-    # SECURITY: Use environment protection for external contributors
-    environment: ${{ github.event.pull_request.head.repo.full_name != github.repository && 'external-testing' || '' }}

Then add a gated job for external PRs (example):

  external-pr:
    name: External PR (gated)
    runs-on: ubuntu-latest
    if: github.event_name == 'pull_request_target' && github.event.pull_request.head.repo.full_name != github.repository
    environment: external-testing
    permissions:
      contents: read
      pull-requests: read
    steps:
      - name: Checkout trusted base
        uses: actions/checkout@v4
        with:
          ref: ${{ github.sha }}
      - name: Install Node.js
        uses: actions/setup-node@v4
        with:
          node-version: 20.x
          cache: npm
          cache-dependency-path: package-lock.json
      - name: Install dependencies
        run: npm ci --no-fund --no-audit
      - name: Build
        run: npm run build
      - name: Run tests
        run: npm run test
        env:
          AWS_BUCKET: ${{secrets.AWS_BUCKET}}
          AWS_ACCESS_KEY_ID: ${{secrets.AWS_ACCESS_KEY_ID}}
          AWS_SECRET_ACCESS_KEY: ${{secrets.AWS_SECRET_ACCESS_KEY}}
          AZURE_ACCOUNT_ID: ${{secrets.AZURE_ACCOUNT_ID}}
          AZURE_ACCOUNT_KEY: ${{secrets.AZURE_ACCOUNT_KEY}}
          AZURE_CONTAINER_NAME: ${{secrets.AZURE_CONTAINER_NAME}}
          AWS_REGION: ${{secrets.AWS_REGION}}

70-73: External PRs never run this job; environment gating is dead code.

The if excludes forked PRs, so approval is never requested. Either split jobs (preferred; see prior comment) or broaden the condition.

If you keep a single job, minimally allow PR events:

     if: |
-      github.event_name == 'push' ||
-      (github.event.pull_request.head.repo.full_name == github.repository)
+      github.event_name == 'push' ||
+      (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository) ||
+      (github.event_name == 'pull_request_target')

Note: With the above, ensure untrusted code paths are gated by an environment before exposing secrets.

@Murderlon Murderlon merged commit 15c2d14 into main Sep 24, 2025
6 checks passed
@Murderlon Murderlon deleted the ci-environments branch September 24, 2025 07:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants