From 902e73888dee25c51ba61b833b81f7e8cb8b139d Mon Sep 17 00:00:00 2001 From: David Sargent Date: Fri, 11 Jul 2025 15:57:47 -0700 Subject: [PATCH 01/11] Update dev.sh to auto open the dev container Add run.sh --- dev.sh | 133 ++++++++++++++++++++++++++++++++++++++------------------- run.sh | 30 +++++++++++++ 2 files changed, 118 insertions(+), 45 deletions(-) create mode 100755 run.sh diff --git a/dev.sh b/dev.sh index a642766..e20b3c5 100755 --- a/dev.sh +++ b/dev.sh @@ -2,79 +2,109 @@ # # This script will start the dev container and open an interactive prompt into it. # +# cSpell:ignore set -euo pipefail IFS=$'\n\t' +# What quick two letter command do we want to use for this dev container / project. +# If this is empty, no command will be installed. +# Example: qq +docker_exec_command="" +# Name of the project folder +project_name="go-dev-container" +# Name of the container +container_name="${project_name}" +# User being created in the container +container_user="vscode" + +colors_sourced=false +# shellcheck source=/dev/null +if [ -f "usr/bin/lib/sh/colors.sh" ]; then + source "usr/bin/lib/sh/colors.sh" + colors_sourced=true +fi # shellcheck source=/dev/null -source "usr/bin/lib/sh/colors.sh" +if [ -f "lib/sh/colors.sh" ]; then + source "lib/sh/colors.sh" + colors_sourced=true +fi -# Check if user is using Docker Deskop for Windows or the native Docker Engine. -main() { - # What quick two letter command do we want to use for this dev container / project. - # If this is empty, no command will be installed. - # Example: qq - local docker_exec_command="gdc" - # Name of the project folder - local project_name="go-dev-container" - # Name of the container. This assumes you are using the same name as the project folder in the devcontainer.json file 'runargs' section. - local container_name="${project_name}" - # User being created in the container - local container_user="vscode" - - local is_windows_docker=true - if [[ $(docker version) != *"Server: Docker Desktop"* ]]; then - is_windows_docker=false - fi +if [ "$colors_sourced" = false ]; then + echo "Error: colors.sh not found. Please ensure it is availing in either the usr/bin/lib/sh or lib/sh directory." + exit 1 +fi +add_docker_exec_command() { if [[ -n "$docker_exec_command" ]]; then # Add ${docker_exec_command} command to open the dev container to a users .bashrc file if it is not already there. if ! grep -F "${docker_exec_command} ()" "${HOME}/.bashrc" >/dev/null 2>&1 && [ -f "${HOME}/.bashrc" ]; then - echo -e "${docker_exec_command} (){\n\ + echo -e "\n${docker_exec_command} (){\n\ docker exec -it -u ${container_user} -w /workspaces/${project_name} ${container_name} zsh\n\ }" >>"${HOME}/.bashrc" echo -e "${GREEN}Created \"${docker_exec_command}\" command in your ${HOME}/.bashrc file.${NC}" - # shellcheck source=/dev/null - source "${HOME}/.bashrc" + # Source .bashrc in a subshell to retain current environment variables + bash -c "source '${HOME}/.bashrc'" fi # Add ${docker_exec_command} command to open the dev container to a users .zshrc file if it is not already there. if ! grep -F "${docker_exec_command} ()" "${HOME}/.zshrc" >/dev/null 2>&1 && [ -f "${HOME}/.zshrc" ]; then - echo -e "${docker_exec_command} (){\n\ + echo -e "\n${docker_exec_command} (){\n\ docker exec -it -u ${container_user} -w /workspaces/${project_name} ${container_name} zsh\n\ }" >>"${HOME}/.zshrc" echo -e "${GREEN}Created \"${docker_exec_command}\" command in your ${HOME}/.zshrc file.${NC}" - # shellcheck source=/dev/null - source "${HOME}/.zshrc" + + # Source .zshrc in a subshell to retain current environment variables + zsh -c "source '${HOME}/.zshrc'" fi fi +} - # If the dev container is running, we assume VSCode is also running. If VSCode is not running, then open it. - if ! docker ps | grep ${container_name}; then - # Check if we are using "Docker for Windows". `devcontainer open` only works with "Docker for Windows". - if [[ "${is_windows_docker}" = true ]]; then - # Check if devcontainer cli is installed, if not let the user know and open VSCode with `code .`. - if ! which devcontainer; then - echo -e "${YELLOW}The 'devcontainer' command was not found." - echo "" - echo "Opening VS Code outside of the dev container." - echo "Once VS Code is open, press F1 or ctrl+shift+p to open the command pallet." - echo "Type 'devcontainer' then select 'Remote Containers: Install devcontainer CLI' from the list." - echo -e "Windows users will need to restart their computer for this to take effect.${NC}" - - code . - else - # Open the dev container in another shell so it doesn't hang on the command line for 45 seconds for some unknown reason. - (devcontainer open &) >/dev/null 2>&1 - fi - fi +open_vs_code() { + # check for dependencies + if ! command -v xxd &>/dev/null; then + echo "xxd command not found, install with" + echo "sudo apt install xxd" + exit 1 + fi + + DEVCONTAINER_JSON="$PWD/.devcontainer/devcontainer.json" + CODE_WS_FILE="$PWD/workspace.code-workspace" - # Looks like we are using native Docker on linux, so just do a `code .` as `devcontainer open` is not supported. - if [[ "${is_windows_docker}" = false ]]; then + if [ ! -f "$DEVCONTAINER_JSON" ]; then + # open code without container + if [ -f "$CODE_WS_FILE" ]; then + echo "Opening vscode workspace from $CODE_WS_FILE" + code $CODE_WS_FILE + else + echo "Opening vscode in current directory" code . fi + exit 0 + fi + + # open devcontainer + HOST_PATH=$(echo $(wslpath -w $PWD) | sed -e 's,\\,\\\\,g') + WORKSPACE="/workspaces/$(basename $PWD)" + + URI_SUFFIX= + if [ -f "$CODE_WS_FILE" ]; then + # open workspace file + URI_TYPE="--file-uri" + URI_SUFFIX="$WORKSPACE/$(basename $CODE_WS_FILE)" + echo "Opening vscode workspace file within devcontainer" + else + URI_TYPE="--folder-uri" + URI_SUFFIX="$WORKSPACE" + echo "Opening vscode within devcontainer" fi + URI="{\"hostPath\":\"$HOST_PATH\",\"configFile\":{\"\$mid\":1,\"path\":\"$DEVCONTAINER_JSON\",\"scheme\":\"vscode-fileHost\"}}" + URI_HEX=$(echo "${URI}" | xxd -c 0 -p) + code ${URI_TYPE}="vscode-remote://dev-container%2B${URI_HEX}${URI_SUFFIX}" & +} + +exec_into_container() { # Here we check if the dev container has started yet. # Wait a max of 600 seconds (10 minutes). local max_wait=600 @@ -115,9 +145,22 @@ main() { if [[ -n "$docker_exec_command" ]]; then echo -e "${BLUE}You can use the \"${docker_exec_command}\" command to exec into the dev container from another terminal.${NC}" fi + docker exec -u "${container_user}" -w /workspaces/${project_name} -it ${container_name} zsh } +# Check if user is using Docker Deskop for Windows or the native Docker Engine. +main() { + add_docker_exec_command + + # If the dev container is running, we assume VSCode is also running. If VSCode is not running, then open it. + if ! docker ps | grep ${container_name}; then + open_vs_code + fi + + exec_into_container +} + if ! (return 0 2>/dev/null); then (main "$@") fi diff --git a/run.sh b/run.sh new file mode 100755 index 0000000..97d5264 --- /dev/null +++ b/run.sh @@ -0,0 +1,30 @@ +#!/bin/bash +# +# This script will start the dev container outside of VSCode. +# +# cSpell:ignore + +set -euo pipefail +IFS=$'\n\t' + +main() { + local tag="$1" + if [ -z "$tag" ]; then + tag="latest" + fi + + # Name of the container + local container_name="ghcr.io/sarg3nt/go-dev-container:${tag}" + + # User being created in the container + local container_user="vscode" + + docker run --mount type=bind,source="$(pwd)",target=/workspaces/working \ + -w /workspaces/working -it --rm -u "${container_user}" \ + "${container_name}" zsh + +} + +if ! (return 0 2>/dev/null); then + (main "$@") +fi From 551425949b4255de6e5a7f569a059e0f4368bd70 Mon Sep 17 00:00:00 2001 From: David Sargent Date: Fri, 11 Jul 2025 15:58:56 -0700 Subject: [PATCH 02/11] Update several dependancies Upgrade to Rocky 10 --- .devcontainer/devcontainer.json | 4 ++-- .dockerignore | 1 + .github/workflows/dependency-review.yml | 4 ++-- .github/workflows/release-weekly.yml | 4 ++-- .github/workflows/release.yml | 4 ++-- .github/workflows/scorecard.yml | 6 +++--- .github/workflows/trivy.yml | 6 +++--- Dockerfile | 4 ++-- README.md | 24 +++++++++++++++--------- images/reopen-in-container.png | Bin 30772 -> 0 bytes 10 files changed, 32 insertions(+), 25 deletions(-) delete mode 100644 images/reopen-in-container.png diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 3d993bd..b8888e8 100755 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -8,8 +8,8 @@ "source=go-dev-container-bashhistory,target=/commandhistory,type=volume", "source=go-dev-container-plugins,target=/home/vscode/.vscode-server/extensions,type=volume", ///// The following should be the same for all dev containers using this image. The post_start_command.sh relies on these. - // Your host should have a .docker directory set up and you should be logged into any Artifactory - // repositories you need access to in the dev container. Logging into a repo inside the dev container will not stick. + // Your host should have a .docker directory set up and you should be logged into any repos you need access to. + // Logging into a repo inside the dev container will not stick. "source=${localEnv:HOME}/.docker,target=/home/vscode/.docker-localhost,type=bind", // If you will be working with Kubernetes you should have a configured kube config file in your .kube directory. "source=${localEnv:HOME}/.kube,target=/home/vscode/.kube-localhost,type=bind", diff --git a/.dockerignore b/.dockerignore index 1f57d97..eb159ca 100644 --- a/.dockerignore +++ b/.dockerignore @@ -4,4 +4,5 @@ cspell.sh dev.sh Dockerfile README.md +images/** run.sh \ No newline at end of file diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml index 03f9df8..7c74ab7 100644 --- a/.github/workflows/dependency-review.yml +++ b/.github/workflows/dependency-review.yml @@ -18,7 +18,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Harden Runner - uses: step-security/harden-runner@c6295a65d1254861815972266d5933fd6e532bdf + uses: step-security/harden-runner@6c439dc8bdf85cadbbce9ed30d1c7b959517bc49 with: disable-sudo: true egress-policy: block @@ -31,4 +31,4 @@ jobs: uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 - name: 'Dependency Review' - uses: actions/dependency-review-action@ce3cf9537a52e8119d91fd484ab5b8a807627bf8 + uses: actions/dependency-review-action@da24556b548a50705dd671f47852072ea4c105d9 diff --git a/.github/workflows/release-weekly.yml b/.github/workflows/release-weekly.yml index db0a29d..43ebab1 100644 --- a/.github/workflows/release-weekly.yml +++ b/.github/workflows/release-weekly.yml @@ -28,7 +28,7 @@ jobs: packages: write steps: - name: Harden Runner - uses: step-security/harden-runner@c6295a65d1254861815972266d5933fd6e532bdf + uses: step-security/harden-runner@6c439dc8bdf85cadbbce9ed30d1c7b959517bc49 with: disable-sudo: true egress-policy: audit @@ -56,7 +56,7 @@ jobs: - name: Build and Push Docker image id: build - uses: docker/build-push-action@471d1dc4e07e5cdedd4c2171150001c434f0b7a4 + uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 with: push: true tags: ${{ env.TAG_MAJOR }},${{ env.TAG_MINOR }},${{ env.TAG_PATCH }},${{ env.TAG_LATEST }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 01bf340..fb6a33e 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -21,7 +21,7 @@ jobs: steps: - name: Harden Runner - uses: step-security/harden-runner@c6295a65d1254861815972266d5933fd6e532bdf + uses: step-security/harden-runner@6c439dc8bdf85cadbbce9ed30d1c7b959517bc49 with: disable-sudo: true egress-policy: audit @@ -51,7 +51,7 @@ jobs: type=semver,pattern={{major}} - name: Build and Push Docker Image - uses: docker/build-push-action@471d1dc4e07e5cdedd4c2171150001c434f0b7a4 + uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 with: context: . push: true diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index 58848c2..48cea53 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -34,7 +34,7 @@ jobs: steps: - name: Harden Runner - uses: step-security/harden-runner@c6295a65d1254861815972266d5933fd6e532bdf + uses: step-security/harden-runner@6c439dc8bdf85cadbbce9ed30d1c7b959517bc49 with: disable-sudo: true egress-policy: block @@ -56,7 +56,7 @@ jobs: persist-credentials: false - name: "Run Analysis" - uses: ossf/scorecard-action@f49aabe0b5af0936a0987cfb85d86b75731b0186 + uses: ossf/scorecard-action@05b42c624433fc40578a4040d5cf5e36ddca8cde with: results_file: results.sarif results_format: sarif @@ -87,6 +87,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard (optional). # Commenting out will disable upload of results to your repo's Code Scanning dashboard - name: "Upload to Code-Scanning" - uses: github/codeql-action/upload-sarif@45775bd8235c68ba998cffa5171334d58593da47 + uses: github/codeql-action/upload-sarif@181d5eefc20863364f96762470ba6f862bdef56b with: sarif_file: results.sarif diff --git a/.github/workflows/trivy.yml b/.github/workflows/trivy.yml index 8bcf358..76dccff 100644 --- a/.github/workflows/trivy.yml +++ b/.github/workflows/trivy.yml @@ -41,7 +41,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Harden Runner - uses: step-security/harden-runner@c6295a65d1254861815972266d5933fd6e532bdf + uses: step-security/harden-runner@6c439dc8bdf85cadbbce9ed30d1c7b959517bc49 with: disable-sudo: true egress-policy: audit @@ -57,7 +57,7 @@ jobs: uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 - name: Build Docker Image - uses: docker/build-push-action@471d1dc4e07e5cdedd4c2171150001c434f0b7a4 + uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 with: push: false tags: ${{ env.REGISTRY }}/${{ env.REPOSITORY }}:${{ github.sha }} @@ -75,7 +75,7 @@ jobs: TRIVY_SKIP_JAVA_DB_UPDATE: true - name: Upload Trivy Results - uses: github/codeql-action/upload-sarif@45775bd8235c68ba998cffa5171334d58593da47 + uses: github/codeql-action/upload-sarif@181d5eefc20863364f96762470ba6f862bdef56b with: sarif_file: 'trivy-results.sarif' diff --git a/Dockerfile b/Dockerfile index 4c80225..6525347 100644 --- a/Dockerfile +++ b/Dockerfile @@ -9,10 +9,10 @@ # https://hub.docker.com/r/jdxcode/mise/tags # This is latest. -FROM jdxcode/mise@sha256:f6a96c629ed75c908540acda407194e45544d10e982744b1f02fe78892aaa804 AS mise +FROM jdxcode/mise@sha256:5a4eb0b7b6687f2f42ad24d37a50e605b6064d4cd051edb3286a30311539715c AS mise # https://hub.docker.com/r/rockylinux/rockylinux/tags -FROM rockylinux/rockylinux:9-ubil@sha256:a475955a742ea1e3f83d5765aec206804a714c9b654d17b691c9c17a5da02c8f AS final +FROM rockylinux/rockylinux:10-ubi@sha256:eca03145dd5e0b2a281eef164d391e4758b4a5962d29b688d15a72cef712fbb4 AS final LABEL org.opencontainers.image.source=https://github.com/sarg3nt/go-dev-container diff --git a/README.md b/README.md index 5243a44..ee61809 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ [![Dependabot Updates](https://github.com/sarg3nt/go-dev-container/actions/workflows/dependabot/dependabot-updates/badge.svg)](https://github.com/sarg3nt/go-dev-container/actions/workflows/dependabot/dependabot-updates) [![Dependency Review](https://github.com/sarg3nt/go-dev-container/actions/workflows/dependency-review.yml/badge.svg)](https://github.com/sarg3nt/go-dev-container/actions/workflows/dependency-review.yml) **** -A Go Dev Container using `mise` to install Go and other convenient tools. +A Go Dev Container using [mise](https://mise.jdx.dev/) to install Go and other convenient tools. `mise` can then be used to install various other Go versions as needed. - [Using the Go Dev Container](#using-the-go-dev-container) @@ -60,6 +60,9 @@ See the base `mise` config file at `home/vscode/.config/mise/config.toml` for al ## Using `mise` to Manage Go Versions +[mise](https://mise.jdx.dev/) is a development environment setup tool based on `asdf` but much faster. +See the [mise about](https://mise.jdx.dev/about.html) page for more information. + 1. Copy the `.mise.toml` file from the root of this repo to your project's root and modify it as needed. 1. The provided `.devcontainer` will automatically call `mise install` to install the custom versions of the applications. 1. After the container is started and you exec into it, `mise` will automatically install the app versions listed in the `.mise.toml` file. @@ -86,7 +89,8 @@ We've included an `install.sh` script to automate the process of copying the abo The script must be ran from the root of the `go-dev-container` project. -**Example:** `./install.sh ~/src/my-go-project` +> [!EXAMPLE] +> `./install.sh ~/src/my-go-project` ### Dev Container Setup @@ -99,11 +103,13 @@ Edit the `devcontainer.json` file to make the following changes. - Change `source=go-dev-container-bashhistory` to `source=-bashhistory` - Change `source=go-dev-container-plugins` to `source=-plugins` -> **NOTE:** You may be tempted to find and replace `go-dev-container` with the name of your project, however the `image` for the container is called `go-dev-container` so that would break things. If you want to do a controlled replacement you can, just be careful not to replace that one line. +> [!NOTE] +> You may be tempted to find and replace `go-dev-container` with the name of your project, however the `image` for the container is called `go-dev-container` so that would break things. If you want to do a controlled replacement you can, just be careful not to replace that one line. ### `dev.sh` -This script is used to easily start VSCode and exec into the Dev Container from the terminal that it is ran from. This frees the developer from having to use the VSCode integrated terminal. +This script is used to easily start VSCode and exec into the Dev Container from the terminal that it is ran from. +This frees the developer from having to use the VSCode integrated terminal. You can run `dev.sh` in multiple terminals once VSCode is running and the container has started to easily exec into it. @@ -111,11 +117,10 @@ You can run `dev.sh` in multiple terminals once VSCode is running and the contai - Change `project_name` to match the name of the repository. **Example:** If your root project repository is called `my-go-project` then set `project_name` to `my-go-project` -To use the `./dev.sh` script, simply run it, then when VS Code opens, there should be a prompt at the bottom right of the editor saying "Folder contains a Dev Container . . .". Click the "Reopen in Container" button and VS Code will open the dev container and attach to it. - -Reopen in Container +To use the `./dev.sh` script, simply run it. It will automatically open the dev container once VSCode starts. -> **NOTE:** If you have not opened the dev container before or if it has been updated it will download the container from Github, which can take a while. +> [!NOTE] +> If you have not opened the dev container before or if it has been updated it will download the container from Github, which can take a while. ## Starship @@ -169,7 +174,8 @@ The fonts must be installed in your operating system to be used in VSCode. If y 1. Expand `Text Editor` --> select `Font` 1. In the `Font Family` text box paste the following: - > **NOTE:** This assumes you chose "FiraCode NF", if not, replace the first font name with the name of the font you installed in Windows. + > [!NOTE] + > This assumes you chose "FiraCode NF", if not, replace the first font name with the name of the font you installed in Windows. ``` 'FiraCode NF', 'CaskaydiaCove NF', Consolas, 'Courier New', monospace diff --git a/images/reopen-in-container.png b/images/reopen-in-container.png deleted file mode 100644 index 231b27ed8c6d401c72616c51e8e1024d5b250eaa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 30772 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⪙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 z zIui*(q*jEi-_T;745rLiIKJiD1I1@i-B9gTFETkLrx+70r$IWrXcd_mcpRtIg@sF| zz>UCYmkzmcA-bA#BU)ZIYMq}!D6G5+etewyfpUX)zcN3!XeL)|XLxP}Sd>e7-G}I8 z*N_5Ysjvr`D);Acya~(Z2F<41A1Cu$(3t~-gBgH3o2CUs;;3=`J&kj(*(L>5+QK<} z6w&2{MX+vnYee&^#Cn#%a^Gw& zZUoCA>4b66HP+_hX5pB&faY_EtkNN4HuI9bVZ^D^D3v}-H{#$pa!_8P`2GkAprn<~rvAGG_z#D~2b;~)pTrtPf`-btg{ok+1*?~bn~f>dsAKd=$c zMQ3#Yv)9QO3f@u;ZQMK{wE3nYmyT*KOr(NqLdqhrwB)WFU77uvg@EP?m!U=#ODrb| z@ka?0&=k^|Vlo-8lgL8Kh%e-^@bH_#e%-AG=hDjVsW#h%fJ)TV*Dv)q*9Y!-eYwq@ zV598QxR2xYL*v`a8X-28BH?%!1B2TINJH)=vXAZujVklq*=ni%x~|VlWZ+lT2zd24 z%XuTT{)p|>C)R54=oo>~y9e8`1~i%M)L;S(0U+Py+wqG){WU5?`Ymchgw9lwOYIMI zQGt@ii2aJ@w8MSFF$I&b_$?wM`JNTu#ZQGhu*{4=G6f$QS5~y2BDdw4j0$RCC-HW; zH~(zu{?^;IgQquMIlhK)&RO@qiO$f%p1QWIoHr4iT^U*JZKfF6t$@i7Egya=Gv~rE z2a*9DfqB!P-UNs@c!f<`uaz;ge}_O`GcZK-U;a?P#ONA2V6QU&*4ecG#E}UxL%qZj zyp5GwSq2xuiq*Q>2LwI_A?}aiij3Ws?}ZQyxa#A#={#jl{N?mhv}-6pmugyENb|fi z3OZoW<$lx2^g9O(6%bML#YP&#?iF;qi}4c8vo!?0P>9D2w{=6u&@?S&e?6=aP?AnJsFOucIwr>N2Wp3Hn^;PcWEg^pwq>crs0 z0QvJ%)AQ}T^YbL6dUc1NJa)-=PRSsbp3G!S^7&AvVLl)_6;=54(!^`_SfYwy( z%#yQ>&9SuM3osV@8~uHbv(Aq~Di0mh-F#;+6PEkWtfM{4fX>R!bBB@pgGKno38wy| zslYEGP?1_uxq|RhhX>**Mn)`a$GY*6E=6?1M6XdJ7J#pTQ&0v1k;7N9&;a0G>{_&T=L7ZnBQJ%t=dIbownUY$Z!gKme>f_Uz<1N7Ij{rz zC;tm?kdcw+CRph+<3oMQ%|-3melBe>t7xo1%zAeKPUU+s+yDYaSB35C2#D!Op03Q= zfz^qlY~%}u@xZoxUDW3-4o)rirJ!$zcK=RVh0Ubu9UI;AN+#Rz=+gi;Isp?x`<*?K z2^ImmPpLZfTlV?s4bruOn{jA9n>Top2oKujIM$yM=$noP=5?MPzTCM_;$}yGFTm^e z-N@l?UhmYo>-Y1y`>Vj+bxQeED@y4|XWxW$z%NS53J5pdCz^3y_8ho(omj_FxS5vK zX}8Og%wjO4L^O&J&3t0PjPVq*tGzP}aZW`xQlK0zx2;il4?lsw{Q%ngD~k*Cuh-2V z7(B2fDCm?amO6Z;W$f|wVg{4IM4f7jY8*3(=sP*dX-E>qyA6wjBsCull+ME%%s(@OUJGagb(JND|W63O?5jt`HOem__y+5@}AM*EiVzaA$e zSLdME(Mva)>_|391ekimiF~C?`&l}@P-H)d)z`k>g$WgSIpk=Ty@=a3T2W5P*BZqP z&46D%YGHr0bAPILSxz|8o;cq}%I5#T%wsZneDLD=V=c$qnOEIA2Eg!;$cL#1BBjSrEHr_rYH)1OGG()Sw+=SSQ(S zMijn%qIz#CCflqRLhGXaNB52i^-eU;2nOANYw#S_@&3iK5S3)Cs&w_8|2jiSSlMyj zxqyGck!@5Q!pE5~nCcs`W@c3f-jY|I@N0-vi9q~~sE z#Yz4)=n?+x!MR#5m+x8Af4qV9Y=1|Ks6qmXboeg2aDQ?XB3FCpMyoluYpZANWyump z@P!7Xh9S94vSe6VBtPA$b5qY+IvHO*Q^d6u%w~7*0WLl=y9Qbg(S>^F1f=71_&kPW z^S7k0KLR>Ka`H(FIzeyv9cxM)JU0&3ee*k>*g8}cd0rAR>G_Uk%395dp0afJS^V04 zWsm2$<&$U()DuVTKm+qpv0pc@>8u@QcHE(xabZw$6bAiMq2?w%aM<*fhqdZV-4ZXT z^X;M)jX86}#`})&-CD5+C_ZGi`hn*3DDXUIP4ML=r3@KKkL=6q?T&-OKb;LPJy^Qq zJB3~`WQHJvUFv1&w71>sTYZp#M!$@Iv%9*x_8H?jZ*{*Hd5Iash*=Q3ZH!BjL%RK8 z=Uh}1mg8T)Z&W#*y7jpBP;0jlZgf4BRs+Xgl0)NPvj=Ta9{6;exJ#XjZhN-LVuJ}z z2O0Xko{@ZCd-mj;^?Tbw_r@YiVNbZ*g}Plhax`Fhf%|51>Y*~~Sc_-34tny<5%89Q zzeqACbaCR3MNdkT6HWpp$}37nx-w!UY{O*p(^9`Lw~~j!o8<_)ey42gR#g5%p2!!T zMns|)qF0{Xdd^=%j^@wOrMY`(yq;SYZW~*v=LBVx)_x{T6^1>W6H=4dsJC=aEX6ly z?HQFdwDVyZpX(&bbVvTkJk#+)ATI73o>+HS0hMehw~b+TQ8vg)QWh>IRKiEIScoj~x270i+Ga6e6O*=?FJ1l(OunUvWN0o?Pu+ZRFXvUwsK!XZ# z)0b0q^fEcfhQ%Zg4;1727DxL5LQFSAmS=j!MKY+phF^jmZ}|O$DyD7D(8k8Q?|Q=I z#faN|&H^tK9*$yfA0E#ZbpQTc+!UPHoTkold0@+ojiu>iqa7H@Mh@+q+wcpJp-m4? zO<~%k8-^OsR|af78{X$nz8cf3Ids|iNxa`QDr6IuE4@j7I@3~U@6c;X<(M4M9ygV} zcag^iRR&e^s!nJdJu<#Zsti!-nwz&Yd&qK22+cr-%6`LI+|mzyIAX&!0!P@cuX#P+ z8V-!vA<=~Hp=1ZGO>*J!{(Lwq{PNNl~)He-kE|K`;%BT%#5ZG#Vlbvm< zy4R?vs&uM}=y)5ed$lEn#CcgP26UWb5bNv%Nw>BUGkbLnA$8%GFnxfwP(l^)sH*IH z)eKzjN!=Z;ub^R9N&Z9W0b-b2;kj(tHxWsOb>G}?=a=lk15<7@fpPq>&{|lsH;%Ro zeBJo+f_Mp^{zy5Qu<7^V#YK7KxW|t*M5g;|f$w|#{%VF{UUuw0O2Ffj-&^-t?<0SP z%!=_k#S3*~dZAyKGD+L0TLe}dDcVj`#ICg!d_GV-7Q*?%*t`hQ-5-cP$lh8#Dvgiy zo+(;?Ut*n1?Dl66yd3uHakMyITo5$XO0SO_pm{bmF(6pErBugcYJhx1ycD#O? z+D|>-V$j6C0`p4SynLm9TpyR$YiYT~p;c`-3Z+paV?G5HE2nBq05XkUH0V503xQ;u+8 z6!FF4kpvXRxmXnO zzeM7;>be%qA_WKT@yhqzt!`cHQss-T{;z_{g*AL!fLxzxy1fmP^N!41fLKpDsD>QE zrutMSbAISVHZHs5mpe=^by)GU_{U7`$)<2DO!{_RgkDXps>FW1@ur(F#&YGzo<64( zNw8$1wxKzX22%}}U`O%HccqXlX?BfT*^empCD=BG>|0i7YGR~`RHPK6 zLCj+BpypPMWZ8qINA)-QDm5BeeS2X5dM2iUqvZe)xmZ*B>7UB{+bsp+xuK1n z8#M9xiKgbHw=E!Bu7Ku4z2)ap48QM&AacZWn>?uc&hJ425l%`hGA_BEJ*=&UMxIqk zgRI8>KV<{r1t8v!;LbE7`g12JS4fdygF@?YiCTF`BSsA7l@sk#!Lz4dQA zEf{;D1xZ>n7umQo^G5$gz@x}<=hS6$ox5K1iS3sqA;=sdF$I$UEp+MDu|Vd?8=VA& zW5Md$LGH&76%S#kW}D;iP225v>g0yzWPx!v$L-o$82qECqxZ1vrakxaXQsrczjGy0LhnEt_}A zCpuxu`kiSk;t)02wr6!KH7g~)>azmKSr3+LwJ;YVhGIsdUx5W;6uqP#i6cQT72TQY z@q>)NK^CbC8rt8v*gt~Z*?-u1--vN{M4cNLxDzNH9U9O3 zBAlLty1a&BOI%2L(zoYSK7+Z{zT_m7{m>htzB655Nmh0vUC{1G$Ru(vzG%WqxWyhI z>O4ZWw~%}?dlvxE-32CPf5E6orlZXiGgv>aWOWw+ZWF$EjOCufU&Qd(F<)G+)A$EH zypr1x*F0oi-#R`@q5iu2*x@8}Fld4$6zza6pxFK>&rcOv|EhCyrx322*0L+izvQq_ z$0%^eEEHCIuT+&IbapU>41S-lm&I8|lK!$&*2+(3{$2Z5A{qH=Cijet)0tgv2zRXA zro~KP9@WDsw`aUlzp$r&oG4-m&Xz_0Igomq-_SqKWhJEp@e9$Sz zsFFp8a@xk1k;#ZJ7{#GREa!PxIppR~${or*dE0T@T<3MMH0}Y$>sMY#KTjrzFXTD*!jl0kcWxw#KbP7S9}_!lW2v^NN%2rZEhGOpxOJ&UfI1jgcID=9)G&juO&c! zTwfi7&(aXG(RU8)ImNWb2~MSZMui^)k@f!8ZsE|WG&HF8X2&36Jgcq0fStmB3l{ia z|7`HWF-*gcrk$=T7v*h4gWUk{qHi3Ao>VhE`Ej1xKcVTa-&cFhap#ZEwFUIjOsMp( zI`C@d+$D4hTLC?vezkyZ8xc*@7fL{>V zQ~z6yA5|+&WM3)V|3IiuL73n{)#U6&^&BzS(2Du77kwxR%}8Rs1;&$F3w>Vs6QQJ} zht__RB)ml183>Iv3xwQ^f;(e3QN2epChSKy6e_7s(@3M}kBwQyIvS^DeUv+tytS=7 zAUn_8YhLWQ39p1YKns3DO|%1ub1V#M(mKaGGs1^jeK3ON@>av9SLRp- z<81s%a+z07tw7&rhkXP4>wQ3Vl?zd(bW~qvXx|S`2(@6`U;bk4j=Mfsf3!zQ5w~2W zhX@H1XEWXF^@B-@%@IYK7gwa@!j+15$w5WTbLT^wFBWT(;8mIW=G={!83AB-f0&11nr0i$ zS|=AK6ehUx!;7yo{IT9F>=Q6~mjWya2YCSh{K#J8$K*0z!xJbUvQPL(gu0Q+yy}#C z`3af%kJk#FZjveI$Rfbub%sTw#}-##3|Yx*J1rti zbl~keS+)|(O8z{gxrh6ew{1dBqS+jP$P4C&q4jP3P-^H*+P*q zklh6!D<$CG$Mte&@0uX{0XJ~H3PAPuvK5d#$_b2kRM`A+;<+jFgtC*Co0@0zq3)yya<>oS-m+B>HZGwY+&># zqmAd6YK1oWw{NIe2`A>)`|e+iE}ck);{5tWj(vqlGvW^>Y=XCF98I3H#82|PoO`(* z3Sj)06Z5&yz>fXpM!?SQ`ZiFeGa?+Rd=(PmY&wm|KniLohj7n>sP=| zXjW(%IS+*$*WADwk5ZkboBq(ts;L>B4Wuj~f!=iV+dZB0uX(frUOEMg;ii=dr_^ZD zS=EOdNGzjqX)&zilgYQ$(Q;WTO%7I&`jWOqnK2L28&?5o*Xu~~m|dKEo9SK}1%329 z^nEz&$tYhWT?cC0zbsj8V5scb0`J3{@m$_3syf~pj_6y!~;0Q0|-g6M^#RyC!Wk2dyhATM_llXiX`P%-M1eQV!ug+mY>`8nG#;DIL;cU zg>mqn3k&f{AT^*8YoOmX)#<4X)eq^8zANVD<=ebmvo|pQo>mvaKpkJ79%siLd3a9|FX=8B zpR&aXZ*MuQOc0f%fPl-Xo!1ak?qHl>-;NoWKT?iJGPu!x+g7WotASb$>OV_zAV}yA zPjhlE$avH^RJqpm7L?8BPTOou&yd9PqUi&dk(1{;W1~DT<;Kx$&ju7yCr`Mv3Ju)E zhzl&M9)FSu&#hvpsxcd%WVLVXJ0Xlhp0UAb%3}J@a)T6Gh`h|-9zCJmL9r?xwcbO?mt3O|tSFt?4_*89t&2|jb4W@i& z^lHT$AiqX5qzbnXzUXJ_8w)^I_<&i)+&E}*@>E-_UK{NDEQT-n;BeXGjQPbd;a!rF zD1}ZGUQ+9StT7{w!o9vy_)o%n3FI$rweHK9lYF(J1$9ltogFx?LB6!RP9f0TR_?ns z{7We3U>M!C$?S+qk4uFG_?UBtBnR|(Cp+xHwZ?N-^z2Kd1_Tc7pRS39TLUUmu&nXu z+=W1nuH9E{3=4JFoR3-i?p_s>Yui0AZY}q(jyr!PIlOrY9iP@Ggtc9=3R>}$!QjNN zhB2;BMc^uvVcy4fsXw~_wQVWzDa+%ot(`tET^a5dXR+t6)bD+WjH;wQ&Glk=hOLB2 zUe7!CtA+)%6C~7S8hvDdh9S~#Ht|)VvH5>^H*HInXH%3OekdE2cC+LGGIB$SmyqDu z&rWK(Q4P49eqytmnD@{XGIuo5BIVMw+FWyd?f*Q825SwH+}HBQyr1Wi+oIp56LI02 zH1@v}D7jUq+bndmTY_;zGL~5U152BTd)2CMg28LYP^^5 zxk>YFNKOROcJTL}{r9O{n#TR7NU`Ji;4X@?!Kr%4*;oH8r-WE%#BmPtshS)8-al7G z1Qz@@shge)R3J3EmNdV?!G6JJEYHCi8b70|1#3t1!>)7;zsl5BOTtTjSrB$mJtlavzAygcaLm)m{&75e$j zDq~Vu>>d42z=?DZJ5`wYY?U|;I^*UoU)dS- zqUI$$5XRem=xN+jUDYZD|Hy0j6q9Hy*0ju?l;esqdq}w=nKr-Nlz%ymv$8iwWnn?K zxzJA9Nt&AL+o@$7k*>;0%Im9Hr%LCq$w>3NKkPo`Ww_$GxgO%$yOSK2mF3Ny(}$dFm;*v;v%J8b z1`+V^__G1`H!YSRe6~Ccij0-j)ufCJtba1(QtWGshC(it3+n|u8FT;X5$G~XDXK}{ zj5W^{E%eS_?Yce?8S7QctjyOzCen!to?E{LDzJHLXq z>ooDd!S3pGzP6sCZMuwa_?_k$DKJ)lk#Emu{BQ)5AGb!vkZcb;1)a3qvTiGu4c763PV@Xz;9bU1TKO+Rro=Df6_X`di5VpBHq3pZFDX;M+`NFk9<1wcT>6Rf zPzw%{+k)Gk;I@HK;N}hA6eqx6qxa@L9D5U`p*&3W1jKv%*8yYp-&dSWa3s+8x<^=l z<0UVQ5IPL|yvi^W6@hF=n0>wx@|ci9k!GStWJ(#Eh9!fYqw$}vl|w4>+E^wpWz=JHOYy};>94$J-g|{DEuwyb z-Oq>FM@$Bk9RHfAUT_JM4dXF$N`3zH-?`mRyf}J)ID47bG?nM|W6)l=Kpv`Ddv6Z@ z$>lfi4mmuGsFqI?y;wTB6O?sty$^JkXXoZHQFvthV-63G`bx%IN;;YqG2iI%oo&c) zrT)_glYtb5fineki&|V8+~rGS>owm)qh}zT};hqXGxpKXO^)S zWE*8w)eo`AQR8)4#S1Ed19)}TD$o8y$r_iwlcr7n7kf!*sf>k1!Al>sc5lmE}!Y>1p!)fAEqu&C;?Bzjt2AoG*WPKfcP8-2WmbAG8mt`o+eMrf1UK zJ{EcWFNX8JtX@F)7v=wgIx_FeDApW9ZT_`@36cCe!|5vqY~Q(Q*#3(;pdb7{dyJwZ zVn72;EtvgpIGn>y-^;Gnu_u#d|HS7^)iJ{`ZaXV zW4O9MU-G#JxT{f|eI}KQqWe!P*@I~vjBK)pFh$S^^UnY&1onHZ=jxJdl?Rd}Vq1P` z{oG9&yZ9-h1ArN<#BOVyd3-Yfr*qKF96&o4*^QC^j4!B0c2L#nu_Wp&_&;OS{4R1= h+l6nN3LhTe_r|NX(^6CNrPD8h;yYEjN*Uwe{{uQbTv7l4 From e5ae9a52010711675ecb74bfa791a65d0a0f55a6 Mon Sep 17 00:00:00 2001 From: David Sargent Date: Fri, 11 Jul 2025 16:06:16 -0700 Subject: [PATCH 03/11] Revert example text --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index ee61809..b7cf5d9 100644 --- a/README.md +++ b/README.md @@ -89,7 +89,7 @@ We've included an `install.sh` script to automate the process of copying the abo The script must be ran from the root of the `go-dev-container` project. -> [!EXAMPLE] +> **Example:** > `./install.sh ~/src/my-go-project` ### Dev Container Setup @@ -119,7 +119,7 @@ You can run `dev.sh` in multiple terminals once VSCode is running and the contai To use the `./dev.sh` script, simply run it. It will automatically open the dev container once VSCode starts. -> [!NOTE] +> [!NOTE] > If you have not opened the dev container before or if it has been updated it will download the container from Github, which can take a while. ## Starship From a8ffcc773f43ed63283dfed26911750aaa564615 Mon Sep 17 00:00:00 2001 From: David Sargent Date: Fri, 11 Jul 2025 16:06:52 -0700 Subject: [PATCH 04/11] Attempt to fix non rendering NOTE field --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index b7cf5d9..2c3d86f 100644 --- a/README.md +++ b/README.md @@ -174,8 +174,8 @@ The fonts must be installed in your operating system to be used in VSCode. If y 1. Expand `Text Editor` --> select `Font` 1. In the `Font Family` text box paste the following: - > [!NOTE] - > This assumes you chose "FiraCode NF", if not, replace the first font name with the name of the font you installed in Windows. + > [!NOTE] + > This assumes you chose "FiraCode NF", if not, replace the first font name with the name of the font you installed in Windows. ``` 'FiraCode NF', 'CaskaydiaCove NF', Consolas, 'Courier New', monospace From b5576ae71666a8d98bd9c9ef241599af31db3c90 Mon Sep 17 00:00:00 2001 From: David Sargent Date: Fri, 11 Jul 2025 16:07:39 -0700 Subject: [PATCH 05/11] Test note --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2c3d86f..8ce0368 100644 --- a/README.md +++ b/README.md @@ -174,7 +174,7 @@ The fonts must be installed in your operating system to be used in VSCode. If y 1. Expand `Text Editor` --> select `Font` 1. In the `Font Family` text box paste the following: - > [!NOTE] + > [!NOTE] > This assumes you chose "FiraCode NF", if not, replace the first font name with the name of the font you installed in Windows. ``` From eb30813841e32d7dd2b5c97f8e52d551f7456107 Mon Sep 17 00:00:00 2001 From: David Sargent Date: Fri, 11 Jul 2025 16:07:54 -0700 Subject: [PATCH 06/11] Revert test --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8ce0368..2c3d86f 100644 --- a/README.md +++ b/README.md @@ -174,7 +174,7 @@ The fonts must be installed in your operating system to be used in VSCode. If y 1. Expand `Text Editor` --> select `Font` 1. In the `Font Family` text box paste the following: - > [!NOTE] + > [!NOTE] > This assumes you chose "FiraCode NF", if not, replace the first font name with the name of the font you installed in Windows. ``` From dc7dcfab7a09887591b37da9a7786db974513914 Mon Sep 17 00:00:00 2001 From: David Sargent Date: Fri, 11 Jul 2025 16:13:25 -0700 Subject: [PATCH 07/11] Rearrange some Readme.md text --- README.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 2c3d86f..c8d4426 100644 --- a/README.md +++ b/README.md @@ -173,13 +173,11 @@ The fonts must be installed in your operating system to be used in VSCode. If y 1. Select `File` --> `Preferences` --> `Settings` 1. Expand `Text Editor` --> select `Font` 1. In the `Font Family` text box paste the following: - - > [!NOTE] - > This assumes you chose "FiraCode NF", if not, replace the first font name with the name of the font you installed in Windows. - ``` 'FiraCode NF', 'CaskaydiaCove NF', Consolas, 'Courier New', monospace ``` + > [!NOTE] + > This assumes you chose "FiraCode NF", if not, replace the first font name with the name of the font you installed in Windows. ## Contributions From 87554d9454683b135bb91add8233c08f383beb85 Mon Sep 17 00:00:00 2001 From: David Sargent Date: Fri, 11 Jul 2025 16:14:16 -0700 Subject: [PATCH 08/11] Fix NOTE rendering --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index c8d4426..da692f7 100644 --- a/README.md +++ b/README.md @@ -176,8 +176,8 @@ The fonts must be installed in your operating system to be used in VSCode. If y ``` 'FiraCode NF', 'CaskaydiaCove NF', Consolas, 'Courier New', monospace ``` - > [!NOTE] - > This assumes you chose "FiraCode NF", if not, replace the first font name with the name of the font you installed in Windows. +> [!NOTE] +> This assumes you chose "FiraCode NF", if not, replace the first font name with the name of the font you installed in Windows. ## Contributions From 30309fdc8ebf4d5ce468f5db8d5eed268d16e056 Mon Sep 17 00:00:00 2001 From: David Sargent Date: Fri, 11 Jul 2025 16:19:03 -0700 Subject: [PATCH 09/11] Fix some spelling and grammatical errors in the README.md --- README.md | 72 +++++++++++++++++++++++++++---------------------------- 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/README.md b/README.md index da692f7..b16c0a5 100644 --- a/README.md +++ b/README.md @@ -67,27 +67,27 @@ See the [mise about](https://mise.jdx.dev/about.html) page for more information. 1. The provided `.devcontainer` will automatically call `mise install` to install the custom versions of the applications. 1. After the container is started and you exec into it, `mise` will automatically install the app versions listed in the `.mise.toml` file. 1. Other applications can also be installed by editing the `.mise.toml` file. - Run `mise help` for examples. + Run `mise help` for examples. ## Included `.devcontainer` Config This repository also includes an example on how to use the built Go dev container. -Do the following to use this example. +Do the following to use this example: -1. Clone down the repository. +1. Clone the repository: `git clone https://github.com/sarg3nt/go-dev-container.git` -2. Ensure your target project does not already have a `.devcontainer` directory. If it does, you will either need to rename it for testing or delete it. +2. Ensure your target project does not already have a `.devcontainer` directory. If it does, you will either need to rename it for testing or delete it. 3. Copy the `.devcontainer` directory to your project. 4. Copy the following files to the root of your project. - These are optional but encouraged. - - `.mise.toml`: The config file for managing specific versions of tooling you need for your Go project. - - `cspell.json`: The cspell config for spell checking in your project, edit to add any specific words that your project needs. - - `dev.sh`: Helps launch VSCode and exec into the dev container. This file needs some modification to use in your repository. See [dev.sh](#devsh) for instructions. + These are optional but encouraged: + - `.mise.toml`: The config file for managing specific versions of tooling you need for your Go project. + - `cspell.json`: The cspell config for spell checking in your project; edit to add any specific words that your project needs. + - `dev.sh`: Helps launch VSCode and exec into the dev container. This file needs some modification to use in your repository. See [`dev.sh`](#devsh) for instructions. -We've included an `install.sh` script to automate the process of copying the above files into your project directory. +We've included an `install.sh` script to automate the process of copying the above files into your project directory. -The script must be ran from the root of the `go-dev-container` project. +The script must be run from the root of the `go-dev-container` project. > **Example:** > `./install.sh ~/src/my-go-project` @@ -99,32 +99,32 @@ Once you've followed the above instructions to copy the needed files to your pro Edit the `devcontainer.json` file to make the following changes. - Change `name` from `go-dev-container` to the name of your project. -- Change `--name` in `runargs` from `go-dev-container` to the name of your project. +- Change `--name` in `runargs` from `go-dev-container` to the name of your project. - Change `source=go-dev-container-bashhistory` to `source=-bashhistory` - Change `source=go-dev-container-plugins` to `source=-plugins` > [!NOTE] -> You may be tempted to find and replace `go-dev-container` with the name of your project, however the `image` for the container is called `go-dev-container` so that would break things. If you want to do a controlled replacement you can, just be careful not to replace that one line. +> You may be tempted to find and replace `go-dev-container` with the name of your project; however, the `image` for the container is called `go-dev-container` so that would break things. If you want to do a controlled replacement you can, just be careful not to replace that one line. ### `dev.sh` -This script is used to easily start VSCode and exec into the Dev Container from the terminal that it is ran from. +This script is used to easily start VSCode and exec into the Dev Container from the terminal from which it is run. This frees the developer from having to use the VSCode integrated terminal. You can run `dev.sh` in multiple terminals once VSCode is running and the container has started to easily exec into it. -- Open the `dev.sh` file and set a `docker_exec_command` if desired, this is optional but if this repo is used a lot, it is a nice to have. This will create a command in the users `.bashrc` and `.zshrc` to quickly exec into this running dev container. +- Open the `dev.sh` file and set a `docker_exec_command` if desired; this is optional but if this repo is used frequently, it is a nice convenience. This will create a command in the user's `.bashrc` and `.zshrc` to quickly exec into this running dev container. - Change `project_name` to match the name of the repository. - **Example:** If your root project repository is called `my-go-project` then set `project_name` to `my-go-project` + **Example:** If your root project repository is called `my-go-project`, then set `project_name` to `my-go-project`. -To use the `./dev.sh` script, simply run it. It will automatically open the dev container once VSCode starts. +To use the `./dev.sh` script, simply run it. It will automatically open the dev container once VSCode starts. > [!NOTE] -> If you have not opened the dev container before or if it has been updated it will download the container from Github, which can take a while. +> If you have not opened the dev container before or if it has been updated, it will download the container from GitHub, which can take a while. -## Starship +## Starship -Starship is a custom Power Line command prompt we include. +Starship is a custom PowerLine command prompt we include. ![Starship Prompt](images/starship-prompt.png) @@ -134,33 +134,33 @@ See [Initial Workstation Setup](#initial-workstation-setup) for instructions on ## Initial Workstation Setup -Instructions to set up your workstation. -For more information on Dev Containers check out the [official docs](https://code.visualstudio.com/docs/devcontainers/containers). +Instructions to set up your workstation. +For more information on Dev Containers, check out the [official docs](https://code.visualstudio.com/docs/devcontainers/containers). ### WSL on Windows -1. If you will be building Docker containers in Windows, then install Docker Desktop for Windows following [Docker's instructions](https://docs.docker.com/desktop/install/windows-install/). If you do not need Docker for Windows support then you can [directly install Docker inside of Ubuntu](https://docs.docker.com/engine/install/ubuntu/) **AFTER** you install WSL and Ubuntu in the following steps. +1. If you will be building Docker containers in Windows, then install Docker Desktop for Windows following [Docker's instructions](https://docs.docker.com/desktop/install/windows-install/). If you do not need Docker for Windows support, then you can [directly install Docker inside of Ubuntu](https://docs.docker.com/engine/install/ubuntu/) **AFTER** you install WSL and Ubuntu in the following steps. 1. Install VS Code from the [Visual Studio Code website](https://code.visualstudio.com/download) or from the Microsoft Store. -1. Open VS Code and click on the "Extensions" button to the left. +1. Open VS Code and click on the "Extensions" button on the left. 1. Search for "Dev Containers" and install it. 1. Search for "WSL" and install it. -1. WSL is the Windows Subsystem for Linux and facilitates the use of a Linux distruction on Windows. -Follow the [Microsoft insructions](https://learn.microsoft.com/en-us/windows/wsl/install) to install WSL and a Linux distribution. Ubuntu is probably the most commong Linux OS used in WSL, but feel free to choose what you want. Note that the dev container itself uses Rocky Linux but this shouldn't matter to you during use. +1. WSL is the Windows Subsystem for Linux and facilitates the use of a Linux distribution on Windows. + Follow the [Microsoft instructions](https://learn.microsoft.com/en-us/windows/wsl/install) to install WSL and a Linux distribution. Ubuntu is probably the most common Linux OS used in WSL, but feel free to choose what you want. Note that the dev container itself uses Rocky Linux, but this shouldn't matter to you during use. ### Windows Font Install -To get the full functionality of font ligatures and icons for the Starship prompt you will need to install a [Nerd Font](https://www.nerdfonts.com/) from [Nerd Fonts Downloads](https://www.nerdfonts.com/font-downloads). If you skip this step the Dev Container terminal command line will look weird and not have icons thus making it harder to read. +To get the full functionality of font ligatures and icons for the Starship prompt, you will need to install a [Nerd Font](https://www.nerdfonts.com/) from [Nerd Fonts Downloads](https://www.nerdfonts.com/font-downloads). If you skip this step, the Dev Container terminal command line will look weird and not have icons, thus making it harder to read. -Many of us use [FiraCode Nerd Font](https://github.com/ryanoasis/nerd-fonts/releases/download/v3.0.2/FiraCode.zip) or [FiraMono Nerd Font](https://github.com/ryanoasis/nerd-fonts/releases/download/v3.0.2/FiraMono.zip) but you can [preview](https://www.programmingfonts.org/#firacode) any of the fonts and choose which one is best for you. +Many of us use [FiraCode Nerd Font](https://github.com/ryanoasis/nerd-fonts/releases/download/v3.0.2/FiraCode.zip) or [FiraMono Nerd Font](https://github.com/ryanoasis/nerd-fonts/releases/download/v3.0.2/FiraMono.zip), but you can [preview](https://www.programmingfonts.org/#firacode) any of the fonts and choose which one is best for you. -Download your chosen font and [install it in Windows](https://support.microsoft.com/en-us/office/add-a-font-b7c5f17c-4426-4b53-967f-455339c564c1) then proceed to the next step. +Download your chosen font and [install it in Windows](https://support.microsoft.com/en-us/office/add-a-font-b7c5f17c-4426-4b53-967f-455339c564c1), then proceed to the next step. #### Windows Terminal Font Setup -1. Open Windows Terminal, select the menu chevron to the right of the last tab and select settings. -1. On the left select `Profiles` --> `Defaults` -1. Under `Additional Settings` select `Appearance` -1. Under `Font Face` select the name of the font you downloaded, for example if you chose the "Firacode Nerd Font" then you'd choose `Firacode NF` You may need to check `Show all items` or restart Windows Terminal to see the new fonts. +1. Open Windows Terminal, select the menu chevron to the right of the last tab, and select settings. +1. On the left, select `Profiles` --> `Defaults` +1. Under `Additional Settings`, select `Appearance` +1. Under `Font Face`, select the name of the font you downloaded. For example, if you chose the "Firacode Nerd Font", then you'd choose `Firacode NF`. You may need to check `Show all items` or restart Windows Terminal to see the new fonts. ### Linux Font Install @@ -168,20 +168,20 @@ See [How to Install New (or Nerd) Fonts on Linux (Ultimate Guide)](https://linux ### Visual Studio Code Font Setup -The fonts must be installed in your operating system to be used in VSCode. If you are running VSCode on Windows and using it in Linux inside of WSL you would still install the fonts in Windows. +The fonts must be installed in your operating system to be used in VSCode. If you are running VSCode on Windows and using it in Linux inside of WSL, you would still install the fonts in Windows. 1. Select `File` --> `Preferences` --> `Settings` 1. Expand `Text Editor` --> select `Font` -1. In the `Font Family` text box paste the following: +1. In the `Font Family` text box, paste the following: ``` 'FiraCode NF', 'CaskaydiaCove NF', Consolas, 'Courier New', monospace ``` > [!NOTE] -> This assumes you chose "FiraCode NF", if not, replace the first font name with the name of the font you installed in Windows. +> This assumes you chose "FiraCode NF". If not, replace the first font name with the name of the font you installed in Windows. ## Contributions -Contributions are welcome via the standard Github Fork --> PR process. +Contributions are welcome via the standard GitHub Fork --> PR process. ## Author From 014c361d13104f1225df96b8e14682d833245f2e Mon Sep 17 00:00:00 2001 From: David Sargent Date: Fri, 11 Jul 2025 16:21:34 -0700 Subject: [PATCH 10/11] Improve linux font install instructions --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index b16c0a5..fa965e6 100644 --- a/README.md +++ b/README.md @@ -164,6 +164,8 @@ Download your chosen font and [install it in Windows](https://support.microsoft. ### Linux Font Install +This is not necessary when running VSCode in WSL on Windows, however if you are running things natively in Linux you will need to install the fonts in Linux. + See [How to Install New (or Nerd) Fonts on Linux (Ultimate Guide)](https://linuxtldr.com/install-fonts-on-linux/) for instructions. ### Visual Studio Code Font Setup From ecb80727e243133c2edbe63845ca1512adf9709e Mon Sep 17 00:00:00 2001 From: David Sargent Date: Fri, 11 Jul 2025 16:24:51 -0700 Subject: [PATCH 11/11] Update versions in pre commit config --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index d8562a4..36fbcee 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/gitleaks/gitleaks - rev: v8.16.3 + rev: v8.27.2 hooks: - id: gitleaks - repo: https://github.com/jumanjihouse/pre-commit-hooks @@ -8,7 +8,7 @@ repos: hooks: - id: shellcheck - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.4.0 + rev: v5.0.0 hooks: - id: end-of-file-fixer - id: trailing-whitespace