- Introduction
- Getting Started
- Gitpod Tutorial
- Use Cases
- Languages
- Configure
- Workspaces
- User settings
- Repositories
- Organizations
- Authentication
- Billing
- References
- .gitpod.yml
- IDEs & editors
- Integrations
- Gitpod CLI
- Gitpod API
- Gitpod URL
- Compatibility
- Enterprise
- Overview
- Setup and Preparation
- Deploying
- Configure your Gitpod Instance
- Administration
- Upgrading
- Background
- Reference
- Archive
- Help
- Contribute
- Troubleshooting
Tasks
To get the most out of ephemeral developer environments, it is important to let Gitpod know how to build your project. We can achieve this by defining tasks
in the .gitpod.yml
configuration file.
Note: In your local developer environment, you likely set up your project only once. If you work in a team, you probably have written instructions on how to get started. With Gitpod, you automate these manual steps so that a new environment can be set up repeatedly by Gitpod.
Tasks are shell scripts that run on top of the Docker image you configure (learn more about custom Docker images).
Task types and execution order
Tasks in Gitpod are categorized into three types:
before
: Preparatory steps that should run before the main setup, such as setting up tools or permissions.init
: Tasks for setting up the project, like downloading dependencies and compiling code.command
: Commands that start your main application or services.
The execution of these tasks may vary depending on whether you use prebuilds. Prebuilds have been updated to trigger less frequently, now by default occurring on every 20th commit to reduce resource consumption and improve efficiency (cmp. the changelog and the prebuild docs).
Caveats
- Any file changes made outside of
/workspace
file hierarchy frominit
tasks will be lost on workspace start when prebuilds are enabled. Learn more- User specific environment variables are not loaded automatically for
init
andbefore
tasks but can be loaded if you want. Learn more
Prebuilds
Prebuilds allow for pre caching of dependencies, build artifacts and other setup steps. Prebuilds run in the background and execute the before
and init
tasks. Workspaces are then created based on the result of the most recent prebuild, which allows for faster workspace startup times.
The init
task is where you want to do things like:
- Download & install dependencies
- Compile your source code
- Run database migrations
- Run code generation
- Any other long-running, terminating processes necessary to prepare your project
Note:
init
tasks can be re-run on the same file-system state under certain conditions (cmp. Prebuild: Incremental), so they should be idempotent: no matter how often they are triggered, they should return the same result.
Note: Changing either the
before
orinit
tasks will always trigger a new prebuild. See Use of prebuilds for more information.
Enable prebuilds, and let Gitpod run the time-consuming
init
tasks continuously behind the scene so you and anyone who opens your project on Gitpod doesn’t have to wait.
Start a workspace (without prebuild)
The workspace is started, but Gitpod can’t find a suitable prebuild (yet): all tasks before
, init
and command
are executed in that order.
Start a workspace (with prebuild)
Which tasks are executed depends on the exact commit used to start a) your workspace and b) the prebuild. There are two scenarios: “perfect match” and “incremental”.
Prebuild: Perfect match
The workspace is started, and Gitpod was able to find a prebuild that ran on exactly the same commit.
In this case, your before
and command
tasks are executed: init
already ran as part of the prebuild.
Prebuild: Incremental
The workspace is started, and Gitpod found a prebuild that ran on a slightly older commit than the workspace (cmp. the Commit Interval setting).
In this case, we have to refresh the prebuild: all tasks before
, init
(!) and command
are executed.
Note: Although
init
is executed like on a regular workspace startup, the execution should still be way faster: Caches are pre-fetched, external dependencies downloaded, and almost all build systems support incremental builds.
Restart a Workspace
When you restart a workspace, Gitpod already executed the init
task (see above) either as part of a prebuild or when you started the workspace for the first time.
As part of a workspace restart, Gitpod executes the before
and command
tasks:
Start a Snapshot
When you start a snapshot, Gitpod already executed the init
task (see above) either as part of a prebuild or when you or a team member started the snapshot’s initial workspace for the first time.
As part of starting a snapshot, Gitpod executes the before
and command
tasks:
Configure the terminal
You can configure where terminals open using the openMode
properties below.
Please note that this information is used if no previous terminals in the layout exist.
Snapshots will first try to reuse existing terminals in the layout, before opening new ones.
tasks:
- name: Static Server
command: python3 -m http.server 8080
- name: DB Server
command: sh ./scripts/start-db.sh
openMode: split-right
openMode
You can configure how the terminal should be opened relative to the previous task.
openMode | Description |
---|---|
openMode: tab-after |
Opens in the same tab group right after the previous tab |
openMode: tab-before |
Opens in the same tab group left before the previous tab |
openMode: split-right |
Splits and adds the terminal to the right |
openMode: split-left |
Splits and adds the terminal to the left |
openMode: split-top |
Deprecated. Splits and adds the terminal to the top |
openMode: split-bottom |
Deprecated. Splits and adds the terminal to the bottom |
Example Tasks
The examples below are common use cases you can get inspired by and adjust for your project’s needs.
Note:
before
andinit
tasks need to terminate whilecommand
can run indefinitely (i.e. until cancelled with Ctrl + C). This is becausebefore
andinit
may run as part of a prebuild and if these tasks do not terminate, the prebuild will eventually fail with a timeout.
One-line tasks
Each task contains a single npm
command. The init
task terminates once the dependencies are installed while the command
task starts a development server and does not terminate.
tasks:
- name: Dev Server
init: npm install
command: npm run dev
Multi-line tasks
To run multiple commands for a given task, you can use the |
notation where each line below (make sure you indent correctly) runs in sequence once the previous command terminates.
In the following example, the init
task installs dependencies and configures a database. Then, the command
task starts the dev server(s).
Note: In case of multiple terminals, there is no guarantee on the order in which tasks execute. The only guarantee you have is that
before
,init
andcommand
execute in that sequence per terminal.
tasks:
- name: Dependencies & Database
init: |
npm install
npm run configure-database
command: npm run dev
Note: This doesn’t stop execution on errors. If
npm install
in the example above fails, thenpm run configure-database
will still run. See how to exit after failure below for a workaround.
Wait for commands to complete
When working with multiple terminals, you may have a situation where terminal 1 runs build scripts and terminal 2 and 3 require that these scripts complete first. This can be achieved with gp sync-await
and gp sync-done
.
tasks:
- name: Rails
init: >
bundle install &&
yarn install --check-files &&
rails db:setup &&
gp sync-done bundle # 'bundle' is an arbitrary name
command: rails server
- name: Webpack
init: gp sync-await bundle # wait for the above 'init' to finish
command: bin/webpack-dev-server
- name: Redis
init: gp sync-await bundle
command: redis-server
- name: Sidekiq
init: gp sync-await bundle
command: sidekiq
Wait for a port to be available
Let’s say you have a web app dev server that takes a moment to start up to listen on port 3000. Once it’s up and running, you want to run end-to-end tests against http://localhost:3000
.
You can achieve this with two terminals and the gp ports await
CLI command.
tasks:
- name: Dev Server
init: npm install
command: npm run dev
- name: e2e Tests
command: |
gp ports await 3000
npm run test
Immediately exit for any command failure within a task
If you wish to halt an entire task with for an error within the task script, then you could do the following:
tasks:
- init: |
(
set -e # Tells bash to immediately exit on failure off a command
bundle install
yarn install --frozen-lockfile
bundle exec rake
bundle exec nanoc compile
)
Gitpod starts all your tasks
inside separate bash
($SHELL
) shells. Gitpod can only assert the exit status of the shell process of a task. Normally bash
or other shells don’t halt on a failure of a command unless you explicitly ask it to. bash
only inherits the last exit status of a script run with it before it’s own exit
. Hence Gitpod can’t determine if all of your commands inside the init
task succeeded. To have that effect, you can put set -e;
on top of task shell-commands and wrap your whole task-script with ()
to configure that particular task shell to halt and immediately exit with an error code for a failure of any command. This can be specially helpful for prebuilds (i.e init
tasks)
Task Coupling
Gitpod creates terminal sessions for tasks based on your .gitpod.yml
configuration. Consider the following example where tasks are defined within a single terminal session:
tasks:
- before: export PORT=8080
init: npm install
command: |
cp .env.example .env
npm run dev
Gitpod couples these tasks into a chained bash command, executing them sequentially in one terminal as a whole command, as shown below:
{ export PORT=8080; } && { npm install; } && {
cp .env.example .env
npm run dev
}
When a prebuild is involved, the execution might look like this after a workspace starts:
{ export PORT=8080; } && { cat /workspace/.gitpod/prebuild-logs-0; } && {
cp .env.example .env
npm run dev
}
Now, consider this .gitpod.yml
configuration:
tasks:
- before: touch .foo
- init: npm install
- command: |
cp .env.example .env
npm run dev
In this case, instead of coupling the before
, init
, and command
steps in one terminal, each task runs in a separate terminal in parallel. This approach is sometimes desired, and in such cases, you might also be interested in our gp sync-await command.
Missing examples?
We’d love to hear from you if you have specific questions or ideas for additional examples. Please click the following link to open a pre-configured GitHub issue: Ask for a new Start Task example.