JetBrains Space Help

Configure a Dev Environment for a Project

To provide the best possible experience, a dev environment must be pre-configured for your project. A configured environment includes all necessary tools and runtimes, IDE indexes, and other data required by the project, e.g., environment variables, project dependencies, and so on. As a result, a user can start working on their project right after a dev environment is created.

Configuration steps

Dev environment configuration includes the following steps (you can skip any of these steps depending on your needs):

  • Specify a configuration name

  • Specify a dev environment instance type

    Dev environments come in three different types that differ by available compute resources.

  • Specify a default IDE

    You can specify a default IDE and a particular IDE version for the project.

  • Specify a container image

    The image must include the tooling and runtimes required by the project. You can use an image from Docker Hub (or other registries that doesn't require authentication), from a Space Packages registry, or even define a custom image using a Dockerfile file in the project repository.

    If you skip this step, the created dev environments will use the default image.

  • Create a warm-up snapshot

    A warm-up snapshot contains pre-built project data. By default, the snapshot contains only IDE indexes, but it can also contain additional project data like dependencies, build caches, and so on. To create a warm-up snapshot, you should configure and run an Automation job. Running the job can be automated: Space can run it by schedule, on each commit, or by other triggers. Each time a job run is triggered, Space will create a new warm-up snapshot.

    If you skip this step, Space will create dev environments without warm-up data.

  • Set environment variables

    Define environment variables that are required for development in a dev environment.

  • Specify user secrets and parameters required for development

    A dev environment might require sensitive user data, e.g. credentials to an external service. User secrets and parameters are available in a dev environment as environment variables.

  • Configure JVM options for IntelliJ-based IDEs

    You can change the configuration of Java Virtual Machine (JVM) your IntelliJ-based IDE runs on.

  • Specify the project root directory

Default dev environment

Configuring a dev environment is optional. If you skip it, Space will use a default dev environment: the environment based on the default Docker image with no additional project data.

The default Docker image is based on Ubuntu OS and includes Git, curl, Docker, Docker Compose, Kubernetes, Google Cloud support, Open JDK, Python, PHP, .NET SDK, Ruby, Go, Node.js, npm, yarn, and other tools.

Devfile configuration file

To configure a dev environment for a project, you should use a devfile. Devfile is an open specification that uses YAML formatting for configuring and running build environments. Currently, Space supports only a feature subset of the 2.2.0 specification (the supported features are fully covered by the documentation topic you're currently reading).

A project may have a single devfile.yaml file or a number of *.devfile.yaml files located in the .space directory in the repository root. When users create a dev environment, they can choose from all devfiles available in the project. Dev environment settings are taken from the selected devfile.

Choose a devfile

Here's an example of a devfile.yaml file:

schemaVersion: 2.2.0 metadata: name: 'My custom dev env configuration' attributes: space: # regular, large, xlarge instanceType: large # a default IDE for the project editor: # (Required) IDE type: Idea, WebStorm, PyCharm, # RubyMine, CLion, Fleet, GoLand, PhpStorm type: Idea version: '2022.1' # Space uses JetBrains Toolbox App to install IDEs to a dev environment. # updateChannel defines IDE version release stage: Release, EAP updateChannel: EAP # JVM configuration (appends to the default .vmoptions file) vmoptions: - '-Xms2048m' - '-Xmx4096m' # Parameters and secretes required by a dev environment # e.g., credentials to an external service requiredParameters: # (Required) the name of the environment variable # that will be available in the dev environment - name: USERNAME description: 'Space username' requiredSecrets: - name: PASSWORD description: 'Space permanent token' components: - name: dev-container # Dev environment container config container: # use image from a Space Packages registry image: mycompany.registry.jetbrains.space/p/crl/container/my-dev-image:27 # environment variables env: - name: API_URL value: 'https://my-site/http_api' - name: PATH_IMG value: './img/'

Specify a configuration name

To help users distinguish a partcular dev environment configuration in a project with several devfiles, specify a name for each configuration. If you don't specify a name, the configuration will be named after the IDE it uses.

  1. Open the devfile in the project repository. If it doesn't exist, create a new one, for example, .space/devfile.yaml.

  2. In the devfile, specify a configuration name:

    schemaVersion: 2.2.0 metadata: name: 'My custom config' attributes: space: editor: type: Idea
  3. Commit and push the changes.

Users will see this name when selecting a devfile for a newly created dev environment.

Config name

Specify a default dev environment instance type

Dev environments can run on three different virtual machine instances: regular (4 vCPUs, 8 GB), large (8 vCPUs, 16 GB), and extra large (16 vCPUs, 32 GB). Learn more about dev environments billing.

Using the project's devfile, you can specify a default instance type. A user can choose another instance type when creating a dev environment.

  1. Open the devfile in the project repository. If it doesn't exist, create a new one, for example, .space/devfile.yaml.

  2. In the devfile, specify an instance type:

    schemaVersion: 2.2.0 attributes: space: # regular, large, xlarge instanceType: large editor: type: Idea
  3. Commit and push the changes.

Specify a default IDE

Now, you can use the following IDEs from JetBrains in a dev environment: Fleet, IntelliJ Idea, WebStorm, PyCharm, RubyMine, CLion, GoLand, PhpStorm, and Rider *. To get information about available IDEs, Space uses the JetBrains Toolbox App update service. You can view the available IDEs, IDE versions, and version release states (e.g., Release, EAP, and so on) on the dev environments administration page.

Using the project's devfile, you can specify a default IDE, IDE version, and version release state. A user can change any of these settings when creating a dev environment. When warming up a dev environment, a warm-up job will build IDE indexes for the IDE and IDE version specified in the devfile.

  1. Open the devfile in the project repository. If it doesn't exist, create a new one, for example, .space/devfile.yaml.

  2. In the devfile, specify IDE settings:

    schemaVersion: 2.2.0 attributes: space: editor: # (Required) IDE type: Idea, WebStorm, PyCharm, # RubyMine, CLion, Fleet, GoLand, PhpStorm, Rider type: WebStorm version: '2022.1' # release state, e.g. Release or EAP updateChannel: Release
  3. Commit and push the changes.

Default IDE version

If not specified in a devfile, the default IDE version is always the latest available release version. This is the organization-wide default. To change it, a user must have the Edit dev environments settings global permission (for example, an administrator with the System Admin role).

To specify the default IDE version for organization dev environments

  1. Open Administration, then Dev Environments.

  2. Under Default IDE versions, find the required IDE and choose a new default version.

    Default IDE

Use JetBrains Rider in a dev environment

If you want to use a dev environment with JetBrains Rider, you must additionaly specify a path to the solution file. To specify the path, use the projectRoot parameter. For example:

schemaVersion: 2.2.0 attributes: space: editor: type: Rider version: '2022.1' # projectRoot is specified # relative to repository root projectRoot: projects/my-project/MySolution.sln

Specify an image for the dev environment

A dev environment runs in a Docker container. If you don't specify an image in a devfile.yaml, Space will use the default image. As a custom image, you can use an image from Docker Hub (or other registries that doesn't require authentication), Space Packages, or create an image from Dockerfile each time a user creates a new dev environment. To specify the image, use the project's devfile.

Image requirements
  • OS: any glibc-based Linux distribution (for example, CentOS 7+, Debian 9+, Ubuntu 20.04+).

  • Tools: Git, OpenSSH (if you want to use a remote Git repository), lsof (if you need port forwarding in an IDE).

  • The container must run as root (there must be no non-root users in Dockerfile).

Container image vs warm-up job

In some cases, you might face a dilemma where to put a certain preparation step: to a container image or to a warm-up job. For example, your project requires an SDK. To get the SDK, you run the script: curl - o sdk.zip $SDK_URL && unzip sdk.zip. Where do you put this line: to the Dockerfile or to the warm-up job in .space.kts?

Our recommendation is to use the Dockerfile only to configure the environment. All binary dependencies should go to a warm-up job. So, in the example above, the best solution would be to get the SDK in a warm-up job.

Important: the Space Packages registry must belong to the same project where you configure a dev environment.

  1. Open the devfile in the project repository. If it doesn't exist, create a new one, for example, .space/devfile.yaml.

  2. In the devfile, specify the full image URL:

    schemaVersion: 2.2.0 attributes: space: instanceType: regular editor: type: Idea components: - name: ubuntu-container container: image: mycompany.registry.jetbrains.space/p/crl/container/dev-image:latest
  3. Commit and push the changes.

A dev environment can use a custom Dockerfile for its container image. The Dockerfile can be located anywhere in the project repository. Note that in this case, Space will build the image each time a user creates a new dev environment. To reduce startup time of the dev environment, we recommend that you build the image once and publish it to the project's Space Packages registry.

  1. Open the project source code and create a Dockerfile, for example, in the docker directory.

  2. Edit the Dockerfile to configure the image.

    For example, an image for a Java project:

    FROM ubuntu:20.04 ENV DEBIAN_FRONTEND=noninteractive ENV LC_ALL=C.UTF-8 RUN apt-get update RUN apt-get install -y \ git \ openjdk-11-jdk \ && rm -rf /var/lib/apt/lists/* ENV JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64
  3. Open the project source code and open the project's devfile. If it doesn't exist, create a new one, for example, .space/devfile.yaml.

  4. In the devfile, specify the path to a Dockerfile (uri) and, optionally, to the Docker context (buildContext). You must specify both paths relative to the projectRoot. For example:

    schemaVersion: 2.2.0 attributes: space: instanceType: large editor: type: Idea components: - name: image-build image: # (Required) imageName: my-image:latest dockerfile: # (Optional) path to Docker context relative to projectRoot # by default, projectRoot is repository root buildContext: docker # (Required) path to Dockerfile relative to projectRoot uri: docker/Dockerfile args: - 'ARG1=A' - 'ARG2=B'

  5. Commit and push the changes.

You can use images not only from Docker Hub but from any public registry that doesn't require authentication. In case of an image from Docker Hub, you can specify only the image name. For other registries, you must specify the full image URL.

  1. Open the project source code and open the project's devfile. If it doesn't exist, create a new one, for example, .space/devfile.yaml.

  2. In the devfile, specify the image name:

    schemaVersion: 2.2.0 attributes: space: instanceType: regular editor: type: Idea components: - name: openjdk-container container: # image from Docker Hub image: openjdk:latest
  3. Commit and push the changes.

Warm up the dev environment

Dev environments can significantly increase the speed of development by removing the IDE warm-up phase: a period of time when the IDE builds indexes, and does other background activities like resolving project dependencies. You can put all these routines into a Space Automation job and run this job on schedule, on every commit, or using other triggers. The result of the warm-up job is a disk snapshot (or warm-up snapshot) that is then mounted to a dev environment.

When running the warm-up job, Automation:

  1. (Optional) Runs your custom .sh script that contains other warm-up activities.

  2. Builds project indexes for a specified IDE.

Warm-up job syntax

To create a warm-up job, use the warmup block in the .space.kts file. For example:

job("Build Fleet indexes") { // ide is an IDE you want Space to build indexes for: // for JetBrains Fleet - Ide.Fleet // for IntelliJ-based IDEs via Gateway - // Ide.Idea, Ide.WebStorm, Ide.RubyMine, // Ide.CLion, Ide.GoLand, Ide.PhpStorm, // Ide.PyCharm, Ide.Rider warmup(ide = Ide.Fleet) { // optional custom script scriptLocation = "./dev-env-warmup.sh" } }

The resulting warm-up snapshot will contain project indexes for JetBrains Fleet and data created by the ./dev-env-warmup.sh script.

Warm-up job and dev environment image

To make a warm-up snapshot compatible with the target dev environment, you need to run the warm-up job in the same run environment: using the same container image, environment variables, and so on. The job can take all these settings from the project's devfile.

If you want to run the job in a container based on the image from the devfile, specify the path to the devfile in the devfile property. If the image is not specified in the devfile, the container will use the default image.

// this job will run in a container based on the image // specified in the devfile.yaml (if specified) job("Build Idea indexes") { warmup(ide = Ide.Idea) { devfile = ".space/devfile.yaml" } } // this job will run in a container based on // the default image job("Build Idea indexes") { warmup(ide = Ide.Idea) }
Warm-up job and IDE version

Project indexes are specific for each IDE and most often for each IDE version. A warm-up job looks for the IDE version it must build indexes for in the following order:

  1. The job's ideVersion property

    The property lets you explicitly specify the IDE version in a warm-up job (overrides other values):

    job("Build IDEA indexes") { warmup(ide = Ide.Idea) { // specify IDE version explicitly ideVersion = IdeVersion.Specific("2021.3.1", "Release") // you can also specify release state instead of a version // ideVersion = IdeVersion.LatestOfQuality("Release"). // IDE version from devfile is ignored devfile = ".space/devfile.yaml" } }
  2. The projects' devfile

    Instead of explicitly specifying the IDE version in a job, you can do this in the project's devfile. Note that the IDE specified in warmup(ide = Ide.Idea) must correspond to the IDE in the devfile:

    job("Build IDEA indexes") { warmup(ide = Ide.Idea) { // take IDE version from devfile // in devfile, editor type must be 'Idea' devfile = ".space/devfile.yaml" } }
  3. The default IDE version

    If the IDE version is not specified in a job and in the devfile, the job will create indexes for the default IDE version.

How Space stores warm-up snapshots

Space stores only the latest warm-up snapshot for each combination of an IDE and a Git branch. An IDE version is not taken into account. For example, a project has two branches: main and feature-branch. Suppose some developers use JetBrains Fleet and some use IntelliJ IDEA. There can be four snapshots maximum: main + Fleet, main + IDEA, feature-branch + Fleet, and feature-branch + IDEA.

Note that storing warm-up snapshots is included in disk storage billing. Learn more about billing

To create a warm-up snapshot

  1. Open the project repository.

  2. (Optional) Create a .sh file, for example, dev-env-warmup.sh in the repository root.

    Open dev-env-warmup.sh and add the required warm-up activities. For example, for a Java project which uses Gradle, you might want to assemble and download dependencies with:

    ./gradlew assemble

  3. Open the .space.kts Automation script file. If the file doesn't exist, create it in the repository root.

  4. Add an Automation job that runs the warm-up. For example:

    job("Warmup data for IDEA") { // optional startOn { // run on schedule every day at 5AM schedule { cron("0 5 * * *") } // run on every commit... gitPush { // ...but only to the main branch branchFilter { +"refs/heads/main" } } } warmup(ide = Ide.Idea) { // path to the warm-up script scriptLocation = "./dev-env-warmup.sh" // use image specified in the devfile devfile = ".space/devfile.yaml" } // optional git { // fetch the entire commit history depth = UNLIMITED_DEPTH // fetch all branches refSpec = "refs/*:refs/*" } }

  5. Commit and push the changes.

  6. Make sure the job has been successfully completed. You can check the job state on the project's Jobs page. After this, it will be possible to select the created warm-up snapshot in the New Dev Environment window.

  7. Make sure the job is run regularly: The fresher the index data is, the faster a dev environment will be ready for work.

To view warm-up snapshots available in a project

  1. Open the project.

  2. In the sidebar, select Dev Environments.

  3. Switch to the Warm-up Snapshots tab.

To delete a warm-up snapshot

  1. Open the project.

  2. In the sidebar, select Dev Environments.

  3. Switch to the Warm-up Snapshots tab.

  4. Find the snapshot and click the Delete dev environment Delete button.

Set environment variables

To define environment variables in a dev environment container, use the project's devfile.

  1. Open the devfile in the project repository. If it doesn't exist, create a new one, for example, .space/devfile.yaml.

  2. Specify environment variables and their values in the env parameter:

    schemaVersion: 2.2.0 attributes: space: instanceType: large editor: type: Idea components: - name: dev-container container: env: - name: VAR_A value: 'valueA' - name: VAR_B value: 'valueB'
  3. Commit and push the changes.

    After this, when creating a new environment, you can view the added variables under Environment variables.

    Env vars in dev environments

    Note that the specified enviroment variables will be set only in newly created dev environments. There will be no such variables in the existing dev environments.

Provide personal user data to a dev environment

You can require users to provide values for particular dev environment parameters. Typically, these are personal paramteres and secrets needed for developing the project. For example, user credentials for downloading project binary dependencies. The required parameters and secrets are available on a target dev environment as environment variables.

To define the required environment variables (i.e., parameters and secrets), use the project's devfile. When creating a dev environment, a user will be asked to provide variable values. The values must be taken from the personal user storage of secrets and parameters.

To define the required environment variables

  1. Open the devfile in the project repository. If it doesn't exist, create a new one, for example, .space/devfile.yaml.

  2. Specify the required environment variables. For example, we require an environment variable DB_USERNAME (the value is expected to be a plain parameter) and a variable DB_TOKEN (the value is expected to be a secret):

    schemaVersion: 2.2.0 attributes: space: instanceType: large editor: type: Idea requiredParameters: - name: DB_USERNAME description: 'Database username' requiredSecrets: - name: DB_TOKEN description: 'Database access token'
  3. Commit and push the changes.

    After this, when creating a dev environment, a project developer will be required to provide values for the defined secrets and parameters (this has to be done only for the first created environment; all subsequent environments will have these settings pre-defined).

To assign personal secrets and parameters to the required environment variables

  1. On the Personal navigation sidebar, click Dev Environments, then click Environment Variables.

  2. Create a parameter or a secret by clicking New parameter or New secret.

  3. Specify

    • Key: a parameter/secret name.

    • Value: a parameter/secret value.

  4. When creating a new dev environment, in the New Dev Environment window, under Environment variables, assign environment variables to the corresponding parameters and secrets.

    Env vars in dev environments. Secrets

    Note that the specified enviroment variables are set only in newly created dev environments. There will be no such variables in the existing dev environments.

Configure JVM options for IntelliJ-based IDEs

In some cases, you might need to change the configuration of Java Virtual Machine (JVM) your IntelliJ-based IDE runs on. For example, increase the maximum memory heap size allocated for the IDE. To configure JVM, use the project's devfile.

  1. Open the devfile in the project repository. If it doesn't exist, create a new one, for example, .space/devfile.yaml.

  2. Specify the required JVM options in the vmoptions list. For example, to set the initial and max memory heap size allocated for the IDE:

    schemaVersion: 2.2.0 attributes: space: editor: type: WebStorm # the config appends to the default .vmoptions file vmoptions: - '-Xms2048m' - '-Xmx4096m'
  3. Commit and push the changes.

    The new JVM options will be applied to all newly created dev environments within the project.

Specify the project root directory

After you start a dev environment, an IDE opens a project root directory. By default, the project root is the repository root. You can specify an alternative project root location (relative to the repository root) using the projectRoot parameter. This might be helpful for mono-repositories which include multiple projects.

Also note that all path parameters in a devfile (e.g., components[*].image.dockerfile.uri and components[*].image.dockerfile.buildContext) are specified relative to the project root.

# resulting project root: <path-to-repo>/server schemaVersion: 2.2.0 attributes: space: editor: type: Idea projectRoot: server
# projectRoot is not specified # resulting project root: <path-to-repo> schemaVersion: 2.2.0 attributes: space: editor: type: Idea
Last modified: 25 November 2022