-
Notifications
You must be signed in to change notification settings - Fork 3.4k
Expand file tree
/
Copy pathMakefile.Common
More file actions
360 lines (308 loc) · 13.7 KB
/
Makefile.Common
File metadata and controls
360 lines (308 loc) · 13.7 KB
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
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
# In order to ensure make instructions fail if there is command that fails a pipe (ie: `go test ... | tee -a ./test_results.txt`)
# the value `-o pipefail` (or `set -o pipefail`) is added to each shell command that make runs
# otherwise in the example command pipe, only the exit code of `tee` is recorded instead of `go test` which can cause
# test to pass in CI when they should not.
SHELL = /usr/bin/env bash
.SHELLFLAGS = -o pipefail -c
# SRC_ROOT is the top of the source tree.
SRC_ROOT := $(shell git rev-parse --show-toplevel)
# SRC_PARENT_DIR is the absolute path of source tree's parent directory
SRC_PARENT_DIR := $(shell dirname $(SRC_ROOT))
COVER_DIR?=coverage
COVER_DIR_ABS?=$(SRC_ROOT)/$(COVER_DIR)
# build tags required by any component should be defined as an independent variables and later added to GO_BUILD_TAGS below
GO_BUILD_TAGS=""
# These ldflags allow the build tool to omit the symbol table, debug information, and the DWARF symbol table to downscale binary size.
GO_BUILD_LDFLAGS="-s -w"
GOTEST_TIMEOUT?= 900s
GOCMD?= go
GOOS=$(shell $(GOCMD) env GOOS)
GOARCH=$(shell $(GOCMD) env GOARCH)
GOTESTARCH?=$(GOARCH)
# On Windows arm64 neither `-race` nor cgo are not supported (cgo is not supported due to the GH runner installed gcc not having arm64 libs)
ifeq ($(GOOS)-$(GOARCH),windows-arm64)
CGO_ENABLED_OPT?=0
else
GOTEST_RACE_OPT?=-race
CGO_ENABLED_OPT?=1
endif
GOTEST_OPT?=$(GOTEST_RACE_OPT) -timeout $(GOTEST_TIMEOUT) -parallel 4 --tags=$(GO_BUILD_TAGS)
GOTEST_INTEGRATION_OPT?=$(GOTEST_RACE_OPT) -timeout 360s -parallel 4 -skip Sudo
GOTEST_INTEGRATION_OPT_SUDO?=$(GOTEST_RACE_OPT) -timeout 360s -parallel 4 -exec sudo -run Sudo
COVER_OPT :=-cover -covermode=atomic -test.gocoverdir="$(COVER_DIR_ABS)"
GOTEST_OPT_WITH_INTEGRATION=$(GOTEST_INTEGRATION_OPT) -tags=integration,$(GO_BUILD_TAGS)
GOTEST_OPT_WITH_INTEGRATION_SUDO=$(GOTEST_INTEGRATION_OPT_SUDO) -tags=integration,$(GO_BUILD_TAGS)
GOTEST_OPT_WITH_INTEGRATION_COVERAGE=$(GOTEST_OPT_WITH_INTEGRATION) -coverprofile=integration-coverage.txt -covermode=atomic
DOCKERCMD ?= docker
CURR_MOD := $(shell go list -m | tr '/' '-' )
# In order to help reduce toil related to managing tooling for the open telemetry collector
# this section of the makefile looks at only requiring command definitions to be defined
# as part of $(TOOLS_MOD_DIR)/tools.go, following the existing practice.
# Modifying the tools' `go.mod` file will trigger a rebuild of the tools to help
# ensure that all contributors are using the most recent version to make builds repeatable everywhere.
TOOLS_MOD_DIR := $(SRC_ROOT)/internal/tools
TOOLS_MOD_REGEX := "\s+_\s+\".*\""
TOOLS_PKG_NAMES := $(shell grep -E $(TOOLS_MOD_REGEX) < $(TOOLS_MOD_DIR)/tools.go | tr -d " _\"")
TOOLS_BIN_DIR := $(SRC_ROOT)/.tools
TOOLS_BIN_NAMES := $(addprefix $(TOOLS_BIN_DIR)/, $(notdir $(TOOLS_PKG_NAMES)))
CHLOGGEN_CONFIG := .chloggen/config.yaml
# no trailing slash
JUNIT_OUT_DIR ?= $(TOOLS_MOD_DIR)/testresults
.PHONY: install-tools
install-tools: $(TOOLS_BIN_NAMES)
$(TOOLS_BIN_DIR):
mkdir -p $@
$(TOOLS_BIN_NAMES): $(TOOLS_BIN_DIR) $(TOOLS_MOD_DIR)/go.mod
cd $(TOOLS_MOD_DIR) && GOOS="" GOARCH="" $(GOCMD) build -o $@ -trimpath $(filter %/$(notdir $@),$(TOOLS_PKG_NAMES))
ACTIONLINT := $(TOOLS_BIN_DIR)/actionlint
ADDLICENSE := $(TOOLS_BIN_DIR)/addlicense
MDLINKCHECK := $(TOOLS_BIN_DIR)/markdown-link-check
MISSPELL := $(TOOLS_BIN_DIR)/misspell -error
MISSPELL_CORRECTION := $(TOOLS_BIN_DIR)/misspell -w
LINT := $(TOOLS_BIN_DIR)/golangci-lint
MULTIMOD := $(TOOLS_BIN_DIR)/multimod
CHLOGGEN := $(TOOLS_BIN_DIR)/chloggen
GITHUBGEN := $(TOOLS_BIN_DIR)/githubgen
CODECOVGEN := $(TOOLS_BIN_DIR)/codecovgen
GOIMPORTS := $(TOOLS_BIN_DIR)/goimports
PORTO := $(TOOLS_BIN_DIR)/porto
CHECKFILE := $(TOOLS_BIN_DIR)/checkfile
CROSSLINK := $(TOOLS_BIN_DIR)/crosslink
GOJUNIT := $(TOOLS_BIN_DIR)/go-junit-report
BUILDER := $(TOOLS_BIN_DIR)/builder
GOFUMPT := $(TOOLS_BIN_DIR)/gofumpt
GOVULNCHECK := $(TOOLS_BIN_DIR)/govulncheck
GCI := $(TOOLS_BIN_DIR)/gci
GOTESTSUM := $(TOOLS_BIN_DIR)/gotestsum
CHECKAPI := $(TOOLS_BIN_DIR)/checkapi
MODERNIZE := $(TOOLS_BIN_DIR)/modernize
# Tools used by go generate commands
MDATAGEN := $(TOOLS_BIN_DIR)/mdatagen
# The githubreceiver uses a "go generate" tool that is not used by other components.
GENQLIENT := $(TOOLS_BIN_DIR)/genqlient
GOTESTSUM_OPT?= --rerun-fails=1
# BUILD_TYPE should be one of (dev, release).
BUILD_TYPE?=release
# All source code and documents. Used in spell check.
ALL_SRC_AND_DOC_CMD := find . -type f \( \( -name "*.md" -o -name "*.go" -o -name "*.yaml" \) -and \( -not -path '*/third_party/*' \) \) | sort
ADDLICENSE_CMD := $(ADDLICENSE) -s=only -y "" -c "The OpenTelemetry Authors"
# All source code and .sh files (evaluated when used)
ALL_SRC_AND_SHELL_CMD := find . -type f \( \( -name "*.go" -o -name "*.sh" \) -and \( -not -path '*/third_party/*' \) \) | sort
pwd:
@pwd
.DEFAULT_GOAL := common
.PHONY: common
common: lint test
.PHONY: test
test: $(GOTESTSUM)
$(GOTESTSUM) $(GOTESTSUM_OPT) --packages="./..." -- $(GOTEST_OPT)
# This target is used in scoped tests.
# We do not pass GOTESTSUM_OPT so that we do not re-run failures
# and run each changed test two times.
#
# This helps us catch flakes more easily before they land on main.
test-twice: $(GOTESTSUM)
$(GOTESTSUM) --packages="./..." -- $(GOTEST_OPT) -count=2
.PHONY: test-with-cover
test-with-cover: $(GOTESTSUM)
mkdir -p $(PWD)/coverage/unit
$(GOTESTSUM) $(GOTESTSUM_OPT) --packages="./..." -- $(GOTEST_OPT) -cover -covermode=atomic -args -test.gocoverdir="$(PWD)/coverage/unit"
.PHONY: do-unit-tests-with-cover
do-unit-tests-with-cover: $(GOTESTSUM)
@echo "running $(GOCMD) unit test ./... + coverage in `pwd`"
$(GOTESTSUM) $(GOTESTSUM_OPT) --packages="./..." -- $(GOTEST_OPT) ./... $(COVER_OPT)
$(GOCMD) tool cover -html=coverage.txt -o coverage.html
.PHONY: test-with-junit
test-with-junit: $(GOTESTSUM)
mkdir -p $(JUNIT_OUT_DIR)
$(GOTESTSUM) $(GOTESTSUM_OPT) --packages="./..." --junitfile $(JUNIT_OUT_DIR)/$(CURR_MOD)-junit.xml -- $(GOTEST_OPT) ./...
.PHONY: test-with-junit-and-cover
test-with-junit-and-cover: $(GOTESTSUM)
mkdir -p $(COVER_DIR_ABS)
mkdir -p $(JUNIT_OUT_DIR)
$(GOTESTSUM) $(GOTESTSUM_OPT) --packages="./..." --junitfile $(JUNIT_OUT_DIR)/$(CURR_MOD)-junit.xml -- $(GOTEST_OPT) ./... $(COVER_OPT)
.PHONY: buildtest
buildtest:
ifneq (,$(wildcard ./*.go))
GOARCH=$(GOTESTARCH) CGO_ENABLED=$(CGO_ENABLED_OPT) $(GOCMD) test -c -o builtunitetest.test
endif
.PHONY: runbuilttest
runbuilttest: $(GOTESTSUM)
ifneq (,$(wildcard ./builtunitetest.test))
$(GOTESTSUM) --raw-command -- $(GOCMD) tool test2json -p "./..." -t ./builtunitetest.test -test.v -test.failfast -test.timeout $(GOTEST_TIMEOUT)
endif
INTEGRATION_TEST_FILES := $(shell find . -name *integration_test.go)
INTEGRATION_TESTS := $(if $(INTEGRATION_TEST_FILES),$(shell cat $(INTEGRATION_TEST_FILES) | sed -n "s/func \(Test[A-Za-z0-9_]*\).*/\1/p" | xargs | sed "s/ /|/g"))
.PHONY: mod-integration-test
mod-integration-test: $(GOTESTSUM)
@echo "running $(GOCMD) integration test $(INTEGRATION_TESTS) in `pwd`"
@if [ -n "$(INTEGRATION_TESTS)" ]; then \
$(GOTESTSUM) $(GOTESTSUM_OPT) --packages="./..." -- -run "$(INTEGRATION_TESTS)" $(GOTEST_OPT_WITH_INTEGRATION); \
else \
echo "No integration tests in `pwd`"; \
fi
@if [ -e integration-coverage.txt ]; then \
$(GOCMD) tool cover -html=integration-coverage.txt -o integration-coverage.html; \
fi
.PHONY: mod-integration-sudo-test
mod-integration-sudo-test: $(GOTESTSUM)
@echo "running $(GOCMD) integration sudo (root/privileged) test $(INTEGRATION_TESTS) in `pwd`"
@if [ -n "$(INTEGRATION_TESTS)" ]; then \
$(GOTESTSUM) $(GOTESTSUM_OPT) --format standard-verbose --packages="./..." -- -run "$(INTEGRATION_TESTS)" $(GOTEST_OPT_WITH_INTEGRATION_SUDO); \
else \
echo "No integration tests in `pwd`"; \
fi
.PHONY: do-integration-tests-with-cover
do-integration-tests-with-cover: $(GOTESTSUM)
@echo "running $(GOCMD) integration test $(INTEGRATION_TESTS) + coverage in `pwd`"
@if [ -n "$(INTEGRATION_TESTS)" ]; then \
$(GOTESTSUM) $(GOTESTSUM_OPT) --packages="./..." -- -run "$(INTEGRATION_TESTS)" $(GOTEST_OPT_WITH_INTEGRATION_COVERAGE); \
else \
echo "No integration tests in `pwd`"; \
fi
@if [ -e integration-coverage.txt ]; then \
$(GOCMD) tool cover -html=integration-coverage.txt -o integration-coverage.html; \
fi
.PHONY: benchmark
benchmark: $(GOTESTSUM)
$(GOTESTSUM) $(GOTESTSUM_OPT) --packages="$$(find . -name 'go.mod' -not -path '*/third_party/*' -not -path '*/local/*' -type f | xargs dirname | sort | uniq | xargs -L 1 bash -c 'cd $$0 && go list -f "{{ .Dir }}"' | xargs echo)" -- -bench=. -run=notests --tags=$(GO_BUILD_TAGS)
.PHONY: addlicense
addlicense: $(ADDLICENSE)
@ADDLICENSEOUT=$$(for f in $$($(ALL_SRC_AND_SHELL_CMD)); do \
`$(ADDLICENSE_CMD) "$$f" 2>&1`; \
done); \
if [ "$$ADDLICENSEOUT" ]; then \
echo "$(ADDLICENSE) FAILED => add License errors:\n"; \
echo "$$ADDLICENSEOUT\n"; \
exit 1; \
else \
echo "Add License finished successfully"; \
fi
.PHONY: checklicense
checklicense: $(ADDLICENSE)
@licRes=$$(for f in $$($(ALL_SRC_AND_SHELL_CMD)); do \
if awk '/Copyright The OpenTelemetry Authors|generated|GENERATED/ && NR<=3 { found=1; next } END { if (!found) print FILENAME }' $$f; then \
continue; \
fi; \
if awk '/SPDX-License-Identifier: Apache-2.0|generated|GENERATED/ && NR<=4 { found=1; next } END { if (!found) print FILENAME }' $$f; then \
continue; \
fi; \
$(ADDLICENSE_CMD) -check "$$f" 2>&1 || echo "$$f"; \
done); \
if [ -n "$${licRes}" ]; then \
echo "license header checking failed:"; echo "$${licRes}"; \
exit 1; \
else \
echo "Check License finished successfully"; \
fi
.PHONY: checklinks
checklinks:
command -v $(DOCKERCMD) >/dev/null 2>&1 || { echo >&2 "$(DOCKERCMD) not installed. Install before continuing"; exit 1; }
$(DOCKERCMD) run -w /home/repo --rm \
--mount 'type=bind,source='$(PWD)',target=/home/repo' \
--mount 'type=bind,source='$(SRC_ROOT)/.github/lychee.toml',target=/lychee.toml' \
lycheeverse/lychee \
--config /lychee.toml \
--root-dir /home/repo \
-v \
--no-progress './**/*.md'
.PHONY: fmt
fmt: $(GOFUMPT) $(GOIMPORTS)
$(GOFUMPT) -l -w -extra .
$(GOIMPORTS) -w -local github.com/open-telemetry/opentelemetry-collector-contrib ./
.PHONY: generate-tools
generate-tools: $(MDATAGEN) $(GENQLIENT)
ifeq ($(GOOS),windows)
@echo Adding "exe" extensions to generate tools
@for f in $^; do \
cp -u "$$f" "$$f.exe"; \
done
endif
# On Windows changing path with absolute path includes ':' even escaping it is not enough to get it to correctly
# update PATH, so use a relative path when pre-pending to PATH on Windows. Unfortunately, realpath is not portable
# between mac and GNU based bash so keeping the full path on non-Windows OSes.
ifeq ($(GOOS),windows)
TOOLS_BIN_DIR_PORTABLE?=$(shell realpath --relative-to="$(CURDIR)" "$(TOOLS_BIN_DIR)")
else
TOOLS_BIN_DIR_PORTABLE?=$(TOOLS_BIN_DIR)
endif
.PHONY: generate
generate: generate-tools
ifeq ($(CURDIR),$(SRC_ROOT))
PATH="$(TOOLS_BIN_DIR_PORTABLE):$$PATH" $(MAKE) for-all CMD="$(GOCMD) generate ./..."
$(MAKE) gofmt
else
PATH="$(TOOLS_BIN_DIR_PORTABLE):$$PATH" $(GOCMD) generate ./...
$(MAKE) fmt
endif
.PHONY: lint
lint: $(LINT) checklicense misspell
$(LINT) run
.PHONY: govulncheck
govulncheck: $(GOVULNCHECK)
$(GOVULNCHECK) ./...
.PHONY: modernize
modernize: $(MODERNIZE)
$(MODERNIZE) -fix -test -v ./...
.PHONY: tidy
tidy:
rm -fr go.sum
$(GOCMD) mod tidy -compat=1.24.0
.PHONY: toolchain
toolchain:
$(GOCMD) get toolchain@none
.PHONY: misspell
misspell: $(TOOLS_BIN_DIR)/misspell
@echo "running $(MISSPELL)"
@$(MISSPELL) $$($(ALL_SRC_AND_DOC_CMD))
.PHONY: misspell-correction
misspell-correction: $(TOOLS_BIN_DIR)/misspell
@$(MISSPELL_CORRECTION) $$($(ALL_SRC_AND_DOC_CMD))
.PHONY: moddownload
moddownload:
$(GOCMD) mod download
.PHONY: gci
gci: $(TOOLS_BIN_DIR)/gci
@echo "running $(GCI)"
@$(GCI) write -s standard -s default -s "prefix(github.com/open-telemetry/opentelemetry-collector-contrib)" $$($(ALL_SRC_AND_DOC_CMD))
CHANGED_GOLANG_SOURCES?=$(shell git diff main --name-only | grep -E '.*\.go$$' | grep -v -E '.*_test\.go$$')
.PHONY: for-affected-components
for-affected-components:
@echo "Checking for affected components..."
@if [ -z '$${CHANGED_GOLANG_SOURCES}' ]; then \
echo "No go source changes detected in shippable code."; \
else \
cd $(SRC_ROOT); \
DEPENDENT_PKGS=$$(echo $${CHANGED_GOLANG_SOURCES} | xargs sed -n 's|^package .* // import "\(.*\)"$$|\1|p' | uniq); \
if [ -z '$${DEPENDENT_PKGS}' ]; then \
echo "No other package depends on the one being changed."; \
else \
DEPENDENT_PKG_DIRS=$$(echo $${DEPENDENT_PKGS} | tr ' ' '\n' | xargs -I {} grep --include=go.mod -rl {} | xargs -r dirname | uniq); \
set -e; for dir in $$(echo $${DEPENDENT_PKG_DIRS}); do \
(cd "$${dir}" && \
echo "running $${CMD} in $${dir}" && \
$${CMD} ); \
done \
fi \
fi
# Do not pass GOTESTSUM_OPT so that we do not re-run failures
# and run each changed test three times.
# This helps us catch flakes more easily before they land on main.
CHANGED_GOLANG_TESTS?=$(shell git diff main --name-only | grep -E '.*_test\.go$$')
.PHONY: run-changed-tests
run-changed-tests:
@echo "Checking for affected tests..."
@if [ -z '$${CHANGED_GOLANG_TESTS}' ]; then \
echo "No go test changes detected."; \
else \
cd $(SRC_ROOT); \
AFFECTED_TEST_DIRS=$$(echo $${CHANGED_GOLANG_TESTS} | tr ' ' '\n' | xargs dirname | uniq); \
if [ -z '$${AFFECTED_TEST_DIRS}' ]; then \
echo "Failed to find the affected test directories."; \
else \
set -e; for dir in $$(echo $${AFFECTED_TEST_DIRS}); do \
(cd "$${dir}" && \
$(GOTESTSUM) --packages="./..." -- $(GOTEST_OPT) -count=3 ); \
done \
fi \
fi