Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Node nvm fallback implement for zsh & bash #974

Closed
Show file tree
Hide file tree
Changes from 24 commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
abd9421
[Node]-NVM-Fallback scenario added for 2 way fallback
gauravsaini04 Apr 17, 2024
12cde0d
bumped patch version
gauravsaini04 Apr 17, 2024
b455092
Merge branch 'devcontainers:main' into node_nvm_2_way_fallback
gauravsaini04 May 2, 2024
3158fa1
Merge branch 'devcontainers:main' into node_nvm_2_way_fallback
gauravsaini04 May 8, 2024
a392392
Merge branch 'devcontainers:main' into node_nvm_2_way_fallback
gauravsaini04 May 13, 2024
ce64749
More Changes for zsh & bash functionality working alike
gauravsaini04 May 15, 2024
ad57f70
Merge remote-tracking branch 'refs/remotes/origin/node_nvm_2_way_fall…
gauravsaini04 May 15, 2024
97fc491
[node] - nvm - fallback implementation - both zsh & bash
gauravsaini04 May 16, 2024
5d67846
Merge branch 'devcontainers:main' into node_nvm_fallback_implement_zs…
gauravsaini04 May 17, 2024
58da3ff
changes after comments
gauravsaini04 May 17, 2024
e3767eb
minor change
gauravsaini04 May 17, 2024
76edc3d
another small change
gauravsaini04 May 17, 2024
6fa2789
jq installation failing in centos-7 - fix
gauravsaini04 May 17, 2024
4551675
linter failing fix on pr test runs
gauravsaini04 May 17, 2024
6a7bb95
fedora failing test - fix
gauravsaini04 May 17, 2024
136c3e8
change for linter
gauravsaini04 May 17, 2024
3816a38
misc change - for failing fedora for epel-release while centos needs …
gauravsaini04 May 17, 2024
4aaa7d8
Merge branch 'devcontainers:main' into node_nvm_fallback_implement_zs…
gauravsaini04 May 18, 2024
70c1504
Merge branch 'devcontainers:main' into node_nvm_fallback_implement_zs…
gauravsaini04 May 22, 2024
ee16e7c
Merge branch 'devcontainers:main' into node_nvm_fallback_implement_zs…
gauravsaini04 May 29, 2024
fc46f25
Merge branch 'devcontainers:main' into node_nvm_fallback_implement_zs…
gauravsaini04 May 30, 2024
3d74101
Merge branch 'devcontainers:main' into node_nvm_fallback_implement_zs…
gauravsaini04 May 30, 2024
ea9ed72
Merge branch 'devcontainers:main' into node_nvm_fallback_implement_zs…
gauravsaini04 May 31, 2024
a9907b3
Merge branch 'main' into node_nvm_fallback_implement_zsh_bash
samruddhikhandale Jun 5, 2024
7f32e35
changes as requested !
gauravsaini04 Jun 6, 2024
d1b617a
indentation removed as requested !
gauravsaini04 Jun 6, 2024
23b730e
change for jq failing to be found in centos-7 test case
gauravsaini04 Jun 7, 2024
f434cc2
Merge branch 'devcontainers:main' into node_nvm_fallback_implement_zs…
gauravsaini04 Jun 12, 2024
ffaa440
Merge branch 'devcontainers:main' into node_nvm_fallback_implement_zs…
gauravsaini04 Jun 18, 2024
ad65b40
Merge remote-tracking branch 'origin/main' into node_nvm_fallback_imp…
gauravsaini04 Jun 24, 2024
97cfc3e
Merge branch 'devcontainers:main' into node_nvm_fallback_implement_zs…
gauravsaini04 Jul 3, 2024
9d934ae
Merge branch 'main' into node_nvm_fallback_implement_zsh_bash
gauravsaini04 Jul 11, 2024
5e55f5d
Merge branch 'devcontainers:main' into node_nvm_fallback_implement_zs…
gauravsaini04 Jul 23, 2024
200cb65
Merge branch 'devcontainers:main' into node_nvm_fallback_implement_zs…
gauravsaini04 Jul 26, 2024
cbd7c8f
Merge branch 'devcontainers:main' into node_nvm_fallback_implement_zs…
gauravsaini04 Jul 29, 2024
5e1cf32
Merge branch 'devcontainers:main' into node_nvm_fallback_implement_zs…
gauravsaini04 Jul 30, 2024
d1f146e
Merge branch 'devcontainers:main' into node_nvm_fallback_implement_zs…
gauravsaini04 Aug 6, 2024
6068423
Merge branch 'devcontainers:main' into node_nvm_fallback_implement_zs…
gauravsaini04 Aug 8, 2024
21867b8
Merge branch 'devcontainers:main' into node_nvm_fallback_implement_zs…
gauravsaini04 Aug 13, 2024
a5988c5
Merge branch 'devcontainers:main' into node_nvm_fallback_implement_zs…
gauravsaini04 Aug 14, 2024
b5ee1c1
Merge branch 'devcontainers:main' into node_nvm_fallback_implement_zs…
gauravsaini04 Aug 16, 2024
8613da3
Merge branch 'devcontainers:main' into node_nvm_fallback_implement_zs…
gauravsaini04 Aug 17, 2024
a4bb5c2
Merge branch 'devcontainers:main' into node_nvm_fallback_implement_zs…
gauravsaini04 Aug 19, 2024
9ca9ff2
Merge branch 'devcontainers:main' into node_nvm_fallback_implement_zs…
gauravsaini04 Aug 20, 2024
fb1e45a
Merge branch 'devcontainers:main' into node_nvm_fallback_implement_zs…
gauravsaini04 Aug 27, 2024
9c22b5f
Merge branch 'devcontainers:main' into node_nvm_fallback_implement_zs…
gauravsaini04 Aug 28, 2024
0f185d4
Merge remote-tracking branch 'refs/remotes/origin/node_nvm_fallback_i…
gauravsaini04 Sep 9, 2024
6abbe72
Merge branch 'main' into node_nvm_fallback_implement_zsh_bash
gauravsaini04 Sep 9, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
127 changes: 127 additions & 0 deletions src/node/bash_install_node.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
#!/bin/bash
gauravsaini04 marked this conversation as resolved.
Show resolved Hide resolved

