Skip to content
This repository was archived by the owner on Nov 30, 2023. It is now read-only.

Commit 79a7eb4

Browse files
authored
Add rust version selection, verify rustup-init before use (#1088)
1 parent c5c44d5 commit 79a7eb4

File tree

4 files changed

+125
-31
lines changed

4 files changed

+125
-31
lines changed

script-library/container-features/src/feature-scripts.env

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ _VSC_INSTALL_KUBECTL_HELM_MINIKUBE="kubectl-helm-debian.sh ${_BUILD_ARG_KUBECTL_
44
_VSC_INSTALL_TERRAFORM="terraform-debian.sh ${_BUILD_ARG_TERRAFORM_VERSION:-latest} ${_BUILD_ARG_TERRAFORM_TFLINT:-latest} ${_BUILD_ARG_TERRAFORM_TERRAGRUNT:-latest}"
55
_VSC_INSTALL_GIT="git-from-src-debian.sh ${_BUILD_ARG_GIT_VERSION:-latest} ${_BUILD_ARG_GIT_PPA:-true}"
66
_VSC_INSTALL_GIT_LFS=git-lfs-debian.sh
7-
_VSC_INSTALL_GITHUB_CLI=github-debian.sh ${_BUILD_ARG_GITHUB_CLI_VERSION:-latest}
7+
_VSC_INSTALL_GITHUB_CLI="github-debian.sh ${_BUILD_ARG_GITHUB_CLI_VERSION:-latest}"
88
_VSC_INSTALL_AZURE_CLI="azcli-debian.sh ${_BUILD_ARG_AZURE_CLI_VERSION:-latest}"
99
_VSC_INSTALL_SSH=sshd-debian.sh
1010
_VSC_INSTALL_HOMEBREW=homebrew-debian.sh
@@ -15,6 +15,6 @@ _VSC_INSTALL_JAVA="java-wrapper.sh ${_BUILD_ARG_JAVA_VERSION:-latest}"
1515
_VSC_INSTALL_GRADLE="gradle-debian.sh ${_BUILD_ARG_GRADLE_VERSION:-latest}"
1616
_VSC_INSTALL_MAVEN="maven-debian.sh ${_BUILD_ARG_MAVEN_VERSION:-latest}"
1717
_VSC_INSTALL_RUBY="ruby-debian.sh ${_BUILD_ARG_RUBY_VERSION:-latest}"
18-
_VSC_INSTALL_RUST=rust-debian.sh
19-
_VSC_INSTALL_POWERSHELL=powershell-debian.sh ${_BUILD_ARG_POWERSHELL_VERSION:-latest}
18+
_VSC_INSTALL_RUST="rust-debian.sh /usr/local/cargo /usr/local/rustup automatic true false ${_BUILD_ARG_RUST_VERSION:-latest} ${_BUILD_ARG_RUST_PROFILE:-minimal}"
19+
_VSC_INSTALL_POWERSHELL="powershell-debian.sh ${_BUILD_ARG_POWERSHELL_VERSION:-latest}"
2020
_VSC_INSTALL_DESKTOP_LITE=desktop-lite-debian.sh

script-library/container-features/src/features.json

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -904,9 +904,15 @@
904904
"options": {
905905
"version": {
906906
"type": "string",
907-
"enum": ["latest"],
907+
"proposed": ["latest", "1.55", "1.54", "1.53"],
908908
"default": "latest",
909-
"description": "Currently unused."
909+
"description": "Select or enter a version of Rust to install."
910+
},
911+
"profile": {
912+
"type": "string",
913+
"proposed": ["minimal", "default", "complete"],
914+
"default": "minimal",
915+
"description": "Select a rustup install profile."
910916
}
911917
},
912918
"init": true,
@@ -921,7 +927,7 @@
921927
"containerEnv": {
922928
"CARGO_HOME": "/usr/local/cargo",
923929
"RUSTUP_HOME": "/usr/local/rustup",
924-
"PATH": "${CARGO_HOME}/bin:${RUSTUP_HOME}/bin:${PATH}"
930+
"PATH": "${CARGO_HOME}/bin:${PATH}"
925931
},
926932
"capAdd": [ "SYS_PTRACE" ],
927933
"securityOpt": ["seccomp=unconfined"],

script-library/docs/rust.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
## Syntax
1212

1313
```text
14-
./rust-debian.sh [CARGO_HOME] [RUSTUP_HOME] [Non-root user] [Add to rc files flag] [Update Rust flag]
14+
./rust-debian.sh [CARGO_HOME] [RUSTUP_HOME] [Non-root user] [Add to rc files flag] [Update Rust flag] [Rust version] [rustup install profile]
1515
```
1616

1717
|Argument|Default|Description|
@@ -21,6 +21,8 @@
2121
|Non-root user|`automatic`| Specifies a user in the container other than root that will use Rust. A value of `automatic` will cause the script to check for a user called `vscode`, then `node`, `codespace`, and finally a user with a UID of `1000` before falling back to `root`. |
2222
| Add to rc files flag | `true` | A `true`/`false` flag that indicates whether the `PATH` should be updated and `CARGO_HOME` and `RUSTUP_HOME` set via `/etc/bash.bashrc` and `/etc/zsh/zshrc`. |
2323
| Update Rust flag | `true` | A `true`/`false` flag that indicates whether the script should update Rust (e.g. if it was already installed). |
24+
| Rust version | `latest` | Version of Rust to install. Partial version numbers are allowed (e.g. `1.55`). |
25+
| Rust install profile | `minimal` | The rustup [install profile](https://rust-lang.github.io/rustup/concepts/profiles.html) to use when installing Rust. |
2426

2527
## Usage
2628

@@ -33,7 +35,7 @@ Usage:
3335
```Dockerfile
3436
ENV CARGO_HOME=/usr/local/cargo \
3537
RUSTUP_HOME=/usr/local/rustup
36-
ENV PATH=${CARGO_HOME}/bin:${RUSTUP_HOME}/bin:${PATH}
38+
ENV PATH=${CARGO_HOME}/bin:${PATH}
3739
COPY library-scripts/rust-debian.sh /tmp/library-scripts/
3840
RUN apt-get update && bash /tmp/library-scripts/rust-debian.sh "${CARGO_HOME}" "${RUSTUP_HOME}"
3941
```

script-library/rust-debian.sh

Lines changed: 109 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,15 @@
77
# Docs: https://github.com/microsoft/vscode-dev-containers/blob/main/script-library/docs/rust.md
88
# Maintainer: The VS Code and Codespaces Teams
99
#
10-
# Syntax: ./rust-debian.sh [CARGO_HOME] [RUSTUP_HOME] [non-root user] [add CARGO/RUSTUP_HOME to rc files flag] [whether to update rust]
10+
# Syntax: ./rust-debian.sh [CARGO_HOME] [RUSTUP_HOME] [non-root user] [add CARGO/RUSTUP_HOME to rc files flag] [whether to update rust] [Rust version] [rustup install profile]
1111

1212
export CARGO_HOME=${1:-"/usr/local/cargo"}
1313
export RUSTUP_HOME=${2:-"/usr/local/rustup"}
1414
USERNAME=${3:-"automatic"}
1515
UPDATE_RC=${4:-"true"}
16-
UPDATE_RUST=${5:-"true"}
16+
UPDATE_RUST=${5:-"false"}
17+
RUST_VERSION=${6:-"latest"}
18+
RUSTUP_PROFILE=${7:-"minimal"}
1719

1820
set -e
1921

@@ -44,6 +46,55 @@ elif [ "${USERNAME}" = "none" ] || ! id -u ${USERNAME} > /dev/null 2>&1; then
4446
USERNAME=root
4547
fi
4648

49+
# Get central common setting
50+
get_common_setting() {
51+
if [ "${common_settings_file_loaded}" != "true" ]; then
52+
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."
53+
common_settings_file_loaded=true
54+
fi
55+
if [ -f "/tmp/vsdc-settings.env" ]; then
56+
local multi_line=""
57+
if [ "$2" = "true" ]; then multi_line="-z"; fi
58+
local result="$(grep ${multi_line} -oP "$1=\"?\K[^\"]+" /tmp/vsdc-settings.env | tr -d '\0')"
59+
if [ ! -z "${result}" ]; then declare -g $1="${result}"; fi
60+
fi
61+
echo "$1=${!1}"
62+
}
63+
64+
# Figure out correct version of a three part version number is not passed
65+
find_version_from_git_tags() {
66+
local variable_name=$1
67+
local requested_version=${!variable_name}
68+
if [ "${requested_version}" = "none" ]; then return; fi
69+
local repository=$2
70+
local prefix=${3:-"tags/v"}
71+
local separator=${4:-"."}
72+
local last_part_optional=${5:-"false"}
73+
if [ "$(echo "${requested_version}" | grep -o "." | wc -l)" != "2" ]; then
74+
local escaped_separator=${separator//./\\.}
75+
local last_part
76+
if [ "${last_part_optional}" = "true" ]; then
77+
last_part="(${escaped_separator}[0-9]+)?"
78+
else
79+
last_part="${escaped_separator}[0-9]+"
80+
fi
81+
local regex="${prefix}\\K[0-9]+${escaped_separator}[0-9]+${last_part}$"
82+
local version_list="$(git ls-remote --tags ${repository} | grep -oP "${regex}" | tr -d ' ' | tr "${separator}" "." | sort -rV)"
83+
if [ "${requested_version}" = "latest" ] || [ "${requested_version}" = "current" ] || [ "${requested_version}" = "lts" ]; then
84+
declare -g ${variable_name}="$(echo "${version_list}" | head -n 1)"
85+
else
86+
set +e
87+
declare -g ${variable_name}="$(echo "${version_list}" | grep -E -m 1 "^${requested_version//./\\.}([\\.\\s]|$)")"
88+
set -e
89+
fi
90+
fi
91+
if [ -z "${!variable_name}" ] || ! echo "${version_list}" | grep "^${!variable_name//./\\.}$" > /dev/null 2>&1; then
92+
echo -e "Invalid ${variable_name} value: ${requested_version}\nValid values:\n${version_list}" >&2
93+
exit 1
94+
fi
95+
echo "${variable_name}=${!variable_name}"
96+
}
97+
4798
updaterc() {
4899
if [ "${UPDATE_RC}" = "true" ]; then
49100
echo "Updating /etc/bash.bashrc and /etc/zsh/zshrc..."
@@ -70,44 +121,79 @@ apt_get_update_if_needed()
70121
export DEBIAN_FRONTEND=noninteractive
71122

72123
# Install curl, lldb, python3-minimal,libpython and rust dependencies if missing
73-
if ! dpkg -s curl ca-certificates lldb python3-minimal gcc libc6-dev > /dev/null 2>&1; then
124+
if ! dpkg -s curl ca-certificates gnupg2 lldb python3-minimal gcc libc6-dev > /dev/null 2>&1; then
74125
apt_get_update_if_needed
75126
apt-get -y install --no-install-recommends curl ca-certificates gcc libc6-dev
76127
apt-get -y install lldb python3-minimal libpython3.?
77128
fi
78129

130+
architecture="$(dpkg --print-architecture)"
131+
download_architecture="${architecture}"
132+
case ${download_architecture} in
133+
amd64)
134+
download_architecture="x86_64"
135+
;;
136+
arm64)
137+
download_architecture="aarch64"
138+
;;
139+
*) echo "(!) Architecture ${architecture} not supported."
140+
exit 1
141+
;;
142+
esac
143+
79144
# Install Rust
80-
if ! type rustup > /dev/null 2>&1; then
145+
umask 0002
146+
if ! cat /etc/group | grep -e "^rustlang:" > /dev/null 2>&1; then
147+
groupadd -r rustlang
148+
fi
149+
usermod -a -G rustlang "${USERNAME}"
150+
mkdir -p "${CARGO_HOME}" "${RUSTUP_HOME}"
151+
chown :rustlang "${RUSTUP_HOME}" "${CARGO_HOME}"
152+
chmod g+r+w+s "${RUSTUP_HOME}" "${CARGO_HOME}"
153+
154+
if [ "${RUST_VERSION}" = "none" ] || type rustup > /dev/null 2>&1; then
155+
echo "Rust already installed. Skipping..."
156+
else
157+
if [ "${RUST_VERSION}" != "latest" ] && [ "${RUST_VERSION}" != "lts" ] && [ "${RUST_VERSION}" != "stable" ]; then
158+
# Find version using soft match
159+
if ! type git > /dev/null 2>&1; then
160+
apt_get_update_if_needed
161+
apt-get -y install --no-install-recommends git
162+
fi
163+
find_version_from_git_tags RUST_VERSION "https://github.com/rust-lang/rust" "tags/"
164+
default_toolchain_arg="--default-toolchain ${RUST_VERSION}"
165+
fi
81166
echo "Installing Rust..."
82-
mkdir -p "${CARGO_HOME}" "${RUSTUP_HOME}"
83-
chown ${USERNAME} "${CARGO_HOME}" "${RUSTUP_HOME}"
84-
su ${USERNAME} -c "curl --tlsv1.2 https://sh.rustup.rs -sSf | bash -s -- -y --no-modify-path --profile minimal 2>&1"
85-
else
86-
echo "Rust already installed. Skipping."
167+
# Download and verify rustup sha
168+
mkdir -p /tmp/rustup/target/x86_64-unknown-linux-gnu/release/
169+
curl -sSL --proto '=https' --tlsv1.2 "https://static.rust-lang.org/rustup/dist/${download_architecture}-unknown-linux-gnu/rustup-init" -o /tmp/rustup/target/${download_architecture}-unknown-linux-gnu/release/rustup-init
170+
curl -sSL --proto '=https' --tlsv1.2 "https://static.rust-lang.org/rustup/dist/${download_architecture}-unknown-linux-gnu/rustup-init.sha256" -o /tmp/rustup/rustup-init.sha256
171+
cd /tmp/rustup
172+
sha256sum -c rustup-init.sha256
173+
chmod +x target/x86_64-unknown-linux-gnu/release/rustup-init
174+
target/x86_64-unknown-linux-gnu/release/rustup-init -y --no-modify-path --profile ${RUSTUP_PROFILE} ${default_toolchain_arg}
175+
cd ~
176+
rm -rf /tmp/rustup
87177
fi
88178

89-
su ${USERNAME} -c "$(cat << EOF
90-
set -e
91-
export PATH=${PATH}:${CARGO_HOME}/bin
92-
if [ "${UPDATE_RUST}" = "true" ]; then
93-
echo "Updating Rust..."
94-
rustup update 2>&1
95-
fi
96-
echo "Installing common Rust dependencies..."
97-
rustup component add rls rust-analysis rust-src rustfmt clippy 2>&1
98-
EOF
99-
)"
179+
export PATH=${CARGO_HOME}/bin:${PATH}
180+
if [ "${UPDATE_RUST}" = "true" ]; then
181+
echo "Updating Rust..."
182+
rustup update 2>&1
183+
fi
184+
echo "Installing common Rust dependencies..."
185+
rustup component add rls rust-analysis rust-src rustfmt clippy 2>&1
100186

101187
# Add CARGO_HOME, RUSTUP_HOME and bin directory into bashrc/zshrc files (unless disabled)
102-
updaterc "export CARGO_HOME=\"${CARGO_HOME}\"\nexport RUSTUP_HOME=\"${RUSTUP_HOME}\"\nexport PATH=\"\${CARGO_HOME}/bin:\${PATH}\""
103-
104188
updaterc "$(cat << EOF
105189
export RUSTUP_HOME="${RUSTUP_HOME}"
106190
export CARGO_HOME="${CARGO_HOME}"
107-
if [[ "\${PATH}" != *"\${CARGO_HOME}/bin"* ]]; then export PATH="\${PATH}:\${CARGO_HOME}/bin"; fi
191+
if [[ "\${PATH}" != *"\${CARGO_HOME}/bin"* ]]; then export PATH="\${CARGO_HOME}/bin:\${PATH}"; fi
108192
EOF
109193
)"
110194

195+
# Make files writable for rustlang group
196+
chmod -R g+r+w "${RUSTUP_HOME}" "${CARGO_HOME}"
111197

112198
echo "Done!"
113199

0 commit comments

Comments
 (0)