From 12229f234860b30ac2e0f94052607263614da39e Mon Sep 17 00:00:00 2001 From: chris erway Date: Wed, 3 Nov 2021 23:19:34 -0400 Subject: [PATCH 01/22] set -coverpkg to all go-algorand packages when calling go test --- .circleci/config.yml | 4 +++- Makefile | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 244f5d7ad0..e0106fd2e5 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -319,11 +319,13 @@ commands: scripts/configure_dev.sh scripts/buildtools/install_buildtools.sh -o "gotest.tools/gotestsum" PACKAGES="$(go list ./... | grep -v /go-algorand/test/)" + COVERPACKAGES="$(go list ./... | egrep -v '/go-algorand/(test|debug|cmd|config/defaultsGenerator|tools)' )" export PACKAGE_NAMES=$(echo $PACKAGES | tr -d '\n') + export COVERPACKAGE_NAMES=$(echo $COVERPACKAGES | tr ' ' ',') export PARTITION_TOTAL=${CIRCLE_NODE_TOTAL} export PARTITION_ID=${CIRCLE_NODE_INDEX} export PARALLEL_FLAG="-p 1" - gotestsum --format testname --junitfile << parameters.result_path >>/<< parameters.result_subdir >>/${CIRCLE_NODE_INDEX}/results.xml --jsonfile << parameters.result_path >>/<< parameters.result_subdir >>/${CIRCLE_NODE_INDEX}/testresults.json -- --tags "sqlite_unlock_notify sqlite_omit_load_extension" << parameters.short_test_flag >> -race -timeout 1h -coverprofile=coverage.txt -covermode=atomic -p 1 $PACKAGE_NAMES + gotestsum --format testname --junitfile << parameters.result_path >>/<< parameters.result_subdir >>/${CIRCLE_NODE_INDEX}/results.xml --jsonfile << parameters.result_path >>/<< parameters.result_subdir >>/${CIRCLE_NODE_INDEX}/testresults.json -- --tags "sqlite_unlock_notify sqlite_omit_load_extension" << parameters.short_test_flag >> -race -timeout 1h -coverprofile=coverage.txt -covermode=atomic -p 1 $PACKAGE_NAMES -coverpkg=$COVERPACKAGE_NAMES - store_artifacts: path: << parameters.result_path >> destination: test-results diff --git a/Makefile b/Makefile index 77a9658874..1783acb01e 100644 --- a/Makefile +++ b/Makefile @@ -74,6 +74,7 @@ GOLDFLAGS := $(GOLDFLAGS_BASE) \ -X github.com/algorand/go-algorand/config.Channel=$(CHANNEL) UNIT_TEST_SOURCES := $(sort $(shell GOPATH=$(GOPATH) && GO111MODULE=off && go list ./... | grep -v /go-algorand/test/ )) +COVERPKG_PACKAGES := $(sort $(shell GOPATH=$(GOPATH) && GO111MODULE=off && go list ./... | egrep -v '/go-algorand/(test|debug|cmd|config/defaultsGenerator|tools)' )) ALGOD_API_PACKAGES := $(sort $(shell GOPATH=$(GOPATH) && GO111MODULE=off && cd daemon/algod/api; go list ./... )) MSGP_GENERATE := ./protocol ./protocol/test ./crypto ./crypto/compactcert ./data/basics ./data/transactions ./data/committee ./data/bookkeeping ./data/hashable ./agreement ./rpcs ./node ./ledger ./ledger/ledgercore ./compactcert ./txnsync ./data/pooldata @@ -101,7 +102,7 @@ check_shell: sanity: vet fix lint fmt cover: - go test $(GOTAGS) -coverprofile=cover.out $(UNIT_TEST_SOURCES) + go test $(GOTAGS) -coverprofile=cover.out $(UNIT_TEST_SOURCES) -covermode=atomic -coverpkg=$(shell echo $(COVERPKG_PACKAGES) | sed 's/ /,/g') prof: cd node && go test $(GOTAGS) -cpuprofile=cpu.out -memprofile=mem.out -mutexprofile=mutex.out From 1c6167df971ef740b5ccfd7961a518cf23d44fed Mon Sep 17 00:00:00 2001 From: chris erway Date: Thu, 4 Nov 2021 18:08:28 -0400 Subject: [PATCH 02/22] Log incorrect metrics for debugging test failures --- util/metrics/counter_test.go | 6 +++--- util/metrics/gauge_test.go | 2 +- util/metrics/segment_test.go | 2 +- util/metrics/stringGauge_test.go | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/util/metrics/counter_test.go b/util/metrics/counter_test.go index 67c7a07856..31f46d410b 100644 --- a/util/metrics/counter_test.go +++ b/util/metrics/counter_test.go @@ -67,7 +67,7 @@ func TestMetricCounter(t *testing.T) { defer test.Unlock() // the the loop above we've created a single metric name with five different labels set ( host0, host1 .. host 4) // let's see if we received all the 5 different labels. - require.Equal(t, 5, len(test.metrics), "Missing metric counts were reported.") + require.Equal(t, 5, len(test.metrics), "Missing metric counts were reported: %+v", test.metrics) for k, v := range test.metrics { // we have increased each one of the labels exactly 4 times. See that the counter was counting correctly. @@ -114,7 +114,7 @@ func TestMetricCounterFastInts(t *testing.T) { defer test.Unlock() // the the loop above we've created a single metric name with five different labels set ( host0, host1 .. host 4) // let's see if we received all the 5 different labels. - require.Equal(t, 1, len(test.metrics), "Missing metric counts were reported.") + require.Equal(t, 1, len(test.metrics), "Missing metric counts were reported: %+v", test.metrics) for k, v := range test.metrics { // we have increased each one of the labels exactly 4 times. See that the counter was counting correctly. @@ -163,7 +163,7 @@ func TestMetricCounterMixed(t *testing.T) { defer test.Unlock() // the the loop above we've created a single metric name with five different labels set ( host0, host1 .. host 4) // let's see if we received all the 5 different labels. - require.Equal(t, 1, len(test.metrics), "Missing metric counts were reported.") + require.Equal(t, 1, len(test.metrics), "Missing metric counts were reported: %+v", test.metrics) for k, v := range test.metrics { // we have increased each one of the labels exactly 4 times. See that the counter was counting correctly. diff --git a/util/metrics/gauge_test.go b/util/metrics/gauge_test.go index 1e1164b018..d8ed29db90 100644 --- a/util/metrics/gauge_test.go +++ b/util/metrics/gauge_test.go @@ -68,7 +68,7 @@ func TestMetricGauge(t *testing.T) { // the the loop above we've created a single metric name with five different labels set ( host0, host1 .. host 4) // let's see if we received all the 5 different labels. - require.Equal(t, 5, len(test.metrics), "Missing metric counts were reported.") + require.Equal(t, 5, len(test.metrics), "Missing metric counts were reported: %+v", test.metrics) // iterate through the metrics and check the each of the metrics reached it's correct count. for k, v := range test.metrics { diff --git a/util/metrics/segment_test.go b/util/metrics/segment_test.go index d3590f5a68..a558e63c49 100644 --- a/util/metrics/segment_test.go +++ b/util/metrics/segment_test.go @@ -87,7 +87,7 @@ func testMetricSegmentHelper(t *testing.T, functionTime time.Duration) bool { // test the metrics values. see if we received all the 4 metrics back correctly. // we expect the get 4 metrics : test_segment_name1_sec, test_segment_name1_sec_total, test_segment_name1_total and test_segment_name1_concurrent // ( we don't know in which order they would appear, but the total count should be 4 ) - require.Equal(t, 4, len(test.metrics), "Missing metric counts were reported.") + require.Equal(t, 4, len(test.metrics), "Missing metric counts were reported: %+v", test.metrics) for k, v := range test.metrics { if strings.Contains(k, "test_segment_name1_sec{") { diff --git a/util/metrics/stringGauge_test.go b/util/metrics/stringGauge_test.go index 1ea3650bc2..cd8c3c4cf9 100644 --- a/util/metrics/stringGauge_test.go +++ b/util/metrics/stringGauge_test.go @@ -40,7 +40,7 @@ func TestMetricStringGauge(t *testing.T) { DefaultRegistry().AddMetrics(results) // values are populated - require.Equal(t, 2, len(results)) + require.Equal(t, 2, len(results), "Wrong number of results: %+v", results) require.True(t, hasKey(results, "number-key")) require.Equal(t, "1", results["number-key"]) require.True(t, hasKey(results, "string-key")) From 22c1ed6f4fe509c4ddc93eae7ccb0421a839cd62 Mon Sep 17 00:00:00 2001 From: chris erway Date: Thu, 4 Nov 2021 21:25:26 -0400 Subject: [PATCH 03/22] print algod_crypto_signature_secrets_generate_total call --- crypto/curve25519.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/crypto/curve25519.go b/crypto/curve25519.go index eede5d337d..021447beb3 100644 --- a/crypto/curve25519.go +++ b/crypto/curve25519.go @@ -35,6 +35,7 @@ import "C" import ( "fmt" + "runtime/debug" "github.com/algorand/go-algorand/logging" "github.com/algorand/go-algorand/util/metrics" @@ -197,6 +198,7 @@ func SecretKeyToSeed(secret PrivateKey) (Seed, error) { func GenerateSignatureSecrets(seed Seed) *SignatureSecrets { pk0, sk := ed25519GenerateKeySeed(ed25519Seed(seed)) pk := SignatureVerifier(pk0) + debug.PrintStack() cryptoGenSigSecretsTotal.Inc(map[string]string{}) return &SignatureSecrets{SignatureVerifier: pk, SK: sk} } From baef4fd37ac535fe650f96a108ea515be50ffb47 Mon Sep 17 00:00:00 2001 From: chris erway Date: Thu, 4 Nov 2021 22:11:56 -0400 Subject: [PATCH 04/22] Revert "print algod_crypto_signature_secrets_generate_total call" This reverts commit 22c1ed6f4fe509c4ddc93eae7ccb0421a839cd62. --- crypto/curve25519.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/crypto/curve25519.go b/crypto/curve25519.go index 021447beb3..eede5d337d 100644 --- a/crypto/curve25519.go +++ b/crypto/curve25519.go @@ -35,7 +35,6 @@ import "C" import ( "fmt" - "runtime/debug" "github.com/algorand/go-algorand/logging" "github.com/algorand/go-algorand/util/metrics" @@ -198,7 +197,6 @@ func SecretKeyToSeed(secret PrivateKey) (Seed, error) { func GenerateSignatureSecrets(seed Seed) *SignatureSecrets { pk0, sk := ed25519GenerateKeySeed(ed25519Seed(seed)) pk := SignatureVerifier(pk0) - debug.PrintStack() cryptoGenSigSecretsTotal.Inc(map[string]string{}) return &SignatureSecrets{SignatureVerifier: pk, SK: sk} } From 20d09535d9caf636de62b8cc4b1f1897e9f96847 Mon Sep 17 00:00:00 2001 From: chris erway Date: Thu, 4 Nov 2021 22:12:50 -0400 Subject: [PATCH 05/22] filter out test/testing packages from coverpkg --- .circleci/config.yml | 2 +- Makefile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index e0106fd2e5..b35accfdbd 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -319,7 +319,7 @@ commands: scripts/configure_dev.sh scripts/buildtools/install_buildtools.sh -o "gotest.tools/gotestsum" PACKAGES="$(go list ./... | grep -v /go-algorand/test/)" - COVERPACKAGES="$(go list ./... | egrep -v '/go-algorand/(test|debug|cmd|config/defaultsGenerator|tools)' )" + COVERPACKAGES="$(go list ./... | egrep -v '/go-algorand/(test|debug|cmd|config/defaultsGenerator|tools)' | egrep -v '(test|testing)$' )" export PACKAGE_NAMES=$(echo $PACKAGES | tr -d '\n') export COVERPACKAGE_NAMES=$(echo $COVERPACKAGES | tr ' ' ',') export PARTITION_TOTAL=${CIRCLE_NODE_TOTAL} diff --git a/Makefile b/Makefile index 1783acb01e..e6568ed6ee 100644 --- a/Makefile +++ b/Makefile @@ -74,7 +74,7 @@ GOLDFLAGS := $(GOLDFLAGS_BASE) \ -X github.com/algorand/go-algorand/config.Channel=$(CHANNEL) UNIT_TEST_SOURCES := $(sort $(shell GOPATH=$(GOPATH) && GO111MODULE=off && go list ./... | grep -v /go-algorand/test/ )) -COVERPKG_PACKAGES := $(sort $(shell GOPATH=$(GOPATH) && GO111MODULE=off && go list ./... | egrep -v '/go-algorand/(test|debug|cmd|config/defaultsGenerator|tools)' )) +COVERPKG_PACKAGES := $(sort $(shell GOPATH=$(GOPATH) && GO111MODULE=off && go list ./... | egrep -v '/go-algorand/(test|debug|cmd|config/defaultsGenerator|tools)' | egrep -v '(test|testing)$' )) ALGOD_API_PACKAGES := $(sort $(shell GOPATH=$(GOPATH) && GO111MODULE=off && cd daemon/algod/api; go list ./... )) MSGP_GENERATE := ./protocol ./protocol/test ./crypto ./crypto/compactcert ./data/basics ./data/transactions ./data/committee ./data/bookkeeping ./data/hashable ./agreement ./rpcs ./node ./ledger ./ledger/ledgercore ./compactcert ./txnsync ./data/pooldata From 643a06c4b5ced0f5518c85325aff7e81a558ca5c Mon Sep 17 00:00:00 2001 From: chris erway Date: Fri, 5 Nov 2021 09:35:19 -0400 Subject: [PATCH 06/22] add some codecov ignore rules --- codecov.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 codecov.yml diff --git a/codecov.yml b/codecov.yml new file mode 100644 index 0000000000..26bc01ae72 --- /dev/null +++ b/codecov.yml @@ -0,0 +1,4 @@ +ignore: + - "**/msgp_gen.go" # ignore msgp-generated code + - "**/_string.go" # ignore stringer-generated code + - "**/*_test.go" # don't track coverage inside test files From e6c44df51e67845b1ab3b1421f757108bc53f259 Mon Sep 17 00:00:00 2001 From: chris erway Date: Fri, 5 Nov 2021 16:30:41 -0400 Subject: [PATCH 07/22] also ignore packages named "mock" or "mocks" --- .circleci/config.yml | 2 +- Makefile | 2 +- codecov.yml | 1 - 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index b35accfdbd..40b01e9cd1 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -319,7 +319,7 @@ commands: scripts/configure_dev.sh scripts/buildtools/install_buildtools.sh -o "gotest.tools/gotestsum" PACKAGES="$(go list ./... | grep -v /go-algorand/test/)" - COVERPACKAGES="$(go list ./... | egrep -v '/go-algorand/(test|debug|cmd|config/defaultsGenerator|tools)' | egrep -v '(test|testing)$' )" + COVERPACKAGES="$(go list ./... | egrep -v '/go-algorand/(test|debug|cmd|config/defaultsGenerator|tools)' | egrep -v '(test|testing|mock|mocks)$' )" export PACKAGE_NAMES=$(echo $PACKAGES | tr -d '\n') export COVERPACKAGE_NAMES=$(echo $COVERPACKAGES | tr ' ' ',') export PARTITION_TOTAL=${CIRCLE_NODE_TOTAL} diff --git a/Makefile b/Makefile index e6568ed6ee..30d9c50fad 100644 --- a/Makefile +++ b/Makefile @@ -74,7 +74,7 @@ GOLDFLAGS := $(GOLDFLAGS_BASE) \ -X github.com/algorand/go-algorand/config.Channel=$(CHANNEL) UNIT_TEST_SOURCES := $(sort $(shell GOPATH=$(GOPATH) && GO111MODULE=off && go list ./... | grep -v /go-algorand/test/ )) -COVERPKG_PACKAGES := $(sort $(shell GOPATH=$(GOPATH) && GO111MODULE=off && go list ./... | egrep -v '/go-algorand/(test|debug|cmd|config/defaultsGenerator|tools)' | egrep -v '(test|testing)$' )) +COVERPKG_PACKAGES := $(sort $(shell GOPATH=$(GOPATH) && GO111MODULE=off && go list ./... | egrep -v '/go-algorand/(test|debug|cmd|config/defaultsGenerator|tools)' | egrep -v '(test|testing|mocks|mock)$$' )) ALGOD_API_PACKAGES := $(sort $(shell GOPATH=$(GOPATH) && GO111MODULE=off && cd daemon/algod/api; go list ./... )) MSGP_GENERATE := ./protocol ./protocol/test ./crypto ./crypto/compactcert ./data/basics ./data/transactions ./data/committee ./data/bookkeeping ./data/hashable ./agreement ./rpcs ./node ./ledger ./ledger/ledgercore ./compactcert ./txnsync ./data/pooldata diff --git a/codecov.yml b/codecov.yml index 26bc01ae72..5a9a7b2bc4 100644 --- a/codecov.yml +++ b/codecov.yml @@ -1,4 +1,3 @@ ignore: - "**/msgp_gen.go" # ignore msgp-generated code - "**/_string.go" # ignore stringer-generated code - - "**/*_test.go" # don't track coverage inside test files From b1ab9637790297679309d63ab016d5b31daa851b Mon Sep 17 00:00:00 2001 From: chris erway Date: Fri, 5 Nov 2021 18:11:08 -0400 Subject: [PATCH 08/22] move codecov full coverage to nightly only --- .circleci/config.yml | 16 +++++++++++++--- codecov.yml | 4 ++++ scripts/travis/upload_coverage.sh | 2 +- 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 40b01e9cd1..212220882c 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -291,6 +291,10 @@ commands: result_path: type: string default: << pipeline.parameters.result_path >> + use_coverpkg: + description: whether to provide a -coverpkg flag to go test + type: boolean + default: false steps: - attach_workspace: at: << parameters.build_dir >> @@ -325,7 +329,7 @@ commands: export PARTITION_TOTAL=${CIRCLE_NODE_TOTAL} export PARTITION_ID=${CIRCLE_NODE_INDEX} export PARALLEL_FLAG="-p 1" - gotestsum --format testname --junitfile << parameters.result_path >>/<< parameters.result_subdir >>/${CIRCLE_NODE_INDEX}/results.xml --jsonfile << parameters.result_path >>/<< parameters.result_subdir >>/${CIRCLE_NODE_INDEX}/testresults.json -- --tags "sqlite_unlock_notify sqlite_omit_load_extension" << parameters.short_test_flag >> -race -timeout 1h -coverprofile=coverage.txt -covermode=atomic -p 1 $PACKAGE_NAMES -coverpkg=$COVERPACKAGE_NAMES + gotestsum --format testname --junitfile << parameters.result_path >>/<< parameters.result_subdir >>/${CIRCLE_NODE_INDEX}/results.xml --jsonfile << parameters.result_path >>/<< parameters.result_subdir >>/${CIRCLE_NODE_INDEX}/testresults.json -- --tags "sqlite_unlock_notify sqlite_omit_load_extension" << parameters.short_test_flag >> -race -timeout 1h -coverprofile=coverage.txt -covermode=atomic -p 1 $PACKAGE_NAMES <<# parameters.use_coverpkg >> -coverpkg=$COVERPACKAGE_NAMES <> - store_artifacts: path: << parameters.result_path >> destination: test-results @@ -345,12 +349,16 @@ commands: upload_coverage: description: Collect coverage reports and upload them + parameters: + args: + description: additional codecov arguments + type: string steps: - run: name: Upload Coverage Reports no_output_timeout: 10m command: | - scripts/travis/upload_coverage.sh || true + scripts/travis/upload_coverage.sh << parameters.args >> || true upload_to_buildpulse: description: Collect build reports and upload them @@ -550,7 +558,9 @@ jobs: platform: << parameters.platform >> result_subdir: << parameters.platform >>_test_nightly no_output_timeout: 45m - - upload_coverage + use_coverpkg: true + - upload_coverage: + args: "-F nightly" - slack/notify: &slack-fail-event event: fail template: basic_fail_1 diff --git a/codecov.yml b/codecov.yml index 5a9a7b2bc4..dd2a82285d 100644 --- a/codecov.yml +++ b/codecov.yml @@ -1,3 +1,7 @@ +flags: + nightly: + joined: false + ignore: - "**/msgp_gen.go" # ignore msgp-generated code - "**/_string.go" # ignore stringer-generated code diff --git a/scripts/travis/upload_coverage.sh b/scripts/travis/upload_coverage.sh index e861b7ef98..8465d6ce1c 100755 --- a/scripts/travis/upload_coverage.sh +++ b/scripts/travis/upload_coverage.sh @@ -12,4 +12,4 @@ if [[ "${UPSTREAM_VERSION}" != "${LOCAL_VERSION}" ]]; then echo "WARN: version ${UPSTREAM_VERSION} of the codecov upload script is available." fi -/usr/bin/env bash scripts/travis/codecov +/usr/bin/env bash scripts/travis/codecov "$@" From f4b4e5c21c37c60a7ebcf6df2f819c60ad2b3f0e Mon Sep 17 00:00:00 2001 From: chris erway Date: Fri, 5 Nov 2021 18:12:30 -0400 Subject: [PATCH 09/22] provide default upload_coverage args --- .circleci/config.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index 212220882c..4a2aeefffd 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -353,6 +353,7 @@ commands: args: description: additional codecov arguments type: string + default: "" steps: - run: name: Upload Coverage Reports From a9cf78c671b60e02f5d853c5afbc1ef3969ac160 Mon Sep 17 00:00:00 2001 From: chris erway Date: Fri, 20 May 2022 10:39:12 -0400 Subject: [PATCH 10/22] update codecov.yml --- .codecov.yml | 5 +++++ codecov.yml | 7 ------- 2 files changed, 5 insertions(+), 7 deletions(-) delete mode 100644 codecov.yml diff --git a/.codecov.yml b/.codecov.yml index def78dc007..c927971c3b 100644 --- a/.codecov.yml +++ b/.codecov.yml @@ -1,10 +1,15 @@ codecov: require_ci_to_pass: yes +flags: + nightly: + joined: false + ignore: - "**/*_gen.go" - "**/*_gen_test.go" - "**/generated" + - "**/_string.go" # ignore stringer-generated code coverage: status: diff --git a/codecov.yml b/codecov.yml deleted file mode 100644 index dd2a82285d..0000000000 --- a/codecov.yml +++ /dev/null @@ -1,7 +0,0 @@ -flags: - nightly: - joined: false - -ignore: - - "**/msgp_gen.go" # ignore msgp-generated code - - "**/_string.go" # ignore stringer-generated code From ee17187924977e2b17a9d11b804053eb441be21d Mon Sep 17 00:00:00 2001 From: chris erway Date: Thu, 23 Jun 2022 10:23:29 -0400 Subject: [PATCH 11/22] use circleci orb for codecov upload, rename "nightly" flag --- .circleci/config.yml | 31 +- scripts/travis/codecov | 1883 ----------------------------- scripts/travis/upload_coverage.sh | 15 - 3 files changed, 10 insertions(+), 1919 deletions(-) delete mode 100755 scripts/travis/codecov delete mode 100755 scripts/travis/upload_coverage.sh diff --git a/.circleci/config.yml b/.circleci/config.yml index a7494135bc..435e2baa28 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -4,6 +4,7 @@ orbs: win: circleci/windows@2.3.0 go: circleci/go@1.7.0 slack: circleci/slack@4.4.2 + codecov: codecov/codecov@3.1.1 parameters: ubuntu_image: @@ -294,8 +295,8 @@ commands: result_path: type: string default: << pipeline.parameters.result_path >> - use_coverpkg: - description: whether to provide a -coverpkg flag to go test + full_coverage: + description: whether to provide a go test -coverpkg flag to measure coverage across all packages type: boolean default: false steps: @@ -333,7 +334,7 @@ commands: export COVERPACKAGE_NAMES=$(echo $COVERPACKAGES | tr ' ' ',') export PARTITION_TOTAL=${CIRCLE_NODE_TOTAL} export PARTITION_ID=${CIRCLE_NODE_INDEX} - gotestsum --format standard-verbose --junitfile << parameters.result_path >>/<< parameters.result_subdir >>/${CIRCLE_NODE_INDEX}/results.xml --jsonfile << parameters.result_path >>/<< parameters.result_subdir >>/${CIRCLE_NODE_INDEX}/testresults.json -- --tags "sqlite_unlock_notify sqlite_omit_load_extension" << parameters.short_test_flag >> -race -timeout 1h -coverprofile=coverage.txt -covermode=atomic -p 1 $PACKAGE_NAMES <<# parameters.use_coverpkg >> -coverpkg=$COVERPACKAGE_NAMES <> + gotestsum --format standard-verbose --junitfile << parameters.result_path >>/<< parameters.result_subdir >>/${CIRCLE_NODE_INDEX}/results.xml --jsonfile << parameters.result_path >>/<< parameters.result_subdir >>/${CIRCLE_NODE_INDEX}/testresults.json -- --tags "sqlite_unlock_notify sqlite_omit_load_extension" << parameters.short_test_flag >> -race -timeout 1h -coverprofile=coverage.txt -covermode=atomic -p 1 $PACKAGE_NAMES <<# parameters.full_coverage >> -coverpkg=$COVERPACKAGE_NAMES <> - store_artifacts: path: << parameters.result_path >> destination: test-results @@ -344,20 +345,6 @@ commands: paths: - << parameters.result_subdir >> - upload_coverage: - description: Collect coverage reports and upload them - parameters: - args: - description: additional codecov arguments - type: string - default: "" - steps: - - run: - name: Upload Coverage Reports - no_output_timeout: 10m - command: | - scripts/travis/upload_coverage.sh << parameters.args >> || true - generic_integration: description: Run integration tests from build workspace, for re-use by diferent architectures parameters: @@ -508,7 +495,8 @@ jobs: platform: << parameters.platform >> result_subdir: << parameters.platform >>_test short_test_flag: "-short" - - upload_coverage + - codecov/upload: + validate: true test_nightly: parameters: @@ -524,9 +512,10 @@ jobs: platform: << parameters.platform >> result_subdir: << parameters.platform >>_test_nightly no_output_timeout: 45m - use_coverpkg: true - - upload_coverage: - args: "-F nightly" + full_coverage: true + - codecov/upload: + validate: true + flags: "full_coverage" - slack/notify: &slack-fail-event event: fail template: basic_fail_1 diff --git a/scripts/travis/codecov b/scripts/travis/codecov deleted file mode 100755 index d443a8979c..0000000000 --- a/scripts/travis/codecov +++ /dev/null @@ -1,1883 +0,0 @@ -#!/usr/bin/env bash - -# Apache License Version 2.0, January 2004 -# https://github.com/codecov/codecov-bash/blob/master/LICENSE - -set -e +o pipefail - -VERSION="1.0.3" - -codecov_flags=( ) -url="https://codecov.io" -env="$CODECOV_ENV" -service="" -token="" -search_in="" -# shellcheck disable=SC2153 -flags="$CODECOV_FLAGS" -exit_with=0 -curlargs="" -curlawsargs="" -dump="0" -clean="0" -curl_s="-s" -name="$CODECOV_NAME" -include_cov="" -exclude_cov="" -ddp="$HOME/Library/Developer/Xcode/DerivedData" -xp="" -files="" -save_to="" -direct_file_upload="" -cacert="$CODECOV_CA_BUNDLE" -gcov_ignore="-not -path './bower_components/**' -not -path './node_modules/**' -not -path './vendor/**'" -gcov_include="" - -ft_gcov="1" -ft_coveragepy="1" -ft_fix="1" -ft_search="1" -ft_s3="1" -ft_network="1" -ft_xcodellvm="1" -ft_xcodeplist="0" -ft_gcovout="1" -ft_html="0" -ft_yaml="0" - -_git_root=$(git rev-parse --show-toplevel 2>/dev/null || hg root 2>/dev/null || echo "$PWD") -git_root="$_git_root" -remote_addr="" -if [ "$git_root" = "$PWD" ]; -then - git_root="." -fi - -branch_o="" -build_o="" -commit_o="" -pr_o="" -prefix_o="" -network_filter_o="" -search_in_o="" -slug_o="" -tag_o="" -url_o="" -git_ls_files_recurse_submodules_o="" -package="bash" - -commit="$VCS_COMMIT_ID" -branch="$VCS_BRANCH_NAME" -pr="$VCS_PULL_REQUEST" -slug="$VCS_SLUG" -tag="$VCS_TAG" -build_url="$CI_BUILD_URL" -build="$CI_BUILD_ID" -job="$CI_JOB_ID" - -beta_xcode_partials="" - -proj_root="$git_root" -gcov_exe="gcov" -gcov_arg="" - -b="\033[0;36m" -g="\033[0;32m" -r="\033[0;31m" -e="\033[0;90m" -y="\033[0;33m" -x="\033[0m" - -show_help() { -cat << EOF - - Codecov Bash $VERSION - - Global report uploading tool for Codecov - Documentation at https://docs.codecov.io/docs - Contribute at https://github.com/codecov/codecov-bash - - - -h Display this help and exit - -f FILE Target file(s) to upload - - -f "path/to/file" only upload this file - skips searching unless provided patterns below - - -f '!*.bar' ignore all files at pattern *.bar - -f '*.foo' include all files at pattern *.foo - Must use single quotes. - This is non-exclusive, use -s "*.foo" to match specific paths. - - -s DIR Directory to search for coverage reports. - Already searches project root and artifact folders. - -t TOKEN Set the private repository token - (option) set environment variable CODECOV_TOKEN=:uuid - - -t @/path/to/token_file - -t uuid - - -n NAME Custom defined name of the upload. Visible in Codecov UI - - -e ENV Specify environment variables to be included with this build - Also accepting environment variables: CODECOV_ENV=VAR,VAR2 - - -e VAR,VAR2 - - -k prefix Prefix filepaths to help resolve path fixing - - -i prefix Only include files in the network with a certain prefix. Useful for upload-specific path fixing - - -X feature Toggle functionalities - - -X gcov Disable gcov - -X coveragepy Disable python coverage - -X fix Disable report fixing - -X search Disable searching for reports - -X xcode Disable xcode processing - -X network Disable uploading the file network - -X gcovout Disable gcov output - -X html Enable coverage for HTML files - -X recursesubs Enable recurse submodules in git projects when searching for source files - -X yaml Enable coverage for YAML files - - -N The commit SHA of the parent for which you are uploading coverage. If not present, - the parent will be determined using the API of your repository provider. - When using the repository provider's API, the parent is determined via finding - the closest ancestor to the commit. - - -R root dir Used when not in git/hg project to identify project root directory - -F flag Flag the upload to group coverage metrics - - -F unittests This upload is only unittests - -F integration This upload is only integration tests - -F ui,chrome This upload is Chrome - UI tests - - -c Move discovered coverage reports to the trash - -z FILE Upload specified file directly to Codecov and bypass all report generation. - This is inteded to be used only with a pre-formatted Codecov report and is not - expected to work under any other circumstances. - -Z Exit with 1 if not successful. Default will Exit with 0 - - -- xcode -- - -D Custom Derived Data Path for Coverage.profdata and gcov processing - Default '~/Library/Developer/Xcode/DerivedData' - -J Specify packages to build coverage. Uploader will only build these packages. - This can significantly reduces time to build coverage reports. - - -J 'MyAppName' Will match "MyAppName" and "MyAppNameTests" - -J '^ExampleApp$' Will match only "ExampleApp" not "ExampleAppTests" - - -- gcov -- - -g GLOB Paths to ignore during gcov gathering - -G GLOB Paths to include during gcov gathering - -p dir Project root directory - Also used when preparing gcov - -x gcovexe gcov executable to run. Defaults to 'gcov' - -a gcovargs extra arguments to pass to gcov - - -- Override CI Environment Variables -- - These variables are automatically detected by popular CI providers - - -B branch Specify the branch name - -C sha Specify the commit sha - -P pr Specify the pull request number - -b build Specify the build number - -T tag Specify the git tag - - -- Enterprise -- - -u URL Set the target url for Enterprise customers - Not required when retrieving the bash uploader from your CCE - (option) Set environment variable CODECOV_URL=https://my-hosted-codecov.com - -r SLUG owner/repo slug used instead of the private repo token in Enterprise - (option) set environment variable CODECOV_SLUG=:owner/:repo - (option) set in your codecov.yml "codecov.slug" - -S PATH File path to your cacert.pem file used to verify ssl with Codecov Enterprise (optional) - (option) Set environment variable: CODECOV_CA_BUNDLE="/path/to/ca.pem" - -U curlargs Extra curl arguments to communicate with Codecov. e.g., -U "--proxy http://http-proxy" - -A curlargs Extra curl arguments to communicate with AWS. - - -- Debugging -- - -d Don't upload, but dump upload file to stdout - -q PATH Write upload file to path - -K Remove color from the output - -v Verbose mode - -EOF -} - - -say() { - echo -e "$1" -} - - -urlencode() { - echo "$1" | curl -Gso /dev/null -w "%{url_effective}" --data-urlencode @- "" | cut -c 3- | sed -e 's/%0A//' -} - -swiftcov() { - _dir=$(dirname "$1" | sed 's/\(Build\).*/\1/g') - for _type in app framework xctest - do - find "$_dir" -name "*.$_type" | while read -r f - do - _proj=${f##*/} - _proj=${_proj%."$_type"} - if [ "$2" = "" ] || [ "$(echo "$_proj" | grep -i "$2")" != "" ]; - then - say " $g+$x Building reports for $_proj $_type" - dest=$([ -f "$f/$_proj" ] && echo "$f/$_proj" || echo "$f/Contents/MacOS/$_proj") - # shellcheck disable=SC2001 - _proj_name=$(echo "$_proj" | sed -e 's/[[:space:]]//g') - # shellcheck disable=SC2086 - xcrun llvm-cov show $beta_xcode_partials -instr-profile "$1" "$dest" > "$_proj_name.$_type.coverage.txt" \ - || say " ${r}x>${x} llvm-cov failed to produce results for $dest" - fi - done - done -} - - -# Credits to: https://gist.github.com/pkuczynski/8665367 -parse_yaml() { - local prefix=$2 - local s='[[:space:]]*' w='[a-zA-Z0-9_]*' - local fs - fs=$(echo @|tr @ '\034') - sed -ne "s|^\($s\)\($w\)$s:$s\"\(.*\)\"$s\$|\1$fs\2$fs\3|p" \ - -e "s|^\($s\)\($w\)$s:$s\(.*\)$s\$|\1$fs\2$fs\3|p" "$1" | - awk -F"$fs" '{ - indent = length($1)/2; - vname[indent] = $2; - for (i in vname) {if (i > indent) {delete vname[i]}} - if (length($3) > 0) { - vn=""; if (indent > 0) {vn=(vn)(vname[0])("_")} - printf("%s%s%s=\"%s\"\n", "'"$prefix"'",vn, $2, $3); - } - }' -} - -if [ $# != 0 ]; -then - while getopts "a:A:b:B:cC:dD:e:f:F:g:G:hi:J:k:Kn:p:P:Q:q:r:R:s:S:t:T:u:U:vx:X:Zz:N:-" o - do - codecov_flags+=( "$o" ) - case "$o" in - "-") - echo -e "${r}Long options are not supported${x}" - exit 2 - ;; - "?") - ;; - "N") - parent=$OPTARG - ;; - "a") - gcov_arg=$OPTARG - ;; - "A") - curlawsargs="$OPTARG" - ;; - "b") - build_o="$OPTARG" - ;; - "B") - branch_o="$OPTARG" - ;; - "c") - clean="1" - ;; - "C") - commit_o="$OPTARG" - ;; - "d") - dump="1" - ;; - "D") - ddp="$OPTARG" - ;; - "e") - env="$env,$OPTARG" - ;; - "f") - if [ "${OPTARG::1}" = "!" ]; - then - exclude_cov="$exclude_cov -not -path '${OPTARG:1}'" - - elif [[ "$OPTARG" = *"*"* ]]; - then - include_cov="$include_cov -or -path '$OPTARG'" - - else - ft_search=0 - if [ "$files" = "" ]; - then - files="$OPTARG" - else - files="$files -$OPTARG" - fi - fi - ;; - "F") - if [ "$flags" = "" ]; - then - flags="$OPTARG" - else - flags="$flags,$OPTARG" - fi - ;; - "g") - gcov_ignore="$gcov_ignore -not -path '$OPTARG'" - ;; - "G") - gcov_include="$gcov_include -path '$OPTARG'" - ;; - "h") - show_help - exit 0; - ;; - "i") - network_filter_o="$OPTARG" - ;; - "J") - ft_xcodellvm="1" - ft_xcodeplist="0" - if [ "$xp" = "" ]; - then - xp="$OPTARG" - else - xp="$xp\|$OPTARG" - fi - ;; - "k") - prefix_o=$(echo "$OPTARG" | sed -e 's:^/*::' -e 's:/*$::') - ;; - "K") - b="" - g="" - r="" - e="" - x="" - ;; - "n") - name="$OPTARG" - ;; - "p") - proj_root="$OPTARG" - ;; - "P") - pr_o="$OPTARG" - ;; - "Q") - # this is only meant for Codecov packages to overwrite - package="$OPTARG" - ;; - "q") - save_to="$OPTARG" - ;; - "r") - slug_o="$OPTARG" - ;; - "R") - git_root="$OPTARG" - ;; - "s") - if [ "$search_in_o" = "" ]; - then - search_in_o="$OPTARG" - else - search_in_o="$search_in_o $OPTARG" - fi - ;; - "S") - # shellcheck disable=SC2089 - cacert="--cacert \"$OPTARG\"" - ;; - "t") - if [ "${OPTARG::1}" = "@" ]; - then - token=$(< "${OPTARG:1}" tr -d ' \n') - else - token="$OPTARG" - fi - ;; - "T") - tag_o="$OPTARG" - ;; - "u") - url_o=$(echo "$OPTARG" | sed -e 's/\/$//') - ;; - "U") - curlargs="$OPTARG" - ;; - "v") - set -x - curl_s="" - ;; - "x") - gcov_exe=$OPTARG - ;; - "X") - if [ "$OPTARG" = "gcov" ]; - then - ft_gcov="0" - elif [ "$OPTARG" = "coveragepy" ] || [ "$OPTARG" = "py" ]; - then - ft_coveragepy="0" - elif [ "$OPTARG" = "gcovout" ]; - then - ft_gcovout="0" - elif [ "$OPTARG" = "xcodellvm" ]; - then - ft_xcodellvm="1" - ft_xcodeplist="0" - elif [ "$OPTARG" = "fix" ] || [ "$OPTARG" = "fixes" ]; - then - ft_fix="0" - elif [ "$OPTARG" = "xcode" ]; - then - ft_xcodellvm="0" - ft_xcodeplist="0" - elif [ "$OPTARG" = "search" ]; - then - ft_search="0" - elif [ "$OPTARG" = "xcodepartials" ]; - then - beta_xcode_partials="-use-color" - elif [ "$OPTARG" = "network" ]; - then - ft_network="0" - elif [ "$OPTARG" = "s3" ]; - then - ft_s3="0" - elif [ "$OPTARG" = "html" ]; - then - ft_html="1" - elif [ "$OPTARG" = "recursesubs" ]; - then - git_ls_files_recurse_submodules_o="--recurse-submodules" - elif [ "$OPTARG" = "yaml" ]; - then - ft_yaml="1" - fi - ;; - "Z") - exit_with=1 - ;; - "z") - direct_file_upload="$OPTARG" - ft_gcov="0" - ft_coveragepy="0" - ft_fix="0" - ft_search="0" - ft_network="0" - ft_xcodellvm="0" - ft_gcovout="0" - include_cov="" - ;; - *) - echo -e "${r}Unexpected flag not supported${x}" - ;; - esac - done -fi - -say " - _____ _ - / ____| | | -| | ___ __| | ___ ___ _____ __ -| | / _ \\ / _\` |/ _ \\/ __/ _ \\ \\ / / -| |___| (_) | (_| | __/ (_| (_) \\ V / - \\_____\\___/ \\__,_|\\___|\\___\\___/ \\_/ - Bash-$VERSION - -" - -# check for installed tools -# git/hg -if [ "$direct_file_upload" = "" ]; -then - if [ -x "$(command -v git)" ]; - then - say "$b==>$x $(git --version) found" - else - say "$y==>$x git not installed, testing for mercurial" - if [ -x "$(command -v hg)" ]; - then - say "$b==>$x $(hg --version) found" - else - say "$r==>$x git nor mercurial are installed. Uploader may fail or have unintended consequences" - fi - fi -fi -# curl -if [ -x "$(command -v curl)" ]; -then - say "$b==>$x $(curl --version)" -else - say "$r==>$x curl not installed. Exiting." - exit ${exit_with}; -fi - -search_in="$proj_root" - -#shellcheck disable=SC2154 -if [ "$JENKINS_URL" != "" ]; -then - say "$e==>$x Jenkins CI detected." - # https://wiki.jenkins-ci.org/display/JENKINS/Building+a+software+project - # https://wiki.jenkins-ci.org/display/JENKINS/GitHub+pull+request+builder+plugin#GitHubpullrequestbuilderplugin-EnvironmentVariables - service="jenkins" - - # shellcheck disable=SC2154 - if [ "$ghprbSourceBranch" != "" ]; - then - branch="$ghprbSourceBranch" - elif [ "$GIT_BRANCH" != "" ]; - then - branch="$GIT_BRANCH" - elif [ "$BRANCH_NAME" != "" ]; - then - branch="$BRANCH_NAME" - fi - - # shellcheck disable=SC2154 - if [ "$ghprbActualCommit" != "" ]; - then - commit="$ghprbActualCommit" - elif [ "$GIT_COMMIT" != "" ]; - then - commit="$GIT_COMMIT" - fi - - # shellcheck disable=SC2154 - if [ "$ghprbPullId" != "" ]; - then - pr="$ghprbPullId" - elif [ "$CHANGE_ID" != "" ]; - then - pr="$CHANGE_ID" - fi - - build="$BUILD_NUMBER" - # shellcheck disable=SC2153 - build_url=$(urlencode "$BUILD_URL") - -elif [ "$CI" = "true" ] && [ "$TRAVIS" = "true" ] && [ "$SHIPPABLE" != "true" ]; -then - say "$e==>$x Travis CI detected." - # https://docs.travis-ci.com/user/environment-variables/ - service="travis" - commit="${TRAVIS_PULL_REQUEST_SHA:-$TRAVIS_COMMIT}" - build="$TRAVIS_JOB_NUMBER" - pr="$TRAVIS_PULL_REQUEST" - job="$TRAVIS_JOB_ID" - slug="$TRAVIS_REPO_SLUG" - env="$env,TRAVIS_OS_NAME" - tag="$TRAVIS_TAG" - if [ "$TRAVIS_BRANCH" != "$TRAVIS_TAG" ]; - then - branch="${TRAVIS_PULL_REQUEST_BRANCH:-$TRAVIS_BRANCH}" - fi - - language=$(compgen -A variable | grep "^TRAVIS_.*_VERSION$" | head -1) - if [ "$language" != "" ]; - then - env="$env,${!language}" - fi - -elif [ "$CODEBUILD_CI" = "true" ]; -then - say "$e==>$x AWS Codebuild detected." - # https://docs.aws.amazon.com/codebuild/latest/userguide/build-env-ref-env-vars.html - service="codebuild" - commit="$CODEBUILD_RESOLVED_SOURCE_VERSION" - build="$CODEBUILD_BUILD_ID" - branch="$(echo "$CODEBUILD_WEBHOOK_HEAD_REF" | sed 's/^refs\/heads\///')" - if [ "${CODEBUILD_SOURCE_VERSION/pr}" = "$CODEBUILD_SOURCE_VERSION" ] ; then - pr="false" - else - pr="$(echo "$CODEBUILD_SOURCE_VERSION" | sed 's/^pr\///')" - fi - job="$CODEBUILD_BUILD_ID" - slug="$(echo "$CODEBUILD_SOURCE_REPO_URL" | sed 's/^.*:\/\/[^\/]*\///' | sed 's/\.git$//')" - -elif [ "$CI" = "true" ] && [ "$CI_NAME" = "codeship" ]; -then - say "$e==>$x Codeship CI detected." - # https://www.codeship.io/documentation/continuous-integration/set-environment-variables/ - service="codeship" - branch="$CI_BRANCH" - build="$CI_BUILD_NUMBER" - build_url=$(urlencode "$CI_BUILD_URL") - commit="$CI_COMMIT_ID" - -elif [ -n "$CF_BUILD_URL" ] && [ -n "$CF_BUILD_ID" ]; -then - say "$e==>$x Codefresh CI detected." - # https://docs.codefresh.io/v1.0/docs/variables - service="codefresh" - branch="$CF_BRANCH" - build="$CF_BUILD_ID" - build_url=$(urlencode "$CF_BUILD_URL") - commit="$CF_REVISION" - -elif [ "$TEAMCITY_VERSION" != "" ]; -then - say "$e==>$x TeamCity CI detected." - # https://confluence.jetbrains.com/display/TCD8/Predefined+Build+Parameters - # https://confluence.jetbrains.com/plugins/servlet/mobile#content/view/74847298 - if [ "$TEAMCITY_BUILD_BRANCH" = '' ]; - then - echo " Teamcity does not automatically make build parameters available as environment variables." - echo " Add the following environment parameters to the build configuration" - echo " env.TEAMCITY_BUILD_BRANCH = %teamcity.build.branch%" - echo " env.TEAMCITY_BUILD_ID = %teamcity.build.id%" - echo " env.TEAMCITY_BUILD_URL = %teamcity.serverUrl%/viewLog.html?buildId=%teamcity.build.id%" - echo " env.TEAMCITY_BUILD_COMMIT = %system.build.vcs.number%" - echo " env.TEAMCITY_BUILD_REPOSITORY = %vcsroot..url%" - fi - service="teamcity" - branch="$TEAMCITY_BUILD_BRANCH" - build="$TEAMCITY_BUILD_ID" - build_url=$(urlencode "$TEAMCITY_BUILD_URL") - if [ "$TEAMCITY_BUILD_COMMIT" != "" ]; - then - commit="$TEAMCITY_BUILD_COMMIT" - else - commit="$BUILD_VCS_NUMBER" - fi - remote_addr="$TEAMCITY_BUILD_REPOSITORY" - -elif [ "$CI" = "true" ] && [ "$CIRCLECI" = "true" ]; -then - say "$e==>$x Circle CI detected." - # https://circleci.com/docs/environment-variables - service="circleci" - branch="$CIRCLE_BRANCH" - build="$CIRCLE_BUILD_NUM" - job="$CIRCLE_NODE_INDEX" - if [ "$CIRCLE_PROJECT_REPONAME" != "" ]; - then - slug="$CIRCLE_PROJECT_USERNAME/$CIRCLE_PROJECT_REPONAME" - else - # git@github.com:owner/repo.git - slug="${CIRCLE_REPOSITORY_URL##*:}" - # owner/repo.git - slug="${slug%%.git}" - fi - pr="${CIRCLE_PULL_REQUEST##*/}" - commit="$CIRCLE_SHA1" - search_in="$search_in $CIRCLE_ARTIFACTS $CIRCLE_TEST_REPORTS" - -elif [ "$BUDDYBUILD_BRANCH" != "" ]; -then - say "$e==>$x buddybuild detected" - # http://docs.buddybuild.com/v6/docs/custom-prebuild-and-postbuild-steps - service="buddybuild" - branch="$BUDDYBUILD_BRANCH" - build="$BUDDYBUILD_BUILD_NUMBER" - build_url="https://dashboard.buddybuild.com/public/apps/$BUDDYBUILD_APP_ID/build/$BUDDYBUILD_BUILD_ID" - # BUDDYBUILD_TRIGGERED_BY - if [ "$ddp" = "$HOME/Library/Developer/Xcode/DerivedData" ]; - then - ddp="/private/tmp/sandbox/${BUDDYBUILD_APP_ID}/bbtest" - fi - -elif [ "${bamboo_planRepository_revision}" != "" ]; -then - say "$e==>$x Bamboo detected" - # https://confluence.atlassian.com/bamboo/bamboo-variables-289277087.html#Bamboovariables-Build-specificvariables - service="bamboo" - commit="${bamboo_planRepository_revision}" - # shellcheck disable=SC2154 - branch="${bamboo_planRepository_branch}" - # shellcheck disable=SC2154 - build="${bamboo_buildNumber}" - # shellcheck disable=SC2154 - build_url="${bamboo_buildResultsUrl}" - # shellcheck disable=SC2154 - remote_addr="${bamboo_planRepository_repositoryUrl}" - -elif [ "$CI" = "true" ] && [ "$BITRISE_IO" = "true" ]; -then - # http://devcenter.bitrise.io/faq/available-environment-variables/ - say "$e==>$x Bitrise CI detected." - service="bitrise" - branch="$BITRISE_GIT_BRANCH" - build="$BITRISE_BUILD_NUMBER" - build_url=$(urlencode "$BITRISE_BUILD_URL") - pr="$BITRISE_PULL_REQUEST" - if [ "$GIT_CLONE_COMMIT_HASH" != "" ]; - then - commit="$GIT_CLONE_COMMIT_HASH" - fi - -elif [ "$CI" = "true" ] && [ "$SEMAPHORE" = "true" ]; -then - say "$e==>$x Semaphore CI detected." -# https://docs.semaphoreci.com/ci-cd-environment/environment-variables/#semaphore-related - service="semaphore" - branch="$SEMAPHORE_GIT_BRANCH" - build="$SEMAPHORE_WORKFLOW_NUMBER" - job="$SEMAPHORE_JOB_ID" - pr="$PULL_REQUEST_NUMBER" - slug="$SEMAPHORE_REPO_SLUG" - commit="$REVISION" - env="$env,SEMAPHORE_TRIGGER_SOURCE" - -elif [ "$CI" = "true" ] && [ "$BUILDKITE" = "true" ]; -then - say "$e==>$x Buildkite CI detected." - # https://buildkite.com/docs/guides/environment-variables - service="buildkite" - branch="$BUILDKITE_BRANCH" - build="$BUILDKITE_BUILD_NUMBER" - job="$BUILDKITE_JOB_ID" - build_url=$(urlencode "$BUILDKITE_BUILD_URL") - slug="$BUILDKITE_PROJECT_SLUG" - commit="$BUILDKITE_COMMIT" - if [[ "$BUILDKITE_PULL_REQUEST" != "false" ]]; then - pr="$BUILDKITE_PULL_REQUEST" - fi - tag="$BUILDKITE_TAG" - -elif [ "$CI" = "drone" ] || [ "$DRONE" = "true" ]; -then - say "$e==>$x Drone CI detected." - # http://docs.drone.io/env.html - # drone commits are not full shas - service="drone.io" - branch="$DRONE_BRANCH" - build="$DRONE_BUILD_NUMBER" - build_url=$(urlencode "${DRONE_BUILD_LINK}") - pr="$DRONE_PULL_REQUEST" - job="$DRONE_JOB_NUMBER" - tag="$DRONE_TAG" - -elif [ "$CI" = "true" ] && [ "$HEROKU_TEST_RUN_BRANCH" != "" ]; -then - say "$e==>$x Heroku CI detected." - # https://devcenter.heroku.com/articles/heroku-ci#environment-variables - service="heroku" - branch="$HEROKU_TEST_RUN_BRANCH" - build="$HEROKU_TEST_RUN_ID" - commit="$HEROKU_TEST_RUN_COMMIT_VERSION" - -elif [[ "$CI" = "true" || "$CI" = "True" ]] && [[ "$APPVEYOR" = "true" || "$APPVEYOR" = "True" ]]; -then - say "$e==>$x Appveyor CI detected." - # http://www.appveyor.com/docs/environment-variables - service="appveyor" - branch="$APPVEYOR_REPO_BRANCH" - build=$(urlencode "$APPVEYOR_JOB_ID") - pr="$APPVEYOR_PULL_REQUEST_NUMBER" - job="$APPVEYOR_ACCOUNT_NAME%2F$APPVEYOR_PROJECT_SLUG%2F$APPVEYOR_BUILD_VERSION" - slug="$APPVEYOR_REPO_NAME" - commit="$APPVEYOR_REPO_COMMIT" - build_url=$(urlencode "${APPVEYOR_URL}/project/${APPVEYOR_REPO_NAME}/builds/$APPVEYOR_BUILD_ID/job/${APPVEYOR_JOB_ID}") - -elif [ "$CI" = "true" ] && [ "$WERCKER_GIT_BRANCH" != "" ]; -then - say "$e==>$x Wercker CI detected." - # http://devcenter.wercker.com/articles/steps/variables.html - service="wercker" - branch="$WERCKER_GIT_BRANCH" - build="$WERCKER_MAIN_PIPELINE_STARTED" - slug="$WERCKER_GIT_OWNER/$WERCKER_GIT_REPOSITORY" - commit="$WERCKER_GIT_COMMIT" - -elif [ "$CI" = "true" ] && [ "$MAGNUM" = "true" ]; -then - say "$e==>$x Magnum CI detected." - # https://magnum-ci.com/docs/environment - service="magnum" - branch="$CI_BRANCH" - build="$CI_BUILD_NUMBER" - commit="$CI_COMMIT" - -elif [ "$SHIPPABLE" = "true" ]; -then - say "$e==>$x Shippable CI detected." - # http://docs.shippable.com/ci_configure/ - service="shippable" - # shellcheck disable=SC2153 - branch=$([ "$HEAD_BRANCH" != "" ] && echo "$HEAD_BRANCH" || echo "$BRANCH") - build="$BUILD_NUMBER" - build_url=$(urlencode "$BUILD_URL") - pr="$PULL_REQUEST" - slug="$REPO_FULL_NAME" - # shellcheck disable=SC2153 - commit="$COMMIT" - -elif [ "$TDDIUM" = "true" ]; -then - say "Solano CI detected." - # http://docs.solanolabs.com/Setup/tddium-set-environment-variables/ - service="solano" - commit="$TDDIUM_CURRENT_COMMIT" - branch="$TDDIUM_CURRENT_BRANCH" - build="$TDDIUM_TID" - pr="$TDDIUM_PR_ID" - -elif [ "$GREENHOUSE" = "true" ]; -then - say "$e==>$x Greenhouse CI detected." - # http://docs.greenhouseci.com/docs/environment-variables-files - service="greenhouse" - branch="$GREENHOUSE_BRANCH" - build="$GREENHOUSE_BUILD_NUMBER" - build_url=$(urlencode "$GREENHOUSE_BUILD_URL") - pr="$GREENHOUSE_PULL_REQUEST" - commit="$GREENHOUSE_COMMIT" - search_in="$search_in $GREENHOUSE_EXPORT_DIR" - -elif [ "$GITLAB_CI" != "" ]; -then - say "$e==>$x GitLab CI detected." - # http://doc.gitlab.com/ce/ci/variables/README.html - service="gitlab" - branch="${CI_BUILD_REF_NAME:-$CI_COMMIT_REF_NAME}" - build="${CI_BUILD_ID:-$CI_JOB_ID}" - remote_addr="${CI_BUILD_REPO:-$CI_REPOSITORY_URL}" - commit="${CI_BUILD_REF:-$CI_COMMIT_SHA}" - slug="${CI_PROJECT_PATH}" - -elif [ "$GITHUB_ACTIONS" != "" ]; -then - say "$e==>$x GitHub Actions detected." - say " Env vars used:" - say " -> GITHUB_ACTIONS: ${GITHUB_ACTIONS}" - say " -> GITHUB_HEAD_REF: ${GITHUB_HEAD_REF}" - say " -> GITHUB_REF: ${GITHUB_REF}" - say " -> GITHUB_REPOSITORY: ${GITHUB_REPOSITORY}" - say " -> GITHUB_RUN_ID: ${GITHUB_RUN_ID}" - say " -> GITHUB_SHA: ${GITHUB_SHA}" - say " -> GITHUB_WORKFLOW: ${GITHUB_WORKFLOW}" - - # https://github.com/features/actions - service="github-actions" - - # https://help.github.com/en/articles/virtual-environments-for-github-actions#environment-variables - branch="${GITHUB_REF#refs/heads/}" - if [ "$GITHUB_HEAD_REF" != "" ]; - then - # PR refs are in the format: refs/pull/7/merge - pr="${GITHUB_REF#refs/pull/}" - pr="${pr%/merge}" - branch="${GITHUB_HEAD_REF}" - fi - commit="${GITHUB_SHA}" - slug="${GITHUB_REPOSITORY}" - build="${GITHUB_RUN_ID}" - build_url=$(urlencode "http://github.com/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}") - job="$(urlencode "${GITHUB_WORKFLOW}")" - - # actions/checkout runs in detached HEAD - mc= - if [ -n "$pr" ] && [ "$pr" != false ] && [ "$commit_o" == "" ]; - then - mc=$(git show --no-patch --format="%P" 2>/dev/null || echo "") - - if [[ "$mc" =~ ^[a-z0-9]{40}[[:space:]][a-z0-9]{40}$ ]]; - then - mc=$(echo "$mc" | cut -d' ' -f2) - say " Fixing merge commit SHA $commit -> $mc" - commit=$mc - elif [[ "$mc" = "" ]]; - then - say "$r-> Issue detecting commit SHA. Please run actions/checkout with fetch-depth > 1 or set to 0$x" - fi - fi - -elif [ "$SYSTEM_TEAMFOUNDATIONSERVERURI" != "" ]; -then - say "$e==>$x Azure Pipelines detected." - # https://docs.microsoft.com/en-us/azure/devops/pipelines/build/variables?view=vsts - # https://docs.microsoft.com/en-us/azure/devops/pipelines/build/variables?view=azure-devops&viewFallbackFrom=vsts&tabs=yaml - service="azure_pipelines" - commit="$BUILD_SOURCEVERSION" - build="$BUILD_BUILDNUMBER" - if [ -z "$SYSTEM_PULLREQUEST_PULLREQUESTNUMBER" ]; - then - pr="$SYSTEM_PULLREQUEST_PULLREQUESTID" - else - pr="$SYSTEM_PULLREQUEST_PULLREQUESTNUMBER" - fi - project="${SYSTEM_TEAMPROJECT}" - server_uri="${SYSTEM_TEAMFOUNDATIONSERVERURI}" - job="${BUILD_BUILDID}" - branch="${BUILD_SOURCEBRANCH#"refs/heads/"}" - build_url=$(urlencode "${SYSTEM_TEAMFOUNDATIONSERVERURI}${SYSTEM_TEAMPROJECT}/_build/results?buildId=${BUILD_BUILDID}") - - # azure/pipelines runs in detached HEAD - mc= - if [ -n "$pr" ] && [ "$pr" != false ]; - then - mc=$(git show --no-patch --format="%P" 2>/dev/null || echo "") - - if [[ "$mc" =~ ^[a-z0-9]{40}[[:space:]][a-z0-9]{40}$ ]]; - then - mc=$(echo "$mc" | cut -d' ' -f2) - say " Fixing merge commit SHA $commit -> $mc" - commit=$mc - fi - fi - -elif [ "$CI" = "true" ] && [ "$BITBUCKET_BUILD_NUMBER" != "" ]; -then - say "$e==>$x Bitbucket detected." - # https://confluence.atlassian.com/bitbucket/variables-in-pipelines-794502608.html - service="bitbucket" - branch="$BITBUCKET_BRANCH" - build="$BITBUCKET_BUILD_NUMBER" - slug="$BITBUCKET_REPO_OWNER/$BITBUCKET_REPO_SLUG" - job="$BITBUCKET_BUILD_NUMBER" - pr="$BITBUCKET_PR_ID" - commit="$BITBUCKET_COMMIT" - # See https://jira.atlassian.com/browse/BCLOUD-19393 - if [ "${#commit}" = 12 ]; - then - commit=$(git rev-parse "$BITBUCKET_COMMIT") - fi - -elif [ "$CI" = "true" ] && [ "$BUDDY" = "true" ]; -then - say "$e==>$x Buddy CI detected." - # https://buddy.works/docs/pipelines/environment-variables - service="buddy" - branch="$BUDDY_EXECUTION_BRANCH" - build="$BUDDY_EXECUTION_ID" - build_url=$(urlencode "$BUDDY_EXECUTION_URL") - commit="$BUDDY_EXECUTION_REVISION" - pr="$BUDDY_EXECUTION_PULL_REQUEST_NO" - tag="$BUDDY_EXECUTION_TAG" - slug="$BUDDY_REPO_SLUG" - -elif [ "$CIRRUS_CI" != "" ]; -then - say "$e==>$x Cirrus CI detected." - # https://cirrus-ci.org/guide/writing-tasks/#environment-variables - service="cirrus-ci" - slug="$CIRRUS_REPO_FULL_NAME" - branch="$CIRRUS_BRANCH" - pr="$CIRRUS_PR" - commit="$CIRRUS_CHANGE_IN_REPO" - build="$CIRRUS_BUILD_ID" - build_url=$(urlencode "https://cirrus-ci.com/task/$CIRRUS_TASK_ID") - job="$CIRRUS_TASK_NAME" - -elif [ "$DOCKER_REPO" != "" ]; -then - say "$e==>$x Docker detected." - # https://docs.docker.com/docker-cloud/builds/advanced/ - service="docker" - branch="$SOURCE_BRANCH" - commit="$SOURCE_COMMIT" - slug="$DOCKER_REPO" - tag="$CACHE_TAG" - env="$env,IMAGE_NAME" - -else - say "${r}x>${x} No CI provider detected." - say " Testing inside Docker? ${b}http://docs.codecov.io/docs/testing-with-docker${x}" - say " Testing with Tox? ${b}https://docs.codecov.io/docs/python#section-testing-with-tox${x}" - -fi - -say " ${e}project root:${x} $git_root" - -# find branch, commit, repo from git command -if [ "$GIT_BRANCH" != "" ]; -then - branch="$GIT_BRANCH" - -elif [ "$branch" = "" ]; -then - branch=$(git rev-parse --abbrev-ref HEAD 2>/dev/null || hg branch 2>/dev/null || echo "") - if [ "$branch" = "HEAD" ]; - then - branch="" - fi -fi - -if [ "$commit_o" = "" ]; -then - if [ "$GIT_COMMIT" != "" ]; - then - commit="$GIT_COMMIT" - elif [ "$commit" = "" ]; - then - commit=$(git log -1 --format="%H" 2>/dev/null || hg id -i --debug 2>/dev/null | tr -d '+' || echo "") - fi -else - commit="$commit_o" -fi - -if [ "$CODECOV_TOKEN" != "" ] && [ "$token" = "" ]; -then - say "${e}-->${x} token set from env" - token="$CODECOV_TOKEN" -fi - -if [ "$CODECOV_URL" != "" ] && [ "$url_o" = "" ]; -then - say "${e}-->${x} url set from env" - url_o=$(echo "$CODECOV_URL" | sed -e 's/\/$//') -fi - -if [ "$CODECOV_SLUG" != "" ]; -then - say "${e}-->${x} slug set from env" - slug_o="$CODECOV_SLUG" - -elif [ "$slug" = "" ]; -then - if [ "$remote_addr" = "" ]; - then - remote_addr=$(git config --get remote.origin.url || hg paths default || echo '') - fi - if [ "$remote_addr" != "" ]; - then - if echo "$remote_addr" | grep -q "//"; then - # https - slug=$(echo "$remote_addr" | cut -d / -f 4,5 | sed -e 's/\.git$//') - else - # ssh - slug=$(echo "$remote_addr" | cut -d : -f 2 | sed -e 's/\.git$//') - fi - fi - if [ "$slug" = "/" ]; - then - slug="" - fi -fi - -yaml=$(cd "$git_root" && \ - git ls-files "*codecov.yml" "*codecov.yaml" 2>/dev/null \ - || hg locate "*codecov.yml" "*codecov.yaml" 2>/dev/null \ - || cd "$proj_root" && find . -maxdepth 1 -type f -name '*codecov.y*ml' 2>/dev/null \ - || echo '') -yaml=$(echo "$yaml" | head -1) - -if [ "$yaml" != "" ]; -then - say " ${e}Yaml found at:${x} $yaml" - if [[ "$yaml" != /* ]]; then - # relative path for yaml file given, assume relative to the repo root - yaml="$git_root/$yaml" - fi - config=$(parse_yaml "$yaml" || echo '') - - # TODO validate the yaml here - - if [ "$(echo "$config" | grep 'codecov_token="')" != "" ] && [ "$token" = "" ]; - then - say "${e}-->${x} token set from yaml" - token="$(echo "$config" | grep 'codecov_token="' | sed -e 's/codecov_token="//' | sed -e 's/"\.*//')" - fi - - if [ "$(echo "$config" | grep 'codecov_url="')" != "" ] && [ "$url_o" = "" ]; - then - say "${e}-->${x} url set from yaml" - url_o="$(echo "$config" | grep 'codecov_url="' | sed -e 's/codecov_url="//' | sed -e 's/"\.*//')" - fi - - if [ "$(echo "$config" | grep 'codecov_slug="')" != "" ] && [ "$slug_o" = "" ]; - then - say "${e}-->${x} slug set from yaml" - slug_o="$(echo "$config" | grep 'codecov_slug="' | sed -e 's/codecov_slug="//' | sed -e 's/"\.*//')" - fi -else - say " ${g}Yaml not found, that's ok! Learn more at${x} ${b}http://docs.codecov.io/docs/codecov-yaml${x}" -fi - -if [ "$branch_o" != "" ]; -then - branch=$(urlencode "$branch_o") -else - branch=$(urlencode "$branch") -fi - -if [ "$slug_o" = "" ]; -then - urlencoded_slug=$(urlencode "$slug") -else - urlencoded_slug=$(urlencode "$slug_o") -fi - -query="branch=$branch\ - &commit=$commit\ - &build=$([ "$build_o" = "" ] && echo "$build" || echo "$build_o")\ - &build_url=$build_url\ - &name=$(urlencode "$name")\ - &tag=$([ "$tag_o" = "" ] && echo "$tag" || echo "$tag_o")\ - &slug=$urlencoded_slug\ - &service=$service\ - &flags=$flags\ - &pr=$([ "$pr_o" = "" ] && echo "${pr##\#}" || echo "${pr_o##\#}")\ - &job=$job\ - &cmd_args=$(IFS=,; echo "${codecov_flags[*]}")" - -if [ -n "$project" ] && [ -n "$server_uri" ]; -then - query=$(echo "$query&project=$project&server_uri=$server_uri" | tr -d ' ') -fi - -if [ "$parent" != "" ]; -then - query=$(echo "parent=$parent&$query" | tr -d ' ') -fi - -if [ "$ft_search" = "1" ]; -then - # detect bower comoponents location - bower_components="bower_components" - bower_rc=$(cd "$git_root" && cat .bowerrc 2>/dev/null || echo "") - if [ "$bower_rc" != "" ]; - then - bower_components=$(echo "$bower_rc" | tr -d '\n' | grep '"directory"' | cut -d'"' -f4 | sed -e 's/\/$//') - if [ "$bower_components" = "" ]; - then - bower_components="bower_components" - fi - fi - - # Swift Coverage - if [ "$ft_xcodellvm" = "1" ] && [ -d "$ddp" ]; - then - say "${e}==>${x} Processing Xcode reports via llvm-cov" - say " DerivedData folder: $ddp" - profdata_files=$(find "$ddp" -name '*.profdata' 2>/dev/null || echo '') - if [ "$profdata_files" != "" ]; - then - # xcode via profdata - if [ "$xp" = "" ]; - then - # xp=$(xcodebuild -showBuildSettings 2>/dev/null | grep -i "^\s*PRODUCT_NAME" | sed -e 's/.*= \(.*\)/\1/') - # say " ${e}->${x} Speed up Xcode processing by adding ${e}-J '$xp'${x}" - say " ${g}hint${x} Speed up Swift processing by using use ${g}-J 'AppName'${x} (regexp accepted)" - say " ${g}hint${x} This will remove Pods/ from your report. Also ${b}https://docs.codecov.io/docs/ignoring-paths${x}" - fi - while read -r profdata; - do - if [ "$profdata" != "" ]; - then - swiftcov "$profdata" "$xp" - fi - done <<< "$profdata_files" - else - say " ${e}->${x} No Swift coverage found" - fi - - # Obj-C Gcov Coverage - if [ "$ft_gcov" = "1" ]; - then - say " ${e}->${x} Running $gcov_exe for Obj-C" - if [ "$ft_gcovout" = "0" ]; - then - # suppress gcov output - bash -c "find $ddp -type f -name '*.gcda' $gcov_include $gcov_ignore -exec $gcov_exe -p $gcov_arg {} +" >/dev/null 2>&1 || true - else - bash -c "find $ddp -type f -name '*.gcda' $gcov_include $gcov_ignore -exec $gcov_exe -p $gcov_arg {} +" || true - fi - fi - fi - - if [ "$ft_xcodeplist" = "1" ] && [ -d "$ddp" ]; - then - say "${e}==>${x} Processing Xcode plists" - plists_files=$(find "$ddp" -name '*.xccoverage' 2>/dev/null || echo '') - if [ "$plists_files" != "" ]; - then - while read -r plist; - do - if [ "$plist" != "" ]; - then - say " ${g}Found${x} plist file at $plist" - plutil -convert xml1 -o "$(basename "$plist").plist" -- "$plist" - fi - done <<< "$plists_files" - fi - fi - - # Gcov Coverage - if [ "$ft_gcov" = "1" ]; - then - say "${e}==>${x} Running $gcov_exe in $proj_root ${e}(disable via -X gcov)${x}" - if [ "$ft_gcovout" = "0" ]; - then - # suppress gcov output - bash -c "find $proj_root -type f -name '*.gcno' $gcov_include $gcov_ignore -exec $gcov_exe -pb $gcov_arg {} +" >/dev/null 2>&1 || true - else - bash -c "find $proj_root -type f -name '*.gcno' $gcov_include $gcov_ignore -exec $gcov_exe -pb $gcov_arg {} +" || true - fi - else - say "${e}==>${x} gcov disabled" - fi - - # Python Coverage - if [ "$ft_coveragepy" = "1" ]; - then - if [ ! -f coverage.xml ]; - then - if command -v coverage >/dev/null 2>&1; - then - say "${e}==>${x} Python coveragepy exists ${e}disable via -X coveragepy${x}" - - dotcoverage=$(find "$git_root" -name '.coverage' -or -name '.coverage.*' | head -1 || echo '') - if [ "$dotcoverage" != "" ]; - then - cd "$(dirname "$dotcoverage")" - if [ ! -f .coverage ]; - then - say " ${e}->${x} Running coverage combine" - coverage combine -a - fi - say " ${e}->${x} Running coverage xml" - if [ "$(coverage xml -i)" != "No data to report." ]; - then - files="$files -$PWD/coverage.xml" - else - say " ${r}No data to report.${x}" - fi - cd "$proj_root" - else - say " ${r}No .coverage file found.${x}" - fi - else - say "${e}==>${x} Python coveragepy not found" - fi - fi - else - say "${e}==>${x} Python coveragepy disabled" - fi - - if [ "$search_in_o" != "" ]; - then - # location override - search_in="$search_in_o" - fi - - say "$e==>$x Searching for coverage reports in:" - for _path in $search_in - do - say " ${g}+${x} $_path" - done - - patterns="find $search_in \( \ - -name vendor \ - -or -name '$bower_components' \ - -or -name '.egg-info*' \ - -or -name 'conftest_*.c.gcov' \ - -or -name .env \ - -or -name .envs \ - -or -name .git \ - -or -name .hg \ - -or -name .tox \ - -or -name .venv \ - -or -name .venvs \ - -or -name .virtualenv \ - -or -name .virtualenvs \ - -or -name .yarn-cache \ - -or -name __pycache__ \ - -or -name env \ - -or -name envs \ - -or -name htmlcov \ - -or -name js/generated/coverage \ - -or -name node_modules \ - -or -name venv \ - -or -name venvs \ - -or -name virtualenv \ - -or -name virtualenvs \ - \) -prune -or \ - -type f \( -name '*coverage*.*' \ - -or -name '*.clover' \ - -or -name '*.codecov.*' \ - -or -name '*.gcov' \ - -or -name '*.lcov' \ - -or -name '*.lst' \ - -or -name 'clover.xml' \ - -or -name 'cobertura.xml' \ - -or -name 'codecov.*' \ - -or -name 'cover.out' \ - -or -name 'codecov-result.json' \ - -or -name 'coverage-final.json' \ - -or -name 'excoveralls.json' \ - -or -name 'gcov.info' \ - -or -name 'jacoco*.xml' \ - -or -name '*Jacoco*.xml' \ - -or -name 'lcov.dat' \ - -or -name 'lcov.info' \ - -or -name 'luacov.report.out' \ - -or -name 'naxsi.info' \ - -or -name 'nosetests.xml' \ - -or -name 'report.xml' \ - $include_cov \) \ - $exclude_cov \ - -not -name '*.am' \ - -not -name '*.bash' \ - -not -name '*.bat' \ - -not -name '*.bw' \ - -not -name '*.cfg' \ - -not -name '*.class' \ - -not -name '*.cmake' \ - -not -name '*.cmake' \ - -not -name '*.conf' \ - -not -name '*.coverage' \ - -not -name '*.cp' \ - -not -name '*.cpp' \ - -not -name '*.crt' \ - -not -name '*.css' \ - -not -name '*.csv' \ - -not -name '*.csv' \ - -not -name '*.data' \ - -not -name '*.db' \ - -not -name '*.dox' \ - -not -name '*.ec' \ - -not -name '*.ec' \ - -not -name '*.egg' \ - -not -name '*.el' \ - -not -name '*.env' \ - -not -name '*.erb' \ - -not -name '*.exe' \ - -not -name '*.ftl' \ - -not -name '*.gif' \ - -not -name '*.gradle' \ - -not -name '*.gz' \ - -not -name '*.h' \ - -not -name '*.html' \ - -not -name '*.in' \ - -not -name '*.jade' \ - -not -name '*.jar*' \ - -not -name '*.jpeg' \ - -not -name '*.jpg' \ - -not -name '*.js' \ - -not -name '*.less' \ - -not -name '*.log' \ - -not -name '*.m4' \ - -not -name '*.mak*' \ - -not -name '*.md' \ - -not -name '*.o' \ - -not -name '*.p12' \ - -not -name '*.pem' \ - -not -name '*.png' \ - -not -name '*.pom*' \ - -not -name '*.profdata' \ - -not -name '*.proto' \ - -not -name '*.ps1' \ - -not -name '*.pth' \ - -not -name '*.py' \ - -not -name '*.pyc' \ - -not -name '*.pyo' \ - -not -name '*.rb' \ - -not -name '*.rsp' \ - -not -name '*.rst' \ - -not -name '*.ru' \ - -not -name '*.sbt' \ - -not -name '*.scss' \ - -not -name '*.scss' \ - -not -name '*.serialized' \ - -not -name '*.sh' \ - -not -name '*.snapshot' \ - -not -name '*.sql' \ - -not -name '*.svg' \ - -not -name '*.tar.tz' \ - -not -name '*.template' \ - -not -name '*.whl' \ - -not -name '*.xcconfig' \ - -not -name '*.xcoverage.*' \ - -not -name '*/classycle/report.xml' \ - -not -name '*codecov.yml' \ - -not -name '*~' \ - -not -name '.*coveragerc' \ - -not -name '.coverage*' \ - -not -name 'coverage-summary.json' \ - -not -name 'createdFiles.lst' \ - -not -name 'fullLocaleNames.lst' \ - -not -name 'include.lst' \ - -not -name 'inputFiles.lst' \ - -not -name 'phpunit-code-coverage.xml' \ - -not -name 'phpunit-coverage.xml' \ - -not -name 'remapInstanbul.coverage*.json' \ - -not -name 'scoverage.measurements.*' \ - -not -name 'test_*_coverage.txt' \ - -not -name 'testrunner-coverage*' \ - -print 2>/dev/null" - files=$(eval "$patterns" || echo '') - -elif [ "$include_cov" != "" ]; -then - files=$(eval "find $search_in -type f \( ${include_cov:5} \)$exclude_cov 2>/dev/null" || echo '') -elif [ "$direct_file_upload" != "" ]; -then - files=$direct_file_upload -fi - -num_of_files=$(echo "$files" | wc -l | tr -d ' ') -if [ "$num_of_files" != '' ] && [ "$files" != '' ]; -then - say " ${e}->${x} Found $num_of_files reports" -fi - -# no files found -if [ "$files" = "" ]; -then - say "${r}-->${x} No coverage report found." - say " Please visit ${b}http://docs.codecov.io/docs/supported-languages${x}" - exit ${exit_with}; -fi - -if [ "$ft_network" == "1" ]; -then - say "${e}==>${x} Detecting git/mercurial file structure" - network=$(cd "$git_root" && git ls-files $git_ls_files_recurse_submodules_o 2>/dev/null || hg locate 2>/dev/null || echo "") - if [ "$network" = "" ]; - then - network=$(find "$git_root" \( \ - -name virtualenv \ - -name .virtualenv \ - -name virtualenvs \ - -name .virtualenvs \ - -name '*.png' \ - -name '*.gif' \ - -name '*.jpg' \ - -name '*.jpeg' \ - -name '*.md' \ - -name .env \ - -name .envs \ - -name env \ - -name envs \ - -name .venv \ - -name .venvs \ - -name venv \ - -name venvs \ - -name .git \ - -name .egg-info \ - -name shunit2-2.1.6 \ - -name vendor \ - -name __pycache__ \ - -name node_modules \ - -path "*/$bower_components/*" \ - -path '*/target/delombok/*' \ - -path '*/build/lib/*' \ - -path '*/js/generated/coverage/*' \ - \) -prune -or \ - -type f -print 2>/dev/null || echo '') - fi - - if [ "$network_filter_o" != "" ]; - then - network=$(echo "$network" | grep -e "$network_filter_o/*") - fi - if [ "$prefix_o" != "" ]; - then - network=$(echo "$network" | awk "{print \"$prefix_o/\"\$0}") - fi -fi - -upload_file=$(mktemp /tmp/codecov.XXXXXX) -adjustments_file=$(mktemp /tmp/codecov.adjustments.XXXXXX) - -cleanup() { - rm -f "$upload_file" "$adjustments_file" "$upload_file.gz" -} - -trap cleanup INT ABRT TERM - - -if [ "$env" != "" ]; -then - inc_env="" - say "${e}==>${x} Appending build variables" - for varname in $(echo "$env" | tr ',' ' ') - do - if [ "$varname" != "" ]; - then - say " ${g}+${x} $varname" - inc_env="${inc_env}${varname}=$(eval echo "\$${varname}") -" - fi - done - echo "$inc_env<<<<<< ENV" >> "$upload_file" -fi - -# Append git file list -# write discovered yaml location -if [ "$direct_file_upload" = "" ]; -then - echo "$yaml" >> "$upload_file" -fi - -if [ "$ft_network" == "1" ]; -then - i="woff|eot|otf" # fonts - i="$i|gif|png|jpg|jpeg|psd" # images - i="$i|ptt|pptx|numbers|pages|md|txt|xlsx|docx|doc|pdf|csv" # docs - i="$i|.gitignore" # supporting docs - - if [ "$ft_html" != "1" ]; - then - i="$i|html" - fi - - if [ "$ft_yaml" != "1" ]; - then - i="$i|yml|yaml" - fi - - echo "$network" | grep -vwE "($i)$" >> "$upload_file" -fi -echo "<<<<<< network" >> "$upload_file" - -if [ "$direct_file_upload" = "" ]; -then - fr=0 - say "${e}==>${x} Reading reports" - while IFS='' read -r file; - do - # read the coverage file - if [ "$(echo "$file" | tr -d ' ')" != '' ]; - then - if [ -f "$file" ]; - then - report_len=$(wc -c < "$file") - if [ "$report_len" -ne 0 ]; - then - say " ${g}+${x} $file ${e}bytes=$(echo "$report_len" | tr -d ' ')${x}" - # append to to upload - _filename=$(basename "$file") - if [ "${_filename##*.}" = 'gcov' ]; - then - { - echo "# path=$(echo "$file.reduced" | sed "s|^$git_root/||")"; - # get file name - head -1 "$file"; - } >> "$upload_file" - # 1. remove source code - # 2. remove ending bracket lines - # 3. remove whitespace - # 4. remove contextual lines - # 5. remove function names - awk -F': *' '{print $1":"$2":"}' "$file" \ - | sed '\/: *} *$/d' \ - | sed 's/^ *//' \ - | sed '/^-/d' \ - | sed 's/^function.*/func/' >> "$upload_file" - else - { - echo "# path=${file//^$git_root/||}"; - cat "$file"; - } >> "$upload_file" - fi - echo "<<<<<< EOF" >> "$upload_file" - fr=1 - if [ "$clean" = "1" ]; - then - rm "$file" - fi - else - say " ${r}-${x} Skipping empty file $file" - fi - else - say " ${r}-${x} file not found at $file" - fi - fi - done <<< "$(echo -e "$files")" - - if [ "$fr" = "0" ]; - then - say "${r}-->${x} No coverage data found." - say " Please visit ${b}http://docs.codecov.io/docs/supported-languages${x}" - say " search for your projects language to learn how to collect reports." - exit ${exit_with}; - fi -else - cp "$direct_file_upload" "$upload_file" - if [ "$clean" = "1" ]; - then - rm "$direct_file_upload" - fi -fi - -if [ "$ft_fix" = "1" ]; -then - say "${e}==>${x} Appending adjustments" - say " ${b}https://docs.codecov.io/docs/fixing-reports${x}" - - empty_line='^[[:space:]]*$' - # // - syntax_comment='^[[:space:]]*//.*' - # /* or */ - syntax_comment_block='^[[:space:]]*(\/\*|\*\/)[[:space:]]*$' - # { or } - syntax_bracket='^[[:space:]]*[\{\}][[:space:]]*(//.*)?$' - # [ or ] - syntax_list='^[[:space:]]*[][][[:space:]]*(//.*)?$' - # func ... { - syntax_go_func='^[[:space:]]*[func].*[\{][[:space:]]*$' - - # shellcheck disable=SC2089 - skip_dirs="-not -path '*/$bower_components/*' \ - -not -path '*/node_modules/*'" - - cut_and_join() { - awk 'BEGIN { FS=":" } - $3 ~ /\/\*/ || $3 ~ /\*\// { print $0 ; next } - $1!=key { if (key!="") print out ; key=$1 ; out=$1":"$2 ; next } - { out=out","$2 } - END { print out }' 2>/dev/null - } - - if echo "$network" | grep -m1 '.kt$' 1>/dev/null; - then - # skip brackets and comments - cd "$git_root" && \ - find . -type f \ - -name '*.kt' \ - -exec \ - grep -nIHE -e "$syntax_bracket" \ - -e "$syntax_comment_block" {} \; \ - | cut_and_join \ - >> "$adjustments_file" \ - || echo '' - - # last line in file - cd "$git_root" && \ - find . -type f \ - -name '*.kt' -exec \ - wc -l {} \; \ - | while read -r l; do echo "EOF: $l"; done \ - 2>/dev/null \ - >> "$adjustments_file" \ - || echo '' - fi - - if echo "$network" | grep -m1 '.go$' 1>/dev/null; - then - # skip empty lines, comments, and brackets - cd "$git_root" && \ - find . -type f \ - -not -path '*/vendor/*' \ - -not -path '*/caches/*' \ - -name '*.go' \ - -exec \ - grep -nIHE \ - -e "$empty_line" \ - -e "$syntax_comment" \ - -e "$syntax_comment_block" \ - -e "$syntax_bracket" \ - -e "$syntax_go_func" \ - {} \; \ - | cut_and_join \ - >> "$adjustments_file" \ - || echo '' - fi - - if echo "$network" | grep -m1 '.dart$' 1>/dev/null; - then - # skip brackets - cd "$git_root" && \ - find . -type f \ - -name '*.dart' \ - -exec \ - grep -nIHE \ - -e "$syntax_bracket" \ - {} \; \ - | cut_and_join \ - >> "$adjustments_file" \ - || echo '' - fi - - if echo "$network" | grep -m1 '.php$' 1>/dev/null; - then - # skip empty lines, comments, and brackets - cd "$git_root" && \ - find . -type f \ - -not -path "*/vendor/*" \ - -name '*.php' \ - -exec \ - grep -nIHE \ - -e "$syntax_list" \ - -e "$syntax_bracket" \ - -e '^[[:space:]]*\);[[:space:]]*(//.*)?$' \ - {} \; \ - | cut_and_join \ - >> "$adjustments_file" \ - || echo '' - fi - - if echo "$network" | grep -m1 '\(.c\.cpp\|.cxx\|.h\|.hpp\|.m\|.swift\|.vala\)$' 1>/dev/null; - then - # skip brackets - # shellcheck disable=SC2086,SC2090 - cd "$git_root" && \ - find . -type f \ - $skip_dirs \ - \( \ - -name '*.c' \ - -or -name '*.cpp' \ - -or -name '*.cxx' \ - -or -name '*.h' \ - -or -name '*.hpp' \ - -or -name '*.m' \ - -or -name '*.swift' \ - -or -name '*.vala' \ - \) -exec \ - grep -nIHE \ - -e "$empty_line" \ - -e "$syntax_bracket" \ - -e '// LCOV_EXCL' \ - {} \; \ - | cut_and_join \ - >> "$adjustments_file" \ - || echo '' - - # skip brackets - # shellcheck disable=SC2086,SC2090 - cd "$git_root" && \ - find . -type f \ - $skip_dirs \ - \( \ - -name '*.c' \ - -or -name '*.cpp' \ - -or -name '*.cxx' \ - -or -name '*.h' \ - -or -name '*.hpp' \ - -or -name '*.m' \ - -or -name '*.swift' \ - -or -name '*.vala' \ - \) -exec \ - grep -nIH '// LCOV_EXCL' \ - {} \; \ - >> "$adjustments_file" \ - || echo '' - - fi - - found=$(< "$adjustments_file" tr -d ' ') - - if [ "$found" != "" ]; - then - say " ${g}+${x} Found adjustments" - { - echo "# path=fixes"; - cat "$adjustments_file"; - echo "<<<<<< EOF"; - } >> "$upload_file" - rm -rf "$adjustments_file" - else - say " ${e}->${x} No adjustments found" - fi -fi - -if [ "$url_o" != "" ]; -then - url="$url_o" -fi - -if [ "$dump" != "0" ]; -then - # trim whitespace from query - say " ${e}->${x} Dumping upload file (no upload)" - echo "$url/upload/v4?$(echo "package=$package-$VERSION&token=$token&$query" | tr -d ' ')" - cat "$upload_file" -else - if [ "$save_to" != "" ]; - then - say "${e}==>${x} Copying upload file to ${save_to}" - mkdir -p "$(dirname "$save_to")" - cp "$upload_file" "$save_to" - fi - - say "${e}==>${x} Gzipping contents" - gzip -nf9 "$upload_file" - say " $(du -h "$upload_file.gz")" - - query=$(echo "${query}" | tr -d ' ') - say "${e}==>${x} Uploading reports" - say " ${e}url:${x} $url" - say " ${e}query:${x} $query" - - # Full query without token (to display on terminal output) - queryNoToken=$(echo "package=$package-$VERSION&token=secret&$query" | tr -d ' ') - # now add token to query - query=$(echo "package=$package-$VERSION&token=$token&$query" | tr -d ' ') - - if [ "$ft_s3" = "1" ]; - then - say "${e}->${x} Pinging Codecov" - say "$url/upload/v4?$queryNoToken" - # shellcheck disable=SC2086,2090 - res=$(curl $curl_s -X POST $cacert \ - --retry 5 --retry-delay 2 --connect-timeout 2 \ - -H 'X-Reduced-Redundancy: false' \ - -H 'X-Content-Type: application/x-gzip' \ - -H 'Content-Length: 0' \ - --write-out "\n%{response_code}\n" \ - $curlargs \ - "$url/upload/v4?$query" || true) - # a good reply is "https://codecov.io" + "\n" + "https://storage.googleapis.com/codecov/..." - s3target=$(echo "$res" | sed -n 2p) - status=$(tail -n1 <<< "$res") - - if [ "$status" = "200" ] && [ "$s3target" != "" ]; - then - say "${e}->${x} Uploading to" - say "${s3target}" - - # shellcheck disable=SC2086 - s3=$(curl -fiX PUT \ - --data-binary @"$upload_file.gz" \ - -H 'Content-Type: application/x-gzip' \ - -H 'Content-Encoding: gzip' \ - $curlawsargs \ - "$s3target" || true) - - if [ "$s3" != "" ]; - then - say " ${g}->${x} Reports have been successfully queued for processing at ${b}$(echo "$res" | sed -n 1p)${x}" - exit 0 - else - say " ${r}X>${x} Failed to upload" - fi - elif [ "$status" = "400" ]; - then - # 400 Error - say "${r}${res}${x}" - exit ${exit_with} - else - say "${r}${res}${x}" - fi - fi - - say "${e}==>${x} Uploading to Codecov" - - # shellcheck disable=SC2086,2090 - res=$(curl -X POST $cacert \ - --data-binary @"$upload_file.gz" \ - --retry 5 --retry-delay 2 --connect-timeout 2 \ - -H 'Content-Type: text/plain' \ - -H 'Content-Encoding: gzip' \ - -H 'X-Content-Encoding: gzip' \ - -H 'Accept: text/plain' \ - $curlargs \ - "$url/upload/v2?$query&attempt=$i" || echo 'HTTP 500') - # {"message": "Coverage reports upload successfully", "uploaded": true, "queued": true, "id": "...", "url": "https://codecov.io/..."\} - uploaded=$(grep -o '\"uploaded\": [a-z]*' <<< "$res" | head -1 | cut -d' ' -f2) - if [ "$uploaded" = "true" ] - then - say " Reports have been successfully queued for processing at ${b}$(echo "$res" | head -2 | tail -1)${x}" - exit 0 - else - say " ${g}${res}${x}" - exit ${exit_with} - fi - - say " ${r}X> Failed to upload coverage reports${x}" -fi - -exit ${exit_with} diff --git a/scripts/travis/upload_coverage.sh b/scripts/travis/upload_coverage.sh deleted file mode 100755 index 8465d6ce1c..0000000000 --- a/scripts/travis/upload_coverage.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/usr/bin/env bash - -# Print a warning when there is a new version notification before uploading the -# coverage report to codecov. -set -eo pipefail - -# Check if there is a new version. -curl -fLso codecov https://codecov.io/bash -UPSTREAM_VERSION=$(grep -o 'VERSION=\"[0-9\.]*\"' codecov | cut -d'"' -f2) -LOCAL_VERSION=$(grep -o 'VERSION=\"[0-9\.]*\"' scripts/travis/codecov | cut -d'"' -f2) -if [[ "${UPSTREAM_VERSION}" != "${LOCAL_VERSION}" ]]; then - echo "WARN: version ${UPSTREAM_VERSION} of the codecov upload script is available." -fi - -/usr/bin/env bash scripts/travis/codecov "$@" From 694735bd7e5bc2c833f51826d2c6f503e9e396cf Mon Sep 17 00:00:00 2001 From: chris erway Date: Thu, 23 Jun 2022 20:40:08 -0400 Subject: [PATCH 12/22] Revert "use circleci orb for codecov upload, rename "nightly" flag" This reverts commit ee17187924977e2b17a9d11b804053eb441be21d. --- .circleci/config.yml | 31 +- scripts/travis/codecov | 1883 +++++++++++++++++++++++++++++ scripts/travis/upload_coverage.sh | 15 + 3 files changed, 1919 insertions(+), 10 deletions(-) create mode 100755 scripts/travis/codecov create mode 100755 scripts/travis/upload_coverage.sh diff --git a/.circleci/config.yml b/.circleci/config.yml index 435e2baa28..a7494135bc 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -4,7 +4,6 @@ orbs: win: circleci/windows@2.3.0 go: circleci/go@1.7.0 slack: circleci/slack@4.4.2 - codecov: codecov/codecov@3.1.1 parameters: ubuntu_image: @@ -295,8 +294,8 @@ commands: result_path: type: string default: << pipeline.parameters.result_path >> - full_coverage: - description: whether to provide a go test -coverpkg flag to measure coverage across all packages + use_coverpkg: + description: whether to provide a -coverpkg flag to go test type: boolean default: false steps: @@ -334,7 +333,7 @@ commands: export COVERPACKAGE_NAMES=$(echo $COVERPACKAGES | tr ' ' ',') export PARTITION_TOTAL=${CIRCLE_NODE_TOTAL} export PARTITION_ID=${CIRCLE_NODE_INDEX} - gotestsum --format standard-verbose --junitfile << parameters.result_path >>/<< parameters.result_subdir >>/${CIRCLE_NODE_INDEX}/results.xml --jsonfile << parameters.result_path >>/<< parameters.result_subdir >>/${CIRCLE_NODE_INDEX}/testresults.json -- --tags "sqlite_unlock_notify sqlite_omit_load_extension" << parameters.short_test_flag >> -race -timeout 1h -coverprofile=coverage.txt -covermode=atomic -p 1 $PACKAGE_NAMES <<# parameters.full_coverage >> -coverpkg=$COVERPACKAGE_NAMES <> + gotestsum --format standard-verbose --junitfile << parameters.result_path >>/<< parameters.result_subdir >>/${CIRCLE_NODE_INDEX}/results.xml --jsonfile << parameters.result_path >>/<< parameters.result_subdir >>/${CIRCLE_NODE_INDEX}/testresults.json -- --tags "sqlite_unlock_notify sqlite_omit_load_extension" << parameters.short_test_flag >> -race -timeout 1h -coverprofile=coverage.txt -covermode=atomic -p 1 $PACKAGE_NAMES <<# parameters.use_coverpkg >> -coverpkg=$COVERPACKAGE_NAMES <> - store_artifacts: path: << parameters.result_path >> destination: test-results @@ -345,6 +344,20 @@ commands: paths: - << parameters.result_subdir >> + upload_coverage: + description: Collect coverage reports and upload them + parameters: + args: + description: additional codecov arguments + type: string + default: "" + steps: + - run: + name: Upload Coverage Reports + no_output_timeout: 10m + command: | + scripts/travis/upload_coverage.sh << parameters.args >> || true + generic_integration: description: Run integration tests from build workspace, for re-use by diferent architectures parameters: @@ -495,8 +508,7 @@ jobs: platform: << parameters.platform >> result_subdir: << parameters.platform >>_test short_test_flag: "-short" - - codecov/upload: - validate: true + - upload_coverage test_nightly: parameters: @@ -512,10 +524,9 @@ jobs: platform: << parameters.platform >> result_subdir: << parameters.platform >>_test_nightly no_output_timeout: 45m - full_coverage: true - - codecov/upload: - validate: true - flags: "full_coverage" + use_coverpkg: true + - upload_coverage: + args: "-F nightly" - slack/notify: &slack-fail-event event: fail template: basic_fail_1 diff --git a/scripts/travis/codecov b/scripts/travis/codecov new file mode 100755 index 0000000000..d443a8979c --- /dev/null +++ b/scripts/travis/codecov @@ -0,0 +1,1883 @@ +#!/usr/bin/env bash + +# Apache License Version 2.0, January 2004 +# https://github.com/codecov/codecov-bash/blob/master/LICENSE + +set -e +o pipefail + +VERSION="1.0.3" + +codecov_flags=( ) +url="https://codecov.io" +env="$CODECOV_ENV" +service="" +token="" +search_in="" +# shellcheck disable=SC2153 +flags="$CODECOV_FLAGS" +exit_with=0 +curlargs="" +curlawsargs="" +dump="0" +clean="0" +curl_s="-s" +name="$CODECOV_NAME" +include_cov="" +exclude_cov="" +ddp="$HOME/Library/Developer/Xcode/DerivedData" +xp="" +files="" +save_to="" +direct_file_upload="" +cacert="$CODECOV_CA_BUNDLE" +gcov_ignore="-not -path './bower_components/**' -not -path './node_modules/**' -not -path './vendor/**'" +gcov_include="" + +ft_gcov="1" +ft_coveragepy="1" +ft_fix="1" +ft_search="1" +ft_s3="1" +ft_network="1" +ft_xcodellvm="1" +ft_xcodeplist="0" +ft_gcovout="1" +ft_html="0" +ft_yaml="0" + +_git_root=$(git rev-parse --show-toplevel 2>/dev/null || hg root 2>/dev/null || echo "$PWD") +git_root="$_git_root" +remote_addr="" +if [ "$git_root" = "$PWD" ]; +then + git_root="." +fi + +branch_o="" +build_o="" +commit_o="" +pr_o="" +prefix_o="" +network_filter_o="" +search_in_o="" +slug_o="" +tag_o="" +url_o="" +git_ls_files_recurse_submodules_o="" +package="bash" + +commit="$VCS_COMMIT_ID" +branch="$VCS_BRANCH_NAME" +pr="$VCS_PULL_REQUEST" +slug="$VCS_SLUG" +tag="$VCS_TAG" +build_url="$CI_BUILD_URL" +build="$CI_BUILD_ID" +job="$CI_JOB_ID" + +beta_xcode_partials="" + +proj_root="$git_root" +gcov_exe="gcov" +gcov_arg="" + +b="\033[0;36m" +g="\033[0;32m" +r="\033[0;31m" +e="\033[0;90m" +y="\033[0;33m" +x="\033[0m" + +show_help() { +cat << EOF + + Codecov Bash $VERSION + + Global report uploading tool for Codecov + Documentation at https://docs.codecov.io/docs + Contribute at https://github.com/codecov/codecov-bash + + + -h Display this help and exit + -f FILE Target file(s) to upload + + -f "path/to/file" only upload this file + skips searching unless provided patterns below + + -f '!*.bar' ignore all files at pattern *.bar + -f '*.foo' include all files at pattern *.foo + Must use single quotes. + This is non-exclusive, use -s "*.foo" to match specific paths. + + -s DIR Directory to search for coverage reports. + Already searches project root and artifact folders. + -t TOKEN Set the private repository token + (option) set environment variable CODECOV_TOKEN=:uuid + + -t @/path/to/token_file + -t uuid + + -n NAME Custom defined name of the upload. Visible in Codecov UI + + -e ENV Specify environment variables to be included with this build + Also accepting environment variables: CODECOV_ENV=VAR,VAR2 + + -e VAR,VAR2 + + -k prefix Prefix filepaths to help resolve path fixing + + -i prefix Only include files in the network with a certain prefix. Useful for upload-specific path fixing + + -X feature Toggle functionalities + + -X gcov Disable gcov + -X coveragepy Disable python coverage + -X fix Disable report fixing + -X search Disable searching for reports + -X xcode Disable xcode processing + -X network Disable uploading the file network + -X gcovout Disable gcov output + -X html Enable coverage for HTML files + -X recursesubs Enable recurse submodules in git projects when searching for source files + -X yaml Enable coverage for YAML files + + -N The commit SHA of the parent for which you are uploading coverage. If not present, + the parent will be determined using the API of your repository provider. + When using the repository provider's API, the parent is determined via finding + the closest ancestor to the commit. + + -R root dir Used when not in git/hg project to identify project root directory + -F flag Flag the upload to group coverage metrics + + -F unittests This upload is only unittests + -F integration This upload is only integration tests + -F ui,chrome This upload is Chrome - UI tests + + -c Move discovered coverage reports to the trash + -z FILE Upload specified file directly to Codecov and bypass all report generation. + This is inteded to be used only with a pre-formatted Codecov report and is not + expected to work under any other circumstances. + -Z Exit with 1 if not successful. Default will Exit with 0 + + -- xcode -- + -D Custom Derived Data Path for Coverage.profdata and gcov processing + Default '~/Library/Developer/Xcode/DerivedData' + -J Specify packages to build coverage. Uploader will only build these packages. + This can significantly reduces time to build coverage reports. + + -J 'MyAppName' Will match "MyAppName" and "MyAppNameTests" + -J '^ExampleApp$' Will match only "ExampleApp" not "ExampleAppTests" + + -- gcov -- + -g GLOB Paths to ignore during gcov gathering + -G GLOB Paths to include during gcov gathering + -p dir Project root directory + Also used when preparing gcov + -x gcovexe gcov executable to run. Defaults to 'gcov' + -a gcovargs extra arguments to pass to gcov + + -- Override CI Environment Variables -- + These variables are automatically detected by popular CI providers + + -B branch Specify the branch name + -C sha Specify the commit sha + -P pr Specify the pull request number + -b build Specify the build number + -T tag Specify the git tag + + -- Enterprise -- + -u URL Set the target url for Enterprise customers + Not required when retrieving the bash uploader from your CCE + (option) Set environment variable CODECOV_URL=https://my-hosted-codecov.com + -r SLUG owner/repo slug used instead of the private repo token in Enterprise + (option) set environment variable CODECOV_SLUG=:owner/:repo + (option) set in your codecov.yml "codecov.slug" + -S PATH File path to your cacert.pem file used to verify ssl with Codecov Enterprise (optional) + (option) Set environment variable: CODECOV_CA_BUNDLE="/path/to/ca.pem" + -U curlargs Extra curl arguments to communicate with Codecov. e.g., -U "--proxy http://http-proxy" + -A curlargs Extra curl arguments to communicate with AWS. + + -- Debugging -- + -d Don't upload, but dump upload file to stdout + -q PATH Write upload file to path + -K Remove color from the output + -v Verbose mode + +EOF +} + + +say() { + echo -e "$1" +} + + +urlencode() { + echo "$1" | curl -Gso /dev/null -w "%{url_effective}" --data-urlencode @- "" | cut -c 3- | sed -e 's/%0A//' +} + +swiftcov() { + _dir=$(dirname "$1" | sed 's/\(Build\).*/\1/g') + for _type in app framework xctest + do + find "$_dir" -name "*.$_type" | while read -r f + do + _proj=${f##*/} + _proj=${_proj%."$_type"} + if [ "$2" = "" ] || [ "$(echo "$_proj" | grep -i "$2")" != "" ]; + then + say " $g+$x Building reports for $_proj $_type" + dest=$([ -f "$f/$_proj" ] && echo "$f/$_proj" || echo "$f/Contents/MacOS/$_proj") + # shellcheck disable=SC2001 + _proj_name=$(echo "$_proj" | sed -e 's/[[:space:]]//g') + # shellcheck disable=SC2086 + xcrun llvm-cov show $beta_xcode_partials -instr-profile "$1" "$dest" > "$_proj_name.$_type.coverage.txt" \ + || say " ${r}x>${x} llvm-cov failed to produce results for $dest" + fi + done + done +} + + +# Credits to: https://gist.github.com/pkuczynski/8665367 +parse_yaml() { + local prefix=$2 + local s='[[:space:]]*' w='[a-zA-Z0-9_]*' + local fs + fs=$(echo @|tr @ '\034') + sed -ne "s|^\($s\)\($w\)$s:$s\"\(.*\)\"$s\$|\1$fs\2$fs\3|p" \ + -e "s|^\($s\)\($w\)$s:$s\(.*\)$s\$|\1$fs\2$fs\3|p" "$1" | + awk -F"$fs" '{ + indent = length($1)/2; + vname[indent] = $2; + for (i in vname) {if (i > indent) {delete vname[i]}} + if (length($3) > 0) { + vn=""; if (indent > 0) {vn=(vn)(vname[0])("_")} + printf("%s%s%s=\"%s\"\n", "'"$prefix"'",vn, $2, $3); + } + }' +} + +if [ $# != 0 ]; +then + while getopts "a:A:b:B:cC:dD:e:f:F:g:G:hi:J:k:Kn:p:P:Q:q:r:R:s:S:t:T:u:U:vx:X:Zz:N:-" o + do + codecov_flags+=( "$o" ) + case "$o" in + "-") + echo -e "${r}Long options are not supported${x}" + exit 2 + ;; + "?") + ;; + "N") + parent=$OPTARG + ;; + "a") + gcov_arg=$OPTARG + ;; + "A") + curlawsargs="$OPTARG" + ;; + "b") + build_o="$OPTARG" + ;; + "B") + branch_o="$OPTARG" + ;; + "c") + clean="1" + ;; + "C") + commit_o="$OPTARG" + ;; + "d") + dump="1" + ;; + "D") + ddp="$OPTARG" + ;; + "e") + env="$env,$OPTARG" + ;; + "f") + if [ "${OPTARG::1}" = "!" ]; + then + exclude_cov="$exclude_cov -not -path '${OPTARG:1}'" + + elif [[ "$OPTARG" = *"*"* ]]; + then + include_cov="$include_cov -or -path '$OPTARG'" + + else + ft_search=0 + if [ "$files" = "" ]; + then + files="$OPTARG" + else + files="$files +$OPTARG" + fi + fi + ;; + "F") + if [ "$flags" = "" ]; + then + flags="$OPTARG" + else + flags="$flags,$OPTARG" + fi + ;; + "g") + gcov_ignore="$gcov_ignore -not -path '$OPTARG'" + ;; + "G") + gcov_include="$gcov_include -path '$OPTARG'" + ;; + "h") + show_help + exit 0; + ;; + "i") + network_filter_o="$OPTARG" + ;; + "J") + ft_xcodellvm="1" + ft_xcodeplist="0" + if [ "$xp" = "" ]; + then + xp="$OPTARG" + else + xp="$xp\|$OPTARG" + fi + ;; + "k") + prefix_o=$(echo "$OPTARG" | sed -e 's:^/*::' -e 's:/*$::') + ;; + "K") + b="" + g="" + r="" + e="" + x="" + ;; + "n") + name="$OPTARG" + ;; + "p") + proj_root="$OPTARG" + ;; + "P") + pr_o="$OPTARG" + ;; + "Q") + # this is only meant for Codecov packages to overwrite + package="$OPTARG" + ;; + "q") + save_to="$OPTARG" + ;; + "r") + slug_o="$OPTARG" + ;; + "R") + git_root="$OPTARG" + ;; + "s") + if [ "$search_in_o" = "" ]; + then + search_in_o="$OPTARG" + else + search_in_o="$search_in_o $OPTARG" + fi + ;; + "S") + # shellcheck disable=SC2089 + cacert="--cacert \"$OPTARG\"" + ;; + "t") + if [ "${OPTARG::1}" = "@" ]; + then + token=$(< "${OPTARG:1}" tr -d ' \n') + else + token="$OPTARG" + fi + ;; + "T") + tag_o="$OPTARG" + ;; + "u") + url_o=$(echo "$OPTARG" | sed -e 's/\/$//') + ;; + "U") + curlargs="$OPTARG" + ;; + "v") + set -x + curl_s="" + ;; + "x") + gcov_exe=$OPTARG + ;; + "X") + if [ "$OPTARG" = "gcov" ]; + then + ft_gcov="0" + elif [ "$OPTARG" = "coveragepy" ] || [ "$OPTARG" = "py" ]; + then + ft_coveragepy="0" + elif [ "$OPTARG" = "gcovout" ]; + then + ft_gcovout="0" + elif [ "$OPTARG" = "xcodellvm" ]; + then + ft_xcodellvm="1" + ft_xcodeplist="0" + elif [ "$OPTARG" = "fix" ] || [ "$OPTARG" = "fixes" ]; + then + ft_fix="0" + elif [ "$OPTARG" = "xcode" ]; + then + ft_xcodellvm="0" + ft_xcodeplist="0" + elif [ "$OPTARG" = "search" ]; + then + ft_search="0" + elif [ "$OPTARG" = "xcodepartials" ]; + then + beta_xcode_partials="-use-color" + elif [ "$OPTARG" = "network" ]; + then + ft_network="0" + elif [ "$OPTARG" = "s3" ]; + then + ft_s3="0" + elif [ "$OPTARG" = "html" ]; + then + ft_html="1" + elif [ "$OPTARG" = "recursesubs" ]; + then + git_ls_files_recurse_submodules_o="--recurse-submodules" + elif [ "$OPTARG" = "yaml" ]; + then + ft_yaml="1" + fi + ;; + "Z") + exit_with=1 + ;; + "z") + direct_file_upload="$OPTARG" + ft_gcov="0" + ft_coveragepy="0" + ft_fix="0" + ft_search="0" + ft_network="0" + ft_xcodellvm="0" + ft_gcovout="0" + include_cov="" + ;; + *) + echo -e "${r}Unexpected flag not supported${x}" + ;; + esac + done +fi + +say " + _____ _ + / ____| | | +| | ___ __| | ___ ___ _____ __ +| | / _ \\ / _\` |/ _ \\/ __/ _ \\ \\ / / +| |___| (_) | (_| | __/ (_| (_) \\ V / + \\_____\\___/ \\__,_|\\___|\\___\\___/ \\_/ + Bash-$VERSION + +" + +# check for installed tools +# git/hg +if [ "$direct_file_upload" = "" ]; +then + if [ -x "$(command -v git)" ]; + then + say "$b==>$x $(git --version) found" + else + say "$y==>$x git not installed, testing for mercurial" + if [ -x "$(command -v hg)" ]; + then + say "$b==>$x $(hg --version) found" + else + say "$r==>$x git nor mercurial are installed. Uploader may fail or have unintended consequences" + fi + fi +fi +# curl +if [ -x "$(command -v curl)" ]; +then + say "$b==>$x $(curl --version)" +else + say "$r==>$x curl not installed. Exiting." + exit ${exit_with}; +fi + +search_in="$proj_root" + +#shellcheck disable=SC2154 +if [ "$JENKINS_URL" != "" ]; +then + say "$e==>$x Jenkins CI detected." + # https://wiki.jenkins-ci.org/display/JENKINS/Building+a+software+project + # https://wiki.jenkins-ci.org/display/JENKINS/GitHub+pull+request+builder+plugin#GitHubpullrequestbuilderplugin-EnvironmentVariables + service="jenkins" + + # shellcheck disable=SC2154 + if [ "$ghprbSourceBranch" != "" ]; + then + branch="$ghprbSourceBranch" + elif [ "$GIT_BRANCH" != "" ]; + then + branch="$GIT_BRANCH" + elif [ "$BRANCH_NAME" != "" ]; + then + branch="$BRANCH_NAME" + fi + + # shellcheck disable=SC2154 + if [ "$ghprbActualCommit" != "" ]; + then + commit="$ghprbActualCommit" + elif [ "$GIT_COMMIT" != "" ]; + then + commit="$GIT_COMMIT" + fi + + # shellcheck disable=SC2154 + if [ "$ghprbPullId" != "" ]; + then + pr="$ghprbPullId" + elif [ "$CHANGE_ID" != "" ]; + then + pr="$CHANGE_ID" + fi + + build="$BUILD_NUMBER" + # shellcheck disable=SC2153 + build_url=$(urlencode "$BUILD_URL") + +elif [ "$CI" = "true" ] && [ "$TRAVIS" = "true" ] && [ "$SHIPPABLE" != "true" ]; +then + say "$e==>$x Travis CI detected." + # https://docs.travis-ci.com/user/environment-variables/ + service="travis" + commit="${TRAVIS_PULL_REQUEST_SHA:-$TRAVIS_COMMIT}" + build="$TRAVIS_JOB_NUMBER" + pr="$TRAVIS_PULL_REQUEST" + job="$TRAVIS_JOB_ID" + slug="$TRAVIS_REPO_SLUG" + env="$env,TRAVIS_OS_NAME" + tag="$TRAVIS_TAG" + if [ "$TRAVIS_BRANCH" != "$TRAVIS_TAG" ]; + then + branch="${TRAVIS_PULL_REQUEST_BRANCH:-$TRAVIS_BRANCH}" + fi + + language=$(compgen -A variable | grep "^TRAVIS_.*_VERSION$" | head -1) + if [ "$language" != "" ]; + then + env="$env,${!language}" + fi + +elif [ "$CODEBUILD_CI" = "true" ]; +then + say "$e==>$x AWS Codebuild detected." + # https://docs.aws.amazon.com/codebuild/latest/userguide/build-env-ref-env-vars.html + service="codebuild" + commit="$CODEBUILD_RESOLVED_SOURCE_VERSION" + build="$CODEBUILD_BUILD_ID" + branch="$(echo "$CODEBUILD_WEBHOOK_HEAD_REF" | sed 's/^refs\/heads\///')" + if [ "${CODEBUILD_SOURCE_VERSION/pr}" = "$CODEBUILD_SOURCE_VERSION" ] ; then + pr="false" + else + pr="$(echo "$CODEBUILD_SOURCE_VERSION" | sed 's/^pr\///')" + fi + job="$CODEBUILD_BUILD_ID" + slug="$(echo "$CODEBUILD_SOURCE_REPO_URL" | sed 's/^.*:\/\/[^\/]*\///' | sed 's/\.git$//')" + +elif [ "$CI" = "true" ] && [ "$CI_NAME" = "codeship" ]; +then + say "$e==>$x Codeship CI detected." + # https://www.codeship.io/documentation/continuous-integration/set-environment-variables/ + service="codeship" + branch="$CI_BRANCH" + build="$CI_BUILD_NUMBER" + build_url=$(urlencode "$CI_BUILD_URL") + commit="$CI_COMMIT_ID" + +elif [ -n "$CF_BUILD_URL" ] && [ -n "$CF_BUILD_ID" ]; +then + say "$e==>$x Codefresh CI detected." + # https://docs.codefresh.io/v1.0/docs/variables + service="codefresh" + branch="$CF_BRANCH" + build="$CF_BUILD_ID" + build_url=$(urlencode "$CF_BUILD_URL") + commit="$CF_REVISION" + +elif [ "$TEAMCITY_VERSION" != "" ]; +then + say "$e==>$x TeamCity CI detected." + # https://confluence.jetbrains.com/display/TCD8/Predefined+Build+Parameters + # https://confluence.jetbrains.com/plugins/servlet/mobile#content/view/74847298 + if [ "$TEAMCITY_BUILD_BRANCH" = '' ]; + then + echo " Teamcity does not automatically make build parameters available as environment variables." + echo " Add the following environment parameters to the build configuration" + echo " env.TEAMCITY_BUILD_BRANCH = %teamcity.build.branch%" + echo " env.TEAMCITY_BUILD_ID = %teamcity.build.id%" + echo " env.TEAMCITY_BUILD_URL = %teamcity.serverUrl%/viewLog.html?buildId=%teamcity.build.id%" + echo " env.TEAMCITY_BUILD_COMMIT = %system.build.vcs.number%" + echo " env.TEAMCITY_BUILD_REPOSITORY = %vcsroot..url%" + fi + service="teamcity" + branch="$TEAMCITY_BUILD_BRANCH" + build="$TEAMCITY_BUILD_ID" + build_url=$(urlencode "$TEAMCITY_BUILD_URL") + if [ "$TEAMCITY_BUILD_COMMIT" != "" ]; + then + commit="$TEAMCITY_BUILD_COMMIT" + else + commit="$BUILD_VCS_NUMBER" + fi + remote_addr="$TEAMCITY_BUILD_REPOSITORY" + +elif [ "$CI" = "true" ] && [ "$CIRCLECI" = "true" ]; +then + say "$e==>$x Circle CI detected." + # https://circleci.com/docs/environment-variables + service="circleci" + branch="$CIRCLE_BRANCH" + build="$CIRCLE_BUILD_NUM" + job="$CIRCLE_NODE_INDEX" + if [ "$CIRCLE_PROJECT_REPONAME" != "" ]; + then + slug="$CIRCLE_PROJECT_USERNAME/$CIRCLE_PROJECT_REPONAME" + else + # git@github.com:owner/repo.git + slug="${CIRCLE_REPOSITORY_URL##*:}" + # owner/repo.git + slug="${slug%%.git}" + fi + pr="${CIRCLE_PULL_REQUEST##*/}" + commit="$CIRCLE_SHA1" + search_in="$search_in $CIRCLE_ARTIFACTS $CIRCLE_TEST_REPORTS" + +elif [ "$BUDDYBUILD_BRANCH" != "" ]; +then + say "$e==>$x buddybuild detected" + # http://docs.buddybuild.com/v6/docs/custom-prebuild-and-postbuild-steps + service="buddybuild" + branch="$BUDDYBUILD_BRANCH" + build="$BUDDYBUILD_BUILD_NUMBER" + build_url="https://dashboard.buddybuild.com/public/apps/$BUDDYBUILD_APP_ID/build/$BUDDYBUILD_BUILD_ID" + # BUDDYBUILD_TRIGGERED_BY + if [ "$ddp" = "$HOME/Library/Developer/Xcode/DerivedData" ]; + then + ddp="/private/tmp/sandbox/${BUDDYBUILD_APP_ID}/bbtest" + fi + +elif [ "${bamboo_planRepository_revision}" != "" ]; +then + say "$e==>$x Bamboo detected" + # https://confluence.atlassian.com/bamboo/bamboo-variables-289277087.html#Bamboovariables-Build-specificvariables + service="bamboo" + commit="${bamboo_planRepository_revision}" + # shellcheck disable=SC2154 + branch="${bamboo_planRepository_branch}" + # shellcheck disable=SC2154 + build="${bamboo_buildNumber}" + # shellcheck disable=SC2154 + build_url="${bamboo_buildResultsUrl}" + # shellcheck disable=SC2154 + remote_addr="${bamboo_planRepository_repositoryUrl}" + +elif [ "$CI" = "true" ] && [ "$BITRISE_IO" = "true" ]; +then + # http://devcenter.bitrise.io/faq/available-environment-variables/ + say "$e==>$x Bitrise CI detected." + service="bitrise" + branch="$BITRISE_GIT_BRANCH" + build="$BITRISE_BUILD_NUMBER" + build_url=$(urlencode "$BITRISE_BUILD_URL") + pr="$BITRISE_PULL_REQUEST" + if [ "$GIT_CLONE_COMMIT_HASH" != "" ]; + then + commit="$GIT_CLONE_COMMIT_HASH" + fi + +elif [ "$CI" = "true" ] && [ "$SEMAPHORE" = "true" ]; +then + say "$e==>$x Semaphore CI detected." +# https://docs.semaphoreci.com/ci-cd-environment/environment-variables/#semaphore-related + service="semaphore" + branch="$SEMAPHORE_GIT_BRANCH" + build="$SEMAPHORE_WORKFLOW_NUMBER" + job="$SEMAPHORE_JOB_ID" + pr="$PULL_REQUEST_NUMBER" + slug="$SEMAPHORE_REPO_SLUG" + commit="$REVISION" + env="$env,SEMAPHORE_TRIGGER_SOURCE" + +elif [ "$CI" = "true" ] && [ "$BUILDKITE" = "true" ]; +then + say "$e==>$x Buildkite CI detected." + # https://buildkite.com/docs/guides/environment-variables + service="buildkite" + branch="$BUILDKITE_BRANCH" + build="$BUILDKITE_BUILD_NUMBER" + job="$BUILDKITE_JOB_ID" + build_url=$(urlencode "$BUILDKITE_BUILD_URL") + slug="$BUILDKITE_PROJECT_SLUG" + commit="$BUILDKITE_COMMIT" + if [[ "$BUILDKITE_PULL_REQUEST" != "false" ]]; then + pr="$BUILDKITE_PULL_REQUEST" + fi + tag="$BUILDKITE_TAG" + +elif [ "$CI" = "drone" ] || [ "$DRONE" = "true" ]; +then + say "$e==>$x Drone CI detected." + # http://docs.drone.io/env.html + # drone commits are not full shas + service="drone.io" + branch="$DRONE_BRANCH" + build="$DRONE_BUILD_NUMBER" + build_url=$(urlencode "${DRONE_BUILD_LINK}") + pr="$DRONE_PULL_REQUEST" + job="$DRONE_JOB_NUMBER" + tag="$DRONE_TAG" + +elif [ "$CI" = "true" ] && [ "$HEROKU_TEST_RUN_BRANCH" != "" ]; +then + say "$e==>$x Heroku CI detected." + # https://devcenter.heroku.com/articles/heroku-ci#environment-variables + service="heroku" + branch="$HEROKU_TEST_RUN_BRANCH" + build="$HEROKU_TEST_RUN_ID" + commit="$HEROKU_TEST_RUN_COMMIT_VERSION" + +elif [[ "$CI" = "true" || "$CI" = "True" ]] && [[ "$APPVEYOR" = "true" || "$APPVEYOR" = "True" ]]; +then + say "$e==>$x Appveyor CI detected." + # http://www.appveyor.com/docs/environment-variables + service="appveyor" + branch="$APPVEYOR_REPO_BRANCH" + build=$(urlencode "$APPVEYOR_JOB_ID") + pr="$APPVEYOR_PULL_REQUEST_NUMBER" + job="$APPVEYOR_ACCOUNT_NAME%2F$APPVEYOR_PROJECT_SLUG%2F$APPVEYOR_BUILD_VERSION" + slug="$APPVEYOR_REPO_NAME" + commit="$APPVEYOR_REPO_COMMIT" + build_url=$(urlencode "${APPVEYOR_URL}/project/${APPVEYOR_REPO_NAME}/builds/$APPVEYOR_BUILD_ID/job/${APPVEYOR_JOB_ID}") + +elif [ "$CI" = "true" ] && [ "$WERCKER_GIT_BRANCH" != "" ]; +then + say "$e==>$x Wercker CI detected." + # http://devcenter.wercker.com/articles/steps/variables.html + service="wercker" + branch="$WERCKER_GIT_BRANCH" + build="$WERCKER_MAIN_PIPELINE_STARTED" + slug="$WERCKER_GIT_OWNER/$WERCKER_GIT_REPOSITORY" + commit="$WERCKER_GIT_COMMIT" + +elif [ "$CI" = "true" ] && [ "$MAGNUM" = "true" ]; +then + say "$e==>$x Magnum CI detected." + # https://magnum-ci.com/docs/environment + service="magnum" + branch="$CI_BRANCH" + build="$CI_BUILD_NUMBER" + commit="$CI_COMMIT" + +elif [ "$SHIPPABLE" = "true" ]; +then + say "$e==>$x Shippable CI detected." + # http://docs.shippable.com/ci_configure/ + service="shippable" + # shellcheck disable=SC2153 + branch=$([ "$HEAD_BRANCH" != "" ] && echo "$HEAD_BRANCH" || echo "$BRANCH") + build="$BUILD_NUMBER" + build_url=$(urlencode "$BUILD_URL") + pr="$PULL_REQUEST" + slug="$REPO_FULL_NAME" + # shellcheck disable=SC2153 + commit="$COMMIT" + +elif [ "$TDDIUM" = "true" ]; +then + say "Solano CI detected." + # http://docs.solanolabs.com/Setup/tddium-set-environment-variables/ + service="solano" + commit="$TDDIUM_CURRENT_COMMIT" + branch="$TDDIUM_CURRENT_BRANCH" + build="$TDDIUM_TID" + pr="$TDDIUM_PR_ID" + +elif [ "$GREENHOUSE" = "true" ]; +then + say "$e==>$x Greenhouse CI detected." + # http://docs.greenhouseci.com/docs/environment-variables-files + service="greenhouse" + branch="$GREENHOUSE_BRANCH" + build="$GREENHOUSE_BUILD_NUMBER" + build_url=$(urlencode "$GREENHOUSE_BUILD_URL") + pr="$GREENHOUSE_PULL_REQUEST" + commit="$GREENHOUSE_COMMIT" + search_in="$search_in $GREENHOUSE_EXPORT_DIR" + +elif [ "$GITLAB_CI" != "" ]; +then + say "$e==>$x GitLab CI detected." + # http://doc.gitlab.com/ce/ci/variables/README.html + service="gitlab" + branch="${CI_BUILD_REF_NAME:-$CI_COMMIT_REF_NAME}" + build="${CI_BUILD_ID:-$CI_JOB_ID}" + remote_addr="${CI_BUILD_REPO:-$CI_REPOSITORY_URL}" + commit="${CI_BUILD_REF:-$CI_COMMIT_SHA}" + slug="${CI_PROJECT_PATH}" + +elif [ "$GITHUB_ACTIONS" != "" ]; +then + say "$e==>$x GitHub Actions detected." + say " Env vars used:" + say " -> GITHUB_ACTIONS: ${GITHUB_ACTIONS}" + say " -> GITHUB_HEAD_REF: ${GITHUB_HEAD_REF}" + say " -> GITHUB_REF: ${GITHUB_REF}" + say " -> GITHUB_REPOSITORY: ${GITHUB_REPOSITORY}" + say " -> GITHUB_RUN_ID: ${GITHUB_RUN_ID}" + say " -> GITHUB_SHA: ${GITHUB_SHA}" + say " -> GITHUB_WORKFLOW: ${GITHUB_WORKFLOW}" + + # https://github.com/features/actions + service="github-actions" + + # https://help.github.com/en/articles/virtual-environments-for-github-actions#environment-variables + branch="${GITHUB_REF#refs/heads/}" + if [ "$GITHUB_HEAD_REF" != "" ]; + then + # PR refs are in the format: refs/pull/7/merge + pr="${GITHUB_REF#refs/pull/}" + pr="${pr%/merge}" + branch="${GITHUB_HEAD_REF}" + fi + commit="${GITHUB_SHA}" + slug="${GITHUB_REPOSITORY}" + build="${GITHUB_RUN_ID}" + build_url=$(urlencode "http://github.com/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}") + job="$(urlencode "${GITHUB_WORKFLOW}")" + + # actions/checkout runs in detached HEAD + mc= + if [ -n "$pr" ] && [ "$pr" != false ] && [ "$commit_o" == "" ]; + then + mc=$(git show --no-patch --format="%P" 2>/dev/null || echo "") + + if [[ "$mc" =~ ^[a-z0-9]{40}[[:space:]][a-z0-9]{40}$ ]]; + then + mc=$(echo "$mc" | cut -d' ' -f2) + say " Fixing merge commit SHA $commit -> $mc" + commit=$mc + elif [[ "$mc" = "" ]]; + then + say "$r-> Issue detecting commit SHA. Please run actions/checkout with fetch-depth > 1 or set to 0$x" + fi + fi + +elif [ "$SYSTEM_TEAMFOUNDATIONSERVERURI" != "" ]; +then + say "$e==>$x Azure Pipelines detected." + # https://docs.microsoft.com/en-us/azure/devops/pipelines/build/variables?view=vsts + # https://docs.microsoft.com/en-us/azure/devops/pipelines/build/variables?view=azure-devops&viewFallbackFrom=vsts&tabs=yaml + service="azure_pipelines" + commit="$BUILD_SOURCEVERSION" + build="$BUILD_BUILDNUMBER" + if [ -z "$SYSTEM_PULLREQUEST_PULLREQUESTNUMBER" ]; + then + pr="$SYSTEM_PULLREQUEST_PULLREQUESTID" + else + pr="$SYSTEM_PULLREQUEST_PULLREQUESTNUMBER" + fi + project="${SYSTEM_TEAMPROJECT}" + server_uri="${SYSTEM_TEAMFOUNDATIONSERVERURI}" + job="${BUILD_BUILDID}" + branch="${BUILD_SOURCEBRANCH#"refs/heads/"}" + build_url=$(urlencode "${SYSTEM_TEAMFOUNDATIONSERVERURI}${SYSTEM_TEAMPROJECT}/_build/results?buildId=${BUILD_BUILDID}") + + # azure/pipelines runs in detached HEAD + mc= + if [ -n "$pr" ] && [ "$pr" != false ]; + then + mc=$(git show --no-patch --format="%P" 2>/dev/null || echo "") + + if [[ "$mc" =~ ^[a-z0-9]{40}[[:space:]][a-z0-9]{40}$ ]]; + then + mc=$(echo "$mc" | cut -d' ' -f2) + say " Fixing merge commit SHA $commit -> $mc" + commit=$mc + fi + fi + +elif [ "$CI" = "true" ] && [ "$BITBUCKET_BUILD_NUMBER" != "" ]; +then + say "$e==>$x Bitbucket detected." + # https://confluence.atlassian.com/bitbucket/variables-in-pipelines-794502608.html + service="bitbucket" + branch="$BITBUCKET_BRANCH" + build="$BITBUCKET_BUILD_NUMBER" + slug="$BITBUCKET_REPO_OWNER/$BITBUCKET_REPO_SLUG" + job="$BITBUCKET_BUILD_NUMBER" + pr="$BITBUCKET_PR_ID" + commit="$BITBUCKET_COMMIT" + # See https://jira.atlassian.com/browse/BCLOUD-19393 + if [ "${#commit}" = 12 ]; + then + commit=$(git rev-parse "$BITBUCKET_COMMIT") + fi + +elif [ "$CI" = "true" ] && [ "$BUDDY" = "true" ]; +then + say "$e==>$x Buddy CI detected." + # https://buddy.works/docs/pipelines/environment-variables + service="buddy" + branch="$BUDDY_EXECUTION_BRANCH" + build="$BUDDY_EXECUTION_ID" + build_url=$(urlencode "$BUDDY_EXECUTION_URL") + commit="$BUDDY_EXECUTION_REVISION" + pr="$BUDDY_EXECUTION_PULL_REQUEST_NO" + tag="$BUDDY_EXECUTION_TAG" + slug="$BUDDY_REPO_SLUG" + +elif [ "$CIRRUS_CI" != "" ]; +then + say "$e==>$x Cirrus CI detected." + # https://cirrus-ci.org/guide/writing-tasks/#environment-variables + service="cirrus-ci" + slug="$CIRRUS_REPO_FULL_NAME" + branch="$CIRRUS_BRANCH" + pr="$CIRRUS_PR" + commit="$CIRRUS_CHANGE_IN_REPO" + build="$CIRRUS_BUILD_ID" + build_url=$(urlencode "https://cirrus-ci.com/task/$CIRRUS_TASK_ID") + job="$CIRRUS_TASK_NAME" + +elif [ "$DOCKER_REPO" != "" ]; +then + say "$e==>$x Docker detected." + # https://docs.docker.com/docker-cloud/builds/advanced/ + service="docker" + branch="$SOURCE_BRANCH" + commit="$SOURCE_COMMIT" + slug="$DOCKER_REPO" + tag="$CACHE_TAG" + env="$env,IMAGE_NAME" + +else + say "${r}x>${x} No CI provider detected." + say " Testing inside Docker? ${b}http://docs.codecov.io/docs/testing-with-docker${x}" + say " Testing with Tox? ${b}https://docs.codecov.io/docs/python#section-testing-with-tox${x}" + +fi + +say " ${e}project root:${x} $git_root" + +# find branch, commit, repo from git command +if [ "$GIT_BRANCH" != "" ]; +then + branch="$GIT_BRANCH" + +elif [ "$branch" = "" ]; +then + branch=$(git rev-parse --abbrev-ref HEAD 2>/dev/null || hg branch 2>/dev/null || echo "") + if [ "$branch" = "HEAD" ]; + then + branch="" + fi +fi + +if [ "$commit_o" = "" ]; +then + if [ "$GIT_COMMIT" != "" ]; + then + commit="$GIT_COMMIT" + elif [ "$commit" = "" ]; + then + commit=$(git log -1 --format="%H" 2>/dev/null || hg id -i --debug 2>/dev/null | tr -d '+' || echo "") + fi +else + commit="$commit_o" +fi + +if [ "$CODECOV_TOKEN" != "" ] && [ "$token" = "" ]; +then + say "${e}-->${x} token set from env" + token="$CODECOV_TOKEN" +fi + +if [ "$CODECOV_URL" != "" ] && [ "$url_o" = "" ]; +then + say "${e}-->${x} url set from env" + url_o=$(echo "$CODECOV_URL" | sed -e 's/\/$//') +fi + +if [ "$CODECOV_SLUG" != "" ]; +then + say "${e}-->${x} slug set from env" + slug_o="$CODECOV_SLUG" + +elif [ "$slug" = "" ]; +then + if [ "$remote_addr" = "" ]; + then + remote_addr=$(git config --get remote.origin.url || hg paths default || echo '') + fi + if [ "$remote_addr" != "" ]; + then + if echo "$remote_addr" | grep -q "//"; then + # https + slug=$(echo "$remote_addr" | cut -d / -f 4,5 | sed -e 's/\.git$//') + else + # ssh + slug=$(echo "$remote_addr" | cut -d : -f 2 | sed -e 's/\.git$//') + fi + fi + if [ "$slug" = "/" ]; + then + slug="" + fi +fi + +yaml=$(cd "$git_root" && \ + git ls-files "*codecov.yml" "*codecov.yaml" 2>/dev/null \ + || hg locate "*codecov.yml" "*codecov.yaml" 2>/dev/null \ + || cd "$proj_root" && find . -maxdepth 1 -type f -name '*codecov.y*ml' 2>/dev/null \ + || echo '') +yaml=$(echo "$yaml" | head -1) + +if [ "$yaml" != "" ]; +then + say " ${e}Yaml found at:${x} $yaml" + if [[ "$yaml" != /* ]]; then + # relative path for yaml file given, assume relative to the repo root + yaml="$git_root/$yaml" + fi + config=$(parse_yaml "$yaml" || echo '') + + # TODO validate the yaml here + + if [ "$(echo "$config" | grep 'codecov_token="')" != "" ] && [ "$token" = "" ]; + then + say "${e}-->${x} token set from yaml" + token="$(echo "$config" | grep 'codecov_token="' | sed -e 's/codecov_token="//' | sed -e 's/"\.*//')" + fi + + if [ "$(echo "$config" | grep 'codecov_url="')" != "" ] && [ "$url_o" = "" ]; + then + say "${e}-->${x} url set from yaml" + url_o="$(echo "$config" | grep 'codecov_url="' | sed -e 's/codecov_url="//' | sed -e 's/"\.*//')" + fi + + if [ "$(echo "$config" | grep 'codecov_slug="')" != "" ] && [ "$slug_o" = "" ]; + then + say "${e}-->${x} slug set from yaml" + slug_o="$(echo "$config" | grep 'codecov_slug="' | sed -e 's/codecov_slug="//' | sed -e 's/"\.*//')" + fi +else + say " ${g}Yaml not found, that's ok! Learn more at${x} ${b}http://docs.codecov.io/docs/codecov-yaml${x}" +fi + +if [ "$branch_o" != "" ]; +then + branch=$(urlencode "$branch_o") +else + branch=$(urlencode "$branch") +fi + +if [ "$slug_o" = "" ]; +then + urlencoded_slug=$(urlencode "$slug") +else + urlencoded_slug=$(urlencode "$slug_o") +fi + +query="branch=$branch\ + &commit=$commit\ + &build=$([ "$build_o" = "" ] && echo "$build" || echo "$build_o")\ + &build_url=$build_url\ + &name=$(urlencode "$name")\ + &tag=$([ "$tag_o" = "" ] && echo "$tag" || echo "$tag_o")\ + &slug=$urlencoded_slug\ + &service=$service\ + &flags=$flags\ + &pr=$([ "$pr_o" = "" ] && echo "${pr##\#}" || echo "${pr_o##\#}")\ + &job=$job\ + &cmd_args=$(IFS=,; echo "${codecov_flags[*]}")" + +if [ -n "$project" ] && [ -n "$server_uri" ]; +then + query=$(echo "$query&project=$project&server_uri=$server_uri" | tr -d ' ') +fi + +if [ "$parent" != "" ]; +then + query=$(echo "parent=$parent&$query" | tr -d ' ') +fi + +if [ "$ft_search" = "1" ]; +then + # detect bower comoponents location + bower_components="bower_components" + bower_rc=$(cd "$git_root" && cat .bowerrc 2>/dev/null || echo "") + if [ "$bower_rc" != "" ]; + then + bower_components=$(echo "$bower_rc" | tr -d '\n' | grep '"directory"' | cut -d'"' -f4 | sed -e 's/\/$//') + if [ "$bower_components" = "" ]; + then + bower_components="bower_components" + fi + fi + + # Swift Coverage + if [ "$ft_xcodellvm" = "1" ] && [ -d "$ddp" ]; + then + say "${e}==>${x} Processing Xcode reports via llvm-cov" + say " DerivedData folder: $ddp" + profdata_files=$(find "$ddp" -name '*.profdata' 2>/dev/null || echo '') + if [ "$profdata_files" != "" ]; + then + # xcode via profdata + if [ "$xp" = "" ]; + then + # xp=$(xcodebuild -showBuildSettings 2>/dev/null | grep -i "^\s*PRODUCT_NAME" | sed -e 's/.*= \(.*\)/\1/') + # say " ${e}->${x} Speed up Xcode processing by adding ${e}-J '$xp'${x}" + say " ${g}hint${x} Speed up Swift processing by using use ${g}-J 'AppName'${x} (regexp accepted)" + say " ${g}hint${x} This will remove Pods/ from your report. Also ${b}https://docs.codecov.io/docs/ignoring-paths${x}" + fi + while read -r profdata; + do + if [ "$profdata" != "" ]; + then + swiftcov "$profdata" "$xp" + fi + done <<< "$profdata_files" + else + say " ${e}->${x} No Swift coverage found" + fi + + # Obj-C Gcov Coverage + if [ "$ft_gcov" = "1" ]; + then + say " ${e}->${x} Running $gcov_exe for Obj-C" + if [ "$ft_gcovout" = "0" ]; + then + # suppress gcov output + bash -c "find $ddp -type f -name '*.gcda' $gcov_include $gcov_ignore -exec $gcov_exe -p $gcov_arg {} +" >/dev/null 2>&1 || true + else + bash -c "find $ddp -type f -name '*.gcda' $gcov_include $gcov_ignore -exec $gcov_exe -p $gcov_arg {} +" || true + fi + fi + fi + + if [ "$ft_xcodeplist" = "1" ] && [ -d "$ddp" ]; + then + say "${e}==>${x} Processing Xcode plists" + plists_files=$(find "$ddp" -name '*.xccoverage' 2>/dev/null || echo '') + if [ "$plists_files" != "" ]; + then + while read -r plist; + do + if [ "$plist" != "" ]; + then + say " ${g}Found${x} plist file at $plist" + plutil -convert xml1 -o "$(basename "$plist").plist" -- "$plist" + fi + done <<< "$plists_files" + fi + fi + + # Gcov Coverage + if [ "$ft_gcov" = "1" ]; + then + say "${e}==>${x} Running $gcov_exe in $proj_root ${e}(disable via -X gcov)${x}" + if [ "$ft_gcovout" = "0" ]; + then + # suppress gcov output + bash -c "find $proj_root -type f -name '*.gcno' $gcov_include $gcov_ignore -exec $gcov_exe -pb $gcov_arg {} +" >/dev/null 2>&1 || true + else + bash -c "find $proj_root -type f -name '*.gcno' $gcov_include $gcov_ignore -exec $gcov_exe -pb $gcov_arg {} +" || true + fi + else + say "${e}==>${x} gcov disabled" + fi + + # Python Coverage + if [ "$ft_coveragepy" = "1" ]; + then + if [ ! -f coverage.xml ]; + then + if command -v coverage >/dev/null 2>&1; + then + say "${e}==>${x} Python coveragepy exists ${e}disable via -X coveragepy${x}" + + dotcoverage=$(find "$git_root" -name '.coverage' -or -name '.coverage.*' | head -1 || echo '') + if [ "$dotcoverage" != "" ]; + then + cd "$(dirname "$dotcoverage")" + if [ ! -f .coverage ]; + then + say " ${e}->${x} Running coverage combine" + coverage combine -a + fi + say " ${e}->${x} Running coverage xml" + if [ "$(coverage xml -i)" != "No data to report." ]; + then + files="$files +$PWD/coverage.xml" + else + say " ${r}No data to report.${x}" + fi + cd "$proj_root" + else + say " ${r}No .coverage file found.${x}" + fi + else + say "${e}==>${x} Python coveragepy not found" + fi + fi + else + say "${e}==>${x} Python coveragepy disabled" + fi + + if [ "$search_in_o" != "" ]; + then + # location override + search_in="$search_in_o" + fi + + say "$e==>$x Searching for coverage reports in:" + for _path in $search_in + do + say " ${g}+${x} $_path" + done + + patterns="find $search_in \( \ + -name vendor \ + -or -name '$bower_components' \ + -or -name '.egg-info*' \ + -or -name 'conftest_*.c.gcov' \ + -or -name .env \ + -or -name .envs \ + -or -name .git \ + -or -name .hg \ + -or -name .tox \ + -or -name .venv \ + -or -name .venvs \ + -or -name .virtualenv \ + -or -name .virtualenvs \ + -or -name .yarn-cache \ + -or -name __pycache__ \ + -or -name env \ + -or -name envs \ + -or -name htmlcov \ + -or -name js/generated/coverage \ + -or -name node_modules \ + -or -name venv \ + -or -name venvs \ + -or -name virtualenv \ + -or -name virtualenvs \ + \) -prune -or \ + -type f \( -name '*coverage*.*' \ + -or -name '*.clover' \ + -or -name '*.codecov.*' \ + -or -name '*.gcov' \ + -or -name '*.lcov' \ + -or -name '*.lst' \ + -or -name 'clover.xml' \ + -or -name 'cobertura.xml' \ + -or -name 'codecov.*' \ + -or -name 'cover.out' \ + -or -name 'codecov-result.json' \ + -or -name 'coverage-final.json' \ + -or -name 'excoveralls.json' \ + -or -name 'gcov.info' \ + -or -name 'jacoco*.xml' \ + -or -name '*Jacoco*.xml' \ + -or -name 'lcov.dat' \ + -or -name 'lcov.info' \ + -or -name 'luacov.report.out' \ + -or -name 'naxsi.info' \ + -or -name 'nosetests.xml' \ + -or -name 'report.xml' \ + $include_cov \) \ + $exclude_cov \ + -not -name '*.am' \ + -not -name '*.bash' \ + -not -name '*.bat' \ + -not -name '*.bw' \ + -not -name '*.cfg' \ + -not -name '*.class' \ + -not -name '*.cmake' \ + -not -name '*.cmake' \ + -not -name '*.conf' \ + -not -name '*.coverage' \ + -not -name '*.cp' \ + -not -name '*.cpp' \ + -not -name '*.crt' \ + -not -name '*.css' \ + -not -name '*.csv' \ + -not -name '*.csv' \ + -not -name '*.data' \ + -not -name '*.db' \ + -not -name '*.dox' \ + -not -name '*.ec' \ + -not -name '*.ec' \ + -not -name '*.egg' \ + -not -name '*.el' \ + -not -name '*.env' \ + -not -name '*.erb' \ + -not -name '*.exe' \ + -not -name '*.ftl' \ + -not -name '*.gif' \ + -not -name '*.gradle' \ + -not -name '*.gz' \ + -not -name '*.h' \ + -not -name '*.html' \ + -not -name '*.in' \ + -not -name '*.jade' \ + -not -name '*.jar*' \ + -not -name '*.jpeg' \ + -not -name '*.jpg' \ + -not -name '*.js' \ + -not -name '*.less' \ + -not -name '*.log' \ + -not -name '*.m4' \ + -not -name '*.mak*' \ + -not -name '*.md' \ + -not -name '*.o' \ + -not -name '*.p12' \ + -not -name '*.pem' \ + -not -name '*.png' \ + -not -name '*.pom*' \ + -not -name '*.profdata' \ + -not -name '*.proto' \ + -not -name '*.ps1' \ + -not -name '*.pth' \ + -not -name '*.py' \ + -not -name '*.pyc' \ + -not -name '*.pyo' \ + -not -name '*.rb' \ + -not -name '*.rsp' \ + -not -name '*.rst' \ + -not -name '*.ru' \ + -not -name '*.sbt' \ + -not -name '*.scss' \ + -not -name '*.scss' \ + -not -name '*.serialized' \ + -not -name '*.sh' \ + -not -name '*.snapshot' \ + -not -name '*.sql' \ + -not -name '*.svg' \ + -not -name '*.tar.tz' \ + -not -name '*.template' \ + -not -name '*.whl' \ + -not -name '*.xcconfig' \ + -not -name '*.xcoverage.*' \ + -not -name '*/classycle/report.xml' \ + -not -name '*codecov.yml' \ + -not -name '*~' \ + -not -name '.*coveragerc' \ + -not -name '.coverage*' \ + -not -name 'coverage-summary.json' \ + -not -name 'createdFiles.lst' \ + -not -name 'fullLocaleNames.lst' \ + -not -name 'include.lst' \ + -not -name 'inputFiles.lst' \ + -not -name 'phpunit-code-coverage.xml' \ + -not -name 'phpunit-coverage.xml' \ + -not -name 'remapInstanbul.coverage*.json' \ + -not -name 'scoverage.measurements.*' \ + -not -name 'test_*_coverage.txt' \ + -not -name 'testrunner-coverage*' \ + -print 2>/dev/null" + files=$(eval "$patterns" || echo '') + +elif [ "$include_cov" != "" ]; +then + files=$(eval "find $search_in -type f \( ${include_cov:5} \)$exclude_cov 2>/dev/null" || echo '') +elif [ "$direct_file_upload" != "" ]; +then + files=$direct_file_upload +fi + +num_of_files=$(echo "$files" | wc -l | tr -d ' ') +if [ "$num_of_files" != '' ] && [ "$files" != '' ]; +then + say " ${e}->${x} Found $num_of_files reports" +fi + +# no files found +if [ "$files" = "" ]; +then + say "${r}-->${x} No coverage report found." + say " Please visit ${b}http://docs.codecov.io/docs/supported-languages${x}" + exit ${exit_with}; +fi + +if [ "$ft_network" == "1" ]; +then + say "${e}==>${x} Detecting git/mercurial file structure" + network=$(cd "$git_root" && git ls-files $git_ls_files_recurse_submodules_o 2>/dev/null || hg locate 2>/dev/null || echo "") + if [ "$network" = "" ]; + then + network=$(find "$git_root" \( \ + -name virtualenv \ + -name .virtualenv \ + -name virtualenvs \ + -name .virtualenvs \ + -name '*.png' \ + -name '*.gif' \ + -name '*.jpg' \ + -name '*.jpeg' \ + -name '*.md' \ + -name .env \ + -name .envs \ + -name env \ + -name envs \ + -name .venv \ + -name .venvs \ + -name venv \ + -name venvs \ + -name .git \ + -name .egg-info \ + -name shunit2-2.1.6 \ + -name vendor \ + -name __pycache__ \ + -name node_modules \ + -path "*/$bower_components/*" \ + -path '*/target/delombok/*' \ + -path '*/build/lib/*' \ + -path '*/js/generated/coverage/*' \ + \) -prune -or \ + -type f -print 2>/dev/null || echo '') + fi + + if [ "$network_filter_o" != "" ]; + then + network=$(echo "$network" | grep -e "$network_filter_o/*") + fi + if [ "$prefix_o" != "" ]; + then + network=$(echo "$network" | awk "{print \"$prefix_o/\"\$0}") + fi +fi + +upload_file=$(mktemp /tmp/codecov.XXXXXX) +adjustments_file=$(mktemp /tmp/codecov.adjustments.XXXXXX) + +cleanup() { + rm -f "$upload_file" "$adjustments_file" "$upload_file.gz" +} + +trap cleanup INT ABRT TERM + + +if [ "$env" != "" ]; +then + inc_env="" + say "${e}==>${x} Appending build variables" + for varname in $(echo "$env" | tr ',' ' ') + do + if [ "$varname" != "" ]; + then + say " ${g}+${x} $varname" + inc_env="${inc_env}${varname}=$(eval echo "\$${varname}") +" + fi + done + echo "$inc_env<<<<<< ENV" >> "$upload_file" +fi + +# Append git file list +# write discovered yaml location +if [ "$direct_file_upload" = "" ]; +then + echo "$yaml" >> "$upload_file" +fi + +if [ "$ft_network" == "1" ]; +then + i="woff|eot|otf" # fonts + i="$i|gif|png|jpg|jpeg|psd" # images + i="$i|ptt|pptx|numbers|pages|md|txt|xlsx|docx|doc|pdf|csv" # docs + i="$i|.gitignore" # supporting docs + + if [ "$ft_html" != "1" ]; + then + i="$i|html" + fi + + if [ "$ft_yaml" != "1" ]; + then + i="$i|yml|yaml" + fi + + echo "$network" | grep -vwE "($i)$" >> "$upload_file" +fi +echo "<<<<<< network" >> "$upload_file" + +if [ "$direct_file_upload" = "" ]; +then + fr=0 + say "${e}==>${x} Reading reports" + while IFS='' read -r file; + do + # read the coverage file + if [ "$(echo "$file" | tr -d ' ')" != '' ]; + then + if [ -f "$file" ]; + then + report_len=$(wc -c < "$file") + if [ "$report_len" -ne 0 ]; + then + say " ${g}+${x} $file ${e}bytes=$(echo "$report_len" | tr -d ' ')${x}" + # append to to upload + _filename=$(basename "$file") + if [ "${_filename##*.}" = 'gcov' ]; + then + { + echo "# path=$(echo "$file.reduced" | sed "s|^$git_root/||")"; + # get file name + head -1 "$file"; + } >> "$upload_file" + # 1. remove source code + # 2. remove ending bracket lines + # 3. remove whitespace + # 4. remove contextual lines + # 5. remove function names + awk -F': *' '{print $1":"$2":"}' "$file" \ + | sed '\/: *} *$/d' \ + | sed 's/^ *//' \ + | sed '/^-/d' \ + | sed 's/^function.*/func/' >> "$upload_file" + else + { + echo "# path=${file//^$git_root/||}"; + cat "$file"; + } >> "$upload_file" + fi + echo "<<<<<< EOF" >> "$upload_file" + fr=1 + if [ "$clean" = "1" ]; + then + rm "$file" + fi + else + say " ${r}-${x} Skipping empty file $file" + fi + else + say " ${r}-${x} file not found at $file" + fi + fi + done <<< "$(echo -e "$files")" + + if [ "$fr" = "0" ]; + then + say "${r}-->${x} No coverage data found." + say " Please visit ${b}http://docs.codecov.io/docs/supported-languages${x}" + say " search for your projects language to learn how to collect reports." + exit ${exit_with}; + fi +else + cp "$direct_file_upload" "$upload_file" + if [ "$clean" = "1" ]; + then + rm "$direct_file_upload" + fi +fi + +if [ "$ft_fix" = "1" ]; +then + say "${e}==>${x} Appending adjustments" + say " ${b}https://docs.codecov.io/docs/fixing-reports${x}" + + empty_line='^[[:space:]]*$' + # // + syntax_comment='^[[:space:]]*//.*' + # /* or */ + syntax_comment_block='^[[:space:]]*(\/\*|\*\/)[[:space:]]*$' + # { or } + syntax_bracket='^[[:space:]]*[\{\}][[:space:]]*(//.*)?$' + # [ or ] + syntax_list='^[[:space:]]*[][][[:space:]]*(//.*)?$' + # func ... { + syntax_go_func='^[[:space:]]*[func].*[\{][[:space:]]*$' + + # shellcheck disable=SC2089 + skip_dirs="-not -path '*/$bower_components/*' \ + -not -path '*/node_modules/*'" + + cut_and_join() { + awk 'BEGIN { FS=":" } + $3 ~ /\/\*/ || $3 ~ /\*\// { print $0 ; next } + $1!=key { if (key!="") print out ; key=$1 ; out=$1":"$2 ; next } + { out=out","$2 } + END { print out }' 2>/dev/null + } + + if echo "$network" | grep -m1 '.kt$' 1>/dev/null; + then + # skip brackets and comments + cd "$git_root" && \ + find . -type f \ + -name '*.kt' \ + -exec \ + grep -nIHE -e "$syntax_bracket" \ + -e "$syntax_comment_block" {} \; \ + | cut_and_join \ + >> "$adjustments_file" \ + || echo '' + + # last line in file + cd "$git_root" && \ + find . -type f \ + -name '*.kt' -exec \ + wc -l {} \; \ + | while read -r l; do echo "EOF: $l"; done \ + 2>/dev/null \ + >> "$adjustments_file" \ + || echo '' + fi + + if echo "$network" | grep -m1 '.go$' 1>/dev/null; + then + # skip empty lines, comments, and brackets + cd "$git_root" && \ + find . -type f \ + -not -path '*/vendor/*' \ + -not -path '*/caches/*' \ + -name '*.go' \ + -exec \ + grep -nIHE \ + -e "$empty_line" \ + -e "$syntax_comment" \ + -e "$syntax_comment_block" \ + -e "$syntax_bracket" \ + -e "$syntax_go_func" \ + {} \; \ + | cut_and_join \ + >> "$adjustments_file" \ + || echo '' + fi + + if echo "$network" | grep -m1 '.dart$' 1>/dev/null; + then + # skip brackets + cd "$git_root" && \ + find . -type f \ + -name '*.dart' \ + -exec \ + grep -nIHE \ + -e "$syntax_bracket" \ + {} \; \ + | cut_and_join \ + >> "$adjustments_file" \ + || echo '' + fi + + if echo "$network" | grep -m1 '.php$' 1>/dev/null; + then + # skip empty lines, comments, and brackets + cd "$git_root" && \ + find . -type f \ + -not -path "*/vendor/*" \ + -name '*.php' \ + -exec \ + grep -nIHE \ + -e "$syntax_list" \ + -e "$syntax_bracket" \ + -e '^[[:space:]]*\);[[:space:]]*(//.*)?$' \ + {} \; \ + | cut_and_join \ + >> "$adjustments_file" \ + || echo '' + fi + + if echo "$network" | grep -m1 '\(.c\.cpp\|.cxx\|.h\|.hpp\|.m\|.swift\|.vala\)$' 1>/dev/null; + then + # skip brackets + # shellcheck disable=SC2086,SC2090 + cd "$git_root" && \ + find . -type f \ + $skip_dirs \ + \( \ + -name '*.c' \ + -or -name '*.cpp' \ + -or -name '*.cxx' \ + -or -name '*.h' \ + -or -name '*.hpp' \ + -or -name '*.m' \ + -or -name '*.swift' \ + -or -name '*.vala' \ + \) -exec \ + grep -nIHE \ + -e "$empty_line" \ + -e "$syntax_bracket" \ + -e '// LCOV_EXCL' \ + {} \; \ + | cut_and_join \ + >> "$adjustments_file" \ + || echo '' + + # skip brackets + # shellcheck disable=SC2086,SC2090 + cd "$git_root" && \ + find . -type f \ + $skip_dirs \ + \( \ + -name '*.c' \ + -or -name '*.cpp' \ + -or -name '*.cxx' \ + -or -name '*.h' \ + -or -name '*.hpp' \ + -or -name '*.m' \ + -or -name '*.swift' \ + -or -name '*.vala' \ + \) -exec \ + grep -nIH '// LCOV_EXCL' \ + {} \; \ + >> "$adjustments_file" \ + || echo '' + + fi + + found=$(< "$adjustments_file" tr -d ' ') + + if [ "$found" != "" ]; + then + say " ${g}+${x} Found adjustments" + { + echo "# path=fixes"; + cat "$adjustments_file"; + echo "<<<<<< EOF"; + } >> "$upload_file" + rm -rf "$adjustments_file" + else + say " ${e}->${x} No adjustments found" + fi +fi + +if [ "$url_o" != "" ]; +then + url="$url_o" +fi + +if [ "$dump" != "0" ]; +then + # trim whitespace from query + say " ${e}->${x} Dumping upload file (no upload)" + echo "$url/upload/v4?$(echo "package=$package-$VERSION&token=$token&$query" | tr -d ' ')" + cat "$upload_file" +else + if [ "$save_to" != "" ]; + then + say "${e}==>${x} Copying upload file to ${save_to}" + mkdir -p "$(dirname "$save_to")" + cp "$upload_file" "$save_to" + fi + + say "${e}==>${x} Gzipping contents" + gzip -nf9 "$upload_file" + say " $(du -h "$upload_file.gz")" + + query=$(echo "${query}" | tr -d ' ') + say "${e}==>${x} Uploading reports" + say " ${e}url:${x} $url" + say " ${e}query:${x} $query" + + # Full query without token (to display on terminal output) + queryNoToken=$(echo "package=$package-$VERSION&token=secret&$query" | tr -d ' ') + # now add token to query + query=$(echo "package=$package-$VERSION&token=$token&$query" | tr -d ' ') + + if [ "$ft_s3" = "1" ]; + then + say "${e}->${x} Pinging Codecov" + say "$url/upload/v4?$queryNoToken" + # shellcheck disable=SC2086,2090 + res=$(curl $curl_s -X POST $cacert \ + --retry 5 --retry-delay 2 --connect-timeout 2 \ + -H 'X-Reduced-Redundancy: false' \ + -H 'X-Content-Type: application/x-gzip' \ + -H 'Content-Length: 0' \ + --write-out "\n%{response_code}\n" \ + $curlargs \ + "$url/upload/v4?$query" || true) + # a good reply is "https://codecov.io" + "\n" + "https://storage.googleapis.com/codecov/..." + s3target=$(echo "$res" | sed -n 2p) + status=$(tail -n1 <<< "$res") + + if [ "$status" = "200" ] && [ "$s3target" != "" ]; + then + say "${e}->${x} Uploading to" + say "${s3target}" + + # shellcheck disable=SC2086 + s3=$(curl -fiX PUT \ + --data-binary @"$upload_file.gz" \ + -H 'Content-Type: application/x-gzip' \ + -H 'Content-Encoding: gzip' \ + $curlawsargs \ + "$s3target" || true) + + if [ "$s3" != "" ]; + then + say " ${g}->${x} Reports have been successfully queued for processing at ${b}$(echo "$res" | sed -n 1p)${x}" + exit 0 + else + say " ${r}X>${x} Failed to upload" + fi + elif [ "$status" = "400" ]; + then + # 400 Error + say "${r}${res}${x}" + exit ${exit_with} + else + say "${r}${res}${x}" + fi + fi + + say "${e}==>${x} Uploading to Codecov" + + # shellcheck disable=SC2086,2090 + res=$(curl -X POST $cacert \ + --data-binary @"$upload_file.gz" \ + --retry 5 --retry-delay 2 --connect-timeout 2 \ + -H 'Content-Type: text/plain' \ + -H 'Content-Encoding: gzip' \ + -H 'X-Content-Encoding: gzip' \ + -H 'Accept: text/plain' \ + $curlargs \ + "$url/upload/v2?$query&attempt=$i" || echo 'HTTP 500') + # {"message": "Coverage reports upload successfully", "uploaded": true, "queued": true, "id": "...", "url": "https://codecov.io/..."\} + uploaded=$(grep -o '\"uploaded\": [a-z]*' <<< "$res" | head -1 | cut -d' ' -f2) + if [ "$uploaded" = "true" ] + then + say " Reports have been successfully queued for processing at ${b}$(echo "$res" | head -2 | tail -1)${x}" + exit 0 + else + say " ${g}${res}${x}" + exit ${exit_with} + fi + + say " ${r}X> Failed to upload coverage reports${x}" +fi + +exit ${exit_with} diff --git a/scripts/travis/upload_coverage.sh b/scripts/travis/upload_coverage.sh new file mode 100755 index 0000000000..8465d6ce1c --- /dev/null +++ b/scripts/travis/upload_coverage.sh @@ -0,0 +1,15 @@ +#!/usr/bin/env bash + +# Print a warning when there is a new version notification before uploading the +# coverage report to codecov. +set -eo pipefail + +# Check if there is a new version. +curl -fLso codecov https://codecov.io/bash +UPSTREAM_VERSION=$(grep -o 'VERSION=\"[0-9\.]*\"' codecov | cut -d'"' -f2) +LOCAL_VERSION=$(grep -o 'VERSION=\"[0-9\.]*\"' scripts/travis/codecov | cut -d'"' -f2) +if [[ "${UPSTREAM_VERSION}" != "${LOCAL_VERSION}" ]]; then + echo "WARN: version ${UPSTREAM_VERSION} of the codecov upload script is available." +fi + +/usr/bin/env bash scripts/travis/codecov "$@" From 916ecb8a9effb178285a48966b4c1a84ebe09b2e Mon Sep 17 00:00:00 2001 From: chris erway Date: Thu, 23 Jun 2022 20:41:47 -0400 Subject: [PATCH 13/22] use full_coverage name for flag and arg --- .circleci/config.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index a7494135bc..81c5c967bf 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -294,8 +294,8 @@ commands: result_path: type: string default: << pipeline.parameters.result_path >> - use_coverpkg: - description: whether to provide a -coverpkg flag to go test + full_coverage: + description: whether to provide a go test -coverpkg flag to measure coverage across all packages type: boolean default: false steps: @@ -333,7 +333,7 @@ commands: export COVERPACKAGE_NAMES=$(echo $COVERPACKAGES | tr ' ' ',') export PARTITION_TOTAL=${CIRCLE_NODE_TOTAL} export PARTITION_ID=${CIRCLE_NODE_INDEX} - gotestsum --format standard-verbose --junitfile << parameters.result_path >>/<< parameters.result_subdir >>/${CIRCLE_NODE_INDEX}/results.xml --jsonfile << parameters.result_path >>/<< parameters.result_subdir >>/${CIRCLE_NODE_INDEX}/testresults.json -- --tags "sqlite_unlock_notify sqlite_omit_load_extension" << parameters.short_test_flag >> -race -timeout 1h -coverprofile=coverage.txt -covermode=atomic -p 1 $PACKAGE_NAMES <<# parameters.use_coverpkg >> -coverpkg=$COVERPACKAGE_NAMES <> + gotestsum --format standard-verbose --junitfile << parameters.result_path >>/<< parameters.result_subdir >>/${CIRCLE_NODE_INDEX}/results.xml --jsonfile << parameters.result_path >>/<< parameters.result_subdir >>/${CIRCLE_NODE_INDEX}/testresults.json -- --tags "sqlite_unlock_notify sqlite_omit_load_extension" << parameters.short_test_flag >> -race -timeout 1h -coverprofile=coverage.txt -covermode=atomic -p 1 $PACKAGE_NAMES <<# parameters.full_coverage >> -coverpkg=$COVERPACKAGE_NAMES <> - store_artifacts: path: << parameters.result_path >> destination: test-results @@ -524,9 +524,9 @@ jobs: platform: << parameters.platform >> result_subdir: << parameters.platform >>_test_nightly no_output_timeout: 45m - use_coverpkg: true + full_coverage: true - upload_coverage: - args: "-F nightly" + args: "-F full_coverage" - slack/notify: &slack-fail-event event: fail template: basic_fail_1 From 0eb661e32f52d228ee4c441a8fa4047b727e1594 Mon Sep 17 00:00:00 2001 From: chris erway Date: Fri, 24 Jun 2022 07:43:14 -0400 Subject: [PATCH 14/22] add support for "make cover PACKAGE=ledger" --- Makefile | 13 ++++++++++++- ledger/metrics_test.go | 1 + 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 66212e33c3..e47d178f8b 100644 --- a/Makefile +++ b/Makefile @@ -111,8 +111,19 @@ check_shell: sanity: vet fix lint fmt +# "make cover" runs all tests, and collects full coverage across all go-algorand packages by setting -coverpkg. +# Without setting -coverpkg, coverage reports only measure lines of code exercised within the same package as the tests. +# +# "make cover PACKAGE=X" runs all tests in package github.com/algorand/go-algorand/X/... and collects full coverage +# across all packages that are dependencies of that package. cover: - go test $(GOTAGS) -coverprofile=cover.out $(UNIT_TEST_SOURCES) -covermode=atomic -coverpkg=$(shell echo $(COVERPKG_PACKAGES) | sed 's/ /,/g') +ifeq ($(PACKAGE),) + go test -v $(GOTAGS) -coverprofile=cover.out $(UNIT_TEST_SOURCES) -covermode=atomic -coverpkg=$(shell echo $(COVERPKG_PACKAGES) | sed 's/ /,/g') +else + cd $(PACKAGE); \ + go test -v $(GOTAGS) -coverprofile=cover.out ./... -covermode=atomic -coverpkg=$$( (go list -f '{{ join .Deps "\n" }}' ./...; go list -f '{{ join .TestImports "\n" }}' ./...) | grep 'github.com/algorand/go-algorand' | egrep -v '/go-algorand/(test|debug|cmd|config/defaultsGenerator|tools)' | egrep -v '(test|testing|mocks|mock)$$' | sort | uniq | paste -sd ',' -); \ + go tool cover -html cover.out +endif prof: cd node && go test $(GOTAGS) -cpuprofile=cpu.out -memprofile=mem.out -mutexprofile=mutex.out diff --git a/ledger/metrics_test.go b/ledger/metrics_test.go index ca24e0f0f2..b46ec6060c 100644 --- a/ledger/metrics_test.go +++ b/ledger/metrics_test.go @@ -33,6 +33,7 @@ import ( func TestMetricsReload(t *testing.T) { partitiontest.PartitionTest(t) + t.Skip() mt := metricsTracker{} accts := ledgertesting.RandomAccounts(1, true) From 2b6a21c4996b5c7b177d0ee1bfc2d9fb5ce4d997 Mon Sep 17 00:00:00 2001 From: chris erway Date: Fri, 24 Jun 2022 07:49:45 -0400 Subject: [PATCH 15/22] measure full coverage performance again --- .circleci/config.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 81c5c967bf..12d1badb9c 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -328,12 +328,11 @@ commands: scripts/configure_dev.sh scripts/buildtools/install_buildtools.sh -o "gotest.tools/gotestsum" PACKAGES="$(go list ./... | grep -v /go-algorand/test/)" - COVERPACKAGES="$(go list ./... | egrep -v '/go-algorand/(test|debug|cmd|config/defaultsGenerator|tools)' | egrep -v '(test|testing|mock|mocks)$' )" + COVERPACKAGES="$(go list ./... | egrep -v '/go-algorand/(test|debug|cmd|config/defaultsGenerator|tools)' | egrep -v '(test|testing|mock|mocks)$' | paste -sd ',' -)" export PACKAGE_NAMES=$(echo $PACKAGES | tr -d '\n') - export COVERPACKAGE_NAMES=$(echo $COVERPACKAGES | tr ' ' ',') export PARTITION_TOTAL=${CIRCLE_NODE_TOTAL} export PARTITION_ID=${CIRCLE_NODE_INDEX} - gotestsum --format standard-verbose --junitfile << parameters.result_path >>/<< parameters.result_subdir >>/${CIRCLE_NODE_INDEX}/results.xml --jsonfile << parameters.result_path >>/<< parameters.result_subdir >>/${CIRCLE_NODE_INDEX}/testresults.json -- --tags "sqlite_unlock_notify sqlite_omit_load_extension" << parameters.short_test_flag >> -race -timeout 1h -coverprofile=coverage.txt -covermode=atomic -p 1 $PACKAGE_NAMES <<# parameters.full_coverage >> -coverpkg=$COVERPACKAGE_NAMES <> + gotestsum --format standard-verbose --junitfile << parameters.result_path >>/<< parameters.result_subdir >>/${CIRCLE_NODE_INDEX}/results.xml --jsonfile << parameters.result_path >>/<< parameters.result_subdir >>/${CIRCLE_NODE_INDEX}/testresults.json -- --tags "sqlite_unlock_notify sqlite_omit_load_extension" << parameters.short_test_flag >> -race -timeout 1h -coverprofile=coverage.txt -covermode=atomic -p 1 $PACKAGE_NAMES <<# parameters.full_coverage >> -coverpkg=$COVERPACKAGES <> - store_artifacts: path: << parameters.result_path >> destination: test-results @@ -508,6 +507,7 @@ jobs: platform: << parameters.platform >> result_subdir: << parameters.platform >>_test short_test_flag: "-short" + full_coverage: true - upload_coverage test_nightly: From 9d91d503d14e548d07d4dc44e596a9664343c952 Mon Sep 17 00:00:00 2001 From: chris erway Date: Fri, 1 Jul 2022 15:54:52 -0400 Subject: [PATCH 16/22] use non-DefaultRegistry in metrics tests --- util/metrics/counter_test.go | 24 +++++++++++++++++++++--- util/metrics/gauge_test.go | 9 ++++++++- util/metrics/registry_test.go | 19 +++++++++++++------ util/metrics/reporter.go | 6 +++++- util/metrics/serviceCommon.go | 1 + 5 files changed, 48 insertions(+), 11 deletions(-) diff --git a/util/metrics/counter_test.go b/util/metrics/counter_test.go index 75512b80e0..ab21fd0bce 100644 --- a/util/metrics/counter_test.go +++ b/util/metrics/counter_test.go @@ -38,6 +38,9 @@ func TestMetricCounter(t *testing.T) { MetricTest: NewMetricTest(), } + // create a non-default registry for the metrics in this test + registry := MakeRegistry() + // create a http listener. port := test.createListener(":0") @@ -46,10 +49,13 @@ func TestMetricCounter(t *testing.T) { Labels: map[string]string{ "host_name": "host_one", "session_id": "AFX-229"}, + registry: registry, }) metricService.Start(context.Background()) counter := MakeCounter(MetricName{Name: "metric_test_name1", Description: "this is the metric test for counter object"}) + counter.Deregister(nil) + counter.Register(registry) for i := 0; i < 20; i++ { counter.Inc(map[string]string{"pid": "123", "data_host": fmt.Sprintf("host%d", i%5)}) @@ -61,7 +67,7 @@ func TestMetricCounter(t *testing.T) { metricService.Shutdown() - counter.Deregister(nil) + counter.Deregister(registry) // test the metrics values. test.Lock() @@ -84,6 +90,9 @@ func TestMetricCounterFastInts(t *testing.T) { MetricTest: NewMetricTest(), } + // create a non-default registry for the metrics in this test + registry := MakeRegistry() + // create a http listener. port := test.createListener(":0") @@ -92,10 +101,13 @@ func TestMetricCounterFastInts(t *testing.T) { Labels: map[string]string{ "host_name": "host_one", "session_id": "AFX-229"}, + registry: registry, }) metricService.Start(context.Background()) counter := MakeCounter(MetricName{Name: "metric_test_name1", Description: "this is the metric test for counter object"}) + counter.Deregister(nil) + counter.Register(registry) for i := 0; i < 20; i++ { counter.Inc(nil) @@ -108,7 +120,7 @@ func TestMetricCounterFastInts(t *testing.T) { metricService.Shutdown() - counter.Deregister(nil) + counter.Deregister(registry) // test the metrics values. test.Lock() @@ -131,6 +143,9 @@ func TestMetricCounterMixed(t *testing.T) { MetricTest: NewMetricTest(), } + // create a non-default registry for the metrics in this test + registry := MakeRegistry() + // create a http listener. port := test.createListener(":0") @@ -139,10 +154,13 @@ func TestMetricCounterMixed(t *testing.T) { Labels: map[string]string{ "host_name": "host_one", "session_id": "AFX-229"}, + registry: registry, }) metricService.Start(context.Background()) counter := MakeCounter(MetricName{Name: "metric_test_name1", Description: "this is the metric test for counter object"}) + counter.Deregister(nil) + counter.Register(registry) counter.Add(5.25, nil) counter.Add(8.25, map[string]string{}) @@ -157,7 +175,7 @@ func TestMetricCounterMixed(t *testing.T) { metricService.Shutdown() - counter.Deregister(nil) + counter.Deregister(registry) // test the metrics values. test.Lock() diff --git a/util/metrics/gauge_test.go b/util/metrics/gauge_test.go index 9a228c0670..213ed1eee0 100644 --- a/util/metrics/gauge_test.go +++ b/util/metrics/gauge_test.go @@ -37,6 +37,10 @@ func TestMetricGauge(t *testing.T) { test := &GaugeTest{ MetricTest: NewMetricTest(), } + + // create a non-default registry for the metrics in this test + registry := MakeRegistry() + // create a http listener. port := test.createListener(":0") @@ -45,10 +49,13 @@ func TestMetricGauge(t *testing.T) { Labels: map[string]string{ "host_name": "host_one", "session_id": "AFX-229"}, + registry: registry, }) metricService.Start(context.Background()) gauge := MakeGauge(MetricName{Name: "metric_test_name1", Description: "this is the metric test for counter object"}) + gauge.Deregister(nil) + gauge.Register(registry) for i := 0; i < 20; i++ { gauge.Set(float64(i*10), map[string]string{"pid": "123", "data_host": fmt.Sprintf("host%d", i%5)}) @@ -60,7 +67,7 @@ func TestMetricGauge(t *testing.T) { time.Sleep(test.sampleRate * 2) metricService.Shutdown() - gauge.Deregister(nil) + gauge.Deregister(registry) // test the metrics values. test.Lock() diff --git a/util/metrics/registry_test.go b/util/metrics/registry_test.go index 2256993f20..1025d9a831 100644 --- a/util/metrics/registry_test.go +++ b/util/metrics/registry_test.go @@ -27,15 +27,22 @@ import ( func TestWriteAdd(t *testing.T) { partitiontest.PartitionTest(t) + // create a non-default registry for the metrics in this test + registry := MakeRegistry() + // Test AddMetrics and WriteMetrics with a counter counter := MakeCounter(MetricName{Name: "gauge-name", Description: "gauge description"}) + counter.Deregister(nil) + counter.Register(registry) counter.Add(12.34, nil) labelCounter := MakeCounter(MetricName{Name: "label-counter", Description: "counter with labels"}) + labelCounter.Deregister(nil) + labelCounter.Register(registry) labelCounter.Add(5, map[string]string{"label": "a label value"}) results := make(map[string]float64) - DefaultRegistry().AddMetrics(results) + registry.AddMetrics(results) require.Equal(t, 2, len(results), "results", results) require.Contains(t, results, "gauge-name") @@ -44,19 +51,19 @@ func TestWriteAdd(t *testing.T) { require.InDelta(t, 5, results["label-counter_label__a_label_value_"], 0.01) bufBefore := strings.Builder{} - DefaultRegistry().WriteMetrics(&bufBefore, "label") + registry.WriteMetrics(&bufBefore, "label") require.True(t, bufBefore.Len() > 0) - DefaultRegistry().AddMetrics(results) + registry.AddMetrics(results) require.Contains(t, results, "gauge-name") require.InDelta(t, 12.34, results["gauge-name"], 0.01) // not included in string builder bufAfter := strings.Builder{} - DefaultRegistry().WriteMetrics(&bufAfter, "label") + registry.WriteMetrics(&bufAfter, "label") require.Equal(t, bufBefore.String(), bufAfter.String()) - counter.Deregister(nil) - labelCounter.Deregister(nil) + counter.Deregister(registry) + labelCounter.Deregister(registry) } diff --git a/util/metrics/reporter.go b/util/metrics/reporter.go index efecf6f659..d1fc68ee01 100644 --- a/util/metrics/reporter.go +++ b/util/metrics/reporter.go @@ -121,7 +121,11 @@ func (reporter *MetricReporter) waitForTimeStamp(ctx context.Context) bool { func (reporter *MetricReporter) gatherMetrics() { var buf strings.Builder - DefaultRegistry().WriteMetrics(&buf, reporter.formattedLabels) + if reporter.serviceConfig.registry != nil { + reporter.serviceConfig.registry.WriteMetrics(&buf, reporter.formattedLabels) + } else { + DefaultRegistry().WriteMetrics(&buf, reporter.formattedLabels) + } reporter.lastMetricsBuffer = buf } diff --git a/util/metrics/serviceCommon.go b/util/metrics/serviceCommon.go index e0b26c8207..6542f66a14 100644 --- a/util/metrics/serviceCommon.go +++ b/util/metrics/serviceCommon.go @@ -30,6 +30,7 @@ type ServiceConfig struct { NodeExporterListenAddress string Labels map[string]string NodeExporterPath string + registry *Registry // if nil, will use DefaultRegistry(). Used for testing } // MetricService represent a single running metric server instance From 47c69063ab4315b75dc715b98f9d35b3226a8085 Mon Sep 17 00:00:00 2001 From: cce <51567+cce@users.noreply.github.com> Date: Thu, 29 Jan 2026 17:35:16 -0500 Subject: [PATCH 17/22] CI: allow manual full-coverage runs on PRs via workflow_dispatch Add a workflow_dispatch trigger to ci-pr.yml with a full_coverage option. When enabled, the test job passes -coverpkg to go test to measure coverage across all packages, and tags the codecov upload with the full_coverage flag. Also rename the codecov flag from "nightly" to "full_coverage" to match the actual upload tag. --- .codecov.yml | 2 +- .github/workflows/ci-pr.yml | 16 +++++++++++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/.codecov.yml b/.codecov.yml index c927971c3b..1ff08129e6 100644 --- a/.codecov.yml +++ b/.codecov.yml @@ -2,7 +2,7 @@ codecov: require_ci_to_pass: yes flags: - nightly: + full_coverage: joined: false ignore: diff --git a/.github/workflows/ci-pr.yml b/.github/workflows/ci-pr.yml index 0a97bfab28..876215417a 100644 --- a/.github/workflows/ci-pr.yml +++ b/.github/workflows/ci-pr.yml @@ -4,6 +4,13 @@ on: branches: - master - 'rel/**' + workflow_dispatch: + inputs: + full_coverage: + description: 'Run with -coverpkg to measure cross-package coverage (slower)' + required: false + type: boolean + default: false env: CODECOV_TOKEN: "8b4a1f91-f154-4c26-b84c-c9aaa90159c6" # Same public token from CircleCI config @@ -49,13 +56,19 @@ jobs: - name: Run tests run: | PACKAGES="$(go list ./... | grep -v /go-algorand/test/)" - export PACKAGE_NAMES=$(echo $PACKAGES | tr -d '\n') + export PACKAGE_NAMES=$(echo $PACKAGES | tr -d '\n') + COVERPKG_FLAG="" + if [[ "${{ inputs.full_coverage }}" == "true" ]]; then + COVERPACKAGES="$(go list ./... | grep -E -v '/go-algorand/(test|debug|cmd|config/defaultsGenerator|tools)' | grep -E -v '(test|testing|mock|mocks)$' | paste -sd ',' -)" + COVERPKG_FLAG="-coverpkg=$COVERPACKAGES" + fi mkdir -p test_results/${{ matrix.platform }}_test/${PARTITION_ID} go tool -modfile=tool.mod gotestsum --format standard-quiet \ --junitfile ~/test_results/${{ matrix.platform }}_test/${PARTITION_ID}/results.xml \ --jsonfile ~/test_results/${{ matrix.platform }}_test/${PARTITION_ID}/testresults.json \ -- --tags "sqlite_unlock_notify sqlite_omit_load_extension" $SHORTTEST \ -race -timeout 1h -coverprofile=coverage.txt -covermode=atomic -p 4 \ + $COVERPKG_FLAG \ $PACKAGE_NAMES - name: Notify Slack on failure if: failure() @@ -89,6 +102,7 @@ jobs: with: token: ${{ env.CODECOV_TOKEN }} file: ./coverage.txt + flags: ${{ inputs.full_coverage && 'full_coverage' || '' }} fail_ci_if_error: false - name: Upload test results to Codecov if: ${{ !cancelled() }} From 63784f7f413f946f46c06fa3a38723f0f659c056 Mon Sep 17 00:00:00 2001 From: cce <51567+cce@users.noreply.github.com> Date: Fri, 30 Jan 2026 15:00:33 -0500 Subject: [PATCH 18/22] metrics: export MakeCounterUnregistered/MakeGaugeUnregistered Export the previously unexported makeCounter/makeGauge constructors so callers outside the metrics package can create metrics without auto-registering on the default registry. Use these in tests and in metricsTracker to avoid the Deregister(nil)+Register(registry) pattern. Add a registry field to metricsTracker so loadFromDisk and close operate on the correct registry, fixing TestMetricsReload under -coverpkg without needing t.Skip(). --- ledger/metrics.go | 23 +++++++++++++++-------- ledger/metrics_test.go | 9 ++++++--- util/metrics/counter.go | 8 ++++---- util/metrics/counter_test.go | 9 +++------ util/metrics/gauge.go | 8 ++++---- util/metrics/gauge_test.go | 3 +-- util/metrics/opencensus.go | 8 ++++---- util/metrics/prometheus.go | 4 ++-- util/metrics/registry_test.go | 6 ++---- 9 files changed, 41 insertions(+), 37 deletions(-) diff --git a/ledger/metrics.go b/ledger/metrics.go index aeae7e7853..52e3ebd0c6 100644 --- a/ledger/metrics.go +++ b/ledger/metrics.go @@ -31,31 +31,38 @@ type metricsTracker struct { ledgerRewardClaimsTotal *metrics.Counter ledgerRound *metrics.Gauge ledgerDBRound *metrics.Gauge + registry *metrics.Registry } func (mt *metricsTracker) loadFromDisk(l ledgerForTracker, _ basics.Round) error { - mt.ledgerTransactionsTotal = metrics.MakeCounter(metrics.LedgerTransactionsTotal) - mt.ledgerRewardClaimsTotal = metrics.MakeCounter(metrics.LedgerRewardClaimsTotal) - mt.ledgerRound = metrics.MakeGauge(metrics.LedgerRound) - mt.ledgerDBRound = metrics.MakeGauge(metrics.LedgerDBRound) + reg := mt.registry + mt.ledgerTransactionsTotal = metrics.MakeCounterUnregistered(metrics.LedgerTransactionsTotal) + mt.ledgerTransactionsTotal.Register(reg) + mt.ledgerRewardClaimsTotal = metrics.MakeCounterUnregistered(metrics.LedgerRewardClaimsTotal) + mt.ledgerRewardClaimsTotal.Register(reg) + mt.ledgerRound = metrics.MakeGaugeUnregistered(metrics.LedgerRound) + mt.ledgerRound.Register(reg) + mt.ledgerDBRound = metrics.MakeGaugeUnregistered(metrics.LedgerDBRound) + mt.ledgerDBRound.Register(reg) return nil } func (mt *metricsTracker) close() { + reg := mt.registry if mt.ledgerTransactionsTotal != nil { - mt.ledgerTransactionsTotal.Deregister(nil) + mt.ledgerTransactionsTotal.Deregister(reg) mt.ledgerTransactionsTotal = nil } if mt.ledgerRewardClaimsTotal != nil { - mt.ledgerRewardClaimsTotal.Deregister(nil) + mt.ledgerRewardClaimsTotal.Deregister(reg) mt.ledgerRewardClaimsTotal = nil } if mt.ledgerRound != nil { - mt.ledgerRound.Deregister(nil) + mt.ledgerRound.Deregister(reg) mt.ledgerRound = nil } if mt.ledgerDBRound != nil { - mt.ledgerDBRound.Deregister(nil) + mt.ledgerDBRound.Deregister(reg) mt.ledgerDBRound = nil } } diff --git a/ledger/metrics_test.go b/ledger/metrics_test.go index 9309096e77..943b44fcf8 100644 --- a/ledger/metrics_test.go +++ b/ledger/metrics_test.go @@ -33,9 +33,12 @@ import ( func TestMetricsReload(t *testing.T) { partitiontest.PartitionTest(t) - t.Skip() - mt := metricsTracker{} + // Use a non-default registry so the test is not affected by metrics + // registered by other packages when running with -coverpkg. + registry := metrics.MakeRegistry() + + mt := metricsTracker{registry: registry} accts := ledgertesting.RandomAccounts(1, true) ml := makeMockLedgerForTracker(t, true, 1, protocol.ConsensusCurrentVersion, []map[basics.Address]basics.AccountData{accts}) @@ -49,7 +52,7 @@ func TestMetricsReload(t *testing.T) { mt.newBlock(blk, ledgercore.StateDelta{}) var buf strings.Builder - metrics.DefaultRegistry().WriteMetrics(&buf, "") + registry.WriteMetrics(&buf, "") lines := strings.Split(buf.String(), "\n") txCount := 0 rcCount := 0 diff --git a/util/metrics/counter.go b/util/metrics/counter.go index 54781661f9..19a0ede342 100644 --- a/util/metrics/counter.go +++ b/util/metrics/counter.go @@ -28,14 +28,14 @@ type Counter struct { // MakeCounter create a new counter with the provided name and description. func MakeCounter(metric MetricName) *Counter { - c := makeCounter(metric) + c := MakeCounterUnregistered(metric) c.Register(nil) return c } -// makeCounter create a new counter with the provided name and description -// but does not register it with the default registry. -func makeCounter(metric MetricName) *Counter { +// MakeCounterUnregistered creates a new counter without registering it. +// Use Register() to add it to a specific registry. +func MakeCounterUnregistered(metric MetricName) *Counter { c := &Counter{c: couge{ values: make([]*cougeValues, 0), description: metric.Description, diff --git a/util/metrics/counter_test.go b/util/metrics/counter_test.go index 07511c43c7..9e28a49bd1 100644 --- a/util/metrics/counter_test.go +++ b/util/metrics/counter_test.go @@ -53,8 +53,7 @@ func TestMetricCounter(t *testing.T) { }) metricService.Start(context.Background()) - counter := MakeCounter(MetricName{Name: "metric_test_name1", Description: "this is the metric test for counter object"}) - counter.Deregister(nil) + counter := MakeCounterUnregistered(MetricName{Name: "metric_test_name1", Description: "this is the metric test for counter object"}) counter.Register(registry) for i := 0; i < 20; i++ { @@ -105,8 +104,7 @@ func TestMetricCounterFastInts(t *testing.T) { }) metricService.Start(context.Background()) - counter := MakeCounter(MetricName{Name: "metric_test_name1", Description: "this is the metric test for counter object"}) - counter.Deregister(nil) + counter := MakeCounterUnregistered(MetricName{Name: "metric_test_name1", Description: "this is the metric test for counter object"}) counter.Register(registry) for i := 0; i < 20; i++ { @@ -158,8 +156,7 @@ func TestMetricCounterMixed(t *testing.T) { }) metricService.Start(context.Background()) - counter := MakeCounter(MetricName{Name: "metric_test_name1", Description: "this is the metric test for counter object"}) - counter.Deregister(nil) + counter := MakeCounterUnregistered(MetricName{Name: "metric_test_name1", Description: "this is the metric test for counter object"}) counter.Register(registry) counter.AddUint64(5, nil) diff --git a/util/metrics/gauge.go b/util/metrics/gauge.go index eabf156720..f0a7a87f14 100644 --- a/util/metrics/gauge.go +++ b/util/metrics/gauge.go @@ -27,14 +27,14 @@ type Gauge struct { // MakeGauge create a new gauge with the provided name and description. func MakeGauge(metric MetricName) *Gauge { - c := makeGauge(metric) + c := MakeGaugeUnregistered(metric) c.Register(nil) return c } -// makeGauge create a new gauge with the provided name and description -// but does not register it with the default registry. -func makeGauge(metric MetricName) *Gauge { +// MakeGaugeUnregistered creates a new gauge without registering it. +// Use Register() to add it to a specific registry. +func MakeGaugeUnregistered(metric MetricName) *Gauge { c := &Gauge{g: couge{ values: make([]*cougeValues, 0), description: metric.Description, diff --git a/util/metrics/gauge_test.go b/util/metrics/gauge_test.go index 76b259690c..8410e1f101 100644 --- a/util/metrics/gauge_test.go +++ b/util/metrics/gauge_test.go @@ -54,8 +54,7 @@ func TestMetricGauge(t *testing.T) { metricService.Start(context.Background()) gauges := make([]*Gauge, 3) for i := 0; i < 3; i++ { - gauges[i] = MakeGauge(MetricName{Name: fmt.Sprintf("gauge_%d", i), Description: "this is the metric test for gauge object"}) - gauges[i].Deregister(nil) + gauges[i] = MakeGaugeUnregistered(MetricName{Name: fmt.Sprintf("gauge_%d", i), Description: "this is the metric test for gauge object"}) gauges[i].Register(registry) } for i := 0; i < 9; i++ { diff --git a/util/metrics/opencensus.go b/util/metrics/opencensus.go index 4bda632887..a15136937f 100644 --- a/util/metrics/opencensus.go +++ b/util/metrics/opencensus.go @@ -78,7 +78,7 @@ type statCounter struct { // WriteMetric outputs Prometheus metrics for all labels/values in statCounter func (st *statCounter) WriteMetric(buf *strings.Builder, parentLabels string) { name := sanitizePrometheusName(st.name) - counter := makeCounter(MetricName{name, st.description}) + counter := MakeCounterUnregistered(MetricName{name, st.description}) for i := 0; i < len(st.labels); i++ { counter.AddUint64(uint64(st.values[i]), st.labels[i]) } @@ -87,7 +87,7 @@ func (st *statCounter) WriteMetric(buf *strings.Builder, parentLabels string) { // AddMetric outputs all statCounter's labels/values into a map func (st *statCounter) AddMetric(values map[string]float64) { - counter := makeCounter(MetricName{st.name, st.description}) + counter := MakeCounterUnregistered(MetricName{st.name, st.description}) for i := 0; i < len(st.labels); i++ { counter.AddUint64(uint64(st.values[i]), st.labels[i]) } @@ -105,7 +105,7 @@ type statDistribution struct { // WriteMetric outputs Prometheus metrics for all labels/values in statCounter func (st *statDistribution) WriteMetric(buf *strings.Builder, parentLabels string) { name := sanitizePrometheusName(st.name) - gauge := makeGauge(MetricName{name, st.description}) + gauge := MakeGaugeUnregistered(MetricName{name, st.description}) for i := 0; i < len(st.labels); i++ { gauge.SetLabels(uint64(st.values[i]), st.labels[i]) } @@ -114,7 +114,7 @@ func (st *statDistribution) WriteMetric(buf *strings.Builder, parentLabels strin // AddMetric outputs all statCounter's labels/values into a map func (st *statDistribution) AddMetric(values map[string]float64) { - gauge := makeGauge(MetricName{st.name, st.description}) + gauge := MakeGaugeUnregistered(MetricName{st.name, st.description}) for i := 0; i < len(st.labels); i++ { gauge.SetLabels(uint64(st.values[i]), st.labels[i]) } diff --git a/util/metrics/prometheus.go b/util/metrics/prometheus.go index e916491fc4..d6fa5bae33 100644 --- a/util/metrics/prometheus.go +++ b/util/metrics/prometheus.go @@ -75,7 +75,7 @@ func collectPrometheusMetrics(names []string) []Metric { } if _, ok := namesMap[metric.GetName()]; len(namesMap) > 0 && ok || len(namesMap) == 0 { if metric.GetType() == iopc.MetricType_COUNTER && metric.GetMetric() != nil { - counter := makeCounter(MetricName{metric.GetName(), metric.GetHelp()}) + counter := MakeCounterUnregistered(MetricName{metric.GetName(), metric.GetHelp()}) ma := metric.GetMetric() for _, m := range ma { if m.GetCounter() == nil { @@ -87,7 +87,7 @@ func collectPrometheusMetrics(names []string) []Metric { } result = append(result, counter) } else if metric.GetType() == iopc.MetricType_GAUGE && metric.GetMetric() != nil { - gauge := makeGauge(MetricName{metric.GetName(), metric.GetHelp()}) + gauge := MakeGaugeUnregistered(MetricName{metric.GetName(), metric.GetHelp()}) ma := metric.GetMetric() for _, m := range ma { diff --git a/util/metrics/registry_test.go b/util/metrics/registry_test.go index 824c970d3c..b8f91a67ed 100644 --- a/util/metrics/registry_test.go +++ b/util/metrics/registry_test.go @@ -31,14 +31,12 @@ func TestWriteAdd(t *testing.T) { registry := MakeRegistry() // Test AddMetrics and WriteMetrics with a counter - counter := MakeCounter(MetricName{Name: "gauge-name", Description: "gauge description"}) - counter.Deregister(nil) + counter := MakeCounterUnregistered(MetricName{Name: "gauge-name", Description: "gauge description"}) counter.Register(registry) counter.AddUint64(12, nil) - labelCounter := MakeCounter(MetricName{Name: "label-counter", Description: "counter with labels"}) - labelCounter.Deregister(nil) + labelCounter := MakeCounterUnregistered(MetricName{Name: "label-counter", Description: "counter with labels"}) labelCounter.Register(registry) labelCounter.AddUint64(5, map[string]string{"label": "a label value"}) From a5abe2b3bbddf9ec03f2191e67e8b64a4cf4560f Mon Sep 17 00:00:00 2001 From: cce <51567+cce@users.noreply.github.com> Date: Fri, 30 Jan 2026 15:03:00 -0500 Subject: [PATCH 19/22] make diff a little smaller --- util/metrics/counter.go | 4 ++-- util/metrics/gauge.go | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/util/metrics/counter.go b/util/metrics/counter.go index 19a0ede342..be713284f2 100644 --- a/util/metrics/counter.go +++ b/util/metrics/counter.go @@ -33,8 +33,8 @@ func MakeCounter(metric MetricName) *Counter { return c } -// MakeCounterUnregistered creates a new counter without registering it. -// Use Register() to add it to a specific registry. +// makeCounter creates a new counter with the provided name and description +// but does not register it with the default registry. func MakeCounterUnregistered(metric MetricName) *Counter { c := &Counter{c: couge{ values: make([]*cougeValues, 0), diff --git a/util/metrics/gauge.go b/util/metrics/gauge.go index f0a7a87f14..bf7d3b6940 100644 --- a/util/metrics/gauge.go +++ b/util/metrics/gauge.go @@ -32,8 +32,8 @@ func MakeGauge(metric MetricName) *Gauge { return c } -// MakeGaugeUnregistered creates a new gauge without registering it. -// Use Register() to add it to a specific registry. +// MakeGaugeUnregistered creates a new gauge with the provided name and description +// but does not register it with the default registry. func MakeGaugeUnregistered(metric MetricName) *Gauge { c := &Gauge{g: couge{ values: make([]*cougeValues, 0), From fdcb2dcf964f11148ccf1a13169f9c057261f161 Mon Sep 17 00:00:00 2001 From: cce <51567+cce@users.noreply.github.com> Date: Fri, 30 Jan 2026 15:16:46 -0500 Subject: [PATCH 20/22] fix lint --- util/metrics/counter.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/util/metrics/counter.go b/util/metrics/counter.go index be713284f2..b2bbc951b0 100644 --- a/util/metrics/counter.go +++ b/util/metrics/counter.go @@ -33,7 +33,7 @@ func MakeCounter(metric MetricName) *Counter { return c } -// makeCounter creates a new counter with the provided name and description +// MakeCounterUnregistered creates a new counter with the provided name and description // but does not register it with the default registry. func MakeCounterUnregistered(metric MetricName) *Counter { c := &Counter{c: couge{ From aa03c03de9944696108433ca6a8be55ed26ed6a2 Mon Sep 17 00:00:00 2001 From: cce <51567+cce@users.noreply.github.com> Date: Fri, 30 Jan 2026 15:48:50 -0500 Subject: [PATCH 21/22] use GOTESTCOMMAND in makefile --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index be708bf599..e9552dcafc 100644 --- a/Makefile +++ b/Makefile @@ -140,10 +140,10 @@ sanity: fix lint fmt tidy modernize # across all packages that are dependencies of that package. cover: ifeq ($(PACKAGE),) - go test -v $(GOTAGS) -coverprofile=cover.out $(UNIT_TEST_SOURCES) -covermode=atomic -coverpkg=$(shell echo $(COVERPKG_PACKAGES) | sed 's/ /,/g') + $(GOTESTCOMMAND) $(GOTAGS) -coverprofile=cover.out $(UNIT_TEST_SOURCES) -covermode=atomic -coverpkg=$(shell echo $(COVERPKG_PACKAGES) | sed 's/ /,/g') else cd $(PACKAGE); \ - go test -v $(GOTAGS) -coverprofile=cover.out ./... -covermode=atomic -coverpkg=$$( (go list -f '{{ join .Deps "\n" }}' ./...; go list -f '{{ join .TestImports "\n" }}' ./...) | grep 'github.com/algorand/go-algorand' | egrep -v '/go-algorand/(test|debug|cmd|config/defaultsGenerator|tools)' | egrep -v '(test|testing|mocks|mock)$$' | sort | uniq | paste -sd ',' -); \ + $(GOTESTCOMMAND) $(GOTAGS) -coverprofile=cover.out ./... -covermode=atomic -coverpkg=$$( (go list -f '{{ join .Deps "\n" }}' ./...; go list -f '{{ join .TestImports "\n" }}' ./...) | grep 'github.com/algorand/go-algorand' | egrep -v '/go-algorand/(test|debug|cmd|config/defaultsGenerator|tools)' | egrep -v '(test|testing|mocks|mock)$$' | sort | uniq | paste -sd ',' -); \ go tool cover -html cover.out endif From f2276b42079152aa4b21bea9485293a8b74c3b79 Mon Sep 17 00:00:00 2001 From: cce <51567+cce@users.noreply.github.com> Date: Mon, 2 Feb 2026 14:27:17 -0500 Subject: [PATCH 22/22] Update .codecov.yml Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .codecov.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.codecov.yml b/.codecov.yml index 1ff08129e6..691bb6d2f4 100644 --- a/.codecov.yml +++ b/.codecov.yml @@ -9,7 +9,7 @@ ignore: - "**/*_gen.go" - "**/*_gen_test.go" - "**/generated" - - "**/_string.go" # ignore stringer-generated code + - "**/*_string.go" # ignore stringer-generated code coverage: status: