Skip to content

refactor: add SourceControlProvider interface for GitHub#68

Merged
ColeMurray merged 6 commits intomainfrom
refactor/source-control-provider
Feb 5, 2026
Merged

refactor: add SourceControlProvider interface for GitHub#68
ColeMurray merged 6 commits intomainfrom
refactor/source-control-provider

Conversation

@ColeMurray
Copy link
Owner

Summary

Introduces a pluggable SourceControlProvider interface for source control platforms, with an initial GitHub implementation. This establishes the abstraction layer for future GitLab/Bitbucket support.

  • Add source-control module with types, errors, and token manager
  • Implement GitHubSourceControlProvider with getRepository(), createPullRequest(), and generatePushAuth() methods
  • Refactor handleCreatePR in SessionDO to use the new provider interface
  • Organize files following codebase conventions: types.ts, errors.ts, providers/constants.ts, providers/types.ts

Key Design Decisions

  • Naming: SourceControlProvider matches existing SandboxProvider pattern
  • Push stays in session layer: Provider only generates auth tokens; push coordination via WebSocket remains in the durable object
  • Lazy initialization: Provider is created on first use, matching the lifecycle manager pattern
  • Error classification: transient vs permanent errors for future retry logic

Bug Fixes (from code review)

  • Properly detect merged PR state (GitHub returns state: "closed" with merged: true)
  • Fail early when push auth generation fails instead of attempting a doomed push

Test plan

  • TypeScript compilation passes (npm run typecheck -w @open-inspect/control-plane)
  • ESLint passes (npm run lint -w @open-inspect/control-plane)
  • Deploy to staging and verify PR creation flow works end-to-end

Introduces a pluggable abstraction for source control platforms
(GitHub, with future support for GitLab/Bitbucket) through the
SourceControlProvider interface.

Changes:
- Add source-control module with types, errors, and token manager
- Implement GitHubSourceControlProvider with getRepository(),
  createPullRequest(), and generatePushAuth() methods
- Refactor handleCreatePR in SessionDO to use the new provider
- Organize files: types.ts, errors.ts, providers/constants.ts,
  providers/types.ts following codebase conventions

The provider properly handles merged PR state detection and fails
early when push auth generation fails (rather than attempting a
doomed push).
@github-actions
Copy link

github-actions bot commented Feb 5, 2026

Terraform Validation Results

Step Status
Format ⚠️
Init
Validate

Note: Terraform plan was skipped because secrets are not configured. This is expected for external contributors. See docs/GETTING_STARTED.md for setup instructions.

Pushed by: @ColeMurray, Action: pull_request

@greptile-apps
Copy link

greptile-apps bot commented Feb 5, 2026

Greptile Overview

Greptile Summary

Introduced a pluggable SourceControlProvider interface with an initial GitHub implementation, establishing the foundation for supporting multiple source control platforms (GitLab, Bitbucket).

Key changes:

  • Abstracted PR creation and repository operations behind the SourceControlProvider interface
  • Properly handles merged PR state detection (GitHub returns state: "closed" with merged: true)
  • Fails early when push auth generation fails instead of attempting doomed push operations
  • Maintained token refresh logic and error handling from the original implementation
  • Organized code following codebase conventions with separate types.ts, errors.ts, and provider modules

The refactoring maintains all existing functionality while improving testability and enabling future GitLab/Bitbucket support.

Move token decryption to the session layer where it belongs:
- Remove SourceControlTokenManager interface and token-manager.ts
- Simplify SourceControlAuthContext to use plain token instead of encrypted
- Session layer now decrypts tokens before calling provider methods
- Provider is now a pure API client with no encryption concerns

This improves separation of concerns:
- Session layer: storage, encryption, token refresh
- Provider: API calls with plain tokens

Also simplifies testing - providers can be tested with plain token strings
without needing to mock encryption.
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR introduces a pluggable SourceControlProvider abstraction layer to enable future support for multiple source control platforms (GitLab, Bitbucket). The initial implementation includes a GitHub provider that wraps existing GitHub API functionality.

