From 632b87b55c7ca2ffbb86dd32b505f855c62e2100 Mon Sep 17 00:00:00 2001 From: Matt Clay Date: Wed, 25 Jun 2025 10:04:15 -0700 Subject: [PATCH] Use codecov-cli for uploads (#85386) ci_coverage ci_complete (cherry picked from commit 4a03ccbd41e3ce506fca98488a9e2d25f2c9c859) --- .azure-pipelines/scripts/publish-codecov.py | 70 +++++++++++++-------- 1 file changed, 43 insertions(+), 27 deletions(-) diff --git a/.azure-pipelines/scripts/publish-codecov.py b/.azure-pipelines/scripts/publish-codecov.py index ae328a5cf5e..8a15822b0e8 100755 --- a/.azure-pipelines/scripts/publish-codecov.py +++ b/.azure-pipelines/scripts/publish-codecov.py @@ -9,11 +9,11 @@ from __future__ import annotations import argparse import dataclasses import pathlib -import shutil +import shlex import subprocess import tempfile import typing as t -import urllib.request +import venv @dataclasses.dataclass(frozen=True) @@ -43,6 +43,27 @@ def parse_args() -> Args: return Args(**kwargs) +def run(*args: str | pathlib.Path) -> None: + cmd = [str(arg) for arg in args] + print(f'==> {shlex.join(cmd)}', flush=True) + subprocess.run(cmd, check=True) + + +def install_codecov(dest: pathlib.Path) -> pathlib.Path: + package = 'codecov-cli' + version = '11.0.3' + + venv_dir = dest / 'venv' + python_bin = venv_dir / 'bin' / 'python' + codecov_bin = venv_dir / 'bin' / 'codecovcli' + + venv.create(venv_dir, with_pip=True) + + run(python_bin, '-m', 'pip', 'install', f'{package}=={version}', '--disable-pip-version-check') + + return codecov_bin + + def process_files(directory: pathlib.Path) -> t.Tuple[CoverageFile, ...]: processed = [] for file in directory.joinpath('reports').glob('coverage*.xml'): @@ -57,48 +78,43 @@ def process_files(directory: pathlib.Path) -> t.Tuple[CoverageFile, ...]: return tuple(processed) -def upload_files(codecov_bin: pathlib.Path, files: t.Tuple[CoverageFile, ...], dry_run: bool = False) -> None: +def upload_files(codecov_bin: pathlib.Path, config_file: pathlib.Path, files: t.Tuple[CoverageFile, ...], dry_run: bool = False) -> None: for file in files: cmd = [ - str(codecov_bin), + codecov_bin, + '--disable-telem', + '--codecov-yml-path', + config_file, + 'upload-process', + '--disable-search', + '--disable-file-fixes', + '--plugin', + 'noop', '--name', file.name, '--file', - str(file.path), + file.path, ] for flag in file.flags: - cmd.extend(['--flags', flag]) + cmd.extend(['--flag', flag]) if dry_run: - print(f'DRY-RUN: Would run command: {cmd}') - continue - - subprocess.run(cmd, check=True) - + cmd.append('--dry-run') -def download_file(url: str, dest: pathlib.Path, flags: int, dry_run: bool = False) -> None: - if dry_run: - print(f'DRY-RUN: Would download {url} to {dest} and set mode to {flags:o}') - return + run(*cmd) - with urllib.request.urlopen(url) as resp: - with dest.open('w+b') as f: - # Read data in chunks rather than all at once - shutil.copyfileobj(resp, f, 64 * 1024) - dest.chmod(flags) - - -def main(): +def main() -> None: args = parse_args() - url = 'https://ci-files.testing.ansible.com/codecov/linux/codecov' + with tempfile.TemporaryDirectory(prefix='codecov-') as tmpdir: - codecov_bin = pathlib.Path(tmpdir) / 'codecov' - download_file(url, codecov_bin, 0o755, args.dry_run) + config_file = pathlib.Path(tmpdir) / 'config.yml' + config_file.write_text('') + codecov_bin = install_codecov(pathlib.Path(tmpdir)) files = process_files(args.path) - upload_files(codecov_bin, files, args.dry_run) + upload_files(codecov_bin, config_file, files, args.dry_run) if __name__ == '__main__':