Skip to content

ci: support fork PRs via environment-gated secrets [DX-1292]#3289

Open
ethan ozelius (ethan-ozelius-contentful) wants to merge 1 commit into
mainfrom
fork-ci
Open

ci: support fork PRs via environment-gated secrets [DX-1292]#3289
ethan ozelius (ethan-ozelius-contentful) wants to merge 1 commit into
mainfrom
fork-ci

Conversation

@ethan-ozelius-contentful

@ethan-ozelius-contentful ethan ozelius (ethan-ozelius-contentful) commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Adds a fork-ci.yaml workflow that runs for PRs opened from forks,
    routing check and e2e-tests jobs through a fork-ci GitHub
    environment so secrets are injected after maintainer approval
  • Updates check.yaml and test-e2e.yaml to accept an optional
    environment input, removing the hard required: true on secrets
    (they still resolve normally for internal PRs — the input defaults to '')
  • Gates main.yaml to skip fork PRs so both workflows don't fire on the
    same event

How it works

When an external contributor opens a fork PR, fork-ci.yaml triggers.
The build job runs immediately. The check and e2e-tests jobs pause
at the fork-ci environment gate until a maintainer approves — at which
point CONTENTFUL_INTEGRATION_TEST_CMA_TOKEN and CLI_E2E_ORG_ID are
injected from environment secrets and the jobs proceed normally.

Internal PRs are unaffected — main.yaml still runs with secrets: inherit.

Pre-requisites (manual setup required before merging)

  • Create a fork-ci environment in repo Settings → Environments
  • Add CONTENTFUL_INTEGRATION_TEST_CMA_TOKEN and CLI_E2E_ORG_ID
    as secrets on that environment
  • Enable required reviewers on the environment (critical — without
    this gate, fork code runs with live secrets unreviewed)

Test plan

  • Open a test PR from a fork and confirm fork-ci workflow triggers
    and pauses at the environment gate
  • Approve the environment deployment and confirm jobs complete
  • Confirm an internal PR still runs main.yaml only

Summary by Bito

This PR implements a secure fork PR CI pipeline for external contributors by introducing a new fork-ci.yaml workflow, updating existing reusable workflows to accept environment inputs, and gating main.yaml to prevent duplicate runs on fork PRs.

Detailed Changes
  • Introduces fork-ci.yaml workflow that triggers for fork PRs (github.event.pull_request.head.repo.fork == true), routing build/check/e2e-tests jobs through a fork-ci GitHub environment for maintainer-approved secret injection
  • Adds optional environment input to check.yaml and test-e2e.yaml reusable workflows, enabling environment-gated secret injection while preserving existing behavior for internal PRs
  • Gates main.yaml to skip fork PRs via conditional check on fork status, preventing duplicate CI runs when fork-ci.yaml is active

@bito-code-review

bito-code-review Bot commented Jul 1, 2026

Copy link
Copy Markdown

Changelist by Bito

This pull request implements the following key changes.

Key Change Files Impacted Summary
New Feature - Fork CI Pipeline for External Contributors
Introduces fork-ci.yaml workflow that triggers for fork PRs, routing build/check/e2e-tests jobs through a fork-ci GitHub environment for maintainer-approved secret injection.
Feature Improvement - Reusable Workflow Environment Input Support
Adds optional environment input to check.yaml and test-e2e.yaml reusable workflows, enabling environment-gated secret injection while preserving existing behavior for internal PRs.
Bug Fix - Main Workflow Fork PR Gating
Gates main.yaml to skip fork PRs via conditional check on fork status, preventing duplicate CI runs when fork-ci.yaml is active.

@bito-code-review

bito-code-review Bot commented Jul 1, 2026

Copy link
Copy Markdown

Impact Analysis by Bito

