DEV Community

Brian Canzanella for CodeStream

Posted on • Originally published at Medium

How we extended GitLens’ Pull Request functionality in Visual Studio Code

GitLens, the incredible git-toolbelt extension for Visual Studio Code, recently added the ability for other VS Code extensions to tie into its user interface.

We're looking at the GitLens UI. Click on the pull request icon to open this GitHub pull request with CodeStream

Specifically, it added additional touchpoints around the ability to create and view pull requests. As a developer of an open source VS Code extension (CodeStream), this seemed like a great way to give out users additional choices with regard to how they create and view their pull requests.

Another view in GitLens. Click the pull request icon to create a new GitHub pull request with CodeStream

Here comes the technical parts!

At CodeStream, we use TypeScript, so you'll need a definition file for the GitLens api. I have this saved in @types/gitlens.d.ts

import { Disposable } from "vscode";

export { Disposable } from "vscode";

export interface CreatePullRequestActionContext {
    readonly type: "createPullRequest";
    readonly branch: {
        readonly name: string;
        readonly remote?: {
            readonly name: string;
            readonly provider?: string;
            readonly url?: string;
        };
        readonly repoPath: string;
    };
}

export interface OpenPullRequestActionContext {
    readonly type: "openPullRequest";
    readonly pullRequest: {
        readonly id: string;
        readonly provider: string;
        readonly repoPath: string;
        readonly url: string;
    };
}

export type ActionContext = CreatePullRequestActionContext | OpenPullRequestActionContext;
export type Action<T extends ActionContext> = T["type"];

export interface ActionRunner {
    readonly label: string;

    run(context: ActionContext): void | Promise<void>;
}

export interface GitLensApi {
    registerActionRunner<T extends ActionContext>(
        action: Action<T>,
        runner: ActionRunner
    ): Disposable;
}
Enter fullscreen mode Exit fullscreen mode

Inside your extension's activatefunction is where you can create this integration. Below, I've added a simplified version of what we finally went with. The main idea is to find either the stable version of GitLens or the insiders (aka the nightly version) and listen for "openPullRequest" and "createPullRequest" attaching using the GitLens api registerActionProvider method.

const gitLens = extensions.getExtension<Promise<GitLensApi>>("eamodio.gitlens") ||
extensions.getExtension<Promise<GitLensApi>>("eamodio.gitlens-insiders");
if (gitlens && gitlens.isActive) {
 const api: GitLensApi = await gitlens.exports;
 api.registerActionRunner("openPullRequest", {
  label: "CodeStream",
  run: function(context: OpenPullRequestActionContext) {
   console.log(context, "it worked!")
  }
 });
 api.registerActionRunner("createPullRequest", {
  label: "CodeStream",
  run: function(context: CreatePullRequestActionContext) {
   console.log(context, "it worked")
  }
 }); 
}
Enter fullscreen mode Exit fullscreen mode

Our implementation was a little more involved since we wanted to ensure that GitLens was actually active before attempting to register. There isn't a great way to truly know when another extension is active, so we used a polling mechanism. As noted in a comment in the code, there is an open issue with the VS Code team to address this.

Our complete solution can be found in the CodeStream repo on GitHub or alternatively on CodeStream itself.

Look out for this feature in the next version of CodeStream!

Discussion (0)