From 0e13d832bc9f925145ae2145a98f308cc55a710d Mon Sep 17 00:00:00 2001 From: apolopena <3060702+apolopena@users.noreply.github.com> Date: Sat, 6 Feb 2021 08:19:22 -0800 Subject: [PATCH] Features 25, 23 and Fixes 21 and 24 (#26) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 📦 NEW: fix npm WARN lifecycle The node binary mistmatch... * 🐛 FIX: #23 * 🐛 FIX: refactored parsing rountines * 🐛 FIX: smoother install of github-changelog-generator * 📖 DOC: improve log msg * 👌 IMPROVE: messages and spinners * 👌 IMPROVE: log utils * 🐛 FIX: #24 * 📖 DOC: ending message * 📖 DOC: console messages * 🤖 TEST: logs * 🐛 FIX: dev qa complete for https://github.com/apolopena/gitpod-laravel8-starter/issues/24 * 👌 IMPROVE: colorized spinner * 👌 IMPROVE: colorized spinner ansi 256 --- .gitpod.Dockerfile | 3 + .gitpod.yml | 3 +- .npmrc | 1 + bash/helpers.sh | 89 +++++++++++++++++------- bash/init-complete.sh | 14 ++++ bash/init-gitpod.sh | 86 +++++++++++++++++------ bash/init-optional-scaffolding.sh | 112 +++++++++++++++--------------- bash/init-rake-tasks.sh | 40 +++++++++++ bash/third-party/spinner.sh | 8 ++- bash/utils.sh | 50 ++++++++++++- starter.ini | 16 +++-- 11 files changed, 310 insertions(+), 112 deletions(-) create mode 100644 .npmrc create mode 100644 bash/init-complete.sh create mode 100644 bash/init-rake-tasks.sh diff --git a/.gitpod.Dockerfile b/.gitpod.Dockerfile index 570b5d28..d67d30b9 100644 --- a/.gitpod.Dockerfile +++ b/.gitpod.Dockerfile @@ -5,6 +5,9 @@ USER gitpod RUN sudo touch /var/log/workspace-image.log \ && sudo chmod 666 /var/log/workspace-image.log +RUN sudo touch /var/log/workspace-init.log \ + && sudo chmod 666 /var/log/workspace-init.log + RUN sudo touch /var/log/xdebug.log \ && sudo chmod 666 /var/log/xdebug.log diff --git a/.gitpod.yml b/.gitpod.yml index f6d6762c..0e9d9fbc 100644 --- a/.gitpod.yml +++ b/.gitpod.yml @@ -20,7 +20,8 @@ tasks: bash bash/init-gitpod.sh && source ~/.bash_profile && url=$(gp url 8000); sed -i'' "s#^APP_URL=http://localhost*#APP_URL=$url\nASSET_URL=$url#g" .env && - . bash/init-optional-scaffolding.sh + bash bash/init-optional-scaffolding.sh && + bash bash/init-complete.sh name: Init - openMode: split-left command: | diff --git a/.npmrc b/.npmrc new file mode 100644 index 00000000..a21347f1 --- /dev/null +++ b/.npmrc @@ -0,0 +1 @@ +scripts-prepend-node-path=true \ No newline at end of file diff --git a/bash/helpers.sh b/bash/helpers.sh index 1bf24c8f..f272c037 100644 --- a/bash/helpers.sh +++ b/bash/helpers.sh @@ -2,16 +2,18 @@ # helpers.sh # Author: Apolo Pena -# Description: A variety of useful functions with that depend on gitpod other -# binaries, aliases and functions in .bashrc +# Description: A variety of useful functions with that depend on gitpod +# and other binaries, aliases and functions such as code in .bashrc # other than coreutils. # Note: Do not execute this script witout calling a function from it +# Additional Note: some functions use functions from .bashrc so the -i flag +# is the safest way to invoke functions from this script. # # Usage: bash -i arg1 arg2 arg3 ... # version () { - echo "helpers.sh version 0.0.2" + echo "helpers.sh version 0.0.3" } # start_server @@ -34,33 +36,68 @@ start_server() { # Bump the value of the default_server in starter.ini to lowercase server=$(echo "$s" | tr '[:upper:]' '[:lower:]') if [ -z "$1" ]; then - case "$server" in - 'php') - start_php_dev - ;; - 'apache') - start_apache - ;; - *) - echo "$err invalid default server: $server. Check the file $GITPOD_REPO_ROOT/starter.ini" - ;; - esac + case "$server" in + 'php') + start_php_dev + ;; + 'apache') + start_apache + ;; + *) + echo "$err invalid default server: $server. Check the file $GITPOD_REPO_ROOT/starter.ini" + ;; + esac else echo $(echo "$1" | tr '[:upper:]' '[:lower:]') - case $(echo "$1" | tr '[:upper:]' '[:lower:]') in - 'php') - start_php_dev - ;; - 'apache') - start_apache - ;; - *) - echo "$err invalid server type: $1" - ;; - esac + case $(echo "$1" | tr '[:upper:]' '[:lower:]') in + 'php') + start_php_dev + ;; + 'apache') + start_apache + ;; + *) + echo "$err invalid server type: $1" + ;; + esac fi } +# add_global_rake_task +# Description: +# Writes a rake task multiline string ($1) to a file named by the command ($2) in ~/.rake +# +# Notes: +# Depending on how the task is written you may need to +# invoke a global rake task using the -g flag like so: rake -g hello-world +# Do not use the .rake suffic in your command. The rake file name will +# automatically written as to "$2.rake" +# Any exisitng rake command in ~/.rake will be clobbered. +# +# Usage: +# Example: a dynamically created hello world rake task +# # create a safe multiline string (with variable interpolation) to pass to add_global_rake_task +# name='Apolo' +# rake_task_name='hello' +# IFS='' read -r -d '' __task < "$root/$file" +} + # Call functions from this script gracefully if declare -f "$1" > /dev/null then @@ -69,4 +106,4 @@ then else echo "helpers.sh: '$1' is not a known function name." >&2 exit 1 -fi \ No newline at end of file +fi diff --git a/bash/init-complete.sh b/bash/init-complete.sh new file mode 100644 index 00000000..7d408735 --- /dev/null +++ b/bash/init-complete.sh @@ -0,0 +1,14 @@ +#!/bin/bash + +workspace_log='/var/log/workspace-image.log' +init_log='/var/log/workspace-init.log' +echo -e "\n\e[38;5;171mSUMMARY 📃\e[0m\n" +echo -en "\e[38;5;194mResults of building the workspace image\e[0m \e[38;5;34m$workspace_log\e[0m ➥\n\e[38;5;183m" +cat $workspace_log +echo -en "\e[0m" +echo '' +echo -en "\e[38;5;194mResults of the gitpod initialization\e[0m \e[38;5;34m$init_log\e[0m ➥\e[38;5;39m" +cat $init_log +echo -en "\e[0m" +echo -en "\n\e[38;5;171mALL DONE 🚀\e[0m\n" +echo -e "\e[38;5;194mIf everything looks good in the above results then push the newly created\n project files to your git repo and get started coding your project\e[0m" \ No newline at end of file diff --git a/bash/init-gitpod.sh b/bash/init-gitpod.sh index 4a908374..95dca0d5 100644 --- a/bash/init-gitpod.sh +++ b/bash/init-gitpod.sh @@ -1,44 +1,88 @@ #!/bin/bash -#printf "\033c" + +# Log to the console and a file +log () { + if [ -z "$2" ]; then + bash bash/utils.sh log "$1" /var/log/workspace-init.log + else + bash bash/utils.sh log "$1" /var/log/workspace-init.log -e + fi +} + +# Log only to a file +log_silent () { + if [ -z "$2" ]; then + bash bash/utils.sh log_silent "$1" /var/log/workspace-init.log + else + bash bash/utils.sh log_silent "$1" /var/log/workspace-init.log -e + fi +} + + +# Load spinner +. bash/third-party/spinner.sh # Bootstrap scaffolding if [ ! -d "$GITPOD_REPO_ROOT/bootstrap" ]; then - echo "Results of building the workspace image ➥" - cat /var/log/workspace-image.log - echo -e "\nMoving Laravel project from ~/temp-app to $GITPOD_REPO_ROOT ..." + # Todo replacespinner with a real progress bar for coreutils + msg="\nMoving Laravel project from ~/temp-app to $GITPOD_REPO_ROOT" + log_silent "$msg" && start_spinner "$msg" shopt -s dotglob mv --no-clobber ~/test-app/* $GITPOD_REPO_ROOT - RESULT=$? - if [ $? -ne 0 ]; then - >&2 echo "ERROR: Failed to move Laravel project from ~/temp-app to $GITPOD_REPO_ROOT" + err_code=$? + if [ $err_code != 0 ]; then + stop_spinner $err_code + log "ERROR: Failed to move Laravel project from ~/temp-app to $GITPOD_REPO_ROOT" -e else - echo "SUCCESS: moved Laravel project from ~/temp-app to $GITPOD_REPO_ROOT" + stop_spinner $err_code + log "SUCCESS: moved Laravel project from ~/temp-app to $GITPOD_REPO_ROOT" fi # BEGIN: Optional configurations + # Super user account for phpmyadmin installed_phpmyadmin=$(. /tmp/utils.sh parse_ini_value /tmp/starter.ini phpmyadmin install) - if [ $installed_phpmyadmin -eq 1 ]; then - echo "Creating phpmyadmin superuser: pmasu..." + if [ "$installed_phpmyadmin" == 1 ]; then + msg="Creating phpmyadmin superuser: pmasu" + log_silent "$msg" && start_spinner "$msg" mysql -e "CREATE USER 'pmasu'@'%' IDENTIFIED BY '123456';" mysql -e "GRANT ALL PRIVILEGES ON *.* TO 'pmasu'@'%';" - RESULT=$? - if [ $? -ne 0 ]; then - >&2 echo "ERROR: failed to create phpmyadmin superuser: pmasu" + err_code=$? + if [ $err_code != 0 ]; then + stop_spinner $err_code + log "ERROR: failed to create phpmyadmin superuser: pmasu" -e else - echo "SUCCESS: created phpmyadmin superuser: pmasu" + stop_spinner $err_code fi fi + # Install https://github.com/github-changelog-generator/github-changelog-generator + installed_changelog_gen=$(bash bash/utils.sh parse_ini_value starter.ini github-changelog-generator install) + if [ "$installed_changelog_gen" == 1 ]; then + msg="Installing github-changelog-generator" + log_silent "$msg" && start_spinner "$msg" && + gem install github_changelog_generator --no-document --silent && + stop_spinner $? + fi # END: Optional configurations + # Move and or merge necessary failes then cleanup (echo; cat ~/test-app/.gitignore) >> $GITPOD_REPO_ROOT/.gitignore && rm ~/test-app/.gitignore mv ~/test-app/README.md $GITPOD_REPO_ROOT/README_LARAVEL.md rmdir ~/test-app fi -# Aliases for git -echo "Writing git aliases..." -bash bash/utils.sh add_file_to_file_after \\[alias\\] bash/snippets/emoji-log ~/.gitconfig -bash bash/utils.sh add_file_to_file_after \\[alias\\] bash/snippets/git-aliases ~/.gitconfig -echo "Writing git aliases complete, check the log for any possible errors." -echo "try: git a or: git aliases for a list your git aliases." +# Rake tasks (will be written to ~/.rake). +# Some rake tasks are dynamic and depend on the configuration in starter.ini +bash bash/init-rake-tasks.sh + +# Aliases for git +msg="Writing git aliases" +log_silent "$msg" && start_spinner "$msg" && +bash bash/utils.sh add_file_to_file_after \\[alias\\] bash/snippets/emoji-log ~/.gitconfig && +bash bash/utils.sh add_file_to_file_after \\[alias\\] bash/snippets/git-aliases ~/.gitconfig && +stop_spinner $? +log "try: git a or: git aliases for a list your git aliases.\n" -echo "If the above results are successful then make sure to add, commit and push the changes to your git repository." +# Messages for github_changelog_generator +[ "$installed_changelog_gen" == 1 ] && +log "You may auto generate a CHANGELOG.md from github commits by running the command:\nrake changelog [...options]\n" && +log "See starter.ini (github_changelog_generator section) for configurable options" && +log "For a full list of options see the github-changelog-generator repository on github" diff --git a/bash/init-optional-scaffolding.sh b/bash/init-optional-scaffolding.sh index d48ae71f..027f9c66 100644 --- a/bash/init-optional-scaffolding.sh +++ b/bash/init-optional-scaffolding.sh @@ -4,41 +4,54 @@ # Description: # Installs various packages according to the configuration set in starter.ini -# BEGIN: Parse starter.ini -install_react=$(. /tmp/utils.sh parse_ini_value starter.ini react install) -install_vue=$(. /tmp/utils.sh parse_ini_value starter.ini vue install) -install_bootstrap=$(. /tmp/utils.sh parse_ini_value starter.ini bootstrap install) -# END: Parse starter.ini +# Log to the console and a file +log () { + if [ -z "$2" ]; then + bash bash/utils.sh log "$1" /var/log/workspace-init.log + else + bash bash/utils.sh log "$1" /var/log/workspace-init.log -e + fi +} + +# Log only to a file +log_silent () { + if [ -z "$2" ]; then + bash bash/utils.sh log_silent "$1" /var/log/workspace-init.log + else + bash bash/utils.sh log_silent "$1" /var/log/workspace-init.log -e + fi +} + +parse="bash bash/utils.sh parse_ini_value starter.ini" + +install_react=$(eval $parse react install) +install_vue=$(eval $parse vue install) +install_bootstrap=$(eval $parse bootstrap install) # BEGIN: Install Laravel ui if needed if [[ $install_react == 1 || $install_bootstrap == 1 ]]; then - echo "Optional installations that require laravel/ui scaffolding were found." - echo "Installing laravel/ui scaffolding..." + log "Optional installations that require laravel/ui scaffolding were found" + log "Installing laravel/ui scaffolding" composer require laravel/ui:^3.2.0 err_code=$? if [ $err_code == 0 ]; then - echo "SUCCESS: laravel/ui scaffolding installed." - echo "Compiling fresh scaffolding and running Laravel Mix." + log "SUCCESS: laravel/ui scaffolding installed" + log "Compiling fresh scaffolding and running Laravel Mix" yarn install && yarn run dev - #echo "current working dir is: $(pwd)" else - >&2 echo "ERROR $err_code: There was a problem installing laravel/ui" + log "ERROR $err_code: There was a problem installing laravel/ui" -e fi fi # END: Install Laravel ui if needed # BEGIN: Optional react and react-dom install if [ "$install_react" == 1 ]; then - version=$(. /tmp/utils.sh parse_ini_value starter.ini react version) - auth=$(. /tmp/utils.sh parse_ini_value starter.ini react auth) - + version=$(eval $parse react version) + auth=$(eval $parse react auth) [ -z "$version" ] && version_msg='' || version_msg=" version $version" [ "$auth" != 1 ] && auth_msg='' || auth_msg=' with --auth' - - echo "React/React DOM install directive found in starter.ini" - echo "Installing React and React DOM..." - sleep 3 - + log "React/React DOM install directive found in starter.ini" + log "Installing React and React DOM" if [ "$auth" == 1 ]; then php artisan ui react --auth else @@ -46,35 +59,30 @@ if [ "$install_react" == 1 ]; then fi err_code=$? if [ $err_code == 0 ]; then - echo "SUCCESS: React and React DOM$version_msg$auth_msg has been installed" - echo "Compiling fresh scaffolding and running Laravel Mix" + log "SUCCESS: React and React DOM$version_msg$auth_msg has been installed" + log "Compiling fresh scaffolding and running Laravel Mix" yarn install && yarn run dev && sleep 1 && yarn run dev - if [ ! -z "$version" ]; then - echo "Setting react and react-dom to$version_msg" + log "Setting react and react-dom to$version_msg" # TODO: validate semver and valid version for the package so users cant pass in junk yarn upgrade react@$version react-dom@$version fi - - [ "$install_bootstrap" == 1 ] && echo "Bootstrap install directive found but ignored. Already installed." - [ "$install_vue" == 1 ] && echo "Vue install directive found but ignored. The install of react superceded this." + [ "$install_bootstrap" == 1 ] && log "Bootstrap install directive found but ignored. Already installed" + [ "$install_vue" == 1 ] && log "Vue install directive found but ignored. The install of react superceded this" else - >&2 echo "ERROR $err_code: There was a problem installing React/React DOM$version_msg$auth_msg" + log "ERROR $err_code: There was a problem installing React/React DOM$version_msg$auth_msg" -e fi fi # END: Optional react and react-dom install # BEGIN: Optional vue install if [[ "$install_vue" == 1 && "$install_react" == 0 ]]; then - version=$(. /tmp/utils.sh parse_ini_value starter.ini vue version) - auth=$(. /tmp/utils.sh parse_ini_value starter.ini vue auth) - + version=$(eval $parse vue version) + auth=$(eval $parse vue auth) [ -z "$version" ] && version_msg='' || version_msg=" version $version" [ "$auth" != 1 ] && auth_msg='' || auth_msg=' with --auth' - - echo "Vue install directive found in starter.ini" - echo "Installing Vue..." - + log "Vue install directive found in starter.ini" + log "Installing Vue..." if [ "$auth" == 1 ]; then php artisan ui vue --auth else @@ -82,34 +90,29 @@ if [[ "$install_vue" == 1 && "$install_react" == 0 ]]; then fi err_code=$? if [ $err_code == 0 ]; then - echo "SUCCESS: Vue$version_msg$auth_msg has been installed." - echo "Compiling fresh scaffolding and running Laravel Mix." + log "SUCCESS: Vue$version_msg$auth_msg has been installed" + log "Compiling fresh scaffolding and running Laravel Mix" yarn install && yarn run dev && sleep 1 && yarn run dev - if [ ! -z "$version" ]; then - echo "Setting vue to$version_msg" + log "Setting vue to$version_msg" # TODO: validate semver and valid version for the package so users cant pass in junk yarn upgrade vue@$version fi - - [ "$install_bootstrap" == 1 ] && echo "Bootstrap install directive found but ignored. Already installed." + [ "$install_bootstrap" == 1 ] && log "Bootstrap install directive found but ignored. Already installed." else - >&2 echo "ERROR $err_code: There was a problem installing Vue$version_msg$auth_msg" + log "ERROR $err_code: There was a problem installing Vue$version_msg$auth_msg" -e fi fi # END: Optional vue install # BEGIN: Optional bootstrap install if [[ $install_bootstrap == 1 && $install_react == 0 && $install_vue == 0 ]]; then - version=$(. /tmp/utils.sh parse_ini_value starter.ini bootstrap version) - auth=$(. /tmp/utils.sh parse_ini_value starter.ini bootstrap auth) - + version=$(eval $parse bootstrap version) + auth=$(eval $parse bootstrap auth) [ -z "$version" ] && version_msg='' || version_msg=" version $version" [ "$auth" != 1 ] && auth_msg='' || auth_msg=' with --auth' - - echo "Bootstrap install directive found in starter.ini" - echo "Installing Bootstrap..." - + log "Bootstrap install directive found in starter.ini" + log "Installing Bootstrap" if [ "$auth" == 1 ]; then php artisan ui bootstrap --auth else @@ -117,23 +120,22 @@ if [[ $install_bootstrap == 1 && $install_react == 0 && $install_vue == 0 ]]; th fi err_code=$? if [ $err_code == 0 ]; then - echo "SUCCESS: Bootstrap$version_msg$auth_msg has been installed." - echo "Compiling fresh scaffolding and running Laravel Mix." + log "SUCCESS: Bootstrap$version_msg$auth_msg has been installed" + log "Compiling fresh scaffolding and running Laravel Mix" yarn install && yarn run dev && sleep 1 && yarn run dev - if [ ! -z "$version" ]; then - echo "Setting bootstrap to$version_msg" + log "Setting bootstrap to$version_msg" # TODO: validate semver and valid version for the package so users cant pass in junk yarn upgrade bootstrap@$version fi else - >&2 echo "ERROR $err_code: There was a problem installing Bootstrap$version_msg$auth_msg" + >&2 log "ERROR $err_code: There was a problem installing Bootstrap$version_msg$auth_msg" fi else - version=$(. /tmp/utils.sh parse_ini_value starter.ini bootstrap version) + version=$(eval $parse bootstrap version) [ -z "$version" ] && version_msg='' || version_msg=" version $version" if [[ ! -z $version && $install_bootstrap == 1 ]]; then - echo "Setting bootstrap to$version_msg" + log "Setting bootstrap to$version_msg" yarn upgrade bootstrap@$version fi fi diff --git a/bash/init-rake-tasks.sh b/bash/init-rake-tasks.sh new file mode 100644 index 00000000..f102280e --- /dev/null +++ b/bash/init-rake-tasks.sh @@ -0,0 +1,40 @@ +#!/bin/bash + +parse="bash bash/utils.sh parse_ini_value starter.ini" +# BEGIN: dynamic rake task functions +add_changelog_rake() { + local rake='changelog' + local project=$(basename $GITPOD_REPO_ROOT) + local since_tag + local future_release + since_tag=$(eval $parse github-changelog-generator since_tag) + future_release=$(eval $parse github-changelog-generator future_release) + + # this rake task cannot handle empty strings as values so handle them (whitespace is ok though) + [ -z "$since_tag" ] && default_since_tag='' || default_since_tag="config.since_tag = '$since_tag'" + [ -z "$future_release" ] && default_future_release='' || default_future_release="config.future_release = '$future_release'" + +# Do not indent the below HEREDOC code block! +IFS='' read -r -d '' __task </s/(.*)=(.*)/\2/p}' "$1") } +# log +# Description: +# Log a message ($1) to the console and an output file ($2). Logs to stdout if no -e option ($3) is passed in. +# Logs to stdout and stderr if the -e option is passed in. +# +# Notes: +# The output file must already exist. +# Backslash escapes are interpreted in both the console +# and the output file (e.g., they are not printed literally). +# +# Usage: +# Example 1: log a standard message to the console and an output file +# log "Hello World" /var/log/test.log +# +# Example 2: log an error message to the console and an output file +# log "Hello World" /var/log/test.log -e +# +log () { + if [[ "$3" == '-e' || "$3" == '--error' ]]; then + >&2 echo -e "$1" && printf "$1\n" >> "$2" + else + echo -e "$1" && printf "$1\n" >> "$2" + fi +} + +# log_silent +# Description: +# Log a message ($1) to the console. Logs to stdout if no -e option ($2) is passed in. +# Logs to stdout and stderr if the -e option is passed in. +# +# Notes: +# Backslash escapes are interpreted in the output file (e.g., they are not printed literally). +# +# Usage: +# Example 1: log a standard message to an output file +# log "Hello World" +# +# Example 2: log an error message to an output file +# log "Hello World" -e +# +log_silent () { + if [[ "$3" == '-e' || "$3" == '--error' ]]; then + 1>&2 printf "$1\n" >> "$2" + else + printf "$1\n" >> "$2" + fi +} + # Call functions from this script gracefully if declare -f "$1" > /dev/null diff --git a/starter.ini b/starter.ini index 3cc18a44..67ce8313 100644 --- a/starter.ini +++ b/starter.ini @@ -12,14 +12,14 @@ default_server=apache [phpmyadmin] # This install happens in .gitpod.Dockerfile so it can get cached one way or the other, # force a build of the image workspace (see .gitpod.Dockerfile) to get your desired results. -install=1 +install=0 [react] # An install of react also installs and upgrades react-dom to the same version set below # if install = 1 then vue will not be installed if its install value is also set to 1 install=0 -auth=0 -version= +auth=1 +version=^17.0.1 [vue] # An install of react will supercede an install of vue, choose one or the other @@ -31,5 +31,11 @@ version= # Installs of either react or vue have bootstrap already so this section will be superceded in those cases install=0 # auth only appies here when react or vue are not installed. -auth=0 -version= \ No newline at end of file +auth=1 +version= + +[github-changelog-generator] +# Installs https://github.com/github-changelog-generator/github-changelog-generator +install=1 +since_tag= +future_release= \ No newline at end of file