Code Anywhere With Codespaces

Lucas Santos - Sep 3 '20 - - Dev Community

The dream of anyone who works with technology is to always be with our best friend, the computer. There are several solutions that transform small devices like Raspberry Pis into complete computers, other solutions create small, pocket-sized computers that can be accessed at any time.

There are several reasons why someone needs - or just likes - to be with a computer by their side at all times. Often the person prefers to have a super powerful tool always at hand for any problems or even develop that idea that was conceived in the middle of the street. In other more special cases, the person may be one of the maintainers of critical projects and must always be available to solve any problems, this takes away the freedom of movement, having such a device makes the person able to gain their mobility back.

We may have the best portable machines, but no computer can match our own, with our environments and configurations.

Codespaces

Code Anywhere with Codespaces
Opening screen for GitHub Codespaces

Recently GitHub at its Satellite 2020 event announced the release of a new feature on their platform, Codespaces. At the moment, it is only available by requesting early access through the website. However, you can be one of those who have received access recently and will be able to access this incredible new way of working!

For now GitHub's Codespaces is in beta and you may not have the functionality enabled. Then you will not be able to see what I will show next, but you will be able to register directly on the site to receive early access.

Codespaces are an online implementation of Visual Studio Code. As an editor based on web technologies, VSCode has the incredible perk of being one of the few projects that can be ported between platforms extremely easy.

This had already been done before with Code Server - we even used an interesting implementation created by Alejandro Oviedo, our colleague from Argentina, at Nodeschool SP - but one of the major problems with Code Server was that the extension store did not support all existing extensions for VSCode and also that the editor got confused when we used keyboards with different layouts.

The great advantage that GitHub Codespaces (GH Codespaces or GHC) brought is that it is integrated directly into GitHub, that is, you can open any repository that you have permission to write in a web-ready editor! See an example from my GotQL repository:

Code Anywhere with codespaces
Cloning screen on GitHub showing the green "Open with Codespaces" button

And all of this is free, for both paid and private repositories.

How does it work?

Codespaces are built on top of another existing Microsoft solution called Visual Studio Codespaces (VSC), which is an excellent paid alternative to GH Codespaces when you are looking for something more open, this is because VS Codespaces create a virtual machine on Azure and connect to it through the native VSCode functionality called Remote Development.

Important Update

Microsoft is consolidating VS Codespaces into GH Codespaces, which means that, by November 20th 2020 all new VS Codespaces will be unavailable and by February 2021, VSC will be retired completely.

Thanks for the comments on this update. You can read more here

Remote Development connects to another computer running a small server on the other side. That is, you can separate the processing of the editor from the interface. That way you can practically run VSCode anywhere, because any browser that supports the latest JavaScript can run the editor interface.

And then we put together another incredible technology that is containers. As you may have seen on my blog (in Portuguese), containers are an incredible technology that allows you to run virtually all applications in a self-contained manner without relying on external libraries. Codespaces take advantage of this mainly so that they can build the images of the machines they are going to run on.

That way we can have a container that contains all the necessary tools for our project to run, because it is completely customizable.

Visual Studio Codespaces

Visual Studio Codespaces home page

Before we dive into GitHub Codespaces, I'll show you how we can use VS Codespaces to create a remote development environment, so that we can understand what we're dealing with

After logging in and creating your VSC instance, let's create a new codespace:

Visual Studio Codespace creation button

And, after clicking on the "Create Codespace" button, things start to get interesting, as we start to have a series of awesome options that can be toggled:

Visual Studio Codespaces config screen

The first option is very simple, we have to give a name to our codespace, this will be the name that's going to identify this machine, so it needs to be a very descriptive name.

Then, we have the most interesting option, the VSC itself already allows us to start a Codespace from another GitHub repository, that is, GH Codespaces itself is a different interface for VSCs.

From there we have the configuration of our VMs, so we can choose how strong our remote machine will be and also how much idle time can pass before suspending the VM, this way we don't have to pay for idle computation.

And then we enter the coolest part! We can define what are called dotfiles, which are the configuration files for our shell. That way, we can have a separate repository of dotfiles - like I have - and a script to install these dotfiles on our online machine, that is, we can replicate exactly what we have on our local computer in a web interface!

Visual Studio Codespace online

GitHub Codespaces

With the GHC it's exactly the same! The only different action you will have to do is to enter a repository - like GotQL - click on the green button that would be "clone". Then click on "open with codespace":

Opening a new repository in a codespace

All beta users are entitled to 2 free codespaces. That is, you can maintain up to 2 development machines without paying absolutely anything. Then, you will need to remove the old ones to create new ones. In the GotQL example, we have the option to open with Codespaces, this action will already create an environment which is ready for development, with all dependencies installed

But how do we do it?

Customisation

One of the coolest features of codespaces is the fact that they are completely customisable.

In the case of dotfiles, you can configure both your local VSCode (the editor installed on your machine) to search for a series of files according like this documentation explains or, in the case of GitHub, you can directly have a repository called dotfiles, like the documentation also explains.

