diff --git a/.dockerignore b/.dockerignore index a5d8f7237..e660fd93d 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,2 +1 @@ bin/ -dist/ diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4f73eaaca..e7af40b02 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,9 +1,15 @@ -name: Continuous integration +name: ci + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true on: push: branches: - - v2 + - 'v2' + tags: + - 'v*' pull_request: workflow_dispatch: inputs: @@ -11,115 +17,201 @@ on: description: 'To run with tmate enter "debug_enabled"' required: false default: "false" + env: - GO_VERSION: 1.18.5 - DOCKER_CLI_VERSION: 20.10.17 + GO_VERSION: "1.18.5" # for non sandboxed e2e tests + DESTDIR: "./bin" + DOCKER_CLI_VERSION: "20.10.17" + jobs: - lint: - name: Lint + prepare: + runs-on: ubuntu-latest + outputs: + matrix: ${{ steps.platforms.outputs.matrix }} + steps: + - + name: Checkout + uses: actions/checkout@v3 + - + name: Create matrix + id: platforms + run: | + echo ::set-output name=matrix::$(docker buildx bake binary-cross --print | jq -cr '.target."binary-cross".platforms') + - + name: Show matrix + run: | + echo ${{ steps.platforms.outputs.matrix }} + + validate: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + target: + - lint + - validate-go-mod + - validate-headers + - validate-docs + steps: + - + name: Checkout + uses: actions/checkout@v3 + - + name: Set up Docker Buildx + uses: docker/setup-buildx-action@v2 + - + name: Run + run: | + make ${{ matrix.target }} + + binary: + runs-on: ubuntu-latest + needs: + - prepare + strategy: + fail-fast: false + matrix: + platform: ${{ fromJson(needs.prepare.outputs.matrix) }} + steps: + - + name: Prepare + run: | + platform=${{ matrix.platform }} + echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV + - + name: Checkout + uses: actions/checkout@v3 + - + name: Set up QEMU + uses: docker/setup-qemu-action@v2 + - + name: Set up Docker Buildx + uses: docker/setup-buildx-action@v2 + - + name: Build + uses: docker/bake-action@v2 + with: + targets: release + set: | + *.platform=${{ matrix.platform }} + *.cache-from=type=gha,scope=binary-${{ env.PLATFORM_PAIR }} + *.cache-to=type=gha,scope=binary-${{ env.PLATFORM_PAIR }},mode=max + - + name: Upload artifacts + uses: actions/upload-artifact@v3 + with: + name: compose + path: ${{ env.DESTDIR }}/* + if-no-files-found: error + + test: runs-on: ubuntu-latest steps: - - name: Checkout code into the Go module directory + - + name: Checkout uses: actions/checkout@v3 + - + name: Set up Docker Buildx + uses: docker/setup-buildx-action@v2 + - + name: Test + uses: docker/bake-action@v2 + with: + targets: test + set: | + *.cache-from=type=gha,scope=test + *.cache-to=type=gha,scope=test - - name: Set up Go ${{ env.GO_VERSION }} + e2e: + runs-on: ubuntu-latest + env: + DESTDIR: "./bin/build" + strategy: + fail-fast: false + matrix: + mode: + - plugin + - standalone + steps: + - + name: Checkout + uses: actions/checkout@v3 + - + name: Set up Docker Buildx + uses: docker/setup-buildx-action@v2 + - + name: Set up Go uses: actions/setup-go@v3 with: go-version: ${{ env.GO_VERSION }} cache: true - - - name: Validate go-mod, license headers and docs are up-to-date - run: make validate - - - name: Run golangci-lint - env: - BUILD_TAGS: e2e - uses: golangci/golangci-lint-action@v3 - with: - version: v1.47.3 - args: --timeout=180s - - # only on main branch, costs too much for the gain on every PR - validate-cross-build: - name: Validate cross build - runs-on: ubuntu-latest - if: github.ref == 'refs/heads/main' - steps: - - name: Checkout code into the Go module directory - uses: actions/checkout@v3 - - - name: Set up Go ${{ env.GO_VERSION }} - uses: actions/setup-go@v3 - with: - go-version: ${{ env.GO_VERSION }} - cache: true - - # Ensure we don't discover cross platform build issues at release time. - # Time used to build linux here is gained back in the build for local E2E step - - name: Build packages - run: make -f builder.Makefile cross - - build-plugin: - name: Build and tests in plugin mode - runs-on: ubuntu-latest - steps: - - name: Checkout code into the Go module directory - uses: actions/checkout@v3 - - - name: Set up Go ${{ env.GO_VERSION }} - uses: actions/setup-go@v3 - with: - go-version: ${{ env.GO_VERSION }} - cache: true - - - name: Setup docker CLI + - + name: Setup docker CLI run: | curl https://download.docker.com/linux/static/stable/x86_64/docker-${DOCKER_CLI_VERSION}.tgz | tar xz sudo cp ./docker/docker /usr/bin/ && rm -rf docker && docker version - - - name: Test - run: make -f builder.Makefile test - - - name: Build for local E2E - env: - BUILD_TAGS: e2e - run: make GIT_TAG=e2e-PR-${{ github.event.pull_request.number }}-${{ github.event.pull_request.head.sha }} -f builder.Makefile compose-plugin - - - name: E2E Test in plugin mode - run: make e2e-compose - - build-standalone: - name: Build and tests in standalone mode - runs-on: ubuntu-latest - steps: - - name: Checkout code into the Go module directory - uses: actions/checkout@v3 - - - name: Set up Go ${{ env.GO_VERSION }} - uses: actions/setup-go@v3 + - + name: Build + uses: docker/bake-action@v2 with: - go-version: ${{ env.GO_VERSION }} - cache: true - - - name: Setup docker CLI - run: | - curl https://download.docker.com/linux/static/stable/x86_64/docker-${DOCKER_CLI_VERSION}.tgz | tar xz - sudo cp ./docker/docker /usr/bin/ && rm -rf docker && docker version - - - name: Build for local E2E + targets: binary + set: | + *.cache-from=type=gha,scope=binary-linux-amd64 + *.cache-from=type=gha,scope=binary-e2e-${{ matrix.mode }} + *.cache-to=type=gha,scope=binary-e2e-${{ matrix.mode }},mode=max env: BUILD_TAGS: e2e - run: make GIT_TAG=e2e-PR-${{ github.event.pull_request.number }}-${{ github.event.pull_request.head.sha }} -f builder.Makefile compose-plugin - - - name: Setup tmate session - uses: mxschmitt/action-tmate@v3 + - + name: Setup tmate session + if: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.debug_enabled }} + uses: mxschmitt/action-tmate@8b4e4ac71822ed7e0ad5fb3d1c33483e9e8fb270 # v3.11 with: limit-access-to-actor: true github-token: ${{ secrets.GITHUB_TOKEN }} - if: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.debug_enabled }} - - - name: E2E Test in standalone mode + - + name: Test plugin mode + if: ${{ matrix.mode == 'plugin' }} + run: | + make e2e-compose + - + name: Test standalone mode + if: ${{ matrix.mode == 'standalone' }} run: | rm -f /usr/local/bin/docker-compose - cp bin/docker-compose /usr/local/bin + cp bin/build/docker-compose /usr/local/bin make e2e-compose-standalone + + release: + runs-on: ubuntu-latest + needs: + - binary + steps: + - + name: Checkout + uses: actions/checkout@v3 + - + name: Download artifacts + uses: actions/download-artifact@v3 + with: + name: compose + path: ${{ env.DESTDIR }} + - + name: License + run: cp packaging/* ${{ env.DESTDIR }}/ + - + name: List artifacts + run: | + tree -nh ${{ env.DESTDIR }} + - + name: Check artifacts + run: | + find ${{ env.DESTDIR }} -type f -exec file -e ascii -- {} + + - + name: GitHub Release + if: startsWith(github.ref, 'refs/tags/v') + uses: ncipollo/release-action@58ae73b360456532aafd58ee170c045abbeaee37 # v1.10.0 + with: + artifacts: ${{ env.DESTDIR }}/* + generateReleaseNotes: true + draft: true + token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml deleted file mode 100644 index 002c105be..000000000 --- a/.github/workflows/release.yaml +++ /dev/null @@ -1,45 +0,0 @@ -name: Releaser - -on: - workflow_dispatch: - inputs: - tag: - description: "Release Tag" - required: true -env: - GO_VERSION: 1.18.5 -jobs: - upload-release: - runs-on: ubuntu-latest - steps: - - name: Checkout code into the Go module directory - uses: actions/checkout@v3 - - - name: Set up Go ${{ env.GO_VERSION }} - uses: actions/setup-go@v3 - with: - go-version: ${{ env.GO_VERSION }} - cache: true - - - name: Setup docker CLI - run: | - curl https://download.docker.com/linux/static/stable/x86_64/docker-20.10.17.tgz | tar xz - sudo cp ./docker/docker /usr/bin/ && rm -rf docker && docker version - - - name: Build - run: make GIT_TAG=${{ github.event.inputs.tag }} -f builder.Makefile cross - - - name: Compute checksums - run: cd bin; for f in *; do shasum --binary --algorithm 256 $f | tee -a checksums.txt > $f.sha256; done - - - name: License - run: cp packaging/* bin/ - - - uses: ncipollo/release-action@v1 - with: - artifacts: "bin/*" - generateReleaseNotes: true - draft: true - commit: "v2" - token: ${{ secrets.GITHUB_TOKEN }} - tag: ${{ github.event.inputs.tag }} diff --git a/.gitignore b/.gitignore index 480478873..c04e81c4d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,2 @@ bin/ -dist/ /.vscode/ diff --git a/.golangci.yml b/.golangci.yml index ea8f78c8a..40dda7281 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,5 +1,6 @@ run: concurrency: 2 + timeout: 10m linters: enable-all: false disable-all: true diff --git a/BUILDING.md b/BUILDING.md index c51a1a3eb..9e8458306 100644 --- a/BUILDING.md +++ b/BUILDING.md @@ -19,7 +19,8 @@ Once you have the prerequisites installed, you can build the CLI using: make ``` -This will output a `docker-compose` CLI plugin for your host machine in `./bin`. +This will output a `docker-compose` CLI plugin for your host machine in +`./bin/build`. You can statically cross compile the CLI for Windows, macOS, and Linux using the `cross` target. @@ -38,7 +39,6 @@ If you need to update a golden file simply do `go test ./... -test.update-golden To run e2e tests, the Compose CLI binary need to be build. All the commands to run e2e tests propose a version with the prefix `build-and-e2e` to first build the CLI before executing tests. - Note that this requires a local Docker Engine to be running. #### Whole end-to-end tests suite @@ -76,6 +76,7 @@ make e2e-compose-standalone ``` Or if you need to build the CLI, run: + ```console make build-and-e2e-compose-standalone ``` diff --git a/Dockerfile b/Dockerfile index adfe3f965..856b6a0a6 100644 --- a/Dockerfile +++ b/Dockerfile @@ -15,98 +15,173 @@ # See the License for the specific language governing permissions and # limitations under the License. -ARG GO_VERSION=1.18.5-alpine -ARG GOLANGCI_LINT_VERSION=v1.47.3-alpine -ARG PROTOC_GEN_GO_VERSION=v1.4.3 +ARG GO_VERSION=1.18.5 +ARG XX_VERSION=1.1.2 +ARG GOLANGCI_LINT_VERSION=v1.47.3 +ARG ADDLICENSE_VERSION=v1.0.0 -FROM --platform=${BUILDPLATFORM} golangci/golangci-lint:${GOLANGCI_LINT_VERSION} AS local-golangci-lint +ARG BUILD_TAGS="e2e,kube" +ARG DOCS_FORMATS="md,yaml" +ARG LICENSE_FILES=".*\(Dockerfile\|Makefile\|\.go\|\.hcl\|\.sh\)" -FROM --platform=${BUILDPLATFORM} golang:${GO_VERSION} AS base -WORKDIR /compose-cli -RUN apk add --no-cache -vv \ - git \ - docker \ - make \ - protoc \ - protobuf-dev +# xx is a helper for cross-compilation +FROM --platform=${BUILDPLATFORM} tonistiigi/xx:${XX_VERSION} AS xx + +FROM golangci/golangci-lint:${GOLANGCI_LINT_VERSION}-alpine AS golangci-lint +FROM ghcr.io/google/addlicense:${ADDLICENSE_VERSION} AS addlicense + +FROM --platform=${BUILDPLATFORM} golang:${GO_VERSION}-alpine AS base +COPY --from=xx / / +RUN apk add --no-cache \ + docker \ + file \ + git \ + protoc \ + protobuf-dev +WORKDIR /src +ENV CGO_ENABLED=0 + +FROM base AS build-base COPY go.* . RUN --mount=type=cache,target=/go/pkg/mod \ --mount=type=cache,target=/root/.cache/go-build \ go mod download -FROM base AS lint -ENV CGO_ENABLED=0 -COPY --from=local-golangci-lint /usr/bin/golangci-lint /usr/bin/golangci-lint -ARG BUILD_TAGS -ARG GIT_TAG -RUN --mount=target=. \ +FROM build-base AS vendored +RUN --mount=type=bind,target=.,rw \ --mount=type=cache,target=/go/pkg/mod \ - --mount=type=cache,target=/root/.cache/go-build \ - --mount=type=cache,target=/root/.cache/golangci-lint \ - BUILD_TAGS=${BUILD_TAGS} \ - GIT_TAG=${GIT_TAG} \ - make -f builder.Makefile lint + go mod tidy && mkdir /out && cp go.mod go.sum /out -FROM base AS make-compose-plugin -ENV CGO_ENABLED=0 +FROM scratch AS vendor-update +COPY --from=vendored /out / + +FROM vendored AS vendor-validate +RUN --mount=type=bind,target=.,rw <&2 'ERROR: Vendor result differs. Please vendor your package with "make go-mod-tidy"' + echo "$diff" + exit 1 + fi +EOT + +FROM base AS version +RUN --mount=target=. \ + PKG=github.com/docker/compose/v2 VERSION=$(git describe --match 'v[0-9]*' --dirty='.m' --always --tags); \ + echo "-X ${PKG}/internal.Version=${VERSION}" | tee /tmp/.ldflags; \ + echo -n "${VERSION}" | tee /tmp/.version; + +FROM build-base AS build +ARG BUILD_TAGS +ARG TARGETPLATFORM +RUN --mount=type=bind,target=. \ + --mount=type=cache,target=/root/.cache \ + --mount=type=cache,target=/go/pkg/mod \ + --mount=type=bind,source=/tmp/.ldflags,target=/tmp/.ldflags,from=version \ + set -x; xx-go build -trimpath -tags "$BUILD_TAGS" -ldflags "$(cat /tmp/.ldflags) -w -s" -o /usr/bin/docker-compose ./cmd && \ + xx-verify --static /usr/bin/docker-compose + +FROM build-base AS lint +ARG BUILD_TAGS +RUN --mount=type=bind,target=. \ + --mount=type=cache,target=/root/.cache \ + --mount=from=golangci-lint,source=/usr/bin/golangci-lint,target=/usr/bin/golangci-lint \ + golangci-lint run --build-tags "$BUILD_TAGS" ./... + +FROM build-base AS test +ARG CGO_ENABLED=0 +ARG BUILD_TAGS +RUN --mount=type=bind,target=. \ + --mount=type=cache,target=/root/.cache \ + --mount=type=cache,target=/go/pkg/mod \ + go test -tags "$BUILD_TAGS" -v -coverprofile=/tmp/coverage.txt -covermode=atomic $(go list $(TAGS) ./... | grep -vE 'e2e') && \ + go tool cover -func=/tmp/coverage.txt + +FROM scratch AS test-coverage +COPY --from=test /tmp/coverage.txt /coverage.txt + +FROM base AS license-set +ARG LICENSE_FILES +RUN --mount=type=bind,target=.,rw \ + --mount=from=addlicense,source=/app/addlicense,target=/usr/bin/addlicense \ + find . -regex "${LICENSE_FILES}" | xargs addlicense -c 'Docker Compose CLI' -l apache && \ + mkdir /out && \ + find . -regex "${LICENSE_FILES}" | cpio -pdm /out + +FROM scratch AS license-update +COPY --from=set /out / + +FROM base AS license-validate +ARG LICENSE_FILES +RUN --mount=type=bind,target=. \ + --mount=from=addlicense,source=/app/addlicense,target=/usr/bin/addlicense \ + find . -regex "${LICENSE_FILES}" | xargs addlicense -check -c 'Docker Compose CLI' -l apache -ignore validate -ignore testdata -ignore resolvepath -v + +FROM base AS docsgen +WORKDIR /src +RUN --mount=target=. \ + --mount=target=/root/.cache,type=cache \ + go build -o /out/docsgen ./docs/yaml/main/generate.go + +FROM --platform=${BUILDPLATFORM} alpine AS docs-build +RUN apk add --no-cache rsync git +WORKDIR /src +COPY --from=docsgen /out/docsgen /usr/bin +ARG DOCS_FORMATS +RUN --mount=target=/context \ + --mount=target=.,type=tmpfs <&2 'ERROR: Docs result differs. Please update with "make docs"' + git status --porcelain -- docs/reference + exit 1 + fi +EOT + +FROM scratch AS binary-unix +COPY --link --from=build /usr/bin/docker-compose / +FROM binary-unix AS binary-darwin +FROM binary-unix AS binary-linux +FROM scratch AS binary-windows +COPY --link --from=build /usr/bin/docker-compose /docker-compose.exe +FROM binary-$TARGETOS AS binary + +FROM --platform=$BUILDPLATFORM alpine AS releaser +RUN apk add --no-cache file perl-utils +WORKDIR /work ARG TARGETOS ARG TARGETARCH -ARG BUILD_TAGS -ARG GIT_TAG -RUN --mount=target=. \ - --mount=type=cache,target=/go/pkg/mod \ - --mount=type=cache,target=/root/.cache/go-build \ - GOOS=${TARGETOS} \ - GOARCH=${TARGETARCH} \ - BUILD_TAGS=${BUILD_TAGS} \ - GIT_TAG=${GIT_TAG} \ - make COMPOSE_BINARY=/out/docker-compose -f builder.Makefile compose-plugin +ARG TARGETVARIANT +RUN --mount=from=binary \ + mkdir -p /out && \ + # TODO: should just use standard arch + TARGETARCH=$([ "$TARGETARCH" = "amd64" ] && echo "x86_64" || echo "$TARGETARCH"); \ + TARGETARCH=$([ "$TARGETARCH" = "arm64" ] && echo "aarch64" || echo "$TARGETARCH"); \ + cp docker-compose* "/out/docker-compose-${TARGETOS}-${TARGETARCH}${TARGETVARIANT}$(ls docker-compose* | sed -e 's/^docker-compose//')" && \ + (cd /out ; for f in *; do shasum --binary --algorithm 256 $f | tee -a /out/checksums.txt > $f.sha256; done) -FROM base AS make-cross -ARG BUILD_TAGS -ARG GIT_TAG -RUN --mount=target=. \ - --mount=type=cache,target=/go/pkg/mod \ - --mount=type=cache,target=/root/.cache/go-build \ - BUILD_TAGS=${BUILD_TAGS} \ - GIT_TAG=${GIT_TAG} \ - make COMPOSE_BINARY=/out/docker-compose -f builder.Makefile cross - -FROM scratch AS compose-plugin -COPY --from=make-compose-plugin /out/* . - -FROM scratch AS cross -COPY --from=make-cross /out/* . - -FROM base AS test -ENV CGO_ENABLED=0 -ARG BUILD_TAGS -ARG GIT_TAG -RUN --mount=target=. \ - --mount=type=cache,target=/go/pkg/mod \ - --mount=type=cache,target=/root/.cache/go-build \ - BUILD_TAGS=${BUILD_TAGS} \ - GIT_TAG=${GIT_TAG} \ - make -f builder.Makefile test - -FROM base AS check-license-headers -RUN go install github.com/google/addlicense@latest -RUN --mount=target=. \ - make -f builder.Makefile check-license-headers - -FROM base AS make-go-mod-tidy -COPY . . -RUN --mount=type=cache,target=/go/pkg/mod \ - --mount=type=cache,target=/root/.cache/go-build \ - go mod tidy - -FROM scratch AS go-mod-tidy -COPY --from=make-go-mod-tidy /compose-cli/go.mod . -COPY --from=make-go-mod-tidy /compose-cli/go.sum . - -FROM base AS check-go-mod -COPY . . -RUN make -f builder.Makefile check-go-mod +FROM scratch AS release +COPY --from=releaser /out/ / # docs-reference is a target used as remote context to update docs on release # with latest changes on docker.github.io. diff --git a/Makefile b/Makefile index 2556adbfb..b72a7f5c1 100644 --- a/Makefile +++ b/Makefile @@ -12,7 +12,15 @@ # See the License for the specific language governing permissions and # limitations under the License. -export DOCKER_BUILDKIT=1 +ifneq (, $(BUILDX_BIN)) + export BUILDX_CMD = $(BUILDX_BIN) +else ifneq (, $(shell docker buildx version)) + export BUILDX_CMD = docker buildx +else ifneq (, $(shell which buildx)) + export BUILDX_CMD = $(which buildx) +else + $(error "Buildx is required: https://github.com/docker/buildx#installing") +endif UNAME_S := $(shell uname -s) ifeq ($(UNAME_S),Linux) @@ -35,11 +43,12 @@ all: compose-plugin .PHONY: compose-plugin compose-plugin: ## Compile the compose cli-plugin - @docker build . --target compose-plugin \ - --platform local \ - --build-arg BUILD_TAGS=e2e,kube \ - --build-arg GIT_TAG=$(GIT_TAG) \ - --output ./bin + $(BUILDX_CMD) bake binary + +.PHONY: install +install: compose-plugin + mkdir -p ~/.docker/cli-plugins + install bin/build/docker-compose ~/.docker/cli-plugins/docker-compose .PHONY: e2e-compose e2e-compose: ## Run end to end local tests in plugin mode. Set E2E_TEST=TestName to run a single test @@ -71,45 +80,31 @@ build-and-e2e: compose-plugin e2e-compose e2e-compose-standalone ## Compile the .PHONY: cross cross: ## Compile the CLI for linux, darwin and windows - @docker build . --target cross \ - --build-arg BUILD_TAGS \ - --build-arg GIT_TAG=$(GIT_TAG) \ - --output ./bin \ + $(BUILDX_CMD) bake binary .PHONY: test test: ## Run unit tests - @docker build --progress=plain . \ - --build-arg BUILD_TAGS=kube \ - --build-arg GIT_TAG=$(GIT_TAG) \ - --target test + $(BUILDX_CMD) bake test .PHONY: cache-clear cache-clear: ## Clear the builder cache - @docker builder prune --force --filter type=exec.cachemount --filter=unused-for=24h + $(BUILDX_CMD) prune --force --filter type=exec.cachemount --filter=unused-for=24h .PHONY: lint lint: ## run linter(s) - @docker build . \ - --build-arg BUILD_TAGS=kube,e2e \ - --build-arg GIT_TAG=$(GIT_TAG) \ - --target lint + $(BUILDX_CMD) bake lint .PHONY: docs docs: ## generate documentation - $(eval $@_TMP_OUT := $(shell mktemp -d -t dockercli-output.XXXXXXXXXX)) - docker build . \ - --output type=local,dest=$($@_TMP_OUT) \ - -f ./docs/Dockerfile \ - --target update + $(eval $@_TMP_OUT := $(shell mktemp -d -t compose-output.XXXXXXXXXX)) + $(BUILDX_CMD) bake --set "*.output=type=local,dest=$($@_TMP_OUT)" docs-update rm -rf ./docs/internal cp -R "$($@_TMP_OUT)"/out/* ./docs/ rm -rf "$($@_TMP_OUT)"/* .PHONY: validate-docs validate-docs: ## validate the doc does not change - @docker build . \ - -f ./docs/Dockerfile \ - --target validate + $(BUILDX_CMD) bake docs-validate .PHONY: check-dependencies check-dependencies: ## check dependency updates @@ -117,15 +112,15 @@ check-dependencies: ## check dependency updates .PHONY: validate-headers validate-headers: ## Check license header for all files - @docker build . --target check-license-headers + $(BUILDX_CMD) bake license-validate .PHONY: go-mod-tidy go-mod-tidy: ## Run go mod tidy in a container and output resulting go.mod and go.sum - @docker build . --target go-mod-tidy --output . + $(BUILDX_CMD) bake vendor-update .PHONY: validate-go-mod validate-go-mod: ## Validate go.mod and go.sum are up-to-date - @docker build . --target check-go-mod + $(BUILDX_CMD) bake vendor-validate validate: validate-go-mod validate-headers validate-docs ## Validate sources diff --git a/builder.Makefile b/builder.Makefile deleted file mode 100644 index 0f525adb3..000000000 --- a/builder.Makefile +++ /dev/null @@ -1,73 +0,0 @@ -# Copyright 2020 Docker Compose CLI authors - -# 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. - -GOOS?=$(shell go env GOOS) -GOARCH?=$(shell go env GOARCH) - -PKG_NAME := github.com/docker/compose/v2 - -EXTENSION:= -ifeq ($(GOOS),windows) - EXTENSION:=.exe -endif - -STATIC_FLAGS=CGO_ENABLED=0 - -GIT_TAG?=$(shell git describe --tags --match "v[0-9]*") - -LDFLAGS="-s -w -X $(PKG_NAME)/internal.Version=${GIT_TAG}" -GO_BUILD=$(STATIC_FLAGS) go build -trimpath -ldflags=$(LDFLAGS) - -COMPOSE_BINARY?=bin/docker-compose -COMPOSE_BINARY_WITH_EXTENSION=$(COMPOSE_BINARY)$(EXTENSION) - -WORK_DIR:=$(shell mktemp -d) - -TAGS:= -ifdef BUILD_TAGS - TAGS=-tags $(BUILD_TAGS) - LINT_TAGS=--build-tags $(BUILD_TAGS) -endif - -.PHONY: compose-plugin -compose-plugin: - GOOS=${GOOS} GOARCH=${GOARCH} $(GO_BUILD) $(TAGS) -o $(COMPOSE_BINARY_WITH_EXTENSION) ./cmd - -.PHONY: cross -cross: - GOOS=linux GOARCH=amd64 $(GO_BUILD) $(TAGS) -o $(COMPOSE_BINARY)-linux-x86_64 ./cmd - GOOS=linux GOARCH=ppc64le $(GO_BUILD) $(TAGS) -o $(COMPOSE_BINARY)-linux-ppc64le ./cmd - GOOS=linux GOARCH=arm64 $(GO_BUILD) $(TAGS) -o $(COMPOSE_BINARY)-linux-aarch64 ./cmd - GOOS=linux GOARM=6 GOARCH=arm $(GO_BUILD) $(TAGS) -o $(COMPOSE_BINARY)-linux-armv6 ./cmd - GOOS=linux GOARM=7 GOARCH=arm $(GO_BUILD) $(TAGS) -o $(COMPOSE_BINARY)-linux-armv7 ./cmd - GOOS=linux GOARCH=s390x $(GO_BUILD) $(TAGS) -o $(COMPOSE_BINARY)-linux-s390x ./cmd - GOOS=darwin GOARCH=amd64 $(GO_BUILD) $(TAGS) -o $(COMPOSE_BINARY)-darwin-x86_64 ./cmd - GOOS=darwin GOARCH=arm64 $(GO_BUILD) $(TAGS) -o $(COMPOSE_BINARY)-darwin-aarch64 ./cmd - GOOS=windows GOARCH=amd64 $(GO_BUILD) $(TAGS) -o $(COMPOSE_BINARY)-windows-x86_64.exe ./cmd - -.PHONY: test -test: - go test $(TAGS) -cover $(shell go list $(TAGS) ./... | grep -vE 'e2e') - -.PHONY: lint -lint: - golangci-lint run $(LINT_TAGS) --timeout 10m0s ./... - -.PHONY: check-license-headers -check-license-headers: - ./scripts/validate/fileheader - -.PHONY: check-go-mod -check-go-mod: - ./scripts/validate/check-go-mod diff --git a/docker-bake.hcl b/docker-bake.hcl new file mode 100644 index 000000000..80d6b0546 --- /dev/null +++ b/docker-bake.hcl @@ -0,0 +1,124 @@ +// Copyright 2022 Docker Compose CLI authors +// +// 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. + +variable "GO_VERSION" { + default = "1.18.5" +} + +variable "BUILD_TAGS" { + default = "e2e,kube" +} + +variable "DOCS_FORMATS" { + default = "md,yaml" +} + +# Defines the output folder +variable "DESTDIR" { + default = "" +} +function "bindir" { + params = [defaultdir] + result = DESTDIR != "" ? DESTDIR : "./bin/${defaultdir}" +} + +target "_common" { + args = { + GO_VERSION = GO_VERSION + BUILD_TAGS = BUILD_TAGS + BUILDKIT_CONTEXT_KEEP_GIT_DIR = 1 + } +} + +group "default" { + targets = ["binary"] +} + +group "validate" { + targets = ["lint", "vendor-validate", "license-validate"] +} + +target "lint" { + inherits = ["_common"] + target = "lint" + output = ["type=cacheonly"] +} + +target "license-validate" { + target = "license-validate" + output = ["type=cacheonly"] +} + +target "license-update" { + target = "license-update" + output = ["."] +} + +target "vendor-validate" { + inherits = ["_common"] + target = "vendor-validate" + output = ["type=cacheonly"] +} + +target "vendor" { + inherits = ["_common"] + target = "vendor-update" + output = ["."] +} + +target "test" { + inherits = ["_common"] + target = "test-coverage" + output = [bindir("coverage")] +} + +target "binary" { + inherits = ["_common"] + target = "binary" + output = [bindir("build")] + platforms = ["local"] +} + +target "binary-cross" { + inherits = ["binary"] + platforms = [ + "darwin/amd64", + "darwin/arm64", + "linux/amd64", + "linux/arm/v6", + "linux/arm/v7", + "linux/arm64", + "linux/ppc64le", + "linux/s390x", + "windows/amd64" + ] +} + +target "release" { + inherits = ["binary-cross"] + target = "release" + output = [bindir("release")] +} + +target "docs-validate" { + inherits = ["_common"] + target = "docs-validate" + output = ["type=cacheonly"] +} + +target "docs-update" { + inherits = ["_common"] + target = "docs-update" + output = ["./docs"] +} diff --git a/docs/Dockerfile b/docs/Dockerfile deleted file mode 100644 index b23217608..000000000 --- a/docs/Dockerfile +++ /dev/null @@ -1,57 +0,0 @@ -# syntax=docker/dockerfile:1 - - -# Copyright 2020 Docker Compose CLI authors - -# 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 GO_VERSION=1.18.5 -ARG FORMATS=md,yaml - -FROM --platform=${BUILDPLATFORM} golang:${GO_VERSION}-alpine AS docsgen -WORKDIR /src -RUN --mount=target=. \ - --mount=target=/root/.cache,type=cache \ - go build -o /out/docsgen ./docs/yaml/main/generate.go - -FROM --platform=${BUILDPLATFORM} alpine AS gen -RUN apk add --no-cache rsync git -WORKDIR /src -COPY --from=docsgen /out/docsgen /usr/bin -ARG FORMATS -RUN --mount=target=/context \ - --mount=target=.,type=tmpfs <&2 'ERROR: Docs result differs. Please update with "make docs"' - git status --porcelain -- docs/reference - exit 1 -fi -EOT diff --git a/pkg/e2e/framework.go b/pkg/e2e/framework.go index 6b1534c24..2fa263505 100644 --- a/pkg/e2e/framework.go +++ b/pkg/e2e/framework.go @@ -129,7 +129,7 @@ func initializePlugins(t testing.TB, configDir string) { require.NoError(t, os.MkdirAll(filepath.Join(configDir, "cli-plugins"), 0o755), "Failed to create cli-plugins directory") - composePlugin, err := findExecutable(DockerComposeExecutableName, []string{"../../bin", "../../../bin"}) + composePlugin, err := findExecutable(DockerComposeExecutableName, []string{"../../bin/build", "../../../bin/build"}) if os.IsNotExist(err) { t.Logf("WARNING: docker-compose cli-plugin not found") } @@ -302,7 +302,7 @@ func ComposeStandalonePath(t testing.TB) string { if !composeStandaloneMode { require.Fail(t, "Not running in standalone mode") } - composeBinary, err := findExecutable(DockerComposeExecutableName, []string{"../../bin", "../../../bin"}) + composeBinary, err := findExecutable(DockerComposeExecutableName, []string{"../../bin/build", "../../../bin/build"}) require.NoError(t, err, "Could not find standalone Compose binary (%q)", DockerComposeExecutableName) return composeBinary diff --git a/scripts/validate/check-go-mod b/scripts/validate/check-go-mod deleted file mode 100755 index ad45b563b..000000000 --- a/scripts/validate/check-go-mod +++ /dev/null @@ -1,32 +0,0 @@ -#!/bin/sh - -# Copyright Docker Compose CLI authors - -# 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. - - -set -uo pipefail -mkdir -p /tmp/gomod -cp go.* /tmp/gomod/ -go mod tidy -DIFF=$(diff go.mod /tmp/gomod/go.mod && diff go.sum /tmp/gomod/go.sum) -if [ "$DIFF" ]; then - echo - echo "go.mod and go.sum are not up to date" - echo - echo "$DIFF" - echo - exit 1 -else - echo "go.mod is correct" -fi; diff --git a/scripts/validate/fileheader b/scripts/validate/fileheader deleted file mode 100755 index abb30b03f..000000000 --- a/scripts/validate/fileheader +++ /dev/null @@ -1,27 +0,0 @@ -#!/usr/bin/env sh - -# Copyright 2020,2022 Docker Compose CLI authors - -# 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. - -set -eu -o pipefail - -if ! command -v addlicense; then - >&2 echo "ERROR: addlicense not found. Install with:" - >&2 echo " go install -u github.com/google/addlicense@latest" - exit 1 -fi - -BASEPATH="${1-}" - -find . -regex '.*\.sh' -o -regex '.*\.go' -o -regex '.*Makefile' -o -regex '.*Dockerfile' | xargs addlicense -check -l apache -c 'Docker Compose CLI authors' -ignore validate -ignore testdata -ignore resolvepath -v 1>&2 \ No newline at end of file diff --git a/scripts/validate/template/bash.txt b/scripts/validate/template/bash.txt deleted file mode 100644 index 31e00001c..000000000 --- a/scripts/validate/template/bash.txt +++ /dev/null @@ -1,13 +0,0 @@ -# Copyright 2020 Docker Compose CLI authors - -# 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. diff --git a/scripts/validate/template/dockerfile.txt b/scripts/validate/template/dockerfile.txt deleted file mode 100644 index 31e00001c..000000000 --- a/scripts/validate/template/dockerfile.txt +++ /dev/null @@ -1,13 +0,0 @@ -# Copyright 2020 Docker Compose CLI authors - -# 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. diff --git a/scripts/validate/template/go.txt b/scripts/validate/template/go.txt deleted file mode 100644 index a3ee08615..000000000 --- a/scripts/validate/template/go.txt +++ /dev/null @@ -1,16 +0,0 @@ -/* - Copyright 2020 Docker Compose CLI authors - - 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. -*/ - diff --git a/scripts/validate/template/makefile.txt b/scripts/validate/template/makefile.txt deleted file mode 100644 index 31e00001c..000000000 --- a/scripts/validate/template/makefile.txt +++ /dev/null @@ -1,13 +0,0 @@ -# Copyright 2020 Docker Compose CLI authors - -# 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.