Skip to content

Commit d4c117e

Browse files
committed
ci: merge Go coverage reports before upload
Attempting to fix the state of codecov action checks right now, which are behaving very erratically. Using the new functionality in Go 1.20 to merge multiple reports, so now the unit & E2E coverage data reports are stored as artifacts and then downloaded, merged, and finally uploaded to codecov as a new job. Additionally, add a `codecov.yml` config and try to turn down the aggressiveness of it for CI checks. Signed-off-by: Milas Bowman <[email protected]>
1 parent 32cf776 commit d4c117e

6 files changed

Lines changed: 127 additions & 59 deletions

File tree

.github/workflows/ci.yml

Lines changed: 61 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ on:
1919
default: "false"
2020

2121
env:
22-
DESTDIR: "./bin"
2322
DOCKER_CLI_VERSION: "20.10.17"
2423

2524
permissions:
@@ -103,7 +102,7 @@ jobs:
103102
uses: actions/upload-artifact@v3
104103
with:
105104
name: compose
106-
path: ${{ env.DESTDIR }}/*
105+
path: ./bin/release/*
107106
if-no-files-found: error
108107

109108
test:
@@ -124,13 +123,15 @@ jobs:
124123
*.cache-from=type=gha,scope=test
125124
*.cache-to=type=gha,scope=test
126125
-
127-
name: Upload coverage to Codecov
128-
uses: codecov/codecov-action@v3
126+
name: Gather coverage data
127+
uses: actions/upload-artifact@v3
128+
with:
129+
name: coverage-data-unit
130+
path: bin/coverage/unit/
131+
if-no-files-found: error
129132

130133
e2e:
131134
runs-on: ubuntu-latest
132-
env:
133-
DESTDIR: "./bin/build"
134135
strategy:
135136
fail-fast: false
136137
matrix:
@@ -179,11 +180,17 @@ jobs:
179180
name: Test plugin mode
180181
if: ${{ matrix.mode == 'plugin' }}
181182
run: |
182-
rm -rf ./covdatafiles
183-
mkdir ./covdatafiles
184-
make e2e-compose GOCOVERDIR=covdatafiles
185-
go tool covdata textfmt -i=covdatafiles -o=coverage.out
186-
183+
rm -rf ./bin/coverage/e2e
184+
mkdir -p ./bin/coverage/e2e
185+
make e2e-compose GOCOVERDIR=bin/coverage/e2e TEST_FLAGS="-v"
186+
-
187+
name: Gather coverage data
188+
if: ${{ matrix.mode == 'plugin' }}
189+
uses: actions/upload-artifact@v3
190+
with:
191+
name: coverage-data-e2e
192+
path: bin/coverage/e2e/
193+
if-no-files-found: error
187194
-
188195
name: Test standalone mode
189196
if: ${{ matrix.mode == 'standalone' }}
@@ -196,9 +203,44 @@ jobs:
196203
if: ${{ matrix.mode == 'cucumber'}}
197204
run: |
198205
make test-cucumber
199-
-
200-
name: Upload coverage to Codecov
206+
207+
coverage:
208+
runs-on: ubuntu-22.04
209+
needs:
210+
- test
211+
- e2e
212+
steps:
213+
# codecov won't process the report without the source code available
214+
- name: Checkout
215+
uses: actions/checkout@v3
216+
- name: Set up Go
217+
uses: actions/setup-go@v4
218+
with:
219+
go-version-file: 'go.mod'
220+
check-latest: true
221+
- name: Download unit test coverage
222+
uses: actions/download-artifact@v3
223+
with:
224+
name: coverage-data-unit
225+
path: coverage/unit
226+
- name: Download E2E test coverage
227+
uses: actions/download-artifact@v3
228+
with:
229+
name: coverage-data-e2e
230+
path: coverage/e2e
231+
- name: Merge coverage reports
232+
run: |
233+
go tool covdata textfmt -i=./coverage/unit,./coverage/e2e -o ./coverage.txt
234+
- name: Store coverage report in GitHub Actions
235+
uses: actions/upload-artifact@v3
236+
with:
237+
name: go-covdata-txt
238+
path: ./coverage.txt
239+
if-no-files-found: error
240+
- name: Upload coverage to Codecov
201241
uses: codecov/codecov-action@v3
242+
with:
243+
files: ./coverage.txt
202244

203245
release:
204246
permissions:
@@ -216,32 +258,32 @@ jobs:
216258
uses: actions/download-artifact@v3
217259
with:
218260
name: compose
219-
path: ${{ env.DESTDIR }}
261+
path: bin/release
220262
-
221263
name: Create checksums
222-
working-directory: ${{ env.DESTDIR }}
264+
working-directory: bin/release
223265
run: |
224266
find . -type f -print0 | sort -z | xargs -r0 shasum -a 256 -b | sed 's# \*\./# *#' > $RUNNER_TEMP/checksums.txt
225267
shasum -a 256 -U -c $RUNNER_TEMP/checksums.txt
226268
mv $RUNNER_TEMP/checksums.txt .
227269
cat checksums.txt | while read sum file; do echo "$sum $file" > ${file#\*}.sha256; done
228270
-
229271
name: License
230-
run: cp packaging/* ${{ env.DESTDIR }}/
272+
run: cp packaging/* bin/release/
231273
-
232274
name: List artifacts
233275
run: |
234-
tree -nh ${{ env.DESTDIR }}
276+
tree -nh bin/release
235277
-
236278
name: Check artifacts
237279
run: |
238-
find ${{ env.DESTDIR }} -type f -exec file -e ascii -- {} +
280+
find bin/release -type f -exec file -e ascii -- {} +
239281
-
240282
name: GitHub Release
241283
if: startsWith(github.ref, 'refs/tags/v')
242284
uses: ncipollo/release-action@58ae73b360456532aafd58ee170c045abbeaee37 # v1.10.0
243285
with:
244-
artifacts: ${{ env.DESTDIR }}/*
286+
artifacts: bin/release/*
245287
generateReleaseNotes: true
246288
draft: true
247289
token: ${{ secrets.GITHUB_TOKEN }}

Dockerfile

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,8 @@ RUN --mount=type=bind,target=. \
8484
--mount=type=bind,from=osxcross,src=/osxsdk,target=/xx-sdk \
8585
xx-go --wrap && \
8686
if [ "$(xx-info os)" == "darwin" ]; then export CGO_ENABLED=1; fi && \
87-
make build GO_BUILDTAGS="$BUILD_TAGS" DESTDIR=/usr/bin && \
88-
xx-verify --static /usr/bin/docker-compose
87+
make build GO_BUILDTAGS="$BUILD_TAGS" DESTDIR=/out && \
88+
xx-verify --static /out/docker-compose
8989

9090
FROM build-base AS lint
9191
ARG BUILD_TAGS
@@ -100,11 +100,13 @@ ARG BUILD_TAGS
100100
RUN --mount=type=bind,target=. \
101101
--mount=type=cache,target=/root/.cache \
102102
--mount=type=cache,target=/go/pkg/mod \
103-
go test -tags "$BUILD_TAGS" -v -coverprofile=/tmp/coverage.txt -covermode=atomic $(go list $(TAGS) ./... | grep -vE 'e2e') && \
104-
go tool cover -func=/tmp/coverage.txt
103+
rm -rf /tmp/coverage && \
104+
mkdir -p /tmp/coverage && \
105+
go test -tags "$BUILD_TAGS" -v -cover -covermode=atomic $(go list $(TAGS) ./... | grep -vE 'e2e') -args -test.gocoverdir="/tmp/coverage" && \
106+
go tool covdata percent -i=/tmp/coverage
105107

106108
FROM scratch AS test-coverage
107-
COPY --from=test /tmp/coverage.txt /coverage.txt
109+
COPY --from=test --link /tmp/coverage /
108110

109111
FROM base AS license-set
110112
ARG LICENSE_FILES
@@ -162,11 +164,11 @@ RUN --mount=target=/context \
162164
EOT
163165

164166
FROM scratch AS binary-unix
165-
COPY --link --from=build /usr/bin/docker-compose /
167+
COPY --link --from=build /out/docker-compose /
166168
FROM binary-unix AS binary-darwin
167169
FROM binary-unix AS binary-linux
168170
FROM scratch AS binary-windows
169-
COPY --link --from=build /usr/bin/docker-compose /docker-compose.exe
171+
COPY --link --from=build /out/docker-compose /docker-compose.exe
170172
FROM binary-$TARGETOS AS binary
171173
# enable scanning for this stage
172174
ARG BUILDKIT_SBOM_SCAN_STAGE=true

Makefile

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -25,22 +25,10 @@ else
2525
DETECTED_OS = $(shell uname -s)
2626
endif
2727

28-
ifeq ($(DETECTED_OS),Linux)
29-
MOBY_DOCKER=/usr/bin/docker
30-
endif
31-
ifeq ($(DETECTED_OS),Darwin)
32-
MOBY_DOCKER=/Applications/Docker.app/Contents/Resources/bin/docker
33-
endif
3428
ifeq ($(DETECTED_OS),Windows)
3529
BINARY_EXT=.exe
3630
endif
3731

38-
TEST_COVERAGE_FLAGS = -coverprofile=coverage.out -covermode=atomic
39-
ifneq ($(DETECTED_OS),Windows)
40-
# go race detector requires gcc on Windows so not used by default
41-
# https://github.com/golang/go/issues/27089
42-
TEST_COVERAGE_FLAGS += -race
43-
endif
4432
BUILD_FLAGS?=
4533
TEST_FLAGS?=
4634
E2E_TEST?=
@@ -50,13 +38,23 @@ else
5038
endif
5139

5240
BUILDX_CMD ?= docker buildx
53-
DESTDIR ?= ./bin/build
41+
42+
# DESTDIR overrides the output path for binaries and other artifacts
43+
# this is used by docker/docker-ce-packaging for the apt/rpm builds,
44+
# so it's important that the resulting binary ends up EXACTLY at the
45+
# path $DESTDIR/docker-compose when specified.
46+
#
47+
# See https://github.com/docker/docker-ce-packaging/blob/e43fbd37e48fde49d907b9195f23b13537521b94/rpm/SPECS/docker-compose-plugin.spec#L47
48+
#
49+
# By default, all artifacts go to subdirectories under ./bin/ in the
50+
# repo root, e.g. ./bin/build, ./bin/coverage, ./bin/release.
51+
DESTDIR ?=
5452

5553
all: build
5654

5755
.PHONY: build ## Build the compose cli-plugin
5856
build:
59-
GO111MODULE=on go build $(BUILD_FLAGS) -trimpath -tags "$(GO_BUILDTAGS)" -ldflags "$(GO_LDFLAGS)" -o "$(DESTDIR)/docker-compose$(BINARY_EXT)" ./cmd
57+
GO111MODULE=on go build $(BUILD_FLAGS) -trimpath -tags "$(GO_BUILDTAGS)" -ldflags "$(GO_LDFLAGS)" -o "$(or $(DESTDIR),./bin/build)/docker-compose$(BINARY_EXT)" ./cmd
6058

6159
.PHONY: binary
6260
binary:
@@ -69,7 +67,7 @@ binary-with-coverage:
6967
.PHONY: install
7068
install: binary
7169
mkdir -p ~/.docker/cli-plugins
72-
install bin/build/docker-compose ~/.docker/cli-plugins/docker-compose
70+
install $(or $(DESTDIR),./bin/build)/docker-compose ~/.docker/cli-plugins/docker-compose
7371

7472
.PHONY: e2e-compose
7573
e2e-compose: ## Run end to end local tests in plugin mode. Set E2E_TEST=TestName to run a single test

codecov.yml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
coverage:
2+
status:
3+
project:
4+
default:
5+
informational: true
6+
target: auto
7+
threshold: 2%
8+
patch:
9+
default:
10+
informational: true
11+
12+
comment:
13+
require_changes: true
14+
15+
ignore:
16+
- "packaging"
17+
- "docs"
18+
- "bin"
19+
- "e2e"
20+
- "pkg/e2e"
21+
- "**/*_test.go"

