Better sandboxed workflow and enhanced cross compilation

Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
This commit is contained in:
CrazyMax 2022-08-12 15:05:52 +02:00
parent e8389306ae
commit 5ec20296e4
No known key found for this signature in database
GPG Key ID: 3248E46B6BB8C7F7
18 changed files with 494 additions and 497 deletions

View File

@ -1,2 +1 @@
bin/ bin/
dist/

View File

@ -1,9 +1,15 @@
name: Continuous integration name: ci
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
on: on:
push: push:
branches: branches:
- v2 - 'v2'
tags:
- 'v*'
pull_request: pull_request:
workflow_dispatch: workflow_dispatch:
inputs: inputs:
@ -11,115 +17,201 @@ on:
description: 'To run with tmate enter "debug_enabled"' description: 'To run with tmate enter "debug_enabled"'
required: false required: false
default: "false" default: "false"
env: env:
GO_VERSION: 1.18.5 GO_VERSION: "1.18.5" # for non sandboxed e2e tests
DOCKER_CLI_VERSION: 20.10.17 DESTDIR: "./bin"
DOCKER_CLI_VERSION: "20.10.17"
jobs: jobs:
lint: prepare:
name: Lint 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 runs-on: ubuntu-latest
steps: steps:
- name: Checkout code into the Go module directory -
name: Checkout
uses: actions/checkout@v3 uses: actions/checkout@v3
-
- name: Set up Go ${{ env.GO_VERSION }} name: Set up Docker Buildx
uses: actions/setup-go@v3 uses: docker/setup-buildx-action@v2
-
name: Test
uses: docker/bake-action@v2
with: with:
go-version: ${{ env.GO_VERSION }} targets: test
cache: true set: |
*.cache-from=type=gha,scope=test
*.cache-to=type=gha,scope=test
- name: Validate go-mod, license headers and docs are up-to-date e2e:
run: make validate runs-on: ubuntu-latest
- name: Run golangci-lint
env: env:
BUILD_TAGS: e2e DESTDIR: "./bin/build"
uses: golangci/golangci-lint-action@v3 strategy:
with: fail-fast: false
version: v1.47.3 matrix:
args: --timeout=180s mode:
- plugin
# only on main branch, costs too much for the gain on every PR - standalone
validate-cross-build:
name: Validate cross build
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
steps: steps:
- name: Checkout code into the Go module directory -
name: Checkout
uses: actions/checkout@v3 uses: actions/checkout@v3
-
- name: Set up Go ${{ env.GO_VERSION }} name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
-
name: Set up Go
uses: actions/setup-go@v3 uses: actions/setup-go@v3
with: with:
go-version: ${{ env.GO_VERSION }} go-version: ${{ env.GO_VERSION }}
cache: true cache: true
-
# Ensure we don't discover cross platform build issues at release time. name: Setup docker CLI
# 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
run: | run: |
curl https://download.docker.com/linux/static/stable/x86_64/docker-${DOCKER_CLI_VERSION}.tgz | tar xz 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 sudo cp ./docker/docker /usr/bin/ && rm -rf docker && docker version
-
- name: Test name: Build
run: make -f builder.Makefile test uses: docker/bake-action@v2
- 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
with: with:
go-version: ${{ env.GO_VERSION }} targets: binary
cache: true set: |
*.cache-from=type=gha,scope=binary-linux-amd64
- name: Setup docker CLI *.cache-from=type=gha,scope=binary-e2e-${{ matrix.mode }}
run: | *.cache-to=type=gha,scope=binary-e2e-${{ matrix.mode }},mode=max
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
env: env:
BUILD_TAGS: e2e 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
- name: Setup tmate session if: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.debug_enabled }}
uses: mxschmitt/action-tmate@v3 uses: mxschmitt/action-tmate@8b4e4ac71822ed7e0ad5fb3d1c33483e9e8fb270 # v3.11
with: with:
limit-access-to-actor: true limit-access-to-actor: true
github-token: ${{ secrets.GITHUB_TOKEN }} github-token: ${{ secrets.GITHUB_TOKEN }}
if: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.debug_enabled }} -
name: Test plugin mode
- name: E2E Test in standalone mode if: ${{ matrix.mode == 'plugin' }}
run: |
make e2e-compose
-
name: Test standalone mode
if: ${{ matrix.mode == 'standalone' }}
run: | run: |
rm -f /usr/local/bin/docker-compose 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 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 }}

