diff --git a/.gitignore b/.gitignore index 78b2ed60..09585900 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,22 @@ -# Begin: merged in from laravel8 starter project .starter.env /vendor/ /node_modules/ /public/phpmyadmin -# END: merged in from laravel8 starter project \ No newline at end of file +/node_modules +/public/hot +/public/storage +/storage/*.key +/vendor +.env +.env.backup +.phpunit.result.cache +docker-compose.override.yml +Homestead.json +Homestead.yaml +npm-debug.log +yarn-error.log +# Laravel Mix artifacts +/public/js +/public/css +/public/build +/public/mix-manifest.json diff --git a/.gitpod.Dockerfile b/.gitpod.Dockerfile index 9e9c2219..43249bea 100644 --- a/.gitpod.Dockerfile +++ b/.gitpod.Dockerfile @@ -10,10 +10,22 @@ RUN sudo touch /var/log/workspace-init.log \ RUN sudo touch /var/log/xdebug.log \ && sudo chmod 666 /var/log/xdebug.log + +RUN sudo mkdir /var/log/apache2 \ + && sudo chmod 755 /var/log/apache2 -RUN sudo apt-get update -q \ - && sudo apt-get install -y php-dev +RUN sudo touch /var/log/apache2/access.log \ + && sudo chmod 666 /var/log/apache2/access.log + +RUN sudo touch /var/log/apache2/error.log \ + && sudo chmod 666 /var/log/apache2/error.log +RUN sudo touch /var/log/apache2/other_vhosts_access.log \ + && sudo chmod 666 /var/log/apache2/other_vhosts_access.log + +RUN sudo apt-get update -q \ + && sudo apt-get install -y rsync + RUN wget http://xdebug.org/files/xdebug-3.0.2.tgz \ && tar -xvzf xdebug-3.0.2.tgz \ && cd xdebug-3.0.2 \ @@ -29,7 +41,7 @@ RUN sudo bash -c ". /tmp/update-composer.sh" && rm /tmp/update-composer.sh # gitpod trick to bypass the docker caching mechanism for all lines below this one # just increment the value each time you want to bypass the cache system -ENV INVALIDATE_CACHE=121 +ENV INVALIDATE_CACHE=123 COPY --chown=gitpod:gitpod bash/utils.sh /tmp COPY --chown=gitpod:gitpod starter.ini /tmp @@ -42,4 +54,4 @@ COPY --chown=gitpod:gitpod bash/snippets/browser-functions /tmp RUN echo "# BEGIN: custom code (not internal to gitpod)" \ && cat /tmp/server-functions >> ~/.bashrc \ && echo -e "\n" | cat /tmp/browser-functions >> ~/.bashrc \ - && echo "# END: custom code (not internal to gitpod)" \ No newline at end of file + && echo "# END: custom code (not internal to gitpod)" diff --git a/.gitpod.yml b/.gitpod.yml index eab365b8..2ca1c442 100644 --- a/.gitpod.yml +++ b/.gitpod.yml @@ -1,6 +1,6 @@ image: file: .gitpod.Dockerfile - + ports: - port: 8001 onOpen: ignore @@ -16,10 +16,14 @@ tasks: init: | bash bash/init-gitpod.sh && bash bash/init-optional-scaffolding.sh && + bash bash/init-project.sh && bash bash/init-complete.sh name: Startup - openMode: split-left command: | + if [ $(bash bash/helpers.sh is_inited) == 1 ]; then \ + gp sync-done gitpod-inited + fi; UP=$(pgrep mysql | wc -l); \ if [ "$UP" -ne 1 ]; then \ . bash/third-party/spinner.sh && @@ -33,7 +37,12 @@ tasks: name: Web Server - openMode: split-top command: | - default_server=$(bash bash/utils.sh parse_ini_value starter.ini development default_server); open_preview $default_server + . bash/third-party/spinner.sh && + start_spinner "Opening preview when system is ready..." + gp sync-await gitpod-inited && + default_server=$(bash bash/utils.sh parse_ini_value starter.ini development default_server); \ + open_preview $default_server && + stop_spinner $? name: Main Terminal vscode: diff --git a/README.md b/README.md index b108fc37..ff7f73f0 100644 --- a/README.md +++ b/README.md @@ -149,14 +149,15 @@ The exception right now is the optional installation of `phpmyadmin`. This optio -### Development Servers +### Development Servers This starter project comes pre packaged with two development servers. - Apache2 - PHP Development Sever -By default the server listed in `starter.ini` will be the server used. You can however run both servers at the same time or change your default sever. +By default the server listed in `starter.ini` will be the server used. You can however run both servers at the same time or change your default sever. +You may also run the php development server manually via the command `php artisan serve`. The default server will be started automatically when the workspace is started diff --git a/bash/init-complete.sh b/bash/init-complete.sh index 27cdd59e..c224368c 100644 --- a/bash/init-complete.sh +++ b/bash/init-complete.sh @@ -10,4 +10,5 @@ echo -e "\e[38;5;194mIf everything looks good in the above results then push the bash bash/helpers.sh persist_file /var/log/workspace-init.log # Set initialized flag - Keep this at the bottom of the file -bash bash/helpers.sh mark_as_inited \ No newline at end of file +bash bash/helpers.sh mark_as_inited +gp sync-done gitpod-inited diff --git a/bash/init-gitpod.sh b/bash/init-gitpod.sh index 2ee5b1f2..91c15fa9 100644 --- a/bash/init-gitpod.sh +++ b/bash/init-gitpod.sh @@ -26,26 +26,28 @@ start_spinner "Initializing MySql..." && gp await-port 3306 && stop_spinner $? -# Bootstrap scaffolding -if [ ! -d "$GITPOD_REPO_ROOT/bootstrap" ]; then - msg="\nMoving Laravel project from ~/temp-app to $GITPOD_REPO_ROOT" +# BEGIN: Bootstrap Laravel scaffolding + +# Move Laravel project files if they are not already in version control +if [ ! -d "$GITPOD_REPO_ROOT/vendor" ]; then + msg="\nMoving Laravel project from ~/temp-app to $GITPOD_REPO_ROOT using rsync" # TODO: replace spinner with a real progress bar for coreutils log_silent "$msg" && start_spinner "$msg" shopt -s dotglob - mv --no-clobber ~/test-app/* $GITPOD_REPO_ROOT + rsync -rlptgoD --ignore-existing ~/test-app/ $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 + log "ERROR: Failed to move Laravel project from ~/temp-app to $GITPOD_REPO_ROOT using rsync" -e else stop_spinner $err_code - log "SUCCESS: moved Laravel project from ~/temp-app to $GITPOD_REPO_ROOT" + log "SUCCESS: moved Laravel project from ~/temp-app to $GITPOD_REPO_ROOT using rsync" fi - + # BEGIN: parse configurations # Configure .editorconfig - if [ -e .editorconfig ]; then + if [ -e .editorconfig ]; then ec_type=$(bash bash/utils.sh parse_ini_value starter.ini .editorconfig type) case $(echo "$ec_type" | tr '[:upper:]' '[:lower:]') in 'laravel-js-2space') @@ -59,17 +61,44 @@ if [ ! -d "$GITPOD_REPO_ROOT/bootstrap" ]; then ;; esac fi - - # Laravel .env + + # Laravel .env [ -e .env ] && url=$(gp url 8000); sed -i'' "s#^APP_URL=http://localhost*#APP_URL=$url\nASSET_URL=$url#g" .env # END: parse configurations + # Create laravel database if it does not exist + # TODO: think more about making this dynamic as per .env + __laravel_db_exists=$(mysqlshow 2>/dev/null | grep laravel >/dev/null 2>&1 && echo "1" || echo "0") + if [ $__laravel_db_exists == 0 ]; then + __laravel_db_msg="laravel database did not exist in mysql. Creating database: laravel" + log_silent "$__laravel_db_msg" && start_spinner "$__laravel_db_msg" + mysql -e "CREATE DATABASE laravel;" + err_code=$? + if [ $err_code != 0 ]; then + stop_spinner $err_code + log "ERROR: Failed to move createe mysql database: laravel" -e + else + stop_spinner $err_code + log "SUCCESS: created mysql database: laravel" + fi + fi + # Install node packages if needed, in case the Laravel Ui front end is already in version control + if [[ -f "package.json" && ! -d "node_modules" ]]; then + log "Found a package.json but there are no node modules installed" + log " --> Installing node packages..." + yarn install + log " --> Node packages installed" + log " --> Running Laravel Mix..." + yarn run dev + log " --> Running of Laravel Mix complete" + fi + # BEGIN: Optional configurations # Super user account for phpmyadmin installed_phpmyadmin=$(. bash/utils.sh parse_ini_value starter.ini phpmyadmin install) if [ "$installed_phpmyadmin" == 1 ]; then msg="Creating phpmyadmin superuser: pmasu" - log_silent "$msg" && start_spinner "$msg" + log_silent "$msg" && start_spinner "$msg" mysql -e "CREATE USER 'pmasu'@'%' IDENTIFIED BY '123456';" mysql -e "GRANT ALL PRIVILEGES ON *.* TO 'pmasu'@'%';" err_code=$? @@ -79,6 +108,20 @@ if [ ! -d "$GITPOD_REPO_ROOT/bootstrap" ]; then else stop_spinner $err_code fi + if [ ! -d 'public/phpmyadmin/node_modules' ]; then + log "phpmyadmin node modules have not yet been installed, installing now..." + cd public/phpmyadmin && yarn install && cd ../../ + if [ $? == 0 ]; then + __pmaurl=$(gp url 8001)/phpmyadmin + log "phpmyadmin node modules installed." + log "To login to phpmyadmin:" + log " --> 1. Make sure you are serving it with apache" + log " --> 2. In the browser go to $__pmaurl" + log " --> 3. You should be able to login here using the default account. user: pmasu, pw: 123456" + else + log "ERROR: installing phpmyadmin node modules. Try installing them manually." -e + fi + 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) @@ -90,14 +133,14 @@ if [ ! -d "$GITPOD_REPO_ROOT/bootstrap" ]; then 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 + # Move and merge necessary files, then cleanup mv ~/test-app/README.md $GITPOD_REPO_ROOT/README_LARAVEL.md - rmdir ~/test-app + rm -rf ~/test-app fi +# END: Bootstrap Laravel scaffolding # Messages for github_changelog_generator -[ "$installed_changelog_gen" == 1 ] && +[ "$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" \ No newline at end of file +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 027f9c66..63d81fcf 100644 --- a/bash/init-optional-scaffolding.sh +++ b/bash/init-optional-scaffolding.sh @@ -31,15 +31,23 @@ install_bootstrap=$(eval $parse bootstrap install) # BEGIN: Install Laravel ui if needed if [[ $install_react == 1 || $install_bootstrap == 1 ]]; then 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 - log "SUCCESS: laravel/ui scaffolding installed" - log "Compiling fresh scaffolding and running Laravel Mix" - yarn install && yarn run dev + + # Assume we are using composer 2 or higher, check if the laravel/ui package has already been installed + composer show | grep laravel/ui >/dev/null && __ui=1 || __ui=0 + + if [ "$__ui" == 1 ]; then + log "However it appears that laravel/ui has already been installed, skipping this installation." else - log "ERROR $err_code: There was a problem installing laravel/ui" -e + log "Installing laravel/ui scaffolding" + composer require laravel/ui:^3.2.0 + err_code=$? + if [ $err_code == 0 ]; then + log "SUCCESS: laravel/ui scaffolding installed" + log "Compiling fresh scaffolding and running Laravel Mix" + yarn install && yarn run dev + else + log "ERROR $err_code: There was a problem installing laravel/ui" -e + fi fi fi # END: Install Laravel ui if needed @@ -48,29 +56,34 @@ fi if [ "$install_react" == 1 ]; then version=$(eval $parse react version) auth=$(eval $parse react auth) + __installed=$(bash bash/utils.sh node_package_exists react) [ -z "$version" ] && version_msg='' || version_msg=" version $version" [ "$auth" != 1 ] && auth_msg='' || auth_msg=' with --auth' 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 + if [ "$__installed" == 1 ]; then + log "However it appears that React/React DOM has already been installed, skipping this installation." else - php artisan ui react - fi - err_code=$? - if [ $err_code == 0 ]; then - 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 - 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 + log "Installing React and React DOM" + if [ "$auth" == 1 ]; then + php artisan ui react --auth + else + php artisan ui react + fi + err_code=$? + if [ $err_code == 0 ]; then + log "SUCCESS: React and React DOM$version_msg$auth_msg have been installed" + log "Compiling fresh scaffolding and running Laravel Mix" + yarn install && yarn run dev && sleep 1 && yarn run dev + if [ ! -z "$version" ]; then + 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 ] && 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 + log "ERROR $err_code: There was a problem installing React/React DOM$version_msg$auth_msg" -e fi - [ "$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 - 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 @@ -79,32 +92,41 @@ fi if [[ "$install_vue" == 1 && "$install_react" == 0 ]]; then version=$(eval $parse vue version) auth=$(eval $parse vue auth) + __installed=$(bash bash/utils.sh node_package_exists vue) [ -z "$version" ] && version_msg='' || version_msg=" version $version" [ "$auth" != 1 ] && auth_msg='' || auth_msg=' with --auth' log "Vue install directive found in starter.ini" - log "Installing Vue..." - if [ "$auth" == 1 ]; then - php artisan ui vue --auth + if [ "$__installed" == 1 ]; then + log "However it appears that Vue has already been installed, skipping this installation." else - php artisan ui vue - fi - err_code=$? - if [ $err_code == 0 ]; then - 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 - 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 + log "Installing Vue..." + if [ "$auth" == 1 ]; then + php artisan ui vue --auth + else + php artisan ui vue + fi + err_code=$? + if [ $err_code == 0 ]; then + 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 + 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 ] && log "Bootstrap install directive found but ignored. Already installed." + else + log "ERROR $err_code: There was a problem installing Vue$version_msg$auth_msg" -e fi - [ "$install_bootstrap" == 1 ] && log "Bootstrap install directive found but ignored. Already installed." - else - log "ERROR $err_code: There was a problem installing Vue$version_msg$auth_msg" -e fi fi # END: Optional vue install +# TODO: test bootstrap install without any detection for an existing install. +# If nothing is affected like app.js then install wont need to be skipped. +# otherwise implement the same fix for existing installs that we have for react and vue. + # BEGIN: Optional bootstrap install if [[ $install_bootstrap == 1 && $install_react == 0 && $install_vue == 0 ]]; then version=$(eval $parse bootstrap version) @@ -139,8 +161,4 @@ else yarn upgrade bootstrap@$version fi fi -# END: Optional bootstrap install - - - - +# END: Optional bootstrap install \ No newline at end of file diff --git a/bash/init-project.sh b/bash/init-project.sh new file mode 100644 index 00000000..5771f510 --- /dev/null +++ b/bash/init-project.sh @@ -0,0 +1,37 @@ +#!/bin/bash + +# 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 +} + +# BEGIN example code block - migrate database +# COMMENT: Load spinner +# . bash/third-party/spinner.sh +# __migrate_msg="Migrating database" +# log_silent "$__migrate_msg" && start_spinner "$__migrate_msg" +# php artisan migrate +# err_code=$? +# if [ $err_code != 0 ]; then +# stop_spinner $err_code +# log "ERROR: Failed to migrate database" -e +# else +# stop_spinner $err_code +# log "SUCCESS: migrated database" +# fi + +# BEGIN example code block - migrate database + diff --git a/bash/scaffold-project.sh b/bash/scaffold-project.sh index 8542580b..429b25d3 100644 --- a/bash/scaffold-project.sh +++ b/bash/scaffold-project.sh @@ -5,7 +5,7 @@ # Description:Creates all project files in /tmp # Author: Apolo Pena # -# NOTE: This script assumes it is being run from .gitpod.Dockerfile +# NOTE: This script assumes it is being run from .gitpod.Dockerfile # and all of this scripts dependencies have already been copied to /tmp LOG='/var/log/workspace-image.log' @@ -38,4 +38,4 @@ else fi fi fi -echo "END: Scaffolding Laravel Project" | tee -a $LOG \ No newline at end of file +echo "END: Scaffolding Laravel Project" | tee -a $LOG diff --git a/bash/utils.sh b/bash/utils.sh index 1c14625c..cab5a3d9 100644 --- a/bash/utils.sh +++ b/bash/utils.sh @@ -6,11 +6,11 @@ # Note: Do not execute this script witout calling a function from it # # Usage: bash arg1 arg2 arg3 ... -# +# version () { - echo "utils.sh version 0.0.4" + echo "utils.sh version 0.0.5" } # Use absolute paths or paths relative to this script @@ -26,7 +26,7 @@ version () { # Error code 0 if all files exist # Error code 1 if any file doesn't exist. Function exits on the first file that doesn't exist. # When a file does not exist a message is echoed to the console. -# +# # Notes: # The marker is a regexp expression so it must have any regexp characters in it double escaped. # @@ -50,7 +50,7 @@ check_files_exist () { # add_file_to_file_before # Description: # Adds the contents of file ($2) into another file ($3) before the marker ($1) -# +# # Notes: # The marker is a regexp expression so it must have any regexp characters in it double escaped. # @@ -67,7 +67,7 @@ add_file_to_file_before() { # add_file_to_file_after # Description: # Adds the contents of file ($2) into another file ($3) after the marker ($1) -# +# # Notes: # The marker is a regexp expression so it must have any regexp characters in it double escaped. # @@ -84,11 +84,11 @@ add_file_to_file_after() { # parse_ini_value # Description: # Echoes the value of a variable ($3) for a name value pair under a section ($2) in an .ini file ($1) -# +# # Notes: # Comments are ignored. # Comments are either a pound sign # or a semicolon ; at the beginning of a line. -# The name argument ($3) and the section argument ($2) +# The name argument ($3) and the section argument ($2) # must be simple strings with no special regex characters in them. # If a value is not set then an empty string with be echoed. # @@ -110,10 +110,10 @@ parse_ini_value() { # 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 +# Backslash escapes are interpreted in both the console # and the output file (e.g., they are not printed literally). # # Usage: @@ -135,7 +135,7 @@ log () { # 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). # @@ -154,6 +154,36 @@ log_silent () { fi } +# node_package_exists +# Description: +# Checks is a node package directory ($1) is present on the file system +# An optional argument ($2) of the location to make the check can be passed +# otherwise the current working directory will be searched +# Echos 1 if a directory with the name of the node package ($1) exists within +# a directory named node_modules +# Echos 0 if a directory with the name of the node package ($1) does not exists within +# a directory named node_modules or if the node_modules directory does not exist +# +# Notes: +# If using the optional location argument ($2), make sure the path is valid +# or you can get a false negative +# +# Usage: +# Example 1: +# # Check if the node package react exists in the current working directory (assume that is does) +# node_package_is_installed react # echos 1 +# Example 2: +# # Check if the node package foobar exists in the current working directory (assume that is does not) +# node_package_is_installed foobar # echos 0 +# Example 3: +# # Check if the node package react exists in the foo/bar/baz (assume that is does) +# node_package_is_installed react foo/bar/baz # echos 1 + +node_package_exists () { + [ -z $2 ] && local path='node_modules' || local path="$2/node_modules" + ls "$path" 2>/dev/null | grep -w $1 >/dev/null 2>&1 && echo "1" || echo "0" +} + # Call functions from this script gracefully if declare -f "$1" > /dev/null @@ -163,4 +193,4 @@ then else echo "utils.sh: '$1' is not a known function name." >&2 exit 1 -fi \ No newline at end of file +fi