docker-bake.hcl

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,16 @@ variable "DOCS_FORMATS" {
2525
default = "md,yaml"
2626
}
2727

28-
# Defines the output folder
28+
# Defines the output folder to override the default behavior.
29+
# See Makefile for details, this is generally only useful for
30+
# the packaging scripts and care should be taken to not break
31+
# them.
2932
variable "DESTDIR" {
3033
default = ""
3134
}
32-
function "bindir" {
35+
function "outdir" {
3336
params = [defaultdir]
34-
result = DESTDIR != "" ? DESTDIR : "./bin/${defaultdir}"
37+
result = DESTDIR != "" ? DESTDIR : "${defaultdir}"
3538
}
3639

3740
# Special target: https://github.com/docker/metadata-action#bake-definition
@@ -84,23 +87,23 @@ target "vendor-update" {
8487
target "test" {
8588
inherits = ["_common"]
8689
target = "test-coverage"
87-
output = [bindir("coverage")]
90+
output = [outdir("./bin/coverage/unit")]
8891
}
8992

9093
target "binary-with-coverage" {
9194
inherits = ["_common"]
9295
target = "binary"
9396
args = {
94-
BUILD_FLAGS = "-cover"
97+
BUILD_FLAGS = "-cover -covermode=atomic"
9598
}
96-
output = [bindir("build")]
99+
output = [outdir("./bin/build")]
97100
platforms = ["local"]
98101
}
99102

100103
target "binary" {
101104
inherits = ["_common"]
102105
target = "binary"
103-
output = [bindir("build")]
106+
output = [outdir("./bin/build")]
104107
platforms = ["local"]
105108
}
106109

@@ -124,7 +127,7 @@ target "binary-cross" {
124127
target "release" {
125128
inherits = ["binary-cross"]
126129
target = "release"
127-
output = [bindir("release")]
130+
output = [outdir("./bin/release")]
128131
}
129132

130133
target "docs-validate" {

pkg/e2e/framework.go

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
"encoding/json"
2121
"fmt"
2222
"io"
23+
"io/fs"
2324
"net/http"
2425
"os"
2526
"path/filepath"
@@ -134,7 +135,7 @@ func initializePlugins(t testing.TB, configDir string) {
134135
require.NoError(t, os.MkdirAll(filepath.Join(configDir, "cli-plugins"), 0o755),
135136
"Failed to create cli-plugins directory")
136137
composePlugin, err := findExecutable(DockerComposeExecutableName)
137-
if os.IsNotExist(err) {
138+
if errors.Is(err, fs.ErrNotExist) {
138139
t.Logf("WARNING: docker-compose cli-plugin not found")
139140
}
140141

@@ -161,20 +162,21 @@ func dirContents(dir string) []string {
161162
}
162163

163164
func findExecutable(executableName string) (string, error) {
164-
_, filename, _, _ := runtime.Caller(0)
165-
root := filepath.Join(filepath.Dir(filename), "..", "..")
166-
buildPath := filepath.Join(root, "bin", "build")
167-
168-
bin, err := filepath.Abs(filepath.Join(buildPath, executableName))
169-
if err != nil {
170-
return "", err
165+
bin := os.Getenv("COMPOSE_E2E_BIN_PATH")
166+
if bin == "" {
167+
_, filename, _, _ := runtime.Caller(0)
168+
buildPath := filepath.Join(filepath.Dir(filename), "..", "..", "bin", "build")
169+
var err error
170+
bin, err = filepath.Abs(filepath.Join(buildPath, executableName))
171+
if err != nil {
172+
return "", err
173+
}
171174
}
172175

173176
if _, err := os.Stat(bin); err == nil {
174177
return bin, nil
175178
}
176-
177-
return "", errors.Wrap(os.ErrNotExist, "executable not found")
179+
return "", fmt.Errorf("looking for %q: %w", bin, fs.ErrNotExist)
178180
}
179181

180182
func findPluginExecutable(pluginExecutableName string) (string, error) {

0 commit comments

Comments
 (0)