├── data ├── user │ ├── .gemrc │ └── .bashrc.local ├── system │ └── profile.d │ │ └── rbenv-init.sh └── temp │ ├── summary.sh │ ├── setup.sh │ ├── rbenv-install.sh │ └── nvm-install.sh ├── .dockerignore ├── docker-entrypoint.sh ├── README.md ├── test └── npm-install.sh ├── .gitlab └── merge_request_templates │ └── Feature.md ├── .circleci ├── run-build-locally.sh └── config.yml ├── LICENSE ├── .gitlab-ci.yml ├── .gitignore └── Dockerfile /data/user/.gemrc: -------------------------------------------------------------------------------- 1 | gem: --no-rdoc --no-ri --no-document 2 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | Dockerfile 2 | wrapdocker 3 | var-lib/ 4 | docker-static/ 5 | -------------------------------------------------------------------------------- /docker-entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | echo "RUNNING AS USER: $(whoami)" 4 | echo "WORKING DIRECTORY: $(pwd)" 5 | exec "$@" 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Docker Image: `pddstudio/dindwnvm` 2 | 3 | > Docker in Docker with node v10 & latest npm 4 | 5 | ![build](https://gitlab.com/pddstudio/dindwnvm/badges/develop/build.svg) 6 | 7 | ## General 8 | 9 | This docker image builds on top of `gitlab/dind` (base image: Ubuntu 14.04) -------------------------------------------------------------------------------- /test/npm-install.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | TARGET_PACKAGES=(npm @angular/cli hotel) 4 | 5 | install() { 6 | for pkg in $TARGET_PACKAGES 7 | do 8 | bash -l -c "npm install --global $pkg" 9 | echo "Command returned with exit code: $?" 10 | done 11 | } 12 | 13 | install 14 | -------------------------------------------------------------------------------- /data/user/.bashrc.local: -------------------------------------------------------------------------------- 1 | # bashrc file - sourced when starting shell session 2 | 3 | # append rbenv to path & initialize it 4 | export PATH="$HOME/.rbenv/bin:$PATH" 5 | eval "$(rbenv init -)" 6 | 7 | # initialize nvm 8 | export NVM_DIR="$HOME/.nvm" 9 | [ -s "$NVM_DIR/nvm.sh" ] 10 | . "$NVM_DIR/nvm.sh" 11 | -------------------------------------------------------------------------------- /data/system/profile.d/rbenv-init.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Startup script to initialize rbenv. 4 | # This file will be loaded by the environment via profile & profile.d scripts. 5 | # This file is expected be placed in /etc/profile.d/ 6 | echo rbenv-init: Running as $(whoami) with home directory $HOME 7 | source $HOME/.bashrc.local 8 | eval "$(. $HOME/.bashrc && rbenv init -)" -------------------------------------------------------------------------------- /.gitlab/merge_request_templates/Feature.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | ## What does this feature do? 6 | 7 | 8 | 9 | ## Related issues 10 | 11 | 12 | 13 | Closes 14 | 15 | /label ~Feature 16 | -------------------------------------------------------------------------------- /data/temp/summary.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | source_rc() { 4 | source $HOME/.bashrc 5 | } 6 | 7 | print_summary() { 8 | echo "Installation complete!" 9 | echo "==== BEGIN ENV SETUP ====" 10 | echo "docker Version: $(docker version)" 11 | echo "docker-compose Version: $(docker-compose version)" 12 | echo "docker-manifest Verion: $(docker-manifest version)" 13 | echo "node Version: $(node -v)" 14 | echo "npm Version: $(npm -v)" 15 | echo "ruby Version: $(ruby -v)" 16 | echo "rbenv Version: $(rbenv -v)" 17 | echo "gem Version: $(gem -v)" 18 | echo "bundler Version: $(bundle -v)" 19 | echo "==== END ENV SETUP ====" 20 | } 21 | 22 | source_rc 23 | print_summary 24 | exit 0 -------------------------------------------------------------------------------- /.circleci/run-build-locally.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | prepare() { 4 | if [ -f "./prepare-env.sh" ]; then 5 | source ./prepare-env.sh 6 | else 7 | echo "Environment setup script is missing. Abort." 8 | exit 1 9 | fi 10 | } 11 | 12 | send_curl() { 13 | curl --user ${CIRCLE_TOKEN}: \ 14 | --request POST \ 15 | --form revision=$1\ 16 | --form config=@config.yml \ 17 | --form notify=false \ 18 | https://circleci.com/api/v1.1/project/github/pddstudio/dindwcbt/tree/develop 19 | } 20 | 21 | main() { 22 | prepare 23 | case "$1" in 24 | commit | c | hash) 25 | echo 'Running' 26 | shift 27 | send_curl "$@" 28 | ;; 29 | *) 30 | echo "Usage: $0 { commit | c | hash } commit_hash" 31 | ;; 32 | esac 33 | } 34 | 35 | main "$@" 36 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | License Information: dindwnvm 2 | 3 | Copyright 2018 Patrick Jung 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 10 | -------------------------------------------------------------------------------- /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | jobs: 3 | build: 4 | machine: 5 | enabled: true 6 | image: pddstudio/dindwnvm:latest 7 | working_directory: /home/appuser 8 | steps: 9 | - checkout 10 | - run: 11 | name: Build Docker Image 12 | shell: /bin/bash 13 | command: docker build -t pddstudio/dindwcbt:$CIRCLE_BRANCH . 14 | - run: 15 | name: Test Docker Image 16 | shell: /bin/bash 17 | command: | 18 | docker create -v /home/appuser/build/npm --name configs alpine:3.4 /bin/true 19 | docker cp test/npm-install.sh configs:/home/appuser/build/npm 20 | docker run -d --name dindwcbt --volumes-from configs pddstudio/dindwcbt:$CIRCLE_BRANCH /bin/bash 21 | docker exec dindwcbt bash -l -c "chmod a+x $HOME/build/npm/npm-install.sh; $HOME/build/npm/npm-install.sh;" 22 | 23 | 24 | workflows: 25 | version: 2 26 | commit-workflow: 27 | jobs: 28 | - build 29 | scheduled-workflow: 30 | triggers: 31 | - schedule: 32 | cron: "0 0 * * *" 33 | filters: 34 | branches: 35 | only: develop 36 | jobs: 37 | - build -------------------------------------------------------------------------------- /.gitlab-ci.yml: -------------------------------------------------------------------------------- 1 | image: docker:stable 2 | 3 | variables: 4 | BASE_TAG: pddstudio/dindwnvm 5 | IMAGE_TAG: develop 6 | DOCKER_IMAGE_BUILD: $CI_REGISTRY_IMAGE 7 | 8 | services: 9 | - docker:dind 10 | 11 | stages: 12 | - build 13 | 14 | build-image: 15 | stage: build 16 | before_script: 17 | - echo Building and Pushing public page image to registry ${CI_REGISTRY} 18 | - docker login -u gitlab-ci-token -p $CI_JOB_TOKEN $CI_REGISTRY 19 | script: 20 | - docker build --pull -t $DOCKER_IMAGE_BUILD:$IMAGE_TAG -t $BASE_TAG:$IMAGE_TAG . 21 | - docker push $DOCKER_IMAGE_BUILD:$IMAGE_TAG 22 | after_script: 23 | - docker logout 24 | allow_failure: false 25 | only: 26 | - develop 27 | - web 28 | 29 | build-master: 30 | stage: build 31 | variables: 32 | IMAGE_TAG: latest 33 | before_script: 34 | - echo Building and Pushing public page image to registry ${CI_REGISTRY} 35 | - docker login -u gitlab-ci-token -p $CI_JOB_TOKEN $CI_REGISTRY 36 | script: 37 | - docker build --pull -t $DOCKER_IMAGE_BUILD:$IMAGE_TAG -t $BASE_TAG:$IMAGE_TAG . 38 | - docker push $DOCKER_IMAGE_BUILD:$IMAGE_TAG 39 | after_script: 40 | - docker logout 41 | allow_failure: false 42 | only: 43 | - master 44 | -------------------------------------------------------------------------------- /data/temp/setup.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | prepare_rbenv() { 4 | rbenv install $1 5 | if [ $? -eq 0 ]; then 6 | rbenv global $1 7 | return $? 8 | else 9 | echo 'Failed to install Ruby via rbenv' 10 | exit 1 11 | fi 12 | } 13 | 14 | prepare_nvm() { 15 | nvm install node --latest-npm 16 | if [ $? -eq 0 ]; then 17 | nvm alias default node 18 | return $? 19 | else 20 | echo 'Failed to install node via nvm!' 21 | return 1 22 | fi 23 | } 24 | 25 | prepare_shell() { 26 | echo 'Installing bundler...' 27 | gem install bundler dpl 28 | local installBundler=$? 29 | npm i -g @pddstudio/docker-manifest 30 | local installDockerManifest=$? 31 | echo "Installing bundler returned with exit code ${installBundler}." 32 | echo "Installing docker-manifest returned with exit code ${installDockerManifest}." 33 | return 0 34 | } 35 | 36 | main() { 37 | source $HOME/.bashrc.local 38 | case "$1" in 39 | rbenv) 40 | echo 'Installing Ruby' 41 | shift 42 | prepare_rbenv "$@" 43 | return $? 44 | ;; 45 | nvm) 46 | echo 'Installing Node' 47 | prepare_nvm 48 | return $? 49 | ;; 50 | packages) 51 | echo 'Installing additional packages' 52 | prepare_shell 53 | return $? 54 | ;; 55 | esac 56 | } 57 | 58 | main "$@" 59 | -------------------------------------------------------------------------------- /data/temp/rbenv-install.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | RBENV_GIT_REMOTE="https://github.com/rbenv/rbenv.git" 4 | RUBY_BUILD_GIT_REMOTE="https://github.com/rbenv/ruby-build.git" 5 | 6 | DIR_RBENV="$HOME/.rbenv" 7 | DIR_RUBY_BUILD="$DIR_RBENV/plugins/ruby-build" 8 | RUBY_BUILD_INSTALLER_SCRIPT="$DIR_RUBY_BUILD/install.sh" 9 | PATH_RBENV_BIN="$DIR_RBENV/bin" 10 | 11 | clone_rbenv() { 12 | git clone "$RBENV_GIT_REMOTE" "$DIR_RBENV" 13 | return $? 14 | } 15 | 16 | clone_ruby_builder() { 17 | git clone "$RUBY_BUILD_GIT_REMOTE" "$DIR_RUBY_BUILD" 18 | return $? 19 | } 20 | 21 | install_builder_plugin() { 22 | PREFIX=$HOME/local $RUBY_BUILD_INSTALLER_SCRIPT 23 | return $? 24 | } 25 | 26 | append_local_bashrc() { 27 | echo "source $HOME/.bashrc.local" >> $HOME/.bashrc 28 | return $? 29 | } 30 | 31 | main() { 32 | case "$1" in 33 | git-clone) 34 | echo 'Cloning repositories...' 35 | clone_rbenv 36 | clone_ruby_builder 37 | return 0 38 | ;; 39 | install-plugin) 40 | echo 'Installing Ruby Build Plugin...' 41 | install_builder_plugin 42 | return $? 43 | ;; 44 | prepare-bashrc) 45 | echo 'Preparing .bashrc...' 46 | append_local_bashrc 47 | return $? 48 | ;; 49 | *) 50 | echo 'Usage: $0 { git-clone | install-plugin | prepare-bashrc }' 51 | return 1 52 | ;; 53 | esac 54 | } 55 | 56 | 57 | main "$@" 58 | if [ $? -eq 0 ]; then 59 | echo 'Command execution succeeded!' 60 | exit 0 61 | else 62 | echo 'Command returned non-zero exit code' 63 | exit 1 64 | fi 65 | 66 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Created by https://www.gitignore.io/api/linux,node,visualstudiocode 3 | 4 | ### Linux ### 5 | *~ 6 | 7 | # temporary files which can be created if a process still has a handle open of a deleted file 8 | .fuse_hidden* 9 | 10 | # KDE directory preferences 11 | .directory 12 | 13 | # Linux trash folder which might appear on any partition or disk 14 | .Trash-* 15 | 16 | # .nfs files are created when an open file is removed but is still being accessed 17 | .nfs* 18 | 19 | ### Node ### 20 | # Logs 21 | logs 22 | *.log 23 | npm-debug.log* 24 | yarn-debug.log* 25 | yarn-error.log* 26 | 27 | # Runtime data 28 | pids 29 | *.pid 30 | *.seed 31 | *.pid.lock 32 | 33 | # Directory for instrumented libs generated by jscoverage/JSCover 34 | lib-cov 35 | 36 | # Coverage directory used by tools like istanbul 37 | coverage 38 | 39 | # nyc test coverage 40 | .nyc_output 41 | 42 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 43 | .grunt 44 | 45 | # Bower dependency directory (https://bower.io/) 46 | bower_components 47 | 48 | # node-waf configuration 49 | .lock-wscript 50 | 51 | # Compiled binary addons (https://nodejs.org/api/addons.html) 52 | build/Release 53 | 54 | # Dependency directories 55 | node_modules/ 56 | jspm_packages/ 57 | 58 | # TypeScript v1 declaration files 59 | typings/ 60 | 61 | # Optional npm cache directory 62 | .npm 63 | 64 | # Optional eslint cache 65 | .eslintcache 66 | 67 | # Optional REPL history 68 | .node_repl_history 69 | 70 | # Output of 'npm pack' 71 | *.tgz 72 | 73 | # Yarn Integrity file 74 | .yarn-integrity 75 | 76 | # dotenv environment variables file 77 | .env 78 | 79 | # parcel-bundler cache (https://parceljs.org/) 80 | .cache 81 | 82 | # next.js build output 83 | .next 84 | 85 | # nuxt.js build output 86 | .nuxt 87 | 88 | # vuepress build output 89 | .vuepress/dist 90 | 91 | # Serverless directories 92 | .serverless 93 | 94 | ### VisualStudioCode ### 95 | .vscode/* 96 | !.vscode/settings.json 97 | !.vscode/tasks.json 98 | !.vscode/launch.json 99 | !.vscode/extensions.json 100 | 101 | .circleci/prepare-env.sh 102 | 103 | # End of https://www.gitignore.io/api/linux,node,visualstudiocode 104 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # FROM ubuntu:18.04 2 | FROM gitlab/dind 3 | 4 | RUN apt-get update -qqy && \ 5 | apt-get install -qqy \ 6 | apt-transport-https \ 7 | ca-certificates \ 8 | curl \ 9 | autoconf \ 10 | bison \ 11 | build-essential \ 12 | libssl-dev \ 13 | libyaml-dev \ 14 | libreadline6-dev \ 15 | zlib1g-dev \ 16 | libncurses5-dev \ 17 | libffi-dev \ 18 | libgdbm3 \ 19 | libgdbm-dev 20 | 21 | COPY ./data/system/profile.d/rbenv-init.sh /etc/profile.d/rbenv-init.sh 22 | 23 | # download and setup dumb-init 24 | RUN curl -s -L -o /usr/local/bin/dumb-init https://github.com/Yelp/dumb-init/releases/download/v1.2.2/dumb-init_1.2.2_amd64 && \ 25 | chmod +x /usr/local/bin/dumb-init 26 | 27 | # symlink docker binary 28 | RUN ln -s /usr/bin/docker /usr/local/bin/docker && \ 29 | chmod +x /usr/local/bin/docker 30 | 31 | # create new user as which we want to run further commands 32 | RUN groupadd -r appuser && \ 33 | useradd appuser -r -s /bin/bash -m -g appuser -G root,sudo,docker && \ 34 | usermod -a -G docker appuser 35 | 36 | # set user & workdir to execute further setup without being root 37 | USER appuser 38 | WORKDIR /home/appuser 39 | 40 | # copy rc, config & setup files to container 41 | COPY --chown=appuser:appuser data/user . 42 | COPY --chown=appuser:appuser data/temp ./temp 43 | 44 | ENV TARGET_RUBY_VERSION=${TARGET_VERSION_RUBY:-2.5.0} 45 | ENV TARGET_NODE_VERSION=${TARGET_VERSION_NODE:-10.9.0} 46 | 47 | ENV PATH $HOME/.rbenv/bin:$PATH 48 | 49 | # create required directories 50 | RUN mkdir -p $HOME/build && \ 51 | mkdir -p $HOME/tmp && \ 52 | mkdir -p $HOME/local && \ 53 | mkdir -p $HOME/.nvm 54 | 55 | # download, setup and install rbenv & nvm 56 | RUN bash -l -c "\ 57 | git config --global http.sslVerify false; \ 58 | chmod a+x $HOME/temp/*.sh; \ 59 | $HOME/temp/rbenv-install.sh git-clone; \ 60 | $HOME/temp/rbenv-install.sh install-plugin; \ 61 | $HOME/temp/rbenv-install.sh prepare-bashrc; \ 62 | $HOME/temp/nvm-install.sh;" 63 | 64 | # download, setup & install specified ruby & node version 65 | # install additional packages: 66 | # - bundler via gem (ruby) 67 | # - dpl via gaem (ruby) 68 | # - docker-manifest via npm (node) 69 | RUN bash -l -c "\ 70 | source $HOME/.bashrc; \ 71 | $HOME/temp/setup.sh rbenv ${TARGET_RUBY_VERSION}; \ 72 | $HOME/temp/setup.sh nvm; \ 73 | $HOME/temp/setup.sh packages;" 74 | 75 | # print summary of all available binaries & their versions 76 | # clean up and remove build/setup files 77 | RUN bash -l -c "$HOME/temp/summary.sh; rm -rf $HOME/temp/;" 78 | 79 | # allow custom data to be mounted into $HOME/build 80 | VOLUME [ "/home/appuser/build" ] 81 | 82 | # setting some environment variables (exposed, use with care) 83 | ENV BASH_ENV "/home/appuser/.bashrc" 84 | ENV NVM_DIR "/home/appuser/.nvm" 85 | 86 | ENTRYPOINT [ "/usr/local/bin/dumb-init", "--" ] 87 | CMD [ "./docker-entrypoint.sh", "/usr/local/bin/docker", "version" ] 88 | -------------------------------------------------------------------------------- /data/temp/nvm-install.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | { # this ensures the entire script is downloaded # 4 | 5 | nvm_has() { 6 | type "$1" > /dev/null 2>&1 7 | } 8 | 9 | nvm_install_dir() { 10 | command printf %s "${NVM_DIR:-"$HOME/.nvm"}" 11 | } 12 | 13 | nvm_latest_version() { 14 | echo "v0.33.11" 15 | } 16 | 17 | nvm_profile_is_bash_or_zsh() { 18 | local TEST_PROFILE 19 | TEST_PROFILE="${1-}" 20 | case "${TEST_PROFILE-}" in 21 | *"/.bashrc" | *"/.bash_profile" | *"/.zshrc") 22 | return 23 | ;; 24 | *) 25 | return 1 26 | ;; 27 | esac 28 | } 29 | 30 | # 31 | # Outputs the location to NVM depending on: 32 | # * The availability of $NVM_SOURCE 33 | # * The method used ("script" or "git" in the script, defaults to "git") 34 | # NVM_SOURCE always takes precedence unless the method is "script-nvm-exec" 35 | # 36 | nvm_source() { 37 | local NVM_METHOD 38 | NVM_METHOD="$1" 39 | local NVM_SOURCE_URL 40 | NVM_SOURCE_URL="$NVM_SOURCE" 41 | if [ "_$NVM_METHOD" = "_script-nvm-exec" ]; then 42 | NVM_SOURCE_URL="https://raw.githubusercontent.com/creationix/nvm/$(nvm_latest_version)/nvm-exec" 43 | elif [ "_$NVM_METHOD" = "_script-nvm-bash-completion" ]; then 44 | NVM_SOURCE_URL="https://raw.githubusercontent.com/creationix/nvm/$(nvm_latest_version)/bash_completion" 45 | elif [ -z "$NVM_SOURCE_URL" ]; then 46 | if [ "_$NVM_METHOD" = "_script" ]; then 47 | NVM_SOURCE_URL="https://raw.githubusercontent.com/creationix/nvm/$(nvm_latest_version)/nvm.sh" 48 | elif [ "_$NVM_METHOD" = "_git" ] || [ -z "$NVM_METHOD" ]; then 49 | NVM_SOURCE_URL="https://github.com/creationix/nvm.git" 50 | else 51 | echo >&2 "Unexpected value \"$NVM_METHOD\" for \$NVM_METHOD" 52 | return 1 53 | fi 54 | fi 55 | echo "$NVM_SOURCE_URL" 56 | } 57 | 58 | # 59 | # Node.js version to install 60 | # 61 | nvm_node_version() { 62 | echo "$NODE_VERSION" 63 | } 64 | 65 | nvm_download() { 66 | if nvm_has "curl"; then 67 | curl --compressed -q "$@" 68 | elif nvm_has "wget"; then 69 | # Emulate curl with wget 70 | ARGS=$(echo "$*" | command sed -e 's/--progress-bar /--progress=bar /' \ 71 | -e 's/-L //' \ 72 | -e 's/--compressed //' \ 73 | -e 's/-I /--server-response /' \ 74 | -e 's/-s /-q /' \ 75 | -e 's/-o /-O /' \ 76 | -e 's/-C - /-c /') 77 | # shellcheck disable=SC2086 78 | eval wget $ARGS 79 | fi 80 | } 81 | 82 | install_nvm_from_git() { 83 | local INSTALL_DIR 84 | INSTALL_DIR="$(nvm_install_dir)" 85 | 86 | if [ -d "$INSTALL_DIR/.git" ]; then 87 | echo "=> nvm is already installed in $INSTALL_DIR, trying to update using git" 88 | command printf '\r=> ' 89 | command git --git-dir="$INSTALL_DIR"/.git --work-tree="$INSTALL_DIR" fetch origin tag "$(nvm_latest_version)" --depth=1 2> /dev/null || { 90 | echo >&2 "Failed to update nvm, run 'git fetch' in $INSTALL_DIR yourself." 91 | exit 1 92 | } 93 | else 94 | # Cloning to $INSTALL_DIR 95 | echo "=> Downloading nvm from git to '$INSTALL_DIR'" 96 | command printf '\r=> ' 97 | mkdir -p "${INSTALL_DIR}" 98 | if [ "$(ls -A "${INSTALL_DIR}")" ]; then 99 | command git init "${INSTALL_DIR}" || { 100 | echo >&2 'Failed to initialize nvm repo. Please report this!' 101 | exit 2 102 | } 103 | command git --git-dir="${INSTALL_DIR}/.git" remote add origin "$(nvm_source)" 2> /dev/null \ 104 | || command git --git-dir="${INSTALL_DIR}/.git" remote set-url origin "$(nvm_source)" || { 105 | echo >&2 'Failed to add remote "origin" (or set the URL). Please report this!' 106 | exit 2 107 | } 108 | command git --git-dir="${INSTALL_DIR}/.git" fetch origin tag "$(nvm_latest_version)" --depth=1 || { 109 | echo >&2 'Failed to fetch origin with tags. Please report this!' 110 | exit 2 111 | } 112 | else 113 | command git -c advice.detachedHead=false clone "$(nvm_source)" -b "$(nvm_latest_version)" --depth=1 "${INSTALL_DIR}" || { 114 | echo >&2 'Failed to clone nvm repo. Please report this!' 115 | exit 2 116 | } 117 | fi 118 | fi 119 | command git -c advice.detachedHead=false --git-dir="$INSTALL_DIR"/.git --work-tree="$INSTALL_DIR" checkout -f --quiet "$(nvm_latest_version)" 120 | if [ ! -z "$(command git --git-dir="$INSTALL_DIR"/.git --work-tree="$INSTALL_DIR" show-ref refs/heads/master)" ]; then 121 | if command git --git-dir="$INSTALL_DIR"/.git --work-tree="$INSTALL_DIR" branch --quiet 2>/dev/null; then 122 | command git --git-dir="$INSTALL_DIR"/.git --work-tree="$INSTALL_DIR" branch --quiet -D master >/dev/null 2>&1 123 | else 124 | echo >&2 "Your version of git is out of date. Please update it!" 125 | command git --git-dir="$INSTALL_DIR"/.git --work-tree="$INSTALL_DIR" branch -D master >/dev/null 2>&1 126 | fi 127 | fi 128 | 129 | echo "=> Compressing and cleaning up git repository" 130 | if ! command git --git-dir="$INSTALL_DIR"/.git --work-tree="$INSTALL_DIR" reflog expire --expire=now --all; then 131 | echo >&2 "Your version of git is out of date. Please update it!" 132 | fi 133 | if ! command git --git-dir="$INSTALL_DIR"/.git --work-tree="$INSTALL_DIR" gc --auto --aggressive --prune=now ; then 134 | echo >&2 "Your version of git is out of date. Please update it!" 135 | fi 136 | return 137 | } 138 | 139 | # 140 | # Automatically install Node.js 141 | # 142 | nvm_install_node() { 143 | local NODE_VERSION_LOCAL 144 | NODE_VERSION_LOCAL="$(nvm_node_version)" 145 | 146 | if [ -z "$NODE_VERSION_LOCAL" ]; then 147 | return 0 148 | fi 149 | 150 | echo "=> Installing Node.js version $NODE_VERSION_LOCAL" 151 | nvm install "$NODE_VERSION_LOCAL" 152 | local CURRENT_NVM_NODE 153 | 154 | CURRENT_NVM_NODE="$(nvm_version current)" 155 | if [ "$(nvm_version "$NODE_VERSION_LOCAL")" == "$CURRENT_NVM_NODE" ]; then 156 | echo "=> Node.js version $NODE_VERSION_LOCAL has been successfully installed" 157 | else 158 | echo >&2 "Failed to install Node.js $NODE_VERSION_LOCAL" 159 | fi 160 | } 161 | 162 | install_nvm_as_script() { 163 | local INSTALL_DIR 164 | INSTALL_DIR="$(nvm_install_dir)" 165 | local NVM_SOURCE_LOCAL 166 | NVM_SOURCE_LOCAL="$(nvm_source script)" 167 | local NVM_EXEC_SOURCE 168 | NVM_EXEC_SOURCE="$(nvm_source script-nvm-exec)" 169 | local NVM_BASH_COMPLETION_SOURCE 170 | NVM_BASH_COMPLETION_SOURCE="$(nvm_source script-nvm-bash-completion)" 171 | 172 | # Downloading to $INSTALL_DIR 173 | mkdir -p "$INSTALL_DIR" 174 | if [ -f "$INSTALL_DIR/nvm.sh" ]; then 175 | echo "=> nvm is already installed in $INSTALL_DIR, trying to update the script" 176 | else 177 | echo "=> Downloading nvm as script to '$INSTALL_DIR'" 178 | fi 179 | nvm_download -s "$NVM_SOURCE_LOCAL" -o "$INSTALL_DIR/nvm.sh" || { 180 | echo >&2 "Failed to download '$NVM_SOURCE_LOCAL'" 181 | return 1 182 | } & 183 | nvm_download -s "$NVM_EXEC_SOURCE" -o "$INSTALL_DIR/nvm-exec" || { 184 | echo >&2 "Failed to download '$NVM_EXEC_SOURCE'" 185 | return 2 186 | } & 187 | nvm_download -s "$NVM_BASH_COMPLETION_SOURCE" -o "$INSTALL_DIR/bash_completion" || { 188 | echo >&2 "Failed to download '$NVM_BASH_COMPLETION_SOURCE'" 189 | return 2 190 | } & 191 | for job in $(jobs -p | command sort) 192 | do 193 | wait "$job" || return $? 194 | done 195 | chmod a+x "$INSTALL_DIR/nvm-exec" || { 196 | echo >&2 "Failed to mark '$INSTALL_DIR/nvm-exec' as executable" 197 | return 3 198 | } 199 | } 200 | 201 | nvm_try_profile() { 202 | if [ -z "${1-}" ] || [ ! -f "${1}" ]; then 203 | return 1 204 | fi 205 | echo "${1}" 206 | } 207 | 208 | # 209 | # Detect profile file if not specified as environment variable 210 | # (eg: PROFILE=~/.myprofile) 211 | # The echo'ed path is guaranteed to be an existing file 212 | # Otherwise, an empty string is returned 213 | # 214 | nvm_detect_profile() { 215 | if [ -n "${PROFILE}" ] && [ -f "${PROFILE}" ]; then 216 | echo "${PROFILE}" 217 | return 218 | fi 219 | 220 | local DETECTED_PROFILE 221 | DETECTED_PROFILE='' 222 | 223 | if [ -n "${BASH_VERSION-}" ]; then 224 | if [ -f "$HOME/.bashrc" ]; then 225 | DETECTED_PROFILE="$HOME/.bashrc" 226 | elif [ -f "$HOME/.bash_profile" ]; then 227 | DETECTED_PROFILE="$HOME/.bash_profile" 228 | fi 229 | elif [ -n "${ZSH_VERSION-}" ]; then 230 | DETECTED_PROFILE="$HOME/.zshrc" 231 | fi 232 | 233 | if [ -z "$DETECTED_PROFILE" ]; then 234 | for EACH_PROFILE in ".profile" ".bashrc" ".bash_profile" ".zshrc" 235 | do 236 | if DETECTED_PROFILE="$(nvm_try_profile "${HOME}/${EACH_PROFILE}")"; then 237 | break 238 | fi 239 | done 240 | fi 241 | 242 | if [ ! -z "$DETECTED_PROFILE" ]; then 243 | echo "$DETECTED_PROFILE" 244 | fi 245 | } 246 | 247 | # 248 | # Check whether the user has any globally-installed npm modules in their system 249 | # Node, and warn them if so. 250 | # 251 | nvm_check_global_modules() { 252 | command -v npm >/dev/null 2>&1 || return 0 253 | 254 | local NPM_VERSION 255 | NPM_VERSION="$(npm --version)" 256 | NPM_VERSION="${NPM_VERSION:--1}" 257 | [ "${NPM_VERSION%%[!-0-9]*}" -gt 0 ] || return 0 258 | 259 | local NPM_GLOBAL_MODULES 260 | NPM_GLOBAL_MODULES="$( 261 | npm list -g --depth=0 | 262 | command sed -e '/ npm@/d' -e '/ (empty)$/d' 263 | )" 264 | 265 | local MODULE_COUNT 266 | MODULE_COUNT="$( 267 | command printf %s\\n "$NPM_GLOBAL_MODULES" | 268 | command sed -ne '1!p' | # Remove the first line 269 | wc -l | command tr -d ' ' # Count entries 270 | )" 271 | 272 | if [ "${MODULE_COUNT}" != '0' ]; then 273 | # shellcheck disable=SC2016 274 | echo '=> You currently have modules installed globally with `npm`. These will no' 275 | # shellcheck disable=SC2016 276 | echo '=> longer be linked to the active version of Node when you install a new node' 277 | # shellcheck disable=SC2016 278 | echo '=> with `nvm`; and they may (depending on how you construct your `$PATH`)' 279 | # shellcheck disable=SC2016 280 | echo '=> override the binaries of modules installed with `nvm`:' 281 | echo 282 | 283 | command printf %s\\n "$NPM_GLOBAL_MODULES" 284 | echo '=> If you wish to uninstall them at a later point (or re-install them under your' 285 | # shellcheck disable=SC2016 286 | echo '=> `nvm` Nodes), you can remove them from the system Node as follows:' 287 | echo 288 | echo ' $ nvm use system' 289 | echo ' $ npm uninstall -g a_module' 290 | echo 291 | fi 292 | } 293 | 294 | nvm_do_install() { 295 | if [ -n "${NVM_DIR-}" ] && ! [ -d "${NVM_DIR}" ]; then 296 | echo >&2 "You have \$NVM_DIR set to \"${NVM_DIR}\", but that directory does not exist. Check your profile files and environment." 297 | exit 1 298 | fi 299 | if [ -z "${METHOD}" ]; then 300 | # Autodetect install method 301 | if nvm_has git; then 302 | install_nvm_from_git 303 | elif nvm_has nvm_download; then 304 | install_nvm_as_script 305 | else 306 | echo >&2 'You need git, curl, or wget to install nvm' 307 | exit 1 308 | fi 309 | elif [ "${METHOD}" = 'git' ]; then 310 | if ! nvm_has git; then 311 | echo >&2 "You need git to install nvm" 312 | exit 1 313 | fi 314 | install_nvm_from_git 315 | elif [ "${METHOD}" = 'script' ]; then 316 | if ! nvm_has nvm_download; then 317 | echo >&2 "You need curl or wget to install nvm" 318 | exit 1 319 | fi 320 | install_nvm_as_script 321 | fi 322 | 323 | echo 324 | 325 | local NVM_PROFILE 326 | NVM_PROFILE="$(nvm_detect_profile)" 327 | local PROFILE_INSTALL_DIR 328 | PROFILE_INSTALL_DIR="$(nvm_install_dir | command sed "s:^$HOME:\$HOME:")" 329 | 330 | SOURCE_STR="\\nexport NVM_DIR=\"${PROFILE_INSTALL_DIR}\"\\n[ -s \"\$NVM_DIR/nvm.sh\" ] && \\. \"\$NVM_DIR/nvm.sh\" # This loads nvm\\n" 331 | 332 | # shellcheck disable=SC2016 333 | COMPLETION_STR='[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" # This loads nvm bash_completion\n' 334 | BASH_OR_ZSH=false 335 | 336 | if [ -z "${NVM_PROFILE-}" ] ; then 337 | local TRIED_PROFILE 338 | if [ -n "${PROFILE}" ]; then 339 | TRIED_PROFILE="${NVM_PROFILE} (as defined in \$PROFILE), " 340 | fi 341 | echo "=> Profile not found. Tried ${TRIED_PROFILE-}~/.bashrc, ~/.bash_profile, ~/.zshrc, and ~/.profile." 342 | echo "=> Create one of them and run this script again" 343 | echo " OR" 344 | echo "=> Append the following lines to the correct file yourself:" 345 | command printf "${SOURCE_STR}" 346 | echo 347 | else 348 | if nvm_profile_is_bash_or_zsh "${NVM_PROFILE-}"; then 349 | BASH_OR_ZSH=true 350 | fi 351 | fi 352 | if ${BASH_OR_ZSH} && [ -z "${NVM_PROFILE-}" ] ; then 353 | echo "=> Please also append the following lines to the if you are using bash/zsh shell:" 354 | command printf "${COMPLETION_STR}" 355 | fi 356 | 357 | # Source nvm 358 | # shellcheck source=/dev/null 359 | \. "$(nvm_install_dir)/nvm.sh" 360 | 361 | nvm_check_global_modules 362 | 363 | nvm_install_node 364 | 365 | nvm_reset 366 | 367 | echo "=> Close and reopen your terminal to start using nvm or run the following to use it now:" 368 | command printf "${SOURCE_STR}" 369 | if ${BASH_OR_ZSH} ; then 370 | command printf "${COMPLETION_STR}" 371 | fi 372 | } 373 | 374 | # 375 | # Unsets the various functions defined 376 | # during the execution of the install script 377 | # 378 | nvm_reset() { 379 | unset -f nvm_has nvm_install_dir nvm_latest_version nvm_profile_is_bash_or_zsh \ 380 | nvm_source nvm_node_version nvm_download install_nvm_from_git nvm_install_node \ 381 | install_nvm_as_script nvm_try_profile nvm_detect_profile nvm_check_global_modules \ 382 | nvm_do_install nvm_reset 383 | } 384 | 385 | [ "_$NVM_ENV" = "_testing" ] || nvm_do_install 386 | 387 | } # this ensures the entire script is downloaded # --------------------------------------------------------------------------------