Skip to content

Extracts integrations into the @gitlens/integrations workspace package#5324

Draft
eamodio wants to merge 1 commit into
mainfrom
debt/extract-integrations-package
Draft

Extracts integrations into the @gitlens/integrations workspace package#5324
eamodio wants to merge 1 commit into
mainfrom
debt/extract-integrations-package

Conversation

@eamodio

@eamodio eamodio commented Jun 5, 2026

Copy link
Copy Markdown
Member

This needs a thorough review/testing. Agents have gone through and come up clean, but it needs human attention — especially at the boundary layers (which I personally haven't look at after the latest round of significant changes as I ran out of time before I leave for vacation).

Extracts src/plus/integrations/ into a cloud-only @gitlens/integrations workspace package consumed through a single runtime port (IntegrationServiceContext: storage/account/config/http/cache/repositories + optional hooks) and composed via createIntegrationManager(ctx). The package is vscode-free; the host wires its services through an adapter under src/plus/integrations/host/.

  • Unifies the former subscription/cloudConnection/authentication/uris ports into one account port and relocates the GK-Dev connect/manage OAuth round-trips host-side (gkDevFlows).
  • Moves the per-provider API clients into the package; constructs cloud auth providers in-package while keeping createAuthenticationProvider as an optional consumer extension point.
  • De-leaks the host gitlens. secret-key prefix (host re-prepends; stored keys stay byte-identical).
  • Keeps the self-managed Pro paywall on the GitHub/GitLab Enterprise/self-hosted host connect sites only (Bitbucket Server / Azure DevOps Server stay free).
  • Groups outbound hooks by domain; makes isIntegrationsEnabled an optional, default-enabled config port.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

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 extracts the existing integrations implementation into a new vscode-free workspace package (@gitlens/integrations), shifting the GitLens host to consume integrations through a single runtime context port and moving provider API clients/auth/connect flows into the package while keeping host-only wiring/adapters in src/plus/integrations/host/.

Changes:

  • Introduces the new packages/plus/integrations workspace package (public facade, runtime context port, provider clients, telemetry/source mapping, and package-level tests/fixtures).
  • Refactors host/webview code to import integration constants/models/utils from @gitlens/integrations/* and adapts Container to construct + memoize a single integration context + manager.
  • Updates build/lint/test tooling (webpack aliases, tsconfig paths, esbuild test bundling allowlist, workspace globs, core bundle specifier rewriting) to include the new package and ensure CJS↔ESM interop works in tests.

Reviewed changes

Copilot reviewed 117 out of 123 changed files in this pull request and generated no comments.

Show a summary per file
File Description
webpack.config.mjs Adds webpack alias for @gitlens/integrations source.
tsconfig.node.json Adds TS path mapping + include for integrations package in node build.
tsconfig.browser.json Adds TS path mapping + include for integrations package in browser build.
tests/fixtures/integrations-consumer/tsconfig.json New fixture tsconfig for an external consumer compile check.
tests/fixtures/integrations-consumer/src/consumer.test.ts New external-consumer fixture exercising public facade and runtime-only context.
tests/fixtures/integrations-consumer/scripts/run.mjs Bundles + runs the consumer fixture via esbuild to validate CJS interop at runtime.
tests/fixtures/integrations-consumer/package.json Fixture package wiring to workspace deps and scripts.
src/webviews/settings/settingsWebview.ts Switches webview settings imports to @gitlens/integrations/*.
src/webviews/settings/protocol.ts Switches IssuesCloudHostIntegrationId import to package.
src/webviews/rpc/services/integrations.ts Updates constants/providersMetadata imports and makes state querying synchronous (RPC remains async).
src/webviews/rpc/services/drafts.ts Switches provider helpers imports to package.
src/webviews/plus/graph/graphWebview.utils.ts Switches integration constants import to package.
src/webviews/plus/graph/graphWebview.ts Switches integration constants/types imports to package.
src/webviews/home/protocol.ts Switches IntegrationDescriptor type import to package.
src/webviews/home/homeWebview.ts Switches integrations types/constants/providersMetadata imports; syncs integration state derivation.
src/webviews/apps/tsconfig.json Adds TS path mapping for @gitlens/integrations/* to webview apps.
src/webviews/apps/settings/settings.ts Switches integration types/constants imports to package.
src/webviews/apps/plus/shared/components/integrations-chip.ts Switches integration id type import to package.
src/uris/uriService.ts Switches auth URI prefix import to package.
src/uris/deepLinks/deepLinkService.ts Switches integration id guards import to package.
src/quickpicks/remoteProviderPicker.ts Switches providers metadata + mapping utils to package.
src/quickpicks/integrationPicker.ts Switches integration constants import to package and removes retired local self-managed ids.
src/plus/startWork/startWorkBase.ts Removes local-integration connect flow; uses cloud integrations flow and shared quickpick helpers.
src/plus/startWork/associateIssueWithBranch.ts Switches getIssueOwner import to package; removes local-connect placeholder.
src/plus/launchpad/startReview.ts Switches IntegrationIds import to package; adds host-side paywall gate before connect.
src/plus/launchpad/launchpadProvider.ts Switches provider utilities/types to package and adapts cancellation to AbortSignal.
src/plus/launchpad/launchpadIndicator.ts Switches integration ids/types to package.
src/plus/launchpad/launchpad.ts Switches integration ids/provider enums to package; adds host-side paywall gate before connect; removes local-connect flow.
src/plus/launchpad/enrichmentService.ts Switches integration ids to package and removes retired local self-managed ids from mapping.
src/plus/integrations/utils/-webview/integration.utils.ts Replaces prior utility collection with a host-side ensureIntegrationConnectAllowed Pro gate.
src/plus/integrations/providers/github/github.ts Removes host-side GitHub API client creation (moved into package).
src/plus/integrations/host/providers/githubGitProvider.ts Moves GitHub git provider host adapter to use package auth/session/context types and manager’s GitHub API.
src/plus/integrations/authentication/linear.ts Removes legacy host-side provider auth class (moved into package).
src/plus/integrations/authentication/jira.ts Removes legacy host-side provider auth class (moved into package).
src/plus/integrations/authentication/integrationAuthenticationService.ts Removes legacy host-side auth service (moved into package).
src/plus/integrations/authentication/gitlab.ts Removes legacy host-side GitLab auth providers (moved into package).
src/plus/integrations/authentication/github.ts Removes legacy host-side GitHub auth providers (moved into package).
src/plus/integrations/authentication/bitbucket.ts Removes legacy host-side Bitbucket auth providers (moved into package).
src/plus/integrations/authentication/azureDevOps.ts Removes legacy host-side Azure DevOps auth providers (moved into package).
src/plus/gk/utils/-webview/integrationAuthentication.utils.ts Switches integration auth session types imports to package.
src/plus/gk/serverConnection.ts Switches token info conversion types imports to package.
src/plus/drafts/draftsService.ts Switches provider helpers imports to package; adapts configured integrations lookup to sync.
src/git/utils/-webview/repository.utils.ts Switches getIntegrationIdForRemote import to package.
src/git/utils/-webview/remote.utils.ts Switches integration utils/types imports to package and updates configured integrations lookup API.
src/git/utils/-webview/branch.issue.utils.ts Switches entity-identifier helpers to package and adapts issue-resolution API to new resolver/caching hook.
src/git/remotes/remoteProviderConfigs.ts Switches configured integration descriptor + id helpers to package.
src/git/models/repositoryShape.ts Switches SupportedCloudIntegrationIds type to package.
src/git/gitProviderContext.ts Bridges sync getConfigured into Promise-typed remotes port.
src/errors.ts Removes ProviderFetchError from host (moved into package).
src/env/node/providers.ts Updates dynamic import path to new host provider adapter location.
src/env/browser/providers.ts Updates import path to new host provider adapter location.
src/container.ts Replaces legacy integrations services/APIs with createIntegrationServiceContext + createIntegrationManager.
src/constants.telemetry.ts Switches integration id types to package and removes sourceToContext/detailToContext (moved into package).
src/constants.storage.ts Switches IntegrationIds/IntegrationConnectedKey types to package.
src/config.ts Removes cloudIntegrations config interface (setting removed).
src/commands/remoteProviders.ts Adds host-side ensureIntegrationConnectAllowed gate before connecting remote integration.
src/commands/patches.ts Switches integration id + entity-identifier helper imports to package.
src/commands/git/branch/create.ts Switches getIssueOwner import to package.
src/commands/cloudIntegrations.ts Switches SupportedCloudIntegrationIds type import to package.
src/cache.ts Switches integration model types imports to package.
src/autolinks/utils/-webview/autolinks.utils.ts Switches IssuesCloudHostIntegrationId import to package.
src/autolinks/autolinksProvider.ts Switches integration/auth/model/utils imports to package.
scripts/esbuild.tests.mjs Ensures @gitlens/* workspace packages are bundled from source; clears stale test outputs before build.
scripts/esbuild.mjs Adds @host alias for host-side path resolution.
pnpm-workspace.yaml Adds tests/fixtures/* to workspace package set.
pnpm-lock.yaml Adds workspace importer entries for @gitlens/integrations and the consumer fixture; pins provider-apis.
packages/utils/src/disposable.ts Introduces minimal Disposable type for vscode-free packages; adjusts UnifiedDisposable typing.
packages/plus/integrations/tsconfig.json Adds new package tsconfig with bundler moduleResolution for provider-apis interop typing.
packages/plus/integrations/src/utils/integration.utils.ts Adds package-level integration id and remote→integration mapping utilities.
packages/plus/integrations/src/telemetry.ts Moves sourceToContext/detailToContext mapping into the package.
packages/plus/integrations/src/providers/utils.ts Refactors entity identifier encoding/decoding + issue resolution to be host-agnostic via resolver/caching hooks.
packages/plus/integrations/src/providers/providersApi.ts Normalizes provider-apis factory shape; moves to ctx-provided HTTP/userAgent.
packages/plus/integrations/src/providers/models.ts Adapts provider metadata and enums for package ownership; removes retired local self-managed variants.
packages/plus/integrations/src/providers/linear.ts Migrates Linear integration to package; switches cancellation to AbortSignal and autolink types.
packages/plus/integrations/src/providers/jira.ts Migrates Jira integration to package; uses ctx storage; switches cancellation to AbortSignal.
packages/plus/integrations/src/providers/gitlab/gitlab.utils.ts Updates GitLab utils to new integration id set (cloud self-hosted only).
packages/plus/integrations/src/providers/gitlab/tests/gitlab.utils.test.ts Updates test harness imports (node:assert/strict + mocha).
packages/plus/integrations/src/providers/github/models.ts Adds re-export shim for GitHub models from @gitlens/git-github.
packages/plus/integrations/src/providers/github/github.utils.ts Updates GitHub utils to new integration id set (cloud enterprise only).
packages/plus/integrations/src/providers/github/github.ts Adds package-owned GitHub API client construction using ctx ports + UI hooks.
packages/plus/integrations/src/providers/github/tests/github.utils.test.ts Updates test harness imports (node:assert/strict + mocha).
packages/plus/integrations/src/providers/bitbucket/bitbucket.ts Migrates Bitbucket API client into package, replacing vscode/env/config/message dependencies with ctx ports/hooks.
packages/plus/integrations/src/providers/bitbucket.ts Migrates Bitbucket integration into package; replaces host-only remote resolution with ctx repositories + internal resolver.
packages/plus/integrations/src/providers/bitbucket-server.ts Migrates Bitbucket Server integration into package; switches event emitter type and ctx-backed storage/apis.
packages/plus/integrations/src/providers/azureDevOps.ts Migrates Azure DevOps integration into package; replaces vscode UI usage with ctx hooks and ctx-backed apis/storage.
packages/plus/integrations/src/providers/azure/azure.ts Migrates Azure DevOps API client into package using ctx http/hooks.
packages/plus/integrations/src/providers/apiClients.ts Adds package-owned lazy construction/memoization of per-provider API clients.
packages/plus/integrations/src/providers/tests/providersApi.interop.test.ts Adds explicit CJS↔ESM interop regression test for provider-apis factory binding.
packages/plus/integrations/src/models/issuesIntegration.ts Switches gate decorator import to @gitlens/utils and types to package constants.
packages/plus/integrations/src/models/gitHostIntegration.ts Migrates cancellation semantics to AbortSignal and switches cache access to ctx cache port.
packages/plus/integrations/src/index.ts Adds the public facade and createIntegrationManager(ctx) composition root + retired-id purge.
packages/plus/integrations/src/errors.ts Moves ProviderFetchError into the package and re-exports shared auth/request errors.
packages/plus/integrations/src/constants.ts Updates integration id enums (removes local self-managed ids) and adds stored config shapes.
packages/plus/integrations/src/authentication/models.ts Introduces vscode-free session shape and removes host config gating for supported ids.
packages/plus/integrations/src/authentication/manualTokenProvider.ts Adds consumer hook helper for static/manual token auth.
packages/plus/integrations/src/authentication/integrationAuthenticationService.ts Implements package-owned auth service with host hook override support and internal service accessors.
packages/plus/integrations/src/authentication/cloudIntegrationService.ts Refactors cloud token exchange to use ctx account + telemetry hooks (no direct container/telemetry).
packages/plus/integrations/src/tests/providers.test.ts Adds per-provider construction tests and getByRemote smoke coverage.
packages/plus/integrations/src/tests/manager.test.ts Adds manager smoke tests and retired-id purge tests.
packages/plus/integrations/src/tests/fakeRuntime.ts Adds minimal runtime implementation for package unit tests.
packages/plus/integrations/scripts/test.mjs Adds esbuild-bundled mocha test runner for provider-apis interop correctness.
packages/plus/integrations/package.json Adds new workspace package manifest and exports map.
packages/plus/git-github/src/api/github.ts Switches cancellation contract to AbortSignal across API methods.
packages/core/scripts/bundle.mjs Adds @gitlens/integrations to core bundle rewrite list.
packages/core/package.json Exposes integrations paths in @gitkraken/core-gitlens exports; adds provider-apis dependency.
package.json Removes gitlens.cloudIntegrations.enabled setting; includes integrations package in build and deps.
eslint.config.mjs Adds integrations package to lint patterns and enforces stricter boundary rules for it; ignores fixtures.
docs/telemetry-events.md Updates telemetry provider unions to reflect removed retired integration ids.
.oxlintrc.json Adds integrations package to oxlint patterns; adds fixtures ignore; enforces restricted imports in integrations package.
Files not reviewed (1)
  • pnpm-lock.yaml: Language not supported
Comments suppressed due to low confidence (2)

packages/plus/integrations/src/providers/utils.ts:61

  • getEntityIdentifierInput uses a non-null assertion on entity.provider.domain when checking for GitHub.com. For LaunchpadItem (where provider.domain is optional) this can pass undefined into isGitHubDotCom() (which expects a string) and throw at runtime.

Guard the check on provider.domain != null before calling isGitHubDotCom, and only upgrade to the enterprise provider type when a non-dotcom domain is actually present.
packages/plus/integrations/src/providers/utils.ts:65

  • getEntityIdentifierInput also uses a non-null assertion on entity.provider.domain for GitLab.com detection. Since LaunchpadItem.provider.domain is optional, this can throw at runtime when encoding entity identifiers.

Guard isGitLabDotCom() behind a domain != null check (same as the GitHub case).


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

@eamodio eamodio requested a review from sergeibbb June 5, 2026 20:16
@sergeibbb sergeibbb self-assigned this Jun 8, 2026
@sergeibbb

Copy link
Copy Markdown
Member

Hi @eamodio

I'm reviewing it. I see this note: "External consumers should import from this entry point only (index.js), not from the package's internal subpaths." and at the same time there are a lot of imports from subpaths are still there. As I understand it's left as a follow-up, isn't it?

Extracts src/plus/integrations/ into a cloud-only @gitlens/integrations workspace package consumed through a single runtime port (IntegrationServiceContext: storage/account/config/http/cache/repositories + optional hooks) and composed via createIntegrationManager(ctx). The package is vscode-free; the host wires its services through an adapter under src/plus/integrations/host/.

- Unifies the former subscription/cloudConnection/authentication/uris ports into one account port and relocates the GK-Dev connect/manage OAuth round-trips host-side (gkDevFlows).
- Moves the per-provider API clients into the package; constructs cloud auth providers in-package while keeping createAuthenticationProvider as an optional consumer extension point.
- De-leaks the host gitlens. secret-key prefix (host re-prepends; stored keys stay byte-identical).
- Keeps the self-managed Pro paywall on the GitHub/GitLab Enterprise/self-hosted host connect sites only (Bitbucket Server / Azure DevOps Server stay free).
- Groups outbound hooks by domain; makes isIntegrationsEnabled an optional, default-enabled config port.
@sergeibbb sergeibbb force-pushed the debt/extract-integrations-package branch from 02f54e9 to 5ce83c9 Compare June 16, 2026 15:35
@sergeibbb

Copy link
Copy Markdown
Member

Pervasive this.authenticationService.ctx.* transitive access in providers (Jira, Azure, Bitbucket, BitbucketServer, GitLab) and in integrationService.ts:463. All providers reach for ctx through the auth service instead of receiving it directly. This works because it's the same ctx object, but it's an architectural smell -- the auth service's ctx is readonly but exposed as a public field, creating a coupling that will resist future refactoring (e.g., giving providers their own narrower context). Not blocking, but worth noting for future cleanup.

Why?

Here's the picture. There are ~50 call sites doing this.authenticationService.ctx.<something>. They break down into a few categories:

What providers actually need from ctx:

  • ctx.storage — Jira, Bitbucket, BitbucketServer, AzureDevOps cache provider-specific data (orgs, projects, accounts)
  • ctx.cachegitHostIntegration.ts uses the cache for PRs, issues, metadata, accounts
  • ctx.hooks — GitLab calls onReauthenticationRequired, AzureDevOps calls ui.onError
  • ctx.repositories — Bitbucket scans open remotes for PR search
  • ctx.configIntegrationBase.ensureSession checks isIntegrationsEnabled
  • ctx.accountIntegrationBase.access() calls isTrialOrPaid(), auth provider checks getAccount()

What IntegrationBase itself needs (the base class in models/integration.ts) — this is the bulk: storage (workspace connected-key flags), hooks (session events, disconnect confirmation, failure notifications), config (integrations enabled check), account (access gating).

The chain is: providers receive authenticationService in their constructor (via IntegrationBase), and authenticationService.ctx is a public readonly field. So every provider reaches ctx by hopping through the auth service, even though the auth service has nothing to do with storage or caching — it's just the object that happens to carry the reference.

Why this happened: IntegrationBase's constructor takes (authenticationService, getProvidersApi, didChangeConnection). Before the extraction, these classes reached Container directly. The extraction replaced Container with ctx, but threaded it through authenticationService rather than giving it to providers directly — probably to minimize constructor signature changes.

Is it a real problem? For this PR, no. It's the same ctx object everywhere, so behavior is correct. The concern is about future refactoring: if you ever want to give providers a narrower context (e.g., Jira only needs storage + hooks, not cache + repositories), you'd have to change every provider's constructor. But that's a deliberate narrowing that would happen regardless of how ctx is passed today.

In short: it's a cosmetic coupling, not a behavioral one. The "smell" is real but mild — it's a reasonable trade-off for a clean extraction that doesn't inflate every provider constructor.

@sergeibbb

Copy link
Copy Markdown
Member

Went through the main integration flows in the debug host: connected a cloud integration via OAuth, disconnected and reconnected it, opened Launchpad to verify issues/PRs load, checked the Settings webview autolinks section — all working as expected, no regressions.

let provider = fromStringToEntityIdentifierProviderType(entity.provider.id);
let domain = null;
if (provider === EntityIdentifierProviderType.Github && !isGitHubDotCom(entity.provider.domain)) {
if (provider === EntityIdentifierProviderType.Github && !isGitHubDotCom(entity.provider.domain!)) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

One more question here, that is flagged by the AI analyzed. Should we fix the force-cast to non-null here?

image

It can be simply done by relaxing isGitHubDotCom argument type:

image

The equalsIgnoreCase accepts null values and the behavior does not change.

If by some reason we do not want isGitHubDotCom to accept nulls, then maybe do this?

image

Btw. the AI suggests the opposite: skip entering the if block when the domain is null, because the !-marking looks like the assumption that the legal state then it's not null. That highlight the ambiguity.

So I think that by removing "!" we make the decision of what the null|undefined value should mean here:

  1. we just accept it and let the API provider handle it later
    2 we think that the state is illegal, then even if we assume it never happens, I think we should catch that state in code and fail early: just to nail the expectation.

I prefer #1 just let isGitHubDotCom to accept nulls:

  • it does not change the current behaviour
  • highlight that we are tolerant to nulls here and ready to accept them.

@sergeibbb sergeibbb assigned eamodio and unassigned sergeibbb Jun 16, 2026
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.

3 participants