Automating Project Setup with Bash
Posted on Fri 17 January 2020 in Bash_Automation
One of my plans for 2020 is working on more projects and pushing them to Github to share as well as act as a portofolio for prospective employers. i decided to reduce the barriers to achieving this goal by working on Tools to make my day to day tasks more efficient, Hence the newproject script.
This tool aims to automate the process of starting a new project as well as forcing me to upload all my projects on github.
The manual Process of Starting a Project is :
- Navigate to your project folder and create new folder
- Initialize Git Repo in new Directory
- Create a ReadMe file
- Stage ReadMe File
- Create First Commit
on the Github Page
- Create New Repo
- Copy Origin Address
- Add remote Origin to your project Directory
I decided to automate this process using a bash script due to Linux being my preferred dev environment (Ubuntu WSL2). I however intend to later port the script to a python script to enable it work on numerous platforms.
New Project Script
This is a fairly easy script to understand, i will walk you through some of the snippets which could be useful for creating your own scripts
To Skip to script usage click here here
GitHub Link to project is Here
Creating a Repo with the Github API
curl -u "${GITHUB_USERNAME}:${GITHUB_TOKEN}" https://api.github.com/user/repos -d '{"name":"'$REPO_NAME'"}' > /dev/null 2>&1
the curl command takes the url which consists of the github username, personal access token and repo name as the data to create the new repository the output is passed to /dev/null so it is not displayed on the script as some json object is returned on success.
Setting Default Variables
PROJECT_DIR=${PROJECT_DIR:-$DEFAULT_DIR}
this is used to set a default value to a variable, if the variable is not defined, it takes the 2nd value as its new value. A default_dir is hardcoded, if the Project_dir variable is not passed in to the script, the project_Dir variable takes the values of the default dir.
Bash Functions
Bash functions work almost the same way as every other scripting language, it is used in the script to define repetitive tasks. An example is coloring functions for my error and success messages. The process of getting a colored text is below
normal="\033[0m"
greentext="\033[32m"
echo -e $greentext"this color should be displayed as green to signify success"$normal
This quickly becomes stressful if you have to do it a couple of times.
Defining a function which takes in an argument of message can be used to improve this.
note bash does take in arguments in the name definitions, this can be passed into the function using the $1
arguments.
Also the local
keyword is used to make the variable local to the function so it does not change variables having the same name outside the function scope
success (){
local msg=$1
echo -e $greentext"$msg"$normal
}
success "this color should be displayed as green to signify success"
Other functions that were created are
usage
: function to display error and how the script should be used. this is called at every conditions where the script will exitcleanup
: this is used to clean up files that were created if an error occurs after folders have been created in the script.nameCheck
: function to check if repo name meets the required conventions using regex.
Parsing Commandline Arguments
This is popular in most linux commands e.g cp -r source destination. the Minus sign are commandline arguments which are used to alter the default behavior of the script. Parsing of this argument is done through getopts.
while getopts "d:u:t:f:ih" option; do
case "$option" in
i ) INTERACTIVE=1;;
d ) PROJECT_DIR=$OPTARG;;
f ) REPO_FOLDER=$OPTARG;;
u ) GITHUB_USERNAME=$OPTARG;;
t ) GITHUB_TOKEN=$OPTARG;;
h ) HELP=1;;
\? ) usage
;;
esac
done
shift $((OPTIND -1))
getopts will take a list of characters that it will accept, "d:u:tf"
, each character that is followed by a ":"
will be accepting an argument, while others act as flags.
example
newproject -d argumentforD -i
argumentforD
is passed as the argument for d
, while i
does not need any argument passed to it. The argument for D is stored in the OPTARG
variable which can then be reassigned to your defined variable.
$option
is the variable used to store the current character the while loop is on from the list of arguments. e.g it stores -d
as d, which can then be checked in the case statement to carry out the corresponding action i.e set the variable in my case
case statement works the same way as every other language, the only difference here is the \?
which is used to specify everyother character that i did not define in my case statement. my usage function is passed to trigger an error when an invalid character is passed
the last part of the getopts is the shift $((OPTIND -1))
statement. this helps in processing the arguments by shifting the current character that has been processed. e.g in example, after -d
is processed, -f
should be processed.
for more info about the getopts command: Here
Tests
Various Tests were used all through the script. the basic syntax for the tests is
if
if [[ sometest ]]; then
some action
fi
if else statement
if [[ sometest ]]; then
some action
else
some other action
fi
if elseif
if [[ sometest ]]; then
some action
elif
some other action
fi
Test Conditions
[[ -n *$VARIABLE ]]
# if a variable is set. ! -n $VARIABLE
is for the reverse case. not set
[[ -d $VARIABLE ]]
check if $value is a folder
[[ -e $VARIABLE ]]
check if folder/file exist
[[ $VARIABLE = "somevalue" ]]
if specific condition is met
bash uses "=" rather than the double equal sign in most languages.
[[ $VARIABLE =~ [$someregexvariable] ]]
to check if value does not match regex.
Reading file input
this is used to drive the interactive part of the script.
the read command is used to read input and pass to the variable passed to the command
echo -n "Enter Project Folder: (somedefault) : "
read PROJECT_DIR
echo $PROJECT_DIR
"Enter Project Folder: (somedefault) : /home/seyi/projectfolder"
"/home/seyi/projectfolder"
Dependencies
Github personal access token is required to create repo as well as making commits. Link on Creating your Personal Access Token is Here.
JQ Program for parsing responses from the git api. This checks if there is an existing repo with the same name on users github page
Installing JQ Dependency
for debian
sudo apt-get install jq
for redhat
sudo yum install jq
Usage
"Usage: newproject [ -i | -d | -f | -u | -t | -h ] repo_name"
"-i : Interactive Prompt"
"-d : Projects Directory"
"-f : Folder for Storing Repo"
"-u : Github Username"
"-t : Github Personal Access Token"
"-h : Help"
Basic Usage
newproject reponame
newproject script will create folder with the reponame in the directory set in the DEFAULT_DIR variable.
newproject -d /home/system/opt -f newfolder reponame
Project folder "newfolder" will be created in the directory passed to -d flag.
newproject -u seyio91 -t dummy_token reponame
username and token will overwrite the variables exported to shell environment during setup
newproject -i reponame
Starts the interactive session
newproject -i reponame
"Enter project Default Folder: (/home/seyi/projects)"
"Enter project Folder- Repo name will be used if no default: ()"
"Enter Git Username: (seyio91)"
"Enter Git Token: (dummy_token)"
To view help options
newproject -h
Planned Improvements.
- Specific Project Types. Ability to specify the type of project and create directory structure by project e.g creating virtual env for python or dockerfiles for docker projects
- Add Testing
GitHub Link to project is Here