View File

@ -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 }}

1
.gitignore vendored
View File

@ -1,3 +1,2 @@
bin/ bin/
dist/
/.vscode/ /.vscode/

View File

@ -1,5 +1,6 @@
run: run:
concurrency: 2 concurrency: 2
timeout: 10m
linters: linters:
enable-all: false enable-all: false
disable-all: true disable-all: true

View File

@ -19,7 +19,8 @@ Once you have the prerequisites installed, you can build the CLI using:
make 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 You can statically cross compile the CLI for Windows, macOS, and Linux using the
`cross` target. `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 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. 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. Note that this requires a local Docker Engine to be running.
#### Whole end-to-end tests suite #### Whole end-to-end tests suite
@ -76,6 +76,7 @@ make e2e-compose-standalone
``` ```
Or if you need to build the CLI, run: Or if you need to build the CLI, run:
```console ```console
make build-and-e2e-compose-standalone make build-and-e2e-compose-standalone
``` ```

View File

@ -15,98 +15,173 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
ARG GO_VERSION=1.18.5-alpine ARG GO_VERSION=1.18.5
ARG GOLANGCI_LINT_VERSION=v1.47.3-alpine ARG XX_VERSION=1.1.2
ARG PROTOC_GEN_GO_VERSION=v1.4.3 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 # xx is a helper for cross-compilation
WORKDIR /compose-cli FROM --platform=${BUILDPLATFORM} tonistiigi/xx:${XX_VERSION} AS xx
RUN apk add --no-cache -vv \
git \ 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 \ docker \
make \ file \
git \
protoc \ protoc \
protobuf-dev protobuf-dev
WORKDIR /src
ENV CGO_ENABLED=0
FROM base AS build-base
COPY go.* . COPY go.* .
RUN --mount=type=cache,target=/go/pkg/mod \ RUN --mount=type=cache,target=/go/pkg/mod \
--mount=type=cache,target=/root/.cache/go-build \ --mount=type=cache,target=/root/.cache/go-build \
go mod download go mod download
FROM base AS lint FROM build-base AS vendored
ENV CGO_ENABLED=0 RUN --mount=type=bind,target=.,rw \
COPY --from=local-golangci-lint /usr/bin/golangci-lint /usr/bin/golangci-lint
ARG BUILD_TAGS
ARG GIT_TAG
RUN --mount=target=. \
--mount=type=cache,target=/go/pkg/mod \ --mount=type=cache,target=/go/pkg/mod \
--mount=type=cache,target=/root/.cache/go-build \ go mod tidy && mkdir /out && cp go.mod go.sum /out
--mount=type=cache,target=/root/.cache/golangci-lint \
BUILD_TAGS=${BUILD_TAGS} \
GIT_TAG=${GIT_TAG} \
make -f builder.Makefile lint
FROM base AS make-compose-plugin FROM scratch AS vendor-update
ENV CGO_ENABLED=0 COPY --from=vendored /out /
FROM vendored AS vendor-validate
RUN --mount=type=bind,target=.,rw <<EOT
set -e
git add -A
cp -rf /out/* .
diff=$(git status --porcelain -- go.mod go.sum)
if [ -n "$diff" ]; then
echo >&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 <<EOT
set -e
rsync -a /context/. .
docsgen --formats "$DOCS_FORMATS" --source "docs/reference"
mkdir /out
cp -r docs/reference /out
EOT
FROM scratch AS docs-update
COPY --from=docs-build /out /out
FROM docs-build AS docs-validate
RUN --mount=target=/context \
--mount=target=.,type=tmpfs <<EOT
set -e
rsync -a /context/. .
git add -A
rm -rf docs/reference/*
cp -rf /out/* ./docs/
if [ -n "$(git status --porcelain -- docs/reference)" ]; then
echo >&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 TARGETOS
ARG TARGETARCH ARG TARGETARCH
ARG BUILD_TAGS ARG TARGETVARIANT
ARG GIT_TAG RUN --mount=from=binary \
RUN --mount=target=. \ mkdir -p /out && \
--mount=type=cache,target=/go/pkg/mod \ # TODO: should just use standard arch
--mount=type=cache,target=/root/.cache/go-build \ TARGETARCH=$([ "$TARGETARCH" = "amd64" ] && echo "x86_64" || echo "$TARGETARCH"); \
GOOS=${TARGETOS} \ TARGETARCH=$([ "$TARGETARCH" = "arm64" ] && echo "aarch64" || echo "$TARGETARCH"); \
GOARCH=${TARGETARCH} \ cp docker-compose* "/out/docker-compose-${TARGETOS}-${TARGETARCH}${TARGETVARIANT}$(ls docker-compose* | sed -e 's/^docker-compose//')" && \
BUILD_TAGS=${BUILD_TAGS} \ (cd /out ; for f in *; do shasum --binary --algorithm 256 $f | tee -a /out/checksums.txt > $f.sha256; done)
GIT_TAG=${GIT_TAG} \
make COMPOSE_BINARY=/out/docker-compose -f builder.Makefile compose-plugin
FROM base AS make-cross FROM scratch AS release
ARG BUILD_TAGS COPY --from=releaser /out/ /
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
# docs-reference is a target used as remote context to update docs on release # docs-reference is a target used as remote context to update docs on release
# with latest changes on docker.github.io. # with latest changes on docker.github.io.

View File

@ -12,7 +12,15 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # 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) UNAME_S := $(shell uname -s)
ifeq ($(UNAME_S),Linux) ifeq ($(UNAME_S),Linux)
@ -35,11 +43,12 @@ all: compose-plugin
.PHONY: compose-plugin .PHONY: compose-plugin
compose-plugin: ## Compile the compose cli-plugin compose-plugin: ## Compile the compose cli-plugin
@docker build . --target compose-plugin \ $(BUILDX_CMD) bake binary
--platform local \
--build-arg BUILD_TAGS=e2e,kube \ .PHONY: install
--build-arg GIT_TAG=$(GIT_TAG) \ install: compose-plugin
--output ./bin mkdir -p ~/.docker/cli-plugins
install bin/build/docker-compose ~/.docker/cli-plugins/docker-compose
.PHONY: e2e-compose .PHONY: e2e-compose
e2e-compose: ## Run end to end local tests in plugin mode. Set E2E_TEST=TestName to run a single test 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 .PHONY: cross
cross: ## Compile the CLI for linux, darwin and windows cross: ## Compile the CLI for linux, darwin and windows
@docker build . --target cross \ $(BUILDX_CMD) bake binary
--build-arg BUILD_TAGS \
--build-arg GIT_TAG=$(GIT_TAG) \
--output ./bin \
.PHONY: test .PHONY: test
test: ## Run unit tests test: ## Run unit tests
@docker build --progress=plain . \ $(BUILDX_CMD) bake test
--build-arg BUILD_TAGS=kube \
--build-arg GIT_TAG=$(GIT_TAG) \
--target test
.PHONY: cache-clear .PHONY: cache-clear
cache-clear: ## Clear the builder cache 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 .PHONY: lint
lint: ## run linter(s) lint: ## run linter(s)
@docker build . \ $(BUILDX_CMD) bake lint
--build-arg BUILD_TAGS=kube,e2e \
--build-arg GIT_TAG=$(GIT_TAG) \
--target lint
.PHONY: docs .PHONY: docs
docs: ## generate documentation docs: ## generate documentation
$(eval $@_TMP_OUT := $(shell mktemp -d -t dockercli-output.XXXXXXXXXX)) $(eval $@_TMP_OUT := $(shell mktemp -d -t compose-output.XXXXXXXXXX))
docker build . \ $(BUILDX_CMD) bake --set "*.output=type=local,dest=$($@_TMP_OUT)" docs-update
--output type=local,dest=$($@_TMP_OUT) \
-f ./docs/Dockerfile \
--target update
rm -rf ./docs/internal rm -rf ./docs/internal
cp -R "$($@_TMP_OUT)"/out/* ./docs/ cp -R "$($@_TMP_OUT)"/out/* ./docs/
rm -rf "$($@_TMP_OUT)"/* rm -rf "$($@_TMP_OUT)"/*
.PHONY: validate-docs .PHONY: validate-docs
validate-docs: ## validate the doc does not change validate-docs: ## validate the doc does not change
@docker build . \ $(BUILDX_CMD) bake docs-validate
-f ./docs/Dockerfile \
--target validate
.PHONY: check-dependencies .PHONY: check-dependencies
check-dependencies: ## check dependency updates check-dependencies: ## check dependency updates
@ -117,15 +112,15 @@ check-dependencies: ## check dependency updates
.PHONY: validate-headers .PHONY: validate-headers
validate-headers: ## Check license header for all files validate-headers: ## Check license header for all files
@docker build . --target check-license-headers $(BUILDX_CMD) bake license-validate
.PHONY: go-mod-tidy .PHONY: go-mod-tidy
go-mod-tidy: ## Run go mod tidy in a container and output resulting go.mod and go.sum 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 .PHONY: validate-go-mod
validate-go-mod: ## Validate go.mod and go.sum are up-to-date 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 validate: validate-go-mod validate-headers validate-docs ## Validate sources

View File

@ -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

124
docker-bake.hcl Normal file
View File

@ -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"]
}

View File

@ -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 <<EOT
set -e
rsync -a /context/. .
docsgen --formats "$FORMATS" --source "docs/reference"
mkdir /out
cp -r docs/reference /out
EOT
FROM scratch AS update
COPY --from=gen /out /out
FROM gen AS validate
RUN --mount=target=/context \
--mount=target=.,type=tmpfs <<EOT
set -e
rsync -a /context/. .
git add -A
rm -rf docs/reference/*
cp -rf /out/* ./docs/
if [ -n "$(git status --porcelain -- docs/reference)" ]; then
echo >&2 'ERROR: Docs result differs. Please update with "make docs"'
git status --porcelain -- docs/reference
exit 1
fi
EOT

View File

@ -129,7 +129,7 @@ func initializePlugins(t testing.TB, configDir string) {
require.NoError(t, os.MkdirAll(filepath.Join(configDir, "cli-plugins"), 0o755), require.NoError(t, os.MkdirAll(filepath.Join(configDir, "cli-plugins"), 0o755),
"Failed to create cli-plugins directory") "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) { if os.IsNotExist(err) {
t.Logf("WARNING: docker-compose cli-plugin not found") t.Logf("WARNING: docker-compose cli-plugin not found")
} }
@ -302,7 +302,7 @@ func ComposeStandalonePath(t testing.TB) string {
if !composeStandaloneMode { if !composeStandaloneMode {
require.Fail(t, "Not running in standalone mode") 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)", require.NoError(t, err, "Could not find standalone Compose binary (%q)",
DockerComposeExecutableName) DockerComposeExecutableName)
return composeBinary return composeBinary

View File

@ -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;

View File

@ -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

View File

@ -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.

View File

@ -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.

View File

@ -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.
*/

View File

@ -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.