Skip to content

Commit a0e26b8

Browse files
authored
Merge pull request #7 from jetpack-io/landau/go-monorepo
[go] Add go monorepo plugin
2 parents 50173aa + 3e33483 commit a0e26b8

File tree

4 files changed

+200
-0
lines changed

4 files changed

+200
-0
lines changed

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ This repository includes plugins for configuring packages using Devbox.
44

55
## Available Plugins
66

7+
* Go Monorepo (experimental)
78
* MongoDB
89
* RabbitMQ
910
* NATS Server

go-monorepo/README.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# Go Monorepo Plugin
2+
3+
Experimental!
4+
5+
This plugin helps manage go monorepos.

go-monorepo/gotidy.sh

+151
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
#!/bin/bash
2+
# shellcheck shell=sh
3+
4+
# Credit to @gcurtis for this script!
5+
6+
set -e
7+
8+
if [ "$1" = "-h" ] || [ "$1" = "-help" ] || [ "$1" = "--help" ]; then
9+
echo "usage: $0 [-u | -u direct | -u go]"
10+
echo
11+
echo "gotidy tidies the go.mod files in the current repo and checks that each module"
12+
echo "compiles independently of the workspace. If -u is set, it also updates the"
13+
echo "dependencies of each module. If -u is set to \"go\" then it only updates the Go"
14+
echo "version. If -u is set to \"direct\" then it only updates the direct dependencies"
15+
echo "of each module. Restricting updates to direct dependencies is useful when there"
16+
echo "are prerelease packages with updates that aren't backwards compatible."
17+
exit 2
18+
fi
19+
20+
if [ "$1" = "-u" ]; then
21+
case "$2" in
22+
"")
23+
update_deps=1
24+
;;
25+
"direct")
26+
update_deps=1
27+
direct_deps_only=1
28+
;;
29+
"go")
30+
update_go=1
31+
;;
32+
*)
33+
echo "invalid value \"$2\" for -u flag (must be empty, \"direct\", or \"go\")"
34+
exit 1
35+
;;
36+
esac
37+
elif [ "$1" != "" ]; then
38+
echo "invalid flag \"$1\""
39+
exit 1
40+
fi
41+
42+
# Restore the current directory before exiting.
43+
pwd="$(pwd)"
44+
trap 'cd "${pwd}"' EXIT INT TERM HUP
45+
46+
# Start at the repo root to get a list of all Go modules in the workspace.
47+
repo="$(git rev-parse --show-toplevel)"
48+
cd "${repo}"
49+
50+
# go work use to make sure the workspace Go version is compatible with the
51+
# modules' Go versions.
52+
go work use
53+
mods="$(go list -m -f "{{`{{.Dir}}`}}")"
54+
55+
# Disable workspaces to ensure that each module builds successfully outside of
56+
# the workspace. This is important for Docker containers or mirrored open
57+
# source repos where the workspace won't exist.
58+
export GOWORK=off
59+
60+
# Update the Go version first, since that will influence how Go updates
61+
# dependencies and tidies the modules.
62+
if [ "${update_go}" = 1 ]; then
63+
for dir in ${mods}; do
64+
if ! cd "${dir}"; then
65+
echo "$0: ${dir}: skipping directory"
66+
continue
67+
fi
68+
69+
echo "$0: ${dir}: checking for newer Go version"
70+
go get go@latest
71+
done
72+
fi
73+
74+
if [ "${update_deps}" = 1 ]; then
75+
for dir in ${mods}; do
76+
if ! cd "${dir}"; then
77+
echo "$0: ${dir}: skipping directory"
78+
continue
79+
fi
80+
81+
# Tidy before the update to make sure all the necessary
82+
# dependencies are in go.mod.
83+
echo "$0: ${dir}: tidying go.mod"
84+
go mod tidy -e
85+
86+
# Manually list out the dependencies instead of go get -u ./...
87+
# so we can filter them.
88+
echo "$0: ${dir}: checking for dependency updates"
89+
deps="$(go mod edit -json | jq -c ".Require[]")"
90+
for dep in ${deps}; do
91+
dep_path="$(echo "${dep}" | jq -r ".Path")"
92+
if [ "${direct_deps_only}" = 1 ] && echo "${dep}" | jq -e ".Indirect" >/dev/null; then
93+
echo "$0: ${dir}: skipping indirect dependency ${dep_path}"
94+
continue
95+
fi
96+
97+
# To temporarily skip a problematic update:
98+
#
99+
# if [ "${dep_path}" = "bad_dependency" ]; then
100+
# continue
101+
# fi
102+
echo "$0: ${dir}: checking for updates to ${dep_path}"
103+
go get -u -t "${dep_path}"
104+
done
105+
done
106+
fi
107+
108+
# Final tidy and ensure all packages build without the workspace.
109+
for dir in ${mods}; do
110+
if ! cd "${dir}"; then
111+
echo "$0: ${dir}: skipping directory"
112+
continue
113+
fi
114+
115+
echo "gotidy ${dir}: tidying go.mod"
116+
go mod tidy
117+
118+
echo "gotidy ${dir}: downloading dependencies"
119+
go mod download
120+
121+
echo "gotidy ${dir}: formatting module"
122+
go fmt ./...
123+
124+
echo "gotidy ${dir}: building module"
125+
go build ./...
126+
127+
echo "gotidy ${dir}: building module tests"
128+
go test -c -o /dev/null ./...
129+
done
130+
131+
# Reenable the workspace to sync all of the modules' transitive
132+
# dependencies and ensure everything still builds.
133+
export GOWORK=auto
134+
cd "${repo}"
135+
go work sync
136+
go mod download
137+
138+
for dir in ${mods}; do
139+
if ! cd "${dir}"; then
140+
echo "$0: ${dir}: skipping directory"
141+
continue
142+
fi
143+
144+
echo "gotidy ${dir}: building module"
145+
go build ./...
146+
147+
echo "gotidy ${dir}: building module tests"
148+
go test -c -o /dev/null ./...
149+
done
150+
151+
git --no-pager diff --stat

