diff --git a/.github/actions/run-tests/Dockerfile b/.github/actions/run-tests/Dockerfile deleted file mode 100644 index a67d9b060..000000000 --- a/.github/actions/run-tests/Dockerfile +++ /dev/null @@ -1,35 +0,0 @@ -ARG BASE_VARIANT=bullseye -ARG GO_VERSION=1.17.5 -ARG XX_VERSION=1.1.0 - -ARG LIBGIT2_IMG=ghcr.io/fluxcd/golang-with-libgit2 -ARG LIBGIT2_TAG=libgit2-1.1.1-3 - -FROM tonistiigi/xx:${XX_VERSION} AS xx -FROM ${LIBGIT2_IMG}:${LIBGIT2_TAG} as libgit2 - -FROM golang:${GO_VERSION}-${BASE_VARIANT} as gostable - -# Copy the build utiltiies -COPY --from=xx / / -COPY --from=libgit2 /Makefile /libgit2/ - -# Install the libgit2 build dependencies -RUN make -C /libgit2 cmake - -RUN make -C /libgit2 dependencies - -# Compile and install libgit2 -RUN FLAGS=$(xx-clang --print-cmake-defines) make -C /libgit2 libgit2 - -# Use the GitHub Actions uid:gid combination for proper fs permissions -RUN groupadd -g 116 test && \ - useradd -u 1001 --gid test --shell /bin/sh --create-home test - -# Set path to envtest binaries. -ENV PATH="/github/workspace/envtest:${PATH}" - -# Run as test user -USER test - -ENTRYPOINT [ "/bin/sh", "-c" ] diff --git a/.github/actions/run-tests/action.yml b/.github/actions/run-tests/action.yml deleted file mode 100644 index 6679361aa..000000000 --- a/.github/actions/run-tests/action.yml +++ /dev/null @@ -1,12 +0,0 @@ -name: 'Run tests' -description: 'Run tests in docker container' -inputs: - command: - description: 'Command to run inside the container' - required: true - default: 'make test' -runs: - using: 'docker' - image: 'Dockerfile' - args: - - ${{ inputs.command }} diff --git a/.github/workflows/e2e.yaml b/.github/workflows/e2e.yaml index aec5dcd56..482e7cacb 100644 --- a/.github/workflows/e2e.yaml +++ b/.github/workflows/e2e.yaml @@ -27,6 +27,8 @@ jobs: key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} restore-keys: | ${{ runner.os }}-go- + - name: Run tests + run: make test - name: Setup Kubernetes uses: engineerd/setup-kind@v0.5.0 with: @@ -36,11 +38,6 @@ jobs: uses: fluxcd/pkg/actions/kustomize@main - name: Setup Helm uses: fluxcd/pkg/actions/helm@main - - name: Run tests - uses: ./.github/actions/run-tests - env: - GOROOT: - GOPATH: /github/home/go - name: Verify run: make verify - name: Run E2E tests @@ -59,6 +56,12 @@ jobs: uses: actions/setup-go@v2 with: go-version: 1.17.x + - name: Run tests + run: | + mkdir tmp-download; cd tmp-download; go mod init go-download; + GOBIN="${GITHUB_WORKSPACE}/build/gobin" go install sigs.k8s.io/controller-runtime/tools/setup-envtest@latest + cd ..; rm -rf tmp-download + make test - name: Prepare id: prep run: | @@ -80,3 +83,24 @@ jobs: run: | kind delete cluster --name ${{ steps.prep.outputs.CLUSTER }} rm /tmp/${{ steps.prep.outputs.CLUSTER }} + + # Runs 'make test' on macos-10.15 to assure development environment for + # contributors using MacOS. + darwin-amd64: + runs-on: macos-10.15 + steps: + - name: Checkout + uses: actions/checkout@v2 + - name: Setup Go + uses: actions/setup-go@v2 + with: + go-version: 1.17.x + - name: Restore Go cache + uses: actions/cache@v1 + with: + path: /home/runner/work/_temp/_github_home/go/pkg/mod + key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} + restore-keys: | + ${{ runner.os }}-go- + - name: Run tests + run: make test diff --git a/.gitignore b/.gitignore index f935d4a38..327ff117d 100644 --- a/.gitignore +++ b/.gitignore @@ -17,8 +17,5 @@ bin/ testbin/ config/release/ -# Exclude all libgit2 related files -hack/libgit2/ - # Exclude temporary build files build/ diff --git a/Dockerfile b/Dockerfile index ac8f06848..ca9289fef 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,14 +2,27 @@ ARG BASE_VARIANT=alpine ARG GO_VERSION=1.17 ARG XX_VERSION=1.1.0 -ARG LIBGIT2_IMG=ghcr.io/fluxcd/golang-with-libgit2 -ARG LIBGIT2_TAG=libgit2-1.1.1-4 +ARG LIBGIT2_IMG +ARG LIBGIT2_TAG -FROM --platform=linux/amd64 ${LIBGIT2_IMG}:${LIBGIT2_TAG} as build-amd64 -FROM --platform=linux/arm64 ${LIBGIT2_IMG}:${LIBGIT2_TAG} as build-arm64 -FROM --platform=linux/arm/v7 ${LIBGIT2_IMG}:${LIBGIT2_TAG} as build-armv7 +FROM ${LIBGIT2_IMG}:${LIBGIT2_TAG} AS libgit2-libs -FROM --platform=$BUILDPLATFORM build-$TARGETARCH$TARGETVARIANT AS build +FROM --platform=$BUILDPLATFORM tonistiigi/xx:${XX_VERSION} AS xx + +FROM --platform=$BUILDPLATFORM golang:${GO_VERSION}-${BASE_VARIANT} as gostable + +FROM gostable AS go-linux + +# Build-base consists of build platform dependencies and xx. +# These will be used at current arch to yield execute the cross compilations. +FROM go-${TARGETOS} AS build-base + +RUN apk add --no-cache clang lld pkgconfig + +COPY --from=xx / / + +# build-go-mod can still be cached at build platform architecture. +FROM build-base as build-go-mod # Configure workspace WORKDIR /workspace @@ -24,26 +37,55 @@ COPY go.sum go.sum # Cache modules RUN go mod download -RUN apk add clang lld pkgconfig ca-certificates +# The musl-tool-chain layer is an adhoc solution +# for the problem in which xx gets confused during compilation +# and a) looks for gold linker and then b) cannot find musl's dynamic linker. +FROM --platform=$BUILDPLATFORM alpine as musl-tool-chain + +COPY --from=xx / / + +RUN apk add bash curl tar + +WORKDIR /workspace +COPY hack/download-musl.sh . -# Build the binary -ENV CGO_ENABLED=1 ARG TARGETPLATFORM +ARG TARGETARCH +RUN ROOT_DIR="$(pwd)" TARGET_ARCH="$(xx-info alpine-arch)" ENV_FILE=true \ + ./download-musl.sh -RUN xx-apk add --no-cache \ - musl-dev gcc lld binutils-gold +# Build stage install per target platform +# dependency and effectively cross compile the application. +FROM build-go-mod as build + +ARG TARGETPLATFORM + +COPY --from=libgit2-libs /usr/local/ /usr/local/ + +# Some dependencies have to installed +# for the target platform: https://github.com/tonistiigi/xx#go--cgo +RUN xx-apk add musl-dev gcc lld + +WORKDIR /workspace + +# Copy source code +COPY main.go main.go +COPY controllers/ controllers/ +COPY pkg/ pkg/ +COPY internal/ internal/ + +COPY --from=musl-tool-chain /workspace/build /workspace/build + +ARG TARGETPLATFORM +ARG TARGETARCH +ENV CGO_ENABLED=1 -# Performance related changes: -# - Use read-only bind instead of copying go source files. -# - Cache go packages. -RUN --mount=target=. \ - --mount=type=cache,target=/root/.cache/go-build \ - --mount=type=cache,target=/go/pkg \ - export LIBRARY_PATH="/usr/local/$(xx-info triple)/lib:/usr/local/$(xx-info triple)/lib64:${LIBRARY_PATH}" && \ +# Instead of using xx-go, (cross) compile with vanilla go leveraging musl tool chain. +RUN export $(cat build/musl/$(xx-info alpine-arch).env | xargs) && \ + export LIBRARY_PATH="/usr/local/$(xx-info triple):/usr/local/$(xx-info triple)/lib64" && \ export PKG_CONFIG_PATH="/usr/local/$(xx-info triple)/lib/pkgconfig:/usr/local/$(xx-info triple)/lib64/pkgconfig" && \ - export FLAGS="$(pkg-config --static --libs --cflags libssh2 openssl libgit2)" && \ - CGO_LDFLAGS="${FLAGS} -static" \ - xx-go build \ + export CGO_LDFLAGS="$(pkg-config --static --libs --cflags libssh2 openssl libgit2) -static" && \ + GOARCH=$TARGETARCH go build \ -ldflags "-s -w" \ -tags 'netgo,osusergo,static_build' \ -o /source-controller -trimpath main.go; diff --git a/Makefile b/Makefile index 546da8f3f..b6f636bda 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ TAG ?= latest # Base image used to build the Go binary LIBGIT2_IMG ?= ghcr.io/fluxcd/golang-with-libgit2 -LIBGIT2_TAG ?= libgit2-1.1.1-4 +LIBGIT2_TAG ?= libgit2-1.1.1-6 # Allows for defining additional Docker buildx arguments, # e.g. '--push'. @@ -17,98 +17,94 @@ CRD_OPTIONS ?= crd:crdVersions=v1 # Repository root based on Git metadata REPOSITORY_ROOT := $(shell git rev-parse --show-toplevel) - -# Libgit2 version -LIBGIT2_VERSION ?= 1.1.1 +BUILD_DIR := $(REPOSITORY_ROOT)/build # Other dependency versions ENVTEST_BIN_VERSION ?= 1.19.2 -# libgit2 related magical paths -# These are used to determine if the target libgit2 version is already available on -# the system, or where they should be installed to -SYSTEM_LIBGIT2_VERSION := $(shell pkg-config --modversion libgit2 2>/dev/null) -LIBGIT2_PATH := $(REPOSITORY_ROOT)/hack/libgit2 +# Caches libgit2 versions per tag, "forcing" rebuild only when needed. +LIBGIT2_PATH := $(BUILD_DIR)/libgit2/$(LIBGIT2_TAG) LIBGIT2_LIB_PATH := $(LIBGIT2_PATH)/lib -LIBGIT2 := $(LIBGIT2_LIB_PATH)/libgit2.so.$(LIBGIT2_VERSION) +LIBGIT2_LIB64_PATH := $(LIBGIT2_PATH)/lib64 +LIBGIT2 := $(LIBGIT2_LIB_PATH)/libgit2.a +MUSL-CC = + +export CGO_ENABLED=1 +export PKG_CONFIG_PATH=$(LIBGIT2_LIB_PATH)/pkgconfig +export LIBRARY_PATH=$(LIBGIT2_LIB_PATH) +export CGO_CFLAGS=-I$(LIBGIT2_PATH)/include -I$(LIBGIT2_PATH)/include/openssl -ifneq ($(LIBGIT2_VERSION),$(SYSTEM_LIBGIT2_VERSION)) - LIBGIT2_FORCE ?= 1 -endif +# The pkg-config command will yield warning messages until libgit2 is downloaded. ifeq ($(shell uname -s),Darwin) - LIBGIT2 := $(LIBGIT2_LIB_PATH)/libgit2.$(LIBGIT2_VERSION).dylib - HAS_BREW := $(shell brew --version 2>/dev/null) -ifdef HAS_BREW - HAS_OPENSSL := $(shell brew --prefix openssl@1.1) -endif +export CGO_LDFLAGS=$(shell PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) pkg-config --libs --static --cflags libssh2 openssl libgit2 2>/dev/null) +GO_STATIC_FLAGS=-ldflags "-s -w" -tags 'netgo,osusergo,static_build' +else +export PKG_CONFIG_PATH:=$(PKG_CONFIG_PATH):$(LIBGIT2_LIB64_PATH)/pkgconfig +export LIBRARY_PATH:=$(LIBRARY_PATH):$(LIBGIT2_LIB64_PATH) +export CGO_LDFLAGS=$(shell PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) pkg-config --libs --static --cflags libssh2 openssl libgit2 2>/dev/null) endif +ifeq ($(shell uname -s),Linux) +ifeq ($(shell uname -m),x86_64) +# Linux x86_64 seem to be able to cope with the static libraries +# by having only musl-dev installed, without the need of using musl toolchain. + GO_STATIC_FLAGS=-ldflags "-s -w" -tags 'netgo,osusergo,static_build' +else + MUSL-PREFIX=$(BUILD_DIR)/musl/$(shell uname -m)-linux-musl-native/bin/$(shell uname -m)-linux-musl + MUSL-CC=$(MUSL-PREFIX)-gcc + export CC=$(MUSL-PREFIX)-gcc + export CXX=$(MUSL-PREFIX)-g++ + export AR=$(MUSL-PREFIX)-ar + GO_STATIC_FLAGS=-ldflags "-s -w -extldflags \"-static\"" -tags 'netgo,osusergo,static_build' +endif +endif + # API (doc) generation utilities CONTROLLER_GEN_VERSION ?= v0.7.0 GEN_API_REF_DOCS_VERSION ?= v0.3.0 -# Get the currently used golang install path (in GOPATH/bin, unless GOBIN is set) +# If gobin not set, create one on ./build and add to path. ifeq (,$(shell go env GOBIN)) -GOBIN=$(shell go env GOPATH)/bin +export GOBIN=$(BUILD_DIR)/gobin else -GOBIN=$(shell go env GOBIN) +export GOBIN=$(shell go env GOBIN) endif +export PATH:=${GOBIN}:${PATH} -ifeq ($(strip ${PKG_CONFIG_PATH}),) - MAKE_PKG_CONFIG_PATH = $(LIBGIT2_LIB_PATH)/pkgconfig +# Architecture to use envtest with +ifeq ($(shell uname -m),x86_64) +ENVTEST_ARCH ?= amd64 else - MAKE_PKG_CONFIG_PATH = ${PKG_CONFIG_PATH}:$(LIBGIT2_LIB_PATH)/pkgconfig +ENVTEST_ARCH ?= arm64 endif -ifdef HAS_OPENSSL - MAKE_PKG_CONFIG_PATH := $(MAKE_PKG_CONFIG_PATH):$(HAS_OPENSSL)/lib/pkgconfig +ifeq ($(shell uname -s),Darwin) +# Envtest only supports darwin-amd64 +ENVTEST_ARCH=amd64 endif -# Architecture to use envtest with -ENVTEST_ARCH ?= amd64 - all: build -build: $(LIBGIT2) ## Build manager binary -ifeq ($(shell uname -s),Darwin) - PKG_CONFIG_PATH=$(MAKE_PKG_CONFIG_PATH) \ - CGO_LDFLAGS="-Wl,-rpath,$(LIBGIT2_LIB_PATH)" \ - go build -o bin/manager main.go -else - PKG_CONFIG_PATH=$(MAKE_PKG_CONFIG_PATH) \ - go build -o bin/manager main.go -endif +build: check-deps $(LIBGIT2) ## Build manager binary + go build $(GO_STATIC_FLAGS) -o $(BUILD_DIR)/bin/manager main.go KUBEBUILDER_ASSETS?="$(shell $(ENVTEST) --arch=$(ENVTEST_ARCH) use -i $(ENVTEST_KUBERNETES_VERSION) --bin-dir=$(ENVTEST_ASSETS_DIR) -p path)" -test: $(LIBGIT2) install-envtest test-api ## Run tests -ifeq ($(shell uname -s),Darwin) - LD_LIBRARY_PATH=$(LIBGIT2_LIB_PATH) \ - PKG_CONFIG_PATH=$(MAKE_PKG_CONFIG_PATH) \ - CGO_LDFLAGS="-Wl,-rpath,$(LIBGIT2_LIB_PATH)" \ - KUBEBUILDER_ASSETS=$(KUBEBUILDER_ASSETS) \ - go test ./... -coverprofile cover.out -else - LD_LIBRARY_PATH=$(LIBGIT2_LIB_PATH) \ - PKG_CONFIG_PATH=$(MAKE_PKG_CONFIG_PATH) \ +test: $(LIBGIT2) install-envtest test-api check-deps ## Run tests KUBEBUILDER_ASSETS=$(KUBEBUILDER_ASSETS) \ - go test ./... -coverprofile cover.out + go test $(GO_STATIC_FLAGS) ./... -coverprofile cover.out + +check-deps: +ifeq ($(shell uname -s),Darwin) + if ! command -v pkg-config &> /dev/null; then echo "pkg-config is required"; exit 1; fi endif test-api: ## Run api tests cd api; go test ./... -coverprofile cover.out run: $(LIBGIT2) generate fmt vet manifests ## Run against the configured Kubernetes cluster in ~/.kube/config -ifeq ($(shell uname -s),Darwin) - LD_LIBRARY_PATH=$(LIBGIT2_LIB_PATH) \ - CGO_LDFLAGS="-Wl,-rpath,$(LIBGIT2_LIB_PATH)" \ - go run ./main.go -else - LD_LIBRARY_PATH=$(LIBGIT2_LIB_PATH) \ - go run ./main.go -endif - + go run $(GO_STATIC_FLAGS) ./main.go install: manifests ## Install CRDs into a cluster kustomize build config/crd | kubectl apply -f - @@ -142,16 +138,8 @@ fmt: ## Run go fmt against code cd api; go fmt ./... vet: $(LIBGIT2) ## Run go vet against code -ifeq ($(shell uname -s),Darwin) - PKG_CONFIG_PATH=$(MAKE_PKG_CONFIG_PATH) \ - CGO_LDFLAGS="-Wl,-rpath,$(LIBGIT2_LIB_PATH)" \ - go vet ./... - cd api; go vet ./... -else - PKG_CONFIG_PATH=$(MAKE_PKG_CONFIG_PATH) \ go vet ./... cd api; go vet ./... -endif generate: controller-gen ## Generate API code cd api; $(CONTROLLER_GEN) object:headerFile="../hack/boilerplate.go.txt" paths="./..." @@ -168,38 +156,38 @@ docker-push: ## Push Docker image docker push $(IMG):$(TAG) # Find or download controller-gen -CONTROLLER_GEN = $(shell pwd)/bin/controller-gen +CONTROLLER_GEN = $(GOBIN)/controller-gen .PHONY: controller-gen controller-gen: ## Download controller-gen locally if necessary. $(call go-install-tool,$(CONTROLLER_GEN),sigs.k8s.io/controller-tools/cmd/controller-gen@v0.7.0) # Find or download gen-crd-api-reference-docs -GEN_CRD_API_REFERENCE_DOCS = $(shell pwd)/bin/gen-crd-api-reference-docs +GEN_CRD_API_REFERENCE_DOCS = $(GOBIN)/gen-crd-api-reference-docs .PHONY: gen-crd-api-reference-docs gen-crd-api-reference-docs: ## Download gen-crd-api-reference-docs locally if necessary $(call go-install-tool,$(GEN_CRD_API_REFERENCE_DOCS),github.com/ahmetb/gen-crd-api-reference-docs@v0.3.0) -ENVTEST = $(shell pwd)/bin/setup-envtest +ENVTEST = $(GOBIN)/setup-envtest .PHONY: envtest setup-envtest: ## Download setup-envtest locally if necessary. $(call go-install-tool,$(ENVTEST),sigs.k8s.io/controller-runtime/tools/setup-envtest@latest) -ENVTEST_ASSETS_DIR=$(shell pwd)/testbin +ENVTEST_ASSETS_DIR=$(BUILD_DIR)/testbin ENVTEST_KUBERNETES_VERSION?=latest install-envtest: setup-envtest ## Download envtest binaries locally. mkdir -p ${ENVTEST_ASSETS_DIR} $(ENVTEST) use $(ENVTEST_KUBERNETES_VERSION) --arch=$(ENVTEST_ARCH) --bin-dir=$(ENVTEST_ASSETS_DIR) +# setup-envtest sets anything below k8s to 0555 + chmod -R u+w $(BUILD_DIR) libgit2: $(LIBGIT2) ## Detect or download libgit2 library -$(LIBGIT2): -ifeq (1, $(LIBGIT2_FORCE)) - @{ \ - set -e; \ - mkdir -p $(LIBGIT2_PATH); \ - curl -sL https://raw.githubusercontent.com/fluxcd/golang-with-libgit2/$(LIBGIT2_TAG)/hack/Makefile -o $(LIBGIT2_PATH)/Makefile; \ - INSTALL_PREFIX=$(LIBGIT2_PATH) make -C $(LIBGIT2_PATH) libgit2; \ - } +$(LIBGIT2): $(MUSL-CC) + IMG=$(LIBGIT2_IMG) TAG=$(LIBGIT2_TAG) ./hack/install-libraries.sh + +$(MUSL-CC): +ifneq ($(shell uname -s),Darwin) + ./hack/download-musl.sh endif .PHONY: help @@ -222,7 +210,6 @@ ifneq (, $(shell git status --porcelain --untracked-files=no)) endif # go-install-tool will 'go install' any package $2 and install it to $1. -PROJECT_DIR := $(shell dirname $(abspath $(lastword $(MAKEFILE_LIST)))) define go-install-tool @[ -f $(1) ] || { \ set -e ;\ @@ -230,7 +217,7 @@ TMP_DIR=$$(mktemp -d) ;\ cd $$TMP_DIR ;\ go mod init tmp ;\ echo "Downloading $(2)" ;\ -GOBIN=$(PROJECT_DIR)/bin go install $(2) ;\ +go install $(2) ;\ rm -rf $$TMP_DIR ;\ } endef diff --git a/controllers/suite_test.go b/controllers/suite_test.go index 9520bcbb6..f0c411702 100644 --- a/controllers/suite_test.go +++ b/controllers/suite_test.go @@ -56,6 +56,8 @@ var exampleCA []byte var ctx context.Context var cancel context.CancelFunc +const timeout = time.Second * 30 + func TestAPIs(t *testing.T) { RegisterFailHandler(Fail) @@ -64,7 +66,12 @@ func TestAPIs(t *testing.T) { []Reporter{printer.NewlineReporter{}}) } -var _ = BeforeSuite(func(done Done) { +var _ = BeforeSuite(func() { + done := make(chan interface{}) + go func() { + close(done) + }() + logf.SetLogger( zap.New(zap.WriteTo(GinkgoWriter), zap.UseDevMode(true)), ) @@ -153,7 +160,7 @@ var _ = BeforeSuite(func(done Done) { k8sClient = k8sManager.GetClient() Expect(k8sClient).ToNot(BeNil()) - close(done) + Eventually(done, timeout).Should(BeClosed()) }, 60) var _ = AfterSuite(func() { diff --git a/hack/download-musl.sh b/hack/download-musl.sh new file mode 100755 index 000000000..3f5b527d2 --- /dev/null +++ b/hack/download-musl.sh @@ -0,0 +1,71 @@ +#!/usr/bin/env bash + +set -eoux pipefail + +MUSL_X86_64_FILENAME=x86_64-linux-musl-native.tgz +MUSL_X86_64_SHA512=44d441ad9aa11a06feddf3daa4c9f53ad7d9ca37af1f5a61379aca07793703d179410cea723c1b7fca94c4de19a321228bdb3656bc5cbdb5e3bea8e2d6dac6c7 +MUSL_AARCH64_FILENAME=aarch64-linux-musl-native.tgz +MUSL_AARCH64_SHA512=16d544e09845c9dbba50f29e0cb04dd661e17eb63c56acad6a67fd2a78aa7596b792477c7177d3cd56d408a27dc291a90507df882f2b099c0f25511ce08fd3b5 +MUSL_XX86_64_FILENAME=x86_64-linux-musl-cross.tgz +MUSL_XX86_64_SHA512=52abd1a56e670952116e35d1a62e048a9b6160471d988e16fa0e1611923dd108a581d2e00874af5eb04e4968b1ba32e0eb449a1f15c3e4d5240ebe09caf5a9f3 +MUSL_XAARCH64_FILENAME=aarch64-linux-musl-cross.tgz +MUSL_XAARCH64_SHA512=8695ff86979cdf30fbbcd33061711f5b1ebc3c48a87822b9ca56cde6d3a22abd4dab30fdcd1789ac27c6febbaeb9e5bde59d79d66552fae53d54cc1377a19272 +MUSL_XARMV7_FILENAME=armv7l-linux-musleabihf-cross.tgz +MUSL_XARMV7_SHA512=1bb399a61da425faac521df9b8d303e60ad101f6c7827469e0b4bc685ce1f3dedc606ac7b1e8e34d79f762a3bfe3e8ab479a97e97d9f36fbd9fc5dc9d7ed6fd1 + +TARGET_ARCH="${TARGET_ARCH:-$(uname -m)}" +ENV_FILE="${ENV_FILE:-false}" + +MUSL_FILENAME="" +MUSL_SHA512="" + +ROOT_DIR="${ROOT_DIR:-$(git rev-parse --show-toplevel)}" +MUSL_DIR="${ROOT_DIR}/build/musl" + + +if [ "${TARGET_ARCH}" = "$(uname -m)" ]; then + MUSL_FILENAME="${MUSL_X86_64_FILENAME}" + MUSL_SHA512="${MUSL_X86_64_SHA512}" + MUSL_PREFIX="${TARGET_ARCH}-linux-musl-native/bin/${TARGET_ARCH}-linux-musl" + if [ "${TARGET_ARCH}" = "arm64" ] || [ "${TARGET_ARCH}" = "aarch64" ]; then + MUSL_FILENAME="${MUSL_AARCH64_FILENAME}" + MUSL_SHA512="${MUSL_AARCH64_SHA512}" + fi +else + MUSL_FILENAME="${MUSL_XX86_64_FILENAME}" + MUSL_SHA512="${MUSL_XX86_64_SHA512}" + MUSL_PREFIX="${TARGET_ARCH}-linux-musl-cross/bin/${TARGET_ARCH}-linux-musl" + if [ "${TARGET_ARCH}" = "arm64" ] || [ "${TARGET_ARCH}" = "aarch64" ]; then + MUSL_FILENAME="${MUSL_XAARCH64_FILENAME}" + MUSL_SHA512="${MUSL_XAARCH64_SHA512}" + elif [ "${TARGET_ARCH}" = "arm" ] || [ "${TARGET_ARCH}" = "armv7" ]; then + MUSL_FILENAME="${MUSL_XARMV7_FILENAME}" + MUSL_SHA512="${MUSL_XARMV7_SHA512}" + MUSL_PREFIX=armv7l-linux-musleabihf-cross/bin/armv7l-linux-musleabihf + fi +fi + +mkdir -p "${MUSL_DIR}" + +if "${ENV_FILE}"; then + cat< "${MUSL_DIR}/${TARGET_ARCH}.env" +CC="$(pwd)/build/musl/${MUSL_PREFIX}-gcc" +CXX="$(pwd)/build/musl/${MUSL_PREFIX}-g++" +AR="$(pwd)/build/musl/${MUSL_PREFIX}-ar" +EOF +fi + +MUSL_AARCH64_URL="https://more.musl.cc/11.2.1/x86_64-linux-musl/${MUSL_FILENAME}" + +if [ ! -f "${MUSL_DIR}/bin" ]; then + TARGET_FILE="${MUSL_DIR}/${MUSL_FILENAME}" + curl -o "${TARGET_FILE}" -LO "${MUSL_AARCH64_URL}" + if ! echo "${MUSL_SHA512} ${TARGET_FILE}" | sha512sum; then + echo "Checksum failed for ${MUSL_FILENAME}." + rm -rf "${MUSL_DIR}" + exit 1 + fi + + tar xzf "${TARGET_FILE}" -C "${MUSL_DIR}" + rm "${TARGET_FILE}" +fi diff --git a/hack/install-libraries.sh b/hack/install-libraries.sh new file mode 100755 index 000000000..270ce1915 --- /dev/null +++ b/hack/install-libraries.sh @@ -0,0 +1,98 @@ +#!/usr/bin/env bash + +set -euxo pipefail + +IMG="${IMG:-}" +TAG="${TAG:-}" +IMG_TAG="${IMG}:${TAG}" + +function extract(){ + PLATFORM=$1 + DIR=$2 + + id=$(docker create --platform="${PLATFORM}" "${IMG_TAG}" sh) + docker cp "${id}":/usr/local - > output.tar.gz + docker rm -v "${id}" + + tar -xf output.tar.gz "local/${DIR}" + rm output.tar.gz +} + +function setup() { + PLATFORM=$1 + DIR=$2 + + extract "${PLATFORM}" "${DIR}" + + NEW_DIR="$(/bin/pwd)/build/libgit2/${TAG}" + INSTALLED_DIR="/usr/local/${DIR}" + + mv "local/${DIR}" "${TAG}" + rm -rf "local" + mv "${TAG}/" "./build/libgit2" + + # Update the prefix paths included in the .pc files. + # This will make it easier to update to the location in which they will be used. + find "${NEW_DIR}" -type f -name "*.pc" | xargs -I {} sed -i "s;${INSTALLED_DIR};${NEW_DIR};g" {} +} + +function setup_current() { + if [ -d "./build/libgit2/${TAG}" ]; then + echo "Skipping libgit2 setup as it already exists" + exit 0 + fi + + mkdir -p "./build/libgit2" + if [[ $OSTYPE == 'darwin'* ]]; then + # For MacOS development environments, download the amd64 static libraries released from from golang-with-libgit2. + + #TODO: update URL with official URL + TAG: + curl -o output.tar.gz -LO "https://github.com/fluxcd/golang-with-libgit2/releases/download/${TAG}/darwin-libs.tar.gz" + + DIR=libgit2-darwin + NEW_DIR="$(/bin/pwd)/build/libgit2/${TAG}" + INSTALLED_DIR="/Users/runner/work/golang-with-libgit2/golang-with-libgit2/build/${DIR}-amd64" + + tar -xf output.tar.gz + rm output.tar.gz + mv "${DIR}" "${TAG}" + mv "${TAG}/" "./build/libgit2" + + LIBGIT2_SED="s;-L/Applications/Xcode_.* ;;g" + LIBGIT2PC="$(/bin/pwd)/build/libgit2/${TAG}/lib/pkgconfig/libgit2.pc" + # Some macOS users may override their sed with gsed. If gsed is the PATH, use that instead. + if command -v gsed &> /dev/null; then + # Removes abs path from build machine, and let iconv be resolved automatically by default search paths. + gsed -i "${LIBGIT2_SED}" "${LIBGIT2PC}" + + # Update the prefix paths included in the .pc files. + # This will make it easier to update to the location in which they will be used. + # sed has a sight different behaviour in MacOS + find "${NEW_DIR}" -type f -name "*.pc" | xargs -I {} gsed -i "s;${INSTALLED_DIR};${NEW_DIR};g" {} + else + # Removes abs path from build machine, and let iconv be resolved automatically by default search paths. + sed -i "" "${LIBGIT2_SED}" "${LIBGIT2PC}" + + # Update the prefix paths included in the .pc files. + # This will make it easier to update to the location in which they will be used. + # sed has a sight different behaviour in MacOS + find "${NEW_DIR}" -type f -name "*.pc" | xargs -I {} sed -i "" "s;${INSTALLED_DIR};${NEW_DIR};g" {} + fi + else + # for linux development environments, use the static libraries from the official container images. + DIR="x86_64-alpine-linux-musl" + PLATFORM="linux/amd64" + + if [[ "$(uname -m)" == armv7* ]]; then + DIR="armv7-alpine-linux-musleabihf" + PLATFORM="linux/arm/v7" + elif [ "$(uname -m)" = "arm64" ] || [ "$(uname -m)" = "aarch64" ]; then + DIR="aarch64-alpine-linux-musl" + PLATFORM="linux/arm64" + fi + + setup "${PLATFORM}" "${DIR}" + fi +} + +setup_current