Created
January 27, 2022 12:44
-
-
Save nicknisi/a26f148611517e3d998eb456ac57efff to your computer and use it in GitHub Desktop.
Create a new worktree, install dependencies, and run an initial build
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
# This script should help facilitate setting up a new worktree, including: | |
# - creating a new worktree | |
# - installing dependencies | |
# - creating a new branch | |
set -Eeuo pipefail | |
trap cleanup SIGINT SIGTERM ERR EXIT | |
# shellcheck disable=SC2034 | |
script_dir=$(cd "$(dirname "${BASH_SOURCE[0]}")" &>/dev/null && pwd -P) | |
usage() { | |
cat <<EOF | |
Usage: $(basename "${BASH_SOURCE[0]}") [-h] [-v] [-f] [-b] [-B] [-p] [-N] <path> | |
Script the creation of a new worktree. | |
Available options: | |
-h, --help Print this help and exit | |
-v, --verbose Print script debug info | |
-b, --branch The branch to create | |
-B, --base The branch to use as the base for the new worktree (default: develop) | |
-p, --prefix The prefix to apply to the branch name (default: $(git config github.user)/) | |
-N, --no-create-upstream Do not create an upstream branch | |
This script performs the following steps: | |
1. Create a new worktree, based off the base branch (default: develop) | |
2. Create a new upstream branch to track the work | |
2. Install dependencies | |
3. Run a build | |
EOF | |
exit | |
} | |
cleanup() { | |
trap - SIGINT SIGTERM ERR EXIT | |
tput cnorm # enable cursor | |
# script cleanup here | |
} | |
setup_colors() { | |
if [[ -t 2 ]] && [[ -z "${NO_COLOR-}" ]] && [[ "${TERM-}" != "dumb" ]]; then | |
# shellcheck disable=SC2034 | |
NOFORMAT='\033[0m' GRAY='\033[0;90m' RED='\033[0;31m' GREEN='\033[0;32m' ORANGE='\033[0;33m' BLUE='\033[0;34m' PURPLE='\033[0;35m' CYAN='\033[0;36m' YELLOW='\033[1;33m' | |
else | |
# shellcheck disable=SC2034 | |
NOFORMAT='' GRAY='' RED='' GREEN='' ORANGE='' BLUE='' PURPLE='' CYAN='' YELLOW='' | |
fi | |
} | |
msg() { | |
echo >&2 -e "${1-}" | |
} | |
# log() { | |
# echo >&2 -ne "${1-}" | |
# } | |
info() { | |
msg "${GRAY}[INFO]${NOFORMAT} ${1-}" | |
} | |
die() { | |
local msg=$1 | |
local code=${2-1} # default exit status 1 | |
msg "$msg" | |
exit "$code" | |
} | |
function spinner() { | |
# make sure we use non-unicode character type locale | |
# (that way it works for any locale as long as the font supports the characters) | |
local LC_CTYPE=C | |
local pid=$1 # Process Id of the previous running command | |
local spin='⣾⣽⣻⢿⡿⣟⣯⣷' | |
local charwidth=3 | |
local i=0 | |
tput civis # cursor invisible | |
while kill -0 "$pid" 2>/dev/null; do | |
local i=$(((i + charwidth) % ${#spin})) | |
printf >&2 "%s" "${spin:$i:$charwidth}" | |
printf >&2 "\b" | |
sleep .1 | |
done | |
tput cnorm | |
wait "$pid" # capture exit code | |
return $? | |
} | |
run_command() { | |
local message=$1 | |
shift | |
echo >&2 -ne "$message " | |
"$@" &>/dev/null & | |
spinner $! | |
# shellcheck disable=SC2181 | |
if [ $? -eq 0 ]; then | |
echo >&2 -e " ${GREEN}Done.${NOFORMAT}" | |
else | |
echo >&2 -e " ${RED}FAILED.${NOFORMAT}" | |
exit 1 | |
fi | |
} | |
parse_params() { | |
# default values of variables set from params | |
create_upstream=1 | |
prefix="$(git config github.user)/" | |
base='origin/develop' | |
branch='' | |
while :; do | |
case "${1-}" in | |
-h | --help) usage ;; | |
-v | --verbose) set -x ;; | |
--no-color) NO_COLOR=1 ;; | |
-N | --no-create-upstream) create_upstream=0 ;; | |
-b | --branch) | |
branch="$2" | |
shift | |
;; | |
-B | --base) | |
base="${2-}" | |
shift | |
;; | |
-?*) die "Unknown option: $1" ;; | |
*) break ;; | |
esac | |
shift | |
done | |
args=("$@") | |
# check required params and arguments | |
# [[ -z "${param-}" ]] && die "Missing required parameter: param" | |
[[ ${#args[@]} -eq 0 ]] && die "Missing script arguments" | |
# if a branch was not specified, generate one based on the prefix and folder name | |
if [[ -z "$branch" ]]; then | |
branch="${prefix}${args[0]}" | |
fi | |
worktree="${args[0]}" | |
return 0 | |
} | |
parse_params "$@" | |
setup_colors | |
update_remote() { | |
local branch="$1" | |
# do nothing if create_upstream is disabled | |
[ $create_upstream -eq 0 ] && return 0 | |
if [[ -z "$(git ls-remote --heads origin "$branch")" ]]; then | |
# create remote branch | |
msg "${GRAY}Branch '$branch' does not exist on remote. Creating." | |
run_command "Creating remote branch ${branch}..." git push -u origin "$branch" | |
else | |
msg "${GRAY}Branch '$branch' exists. Setting upstream." | |
run_command "Setting upstream branch to 'origin/$branch'" git branch --set-upstream-to="origin/$branch" | |
fi | |
} | |
# check if branch already exists | |
if [[ -n "$(git branch --list "$branch")" ]]; then | |
run_command "Generating new worktree from existing branch: $branch" git worktree add "$worktree" "$branch" | |
else | |
run_command "Generating new worktree: $worktree" git worktree add -b "$branch" "$worktree" "$base" | |
fi | |
msg "${GRAY}Moving into worktree: $worktree${NOFORMAT}" | |
cd "$worktree" | |
update_remote "$branch" | |
run_command "Setting Node version" fnm use < .nvmrc | |
run_command "Installing dependencies" npm --no-progress --silent install | |
run_command "Building App" npm run --silent build | |
msg "${GREEN}Success.${NOFORMAT}" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
The script accepts the following arguments and options, with all possible combinations based on the provided logic. Below is a concise breakdown of the possible ways to use the script, including required arguments and optional flags.
Script Usage
Required Argument
<path>
: The path for the new worktree (mandatory). Used as part of the branch name if-b
is not specified.Optional Flags and Parameters
-h
,--help
: Print help and exit.-v
,--verbose
: Enable debug output.-b <branch>
,--branch <branch>
: Specify the branch name (overrides default branch name:<prefix><path>
).-B <base>
: Specify the base branch (default:origin/develop
).-N
,--no-create-upstream
: Disable creating an upstream branch.--no-color
: Disable colors output (not listed in usage but supported).Default Values
$(git config github.user)/
(used if-b
is not provided).masterorigin/develop
.-b
is not specified, generated as<prefix><path>
.All Possible Combinations
The script requires at least
<path>
. Optional flags can be combined in any order, except-h
(which exits immediately). Below are the valid combinations, grouped by key scenarios:1. Minimal Usage
./script.sh <path>
<path>
, branch named<prefix><path>
, based onorigin/develop
, with upstream branch creation.2. With Specific Branch (
-b
)./script.sh -b <branch> <path>
<path>
, uses specified<branch>
, based onorigin/develop
, with upstream branch creation../script.sh -b <branch> -B <base> <path>
<base>
instead oforigin/develop
../script.sh -b <branch> -N <path>
-b <branch> <path>
, but no upstream branch creation../script.sh -b <branch> -B <base> -N <path>
<branch>
,<base>
, and no upstream creation.3. With Custom Base Branch (
-B
)./script.sh -B <base> <path>
<path>
, branch named<prefix><path>
, based on specified<base>
, with upstream branch creation../script.sh -B <base> -N <path>
4. Without Upstream Branch Creation (
-N
)./script.sh -N <path>
<path>
, branch named<prefix><path>
, based onorigin/develop
, no upstream branch creation.5. With Verbose Output (
-v
)./script.sh -v <path>
./script.sh -v -b <branch> <path>
./script.sh -v -B <base> <path>
./script.sh -v -N <path>
./script.sh -v -b <branch> -B <base> -N <path>
6. Without Color Output (
--no-color
)./script.sh --no-color <path>
./script.sh --no-color -b <branch> <path>
./script.sh --no-color -B <base> <path>
./script.sh --no-color -N <path>
./script.sh --no-color -v -b <branch> -B <base> -N <path>
7. Help Flag (
-h
)./script.sh -h
or./script.sh --help
Example Combinations
./script.sh my-worktree
my-worktree
, Branch:<github.user>/my-worktree
, Base:origin/develop
, Upstream: Yes./script.sh -b feature/new-thing my-worktree
my-worktree
, Branch:feature/new-thing
, Base:origin/develop
, Upstream: Yes./script.sh -B main -N my-worktree
my-worktree
, Branch:<github.user>/my-worktree
, Base:main
, Upstream: No./script.sh -v -b bugfix/issue-123 -B release/v1.0 -N my-worktree
my-worktree
, Branch:bugfix/issue-123
, Base:release/v1.0
, Upstream: No, Verbose: Yes./script.sh --no-color -b test-branch my-worktree
my-worktree
, Branch:test-branch
, Base:origin/develop
, Upstream: Yes, No colorsNotes
-p
flag is listed in the usage but not implemented in the script, so it’s ignored.-x
) cause the script to exit with an error.<path>
results in an error.<path>
must be last.git
,fnm
, andnpm
are available in the environment.This covers all valid ways to invoke the script based on its logic.