go-monorepo/plugin.json

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
{
2+
"name": "go-monorepo",
3+
"description": "Go monorepo plugin",
4+
"packages": {
5+
"go": "latest",
6+
"golangci-lint": "latest",
7+
},
8+
"env": {
9+
"GOENV": "off",
10+
},
11+
"shell": {
12+
"init_hook": [
13+
// Remove Go environment variables that might've been inherited from the
14+
// user's environment and could affect the build.
15+
"test -z $FISH_VERSION && \\",
16+
"unset CGO_ENABLED GO111MODULE GOARCH GOFLAGS GOMOD GOOS GOROOT GOTOOLCHAIN GOWORK || \\",
17+
"set --erase CGO_ENABLED GO111MODULE GOARCH GOFLAGS GOMOD GOOS GOROOT GOTOOLCHAIN GOWORK",
18+
// Shell function that evals its arguments inside each Go module in the
19+
// workspace. For example, `for_each_gomod go test ./...` runs tests for
20+
// every module.
21+
"for_each_gomod() {",
22+
" pwd=\"$(pwd)\"",
23+
" for dir in $(go list -m -f '{{`{{.Dir}}`}}'); do",
24+
" echo \"$dir: $*\" && cd \"$dir\" && \"$@\"",
25+
" done",
26+
" cd \"$pwd\" || return",
27+
"}"
28+
],
29+
"scripts": {
30+
"tidy": "bash {{.Virtenv}}/gotidy.sh",
31+
"update": "bash {{.Virtenv}}/gotidy.sh -u",
32+
"build": "for_each_gomod go build -v ./...",
33+
// TODO: fmt and lint is not correctly running on all projects.
34+
// Some projects need "devbox run fmt" and "devbox run lint".
35+
"fmt": "for_each_gomod go fmt ./...",
36+
"lint": "for_each_gomod golangci-lint run --timeout 300s",
37+
"test": "for_each_gomod go test -race -cover -v ./...",
38+
}
39+
},
40+
"create_files": {
41+
"{{.Virtenv}}/gotidy.sh": "gotidy.sh",
42+
}
43+
}

0 commit comments

Comments
 (0)