-
Notifications
You must be signed in to change notification settings - Fork 179
/
Makefile
323 lines (278 loc) · 12.4 KB
/
Makefile
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
VERSION=$(shell git describe --tags --always)
COMMIT=$(shell git rev-parse HEAD)
BUILD=$(shell date +%FT%T%z)
PKG=github.com/guacsec/guac/pkg/version
LDFLAGS="-X $(PKG).Version=$(VERSION) -X $(PKG).Commit=$(COMMIT) -X $(PKG).Date=$(BUILD)"
CONTAINER ?= docker
CPUTYPE=$(shell uname -m | sed 's/x86_64/amd64/')
GITHUB_REPOSITORY ?= guacsec/guac
LOCAL_IMAGE_NAME ?= local-organic-guac
.DEFAULT_GOAL := build
.PHONY: all
all: test cover fmt lint build generate
# Run the unit tests
.PHONY: test
test: generate check-gotestsum-tool-check
echo 'mode: atomic' > coverage.txt
gotestsum --format=standard-verbose -- \
-covermode=atomic -coverprofile=coverage.txt -v -race -timeout=30s ./...
# Run the integration tests. Requires github token for scorecard (GITHUB_AUTH_TOKEN=<your token>)
# To run it locally you can run the following command: make start-integration-service
.PHONY: integration-test
integration-test: generate check-env check-gotestsum-tool-check
gotestsum --format=standard-verbose -- \
-tags=integration ./...
# Runs the integration tests locally using docker-compose to start the dependencies and cleans up after itself.
.PHONY: integration-test-local
integration-test-local: generate check-env start-integration-service
# wait for the service to start which is a http server at 8080 port
@echo "Waiting for the service to start"
@counter=0; \
while [ $$counter -lt 15 ] && ! curl --silent --head --output /dev/null --fail http://localhost:8080; do \
printf '.'; \
sleep 1; \
counter=$$((counter+1)); \
done; \
[ $$counter -eq 15 ] && { echo "Service did not start in time"; exit 1; } || echo "Service is up!"
ENT_TEST_DATABASE_URL='postgresql://guac:guac@localhost/guac?sslmode=disable' go test -p 1 -tags=integration ./...
$(CONTAINER) compose down
.PHONY: integration-merge-test
integration-merge-test: generate check-env
go test -tags=integrationMerge ./...
.PHONY: check-env
ifndef GITHUB_AUTH_TOKEN
$(error GITHUB_AUTH_TOKEN is not set)
endif
# Run all the tests and opens the coverage report
.PHONY: cover
cover: test
go tool cover -html=coverage.txt
# Check the formatting
.PHONY: fmt
fmt:
@echo "Testing formatting and imports"
test -z "$(shell git diff --name-status $(git symbolic-ref refs/remotes/origin/HEAD | sed 's@^refs/remotes/origin/@@') -- '*.go' | grep '.go$$' | grep -v '^D' | grep -v '*.pb.go' | grep -v 'vendor/*' | cut -f 2- | xargs -n 1 -P 4 goimports -l -e)"
@echo "Testing copyright notice"
test -z "$(shell git diff --name-status $(git symbolic-ref refs/remotes/origin/HEAD | sed 's@^refs/remotes/origin/@@') -- '*.go' | grep '.go$$' | grep -v '^D' | grep -v '*.pb.go' | grep -v 'vendor/*' | cut -f 2- | xargs -n 1 -P 4 .github/scripts/copyright.sh)"
# Check that generated files are up to date
.PHONY: generated_up_to_date
generated_up_to_date: generate
test -z "$(shell git status -s)"
# Run all the linters
.PHONY: lint
lint: check-golangci-lint-tool-check
golangci-lint run ./...
.PHONY: proto
proto:
protoc --go_out=. --go_opt=paths=source_relative \
--go-grpc_out=. --go-grpc_opt=paths=source_relative \
pkg/collectsub/collectsub/collectsub.proto
# Run atlas to generate ent migration diff for postgres
.PHONY: atlas-diff
atlas-diff: check-atlas-tool-check
atlas migrate diff ent_diff \
--dir "file://pkg/assembler/backends/ent/migrate/migrations" \
--to "ent://pkg/assembler/backends/ent/schema" \
--dev-url "docker://postgres/15/test?search_path=public"
# Run atlas lint to validate and analayze the contents of the migration
.PHONY: atlas-lint
atlas-lint: check-atlas-tool-check
atlas migrate lint \
--dir "file://pkg/assembler/backends/ent/migrate/migrations" \
--dev-url "docker://postgres/15/test?search_path=public" \
--latest=1
# Remove temporary files
.PHONY: clean
clean:
go clean
# Absolutely awesome: http://marmelab.com/blog/2016/02/29/auto-documented-makefile.html
.PHONY: help
help:
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'
# Run all the formatting tasks
.PHONY: format
format: fmt-md
# Format all the markdown files
.PHONY: fmt-md
fmt-md:
npx --yes prettier --write --prose-wrap always **/*.md
# generate code from autogen tools (gqlgen, genqlclient, mockgen, ent)
.PHONY: generate
generate: atlas-diff
go generate ./...
# build bins for goos/goarch of current host
.PHONY: build_bins
build_bins:
goreleaser build --clean --snapshot --single-target
# Build bins and copy to ./bin to align with docs
# Separate build_bins as its own target to ensure (workaround) goreleaser finish writing dist/artifacts.json
.PHONY: build
build: check-goreleaser-tool-check build_bins
@mkdir -p bin
@echo "$(shell cat dist/artifacts.json | jq '.[] | select(.type == "Binary") | { path: .path, name: .extra.ID } | join(" ")' -r)" | xargs -n 2 sh -c 'cp $$0 ./bin/$$1'
@echo "\nThe guac bins are available in ./bin"
.PHONY: build_local_container
build_local_container: GORELEASER_CURRENT_TAG ?= v0.0.0-$(LOCAL_IMAGE_NAME)
build_local_container:
# docker CLI options are inconsistent across platforms; had to use the pretty print output here to extract the current context
GITHUB_REPOSITORY=$(GITHUB_REPOSITORY) \
GORELEASER_CURRENT_TAG=$(GORELEASER_CURRENT_TAG) \
DOCKER_CONTEXT=$(shell docker context ls | grep '*' | awk '{print $$1}') \
goreleaser release --clean --snapshot --skip=sign --skip=sbom
# Build and package a guac container for local testing
# Separate build_container as its own target to ensure (workaround) goreleaser finish writing dist/artifacts.json
.PHONY: container
container: check-docker-tool-check check-docker-buildx-tool-check check-goreleaser-tool-check build_local_container
# tag/name the image according to current docs to avoid changes
@$(CONTAINER) tag \
"$(shell cat dist/artifacts.json | jq --raw-output '.[] | select( .type =="Docker Image" ) | select( .goarch =="$(CPUTYPE)" ).name')" \
$(LOCAL_IMAGE_NAME)
@echo "\nThe guac container image is tagged locally as $(LOCAL_IMAGE_NAME)"
# To run the service, run `make container` and then `make start-service`
# making the container is a longer process and thus not a dependency of service.
.PHONY: start-service
start-service: check-docker-compose-tool-check
# requires force recreate since docker compose reuses containers and neo4j does
# not handle that well.
#
# if container images are missing, run `make container` first
$(CONTAINER) compose -f docker-compose.yml -f container_files/mem.yaml up --force-recreate
@echo "Waiting for the service to start"
@counter=0; \
while [ $$counter -lt 15 ] && ! curl --silent --head --output /dev/null --fail http://localhost:8080; do \
printf '.'; \
sleep 1; \
counter=$$((counter+1)); \
done; \
[ $$counter -eq 15 ] && { echo "Inmem GUAC service did not start in time"; exit 1; } || echo "Inmem GUAC service is up!"
# to flush state, service-stop must be used else state is taken from old containers
.PHONY: stop-service
stop-service:
$(CONTAINER) compose down
# start graphQL server with inmem backend
.PHONY: start-inmem-db
start-inmem-db: check-docker-compose-tool-check
$(CONTAINER) compose -f docker-compose.yml -f container_files/mem.yaml up -d 2>&1
@echo "Waiting for the service to start"
@counter=0; \
while [ $$counter -lt 15 ] && ! curl --silent --head --output /dev/null --fail http://localhost:8080; do \
printf '.'; \
sleep 1; \
counter=$$((counter+1)); \
done; \
[ $$counter -eq 15 ] && { echo "Inmem GUAC service did not start in time"; exit 1; } || echo "Inmem GUAC service is up!"
# start graphQL server with keyvalue-redis backend
.PHONY: start-redis-db
start-redis-db: check-docker-compose-tool-check
$(CONTAINER) compose -f docker-compose.yml -f container_files/redis.yaml up -d 2>&1
@echo "Waiting for the service to start"
@counter=0; \
while [ $$counter -lt 15 ] && ! curl --silent --head --output /dev/null --fail http://localhost:8080; do \
printf '.'; \
sleep 1; \
counter=$$((counter+1)); \
done; \
[ $$counter -eq 15 ] && { echo "Redis GUAC service did not start in time"; exit 1; } || echo "Redis GUAC service is up!"
# start graphQL server with keyvalue-tikv backend
.PHONY: start-tikv-db
start-tikv-db: check-docker-compose-tool-check
$(CONTAINER) compose -f docker-compose.yml -f container_files/tikv.yaml up -d 2>&1
@echo "Waiting for the service to start"
@counter=0; \
while [ $$counter -lt 15 ] && ! curl --silent --head --output /dev/null --fail http://localhost:8080; do \
printf '.'; \
sleep 1; \
counter=$$((counter+1)); \
done; \
[ $$counter -eq 15 ] && { echo "Tikv GUAC service did not start in time"; exit 1; } || echo "Tikv GUAC service is up!"
# start graphQL server with arango backend
.PHONY: start-arango-db
start-arango-db: check-docker-compose-tool-check
$(CONTAINER) compose -f docker-compose.yml -f container_files/arango.yaml up -d 2>&1
@echo "Waiting for the service to start"
@counter=0; \
while [ $$counter -lt 15 ] && ! curl --silent --head --output /dev/null --fail http://localhost:8080; do \
printf '.'; \
sleep 1; \
counter=$$((counter+1)); \
done; \
[ $$counter -eq 15 ] && { echo "Arango GUAC service did not start in time"; exit 1; } || echo "Arango GUAC service is up!"
# start graphQL server with ent backend
.PHONY: start-ent-db
start-ent-db: check-docker-compose-tool-check
$(CONTAINER) compose -f docker-compose.yml -f container_files/ent.yaml up -d 2>&1
@echo "Waiting for the service to start"
@counter=0; \
while [ $$counter -lt 15 ] && ! curl --silent --head --output /dev/null --fail http://localhost:8080; do \
printf '.'; \
sleep 1; \
counter=$$((counter+1)); \
done; \
[ $$counter -eq 15 ] && { echo "Ent GUAC service did not start in time"; exit 1; } || echo "Ent GUAC service is up!"
# This is a helper target to run the integration tests locally.
.PHONY: start-integration-service
start-integration-service: check-docker-compose-tool-check
$(CONTAINER) compose -f integration.docker-compose.yaml up --force-recreate -d
.PHONY: check-docker-tool-check
check-docker-tool-check:
@if ! command -v $(CONTAINER) >/dev/null 2>&1; then \
echo "'$(CONTAINER)' is not installed. Please install '$(CONTAINER)' and try again. Or set the CONTAINER variable to a different container runtime engine."; \
exit 1; \
fi
# Check that docker buildx is installed.
.PHONY: check-docker-buildx-tool-check
check-docker-buildx-tool-check:
@if ! $(CONTAINER) buildx >/dev/null 2>&1; then \
echo "'$(CONTAINER)' buildx is not installed. Please install '$(CONTAINER)' buildx and try again."; \
exit 1; \
fi
# Check that docker compose is installed.
.PHONY: check-docker-compose-tool-check
check-docker-compose-tool-check:
@if ! $(CONTAINER) compose >/dev/null 2>&1; then \
echo "'$(CONTAINER)' compose is not installed or not correctly linked to. Please install '$(CONTAINER)' compose or link it as a plugin and try again."; \
exit 1; \
fi
# Check that protoc is installed.
.PHONY: check-protoc-tool-check
check-protoc-tool-check:
@if ! command -v protoc >/dev/null 2>&1; then \
echo "Protoc is not installed. Please install Protoc and try again."; \
exit 1; \
fi
# Check that golangci-lint is installed.
.PHONY: check-golangci-lint-tool-check
check-golangci-lint-tool-check:
@if ! command -v golangci-lint >/dev/null 2>&1; then \
echo "Golangci-lint is not installed. Please install Golangci-lint and try again."; \
exit 1; \
fi
# Check that mockgen is installed.
.PHONY: check-mockgen-tool-check
check-mockgen-tool-check:
@if ! command -v mockgen >/dev/null 2>&1; then \
echo "mockgen is not installed. Please install mockgen and try again."; \
exit 1; \
fi
.PHONY: check-goreleaser-tool-check
check-goreleaser-tool-check:
@if ! command -v goreleaser >/dev/null 2>&1; then \
echo "goreleaser is not installed. Please install goreleaser and try again."; \
exit 1; \
fi
# Check if atlas is installed
.PHONY: check-atlas-tool-check
check-atlas-tool-check:
@if ! command -v atlas >/dev/null 2>&1; then \
echo "atlas is not installed. Please install atlas (https://atlasgo.io/getting-started#installation) and try again."; \
exit 1; \
fi
.PHONY: check-gotestsum-tool-check
check-gotestsum-tool-check:
@if ! command -v gotestsum >/dev/null 2>&1; then \
echo "gotestsum is not installed. Installing gotestsum..."; \
go install gotest.tools/gotestsum@latest; \
fi
# Check that all the tools are installed.
.PHONY: check-tools
check-tools: check-docker-tool-check check-docker-buildx-tool-check check-docker-compose-tool-check check-protoc-tool-check check-golangci-lint-tool-check check-mockgen-tool-check check-goreleaser-tool-check check-atlas-tool-check