⚠ This page is served via a proxy. Original site: https://github.com
This service does not collect credentials or authentication data.
Skip to content
This repository was archived by the owner on Jul 16, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
213 changes: 8 additions & 205 deletions codecov_cli/commands/labelanalysis.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,13 @@
import json
import logging
import pathlib
import time
from typing import Dict, List, Optional

import click
import requests
import sentry_sdk

from codecov_cli.fallbacks import CodecovOption, FallbackFieldEnum
from codecov_cli.helpers import request
from codecov_cli.helpers.args import get_cli_args
from codecov_cli.helpers.config import CODECOV_API_URL
from codecov_cli.helpers.validators import validate_commit_sha
from codecov_cli.runners import get_runner
from codecov_cli.runners.types import (
Expand Down Expand Up @@ -92,7 +88,6 @@ def label_analysis(
):
with sentry_sdk.start_transaction(op="task", name="Label Analysis"):
with sentry_sdk.start_span(name="labelanalysis"):
enterprise_url = ctx.obj.get("enterprise_url")
args = get_cli_args(ctx)
logger.debug(
"Starting label analysis",
Expand Down Expand Up @@ -124,18 +119,6 @@ def label_analysis(
extra=dict(extra_log_attributes=dict(config=runner.params)),
)

upload_url = enterprise_url or CODECOV_API_URL
url = f"{upload_url}/labels/labels-analysis"
token_header = f"Repotoken {token}"
payload = {
"base_commit": base_commit_sha,
"head_commit": head_commit_sha,
"requested_labels": None,
}
# Send the initial label analysis request without labels
# Because labels might take a long time to collect
eid = _send_labelanalysis_request(payload, url, token_header)

logger.info("Collecting labels...")
requested_labels = runner.collect_tests()
logger.info(f"Collected {len(requested_labels)} test labels")
Expand All @@ -145,98 +128,15 @@ def label_analysis(
extra_log_attributes=dict(labels_collected=requested_labels)
),
)
payload["requested_labels"] = requested_labels

if eid:
# Initial request with no labels was successful
# Now we PATCH the labels in
patch_url = f"{upload_url}/labels/labels-analysis/{eid}"
_patch_labels(payload, patch_url, token_header)
else:
# Initial request with no labels failed
# Retry it
eid = _send_labelanalysis_request(payload, url, token_header)
if eid is None:
_fallback_to_collected_labels(
requested_labels,
runner,
dry_run=dry_run,
dry_run_format=dry_run_format,
fallback_reason="codecov_unavailable",
)
return

has_result = False
logger.info("Waiting for list of tests to run...")
start_wait = time.monotonic()
time.sleep(1)
while not has_result:
resp_data = request.get(
f"{upload_url}/labels/labels-analysis/{eid}",
headers={"Authorization": token_header},
)
resp_json = resp_data.json()
if resp_json["state"] == "finished":
logger.info(
"Received list of tests from Codecov",
extra=dict(
extra_log_attributes=dict(
processing_errors=resp_json.get("errors", [])
)
),
)
request_result = _potentially_calculate_absent_labels(
resp_json["result"], requested_labels
)
if not dry_run:
runner.process_labelanalysis_result(request_result)
else:
_dry_run_output(
LabelAnalysisRequestResult(request_result),
runner,
dry_run_format,
# It's possible that the task had processing errors and fallback to all tests
# Even though it's marked as FINISHED (not ERROR) it's not a true success
fallback_reason=(
"test_list_processing_errors"
if resp_json.get("errors", None)
else None
),
)
return
if resp_json["state"] == "error":
logger.error(
"Request had problems calculating",
extra=dict(
extra_log_attributes=dict(
base_commit=resp_json["base_commit"],
head_commit=resp_json["head_commit"],
external_id=resp_json["external_id"],
)
),
)
_fallback_to_collected_labels(
collected_labels=requested_labels,
runner=runner,
dry_run=dry_run,
dry_run_format=dry_run_format,
fallback_reason="test_list_processing_failed",
)
return
if max_wait_time and (time.monotonic() - start_wait) > max_wait_time:
logger.error(
f"Exceeded max waiting time of {max_wait_time} seconds. Running all tests.",
)
_fallback_to_collected_labels(
collected_labels=requested_labels,
runner=runner,
dry_run=dry_run,
dry_run_format=dry_run_format,
fallback_reason="max_wait_time_exceeded",
)
return
logger.info("Waiting more time for result...")
time.sleep(5)
_fallback_to_collected_labels(
requested_labels,
runner,
dry_run=dry_run,
dry_run_format=dry_run_format,
fallback_reason="codecov_unavailable",
)
return


def _parse_runner_params(runner_params: List[str]) -> Dict[str, str]:
Expand Down Expand Up @@ -271,103 +171,6 @@ def _parse_runner_params(runner_params: List[str]) -> Dict[str, str]:
return final_params


def _potentially_calculate_absent_labels(
request_result, requested_labels
) -> LabelAnalysisRequestResult:
if request_result["absent_labels"]:
# This means that Codecov already calculated everything for us
final_result = LabelAnalysisRequestResult(request_result)
else:
# Here we have to calculate the absent labels
# And also remove labels that maybe don't exist anymore from the set of labels to test
# Because codecov didn't have this info previously
requested_labels_set = set(requested_labels)
present_diff_labels_set = set(request_result.get("present_diff_labels", []))
present_report_labels_set = set(request_result.get("present_report_labels", []))
global_level_labels_set = set(request_result.get("global_level_labels", []))
final_result = LabelAnalysisRequestResult(
{
"present_report_labels": sorted(
present_report_labels_set & requested_labels_set
),
"present_diff_labels": sorted(
present_diff_labels_set & requested_labels_set
),
"absent_labels": sorted(
requested_labels_set - present_report_labels_set
),
"global_level_labels": sorted(
global_level_labels_set & requested_labels_set
),
}
)
logger.info(
"Received information about tests to run",
extra=dict(
extra_log_attributes=dict(
absent_labels=len(final_result.absent_labels),
present_diff_labels=len(final_result.present_diff_labels),
global_level_labels=len(final_result.global_level_labels),
present_report_labels=len(final_result.present_report_labels),
)
),
)
return final_result


def _patch_labels(payload, url, token_header):
logger.info("Sending collected labels to Codecov...")
try:
response = request.patch(
url, json=payload, headers={"Authorization": token_header}
)
if response.status_code < 300:
logger.info("Labels successfully sent to Codecov")
except requests.RequestException:
raise click.ClickException(click.style("Unable to reach Codecov", fg="red"))


def _send_labelanalysis_request(payload, url, token_header):
logger.info(
"Requesting set of labels to run...",
extra=dict(
extra_log_attributes=dict(
with_labels=(payload["requested_labels"] is not None)
)
),
)
try:
response = request.post(
url, data=payload, headers={"Authorization": token_header}
)
if response.status_code >= 500:
logger.warning(
"Sorry. Codecov is having problems",
extra=dict(extra_log_attributes=dict(status_code=response.status_code)),
)
return None
if response.status_code >= 400:
logger.warning(
"Got a 4XX status code back from Codecov",
extra=dict(
extra_log_attributes=dict(
status_code=response.status_code, response_json=response.json()
)
),
)
raise click.ClickException(
"There is some problem with the submitted information"
)
except requests.RequestException:
raise click.ClickException(click.style("Unable to reach Codecov", fg="red"))
eid = response.json()["external_id"]
logger.info(
"Label Analysis request successful",
extra=dict(extra_log_attributes=dict(request_id=eid)),
)
return eid


def _dry_run_json_output(
labels_to_run: set,
labels_to_skip: set,
Expand Down
26 changes: 1 addition & 25 deletions codecov_cli/commands/staticanalysis.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import asyncio
import logging
import pathlib
import typing
Expand All @@ -7,9 +6,7 @@
import sentry_sdk

from codecov_cli.fallbacks import CodecovOption, FallbackFieldEnum
from codecov_cli.helpers.args import get_cli_args
from codecov_cli.helpers.validators import validate_commit_sha
from codecov_cli.services.staticanalysis import run_analysis_entrypoint
from codecov_cli.types import CommandContext

logger = logging.getLogger("codecovcli")
Expand Down Expand Up @@ -62,25 +59,4 @@ def static_analysis(
):
with sentry_sdk.start_transaction(op="task", name="Static Analysis"):
with sentry_sdk.start_span(name="static_analysis"):
enterprise_url = ctx.obj.get("enterprise_url")
args = get_cli_args(ctx)
logger.debug(
"Starting Static Analysis processing",
extra=dict(
extra_log_attributes=args,
),
)
return asyncio.run(
run_analysis_entrypoint(
ctx.obj["codecov_yaml"],
foldertosearch,
numberprocesses,
pattern,
commit,
token,
force,
list(folders_to_exclude),
enterprise_url,
args,
)
)
pass
Loading