Skip to content

Commit

Permalink
refactor: move cli to cmd package (#308)
Browse files Browse the repository at this point in the history
  • Loading branch information
yesnault authored Nov 19, 2020
1 parent f656658 commit 0c2128a
Show file tree
Hide file tree
Showing 18 changed files with 399 additions and 84 deletions.
11 changes: 11 additions & 0 deletions .build/core.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
CI := $(if ${CI},${CI},0)
VERSION := $(if ${CDS_SEMVER},${CDS_SEMVER},snapshot)
CDS_VERSION := $(if ${CDS_VERSION},${CDS_VERSION},snapshot)
UNAME := $(shell uname)
UNAME_LOWERCASE := $(shell uname -s| tr A-Z a-z)

.PHONY: help
help:
@grep -hE '^[ a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | \
awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-17s\033[0m %s\n", $$1, $$2}'

222 changes: 222 additions & 0 deletions .build/go.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,222 @@


GO_BUILD = CGO_ENABLED=0 go build -installsuffix cgo
GO_LIST = env GO111MODULE=on go list
TEST_CMD = go test -v -timeout 600s -coverprofile=profile.coverprofile
TEST_C_CMD = go test -c -coverprofile=profile.coverprofile
TEST_RUN_ARGS = -test.v -test.timeout 600s -test.coverprofile=profile.coverprofile
CURRENT_PACKAGE = $(shell $(GO_LIST))
VERSION := $(if ${CDS_SEMVER},${CDS_SEMVER},snapshot)
TARGET_DIST := ./dist
TARGET_RESULTS := ./results

##### =====> Clean <===== #####

mk_go_clean: # clean target directory
@rm -rf $(TARGET_DIST)
@rm -rf $(TARGET_RESULTS)
@for testfile in `find ./ -name "bin.test"`; do \
rm $$testfile; \
done;
@for TST in `find ./ -name "tests.log"`; do \
rm $$TST; \
done;
@for profile in `find ./ -name "*.coverprofile"`; do \
rm $$profile; \
done;

##### =====> Compile <===== #####

IS_TEST := $(filter test,$(MAKECMDGOALS))
TARGET_OS := $(if ${ENABLE_CROSS_COMPILATION},$(if ${OS},${OS}, $(if $(IS_TEST), $(shell go env GOOS), darwin linux freebsd netbsd openbsd solaris windows)),$(shell go env GOOS))
TARGET_ARCH := $(if ${ARCH},${ARCH}, $(if $(IS_TEST), $(shell go env GOARCH),amd64))
BINARIES = $(addprefix $(TARGET_DIST)/, $(addsuffix _$(OS)_$(ARCH)$(if $(IS_WINDOWS),.exe), $(notdir $(TARGET_NAME))))
CROSS_COMPILED_BINARIES = $(foreach OS, $(TARGET_OS), $(foreach ARCH, $(TARGET_ARCH), $(BINARIES)))
GOFILES = $(call get_recursive_files, '.')

mk_go_build:
$(info *** mk_go_build)

$(CROSS_COMPILED_BINARIES): $(GOFILES) $(TARGET_DIST)
$(info *** compiling $@)
@GOOS=$(call get_os_from_binary_file,$@) \
GOARCH=$(call get_arch_from_binary_file,$@) \
$(GO_BUILD) $(BUILD_MODE) $(LDFLAGS) -o $@;

##### =====> Compile Tests <===== #####

PKGS = $(or $(PKG),$(shell $(GO_LIST) ./...))
TESTPKGS = $(shell $(GO_LIST) -f \
'{{ if or .TestGoFiles .XTestGoFiles }}{{ .ImportPath }}{{ end }}' \
$(PKGS))

TESTPKGS_C_FILE = $(addsuffix /bin.test, $(subst $(CURRENT_PACKAGE),.,$(PKG)))
TESTPKGS_C = $(foreach PKG, $(TESTPKGS), $(TESTPKGS_C_FILE))

$(TESTPKGS_C): #main_test.go
$(info *** compiling test $@)
@cd $(dir $@) && $(TEST_C_CMD) -o bin.test .

##### =====> Running Tests <===== #####

TESTPKGS_RESULTS_LOG_FILE = $(addsuffix /tests.log, $(subst $(CURRENT_PACKAGE),.,$(PKG)))
TESTPKGS_RESULTS = $(foreach PKG, $(TESTPKGS), $(TESTPKGS_RESULTS_LOG_FILE))

$(HOME)/.richstyle.yml:
echo "leaveTestPrefix: true" > $(HOME)/.richstyle.yml

GO_RICHGO = ${GOPATH}/bin/richgo
$(GO_RICHGO): $(HOME)/.richstyle.yml
go get -u github.com/kyoh86/richgo

EXIT_TESTS := 0
$(TESTPKGS_RESULTS): $(GOFILES) $(TESTPKGS_C) $(GO_RICHGO)
$(info *** executing tests in $(dir $@))
@-cd $(dir $@) && ./bin.test $(TEST_RUN_ARGS) | tee tests.log | richgo testfilter ;

GO_COV_MERGE = ${GOPATH}/bin/gocovmerge
$(GO_COV_MERGE):
go get -u github.com/wadey/gocovmerge

GO_GOJUNIT = ${GOPATH}/bin/go-junit-report
$(GO_GOJUNIT):
go get -u github.com/jstemmer/go-junit-report

GO_COBERTURA = ${GOPATH}/bin/gocover-cobertura
$(GO_COBERTURA):
go get -u github.com/t-yuki/gocover-cobertura

mk_go_test: $(GO_COV_MERGE) $(GO_COBERTURA) $(GOFILES) $(TARGET_RESULTS) $(TESTPKGS_RESULTS)# Run tests
@echo "Generating unit tests coverage..."
@$(GO_COV_MERGE) `find ./ -name "*.coverprofile"` > $(TARGET_RESULTS)/cover.out
@$(GO_COBERTURA) < $(TARGET_RESULTS)/cover.out > $(TARGET_RESULTS)/coverage.xml
@go tool cover -html=$(TARGET_RESULTS)/cover.out -o=$(TARGET_RESULTS)/cover.html
@NB=$$(grep "^FAIL" `find . -type f -name "tests.log"`|grep -v ':0'|wc -l); echo "tests failed $$NB" && exit $$NB

mk_go_test-xunit: $(GO_GOJUNIT) $(TARGET_RESULTS) # Generate test with xunit report
@echo "Generating xUnit Report..."
@for TST in `find . -name "tests.log"`; do \
if [ -s $$TST ]; then \
FAILED=`grep -E '(FAIL)+\s([a-z\.\/]*)\s\[build failed\]' $$TST | wc -l`; \
if [ $$FAILED -gt 0 ]; then \
echo "Build Failed \t\t\t($$TST)"; \
echo "Build Failed \t\t\t($$TST)" >> $(TARGET_RESULTS)/fail; \
else \
NO_TESTS=`grep -E '\?+\s+([a-z\.\/]*)\s\[no test files\]' $$TST | wc -l`; \
if [ $$NO_TESTS -gt 0 ]; then \
echo "No tests found \t\t\t($$TST)"; \
else \
if [ ! -z "${CDS_VERSION}" ]; then \
echo "Sending $$TST to CDS"; \
worker upload --tag `echo $$TST | sed 's|./||' | sed 's|./||' | sed 's|/|_|g') | sed 's|_tests.log||'` $(abspath $$TST); \
fi; \
echo "Generating xUnit report \t$$TST.tests-results.xml"; \
cat $$TST | $(GO_GOJUNIT) > $$TST.tests-results.xml; \
fi; \
fi; \
else \
echo "Ignoring empty file \t\t$$TST"; \
fi; \
done; \
for XML in `find . -name "tests.log.tests-results.xml"`; do \
if [ "$$XML" = "./tests.log.tests-results.xml" ]; then \
PWD=`pwd`; \
mv $$XML $(TARGET_RESULTS)/`basename $(PWD)`.tests-results.xml; \
else \
mv $$XML $(TARGET_RESULTS)/`echo $$XML | sed 's|./||' | sed 's|/|_|g' | sed 's|_tests.log||'`; \
fi; \
done; \
rm -f $(TARGET_RESULTS)/report; \
for XML in `find . -name "*.tests-results.xml"`; do \
if [ -s $$XML ]; then \
if grep -q 'testsuite' $$XML; then \
echo "Generating report: " $$XML; \
echo "`xmllint --xpath "//testsuite/@name" $$XML | sed 's/name=//' | sed 's/"//g'`" \
"`xmllint --xpath "//testsuite/@tests" $$XML | sed 's/tests=//' | sed 's/"//g'` Tests :" \
"`xmllint --xpath "//testsuite/@errors" $$XML 2>/dev/null | sed 's/errors=//' | sed 's/"//g'` Errors ;"\
"`xmllint --xpath "//testsuite/@failures" $$XML 2>/dev/null | sed 's/failures=//' | sed 's/"//g'` Failures;" \
"`xmllint --xpath "//testsuite/@skip" $$XML 2>/dev/null | sed 's/skip=//' | sed 's/"//g'` Skipped;" \
>> $(TARGET_RESULTS)/report; \
fi; \
fi; \
done; \
if [ -e $(TARGET_RESULTS)/report ]; then \
cat $(TARGET_RESULTS)/report; \
fi; \
echo "#########################"; \
for XML in `find . -name "*.tests-results.xml"`; do \
if [ -s $$XML ]; then \
if grep -q 'errors' $$XML && grep -q 'testsuite' $$XML; then \
if [ "`xmllint --xpath "//testsuite/@errors" $$XML | sed 's/errors=//' | sed 's/"//g'`" -gt "0" ]; then \
echo " $$XML : Tests failed"; \
fi; \
fi; \
if grep -q 'failures' $$XML && grep -q 'testsuite' $$XML $$XML; then \
if [ "`xmllint --xpath "//testsuite/@failures" $$XML | sed 's/failures=//' | sed 's/"//g'`" -gt "0" ]; then \
echo " $$XML : Tests failed"; \
fi; \
fi; \
fi; \
done; \
if [ -e $(TARGET_RESULTS)/fail ]; then \
echo "#########################"; \
echo "ERROR: Test compilation failure"; \
cat $(TARGET_RESULTS)/fail; \
exit 1; \
fi;

##### =====> lint <===== #####

TMP_DIR = /tmp/ovh/venom

OSNAME=$(shell go env GOOS)
CUR_PATH = $(notdir $(shell pwd))

GOLANGCI_DIR = $(TMP_DIR)/$(CUR_PATH)/golangci-lint
GOLANGCI_TMP_BIN = $(GOLANGCI_DIR)/golangci-lint

GOLANGCI_LINT_VERSION=1.31.0
GOLANGCI_CMD = $(GOLANGCI_TMP_BIN) run --allow-parallel-runners -c .golangci.yml
GOLANGCI_LINT_ARCHIVE = golangci-lint-$(GOLANGCI_LINT_VERSION)-$(OSNAME)-amd64.tar.gz

# Run this on localc machine.
# It downloads a version of golangci-lint and execute it locally.
# duration first time ~6s
# duration second time ~2s
.PHONY: lint
lint: $(GOLANGCI_TMP_BIN)
$(GOLANGCI_DIR)/$(GOLANGCI_CMD)

# install a local golangci-lint if not found.
$(GOLANGCI_TMP_BIN):
curl -OL https://github.com/golangci/golangci-lint/releases/download/v$(GOLANGCI_LINT_VERSION)/$(GOLANGCI_LINT_ARCHIVE)
mkdir -p $(GOLANGCI_DIR)/
tar -xf $(GOLANGCI_LINT_ARCHIVE) --strip-components=1 -C $(GOLANGCI_DIR)/
chmod +x $(GOLANGCI_TMP_BIN)
rm -f $(GOLANGCI_LINT_ARCHIVE)

mk_go_lint: $(GOLANG_CI_LINT) # run golangci lint
$(info *** running lint)
$(GOLANGCI_CMD)

##### =====> Internals <===== #####

$(TARGET_RESULTS):
$(info create $(TARGET_RESULTS) directory)
@mkdir -p $(TARGET_RESULTS)

$(TARGET_DIST):
$(info create $(TARGET_DIST) directory)
@mkdir -p $(TARGET_DIST)

define get_os_from_binary_file
$(strip $(shell echo $(1) | cut -d'_' -f 2))
endef

define get_arch_from_binary_file
$(strip $(patsubst %.exe, %,$(shell echo $(1) | cut -d'_' -f 3)))
endef

define get_recursive_files
$(subst ./,,$(shell find $(1) -type f -name "*.go" -print))
endef
12 changes: 9 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
.idea
.vscode
cli/venom/bin
venom
cmd/venom/bin
tests/pprof*
tests/.DS_Store
.DS_Store
vendor/
dist/
venom.log
venom.log
*.so
foo.yml
dist
results
bin.test
profile.coverprofile
tests.log
91 changes: 71 additions & 20 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,27 +1,78 @@
include linting.mk
##### ^^^^^^ USAGE ^^^^^^ #####

.PHONY: all
all: deps lint build test
##### ^^^^^^ make help ^^^^^^ #####

.PHONY: tidy
tidy:
go mod tidy
DOCKER_IMAGE := $(if ${DOCKER_IMAGE},${DOCKER_IMAGE},ovhcom/venom:snapshot)
DOCKER_IMAGE_NAME = $(shell echo $(DOCKER_IMAGE) | cut -d ':' -f 1)
DOCKER_IMAGE_TAG = $(shell echo $(DOCKER_IMAGE) | cut -d ':' -f 2)

.PHONY: download
download:
go mod download
##### ^^^^^^ EDIT ABOVE ^^^^^^ #####

.PHONY: deps
deps: tidy download
include ./.build/core.mk

.PHONY: verify
verify:
go mod verify
ifneq (,$(strip $(filter build dist run lint clean test test-xunit,$(MAKECMDGOALS))))
include ./.build/go.mk
endif

.PHONY: build
build:
go build ./...
DIST_DIR := dist/
RESULTS_DIR := results/

.PHONY: test
test:
go test ./...
APP_DIST := $(wildcard cmd/venom/dist/*)
ALL_DIST := $(APP_DIST)
ALL_DIST_TARGETS := $(foreach DIST,$(ALL_DIST),$(addprefix $(DIST_DIR),$(notdir $(DIST))))

APP_RESULTS = $(wildcard cmd/venom/results/*)
ALL_RESULTS = $(APP_RESULTS)
ALL_RESULTS_TARGETS := $(foreach RESULTS,$(ALL_RESULTS),$(addprefix $(RESULTS_DIR),$(notdir $(RESULTS))))


define get_dist_from_target
$(filter %/$(notdir $(1)), $(ALL_DIST))
endef

define get_results_from_target
$(filter %/$(notdir $(1)), $(ALL_RESULTS))
endef

$(ALL_DIST_TARGETS):
@mkdir -p $(DIST_DIR)
$(info copying $(call get_dist_from_target, $@) to $@)
@cp -f $(call get_dist_from_target, $@) $@

$(ALL_RESULTS_TARGETS):
@mkdir -p $(RESULTS_DIR)
$(info copying $(call get_results_from_target, $@) to $@)
@cp -f $(call get_results_from_target, $@) $@

.PHONY: build lint clean testrun test dist test-xunit package

build: ## build all components and push them into dist directory
$(info Building Component venom)
$(MAKE) build -C cmd/venom
$(MAKE) dist

dist: $(ALL_DIST_TARGETS)

run: ## build binary for current OS only and run it. For development purpose only
OS=${UNAME_LOWERCASE} $(MAKE) build -C cmd/venom
@cmd/venom/dist/venom_${UNAME_LOWERCASE}_amd64

lint: mk_go_lint ## install and run golangci-lint on all go files. doc https://github.com/golangci/golangci-lint

clean: mk_go_clean ## delete directories dist and results and all temp files (coverage, tests, reports)
@rm -rf ${DIST_DIR}
@rm -rf ${RESULTS_DIR}
$(MAKE) clean -C cmd/venom

test-results: $(ALL_RESULTS_TARGETS)

test: mk_go_test ## run unit tests on all go packages

integration-test: ## run venom integration tests declared in tests/ directory
$(MAKE) start-test-stack -C tests

test-xunit: mk_go_test-xunit ## generate xunit report using the results of previous 'make test', useful on CDS only
$(MAKE) test-results

package: ## build the docker image with existing binaries from dist directory
docker build --tag $(DOCKER_IMAGE) .
2 changes: 1 addition & 1 deletion cli/cli.go → cmd/cli.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package cli
package cmd

import (
"fmt"
Expand Down
File renamed without changes.
25 changes: 25 additions & 0 deletions cmd/venom/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@

##### ^^^^^^ USAGE ^^^^^^ #####

##### ^^^^^^ make help ^^^^^^ #####

TARGET_NAME = venom
LDFLAGS = -ldflags "-X github.com/ovh/venom.Version=$(VERSION)"

# If you want to enable the cross-compilation, uncomment the following line:
ENABLE_CROSS_COMPILATION := true

##### ^^^^^^ EDIT ABOVE ^^^^^^ #####

##### =====> Commands <===== #####

include ../../.build/core.mk
include ../../.build/go.mk

.PHONY: clean

build: $(CROSS_COMPILED_BINARIES) ## Run build

clean:
@rm -f venom
@rm -rf dist
Loading

0 comments on commit 0c2128a

Please sign in to comment.