Thank you for your interest in contributing to Sourcegraph! The goal of this document is to provide a high-level overview of how you can contribute to the Sourcegraph JetBrains Plugin.
New issues and feature requests can be filed through our issue tracker.
Java 17: we recommend installing via SDKMAN! https://sdkman.io. Once you have SDKMAN! installed,
run sdk use java 17-zulu
. Confirm that you have Java 17 installed with java -version
.
🤞 On Windows, SDKMAN requires some Linux tools. If you don't have WSL, use the git bash environment and then:
winget install -e --id GnuWin32.Zip
⚠️ If that fails with the following error message, you should install https://winget.azureedge.net/cache/source.msixFailed in attempting to update the source: winget Failed when searching source: winget An unexpected error occurred while executing the command: 0x8a15000f : Data required by the source is missing
Once you Gnu zip installs:
mkdir ~/bin cp /usr/bin/unzip ~/bin/zip # Yes, unzip and zip are the same binary curl -s "https://beta.sdkman.io" | bash source "${HOME}/.sdkman/bin/sdkman-init.sh" sdk selfupdate force sdk use java 17-zulu
Set up the Cody agent dev environment:
- Clone
https://github.com/sourcegraph/cody
in a sibling directory. - Install its dependencies. The easiest way
is with
asdf
. If not usingasdf
, you just need to install the dependency versions listed in the.tool-versions
file in that repository. - From the root directory of the repository,
cd ./agent && pnpm install && pnpm build
🤞 On Windows ARM64:
- There's no Chromium aarch64 binary (installed by Puppeteer)
- There's no sentry-cli aarch64 binary (Sentry.)
To skip fetching these binaries, run:
$env:PUPPETEER_SKIP_CHROMIUM_DOWNLOAD="true" $env:SENTRYCLI_SKIP_DOWNLOAD=1 pnpm install
From this point, YMMV, but you should be able to build agent!
What | Command |
---|---|
Run the plugin locally | ./gradlew :customRunIde |
Run the plugin locally with fresh build of Cody | ./gradlew -PforceAgentBuild=true :customRunIde |
Run the plugin locally with fresh build of a local clone of Cody (CODY_DIR needs to be an absolute path) | CODY_DIR=<path_to_cody> ./gradlew -PforceAgentBuild=true :customRunIde |
Run the plugin locally with fresh build of Code Search assets | ./gradlew -PforceCodeSearchBuild=true :customRunIde |
Run the plugin locally with different IntelliJ version | ./gradlew -PplatformRuntimeVersion=2024.2.0.2 :customRunIde |
Run the plugin locally in split mode (useful for Gateway testing) | ./gradlew -PsplitMode=true :customRunIde |
Build Code Search assets (separate terminal) | pnpm build |
Continuously re-build Code Search assets (separate terminal) | pnpm watch |
Code Search "Find with Sourcegraph" window | pnpm standalone && open http://localhost:3000/ |
Build deployable plugin | ./gradlew buildPlugin (artifact is generated in build/distributions ) |
Reformat Java and Kotlin sources | ./gradlew spotlessApply |
Debug agent JSON-RPC communication | tail -f build/sourcegraph/cody-agent-trace.json |
- Install the following two IntelliJ plugins to format Java and Kotlin on file save
Few tips and tricks regarding versioning of the tooling:
- If you are using macOS and chose not to use
asdf
, usecorepack
, notbrew
, to installpnpm
version8.6.7
:corepack install --global pnpm@8.6.7
Currentlybrew
does not allow you to pick custompnpm
version which is causing various issues. - Use
node
version18
(newer versions causes hard to diagnose errors withERR_INVALID_THIS
). - If you changed
pnpm
ornode
version after running gradle you need to kill gradle daemon with./gradlew --stop
. Otherwise you won't see effects of your changes. - IF you get error 134 while building different things with jetbrains its because java process doesn't have enough memory to build so you might need to get into your activity monitor to close other processes.
You should build everything in PowerShell. Git Bash, Ubuntu and MinGW all offer unique challenges. If you get it to build and run, add instructions here.
- Install JDK 17 from https://www.oracle.com/java/technologies/javase/jdk17-archive-downloads.html
- Oracle will make you create an account in order to download it. 🙄
- Install the pnpm version in
./tool-versions
- Set
PNPM_HOME
env var for whole system (not just for your account) to the path wherepnpm.cmd
is.
- Set
- Install the node version in
./tool-versions
🤞 On Windows (ARM64 specific?), there's some problem with codesearch's svelte packages. Skip the code search build by setting this environment variable:
$env:SKIP_CODE_SEARCH_BUILD="true"
The fastest way to develop the Web UI is to use Storybook. However for some tasks loading the webview in JetBrains is unavoidable. The process to do this is:
- Use the "Run the plugin locally with fresh build of a local clone of Cody" setup (see above.) Specifically, you must have
CODY_DIR
set. - After changing the Web UI, in
$CODY_DIR
runpnpm -C agent build:webviews
- Start a new chat to load the new webview bundle.
For changes in the TypeScript extension outside of the webview bundle, you must use one of the agent workflows described above.
- Open "Sourcegraph & Cody" settings
- Change to "Nightly"/"Experimental" update channel
- Open "Plugins"
- Update Sourcegraph plugin
- Restart IDE
Remove the URL from the plugin repository list to go back to the stable channel.
INTERNAL ONLY This section is only relevant for Sourcegraph engineers. Take the steps below before running JetBrains plugin with agent.
- Point IntelliJ provider/endpoint at the desired LLM endpoint by editing
$HOME/.sourcegraph-jetbrains.properties
:cody.autocomplete.advanced.provider: unstable-codegen cody.autocomplete.advanced.serverEndpoint: https://backend.example.com/complete_batch
- Run
gcloud
SOCKS proxy to access the LLM backend:- Make sure to authorize with GCP:
gcloud auth login
- Request Sourcegraph GCP access through Entitle.
- Bring up the proxy:
gcloud --verbosity "debug" compute ssh --zone "us-central1-a" "codegen-access-test" --project "sourcegraph-dogfood" --ssh-flag="-D" --ssh-flag="9999" --ssh-flag="-N"
- Patch in sg/socks-proxy. Note: After #56254 is resolved this step is not needed anymore.
- Make sure to authorize with GCP:
To upgrade Cody to the newer version you need to update the cody.commit
hash in gradle.properties
.
After doing that:
-
Run on the
sourcegraph/cody
repo:git diff --name-status OLD_HASH..NEW_HASH -- agent
It will print you a list of files changed between updates.
Changes in tests or bindings might require adjustments in the jetbrains codebase, so please inspect those carefully. -
Check if the main features are working before sending it for the full QA.
Please pay special attention to areas with potential changes indicated by point 1):- autocomplete
- chat
- chat history
- context fixes in chat responses
- @-files in chat prompt
- enhanced remote context
- commands from context menu and commands tab
- login / account switch
You don't need to cover all corner cases and do a full QA, but make sure basic features still work.
Cody version updates tends to break them completely or not at all, so it should allow us to catch most issues early.
We used to publish both stable and nightly channel versions at once. In that approach QA testing and JB approval happened in parallel. However, it consumed a lot of CI time and JB time for the releases that did not pass our QA (and did not go public eventually). Hence, we decided to use a sequential process. We trigger the stable channel release only after the nightly channel release passes QA.
graph TD;
Title --> nightly["Nightly Release / Experimental Release"];
Title["JetBrains Plugin Release"] --> stable["Stable Release"];
stable --> trigger_stable["Manually trigger 'Stable Release' workflow in GitHub Actions"];
release_stable --> marketplace_approval["Wait for JetBrains approval"];
marketplace_approval --> |Automated approval, up to 48hr| unhide["unhide"];
unhide --> available_to_end_users_stable["Available for download"];
marketplace_approval --> |Manual quick-approve| slack_approval["Request JetBrains Marketplace team to manually approve it via Slack"];
slack_approval --> unhide["Unhide the approved release (requires admin access)"];
nightly --> push_tag["Run 'push-git-tag-for-next-release.sh'"];
trigger_stable --> release_stable["Wait for 'Stable Release' workflow to complete"];
push_tag --> release_nightly["Wait for 'Nightly Release' / 'Experimental Release' workflow to complete"];
release_nightly --> available_to_end_users_nightly["Available for download"];
We aim to cut a new Stable release every other week on Mondays. The release cadence is irregular for Nightly versions.
Use the following command for a patch release:
./scripts/push-git-tag-for-next-release.sh --patch
Or this one for a minor release:
./scripts/push-git-tag-for-next-release.sh --minor
Or this one for a major release (note it should be user only on special occasions):
./scripts/push-git-tag-for-next-release.sh --major
This script runs verify-release.sh
, which takes a long time to run with a clean cache, which is why we don't run it in
CI. When you have a local cache of IDEA installations then this script can run decently fast (~1-2min).
After successfully pushing the new tag (for example: v6.0.15
), we are now able to publish.
Wait for the Release to Marketplace
GitHub workflow to complete.
Go to Stable Release workflow,
click Run workflow
and select the tag that has been pushed before (and tested by QA team), run it.
It can take up to 48hr for stable releases to get approved by the JetBrains Marketplace team.
It's possible to expedite this process by posting a message in the #marketplace
channel in
the JetBrains Slack workspace.
For every stable release, create a GitHub release summarizing the changes.
Visit releases page and click Draft a new release
, choose your
tag and use Generate release notes
. Release notes should appear automatically. Be aware that the automatic release are
based on the history of commits, so sometimes the titles are not properly formatted, capitalized or grammatically
correct. This may sometimes require manual tweaks.
Try to maintain a similar style to that of the previous releases, similar to our first release.
It's also optional create GitHub releases for nightly builds where it makes sense.
It is mandatory to post about both stable and nightly releases on our internal
#team-cody-clients
Slack channel. You can refer to past posts in the channel's
history for examples.
Parts of this extension rely on the JCEF web view features built into the JetBrains platform. To enable debugging tools for this view, please follow these steps:
- Enable JetBrains internal mode
- Open Find Actions: (Ctrl+Shift+A / ⌘⇧A)
- Search for "Registry..." and open it
- Find option
ide.browser.jcef.debug.port
- Change the default value to an open port (we use
9222
) - Restart IDE
- Open the “Find with Sourcegraph” window (Alt+A / ⌥A)
- Switch to a browser window, go to
localhost:9222
, and select the Sourcegraph window. Sometimes it needs some back and forth to focus the external browser with the JCEF component also focused—you may need to move the popup out of the way and click the external browser rather than using Alt+Tab / ⌘Tab.
If you have IntelliJ Ultimate Edition, you can debug the Agent in JetBrains. This is useful because you can set breakpoints on both sides of the protocol: On the agent (TypeScript) side, and also on the plugin (Java/Kotlin) side.
There are two supported configurations for debugging this way:
- The Cody extension spawns the agent subprocess normally, but adds
--inspect
- JetBrains can connect and debug the agent via port 9229
- Or, JetBrains spawns the agent in debug mode
- The agent will listen on port 3113
- The Cody extension connects via socket to the "remote" agent
Option 1 is the simplest, and probably makes the most sense for you to use if you are uncertain which method to use for debugging. Option 2 is especially useful when you need to set a breakpoint very early in the Agent startup.
Run configurations are basically IDEA's launcher scripts. You will need to create one run configuration in each project window, using Run → Edit Configurations.
For both debugging setups (Cody-spawns and JB-spawned), you will need:
github.com/sourcegraph/cody
cloned in the same directory where you clonedsourcegraph/jetbrains
, so that they are sibling dirs.- likely not strictly necessary, but it seems to be the convention
sourcegraph/cody
(TypeScript) opened in one IDEA project window- this is a Node project (requires Ultimate Edition)
sourcegraph/jetbrains
opened in a second IDEA project window- this is a Gradle project
You'll always have at least 2 IntelliJ project windows open: One for debugging the Java side, and one for the TS side.
- also a 3rd intellij window pops up when you run your plugin, though this is a new instance completely
If you check Store as project file
and use the default, it will
remember your configuration between sessions.
For each configuration below, you can use whatever name you like, but the other configuration all needs to be there.
With both debug options, you can start the run configurations in either order, using either Run or Debug to launch them.
In each project window, decide whether you need breakpoints on this side of the protocol to trigger in this run. If so, use Debug; otherwise, use Run.
Typically it makes the most sense to run both of them with Debug. You can have breakpoints triggered on both sides of the protocol in different windows, which can be handy.
This option requires you to set up two run configurations, one in each project window.
Create this configuration in the sourcegraph/jetbrains
project window.
Choose Edit Configurations and +
to add a new one:
- Type: Gradle
- Name: whatever, e.g.
Cody-spawned debug agent
- Run on: local machine (the default)
- Run:
customRunIde
(the default) - Modify options → Add Before Launch Task
- choose Run External Tool
- choose the pnpm builder tool
- Gradle project:
jetbrains
(the default) - env vars:
CODY_DIR
=absolute path to your cody repo clone- mine was set to
/Users/stevey/src/sg/cody
- mine was set to
CODY_AGENT_DEBUG_INSPECT=true
- this tells the plugin to spawn agent with
--inspect
- this tells the plugin to spawn agent with
Create this configuration in the sourcegraph/cody
project window.
Choose Edit Configurations and +
to add a new one:
- Type: Attach to Node.js/Chrome
- Name: whatever, e.g. Debug Cody-spawned Agent
- Host: localhost
- Port: 9229
- Attach to:
Chrome or Node.js > 6.3 started with --inspect
- Reconnect automatically: yes
This option has two run configurations, different from two above. Note that if you want both debugging options available, you can set up all four run configurations.
Create this configuration in the sourcegraph/jetbrains
project window:
- Type: Gradle
- Name: whatever, e.g.,
Connect to IDEA-spawned Agent
- Run on: local machine (the default)
- Run:
customRunIde
(the default) - env vars:
CODY_AGENT_DEBUG_REMOTE=true
CODY_AGENT_DEBUG_PORT=3113
Create this configuration in the sourcegraph/cody
project window:
- Type: Node
- Name: Agent on Debug Port
- Node interpreter: node
- Mine defaulted to
~/.asdf/shims/node
- make sure your node is >= the version in https://github.com/sourcegraph/cody/blob/main/package.json
- Mine defaulted to
- Node parameters:
--enable-source-maps
- Working directory:
~/src/sg/cody
(or wherever you cloned sourcegraph/cody) - JavaScript file:
agent/dist/index.js
- note: this is a relative path, unlike the run configs for Option 2
- Application Parameters: leave empty
- Environment variables:
CODY_AGENT_DEBUG_REMOTE=true
CODY_AGENT_DEBUG_PORT=3113
- before actions: use your pnpm external tool if you want to auto-rebuild the agent
This step is optional but recommended.
With any Agent-side run configurations, you can opt to build the agent
before running the task as a "Before Task", which speeds up development
iteration. You can make code changes to the TypeScript and just hit
Debug or Run, and it will pnpm build
your repo before spawning the agent.
Note that for Option 1 (Cody spawns Agent), the Before Task is added to the run configuration on the java side. For IntelliJ spawning the Agent, the Before Task is added to the run configuration on the TypeScript side.
To set this up, in the Before launch section of any Run/Debug configuration, do the following:
- click on + to see the Add New Task popup list
- choose Run External Tool
- this will bring up your personal/custom External Tools list
- choose + in the External Tools dialog to add a new one
- this should pop up a Create Tool form dialog
- Configuration:
- Name: whatever you like
- example: pnpm build agent
- Description: whatever you like
- example: run pnpm build in sourcegraph/cody/agent dir
- Tool Settings:
- Program: pnpm
- Arguments: build
- Working directory:
/Users/you/path/to/sourcegraph/cody/agent
- e.g. mine was
/Users/stevey/src/sg/cody/agent
- e.g. mine was
- for other settings, the defaults are fine, or you can customize them
- Name: whatever you like
- Finally, go back to your Before Actions in your run configuration
- click on + to see the Add New Task popup list again
- your new pnpm build task should be in it
- click on your new task to add it to the Before Actions
- click on + to see the Add New Task popup list again
You only need to do most of these steps once, when you create the External Tool. Then you can use it in any run config that spawns the agent, to rebuild it first.
Sometimes, the TypeScript backend behaves differently when called from IntelliJ via Agent than when the same code is called from the VS Code extension, and you may need to debug the same code paths through the Agent twice. First, when called from the JetBrains extension side, and again when called from the VS Code extension side.
To accomplish the latter, you can use VS Code to debug itself. It works
very similarly to how it works in JetBrains. There are predefined run
configurations for debugging VS Code Cody in the file
.vscode/launch.json
in sourcegraph/cody
, such as Launch VS Code Extension (Desktop)
.
You do not launch VS Code run configurations from the command palette. Instead, use ctrl-shift-D to open the Run and Debug view, and you can see the configuration dropdown at the top.
Chrome Tracing can be used to get CPU and memory profiles of Agent and the TypeScript extension code.
- Set
CODY_AGENT_DEBUG_INSPECT=true
in your run configuration/environment. - Launch the target.
- Open DevTools however you're accustomed to do that, for example,
chrome://inspect
and click "inspect" next to the debuggee. - Use the Performance tab to record CPU, memory profiles, etc.
- Force-stopping the target often corrupts IntelliJ's project indexes,
requiring an extra restart of the debugged target to fix them.
- Workaround is to exit the target gracefully by quitting each time, using the menus or hotkeys, rather than force-stopping it.
Run the integration tests at the command line with:
./gradlew integrationTest
You need to import valid access tokens using export-cody-http-recording-tokens.sh script also used for a Cody agent tests.
You can run and debug the integration tests, including the Agent node process, with the instructions above by making new run configurations for the test.