# Figure out correct version of a three part version number is not passed
find_version_from_git_tags() {
local variable_name=$1
local requested_version=""
requested_version=${!variable_name}
if [ "${requested_version}" = "none" ]; then return; fi
local repository=$2
local prefix=${3:-"tags/v"}
local separator=${4:-"."}
local last_part_optional=${5:-"false"}
if [ "$(echo "${requested_version}" | grep -o "." | wc -l)" != "2" ]; then
local escaped_separator=${separator//./\\.}
local last_part
if [ "${last_part_optional}" = "true" ]; then
last_part="(${escaped_separator}[0-9]+)?"
else
last_part="${escaped_separator}[0-9]+"
fi
local regex="${prefix}\\K[0-9]+${escaped_separator}[0-9]+${last_part}$"
local version_list="$(git ls-remote --tags ${repository} | grep -oP "${regex}" | tr -d ' ' | tr "${separator}" "." | sort -rV)"
if [ "${requested_version}" = "latest" ] || [ "${requested_version}" = "current" ] || [ "${requested_version}" = "lts" ]; then
declare -g ${variable_name}="$(echo "${version_list}" | head -n 1)"
else
set +e
declare -g ${variable_name}="$(echo "${version_list}" | grep -E -m 1 "^${requested_version//./\\.}([\\.\\s]|$)")"
set -e
fi
fi
if [ -z "${!variable_name}" ] || ! echo "${version_list}" | grep "^${!variable_name//./\\.}$" > /dev/null 2>&1; then
echo -e "Invalid ${variable_name} value: ${requested_version}\nValid values:\n${version_list}" >&2
exit 1
fi
echo "${variable_name}=${!variable_name}"
}

# Use semver logic to decrement a version number then look for the closest match
find_prev_version_from_git_tags() {
local variable_name=$1
local current_version=""
current_version=${!variable_name}
# local current_version=${!variable_name}
local repository=$2
# Normally a "v" is used before the version number, but support alternate cases
local prefix=${3:-"tags/v"}
# Some repositories use "_" instead of "." for version number part separation, support that
local separator=${4:-"."}
# Some tools release versions that omit the last digit (e.g. go)
local last_part_optional=${5:-"false"}
# Some repositories may have tags that include a suffix (e.g. actions/node-versions)
local version_suffix_regex=$6
# 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 "${current_version}" | grep -oE '^[0-9]+' || echo '')"
minor="$(echo "${current_version}" | grep -oP '^[0-9]+\.\K[0-9]+' || echo '')"
breakfix="$(echo "${current_version}" | grep -oP '^[0-9]+\.[0-9]+\.\K[0-9]+' 2>/dev/null || echo '')"

if [ "${minor}" = "0" ] && [ "${breakfix}" = "0" ]; then
((major=major-1))
declare -g ${variable_name}="${major}"
# Look for latest version from previous major release
find_version_from_git_tags "${variable_name}" "${repository}" "${prefix}" "${separator}" "${last_part_optional}"
# Handle situations like Go's odd version pattern where "0" releases omit the last part
elif [ "${breakfix}" = "" ] || [ "${breakfix}" = "0" ]; then
((minor=minor-1))
declare -g ${variable_name}="${major}.${minor}"
# Look for latest version from previous minor release
find_version_from_git_tags "${variable_name}" "${repository}" "${prefix}" "${separator}" "${last_part_optional}"
else
((breakfix=breakfix-1))
if [ "${breakfix}" = "0" ] && [ "${last_part_optional}" = "true" ]; then
declare -g ${variable_name}="${major}.${minor}"
else
declare -g ${variable_name}="${major}.${minor}.${breakfix}"
fi
fi
set -e
}

# Function to fetch the version released prior to the latest version
get_previous_version() {
local url=$1
local repo_url=$2
local variable_name=$3
local prev_version=""
prev_version=${!variable_name#v}

output=$(curl -s "$repo_url");

message=$(echo "$output" | jq -r '.message')
if [[ $message == "API rate limit exceeded"* ]]; then
echo -e "\nAn attempt to find latest version using GitHub Api Failed... \nReason: ${message}"
echo -e "\nAttempting to find latest version using GitHub tags."
find_prev_version_from_git_tags prev_version "$url" "tags/v"
declare -g "${variable_name}=${prev_version}"
else
echo -e "\nAttempting to find latest version using GitHub Api."
version=$(echo "$output" | jq -r '.tag_name')
echo "${variable_name}=variable_name from get_previous_version"
echo "${version}=version from get_previous_version"
declare -g "${variable_name}=${version#v}"
fi
echo "${variable_name}=${!variable_name}"
}


get_github_api_repo_url() {
local url=$1
echo "${url/https:\/\/github.com/https:\/\/api.github.com\/repos}/releases/latest"
}

nvm_url="https://github.com/nvm-sh/nvm"

find_version_from_git_tags NVM_VERSION $nvm_url

repo_url=$(get_github_api_repo_url "${nvm_url}")

install_nvm() {
curl -so- "https://raw.githubusercontent.com/nvm-sh/nvm/v${NVM_VERSION}/install.sh" | bash || {
get_previous_version "${nvm_url}" "${repo_url}" NVM_VERSION
echo \"Previous nvm version=$NVM_VERSION\"
curl -so- "https://raw.githubusercontent.com/nvm-sh/nvm/v${NVM_VERSION}/install.sh" | bash
}
}

install_nvm
2 changes: 1 addition & 1 deletion src/node/devcontainer-feature.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"id": "node",
"version": "1.4.1",
"version": "1.4.2",
"name": "Node.js (via nvm), yarn and pnpm",
"documentationURL": "https://github.com/devcontainers/features/tree/main/src/node",
"description": "Installs Node.js, nvm, yarn, pnpm, and needed dependencies.",
Expand Down
71 changes: 21 additions & 50 deletions src/node/install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -147,46 +147,17 @@ check_packages() {
rhel)
if ! rpm -q "$@" > /dev/null 2>&1; then
pkg_mgr_update
if [ "${ID}" = "centos" ]; then
gauravsaini04 marked this conversation as resolved.
Show resolved Hide resolved
if [ "$*" = "jq" ]; then
${INSTALL_CMD} epel-release
fi
fi
${INSTALL_CMD} "$@"
fi
;;
esac
}

# Figure out correct version of a three part version number is not passed
find_version_from_git_tags() {
local variable_name=$1
local requested_version=${!variable_name}
if [ "${requested_version}" = "none" ]; then return; fi
local repository=$2
local prefix=${3:-"tags/v"}
local separator=${4:-"."}
local last_part_optional=${5:-"false"}
if [ "$(echo "${requested_version}" | grep -o "." | wc -l)" != "2" ]; then
local escaped_separator=${separator//./\\.}
local last_part
if [ "${last_part_optional}" = "true" ]; then
last_part="(${escaped_separator}[0-9]+)?"
else
last_part="${escaped_separator}[0-9]+"
fi
local regex="${prefix}\\K[0-9]+${escaped_separator}[0-9]+${last_part}$"
local version_list="$(git ls-remote --tags ${repository} | grep -oP "${regex}" | tr -d ' ' | tr "${separator}" "." | sort -rV)"
if [ "${requested_version}" = "latest" ] || [ "${requested_version}" = "current" ] || [ "${requested_version}" = "lts" ]; then
declare -g ${variable_name}="$(echo "${version_list}" | head -n 1)"
else
set +e
declare -g ${variable_name}="$(echo "${version_list}" | grep -E -m 1 "^${requested_version//./\\.}([\\.\\s]|$)")"
set -e
fi
fi
if [ -z "${!variable_name}" ] || ! echo "${version_list}" | grep "^${!variable_name//./\\.}$" > /dev/null 2>&1; then
echo -e "Invalid ${variable_name} value: ${requested_version}\nValid values:\n${version_list}" >&2
exit 1
fi
echo "${variable_name}=${!variable_name}"
}

install_yarn() {
if [ "${ADJUSTED_ID}" = "debian" ]; then
# for backward compatiblity with existing devcontainer features, install yarn
Expand Down Expand Up @@ -229,6 +200,10 @@ if ! type awk >/dev/null 2>&1; then
check_packages awk
fi

if ! type jq >/dev/null 2>&1; then
check_packages jq
fi

# Determine the appropriate non-root user
if [ "${USERNAME}" = "auto" ] || [ "${USERNAME}" = "automatic" ]; then
USERNAME=""
Expand Down Expand Up @@ -285,23 +260,17 @@ elif [ "${NODE_VERSION}" = "latest" ]; then
export NODE_VERSION="node"
fi

find_version_from_git_tags NVM_VERSION "https://github.com/nvm-sh/nvm"

# Install snipppet that we will run as the user
nvm_install_snippet="$(cat << EOF
set -e
umask 0002
# Do not update profile - we'll do this manually
export PROFILE=/dev/null
curl -so- "https://raw.githubusercontent.com/nvm-sh/nvm/v${NVM_VERSION}/install.sh" | bash || {
PREV_NVM_VERSION=$(curl -s https://api.github.com/repos/nvm-sh/nvm/releases/latest | grep '"tag_name"' | sed -E 's/.*"([^"]+)".*/\1/')
curl -so- "https://raw.githubusercontent.com/nvm-sh/nvm/\${PREV_NVM_VERSION}/install.sh" | bash
NVM_VERSION="\${PREV_NVM_VERSION}"
}
source "${NVM_DIR}/nvm.sh"
if [ "${NODE_VERSION}" != "" ]; then
nvm alias default "${NODE_VERSION}"
fi
set -e
umask 0002
# Do not update profile - we'll do this manually
export PROFILE=/dev/null
./bash_install_node.sh
source "${NVM_DIR}/nvm.sh"
if [ "${NODE_VERSION}" != "" ]; then
nvm alias default "${NODE_VERSION}"
fi
gauravsaini04 marked this conversation as resolved.
Show resolved Hide resolved
EOF
)"

Expand Down Expand Up @@ -331,7 +300,8 @@ if [ ! -d "${NVM_DIR}" ]; then
mkdir -p "${NVM_DIR}"
chown "${USERNAME}:nvm" "${NVM_DIR}"
chmod g+rws "${NVM_DIR}"
su ${USERNAME} -c "${nvm_install_snippet}" 2>&1

su ${USERNAME} -c "source ./bash_install_node.sh && ${nvm_install_snippet}" 2>&1
# Update rc files
if [ "${UPDATE_RC}" = "true" ]; then
updaterc "${nvm_rc_snippet}"
Expand All @@ -343,6 +313,7 @@ else
fi
fi


gauravsaini04 marked this conversation as resolved.
Show resolved Hide resolved
# Possibly install yarn (puts yarn in per-Node install on RHEL, uses system yarn on Debian)
install_yarn

Expand Down
Loading
Loading