Changes:

  • Adds source-control module with provider interface, types, error handling, and token management
  • Implements GitHubSourceControlProvider with repository info retrieval, PR creation, and push authentication
  • Refactors SessionDO.handleCreatePR to use the new provider interface with improved error handling

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
source-control/types.ts Core interfaces defining the provider abstraction, including capabilities, repository info, auth contexts, and PR configuration
source-control/errors.ts Error classification system distinguishing transient (retryable) from permanent errors
source-control/token-manager.ts Token encryption/decryption wrapper implementing the SourceControlTokenManager interface
source-control/providers/types.ts Provider-specific configuration types, starting with GitHubProviderConfig
source-control/providers/constants.ts Shared constants for API base URLs and user-agent strings
source-control/providers/github-provider.ts GitHub implementation with repository queries, PR creation, labels, reviewers, and push auth generation
source-control/providers/index.ts Provider factory exports
source-control/index.ts Main module exports consolidating types, errors, token manager, and providers
session/durable-object.ts Integration of the source control provider with lazy initialization, improved error handling, and early failure when push auth generation fails

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@github-actions
Copy link

github-actions bot commented Feb 5, 2026

Terraform Validation Results

Step Status
Format ⚠️
Init
Validate

Note: Terraform plan was skipped because secrets are not configured. This is expected for external contributors. See docs/GETTING_STARTED.md for setup instructions.

Pushed by: @ColeMurray, Action: pull_request

Remove speculative generality - capabilities were declared but never
checked anywhere in the codebase. Following YAGNI: add capability
checks when a second provider (GitLab/Bitbucket) is actually implemented.
@github-actions
Copy link

github-actions bot commented Feb 5, 2026

Terraform Validation Results

Step Status
Format ⚠️
Init
Validate

Note: Terraform plan was skipped because secrets are not configured. This is expected for external contributors. See docs/GETTING_STARTED.md for setup instructions.

Pushed by: @ColeMurray, Action: pull_request

File was not imported anywhere after migration to SourceControlProvider.
Functions like getPullRequestByHead, updatePullRequest, addPRComment
can be added to the provider interface if needed in the future.
@github-actions
Copy link

github-actions bot commented Feb 5, 2026

Terraform Validation Results

Step Status
Format ⚠️
Init
Validate

Note: Terraform plan was skipped because secrets are not configured. This is expected for external contributors. See docs/GETTING_STARTED.md for setup instructions.

Pushed by: @ColeMurray, Action: pull_request

Add section comments distinguishing user-authenticated operations
(getRepository, createPullRequest) from app-authenticated operations
(generatePushAuth). Explains why generatePushAuth() doesn't take an
auth parameter - it uses app credentials configured at construction.
@github-actions
Copy link

github-actions bot commented Feb 5, 2026

Terraform Validation Results

Step Status
Format ⚠️
Init
Validate

Note: Terraform plan was skipped because secrets are not configured. This is expected for external contributors. See docs/GETTING_STARTED.md for setup instructions.

Pushed by: @ColeMurray, Action: pull_request

Use fetchWithTimeout (60s timeout) instead of raw fetch() to prevent
hung GitHub API requests from blocking the Durable Object indefinitely.
Consistent with existing pattern in auth/github-app.ts.
@github-actions
Copy link

github-actions bot commented Feb 5, 2026

Terraform Validation Results

Step Status
Format ⚠️
Init
Validate

Note: Terraform plan was skipped because secrets are not configured. This is expected for external contributors. See docs/GETTING_STARTED.md for setup instructions.

Pushed by: @ColeMurray, Action: pull_request

@ColeMurray ColeMurray merged commit cfc9273 into main Feb 5, 2026
10 checks passed
@ColeMurray ColeMurray deleted the refactor/source-control-provider branch February 5, 2026 07:57
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.

1 participant