Getting Started
What is Runway?
Runway is a platform to streamline the deployment of projects outside of the main GitLab codebase. If you have a separate codebase containing a service or a web application that can be distributed as a docker container, Runway can help you easily deploy it to staging and production environments. It’s in development right now but is already usable for simple deployment scenarios.
How do I start using Runway?
Add service to inventory
File an MR to add a service to the inventory.yml file in the provisioner project.
If you are using multiple deployments from the one service repository, then you will need to add as many entries as deployments you need all referencing the same project ID. Example:
Parameter Name | Required? | Description |
---|---|---|
name | X | The name of the application to deploy. It can be different from the project name. |
project_id | X | Numerical ID of the GitLab project containing the service’s code or package. |
members | A list of GitLab usernames to grant maintainer access to the deployment project. | |
groups | A list of GitLab groups to grant maintainer access to the deployment project. Inherited group members (from parent groups) will be included. | |
regions | A list of GCP regions that the Runway service would deploy to. This list is the union of regions for all environments. If left empty, it defaults to [“us-east1”]. Ensure subnets are configured for the regions in the networks section. | |
exclude_name_suffix | By default, Runway services have a random suffix to avoid name clashes. Only set to true for production services. All other services, e.g. test services, should set false (or omit the field). | |
gcp_project_group | Name of GCP project group this service belongs to. GCP project groups are defined under gcp_project_groups at the root level of the inventory file. |
There are two ways the service project could be set up:
Using this setup, every commit to the default branch of the service repository will trigger a Runway deployment pipeline in the deployment project.
The image
can be configured with the CI_COMMIT_SHORT_SHA
since the pipeline is triggered from the service project where the application Docker image is built.
Example: https://gitlab.com/gitlab-org/modelops/applied-ml/code-suggestions/ai-assist
Using this setup, the image
input variable has to be updated to deploy the new version of the application. This grants the user a higher degree of control over each deployment.
Example: https://gitlab.com/gitlab-com/gl-infra/cells/topology-service-deployer
Retrieve name of generated deployment project
Once inventory changes are merged, the following happens:
- A deployment GitLab project is created in the Deployments group, as well as a service account for executing deployments.
- Deployment details are located in the downstream pipeline in the created project. This pipeline should be triggered by the CI/CD pipeline of the project.
For the next step you will need to get the Runway service name of your service, which is the name of the project you can
find in Deployments. The format will be
{name}-{hash}
. For example, the service id of a service created in a previous step could be eval-code-viewer-78do0s
.
Update job token permissions
The following steps will allow your deployment project access to your service repository required for Runway to function (see docs).
- Open Settings for your service project
- Go to CI-CD
- Open the Job token permissions drop-down
- Click on Add group or project
- Enter your generated deployment project (from the previous step)
Create Runway configuration files
In the project that holds your code (known as the service repository), you will need to create the following files:
runway.yml
Format
The contents of this file depends on the type of workload you are deploying:
-
RunwayService: this type of workload deploys a Cloud Run Service. You can configure the service with an external and/or internal load balancer.
Example:
woodhouse
, which listens for Slack API requests and performs actions on them. -
RunwayJob: this type of workload deploys a Cloud Run Job, which can be configured to trigger on a schedule or on-demand via CI.
Example:
woodhouse-handover
, which creates an EOC handover issue at set times of the day.
Location
Reconciler will first check if the path .runway/<runway service id>/
exists. If it does, it will look for config files
(e.g., runway.yml
) under this path. If the path does not exist, then it will search under .runway/
.
Example tree structure for running a single deployment:
Directory.runway
- runway.yml
- env-staging.yml
- env-production.yml
- .gitlab-ci.yml
- … etc
Example tree structure for running multiple deployments:
Directory.runway
- runway.yml
- env-staging.yml
- env-production.yml
Directoryfoo-backend
- runway.yml
- env-staging.yml
- env-production.yml
- .gitlab-ci.yml
- … etc
In the example above, when running a deployment for Runway service ID foo-backend
, it will use the config files under
the foo-backend
path, however deployments for any other Runway service ID will use the config files under .runway/
.
Alternatively, to be explicit, you could also make it look like the following and it will have the same effect with the
exception that deployments for any other Runway service ID will fail because there is no runway.yml
(nor env-*.yml
)
file in the .runway/
directory:
Directory.runway
Directoryfoo-frontend
- runway.yml
- env-staging.yml
- env-production.yml
Directoryfoo-backend
- runway.yml
- env-staging.yml
- env-production.yml
- .gitlab-ci.yml
- … etc
Once you have your config files in the right places, scroll down to read the section on updating your project’s
.gitlab-ci.yml
to trigger multiple deployments.
Stage-specific runway.yml
If you only have a single runway.yml
file then it will be used for all stages. You can, alternatively, create
different Runway config files for each stage by defining runway-<stage>.yml
.
Example tree structure might look like this:
Directory.runway
Directoryfoo-frontend
- runway.yml
- runway-staging.yml
- env-staging.yml
- env-production.yml
Directoryfoo-backend
- runway-production.yml
- runway-staging.yml
- env-staging.yml
- env-production.yml
- .gitlab-ci.yml
- … etc
-
In the
foo-frontend
service above, the production deployment would userunway.yml
(as there is norunway-production.yml
) while staging would userunway-staging.yml
. -
In the
foo-backend
service above, we are being explicit by defining a config file for each stage (runway-staging.yml
andrunway-production.yml
). Runway currently supports two stages (staging
andproduction
). It is your choice whether to be explicit or not, however we do recommend being explicit purely from a future-proof perspective so that if Runway ever supports more stages, they will not accidentally use yourrunway.yml
file.
env-staging.yml
and env-production.yml
Inside these two files, which can live in .runway/
or .runway/<runway service ID>/
depending on whether you are
deploying a single (former) or multiple services (latter), is where you define any environment variables that you wish
to make available to the containers running in either the staging
or production
environments.
Given that these files are cleartext and stored in your project repository, you must not place any secrets inside these files. See the documentation on secrets management for more info.
Example contents of one of these files might be:
Trigger Runway deployments
Ensure you have your config files in the right places by reading the section above.
input name | description |
---|---|
runway_service_id | The Runway service id of a service that was created in the step 1. |
image | Docker image to be deployed by Runway platform. Note that the image should contain all the parameters required to start your service. Runway also requires you to build this image as part of your pipeline setup. |
runway_version | The version of Runway to use. When starting, pick the latest version from the Releases page. |
Check the deployment
Once the code above is integrated into the main branch of your project, you can check Pipelines
section and see if it was successfully deployed.
If you expand the jobs on the downstream pipelines, you will see a number jobs:
Each of the downstream pipelines corresponds to a deployment to a stage. You can see the stage name is part of almost all jobs (e.g., Deploy production).
You can also appreciate that the runway_staging
stage (in GitLab terminology) comes before runway_production
meaning that the staging downstream pipeline has
to pass for production to start. As part of the downstream pipeline jobs, there is a monitor job that runs after the deploy, which performs basic error rate
checks to determine if the service is healthy after the deploy. If the staging monitor job passes, then the production deployment will automatically start.
Accessing your environment
The best place to find the links to access your environments (once they have been deployed) is through Operate → Environments in your service project.
In there you should see two environments, staging
and production
.
Clicking on the Open
button will take you to the URL to access that environment:
Keeping up with Runway releases
Renovate is a tool that checks for new dependency versions and, if found, will periodically create MRs to upgrade them to the newest version. It is used extensively within “Infrastructure”.
The easiest way to keep up with Runway releases is to enable Renovate CI triggered merge requests on your service project by doing the following:
- Add
@glrenovatebot
as aDeveloper
for your project underManage > Members
. - Add
runway-workloads
as a topic in your project underSettings > General > Naming, description, topics
. - Set
RENOVATE_DISABLED
totrue
as a CI/CD variable if you are currently getting MRs filed byrenovate-bot.yml
fromcommon-ci-tasks
If you’re not already using Renovate, once you’ve added the runway-workloads
topic to your service project, Renovate
CI will be able to
discover your project and onboard it by opening a merge request like this
one.
If you have an existing renovate.json
file, Renovate will not update it
for you so you will need to update the file yourself and add Runway’s Renovate config preset
to the list of base configs (i.e. the extends
keyword). For example:
This will look for patterns like runway_version: v2.40.0
in your .gitlab-ci.yml
file and keep the version up to date.
Troubleshooting
- If your deployment fails for any reason, check the deployment logs.
- If the downstream pipeline failed to be executed, there’s probably a permission mismatch.
Currently, a person triggering a deployment must have “Developer” permissions in the
runwayctl project and “Maintainer” permissions in
the generated deployment project
(example).
To grant additional permissions, update the inventory.yml
file in the provisioner repo from step 1.
Frequently Asked Questions
How do I roll back the deployment?
At the moment the designed way to roll back a deployment is roll back a commit on the main branch, which will trigger a new deployment to Runway with the reverted code.
How do I view metrics?
By default, metrics are reported for all Runway services. To view metrics, you can use service
filter on Runway
Service Metrics dashboard.
Recommendation: For additional features, such as custom service overview dashboard, alerts, and capacity planning, refer to the observability page.
How do I view logs?
By default, application container logs can be viewed in Cloud Logging UI by filtering resource.labels.service_name
to your runway_service_id
.
To learn more, refer to the observability page.
How do I fix Terraform state error?
Insufficient permissions
When a pipeline is triggered with insufficient permissions, failed job includes following error message:
To fix, there are two potential options:
- Job can be retried by member with the required permissions, or
- Add your GitLab username to
members
attribute ininventory.yml
and retry the job yourself (example MR).