diff --git a/.github/actions/run-eden-test/action.yml b/.github/actions/run-eden-test/action.yml index e250b6953..98bb3f438 100644 --- a/.github/actions/run-eden-test/action.yml +++ b/.github/actions/run-eden-test/action.yml @@ -47,6 +47,22 @@ runs: run: EDEN_TEST_STOP=n ./eden test ./tests/workflow -s ${{ inputs.suite }} -v debug shell: bash working-directory: "./eden" + - name: Collect coverage + if: always() + run: | + mkdir -p eden_coverage + ./eden eve collect-coverage --output-dir ./eden_coverage || true + ls -la eden_coverage/ || true + shell: bash + working-directory: "./eden" + - name: Upload coverage artifact + if: always() && hashFiles('./eden/eden_coverage/eden_e2e_coverage.txt') != '' + uses: actions/upload-artifact@v4 + with: + name: covdata-${{ inputs.suite }}-fs-${{ inputs.file_system }}-tpm-${{ inputs.tpm_enabled }}-attempt-${{ github.run_attempt }} + path: ./eden/eden_coverage/ + if-no-files-found: warn + retention-days: 7 - name: Collect info if: failure() uses: ./eden/.github/actions/collect-info diff --git a/.github/workflows/eden.yml b/.github/workflows/eden.yml index 6958f6b4b..820e733fd 100644 --- a/.github/workflows/eden.yml +++ b/.github/workflows/eden.yml @@ -18,6 +18,7 @@ jobs: run_tests: name: Execute Eden test workflow uses: ./.github/workflows/test.yml + secrets: inherit with: eve_image: "lfedge/eve:16.6.0" eve_kubevirt_image: "lfedge/eve:0.0.0-master-75241279-kubevirt-amd64" diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 0718a136c..f1fa59230 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -393,3 +393,51 @@ jobs: eve_artifact_name: ${{ inputs.eve_artifact_name }} artifact_run_id: ${{ inputs.artifact_run_id }} require_virtualization: true + + coverage-merge: + name: Merge coverage + needs: [smoke, networking, storage, lps-loc, eve-upgrade, user-apps, virtualization] + if: always() + runs-on: ubuntu-22.04 + steps: + - uses: actions/setup-go@v3 + with: + go-version: '1.24' + - name: Download per-job covdata artifacts + uses: actions/download-artifact@v4 + with: + pattern: covdata-* + path: covdata-raw + - name: Merge covdata + run: | + set -e + mkdir -p covdata-merged + # Each artifact directory contains eden_e2e_coverage.txt and a + # covdata/coverage/ subtree with covmeta.* / covcounters.* files. + # Discover every GOCOVERDIR-shaped directory by looking for covmeta.*. + mapfile -t covdirs < <(find covdata-raw -name 'covmeta.*' -printf '%h\n' | sort -u) + if [ ${#covdirs[@]} -eq 0 ]; then + echo "::warning::No raw covdata found across jobs" + exit 0 + fi + inputs=$(IFS=,; echo "${covdirs[*]}") + go tool covdata merge -i="$inputs" -o covdata-merged + go tool covdata textfmt -i=covdata-merged -o combined_coverage.txt + go tool cover -func=combined_coverage.txt | tee coverage-summary.txt + - name: Upload merged covdata + if: always() && hashFiles('combined_coverage.txt') != '' + uses: actions/upload-artifact@v4 + with: + name: covdata-merged + path: | + covdata-merged/ + combined_coverage.txt + coverage-summary.txt + retention-days: 30 + - name: Upload coverage to Codecov + if: always() && hashFiles('combined_coverage.txt') != '' + uses: codecov/codecov-action@57e3a136b779b570ffcdbf80b3bdc90e7fab3de2 # v6.0.0 + with: + token: ${{ secrets.CODECOV_TOKEN }} + files: combined_coverage.txt + fail_ci_if_error: false diff --git a/pkg/openevec/coverage.go b/pkg/openevec/coverage.go index 145134d3b..16fd7fac3 100644 --- a/pkg/openevec/coverage.go +++ b/pkg/openevec/coverage.go @@ -120,26 +120,28 @@ func (openEVEC *OpenEVEC) CollectEveCoverage(outputDir string) error { log.Warnf("EVE coverage: %v; proceeding with whatever was written", err) } - // Copy binary coverage files from EVE to a local temp directory. - tmpDir, err := os.MkdirTemp("", "eve-coverage-*") - if err != nil { - return fmt.Errorf("cannot create temp dir: %w", err) + // Copy binary coverage files from EVE into /covdata so that + // callers wanting to merge coverage across multiple runs (e.g. across + // the Eden CI matrix) have access to the raw covmeta.* / covcounters.* + // files needed by `go tool covdata merge`. + covdataDir := filepath.Join(outputDir, "covdata") + if err := os.MkdirAll(covdataDir, 0755); err != nil { + return fmt.Errorf("cannot create covdata dir %s: %w", covdataDir, err) } - defer os.RemoveAll(tmpDir) log.Infof("EVE coverage: copying %s from EVE to %s", - defaults.DefaultEveCoverageDir, tmpDir) + defaults.DefaultEveCoverageDir, covdataDir) if err := openEVEC.SdnForwardSCPDirFromEve( - defaults.DefaultEveCoverageDir, tmpDir); err != nil { + defaults.DefaultEveCoverageDir, covdataDir); err != nil { return fmt.Errorf("cannot copy coverage data from EVE: %w", err) } // The SCP copies the directory itself, so the files land under - // tmpDir/coverage/. Point covdata at that sub-directory. - coverSubDir := filepath.Join(tmpDir, filepath.Base(defaults.DefaultEveCoverageDir)) + // covdataDir/coverage/. Point covdata at that sub-directory. + coverSubDir := filepath.Join(covdataDir, filepath.Base(defaults.DefaultEveCoverageDir)) if _, err := os.Stat(coverSubDir); os.IsNotExist(err) { - // Fallback: files landed directly in tmpDir. - coverSubDir = tmpDir + // Fallback: files landed directly in covdataDir. + coverSubDir = covdataDir } // Convert binary coverage format → Go text profile format.