From 5e3140b1ff72fe3e6697b11d2d5780a8bcf5f3ef Mon Sep 17 00:00:00 2001 From: Dorival Pedroso Date: Tue, 2 Apr 2024 00:59:23 +0000 Subject: [PATCH] Update Docker Image (Ubuntu 22.04 + Go 1.22.1) --- Dockerfile | 2 +- zscripts/microsoft/common-debian.sh | 71 +++++++-------------- zscripts/microsoft/go-debian.sh | 96 ++++++++++++++++++++++------- 3 files changed, 98 insertions(+), 71 deletions(-) diff --git a/Dockerfile b/Dockerfile index 795cae22..629df41f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:20.04 +FROM ubuntu:22.04 # disable tzdata questions ENV DEBIAN_FRONTEND=noninteractive diff --git a/zscripts/microsoft/common-debian.sh b/zscripts/microsoft/common-debian.sh index dfbe6f6a..efdca351 100644 --- a/zscripts/microsoft/common-debian.sh +++ b/zscripts/microsoft/common-debian.sh @@ -21,7 +21,6 @@ ADD_NON_FREE_PACKAGES=${7:-"false"} SCRIPT_DIR="$(cd $(dirname "${BASH_SOURCE[0]}") && pwd)" MARKER_FILE="/usr/local/etc/vscode-dev-containers/common" - if [ "$(id -u)" -ne 0 ]; then echo -e 'Script must be run as root. Use sudo, su, or add "USER root" to your Dockerfile before running this script.' exit 1 @@ -78,6 +77,7 @@ if [ "${PACKAGES_ALREADY_INSTALLED}" != "true" ]; then package_list="apt-utils \ openssh-client \ gnupg2 \ + dirmngr \ iproute2 \ procps \ lsof \ @@ -102,7 +102,7 @@ if [ "${PACKAGES_ALREADY_INSTALLED}" != "true" ]; then libkrb5-3 \ libgssapi-krb5-2 \ libicu[0-9][0-9] \ - liblttng-ust0 \ + liblttng-ust[0-9] \ libstdc++6 \ zlib1g \ locales \ @@ -180,10 +180,12 @@ if [ "${LOCALE_ALREADY_SET}" != "true" ] && ! grep -o -E '^\s*en_US.UTF-8\s+UTF- fi # Create or update a non-root user to match UID/GID. +group_name="${USERNAME}" if id -u ${USERNAME} > /dev/null 2>&1; then # User exists, update if needed - if [ "${USER_GID}" != "automatic" ] && [ "$USER_GID" != "$(id -G $USERNAME)" ]; then - groupmod --gid $USER_GID $USERNAME + if [ "${USER_GID}" != "automatic" ] && [ "$USER_GID" != "$(id -g $USERNAME)" ]; then + group_name="$(id -gn $USERNAME)" + groupmod --gid $USER_GID ${group_name} usermod --gid $USER_GID $USERNAME fi if [ "${USER_UID}" != "automatic" ] && [ "$USER_UID" != "$(id -u $USERNAME)" ]; then @@ -203,7 +205,7 @@ else fi fi -# Add add sudo support for non-root user +# Add sudo support for non-root user if [ "${USERNAME}" != "root" ] && [ "${EXISTING_NON_ROOT_USER}" != "${USERNAME}" ]; then echo $USERNAME ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/$USERNAME chmod 0440 /etc/sudoers.d/$USERNAME @@ -285,9 +287,9 @@ cat << 'EOF' > /usr/local/bin/systemctl #!/bin/sh set -e if [ -d "/run/systemd/system" ]; then - exec /bin/systemctl/systemctl "$@" + exec /bin/systemctl "$@" else - echo '\n"systemd" is not running in this container due to its overhead.\nUse the "service" command to start services intead. e.g.: \n\nservice --status-all' + echo '\n"systemd" is not running in this container due to its overhead.\nUse the "service" command to start services instead. e.g.: \n\nservice --status-all' fi EOF chmod +x /usr/local/bin/systemctl @@ -302,13 +304,15 @@ __bash_prompt() { && [ ! -z "${GITHUB_USER}" ] && echo -n "\[\033[0;32m\]@${GITHUB_USER} " || echo -n "\[\033[0;32m\]\u " \ && [ "$XIT" -ne "0" ] && echo -n "\[\033[1;31m\]➜" || echo -n "\[\033[0m\]➜"`' local gitbranch='`\ - export BRANCH=$(git symbolic-ref --short HEAD 2>/dev/null || git rev-parse --short HEAD 2>/dev/null); \ - if [ "${BRANCH}" != "" ]; then \ - echo -n "\[\033[0;36m\](\[\033[1;31m\]${BRANCH}" \ - && if git ls-files --error-unmatch -m --directory --no-empty-directory -o --exclude-standard ":/*" > /dev/null 2>&1; then \ - echo -n " \[\033[1;33m\]✗"; \ - fi \ - && echo -n "\[\033[0;36m\]) "; \ + if [ "$(git config --get codespaces-theme.hide-status 2>/dev/null)" != 1 ]; then \ + export BRANCH=$(git symbolic-ref --short HEAD 2>/dev/null || git rev-parse --short HEAD 2>/dev/null); \ + if [ "${BRANCH}" != "" ]; then \ + echo -n "\[\033[0;36m\](\[\033[1;31m\]${BRANCH}" \ + && if git ls-files --error-unmatch -m --directory --no-empty-directory -o --exclude-standard ":/*" > /dev/null 2>&1; then \ + echo -n " \[\033[1;33m\]✗"; \ + fi \ + && echo -n "\[\033[0;36m\]) "; \ + fi; \ fi`' local lightblue='\[\033[1;34m\]' local removecolor='\[\033[0m\]' @@ -332,7 +336,8 @@ __zsh_prompt() { fi PROMPT="%{$fg[green]%}${prompt_username} %(?:%{$reset_color%}➜ :%{$fg_bold[red]%}➜ )" # User/exit code arrow PROMPT+='%{$fg_bold[blue]%}%(5~|%-1~/…/%3~|%4~)%{$reset_color%} ' # cwd - PROMPT+='$(git_prompt_info)%{$fg[white]%}$ %{$reset_color%}' # Git status + PROMPT+='$([ "$(git config --get codespaces-theme.hide-status 2>/dev/null)" != 1 ] && git_prompt_info)' # Git status + PROMPT+='%{$fg[white]%}$ %{$reset_color%}' unset -f __zsh_prompt } ZSH_THEME_GIT_PROMPT_PREFIX="%{$fg_bold[cyan]%}(%{$fg_bold[red]%}" @@ -344,24 +349,6 @@ __zsh_prompt EOF )" -# Add notice that Oh My Bash! has been removed from images and how to provide information on how to install manually -omb_readme="$(cat \ -<<'EOF' -"Oh My Bash!" has been removed from this image in favor of a simple shell prompt. If you -still wish to use it, remove "~/.oh-my-bash" and install it from: https://github.com/ohmybash/oh-my-bash -You may also want to consider "Bash-it" as an alternative: https://github.com/bash-it/bash-it -See here for infomation on adding it to your image or dotfiles: https://aka.ms/codespaces/omb-remove -EOF -)" -omb_stub="$(cat \ -<<'EOF' -#!/usr/bin/env bash -if [ -t 1 ]; then - cat $HOME/.oh-my-bash/README.md -fi -EOF -)" - # Add RC snippet and custom bash prompt if [ "${RC_SNIPPET_ALREADY_ADDED}" != "true" ]; then echo "${rc_snippet}" >> /etc/bash.bashrc @@ -371,24 +358,10 @@ if [ "${RC_SNIPPET_ALREADY_ADDED}" != "true" ]; then echo "${codespaces_bash}" >> "/root/.bashrc" echo 'export PROMPT_DIRTRIM=4' >> "/root/.bashrc" fi - chown ${USERNAME}:${USERNAME} "${user_rc_path}/.bashrc" + chown ${USERNAME}:${group_name} "${user_rc_path}/.bashrc" RC_SNIPPET_ALREADY_ADDED="true" fi -# Add stub for Oh My Bash! -if [ ! -d "${user_rc_path}/.oh-my-bash}" ] && [ "${INSTALL_OH_MYS}" = "true" ]; then - mkdir -p "${user_rc_path}/.oh-my-bash" "/root/.oh-my-bash" - echo "${omb_readme}" >> "${user_rc_path}/.oh-my-bash/README.md" - echo "${omb_stub}" >> "${user_rc_path}/.oh-my-bash/oh-my-bash.sh" - chmod +x "${user_rc_path}/.oh-my-bash/oh-my-bash.sh" - if [ "${USERNAME}" != "root" ]; then - echo "${omb_readme}" >> "/root/.oh-my-bash/README.md" - echo "${omb_stub}" >> "/root/.oh-my-bash/oh-my-bash.sh" - chmod +x "/root/.oh-my-bash/oh-my-bash.sh" - fi - chown -R "${USERNAME}:${USERNAME}" "${user_rc_path}/.oh-my-bash" -fi - # Optionally install and configure zsh and Oh My Zsh! if [ "${INSTALL_ZSH}" = "true" ]; then if ! type zsh > /dev/null 2>&1; then @@ -426,7 +399,7 @@ if [ "${INSTALL_ZSH}" = "true" ]; then # Copy to non-root user if one is specified if [ "${USERNAME}" != "root" ]; then cp -rf "${user_rc_file}" "${oh_my_install_dir}" /root - chown -R ${USERNAME}:${USERNAME} "${user_rc_path}" + chown -R ${USERNAME}:${group_name} "${user_rc_path}" fi fi fi diff --git a/zscripts/microsoft/go-debian.sh b/zscripts/microsoft/go-debian.sh index d93cc738..47ab299c 100644 --- a/zscripts/microsoft/go-debian.sh +++ b/zscripts/microsoft/go-debian.sh @@ -16,6 +16,9 @@ USERNAME=${4:-"automatic"} UPDATE_RC=${5:-"true"} INSTALL_GO_TOOLS=${6:-"true"} +# https://www.google.com/linuxrepositories/ +GO_GPG_KEY_URI="https://dl.google.com/linux/linux_signing_key.pub" + set -e if [ "$(id -u)" -ne 0 ]; then @@ -48,13 +51,14 @@ fi updaterc() { if [ "${UPDATE_RC}" = "true" ]; then echo "Updating /etc/bash.bashrc and /etc/zsh/zshrc..." - echo -e "$1" >> /etc/bash.bashrc - if [ -f "/etc/zsh/zshrc" ]; then + if [[ "$(cat /etc/bash.bashrc)" != *"$1"* ]]; then + echo -e "$1" >> /etc/bash.bashrc + fi + if [ -f "/etc/zsh/zshrc" ] && [[ "$(cat /etc/zsh/zshrc)" != *"$1"* ]]; then echo -e "$1" >> /etc/zsh/zshrc fi fi } - # Figure out correct version of a three part version number is not passed find_version_from_git_tags() { local variable_name=$1 @@ -89,6 +93,21 @@ find_version_from_git_tags() { echo "${variable_name}=${!variable_name}" } +# Get central common setting +get_common_setting() { + if [ "${common_settings_file_loaded}" != "true" ]; then + curl -sfL "https://aka.ms/vscode-dev-containers/script-library/settings.env" 2>/dev/null -o /tmp/vsdc-settings.env || echo "Could not download settings file. Skipping." + common_settings_file_loaded=true + fi + if [ -f "/tmp/vsdc-settings.env" ]; then + local multi_line="" + if [ "$2" = "true" ]; then multi_line="-z"; fi + local result="$(grep ${multi_line} -oP "$1=\"?\K[^\"]+" /tmp/vsdc-settings.env | tr -d '\0')" + if [ ! -z "${result}" ]; then declare -g $1="${result}"; fi + fi + echo "$1=${!1}" +} + # Function to run apt-get if needed apt_get_update_if_needed() { @@ -111,7 +130,7 @@ check_packages() { export DEBIAN_FRONTEND=noninteractive # Install curl, tar, git, other dependencies if missing -check_packages curl ca-certificates tar g++ gcc libc6-dev make pkg-config +check_packages curl ca-certificates gnupg2 tar g++ gcc libc6-dev make pkg-config if ! type git > /dev/null 2>&1; then apt_get_update_if_needed apt-get -y install --no-install-recommends git @@ -130,26 +149,61 @@ case $architecture in esac # Install Go -GO_INSTALL_SCRIPT="$(cat < /dev/null 2>&1; then + groupadd -r golang +fi +usermod -a -G golang "${USERNAME}" +mkdir -p "${TARGET_GOROOT}" "${TARGET_GOPATH}" +if [ "${TARGET_GO_VERSION}" != "none" ] && ! type go > /dev/null 2>&1; then + # Use a temporary locaiton for gpg keys to avoid polluting image + export GNUPGHOME="/tmp/tmp-gnupg" + mkdir -p ${GNUPGHOME} + chmod 700 ${GNUPGHOME} + get_common_setting GO_GPG_KEY_URI + curl -sSL -o /tmp/tmp-gnupg/golang_key "${GO_GPG_KEY_URI}" + gpg -q --import /tmp/tmp-gnupg/golang_key echo "Downloading Go ${TARGET_GO_VERSION}..." - curl -sSL -o /tmp/go.tar.gz "https://golang.org/dl/go${TARGET_GO_VERSION}.linux-${architecture}.tar.gz" + set +e + curl -fsSL -o /tmp/go.tar.gz "https://golang.org/dl/go${TARGET_GO_VERSION}.linux-${architecture}.tar.gz" + exit_code=$? + set -e + if [ "$exit_code" != "0" ]; then + echo "(!) Download failed." + # Try one break fix version number less if we get a failure. Use "set +e" since "set -e" can cause failures in valid scenarios. + set +e + major="$(echo "${TARGET_GO_VERSION}" | grep -oE '^[0-9]+' || echo '')" + minor="$(echo "${TARGET_GO_VERSION}" | grep -oP '^[0-9]+\.\K[0-9]+' || echo '')" + breakfix="$(echo "${TARGET_GO_VERSION}" | grep -oP '^[0-9]+\.[0-9]+\.\K[0-9]+' 2>/dev/null || echo '')" + # Handle Go's odd version pattern where "0" releases omit the last part + if [ "${breakfix}" = "" ] || [ "${breakfix}" = "0" ]; then + ((minor=minor-1)) + TARGET_GO_VERSION="${major}.${minor}" + # Look for latest version from previous minor release + find_version_from_git_tags TARGET_GO_VERSION "https://go.googlesource.com/go" "tags/go" "." "true" + else + ((breakfix=breakfix-1)) + if [ "${breakfix}" = "0" ]; then + TARGET_GO_VERSION="${major}.${minor}" + else + TARGET_GO_VERSION="${major}.${minor}.${breakfix}" + fi + fi + set -e + echo "Trying ${TARGET_GO_VERSION}..." + curl -fsSL -o /tmp/go.tar.gz "https://golang.org/dl/go${TARGET_GO_VERSION}.linux-${architecture}.tar.gz" + fi + curl -fsSL -o /tmp/go.tar.gz.asc "https://golang.org/dl/go${TARGET_GO_VERSION}.linux-${architecture}.tar.gz.asc" + gpg --verify /tmp/go.tar.gz.asc /tmp/go.tar.gz echo "Extracting Go ${TARGET_GO_VERSION}..." tar -xzf /tmp/go.tar.gz -C "${TARGET_GOROOT}" --strip-components=1 - rm -f /tmp/go.tar.gz -EOF -)" -if [ "${TARGET_GO_VERSION}" != "none" ] && ! type go > /dev/null 2>&1; then - mkdir -p "${TARGET_GOROOT}" "${TARGET_GOPATH}" - chown -R ${USERNAME} "${TARGET_GOROOT}" "${TARGET_GOPATH}" - su ${USERNAME} -c "${GO_INSTALL_SCRIPT}" + rm -rf /tmp/go.tar.gz /tmp/go.tar.gz.asc /tmp/tmp-gnupg else echo "Go already installed. Skipping." fi # Install Go tools that are isImportant && !replacedByGopls based on -# https://github.com/golang/vscode-go/blob/0ff533d408e4eb8ea54ce84d6efa8b2524d62873/src/goToolsInformation.ts -# Exception `dlv-dap` is a copy of github.com/go-delve/delve/cmd/dlv built from the master. +# https://github.com/golang/vscode-go/blob/v0.31.1/src/goToolsInformation.ts GO_TOOLS="\ golang.org/x/tools/gopls@latest \ honnef.co/go/tools/cmd/staticcheck@latest \ @@ -180,12 +234,7 @@ if [ "${INSTALL_GO_TOOLS}" = "true" ]; then # Move Go tools into path and clean up mv /tmp/gotools/bin/* ${TARGET_GOPATH}/bin/ - # install dlv-dap (dlv@master) - go ${go_install_command} -v github.com/go-delve/delve/cmd/dlv@master 2>&1 | tee -a /usr/local/etc/vscode-dev-containers/go.log - mv /tmp/gotools/bin/dlv ${TARGET_GOPATH}/bin/dlv-dap - rm -rf /tmp/gotools - chown -R ${USERNAME} "${TARGET_GOPATH}" fi # Add GOPATH variable and bin directory into PATH in bashrc/zshrc files (unless disabled) @@ -197,5 +246,10 @@ if [[ "\${PATH}" != *"\${GOROOT}/bin"* ]]; then export PATH="\${PATH}:\${GOROOT} EOF )" +chown -R :golang "${TARGET_GOROOT}" "${TARGET_GOPATH}" +chmod -R g+r+w "${TARGET_GOROOT}" "${TARGET_GOPATH}" +find "${TARGET_GOROOT}" -type d | xargs -n 1 chmod g+s +find "${TARGET_GOPATH}" -type d | xargs -n 1 chmod g+s + echo "Done!"