Last active
December 30, 2017 23:47
-
-
Save abhishekkr/72355d9db100f4a80c2925862e48b994 to your computer and use it in GitHub Desktop.
golang dependency and other tasks manager (stupid and homegrown, does basic job)
This file contains 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
#!/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