Interaction Diagram
sequenceDiagram
participant Dev as Developer
participant GH as GitHub
participant MainWF as main.yaml<br/>🔄 Updated | ●●● High
participant ForkWF as fork-ci.yaml<br/>🟩 Added | ●●● High
participant Build as build.yaml
participant Check as check.yaml<br/>🔄 Updated | ●●○ Medium
participant E2E as test-e2e.yaml<br/>🔄 Updated | ●●○ Medium
participant Env as GitHub Environment
Note over MainWF, ForkWF: Fork PRs now use<br/>separate workflow path
Dev->>GH: Create Pull Request
alt [PR from fork repository]
GH->>ForkWF: Trigger fork-ci workflow
ForkWF->>Build: Call build job
Build-->>ForkWF: Build artifacts cached
ForkWF->>Check: Call check with environment=fork-ci
Check->>Env: Use fork-ci environment protection
Check-->>ForkWF: Tests complete
ForkWF->>E2E: Call e2e-tests with environment=fork-ci
E2E->>Env: Use fork-ci environment protection
E2E-->>ForkWF: E2E tests complete
else [PR from internal branch]
GH->>MainWF: Trigger main workflow
MainWF->>Build: Call build job
Build-->>MainWF: Build artifacts cached
MainWF->>Check: Call check (no environment)
Check-->>MainWF: Tests complete
MainWF->>E2E: Call e2e-tests (no environment)
E2E-->>MainWF: E2E tests complete
    end
ForkWF-->>Dev: CI results posted
MainWF-->>Dev: CI results posted
Loading

This MR introduces a separate CI workflow for fork PRs (fork-ci.yaml) with environment protection, while modifying main.yaml to skip fork PRs. The check.yaml and test-e2e.yaml workflows now accept an optional environment input to support this segregation. This prevents untrusted fork code from accessing secrets in the default environment while still allowing CI validation.

Cross-Repository Impact Analysis
What Changed Impact of Change Suggested Review Actions
New fork-ci.yaml workflow added with 'fork-ci' GitHub Environment for fork PR builds - intra-repo: GitHub repository settings must configure 'fork-ci' environment with required secrets: The new workflow references environment: fork-ci which requires repository admin to create the environment and configure protection rules/secrets before fork PRs can run CI - Verify 'fork-ci' GitHub Environment exists in repository settings with appropriate secrets (CONTENTFUL_INTEGRATION_TEST_CMA_TOKEN, CLI_E2E_ORG_ID)
- Configure environment protection rules for fork-ci (reviewers, wait timer) before merging
main.yaml build job now skips fork PRs via conditional - intra-repo: Fork PRs will no longer trigger main.yaml build job: The new condition github.event.pull_request.head.repo.fork == false prevents fork PRs from running the main workflow, routing them to fork-ci.yaml instead - Test that internal PRs (non-forks) still trigger main.yaml correctly
- Verify fork PRs are properly routed to fork-ci.yaml and not silently failing
Code Paths Analyzed

Impact:
CI/CD infrastructure change to isolate fork PR builds into a separate security-hardened workflow path with environment-specific secrets

Flow:
Fork PR → fork-ci.yaml (isolated) vs Internal PR → main.yaml (standard). Both paths eventually call check.yaml and test-e2e.yaml with environment parameter.

Direct Changes (Diff Files):
• .github/workflows/check.yaml [7-10,20] — Added optional environment input parameter and job-level environment setting
• .github/workflows/fork-ci.yaml [1-25] — New workflow file for fork PR CI with environment: fork-ci
• .github/workflows/main.yaml [15] — Added conditional to skip fork PRs in main workflow
• .github/workflows/test-e2e.yaml [7-10,19] — Added optional environment input parameter and job-level environment setting

Repository Impact:
GitHub Actions workflow orchestration: Workflow call chain modified: fork-ci.yaml now acts as entry point for fork PRs, passing environment to reusable workflows
Secret management and security posture: Fork PRs now use isolated 'fork-ci' environment, allowing different secret access controls vs main workflow

Cross-Repository Dependencies:
No cross-repo impacts detected: These are internal CI/CD workflow changes. No external repositories consume these GitHub Actions workflows.

Database/Caching Impact:
• None

API Contract Violations:
• No API contract changes detected

Infrastructure Dependencies:
• GitHub Environment 'fork-ci' must be created in repository settings
• Secrets CONTENTFUL_INTEGRATION_TEST_CMA_TOKEN and CLI_E2E_ORG_ID must be configured for fork-ci environment

Additional Insights:
Security improvement for fork PR handling: Isolating fork PRs to a separate environment with potentially restricted secrets follows security best practices for open source projects

Testing Recommendations

Frontend Impact:
• No frontend impact detected

Service Integration:
• Verify workflow_call chain: fork-ci.yaml → check.yaml → test-e2e.yaml executes correctly
• Test that build artifacts are properly cached and shared between jobs in fork PR path

Data Serialization:
• No data serialization changes detected

Privacy Compliance:
• Verify fork-ci environment has appropriate secret access restrictions
• Confirm CONTENTFUL_INTEGRATION_TEST_CMA_TOKEN in fork-ci has minimal required permissions

Backward Compatibility:
• Test that existing internal PRs (non-forks) continue to use main.yaml path unchanged
• Verify non-fork PRs are not affected by the new fork detection logic

OAuth Functionality:
• None

Cross-Service Communication:
• No cross-service communication changes detected

Reliability Testing:
• None

Additional Insights:
• Create test fork PR to validate end-to-end fork-ci workflow execution
• Document the new fork-ci environment setup in repository documentation

Analysis based on known dependency patterns and edges. Actual impact may vary.

@bito-code-review bito-code-review Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review Agent Run #8d9b5f

Actionable Suggestions - 3
  • .github/workflows/check.yaml - 1
    • Missing required workflow input · Line 8-10
  • .github/workflows/fork-ci.yaml - 2
    • CWE-345: Missing Secrets Propagation · Line 14-18
    • CWE-345: Missing Secrets Propagation · Line 20-24
Filtered by Review Rules

Bito filtered these suggestions based on rules created automatically for your feedback. Manage rules.

  • .github/workflows/main.yaml - 1
Review Details
  • Files reviewed - 4 · Commit Range: 6f9ad54..6f9ad54
    • .github/workflows/check.yaml
    • .github/workflows/fork-ci.yaml
    • .github/workflows/main.yaml
    • .github/workflows/test-e2e.yaml
  • Files skipped - 0
  • Tools
    • Whispers (Secret Scanner) - ✔︎ Successful
    • Detect-secrets (Secret Scanner) - ✔︎ Successful

Bito Usage Guide

Commands

Type the following command in the pull request comment and save the comment.

  • /review - Manually triggers a full AI review.

  • /pause - Pauses automatic reviews on this pull request.

  • /resume - Resumes automatic reviews.

  • /resolve - Marks all Bito-posted review comments as resolved.

  • /abort - Cancels all in-progress reviews.

Refer to the documentation for additional commands.

Configuration

This repository uses Default Agent You can customize the agent settings here or contact your Bito workspace admin at jared.jolton@contentful.com.

Documentation & Help

AI Code Review powered by Bito Logo

Comment thread .github/workflows/check.yaml Outdated
Comment on lines +14 to +18
check:
needs: build
uses: ./.github/workflows/check.yaml
with:
environment: fork-ci

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

CWE-345: Missing Secrets Propagation

The check job calls ./.github/workflows/check.yaml which requires CONTENTFUL_INTEGRATION_TEST_CMA_TOKEN and CLI_E2E_ORG_ID secrets (defined as required in check.yaml:12-15). Without secrets: inherit, these required secrets won't be passed, causing the workflow to fail at runtime. Compare with main.yaml:21 which correctly uses secrets: inherit. (CWE-345)

Code Review Run #8d9b5f


Should Bito avoid suggestions like this for future reviews? (Manage Rules)

  • Yes, avoid them

