From 3df0969349140b5becf1e4c2b3621d337b873a22 Mon Sep 17 00:00:00 2001 From: Evan Lezar Date: Thu, 1 Jul 2021 16:16:33 +0200 Subject: [PATCH] Improve CI for container toolkit This change improves the CI for the container toolkit. The go targets are executed in a docker container which allows for reproducible behaviour on local systems as well as CI. The Makefile is updated to facilitate this. Signed-off-by: Evan Lezar --- .common-ci.yml | 91 +++++++++++++++++++++++++++++++++++++++++ .gitlab-ci.yml | 77 ++++------------------------------ Makefile | 80 ++++++++++++++++++++++++++++++++---- docker/Dockerfile.devel | 20 +++++++++ 4 files changed, 192 insertions(+), 76 deletions(-) create mode 100644 .common-ci.yml create mode 100644 docker/Dockerfile.devel diff --git a/.common-ci.yml b/.common-ci.yml new file mode 100644 index 00000000..40fc68e0 --- /dev/null +++ b/.common-ci.yml @@ -0,0 +1,91 @@ +# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +default: + image: docker:stable + services: + - name: docker:stable-dind + command: ["--experimental"] + +variables: + IMAGE: "${CI_REGISTRY_IMAGE}" + IMAGE_TAG: "${CI_COMMIT_REF_SLUG}" + +build-dev-image: + stage: image + before_script: + - docker login -u "${CI_REGISTRY_USER}" -p "${CI_REGISTRY_PASSWORD}" "${CI_REGISTRY}" + script: + - apk --no-cache add make bash + - make .build-image + - make .push-build-image + +.requires-build-image: + variables: + SKIP_IMAGE_BUILD: "yes" + before_script: + - apk --no-cache add make bash + - docker login -u "${CI_REGISTRY_USER}" -p "${CI_REGISTRY_PASSWORD}" "${CI_REGISTRY}" + - make .pull-build-image + +.go-check: + extends: + - .requires-build-image + stage: go-checks + +fmt: + extends: + - .go-check + script: + - make docker-assert-fmt + +vet: + extends: + - .go-check + script: + - make docker-vet + +lint: + extends: + - .go-check + script: + - make docker-lint + allow_failure: true + +ineffassign: + extends: + - .go-check + script: + - make docker-ineffassign + allow_failure: true + +misspell: + extends: + - .go-check + script: + - make docker-misspell + +go-build: + extends: + - .requires-build-image + stage: go-build + script: + - make docker-build + +unit-tests: + extends: + - .requires-build-image + stage: unit-tests + script: + - make docker-coverage + diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 400f6a5e..619c7e66 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -12,86 +12,27 @@ # See the License for the specific language governing permissions and # limitations under the License. -# Build packages for all supported OS / ARCH combinations +include: + - .common-ci.yml stages: - - tests + - image + - go-checks + - go-build + - unit-tests + - test + - scan + - release - build-one - build-all -.tests-setup: &tests-setup - image: golang:1.14.4 - - rules: - - when: always - - variables: - GITHUB_ROOT: "github.com/NVIDIA" - PROJECT_GOPATH: "${GITHUB_ROOT}/nvidia-container-toolkit" - - before_script: - - mkdir -p ${GOPATH}/src/${GITHUB_ROOT} - - ln -s ${CI_PROJECT_DIR} ${GOPATH}/src/${PROJECT_GOPATH} - .build-setup: &build-setup - image: docker:19.03.8 - - services: - - name: docker:19.03.8-dind - command: ["--experimental"] - before_script: - apk update - apk upgrade - apk add coreutils build-base sed git bash make - docker run --rm --privileged multiarch/qemu-user-static --reset -p yes -c yes -# Run a series of sanity-check tests over the code -lint: - <<: *tests-setup - stage: tests - script: - - GO111MODULE=off go get -u golang.org/x/lint/golint - - make lint - -vet: - <<: *tests-setup - stage: tests - script: - - make vet - -unit_test: - <<: *tests-setup - stage: tests - script: - - make test - -coverage: - <<: *tests-setup - stage: tests - script: - - make coverage - -fmt: - <<: *tests-setup - stage: tests - script: - - make assert-fmt - -ineffassign: - <<: *tests-setup - stage: tests - script: - - GO111MODULE=off go get -u github.com/gordonklaus/ineffassign - - make ineffassign - -misspell: - <<: *tests-setup - stage: tests - script: - - GO111MODULE=off go get -u github.com/client9/misspell/cmd/misspell - - make misspell - # build-one jobs build packages for a single OS / ARCH combination. # # They are run during the first stage of the pipeline as a smoke test to ensure diff --git a/Makefile b/Makefile index 7ff8edba..d262f2e4 100644 --- a/Makefile +++ b/Makefile @@ -27,14 +27,40 @@ MODULE := github.com/NVIDIA/nvidia-container-toolkit docker-native: include $(CURDIR)/docker/docker.mk +ifeq ($(IMAGE),) +REGISTRY ?= nvidia +IMAGE=$(REGISTRY)/container-toolkit +endif +IMAGE_TAG ?= $(GOLANG_VERSION) +BUILDIMAGE ?= $(IMAGE):$(IMAGE_TAG)-devel + +EXAMPLES := $(patsubst ./examples/%/,%,$(sort $(dir $(wildcard ./examples/*/)))) +EXAMPLE_TARGETS := $(patsubst %,example-%, $(EXAMPLES)) + +CHECK_TARGETS := assert-fmt vet lint ineffassign misspell +MAKE_TARGETS := binary build all check fmt lint-internal test examples coverage generate $(CHECK_TARGETS) + +TARGETS := $(MAKE_TARGETS) $(EXAMPLE_TARGETS) + +DOCKER_TARGETS := $(patsubst %,docker-%, $(TARGETS)) +.PHONY: $(TARGETS) $(DOCKER_TARGETS) + GOOS ?= linux binary: GOOS=$(GOOS) go build -ldflags "-s -w" -o "$(LIB_NAME)" $(MODULE)/cmd/$(LIB_NAME) -# Define the check targets for the Golang codebase -.PHONY: check fmt assert-fmt ineffassign lint misspell vet -check: assert-fmt lint misspell vet +build: + GOOS=$(GOOS) go build ./... + +examples: $(EXAMPLE_TARGETS) +$(EXAMPLE_TARGETS): example-%: + GOOS=$(GOOS) go build ./examples/$(*) + +all: check test build binary +check: $(CHECK_TARGETS) + +# Apply go fmt to the codebase fmt: go list -f '{{.Dir}}' $(MODULE)/... \ | xargs gofmt -s -l -w @@ -55,8 +81,12 @@ ineffassign: ineffassign $(MODULE)/... lint: - # We use `go list -f '{{.Dir}}' $(GOLANG_PKG_PATH)/...` to skip the `vendor` folder. - go list -f '{{.Dir}}' $(MODULE)/... | xargs golint -set_exit_status +# We use `go list -f '{{.Dir}}' $(MODULE)/...` to skip the `vendor` folder. + go list -f '{{.Dir}}' $(MODULE)/... | grep -v /internal/ | xargs golint -set_exit_status + +lint-internal: +# We use `go list -f '{{.Dir}}' $(MODULE)/...` to skip the `vendor` folder. + go list -f '{{.Dir}}' $(MODULE)/internal/... | xargs golint -set_exit_status misspell: misspell $(MODULE)/... @@ -65,8 +95,42 @@ vet: go vet $(MODULE)/... COVERAGE_FILE := coverage.out -test: - go test -coverprofile=$(COVERAGE_FILE) $(MODULE)/... +test: build + go test -v -coverprofile=$(COVERAGE_FILE) $(MODULE)/... coverage: test - go tool cover -func=$(COVERAGE_FILE) + cat $(COVERAGE_FILE) | grep -v "_mock.go" > $(COVERAGE_FILE).no-mocks + go tool cover -func=$(COVERAGE_FILE).no-mocks + +generate: + go generate $(MODULE)/... + +# Generate an image for containerized builds +# Note: This image is local only +.PHONY: .build-image .pull-build-image .push-build-image +.build-image: docker/Dockerfile.devel + if [ x"$(SKIP_IMAGE_BUILD)" = x"" ]; then \ + $(DOCKER) build \ + --progress=plain \ + --build-arg GOLANG_VERSION="$(GOLANG_VERSION)" \ + --tag $(BUILDIMAGE) \ + -f $(^) \ + docker; \ + fi + +.pull-build-image: + $(DOCKER) pull $(BUILDIMAGE) + +.push-build-image: + $(DOCKER) push $(BUILDIMAGE) + +$(DOCKER_TARGETS): docker-%: .build-image + @echo "Running 'make $(*)' in docker container $(BUILDIMAGE)" + $(DOCKER) run \ + --rm \ + -e GOCACHE=/tmp/.cache \ + -v $(PWD):$(PWD) \ + -w $(PWD) \ + --user $$(id -u):$$(id -g) \ + $(BUILDIMAGE) \ + make $(*) diff --git a/docker/Dockerfile.devel b/docker/Dockerfile.devel new file mode 100644 index 00000000..20e0447f --- /dev/null +++ b/docker/Dockerfile.devel @@ -0,0 +1,20 @@ +# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +ARG GOLANG_VERSION=x.x.x +FROM golang:${GOLANG_VERSION} + +RUN go get -u golang.org/x/lint/golint +RUN go get -u github.com/matryer/moq +RUN go get -u github.com/gordonklaus/ineffassign +RUN go get -u github.com/client9/misspell/cmd/misspell \ No newline at end of file