Skip to content

Instantly share code, notes, and snippets.

@abhishekkr
Last active December 30, 2017 23:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save abhishekkr/72355d9db100f4a80c2925862e48b994 to your computer and use it in GitHub Desktop.
Save abhishekkr/72355d9db100f4a80c2925862e48b994 to your computer and use it in GitHub Desktop.
golang dependency and other tasks manager (stupid and homegrown, does basic job)
#!/bin/bash
#############################################################################
#
# You don't need to keep your project in GOPATH go-get dir.
# Keep your project in your normal workspace as projects on other stacks.
# This works like virtualenv, will create a local GOPATH and manage it's own via Linux's symlinks magic.
#
# 'source go-tasks'
# source this file to load all methods
# it turns on the go environment for the path it's run from
#
# './go-tasks help'
# it can be used for running regular go-tasks among
# * cfg - config specifics for go-task to be used in context of a project
# * deps - to initialize deps if missing, download them
# * deps-refresh or redep - if a new dep has been added, use this for those to be included or upgraded local
# * run - this is to run the main
# * build - this is to build main, plugin if available, migrate main if available
# * build-plugin - this is to re-build plug-ins only
# * migrate - this is to run migrate main
# * quality - thi is to run different quality checks on packages
# * test - this is to run tests on packages
#
#############################################################################
THIS_DIR=$(pwd)
cd $(dirname $0)
MY_DIR=$(pwd)
cd ${THIS_DIR}
[[ -z "${GO_TASK_CONFIG}" ]] && GO_TASK_CONFIG="${MY_DIR}/.go-tasks.cfg"
[[ -f "${GO_TASK_CONFIG}" ]] && source "${GO_TASK_CONFIG}"
[[ -z "${MY_GOPATH}" ]] && export MY_GOPATH="github.com/SOME-USER/SOME-REPO"
[[ -z "${GO_MAIN_FILE}" ]] && export GO_MAIN_FILE="main.go"
[[ -z "${DIR_OF_GO_PLUGINS}" ]] && export DIR_OF_GO_PLUGINS=""
[[ -z "${DB_MIGRATE_MAIN}" ]] && export DB_MIGRATE_MAIN=""
# managing go deps
#############################################################################
export GO_GET_PKG_FILE="go-get-pkg.txt"
#############################################################################
##### from github.com/abhishekkr/dotfiles/shell_profile/a.golang.sh
appendGoImportToListIfMissing(){
local _GO_GET_PKG_FILEPATH="$1"
for goGetPath in $(go list -f {{.Deps}} | sed 's/^\[//' | sed 's/\]$//' | sed -E 's/\s+/\n/g' | grep -v '^[a-zA-Z]*$' | xargs -I{} bash -c "[[ \$(echo {} | sed 's/\/.*//' | grep -c '\.' ) -ne 0 ]] && echo {}"); do
if [[ $(cat "${_GO_GET_PKG_FILEPATH}" | grep -c "^${goGetPath}$") -eq 0 ]]; then
echo "${goGetPath}" | tee -a "${_GO_GET_PKG_FILEPATH}" >/dev/null
fi
done
}
addGoImportsToList(){
local GO_GET_PKG_FILEPATH="$1"
appendGoImportToListIfMissing "${GO_GET_PKG_FILEPATH}"
local currentDir=$(pwd)
cd "${DIR_OF_GO_PLUGINS}"
local pluginAbsolutePath=$(pwd)
cd "${currentDir}"
for pluginMain in $(find "${pluginAbsolutePath}" -name main.go); do
[[ -z "${pluginMain}" ]] && continue
local pluginDir=$(dirname ${pluginMain})
cd "${pluginDir}"
appendGoImportToListIfMissing "${GO_GET_PKG_FILEPATH}"
cd "${currentDir}"
done
if [[ ! -z "${DB_MIGRATE_MAIN}" ]]; then
cd $(dirname "${DB_MIGRATE_MAIN}")
appendGoImportToListIfMissing "${GO_GET_PKG_FILEPATH}"
cd "${currentDir}"
fi
}
goenvOnAt(){
local _GO_ENV_PATH="$1"
local _GOPATH_VALUE="${PWD}/.goenv"
local currentDir=$(pwd)
if [ ! -z "${_GO_ENV_PATH}" ]; then
cd "${_GO_ENV_PATH}"
_GOPATH_VALUE="${_GO_ENV_PATH}/.goenv"
cd "${currentDir}"
fi
if [ ! -d $_GOPATH_VALUE ]; then
mkdir -p "${_GOPATH_VALUE}/site"
fi
export _OLD_GOPATH=$GOPATH
export _OLD_PATH=$PATH
export GOPATH=$_GOPATH_VALUE/site
export PATH=$PATH:$GOPATH/bin
if [ ! -d "${GOPATH}/src/${MY_GOPATH}" ]; then
mkdir -p $(dirname "${GOPATH}/src/${MY_GOPATH}")
ln -sf "${MY_DIR}" "${GOPATH}/src/${MY_GOPATH}"
fi
echo "your new GOPATH is at $GOPATH"
}
goenv(){
goenvOnAt $(pwd)
}
goenvoff(){
export GOPATH="$_OLD_GOPATH"
export PATH="$_OLD_PATH"
unset _OLD_PATH _OLD_GOPATH
}
goGetPkgHelp(){
echo "goGetPkg handles your Golang Project dependencies."
echo ""
echo "* Create new dependency list or install from existing:"
echo " $ $0 deps"
echo ""
echo "* Install from existing with updated dependencies"
echo " $ GO_GET_UPDATE=true $0 deps"
echo ""
echo "* Install from existing with re-prepared binaries (required on new Golang update or local changed dependency code)"
echo " $ GO_GET_RENEW=true $0 deps"
echo ""
echo "* Install from existing with updated dependencies (re-prepared binaries even if no updates)"
echo " $ GO_GET_RENEW=true GO_GET_UPDATE=true $0 deps"
}
goGetPkgListCreate(){
if [ ! -f "$1" ]; then
PKG_LISTS_DIR=$(dirname $PKG_LISTS)
mkdir -p "$PKG_LISTS_DIR" && unset PKG_LISTS_DIR
touch "${1}"
addGoImportsToList "${1}"
echo "Created GoLang Package empty list ${PKG_LISTS}"
fi
}
goGetPkgInstall(){
for pkg_list in $PKG_LISTS; do
cat $pkg_list | while read pkg_path; do
pkg_import_path=$(echo $pkg_path | awk '{print $NF}')
if [[ ! -z $GO_GET_RENEW ]]; then
rm -rf "${GOPATH}/pkg/${GOOS}_${GOARCH}/${pkg_import_path}"
echo "cleaning old pkg for ${pkg_import_path}"
fi
local go_get="go get"
if [[ ! -z $GO_GET_UPDATE ]]; then
go_get="${go_get} -u"
fi
echo "fetching go package: ${go_get} ${pkg_path}";
${go_get} ${pkg_path}
done
done
unset GO_GET_UPDATE GO_GET_RENEW
}
goGetPkgFile(){
if [[ $# -eq 0 ]]; then
PKG_LISTS="$PWD/${GO_GET_PKG_FILE}"
else
PKG_LISTS=($@)
if [[ -d "$PKG_LISTS" ]]; then
PKG_LISTS="${PKG_LISTS}/${GO_GET_PKG_FILE}"
fi
fi
echo "${PKG_LISTS}"
}
goGetPkg(){
if [[ "$1" == "help" ]]; then
goGetPkgHelp
return 0
fi
PKG_LISTS=$(goGetPkgFile $@)
goGetPkgListCreate $PKG_LISTS
if [[ -z $GO_GET_ENV ]]; then
local _GO_GET_ENV=$(dirname $PKG_LISTS)
local currentDir=$(pwd)
cd $_GO_GET_ENV
GO_GET_ENV=$(pwd)
cd ${currentDir}
fi
goenvOnAt $GO_GET_ENV
goGetPkgInstall "$PKG_LISTS"
unset _GO_GET_ENV GO_GET_ENV PKG_LISTS
}
goGetPkgRefresh(){
if [[ "$1" == "help" ]]; then
goGetPkgHelp
return 0
fi
PKG_LISTS=$(goGetPkgFile $@)
rm -f "${PKG_LISTS}"
local _GO_GET_UPDATE="${GO_GET_UPDATE}"
export GO_GET_UPDATE="true"
goGetPkg $@
export GO_GET_UPDATE="${_GO_GET_UPDATE}"
}
buildMigrate(){
[[ -z "${DB_MIGRATE_MAIN}" ]] && echo "no db migrate main provided" && return
go build -o ./bin/migrate "${DB_MIGRATE_MAIN}"
[[ $? -ne 0 ]] && echo "go build for migrate failed" && exit 123
}
buildPlugins(){
[[ -z "${DIR_OF_GO_PLUGINS}" ]] && echo "no plugins mentioned to build" && return
local currentDir=$(pwd)
cd "${DIR_OF_GO_PLUGINS}"
local pluginAbsolutePath=$(pwd)
cd "${currentDir}"
for pluginMain in $(find "${pluginAbsolutePath}" -name main.go); do
[[ -z "${pluginMain}" ]] && continue
local pluginDir=$(dirname ${pluginMain})
local pluginName=$(basename ${pluginDir})
echo "[+] building plug-in at ${pluginDir}"
cd "${pluginDir}"
go build -o "${pluginAbsolutePath}/${pluginName}.so" -buildmode=plugin .
[[ $? -ne 0 ]] && echo "go build for plugin ${pluginName} failed" && exit 123
cd "${currentDir}"
done
}
buildForAll(){
local FOR_OS_ARCH="$1"
local GO_MAIN_BIN=$(echo "${GO_MAIN_FILE}" | sed 's/.go$//')
[[ ! -f "${GO_MAIN_FILE}" ]] && \
echo "[error] missing main file ${GO_MAIN_FILE}, set correct env for GO_MAIN_FILE" && \
exit 123
buildMigrate
buildPlugins
mkdir -p ./bin
for GOOS in darwin linux windows; do
for GOARCH in 386 amd64; do
[[ ! -z "${FOR_OS_ARCH}" && "${GOOS}-${GOARCH}" != "${FOR_OS_ARCH}" ]] && continue
echo "[+] building ${GO_MAIN_FILE} for $GOOS - $GOARCH"
go build -o ./bin/${GO_MAIN_BIN}-$GOOS-$GOARCH "${GO_MAIN_FILE}"
[[ $? -ne 0 ]] && echo "go build for ${GO_MAIN_FILE}-${GOOS}-${GOARCH} failed" && exit 123
done
done
}
allPathsWithGoFiles(){
find . -maxdepth 1 -type d | grep -v -E '^\.$|^./\.git$|^./\.goenv$|^./temp$|^./vendor$'
}
goVetAll(){
go tool vet -all *.go
for loc in $(allPathsWithGoFiles); do
go tool vet -all ${loc}
done
}
goErrcheck(){
go get github.com/kisielk/errcheck
for loc in $(allPathsWithGoFiles); do
find ${loc} -type f -name *.go | xargs -I {} errcheck -abspath -asserts -blank -verbose {}
done
}
goSafesql(){
go get github.com/stripe/safesql
for loc in $(allPathsWithGoFiles); do
safesql -q=false ${loc}
done
}
goReporter(){
go get github.com/360EntSecGroup-Skylar/goreporter
for loc in $(allPathsWithGoFiles); do
goreporter -p ${loc} -f html
done
mkdir -p spec-reports/goreporter
mv ./*.html ./spec-reports/goreporter
}
goTest(){
local _GO_TEST_PATHS=""
echo ""
echo "### running ~ *goTest*"
echo ""
for loc in $(allPathsWithGoFiles); do
[[ $(ls -1 ./$loc/*.go 2>/dev/null | wc -l) -gt 0 ]] && \
_GO_TEST_PATHS="${_GO_TEST_PATHS} ${loc}/..."
done
go test -cover ${_GO_TEST_PATHS}
local _LAST_EXITCODE=$?
[[ ${_LAST_EXITCODE} -ne 0 ]] && exit ${_LAST_EXITCODE}
}
goQualityCheck(){
echo ""
echo "### running ~ *go vet*"
echo ""
goVetAll
echo ""
echo "----------------------------------------------------------------------"
echo ""
echo ""
echo "### running ~ *errorcheck*"
echo ""
goErrcheck
echo ""
echo "----------------------------------------------------------------------"
echo ""
echo ""
echo "### running ~ *safesql*"
echo ""
goSafesql
echo ""
echo "----------------------------------------------------------------------"
echo ""
echo ""
echo "### running ~ *goreporter*"
echo ""
goReporter
echo ""
echo "----------------------------------------------------------------------"
echo ""
}
migrateDB(){
echo $@
local DB_CONNSTR="$1"
local MIGRATION_TYPE="$2"
[[ -z "${DB_CONNSTR}" ]] && export DB_CONNSTR="${DB_CONNECTION_STRING}"
[[ -z "${MIGRATION_TYPE}" ]] && export MIGRATION_TYPE="up"
[[ -z "${DB_CONNSTR}" ]] && echo "env DB_IP is empty, see usage" && exit 123
go run db/schema.go -type ${MIGRATION_TYPE} -dir db/migrations -db "${DB_CONNSTR}"
}
goTasksHelp(){
echo "Use it wisely..."
echo ""
echo "Build usable binaries: '$0 build'"
echo ""
echo "Build plugins for mains in sudirs in specified plugin-directory: '$0 build-plugin'"
echo ""
echo "Run in local go env: '$0 run'"
echo ""
echo "Run db-migrations in local go env: '$0 migrate <db-connection-string> <up|down>]' | tries infer env DB_CONNECTION_STRING if no param, default 'up'"
echo ""
echo "Install tall Go lib dependencies: '$0 deps'"
goGetPkgHelp
echo ""
echo "Install tall Go lib dependencies: '$0 deps-refresh'"
}
configGoTasks(){
[[ -z "${GO_TASK_CONFIG}" ]] && GO_TASK_CONFIG="${MY_DIR}/.go-tasks.cfg"
echo -n "[+] enter 'go get'-able path for this project: "
read MY_GOPATH
echo -n "[+] main.go file or some other name which has package main: "
read GO_MAIN_FILE
echo -n "[+] if there are plug-ins provide their parent-dir path, else just press enter: "
read DIR_OF_GO_PLUGINS
echo -n "[+] if there is a separate main file handling db migration, it's path else just press enter: "
read DB_MIGRATE_MAIN
if [[ ! -z "${MY_GOPATH}" ]]; then
echo "export MY_GOPATH='${MY_GOPATH}'" > "${GO_TASK_CONFIG}"
fi
if [[ ! -z "${GO_MAIN_FILE}" ]]; then
echo "export GO_MAIN_FILE='${GO_MAIN_FILE}'" >> "${GO_TASK_CONFIG}"
fi
if [[ ! -z "${DIR_OF_GO_PLUGINS}" ]]; then
echo "export DIR_OF_GO_PLUGINS='${DIR_OF_GO_PLUGINS}'" >> "${GO_TASK_CONFIG}"
fi
if [[ ! -z "${DB_MIGRATE_MAIN}" ]]; then
echo "export DB_MIGRATE_MAIN='${DB_MIGRATE_MAIN}'" >> "${GO_TASK_CONFIG}"
fi
}
goTasks(){
local axn="$1"
goenvOnAt $PWD
case $axn in
cfg)
configGoTasks
;;
deps)
goGetPkg
;;
deps-refresh|redep)
goGetPkgRefresh
;;
run)
go run $(dirname $0)/${GO_MAIN_FILE} ${@:2}
;;
build)
bash $0 deps
buildForAll "$2"
;;
build-plugin)
bash $0 deps
buildPlugins
;;
migrate)
bash $0 deps
migrateDB ${@:2}
;;
quality)
bash $0 deps
goQualityCheck
;;
test)
bash $0 deps
goTest
;;
*)
goTasksHelp
;;
esac
}
##############################################################################
SCRIPT_NAME=$( basename ${0#-} ) #- needed if sourced no path
[[ ! -z "${BASH_SOURCE}" ]] && THIS_SCRIPT=$( basename ${BASH_SOURCE} )
if [[ ${SCRIPT_NAME} = ${THIS_SCRIPT} ]] ; then
goTasks $@
else
goenv
echo "reset to regular go configs with cmd 'goenoff', to get this local env run 'goenv'."
fi
_OLD_PWD=$PWD
cd $(dirname $0)
cd $_OLD_PWD
##############################################################################
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment