doc/development/remote_development/local_development_setup.md
Set up your local development environment to work on the Remote Development Workspaces features. You can choose between two setup modes depending on your development needs:
agentw):
Install Rancher Desktop 1.20.0.
In Rancher Desktop, select the Preferences icon.
Configure the virtual machine:
Go to Virtual Machine > Hardware and set minimum values of 4 CPUs and 8 GB RAM.
For macOS only:
Go to Container Engine, select containerd.
Go to Kubernetes:
Set the GDK_ROOT environment variable:
echo 'export GDK_ROOT="/path/to/your/gdk"' >> ~/.zshrc
Replace /path/to/your/gdk with your actual GDK directory path.
Configure GDK to run on a local private IP address by following the local network binding documentation.
For this setup, we assume the private IP address is 172.16.123.1. If you use a different IP address,
substitute the correct value in later steps.
Configure NGINX for GDK:
Add this configuration to your gdk.yml file:
hostname: gdk.test
nginx:
enabled: true
http:
enabled: true
Install NGINX:
brew install nginx
Optional. Check out the desired branches on GitLab:
cd "${GDK_ROOT}/gitlab"
git checkout my_branch
To prevent changes from being lost when you run gdk update, add this to your gdk.yml:
gdk:
auto_rebase_projects: true
Restart your GDK:
cd "${GDK_ROOT}"
gdk restart
Enable agent for Kubernetes in your GDK by adding this configuration to gdk.yml:
gitlab_k8s_agent:
enabled: true
agent_listen_address: gdk.test:8150
k8s_api_listen_address: gdk.test:8154
Reconfigure and restart GDK:
cd "${GDK_ROOT}"
gdk reconfigure
gdk restart
Optional. Check out the desired branches on agent for Kubernetes:
cd "${GDK_ROOT}/gitlab-k8s-agent"
git checkout my_branch
Optional. To manually run kas, for example, to run in a different cloned directory or debug in an IDE:
For debugging with JetBrains GoLand IDE:
kas "Run Configuration" "Run Kind: Directory'/path/to/cmd/kas.Run after build.ENV vars and options as you do to Bazel.To ensure agent for Kubernetes is properly installed:
Install Xcode from the Apple App Store and accept the license:
sudo xcodebuild -license accept
Clone the agent repository:
git clone https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent
Test the installation:
cd gitlab-agent
make test
If you encounter errors, clean and retry:
bazel clean --expunge
make test
[!note] You might also need to do this in the
<GDK_ROOT>/gitlab-k8s-agent, which is used by the GDK.
When make test passes, agent for Kubernetes is ready to use.
agentk) for WorkspacesCreate an agent configuration file:
http://gdk.test:3000/gitlab-org.gitlab-agent-configurations with a README..gitlab/agents/remotedev/config.yaml with your agentk configuration.[!note] When you create or change this file, you must start or restart
agentkdescribed in step 4.
Register agentk with GitLab:
gitlab-agent-configurations project, go to Operate > Kubernetes clusters.remotedev in the input field.AGENT_TOKEN environment variable.Map the agent to the gitlab-org group:
http://gdk.test:3000/gitlab-org.remotedev in the list and select Allow.Start the Agent (agentk):
export AGENT_TOKEN='your_copied_token'
cd "${GDK_ROOT}/gitlab-k8s-agent"
echo -n "$AGENT_TOKEN" > "$HOME/.gitlab-agentk-token.txt"
export POD_NAMESPACE=default
export POD_NAME=remotedev
bazel run //cmd/agentk -- --kas-address=grpc://gdk.test:8150 --token-file=$HOME/.gitlab-agentk-token.txt
Optional. To manually run agentk, for example, to run in a different cloned dir or debug in an IDE:
For debugging with JetBrains GoLand IDE:
kas "Run Configuration" "Run Kind: Directory'/path/to/cmd/kas.Run after build.ENV vars and options as you do to Bazel.Go to Operate > Kubernetes clusters. The remotedev agent should now display as Connected.
Use this configuration in the .gitlab/agents/remotedev/config.yaml file:
remote_development:
enabled: true
network_policy:
enabled: true
egress:
- allow: '0.0.0.0/0'
except:
- '10.0.0.0/8'
- '172.16.0.0/12'
- '192.168.0.0/16'
- allow: '172.16.123.1/32'
gitlab_workspaces_proxy:
http_enabled: false
ssh_enabled: false
observability:
logging:
level: debug
grpc_level: warn
Use this configuration in the .gitlab/agents/remotedev/config.yaml file:
remote_development:
enabled: true
dns_zone: workspaces.localtest.me
network_policy:
enabled: true
egress:
- allow: '0.0.0.0/0'
except:
- '10.0.0.0/8'
- '172.16.0.0/12'
- '192.168.0.0/16'
- allow: '172.16.123.1/32'
observability:
logging:
level: debug
grpc_level: warn
If you chose the GitLab Workspaces Proxy mode, complete these additional steps:
Create an OAuth application:
Go to http://gdk.test:3000/admin.
Go to Applications and select Add new application.
Set the name to GitLab Workspaces Proxy.
Set the redirect URI to https://workspaces.localtest.me/auth/callback.
Set the scopes to api, read_user, openid, and profile.
Export the client credentials:
export CLIENT_ID="your_client_id"
export CLIENT_SECRET="your_client_secret"
Export GITLAB_URL to point to your GDK:
export GITLAB_URL="http://gdk.test:3000"
Set up Ingress Controller and GitLab Workspaces Proxy:
brew install mkcert
cd "${GDK_ROOT}/gitlab"
./scripts/remote_development/workspaces_kubernetes_setup.sh
Optional. Define a devfile for testing:
If you don't need to test specific configurations, skip this step in favor of using the default Devfile in the next step.
Go to the gitlab-org/gitlab-shell project at http://gdk.test:3000/gitlab-org/gitlab-shell.
Create a file at .devfile.yaml:
schemaVersion: 2.2.0
components:
- name: tooling-container
attributes:
gl/inject-editor: true
container:
image: "registry.gitlab.com/gitlab-org/workspaces/gitlab-workspaces-docs/ubuntu:04@sha256:07590ca30ebde8a5339c3479404953e43ee70e7e9e0c2ede2770684010ddf7fe"
[!note] The SHA256 is required to ensure the pulled container is the AMD64 architecture container. The GitLab VS Code fork for Workspaces does not support other architectures yet. To track this, see issue 392693.
Create a new workspace:
Go to Your Work > Workspaces at http://gdk.test:3000/-/remote_development/workspaces.
Select New Workspace.
Choose the project with your devfile (or search for shell to find GitLab Shell).
[!note] If you get an error about a missing agent configuration, check your
agentkdebug logs to ensure that youragentksuccessfully connects and reads your agent configuration file.
Choose your cluster agent.
If you skipped the devfile step, select Use GitLab default devfile.
Select Create Workspace.
Wait for the workspace to reach the Running state.
Select Open Workspace.
To enable Extensions Marketplace for Web IDE in a workspace, see manage extensions.
[!note] By default, the GitLab VS Code fork for Workspaces server uses Open VSX Extensions Marketplace. These settings are configured during a workspace startup in the
product.jsonfile. This file is located in the${GL_EDITOR_VOLUME_DIR}/code-serverdirectory.
To customize the Extensions Marketplace configuration, these are the relevant properties in the
product.json file:
{
"extensionsGallery": {
"serviceUrl": "",
"itemUrl": "",
"resourceUrlTemplate": ""
}
}
To enable AI features in workspaces:
Follow the instructions in Set up GitLab Team Member License for GDK.
This page also lists other set up AI features options for local development. To provision a GitLab Self-Managed Ultimate Subscription with GitLab Duo Pro add-on license yourself, follow the cloud license with CustomersDot approach.
Configure your instance to use the staging AI Gateway (https://cloud.staging.gitlab.com/ai).
For workspaces, you must enable GitLab Duo Chat features. They are only available with a GitLab Duo Enterprise
license. You cannot provision this license for yourself through the staging Customers Portal.
To upgrade your subscription from GitLab Duo Pro to GitLab Duo Enterprise, submit your request in the
#g_provision Slack channel.
If configured correctly, in the Admin > GitLab Duo Pro settings, the message, No health problems detected. is displayed.
[!note] While using GitLab Duo Chat, if you see the
Error code: A9999response, clear and reset the chat until it succeeds. It is a common error response from the GitLab Duo API when using the staging gateway.
[!note] It is planned to move some of the information in this section to the RubyMine handbook section, or ideally shared with SCM.
Use these scopes to:
Inspect Code (cmd-shift-A -> Inspect Code) to run static analysis on the scope.remote_devfile[gitlab]:ee/lib/remote_development//*||file[gitlab]:ee/spec/factories/remote_development//*||file[gitlab]:ee/app/services/remote_development//*||file[gitlab]:app/models/remote_development//*||file[gitlab]:ee/app/graphql/mutations/remote_development//*||file[gitlab]:ee/app/graphql/resolvers/remote_development//*||file[gitlab]:ee/app/graphql/types/remote_development//*||file[gitlab]:ee/app/models/remote_development//*||file[gitlab]:ee/spec/graphql/types/remote_development//*||file[gitlab]:ee/spec/models/remote_development//*||file[gitlab]:ee/spec/services/remote_development//*||file[gitlab]:ee/app/finders/remote_development//*||file[gitlab]:ee/spec/features/remote_development//*||file[gitlab]:ee/spec/support/shared_contexts/remote_development//*||file[gitlab]:ee/app/graphql/ee/types/user_interface.rb||file[gitlab]:ee/app/graphql/resolvers/concerns/remote_development//*||file[gitlab]:ee/app/graphql/resolvers/projects/workspaces_resolver.rb||file[gitlab]:ee/app/graphql/resolvers/users/workspaces_resolver.rb||file[gitlab]:ee/spec/requests/api/graphql/mutations/remote_development//*||file[gitlab]:ee/spec/requests/api/graphql/remote_development//*||file[gitlab]:ee/spec/finders/remote_development//*||file[gitlab]:ee/app/assets/javascripts/remote_development//*||file[gitlab]:ee/spec/frontend/remote_development//*||file[gitlab]:ee/spec/graphql/api/workspace_spec.rb||file[gitlab]:ee/spec/fixtures/remote_development//*||file[gitlab]:ee/spec/lib/remote_development//*
remote_dev services & libUse this scope to set up restricted YARD inspections and to have safety warnings for:
Editor -> Inspections -> YARD -> Missing @param tag in method signature, add scope as WarningEditor -> Inspections -> YARD -> Missing @return tag in method, add scope as Warningfile[gitlab]:ee/app/services/remote_development//*||file[gitlab]:ee/lib/remote_development//*
To run a subset of specs related to the Workspaces feature for a pre-commit "Smoke Test", use the following script:
scripts/remote_development/run-smoke-test-suite.sh
agentk.[!note] The test does not set up or teardown any of these components as a part of its execution.
At present, the test is tagged with a
quarantinelabel so it does not run as a part of CI/CD, because of complexities in spinning up KAS andagentkin the CI/CD environment. It must be run manually.
To run the test:
Ensure that the test GitLab instance is up and running with the default KAS or agentk stopped.
Ensure KAS with remote development code is up and running.
By default, the E2E test assumes the existence of an agent with name test-agent under the group
gitlab-org in the GDK GitLab instance:
test-agent in a project in gitlab-org group.
The gitlab-shell project in the gitlab-org group is a candidate for where to create this agent.AGENTK_GROUP and AGENTK_NAME.Change the current working directory to {GDK_ROOT}/gitlab.
Run the test with scripts/remote_development/run-e2e-spec.sh.
AGENTK_GROUP=some-org GITLAB_PASSWORD=example scripts/remote_development/run-e2e-spec.shThe complete list of environment variables are in scripts/remote_development/run-e2e-spec.sh.
Use the example projects to test GitLab Workspaces. These projects include devfiles and work out-of-the-box.
gitlab-org group.README file in each project for specific usage instructions.These repositories are used to develop Workspaces:
| Name | Description | Language |
|---|---|---|
| GitLab | Main logic | Ruby on Rails |
| GitLab Agent for Kubernetes | Logic for creating/report Kubernetes resources | Go |
| GitLab Workspaces Proxy | Logic for authentication and authorization of incoming workspaces traffic | Go |
| GitLab Build Images | Logic for workspaces-related container image builds | Shell script, Docker |
| Devfile Gem | Logic for converting Devfile to Kubernetes resources | Go, Ruby |
These dependencies are external repositories that Workspaces relies on:
| Name | Description | Language | Used by |
|---|---|---|---|
| GitLab VS Code Fork | GitLab fork of upstream VS Code OSS project | Script | GitLab Workspaces Tools |
| GitLab VS Code Extension | GitLab VS Code Extension | TypeScript | GitLab Workspaces Tools |
| Devfile API | Upstream project defining Devfile Schema | Go | GitLab |
| Devfile Library | Upstream project for converting Devfile to Kubernetes resources | Go | Devfile Gem |
For tips on debugging under Ruby Mine, see Using RubyMine debugger for GitLab running under GDK.
KAS and agentk debugging also works under GoLand. If you need help to set up Run Configurations,
reach out to one of the developers or engineers.
log/remote_development.loglog/remote_development.log contains specific remote development logs in JSON format.
You might need to install jq.
tail -f log/remote_development.log | jq
log/development.logFor other details or exceptions that are not in log/remote_development.log, see the standard Rails log/development.log:
tail -f log/development.log
You might get orphaned workspace records on Rails, or you might want to start with a clean slate. To do this:
Go to the gitlab repository in your GDK.
Open the Rails console:
bin/rails c
Delete all the workspace records:
RemoteDevelopment::Workspace.delete_all
| Task | Command |
|---|---|
| List all contexts | kubectl config get-contexts |
| Get current context | kubectl config current-context |
| Switch context | kubectl config use-context CONTEXT_NAME |
| List namespaces | kubectl get namespaces |
| Switch namespace | kubectl config set-context --current --namespace=NAMESPACE |
| Task | Command |
|---|---|
| List pods in all namespaces | kubectl get pods -A |
| Get namespace details | kubectl get namespace NAMESPACE -o yaml |
| Get pod details | kubectl -n NAMESPACE get pods POD_NAME -o yaml |
| List API resources | kubectl api-resources |
[!note] If you omit
-n NAMESPACEfrom commands,kubectluses the current namespace.
Get logs from a pod:
kubectl -n NAMESPACE logs -f POD_NAME
Get logs from a specific container:
kubectl -n NAMESPACE logs -f POD_NAME -c CONTAINER_NAME
Get all workspace objects:
kubectl get serviceaccount,pvc,networkpolicy,resourcequota,deployment,service,secret,configmap -l "agent.gitlab.com/id"
Get the gitlab-workspaces-proxy-config secret:
kubectl -n gitlab-workspaces get secret gitlab-workspaces-proxy-config -o go-template='{{range $k,$v := .data}}{{printf "%s: " $k}}{{if not $v}}{{$v}}{{else}}{{$v | base64decode}}{{end}}{{"\n"}}{{end}}'
Enter workspace main container shell:
PODNAME=$(kubectl get po -o name | cut -d/ -f2) && CONTAINER_NAME=$(kubectl get pod $PODNAME -o jsonpath='{range .spec.containers[*]}{.name}{"\t"}{range .env[*]}{.name}{","}{end}{"\n"}{end}' | grep GL_TOOLS_DIR | cut -f 1) && kubectl exec $PODNAME -c $CONTAINER_NAME -it -- /bin/bash
Run commands in the workspace container (example with log tailing):
PODNAME=$(kubectl get po -o name | cut -d/ -f2) && CONTAINER_NAME=$(kubectl get pod $PODNAME -o jsonpath='{range .spec.containers[*]}{.name}{"\t"}{range .env[*]}{.name}{","}{end}{"\n"}{end}' | grep GL_TOOLS_DIR | cut -f 1) && kubectl exec $PODNAME -c $CONTAINER_NAME -it -- /bin/bash -c "tail -n 100 -f /tmp/*.log"
[!note] These commands run in the current namespace. Use
kubensto switch to the workspace namespace before running them.
Delete a namespace:
kubectl delete namespace NAMESPACE
Delete a pod:
kubectl -n NAMESPACE delete pods POD_NAME
Delete all workspace namespaces:
kubectl get namespace | grep gl- | cut -f1 -d" " | xargs -I {} kubectl delete namespace {}
[!note] This cleanup may take time. If it stalls, restart Rancher Desktop and try again.
For information about how localhost traffic reaches Kubernetes when using GitLab Workspaces Proxy, see this comment.