Published: Oct 31, 2024 by Isaac Johnson
Recently I was granted access to use Codespaces in Github. Since so much is made of Co-pilot today, I feel Codespaces doesn’t get as much coverage as in the past. It’s very similar to dev containers we covered earlier this month
I cover setup and usage below, however, I also want to share a 15 min presentation I gave on this same topic Tuesday Oct 29, 2024 - available on YouTube: SkyStudio DevOps - Github Codespaces, DevContainers, and Project IDX. (This is the pre-record without Q and A)
Getting Started
Assuming you have Codespaces enabled in your Github account:
We should be able to use it in the repos we already configured dev containers. Let’s start with the repo behind this blog:
We see the “Codespaces” section by “Local” in the area we usually find our GIT Clone URLs.
Clicking that create on main fired up a fresh Codespace instance
If I click the link on “Building”, I can see the current status.
I have to admit, this GIT repo has gotten stoopid big and now is 9.6Gb to full clone.
After a while it did come up, albeit noting an error and that it was in recovery mode
The linked build log
2024-10-27 14:58:43.774Z: Host information
2024-10-27 14:58:43.775Z: ----------------
2024-10-27 14:58:43.775Z: OS: Ubuntu 22.04.5 LTS (stable release)
2024-10-27 14:58:43.775Z: Image details: https://github.com/github/codespaces-host-images/blob/main/README.md
2024-10-27 14:58:43.775Z: ----------------
=================================================================================
2024-10-27 14:58:43.775Z: Configuration starting...
2024-10-27 14:58:43.897Z: Cloning...
====================================== ERROR ====================================
2024-10-27 15:02:53.355Z: The following error occurred reading the devcontainer.json file - "After parsing a value an unexpected character was encountered: ". Path 'build', line 26, position 1." Please see https://docs.github.com/en/enterprise-cloud@latest/codespaces/setting-up-your-project-for-codespaces/introduction-to-dev-containers#devcontainerjson for help configuring your file.
=================================================================================
====================================== ERROR ====================================
2024-10-27 15:02:53.362Z: Container creation failed.
=================================================================================
2024-10-27 15:02:59.442Z:
===================================== WARNING ===================================
2024-10-27 15:02:59.443Z: Creating recovery container.
=================================================================================
=================================================================================
2024-10-27 15:03:30.507Z: Creating container...
2024-10-27 15:03:30.534Z: $ devcontainer up --id-label Type=codespaces --workspace-folder /var/lib/docker/codespacemount/workspace/jekyll-blog --mount type=bind,source=/.codespaces/agent/mount/cache,target=/vscode --user-data-folder /var/lib/docker/codespacemount/.persistedshare --container-data-folder .vscode-remote/data/Machine --container-system-data-folder /var/vscode-remote --log-level trace --log-format json --update-remote-user-uid-default never --mount-workspace-git-root false --omit-config-remote-env-from-metadata --skip-non-blocking-commands --skip-post-create --config "/var/lib/docker/codespacemount/workspace/jekyll-blog/.devcontainer/devcontainer.json" --override-config /root/.codespaces/shared/merged_devcontainer.json --default-user-env-probe loginInteractiveShell --container-session-data-folder /workspaces/.codespaces/.persistedshare/devcontainers-cli/cache --secrets-file /root/.codespaces/shared/user-secrets-envs.json
2024-10-27 15:03:30.756Z: @devcontainers/cli 0.68.0. Node.js v18.20.4. linux 6.5.0-1025-azure x64.
2024-10-27 15:03:31.157Z: $alpine -c echo Container started
2024-10-27 15:03:31.185Z: Unable to find image 'mcr.microsoft.com/devcontainers/base:alpine' locally
2024-10-27 15:03:31.425Z: alpine: Pulling from devcontainers/base
It would appear that GH Codespaces is stricter than the dev containers in VS Code noting what is clearly a mistake in my JSON
I made the change in the window and it offered to relaunch. I’m honestly curious how that would work as the devcontainer JSON is on main and I’m not sure it’s saving the file (which would trigger a release GH Action). While I did see it relaunch my container, i did not see it fire a Github Action so it must handle candidate changes on its container files.
It worked and came back up
Before I make any changes, let’s try to do the standard bundle exec jekyll serve
which should fire up the mainline version of the blog
I clicked the link to “Open in browser” and it fired up a new tab
which properly loaded the site
I can go to the source-control section and see the change is ready to be staged, albeit against main
I’m curious what would happen if I make this correction here in the VS Code I’m running locally, push up this new branch then change the Codespace to use the same branch. Will it seamlessly reload?
I did quick catch that i neglected to stage the devcontainer change and pushed that
builder@LuiGi:~/Workspaces/jekyll-blog$ git add .devcontainer/devcontainer.json
builder@LuiGi:~/Workspaces/jekyll-blog$ git commit -m "make sure to add devcontainer"
[2024-10-codespaces 39c8d52] make sure to add devcontainer
1 file changed, 1 insertion(+), 1 deletion(-)
builder@LuiGi:~/Workspaces/jekyll-blog$ git push
Enumerating objects: 7, done.
Counting objects: 100% (7/7), done.
Delta compression using up to 16 threads
Compressing objects: 100% (4/4), done.
Writing objects: 100% (4/4), 369 bytes | 369.00 KiB/s, done.
Total 4 (delta 3), reused 0 (delta 0), pack-reused 0
remote: Resolving deltas: 100% (3/3), completed with 3 local objects.
To github.com:idjohnson/jekyll-blog.git
491f0a9..39c8d52 2024-10-codespaces -> 2024-10-codespaces
Then I ran the checkout and it seemed to start doing things
It eventually gave up because of the local change
root@codespaces-c64ff3:/workspaces/jekyll-blog# git pull
remote: Enumerating objects: 16, done.
remote: Counting objects: 100% (14/14), done.
remote: Compressing objects: 100% (1/1), done.
remote: Total 4 (delta 3), reused 4 (delta 3), pack-reused 0 (from 0)
Unpacking objects: 100% (4/4), 349 bytes | 38.00 KiB/s, done.
From https://github.com/idjohnson/jekyll-blog
491f0a91..39c8d52f 2024-10-codespaces -> origin/2024-10-codespaces
Already up to date.
root@codespaces-c64ff3:/workspaces/jekyll-blog# git checkout 2024-10-codespaces
error: Your local changes to the following files would be overwritten by checkout:
.devcontainer/devcontainer.json
Please commit your changes or stash them before you switch branches.
Aborting
I decided to ditch it and pull the branch. In the process of discarding the local change and pulling from then branch, I did see a “detected local changes do you want to rebuild” message, which I ignored. But after the branch was live, I was fine
At this point I decided to close the window, power down and come back later today to see how it would handle it.
When I came back, I needed to restart Codespaces
Which fired it back up
I was able to sync up the latest changes without issue. This time it was much faster
Prebuilds
If we want to speed up launching Codespaces, we can “prebuild” the container
I’ll click “Set up prebuild”
I could set it up on a branch as well as set failure notifications
However, this (could) incur charges so I will skip for now.
Secrets
As we see in our user settings, we can set secrets that will be exposed to any of our Codespaces environments
For an example, I’ll set a secret for the Jekyll blog repo
I can now see it as a secret set on that one repo
I can now see an existing Codespaces instance on my working branch
The question I had is “would it include my new secret?”
Indeed it did which is awesome. This means I could, if I wanted, pack something like a GCP credential or AWS secret if I needed to connect to a cloud provider without having to do something like gcloud auth login
interactively over and over.
Costs
The standard rate for Codespaces is a mere US$4/mo
This makes it a very compelling offering.
If we want to add Co-pilot for AI that is an additional $10
I mean, this is a pretty good deal when one thinks about it - i pay more for Disney/Hulu each month.
Today I “pay” for GCP Gemini Code Assist (aka Duet AI), however, to date GCP has yet to charge me for it.
I could write an entire blog comparing the two, but when just straight asking code questions, I find them very similar. Gemini often just steps in to offer suggestions and I noticed Copilot does a great job pulling in the local workspace files.
Project IDX vs Codespaces
Here we can see them side-by-side
The difference is that Github Codespaces, like Dev Containers, let’s me create and run the container behind the scenes and runs a hosted VS Code on a container in the cloud (assumably Azure).
ProjectIDX also runs VisualStudio Code in a container (assumably GCP), but doesn’t let’ me customize that container - though I can add in tools (like the Ruby bundler).
That said, ProjectIDX gives me Gemini Code Assist for free whereas I do not get Github Copilot (for free) in Codespaces.
Comparison in usage
Let’s look at a demo of firing up this blog with all three options.
The first, Google Project IDX:
Next, let’s look at using Dev Containers locally
And last, but not least, let’s check out Github Codespaces for the same repo
Summary
Comparing IDX, CodeSpaces and Dev Containers we can see some definate benefits and limitations.
While IDX is free, it’s really focused on Github, but can be worked around to use others. It gives us Gemini Code Assist, but at the free level which isn’t always the latest model and there definitely is no ‘we won’t use for training’ option (hey, cost of being free)
Dev Containers give us the most freedom, but they are local to our machine. That is, the last running dev container on my windows desktop really is not the same image as my laptop. They are based on the same dockerfile, but it’s a case of ‘save your work’. This has come up while creating blog entries and having WIP that wasn’t pushed. DevContainers give us no built in AI, but then again, we can choose whether to go for our own LLM or go with a major cloud provider like Google or Microsoft/Github.
Codespaces grants me that persisting containerized workspace that is hosted by Github/Microsoft so that ‘last’ image is saved and I can handle WIP. It is the fastest, at least in my testing, and is really reasonably priced. The only limitation is it’s tied to Github. To mitigate, one could use remote repo syncing to other systems, but for me, this is an acceptable limitation.