github.com/opencontainers/umoci@v0.4.8-0.20240508124516-656e4836fb0d/Makefile (about)

     1  # umoci: Umoci Modifies Open Containers' Images
     2  # Copyright (C) 2016-2020 SUSE LLC
     3  #
     4  # Licensed under the Apache License, Version 2.0 (the "License");
     5  # you may not use this file except in compliance with the License.
     6  # You may obtain a copy of the License at
     7  #
     8  #   http://www.apache.org/licenses/LICENSE-2.0
     9  #
    10  # Unless required by applicable law or agreed to in writing, software
    11  # distributed under the License is distributed on an "AS IS" BASIS,
    12  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  # See the License for the specific language governing permissions and
    14  # limitations under the License.
    15  
    16  # Use bash, so that we can do process substitution.
    17  SHELL := bash
    18  
    19  # Go tools.
    20  GO ?= go
    21  GO_MD2MAN ?= go-md2man
    22  GOOS ?= $(shell go env GOOS)
    23  GOARCH ?= $(shell go env GOARCH)
    24  export GO111MODULE=on
    25  
    26  # Set up the ... lovely ... GOPATH hacks.
    27  PROJECT := github.com/opencontainers/umoci
    28  CMD := ${PROJECT}/cmd/umoci
    29  
    30  # We use Docker because Go is just horrific to deal with.
    31  UMOCI_IMAGE := umoci/ci:latest
    32  
    33  # TODO: We should test umoci with all of the security options disabled so that
    34  #       we can make sure umoci inside containers works fine (all of these
    35  #       security options are necessary for the test code to run, not umoci
    36  #       itself). The AppArmor/SELinux settings are needed because of the
    37  #       mount-related tests, and the seccomp/systempaths settings are required
    38  #       for the runc tests for rootless containers.
    39  DOCKER_RUN = docker run --rm -v ${PWD}:/go/src/${PROJECT} \
    40                          --security-opt apparmor=unconfined \
    41                          --security-opt label=disable \
    42                          --security-opt seccomp=unconfined \
    43                          --security-opt systempaths=unconfined
    44  
    45  # We only add the CodeCov environment (and ping codecov) if we're running in
    46  # Travis, to avoid pinging third-party servers for local builds.
    47  ifdef TRAVIS
    48  $(shell echo "WARNING: This make invocation will fetch and run code from https://codecov.io/." >&2)
    49  DOCKER_RUN += $(shell echo "+ Running https://codecov.io/env." >&2) \
    50                $(shell ./hack/ci-codecov.sh env)
    51  endif
    52  
    53  DOCKER_ROOTPRIV_RUN = $(DOCKER_RUN) --privileged --cap-add=SYS_ADMIN
    54  DOCKER_ROOTLESS_RUN = $(DOCKER_RUN) -u 1000:1000 --cap-drop=all
    55  
    56  # Output directory.
    57  BUILD_DIR ?= .
    58  
    59  # Release information.
    60  GPG_KEYID ?=
    61  
    62  # Version information.
    63  VERSION := $(shell cat ./VERSION)
    64  COMMIT_NO := $(shell git rev-parse HEAD 2> /dev/null || true)
    65  COMMIT := $(if $(shell git status --porcelain --untracked-files=no),"${COMMIT_NO}-dirty","${COMMIT_NO}")
    66  
    67  # Basic build flags.
    68  BUILD_FLAGS ?=
    69  BASE_FLAGS := ${BUILD_FLAGS} -tags "${BUILDTAGS}" -buildvcs=false
    70  BASE_LDFLAGS := -s -w -X ${PROJECT}.gitCommit=${COMMIT} -X ${PROJECT}.version=${VERSION}
    71  
    72  # Specific build flags for build type.
    73  ifeq ($(GOOS), linux)
    74  	DYN_BUILD_FLAGS := ${BASE_FLAGS} -buildmode=pie -ldflags "${BASE_LDFLAGS}"
    75  	TEST_BUILD_FLAGS := ${BASE_FLAGS} -buildmode=pie -ldflags "${BASE_LDFLAGS} -X ${PROJECT}/pkg/testutils.binaryType=test"
    76  else
    77  	DYN_BUILD_FLAGS := ${BASE_FLAGS} -ldflags "${BASE_LDFLAGS}"
    78  	TEST_BUILD_FLAGS := ${BASE_FLAGS} -ldflags "${BASE_LDFLAGS} -X ${PROJECT}/pkg/testutils.binaryType=test"
    79  endif
    80  
    81  
    82  STATIC_BUILD_FLAGS := ${BASE_FLAGS} -ldflags "${BASE_LDFLAGS} -extldflags '-static'"
    83  
    84  # Installation directories.
    85  DESTDIR ?=
    86  PREFIX ?=/usr/local
    87  BINDIR ?=$(PREFIX)/bin
    88  MANDIR ?=$(PREFIX)/share/man
    89  
    90  .DEFAULT: umoci
    91  
    92  GO_SRC = $(shell find . -type f -name '*.go')
    93  
    94  # NOTE: If you change these make sure you also update local-validate-build.
    95  
    96  umoci: $(GO_SRC)
    97  	GOOS=$(GOOS) GOARCH=$(GOARCH) $(GO) build ${DYN_BUILD_FLAGS} -o $(BUILD_DIR)/$@ ${CMD}
    98  
    99  umoci.static: $(GO_SRC)
   100  	env CGO_ENABLED=0 $(GO) build ${STATIC_BUILD_FLAGS} -o $(BUILD_DIR)/$@ ${CMD}
   101  
   102  .PHONY: static
   103  static: umoci.static
   104  
   105  umoci.cover: $(GO_SRC)
   106  	$(GO) test -c -cover -covermode=count -coverpkg=./... ${TEST_BUILD_FLAGS} -o $(BUILD_DIR)/$@ ${CMD}
   107  
   108  .PHONY: release
   109  release:
   110  	hack/release.sh \
   111  		-a 386 -a amd64 -a arm64 -a ppc64le -a riscv64 -a s390x \
   112  		-v $(VERSION) -S "$(GPG_KEYID)"
   113  
   114  .PHONY: install
   115  install: umoci docs
   116  	install -D -m0755 umoci $(DESTDIR)/$(BINDIR)/umoci
   117  	-for man in $(MANPAGES); do \
   118  		filename="$$(basename -- "$$man")"; \
   119  		target="$(DESTDIR)/$(MANDIR)/man$${filename##*.}/$$filename"; \
   120  		install -D -m0644 "$$man" "$$target"; \
   121  		gzip -9f "$$target"; \
   122  	 done
   123  
   124  .PHONY: uninstall
   125  uninstall:
   126  	rm -f $(DESTDIR)/$(BINDIR)/umoci
   127  	-rm -f $(DESTDIR)/$(MANDIR)/man*/umoci*
   128  
   129  .PHONY: clean
   130  clean:
   131  	rm -f umoci umoci.static umoci-ci.tar umoci.cov*
   132  	rm -f $(MANPAGES)
   133  
   134  .PHONY: validate
   135  validate: ci-image
   136  	$(DOCKER_RUN) $(UMOCI_IMAGE) make local-validate
   137  
   138  .PHONY: local-validate
   139  local-validate: local-validate-go local-validate-spell local-validate-reproducible local-validate-build
   140  
   141  .PHONY: local-validate-go
   142  local-validate-go:
   143  	@type gofmt     >/dev/null 2>/dev/null || (echo "ERROR: gofmt not found." && false)
   144  	test -z "$$(gofmt -s -l . | grep -vE '^vendor/|^third_party/' | tee /dev/stderr)"
   145  	@type golint    >/dev/null 2>/dev/null || (echo "ERROR: golint not found." && false)
   146  	test -z "$$(golint $(PROJECT)/... | grep -vE '/vendor/|/third_party/' | tee /dev/stderr)"
   147  	@go doc cmd/vet >/dev/null 2>/dev/null || (echo "ERROR: go vet not found." && false)
   148  	test -z "$$($(GO) vet $$($(GO) list $(PROJECT)/... | grep -vE '/vendor/|/third_party/') 2>&1 | tee /dev/stderr)"
   149  	@type gosec     >/dev/null 2>/dev/null || (echo "ERROR: gosec not found." && false)
   150  	test -z "$$(gosec -quiet -exclude=G301,G302,G304 $$GOPATH/$(PROJECT)/... | tee /dev/stderr)"
   151  	./hack/test-vendor.sh
   152  
   153  .PHONY: local-validate-spell
   154  local-validate-spell:
   155  	make clean
   156  	@type misspell  >/dev/null 2>/dev/null || (echo "ERROR: misspell not found." && false)
   157  	test -z "$$(find . -type f -print0 | xargs -0 misspell | grep -vE '/(vendor|third_party|\.site)/' | tee /dev/stderr)"
   158  
   159  # Make sure that our builds are reproducible even if you wait between them and
   160  # the modified time of the files is different.
   161  .PHONY: local-validate-reproducible
   162  local-validate-reproducible:
   163  	mkdir -p .tmp-validate
   164  	make -B umoci && cp umoci .tmp-validate/umoci.a
   165  	@echo sleep 10s
   166  	@sleep 10s && touch $(GO_SRC)
   167  	make -B umoci && cp umoci .tmp-validate/umoci.b
   168  	diff -s .tmp-validate/umoci.{a,b}
   169  	sha256sum .tmp-validate/umoci.{a,b}
   170  	rm -r .tmp-validate/umoci.{a,b}
   171  
   172  .PHONY: local-validate-build
   173  local-validate-build:
   174  	$(GO) build ${DYN_BUILD_FLAGS} -o /dev/null ${CMD}
   175  	env CGO_ENABLED=0 $(GO) build ${STATIC_BUILD_FLAGS} -o /dev/null ${CMD}
   176  	$(GO) test -run nothing ${DYN_BUILD_FLAGS} $(PROJECT)/...
   177  
   178  MANPAGES_MD := $(wildcard doc/man/*.md)
   179  MANPAGES    := $(MANPAGES_MD:%.md=%)
   180  
   181  doc/man/%.1: doc/man/%.1.md
   182  	$(GO_MD2MAN) -in $< -out $@
   183  
   184  .PHONY: docs
   185  docs: $(MANPAGES)
   186  
   187  CI_DOCKER_IMAGE ?=$(shell sed -En 's/^FROM\s+(.*)/\1/p' Dockerfile)
   188  TEST_DOCKER_IMAGE ?=$(shell sed -En 's/^ARG\s+TEST_DOCKER_IMAGE=(.*)/\1/p' Dockerfile)
   189  
   190  ifndef COVERAGE
   191  COVERAGE := $(notdir $(shell mktemp -u umoci.cov.XXXXXX))
   192  endif
   193  export COVERAGE
   194  
   195  .PHONY: test-unit
   196  test-unit: ci-image
   197  	touch $(COVERAGE) && chmod a+rw $(COVERAGE)
   198  	$(DOCKER_ROOTPRIV_RUN) -e COVERAGE $(UMOCI_IMAGE) make local-test-unit
   199  	$(DOCKER_ROOTLESS_RUN) -e COVERAGE $(UMOCI_IMAGE) make local-test-unit
   200  
   201  .PHONY: local-test-unit
   202  local-test-unit:
   203  	GO=$(GO) hack/test-unit.sh
   204  
   205  .PHONY: test-integration
   206  test-integration: ci-image
   207  	touch $(COVERAGE) && chmod a+rw $(COVERAGE)
   208  	$(DOCKER_ROOTPRIV_RUN) -e COVERAGE -e TESTS $(UMOCI_IMAGE) make local-test-integration
   209  	$(DOCKER_ROOTLESS_RUN) -e COVERAGE -e TESTS $(UMOCI_IMAGE) make local-test-integration
   210  
   211  .PHONY: local-test-integration
   212  local-test-integration: umoci.cover
   213  	TESTS="${TESTS}" hack/test-integration.sh
   214  
   215  .PHONY: shell
   216  shell: ci-image
   217  	$(DOCKER_RUN) -it $(UMOCI_IMAGE) bash
   218  
   219  .PHONY: root-shell
   220  root-shell: ci-image
   221  	$(DOCKER_ROOTPRIV_RUN) -it $(UMOCI_IMAGE) bash
   222  
   223  .PHONY: rootless-shell
   224  rootless-shell: ci-image
   225  	$(DOCKER_ROOTLESS_RUN) -it $(UMOCI_IMAGE) bash
   226  
   227  CACHE := .cache
   228  CACHE_IMAGE := $(CACHE)/ci-image.tar.zst
   229  
   230  .PHONY: ci-image
   231  ci-image:
   232  	docker pull $(CI_DOCKER_IMAGE)
   233  	! [ -f "$(CACHE_IMAGE)" ] || unzstd < "$(CACHE_IMAGE)" | docker load
   234  	DOCKER_BUILDKIT=1 docker build -t $(UMOCI_IMAGE) \
   235  	                               --progress plain \
   236  	                               --cache-from $(UMOCI_IMAGE) \
   237  	                               --build-arg TEST_DOCKER_IMAGE=$(TEST_DOCKER_IMAGE) \
   238  	                               --build-arg BUILDKIT_INLINE_CACHE=1 .
   239  
   240  .PHONY: ci-cache
   241  ci-cache: ci-image
   242  	rm -rf $(CACHE) && mkdir -p $(CACHE)
   243  	docker save $(UMOCI_IMAGE) | zstd > $(CACHE_IMAGE)
   244  
   245  .PHONY: ci-validate
   246  ci-validate: umoci umoci.static
   247  	make docs local-validate
   248  
   249  .PHONY: ci-unit
   250  ci-unit: umoci.cover
   251  	make test-unit
   252  
   253  .PHONY: ci-integration
   254  ci-integration: umoci.cover
   255  	make test-integration
   256  
   257  .PHONY: ci
   258  ci:
   259  	@echo "NOTE: This is not identical to the upstream CI, but the tests are the same."
   260  	make ci-validate ci-unit ci-integration
   261  	hack/ci-coverage.sh $(COVERAGE)