However, you can do more than that with a folder called .devcontainer. What this folder does is that it groups the possible configurations for a codespace. In it we can have a Dockerfile, a file called devcontainer.json and a .sh file that would be the shell configuration of our environment. When we create a codespace from a repository, GitHub will look for this folder in it and will create the codespace accordingly.

Let's look at GotQL's .devcontainer as an example. We have a Dockerfile, it's responsible for telling us what type of container, or what type of environment we will have, it will be there that we will install packages, create users and etc. As well as choosing the image of our base operating system.

FROM mcr.microsoft.com/vscode/devcontainers/javascript-node:14

# The javascript-node image includes a non-root node user with sudo access. Use 
# the "remoteUser" property in devcontainer.json to use it. On Linux, the container 
# user's GID/UIDs will be updated to match your local UID/GID when using the image
# or dockerFile property. Update USER_UID/USER_GID below if you are using the
# dockerComposeFile property or want the image itself to start with different ID
# values. See https://aka.ms/vscode-remote/containers/non-root-user for details.
ARG USERNAME=node
ARG USER_UID=1000
ARG USER_GID=$USER_UID

# Alter node user as needed, install tslint, typescript. eslint is installed by javascript image
RUN if ["$USER_GID" != "1000"] || ["$USER_UID" != "1000"]; then \
        groupmod --gid $USER_GID $USERNAME \
        && usermod --uid $USER_UID --gid $USER_GID $USERNAME \
        && chmod -R $USER_UID:$USER_GID /home/$USERNAME \
        && chmod -R $USER_UID:root /usr/local/share/nvm /usr/local/share/npm-global; \
    fi \
    #
    # Install tslint, typescript. eslint is installed by javascript image
    && sudo -u ${USERNAME} npm install -g tslint typescript gitmoji-cli
Enter fullscreen mode Exit fullscreen mode

So, when a GotQL codespace is created, this will be the environment that we will have, an environment with a non-root user with access to sudo and tslint and TypeScript already installed. I also added the gitmoji-cli which is the standard for commits I use in this project.

Then, we have devcontainer.json, which is responsible not only for configuring our editor's settings but also for giving directions to the codespace builder. In it we define the name of the codespace, the extensions that our online VSCode will have as soon as it starts, what is the Dockerfile that it'll use to build the base system and we can also overwrite all VSCode settings as well.

{
  "name": "TypeScript website codespace",
  "extensions": [
    "emmanuelbeziat.vscode-great-icons",
    "dbaeumer.vscode-eslint",
    "oderwat.indent-rainbow",
    "vtrois.gitmoji-vscode",
    "dracula-theme.theme-dracula",
    "2gua.rainbow-brackets",
    "ms-vscode.vscode-typescript-tslint-plugin"
  ],
  "dockerFile": "Dockerfile",
  // Set *default* container specific settings.json values on container create.
  "settings": { 
    "terminal.integrated.shell.linux": "/bin/bash",
    "window.autoDetectColorScheme": true,
    "workbench.preferredDarkColorTheme": "Dracula",
    "editor.renderWhitespace": "boundary",
    "workbench.colorTheme": "Dracula",
    "workbench.iconTheme": "vscode-great-icons"
  },
  // Use 'postCreateCommand' to run commands after the container is created.
  "postCreateCommand": "npm install"
}
Enter fullscreen mode Exit fullscreen mode

In addition we have the postCreateCommand, which is extremely useful for running commands after the codespace has been created, in this case we are running the command npm install, so that we will have all the packages installed when we open.

And we have an excellent example repository of codespaces that can serve as a basis for you to create your own. Let's get the file setup.sh from the codespace example for Node

## update and install some things we should probably have
apt-get update
apt-get install -y \
  curl \
  git \
  gnupg2 \
  jq \
  sudo \
  zsh

## set-up and install yarn
curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add -
echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list
apt-get update && apt-get install yarn -y

## install nvm
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.35.3/install.sh | bash

## setup and install oh-my-zsh
sh -c "$(curl -fsSL https://raw.githubusercontent.com/robbyrussell/oh-my-zsh/master/tools/install.sh)"
cp -R /root/.oh-my-zsh /home/$USERNAME
cp /root/.zshrc /home/$USERNAME
sed -i -e "s/\/root\/.oh-my-zsh/\/home\/$USERNAME\/.oh-my-zsh/g" /home/$USERNAME/.zshrc
chown -R $USER_UID:$USER_GID /home/$USERNAME/.oh-my-zsh /home/$USERNAME/.zshrc
Enter fullscreen mode Exit fullscreen mode

This file is referenced within the Dockerfile, being executed as soon as it is started.

Conclusion

Codespaces can become one of the main technologies we currently have, mainly because they allow editing or even more complex development using mobile devices such as cell phones.

Many programmers already used Docker-based solutions to program on the ipad, however these solutions always ended up being more like "workarounds" than real solutions.

With the emergence of technologies and features like these, we have the ability to take our work environment anywhere. Stay tuned in the next articles where I will explain how I set up my remote desktop using GHC!

Like and share your feedbacks in the comments!

See ya!

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .