From 319fcf52fc5eaa3a83c4a152405910a5b516f89a Mon Sep 17 00:00:00 2001 From: Chris Evich Date: Thu, 9 Sep 2021 13:46:21 -0400 Subject: Cross-build release-archives w/ arch in filename Fixes #11417 Cross-building the podman-remote documentation requires a functional native architecture executable. However `make` only deals with files/timestamps, it doesn't understand if an existing binary will function on the system or not. This makes building cross-platform releases incredibly accident-prone and fragile. A practical way to deal with this, is via multiple conditional (nested) `make` calls along with careful manipulation of `$GOOS` and `$GOARCH`. Also, when cross-building releases be kind to humans and cleanup any non-native binaries left behind. Update the `Alt Arch. Cross` Cirrus-CI task to build release archives for all Linux architectures supported by golang and podman. Update the `OSX Cross` task to additionally build for the M1 (arm64) architecture. Finally, update the release process documentation to reflect the new locations (Cirrus-CI task names) for the release archives. Include a note about additional manual work being required to produce the signed `.dmg` file for MacOS. Signed-off-by: Chris Evich --- .cirrus.yml | 10 +++-- Makefile | 98 +++++++++++++++++++++++++++++++++--------------- RELEASE_PROCESS.md | 18 ++++++--- contrib/cirrus/runner.sh | 22 +++++++++-- 4 files changed, 107 insertions(+), 41 deletions(-) diff --git a/.cirrus.yml b/.cirrus.yml index 581aaaa7b..968854771 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -359,11 +359,15 @@ osx_alt_build_task: TEST_FLAVOR: "altbuild" ALT_NAME: 'OSX Cross' osx_instance: - image: 'catalina-base' - script: + image: 'big-sur-base' + setup_script: - brew install go - brew install go-md2man - - make podman-remote-release-darwin.zip + - go version + build_amd64_script: + - make podman-remote-release-darwin_amd64.zip + build_arm64_script: + - make podman-remote-release-darwin_arm64.zip GOARCH=arm64 always: *binary_artifacts diff --git a/Makefile b/Makefile index 12889c1c5..37396a4a6 100644 --- a/Makefile +++ b/Makefile @@ -23,6 +23,7 @@ export GOPROXY=https://proxy.golang.org GO ?= go +GOCMD = CGO_ENABLED=$(CGO_ENABLED) GOOS=$(GOOS) GOARCH=$(GOARCH) $(GO) COVERAGE_PATH ?= .coverage DESTDIR ?= EPOCH_TEST_COMMIT ?= $(shell git merge-base $${DEST_BRANCH:-main} HEAD) @@ -150,7 +151,11 @@ err_if_empty = $(if $(strip $($(1))),$(strip $($(1))),$(error Required variable # Podman does not work w/o CGO_ENABLED, except in some very specific cases CGO_ENABLED ?= 1 # Default to the native OS type and architecture unless otherwise specified -GOOS ?= $(shell $(GO) env GOOS) +NATIVE_GOOS := $(shell env -u GOOS $(GO) env GOOS) +GOOS ?= $(NATIVE_GOOS) +# Default to the native architecture type +NATIVE_GOARCH := $(shell env -u GOARCH $(GO) env GOARCH) +GOARCH ?= $(NATIVE_GOARCH) ifeq ($(call err_if_empty,GOOS),windows) BINSFX := .exe SRCBINDIR := bin/windows @@ -162,7 +167,7 @@ BINSFX := -remote SRCBINDIR := bin endif # Necessary for nested-$(MAKE) calls and docs/remote-docs.sh -export GOOS CGO_ENABLED BINSFX SRCBINDIR +export GOOS GOARCH CGO_ENABLED BINSFX SRCBINDIR define go-get env GO111MODULE=off \ @@ -239,11 +244,11 @@ gofmt: ## Verify the source code gofmt .PHONY: test/checkseccomp/checkseccomp test/checkseccomp/checkseccomp: .gopathok $(wildcard test/checkseccomp/*.go) - $(GO) build $(BUILDFLAGS) -ldflags '$(LDFLAGS_PODMAN)' -tags "$(BUILDTAGS)" -o $@ ./test/checkseccomp + $(GOCMD) build $(BUILDFLAGS) -ldflags '$(LDFLAGS_PODMAN)' -tags "$(BUILDTAGS)" -o $@ ./test/checkseccomp .PHONY: test/testvol/testvol test/testvol/testvol: .gopathok $(wildcard test/testvol/*.go) - $(GO) build $(BUILDFLAGS) -ldflags '$(LDFLAGS_PODMAN)' -o $@ ./test/testvol + $(GOCMD) build $(BUILDFLAGS) -ldflags '$(LDFLAGS_PODMAN)' -o $@ ./test/testvol .PHONY: volume-plugin-test-image volume-plugin-test-img: @@ -251,7 +256,7 @@ volume-plugin-test-img: .PHONY: test/goecho/goecho test/goecho/goecho: .gopathok $(wildcard test/goecho/*.go) - $(GO) build $(BUILDFLAGS) -ldflags '$(LDFLAGS_PODMAN)' -o $@ ./test/goecho + $(GOCMD) build $(BUILDFLAGS) -ldflags '$(LDFLAGS_PODMAN)' -o $@ ./test/goecho test/version/version: .gopathok version/version.go $(GO) build -o $@ ./test/version/ @@ -292,8 +297,7 @@ ifeq (,$(findstring systemd,$(BUILDTAGS))) Install libsystemd on Ubuntu or systemd-devel on rpm based \ distro for journald support." endif - CGO_ENABLED=$(CGO_ENABLED) \ - $(GO) build \ + $(GOCMD) build \ $(BUILDFLAGS) \ -ldflags '$(LDFLAGS_PODMAN)' \ -tags "$(BUILDTAGS)" \ @@ -304,18 +308,14 @@ $(SRCBINDIR): mkdir -p $(SRCBINDIR) $(SRCBINDIR)/podman$(BINSFX): $(SRCBINDIR) .gopathok $(SOURCES) go.mod go.sum - CGO_ENABLED=$(CGO_ENABLED) \ - GOOS=$(GOOS) \ - $(GO) build \ + $(GOCMD) build \ $(BUILDFLAGS) \ -ldflags '$(LDFLAGS_PODMAN)' \ -tags "${REMOTETAGS}" \ -o $@ ./cmd/podman $(SRCBINDIR)/podman-remote-static: $(SRCBINDIR) .gopathok $(SOURCES) go.mod go.sum - CGO_ENABLED=0 \ - GOOS=$(GOOS) \ - $(GO) build \ + $(GOCMD) build \ $(BUILDFLAGS) \ -ldflags '$(LDFLAGS_PODMAN_STATIC)' \ -tags "${REMOTETAGS}" \ @@ -333,6 +333,7 @@ podman-remote-linux: ## Build podman-remote for Linux $(MAKE) \ CGO_ENABLED=0 \ GOOS=linux \ + GOARCH=$(GOARCH) \ bin/podman-remote PHONY: podman-remote-static @@ -350,6 +351,7 @@ podman-remote-darwin: ## Build podman-remote for macOS $(MAKE) \ CGO_ENABLED=0 \ GOOS=darwin \ + GOARCH=$(GOARCH) \ bin/darwin/podman ### @@ -359,7 +361,7 @@ podman-remote-darwin: ## Build podman-remote for macOS .PHONY: generate-bindings generate-bindings: ifneq ($(GOOS),darwin) - GO111MODULE=off $(GO) generate ./pkg/bindings/... ; + GO111MODULE=off $(GOCMD) generate ./pkg/bindings/... ; endif # DO NOT USE: use local-cross instead @@ -444,12 +446,14 @@ docs: $(MANPAGES) ## Generate documentation # docs/remote-docs.sh requires a locally executable 'podman-remote' binary # in addition to the target-archetecture binary (if any). -install-podman-remote-%-docs: podman-remote-$(shell env -i HOME=$$HOME PATH=$$PATH go env GOOS) docs $(MANPAGES) +podman-remote-%-docs: podman-remote-$(NATIVE_GOOS) + $(eval GOOS := $*) + $(MAKE) docs $(MANPAGES) rm -rf docs/build/remote mkdir -p docs/build/remote ln -sf $(CURDIR)/docs/source/markdown/links docs/build/man/ docs/remote-docs.sh \ - $* \ + $(GOOS) \ docs/build/remote/$* \ $(if $(findstring windows,$*),docs/source/markdown,docs/build/man) @@ -602,35 +606,65 @@ tests-expect-exit: ### Release/Packaging targets ### -podman-release.tar.gz: test/version/version binaries docs ## Build all binaries, docs., and installation tree, into a tarball. +.PHONY: podman-release +podman-release: podman-release-$(GOARCH).tar.gz # Build all Linux binaries for $GOARCH, docs., and installation tree, into a tarball. + +# The following two targets are nuanced and complex: +# Cross-building the podman-remote documentation requires a functional +# native architecture executable. However `make` only deals with +# files/timestamps, it doesn't understand if an existing binary will +# function on the system or not. This makes building cross-platform +# releases incredibly accident-prone and fragile. The only practical +# way to deal with this, is via multiple conditional (nested) `make` +# calls along with careful manipulation of `$GOOS` and `$GOARCH`. + +podman-release-%.tar.gz: test/version/version $(eval TMPDIR := $(shell mktemp -d podman_tmp_XXXX)) $(eval SUBDIR := podman-v$(call err_if_empty,RELEASE_NUMBER)) + $(eval _DSTARGS := "DESTDIR=$(TMPDIR)/$(SUBDIR)" "PREFIX=/usr") + $(eval GOARCH := $*) mkdir -p "$(TMPDIR)/$(SUBDIR)" - $(MAKE) install.bin install.remote install.man \ - install.systemd "DESTDIR=$(TMPDIR)/$(SUBDIR)" "PREFIX=/usr" + $(MAKE) GOOS=$(GOOS) GOARCH=$(NATIVE_GOARCH) \ + clean-binaries docs podman-remote-$(GOOS)-docs + if [[ "$(GOARCH)" != "$(NATIVE_GOARCH)" ]]; then \ + $(MAKE) CGO_ENABLED=0 GOOS=$(GOOS) GOARCH=$(GOARCH) \ + BUILDTAGS="$(BUILDTAGS_CROSS)" clean-binaries binaries; \ + else \ + $(MAKE) GOOS=$(GOOS) GOARCH=$(GOARCH) binaries; \ + fi + $(MAKE) $(_DSTARGS) install.bin-nobuild install.remote-nobuild install.man install.systemd tar -czvf $@ --xattrs -C "$(TMPDIR)" "./$(SUBDIR)" + if [[ "$(GOARCH)" != "$(NATIVE_GOARCH)" ]]; then $(MAKE) clean-binaries; fi -rm -rf "$(TMPDIR)" -podman-remote-release-%.zip: test/version/version podman-remote-% install-podman-remote-%-docs ## Build podman-remote for GOOS=%, docs., and installation zip. +podman-remote-release-%.zip: test/version/version ## Build podman-remote for %=$GOOS_$GOARCH, and docs. into an installation zip. $(eval TMPDIR := $(shell mktemp -d podman_tmp_XXXX)) $(eval SUBDIR := podman-$(call err_if_empty,RELEASE_NUMBER)) + $(eval _DSTARGS := "DESTDIR=$(TMPDIR)/$(SUBDIR)" "PREFIX=/usr") + $(eval GOOS := $(firstword $(subst _, ,$*))) + $(eval GOARCH := $(lastword $(subst _, ,$*))) + $(eval _GOPLAT := GOOS=$(call err_if_empty,GOOS) GOARCH=$(call err_if_empty,GOARCH)) mkdir -p "$(TMPDIR)/$(SUBDIR)" - $(MAKE) \ - GOOS=$* \ - DESTDIR=$(TMPDIR)/ \ - BINDIR=$(SUBDIR) \ - SELINUXOPT="" \ - install.remote-nobuild - cp -r ./docs/build/remote/$* "$(TMPDIR)/$(SUBDIR)/docs/" + $(MAKE) GOOS=$(GOOS) GOARCH=$(NATIVE_GOARCH) \ + clean-binaries podman-remote-$(GOOS)-docs + if [[ "$(GOARCH)" != "$(NATIVE_GOARCH)" ]]; then \ + $(MAKE) CGO_ENABLED=0 $(GOPLAT) BUILDTAGS="$(BUILDTAGS_CROSS)" \ + clean-binaries podman-remote-$(GOOS); \ + else \ + $(MAKE) $(GOPLAT) podman-remote-$(GOOS); \ + fi + cp -r ./docs/build/remote/$(GOOS) "$(TMPDIR)/$(SUBDIR)/docs/" cp ./contrib/remote/containers.conf "$(TMPDIR)/$(SUBDIR)/" + $(MAKE) $(GOPLAT) $(_DSTARGS) SELINUXOPT="" install.remote-nobuild cd "$(TMPDIR)" && \ zip --recurse-paths "$(CURDIR)/$@" "./" + if [[ "$(GOARCH)" != "$(NATIVE_GOARCH)" ]]; then $(MAKE) clean-binaries; fi -rm -rf "$(TMPDIR)" .PHONY: podman.msi podman.msi: test/version/version ## Build podman-remote, package for installation on Windows $(MAKE) podman-v$(RELEASE_NUMBER).msi -podman-v$(RELEASE_NUMBER).msi: podman-remote-windows install-podman-remote-windows-docs +podman-v$(RELEASE_NUMBER).msi: podman-remote-windows podman-remote-windows-docs $(eval DOCFILE := docs/build/remote/windows) find $(DOCFILE) -print | \ wixl-heat --var var.ManSourceDir --component-group ManFiles \ @@ -821,8 +855,13 @@ uninstall: rm -f ${DESTDIR}${USERSYSTEMDDIR}/podman.socket rm -f ${DESTDIR}${USERSYSTEMDDIR}/podman.service +.PHONY: clean-binaries +clean-binaries: ## Remove platform/architecture specific binary files + rm -rf \ + bin \ + .PHONY: clean -clean: ## Clean all make artifacts +clean: clean-binaries ## Clean all make artifacts rm -rf \ .gopathok \ _output \ @@ -830,7 +869,6 @@ clean: ## Clean all make artifacts $(wildcard podman-remote*.zip) \ $(wildcard podman_tmp_*) \ $(wildcard podman*.tar.gz) \ - bin \ build \ test/checkseccomp/checkseccomp \ test/goecho/goecho \ diff --git a/RELEASE_PROCESS.md b/RELEASE_PROCESS.md index bdf8aca88..32d4c039e 100644 --- a/RELEASE_PROCESS.md +++ b/RELEASE_PROCESS.md @@ -234,16 +234,24 @@ spelled with complete minutiae. 1. Return to the Cirrus-CI Build page for the new release tag, confirm (or wait for) it to complete, re-running any failed tasks as appropriate. - 1. For anything other than an RC, download the new release artifacts - (the binaries which were actually tested). Visit each of the - "Build for ...", "Static Build", and "... Cross" tasks. - 1. Under the "Artifacts" section of each task, click the "gosrc" item, + 1. For anything other than an RC, download the new release artifacts from CI + (the binaries which were actually tested). The items are + located under the *checks* tab in github for: + + * `Cirrus CI / Alt Arch. Cross` - tarball for each architecture + * `Cirrus CI / OSX Cross` - two zip files (amd64 and arm64) + * `Cirrus CI / Windows Cross` - an `msi` file + * `Cirrus CI / Static Build` - the `bin/podman-remote` file + + Under the "Artifacts" section of each task, click the "gosrc" link, find and download the release archive (`zip`, `tar.gz` or `.msi`). Save the the archive with a meaningful name, for example `podman-v3.0.0.msi`. 1. For the "Static Build" task, find the compiled `podman` and `podman-remote` - binaries under the "binary", "bin" links. Tar these files as + binaries under the "binary", then "bin" links. Tar these files as `podman-static.tar.gz`. + 1. The `podman-vX.Y.Z.dmg` file is produced manually by someone in + posession of a developer signing key. 1. In the directory where you downloaded the archives, run `sha256sum *.tar.gz *.zip *.msi > shasums` to generate SHA sums. 1. Go to `https://github.com/containers/podman/releases/tag/vX.Y.Z` and diff --git a/contrib/cirrus/runner.sh b/contrib/cirrus/runner.sh index c1972b90f..128398c38 100755 --- a/contrib/cirrus/runner.sh +++ b/contrib/cirrus/runner.sh @@ -205,10 +205,12 @@ function _run_build() { # Ensure always start from clean-slate with all vendor modules downloaded make clean make vendor - make podman-release.tar.gz # includes podman, podman-remote, and docs + make podman-release # includes podman, podman-remote, and docs } function _run_altbuild() { + local -a arches + local arch req_env_vars ALT_NAME # Defined in .cirrus.yml # shellcheck disable=SC2154 @@ -221,7 +223,7 @@ function _run_altbuild() { make build-all-new-commits GIT_BASE_BRANCH=origin/$DEST_BRANCH ;; *Windows*) - make podman-remote-release-windows.zip + make podman-remote-release-windows_amd64.zip make podman.msi ;; *Without*) @@ -232,7 +234,21 @@ function _run_altbuild() { rpmbuild --rebuild ./podman-*.src.rpm ;; Alt*Cross) - make local-cross + arches=(\ + amd64 + ppc64le + arm + arm64 + 386 + s390x + mips + mipsle + mips64 + mips64le) + for arch in "${arches[@]}"; do + msg "Building release archive for $arch" + make podman-release-${arch}.tar.gz GOARCH=$arch + done ;; *Static*) req_env_vars CTR_FQIN -- cgit v1.2.3-54-g00ecf