Comment on lines +20 to +24
e2e-tests:
needs: [build, check]
uses: ./.github/workflows/test-e2e.yaml
with:
environment: fork-ci

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

CWE-345: Missing Secrets Propagation

The e2e-tests job calls ./.github/workflows/test-e2e.yaml which requires CONTENTFUL_INTEGRATION_TEST_CMA_TOKEN and CLI_E2E_ORG_ID secrets (defined as required in test-e2e.yaml:12-15). Without secrets: inherit, these required secrets won't be passed, causing the workflow to fail at runtime. Compare with main.yaml:26 which correctly uses secrets: inherit. (CWE-345)

Code Review Run #8d9b5f


Should Bito avoid suggestions like this for future reviews? (Manage Rules)

  • Yes, avoid them

…Rs originating from forked repos

Add a fork-ci workflow and GitHub environment so external contributors
can open PRs from forks and have CI pass after a maintainer approves
the environment deployment.

- Add fork-ci.yaml that routes fork PRs through a `fork-ci` environment
- Thread an `environment` input through check.yaml and test-e2e.yaml so
  jobs pick up environment secrets when set
- Gate main.yaml's build job to skip for fork PRs to avoid double-runs

Requires a `fork-ci` GitHub environment with required reviewers and the
two secrets defined before this workflow is functional.
@bito-code-review

bito-code-review Bot commented Jul 1, 2026

Copy link
Copy Markdown

Code Review Agent Run #2b05a7

Actionable Suggestions - 0
Additional Suggestions - 1
  • .github/workflows/main.yaml - 1
    • Silent skip for fork PRs · Line 15-15
      The `build` job's new `if` condition skips the job for fork PRs, but `check`, `e2e-tests`, and `release` all have `needs: build` (or depend on it transitively) without conditional logic. Per GitHub Actions behavior, downstream jobs with `needs` are automatically skipped when their dependency is skipped—resulting in silent CI bypass for external contributors' PRs. Consider either: (1) adding the same `if` condition to all downstream jobs, (2) removing `needs` dependencies from jobs that should run independently, or (3) using `if: always() && needs.build.result != 'skipped'` to allow jobs to run only when the dependency is skipped (not when it fails).
Review Details
  • Files reviewed - 4 · Commit Range: 3343d42..3343d42
    • .github/workflows/check.yaml
    • .github/workflows/fork-ci.yaml
    • .github/workflows/main.yaml
    • .github/workflows/test-e2e.yaml
  • Files skipped - 0
  • Tools
    • Whispers (Secret Scanner) - ✔︎ Successful
    • Detect-secrets (Secret Scanner) - ✔︎ Successful

Bito Usage Guide

Commands

Type the following command in the pull request comment and save the comment.

  • /review - Manually triggers a full AI review.

  • /pause - Pauses automatic reviews on this pull request.

  • /resume - Resumes automatic reviews.

  • /resolve - Marks all Bito-posted review comments as resolved.

  • /abort - Cancels all in-progress reviews.

Refer to the documentation for additional commands.

Configuration

This repository uses Default Agent You can customize the agent settings here or contact your Bito workspace admin at jared.jolton@contentful.com.

Documentation & Help

AI Code Review powered by Bito Logo

@bito-code-review

Copy link
Copy Markdown

Functional Validation by Bito

SourceRequirement / Code AreaStatusNotes
DX-1292Ensure CLI e2e tests properly inject environment variables when running for forked pull requests✅ MetThe PR implements environment variable injection for forked PRs by: (1) Creating a new .github/workflows/fork-ci.yaml workflow that detects forked PRs with `if: github.event.pull_request.head.repo.fork == true`, (2) Passing `environment: fork-ci` to the e2e-tests workflow via the `with` block, and (3) Adding `environment` input parameter and applying `environment: ${{ inputs.environment }}` to the e2e-tests job in .github/workflows/test-e2e.yaml. This ensures environment variables are properly injected when running e2e tests on pull requests from forks.

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