codecov-cli 11.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- codecov_cli/__init__.py +3 -0
- codecov_cli/commands/__init__.py +0 -0
- codecov_cli/commands/base_picking.py +75 -0
- codecov_cli/commands/commit.py +72 -0
- codecov_cli/commands/create_report_result.py +41 -0
- codecov_cli/commands/empty_upload.py +80 -0
- codecov_cli/commands/get_report_results.py +50 -0
- codecov_cli/commands/labelanalysis.py +269 -0
- codecov_cli/commands/process_test_results.py +273 -0
- codecov_cli/commands/report.py +65 -0
- codecov_cli/commands/send_notifications.py +46 -0
- codecov_cli/commands/staticanalysis.py +62 -0
- codecov_cli/commands/upload.py +316 -0
- codecov_cli/commands/upload_coverage.py +186 -0
- codecov_cli/commands/upload_process.py +133 -0
- codecov_cli/fallbacks.py +41 -0
- codecov_cli/helpers/__init__.py +0 -0
- codecov_cli/helpers/args.py +31 -0
- codecov_cli/helpers/ci_adapters/__init__.py +63 -0
- codecov_cli/helpers/ci_adapters/appveyor_ci.py +54 -0
- codecov_cli/helpers/ci_adapters/azure_pipelines.py +44 -0
- codecov_cli/helpers/ci_adapters/base.py +102 -0
- codecov_cli/helpers/ci_adapters/bitbucket_ci.py +42 -0
- codecov_cli/helpers/ci_adapters/bitrise_ci.py +37 -0
- codecov_cli/helpers/ci_adapters/buildkite.py +45 -0
- codecov_cli/helpers/ci_adapters/circleci.py +47 -0
- codecov_cli/helpers/ci_adapters/cirrus_ci.py +36 -0
- codecov_cli/helpers/ci_adapters/cloudbuild.py +70 -0
- codecov_cli/helpers/ci_adapters/codebuild.py +49 -0
- codecov_cli/helpers/ci_adapters/droneci.py +36 -0
- codecov_cli/helpers/ci_adapters/github_actions.py +90 -0
- codecov_cli/helpers/ci_adapters/gitlab_ci.py +56 -0
- codecov_cli/helpers/ci_adapters/heroku.py +36 -0
- codecov_cli/helpers/ci_adapters/jenkins.py +38 -0
- codecov_cli/helpers/ci_adapters/local.py +39 -0
- codecov_cli/helpers/ci_adapters/teamcity.py +37 -0
- codecov_cli/helpers/ci_adapters/travis_ci.py +44 -0
- codecov_cli/helpers/ci_adapters/woodpeckerci.py +36 -0
- codecov_cli/helpers/config.py +66 -0
- codecov_cli/helpers/encoder.py +49 -0
- codecov_cli/helpers/folder_searcher.py +114 -0
- codecov_cli/helpers/git.py +97 -0
- codecov_cli/helpers/git_services/__init__.py +14 -0
- codecov_cli/helpers/git_services/github.py +40 -0
- codecov_cli/helpers/glob.py +146 -0
- codecov_cli/helpers/logging_utils.py +77 -0
- codecov_cli/helpers/options.py +51 -0
- codecov_cli/helpers/request.py +198 -0
- codecov_cli/helpers/upload_type.py +15 -0
- codecov_cli/helpers/validators.py +13 -0
- codecov_cli/helpers/versioning_systems.py +201 -0
- codecov_cli/main.py +99 -0
- codecov_cli/opentelemetry.py +26 -0
- codecov_cli/plugins/__init__.py +92 -0
- codecov_cli/plugins/compress_pycoverage_contexts.py +141 -0
- codecov_cli/plugins/gcov.py +69 -0
- codecov_cli/plugins/pycoverage.py +134 -0
- codecov_cli/plugins/types.py +8 -0
- codecov_cli/plugins/xcode.py +117 -0
- codecov_cli/runners/__init__.py +80 -0
- codecov_cli/runners/dan_runner.py +64 -0
- codecov_cli/runners/pytest_standard_runner.py +184 -0
- codecov_cli/runners/types.py +33 -0
- codecov_cli/services/__init__.py +0 -0
- codecov_cli/services/commit/__init__.py +86 -0
- codecov_cli/services/commit/base_picking.py +24 -0
- codecov_cli/services/empty_upload/__init__.py +42 -0
- codecov_cli/services/report/__init__.py +169 -0
- codecov_cli/services/upload/__init__.py +169 -0
- codecov_cli/services/upload/file_finder.py +320 -0
- codecov_cli/services/upload/legacy_upload_sender.py +132 -0
- codecov_cli/services/upload/network_finder.py +49 -0
- codecov_cli/services/upload/upload_collector.py +198 -0
- codecov_cli/services/upload/upload_sender.py +232 -0
- codecov_cli/services/upload_completion/__init__.py +38 -0
- codecov_cli/services/upload_coverage/__init__.py +93 -0
- codecov_cli/types.py +88 -0
- codecov_cli-11.0.0.dist-info/METADATA +298 -0
- codecov_cli-11.0.0.dist-info/RECORD +83 -0
- codecov_cli-11.0.0.dist-info/WHEEL +5 -0
- codecov_cli-11.0.0.dist-info/entry_points.txt +3 -0
- codecov_cli-11.0.0.dist-info/licenses/LICENSE +201 -0
- codecov_cli-11.0.0.dist-info/top_level.txt +1 -0
codecov_cli/__init__.py
ADDED
|
File without changes
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import typing
|
|
3
|
+
|
|
4
|
+
import click
|
|
5
|
+
import sentry_sdk
|
|
6
|
+
|
|
7
|
+
from codecov_cli.fallbacks import CodecovOption, FallbackFieldEnum
|
|
8
|
+
from codecov_cli.helpers.args import get_cli_args
|
|
9
|
+
from codecov_cli.helpers.encoder import slug_without_subgroups_is_invalid
|
|
10
|
+
from codecov_cli.services.commit.base_picking import base_picking_logic
|
|
11
|
+
from codecov_cli.types import CommandContext
|
|
12
|
+
|
|
13
|
+
logger = logging.getLogger("codecovcli")
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@click.command()
|
|
17
|
+
@click.option(
|
|
18
|
+
"--base-sha",
|
|
19
|
+
help="Base commit SHA (with 40 chars)",
|
|
20
|
+
cls=CodecovOption,
|
|
21
|
+
fallback_field=FallbackFieldEnum.commit_sha,
|
|
22
|
+
required=True,
|
|
23
|
+
)
|
|
24
|
+
@click.option(
|
|
25
|
+
"--pr",
|
|
26
|
+
help="Pull Request id to associate commit with",
|
|
27
|
+
cls=CodecovOption,
|
|
28
|
+
fallback_field=FallbackFieldEnum.pull_request_number,
|
|
29
|
+
)
|
|
30
|
+
@click.option(
|
|
31
|
+
"--slug",
|
|
32
|
+
cls=CodecovOption,
|
|
33
|
+
fallback_field=FallbackFieldEnum.slug,
|
|
34
|
+
help="owner/repo slug",
|
|
35
|
+
envvar="CODECOV_SLUG",
|
|
36
|
+
)
|
|
37
|
+
@click.option(
|
|
38
|
+
"-t",
|
|
39
|
+
"--token",
|
|
40
|
+
help="Codecov upload token",
|
|
41
|
+
envvar="CODECOV_TOKEN",
|
|
42
|
+
)
|
|
43
|
+
@click.option(
|
|
44
|
+
"--service",
|
|
45
|
+
cls=CodecovOption,
|
|
46
|
+
fallback_field=FallbackFieldEnum.service,
|
|
47
|
+
help="Specify the service provider of the repo e.g. github",
|
|
48
|
+
)
|
|
49
|
+
@click.pass_context
|
|
50
|
+
def pr_base_picking(
|
|
51
|
+
ctx: CommandContext,
|
|
52
|
+
base_sha: str,
|
|
53
|
+
pr: typing.Optional[int],
|
|
54
|
+
slug: typing.Optional[str],
|
|
55
|
+
token: typing.Optional[str],
|
|
56
|
+
service: typing.Optional[str],
|
|
57
|
+
):
|
|
58
|
+
with sentry_sdk.start_transaction(op="task", name="Base Picking"):
|
|
59
|
+
with sentry_sdk.start_span(name="base_picking"):
|
|
60
|
+
enterprise_url = ctx.obj.get("enterprise_url")
|
|
61
|
+
args = get_cli_args(ctx)
|
|
62
|
+
logger.debug(
|
|
63
|
+
"Starting base picking process",
|
|
64
|
+
extra=dict(
|
|
65
|
+
extra_log_attributes=args,
|
|
66
|
+
),
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
if slug_without_subgroups_is_invalid(slug):
|
|
70
|
+
logger.error(
|
|
71
|
+
"Slug is invalid. Slug should be in the form of owner_username/repo_name"
|
|
72
|
+
)
|
|
73
|
+
return
|
|
74
|
+
|
|
75
|
+
base_picking_logic(base_sha, pr, slug, token, service, enterprise_url, args)
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import typing
|
|
3
|
+
|
|
4
|
+
import click
|
|
5
|
+
import sentry_sdk
|
|
6
|
+
|
|
7
|
+
from codecov_cli.fallbacks import CodecovOption, FallbackFieldEnum
|
|
8
|
+
from codecov_cli.helpers.args import get_cli_args
|
|
9
|
+
from codecov_cli.helpers.git import GitService
|
|
10
|
+
from codecov_cli.helpers.options import global_options
|
|
11
|
+
from codecov_cli.services.commit import create_commit_logic
|
|
12
|
+
from codecov_cli.types import CommandContext
|
|
13
|
+
|
|
14
|
+
logger = logging.getLogger("codecovcli")
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@click.command()
|
|
18
|
+
@click.option(
|
|
19
|
+
"--parent-sha",
|
|
20
|
+
help="SHA (with 40 chars) of what should be the parent of this commit",
|
|
21
|
+
)
|
|
22
|
+
@click.option(
|
|
23
|
+
"-P",
|
|
24
|
+
"--pr",
|
|
25
|
+
"--pull-request-number",
|
|
26
|
+
"pull_request_number",
|
|
27
|
+
help="Specify the pull request number manually. Used to override pre-existing CI environment variables",
|
|
28
|
+
cls=CodecovOption,
|
|
29
|
+
fallback_field=FallbackFieldEnum.pull_request_number,
|
|
30
|
+
)
|
|
31
|
+
@click.option(
|
|
32
|
+
"-B",
|
|
33
|
+
"--branch",
|
|
34
|
+
help="Branch to which this commit belongs to",
|
|
35
|
+
cls=CodecovOption,
|
|
36
|
+
fallback_field=FallbackFieldEnum.branch,
|
|
37
|
+
)
|
|
38
|
+
@global_options
|
|
39
|
+
@click.pass_context
|
|
40
|
+
def create_commit(
|
|
41
|
+
ctx: CommandContext,
|
|
42
|
+
commit_sha: str,
|
|
43
|
+
parent_sha: typing.Optional[str],
|
|
44
|
+
pull_request_number: typing.Optional[int],
|
|
45
|
+
branch: typing.Optional[str],
|
|
46
|
+
slug: typing.Optional[str],
|
|
47
|
+
token: typing.Optional[str],
|
|
48
|
+
git_service: typing.Optional[str],
|
|
49
|
+
fail_on_error: bool,
|
|
50
|
+
):
|
|
51
|
+
with sentry_sdk.start_transaction(op="task", name="Create Commit"):
|
|
52
|
+
with sentry_sdk.start_span(name="create_commit"):
|
|
53
|
+
enterprise_url = ctx.obj.get("enterprise_url")
|
|
54
|
+
args = get_cli_args(ctx)
|
|
55
|
+
logger.debug(
|
|
56
|
+
"Starting create commit process",
|
|
57
|
+
extra=dict(
|
|
58
|
+
extra_log_attributes=args,
|
|
59
|
+
),
|
|
60
|
+
)
|
|
61
|
+
create_commit_logic(
|
|
62
|
+
commit_sha,
|
|
63
|
+
parent_sha,
|
|
64
|
+
pull_request_number,
|
|
65
|
+
branch,
|
|
66
|
+
slug,
|
|
67
|
+
token,
|
|
68
|
+
git_service,
|
|
69
|
+
enterprise_url,
|
|
70
|
+
fail_on_error,
|
|
71
|
+
args,
|
|
72
|
+
)
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
|
|
3
|
+
import click
|
|
4
|
+
import sentry_sdk
|
|
5
|
+
|
|
6
|
+
from codecov_cli.helpers.args import get_cli_args
|
|
7
|
+
from codecov_cli.helpers.options import global_options
|
|
8
|
+
from codecov_cli.services.report import create_report_results_logic
|
|
9
|
+
from codecov_cli.types import CommandContext
|
|
10
|
+
|
|
11
|
+
logger = logging.getLogger("codecovcli")
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@click.command(hidden=True, deprecated=True)
|
|
15
|
+
@click.option(
|
|
16
|
+
"--code", help="The code of the report. If unsure, leave default", default="default"
|
|
17
|
+
)
|
|
18
|
+
@global_options
|
|
19
|
+
@click.pass_context
|
|
20
|
+
def create_report_results(
|
|
21
|
+
ctx: CommandContext,
|
|
22
|
+
commit_sha: str,
|
|
23
|
+
code: str,
|
|
24
|
+
slug: str,
|
|
25
|
+
git_service: str,
|
|
26
|
+
token: str,
|
|
27
|
+
fail_on_error: bool,
|
|
28
|
+
):
|
|
29
|
+
with sentry_sdk.start_transaction(op="task", name="Create Report Result"):
|
|
30
|
+
with sentry_sdk.start_span(name="create_report_result"):
|
|
31
|
+
enterprise_url = ctx.obj.get("enterprise_url")
|
|
32
|
+
args = get_cli_args(ctx)
|
|
33
|
+
logger.debug(
|
|
34
|
+
"Creating report results",
|
|
35
|
+
extra=dict(
|
|
36
|
+
extra_log_attributes=args,
|
|
37
|
+
),
|
|
38
|
+
)
|
|
39
|
+
create_report_results_logic(
|
|
40
|
+
commit_sha, code, slug, git_service, token, enterprise_url, fail_on_error, args
|
|
41
|
+
)
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import typing
|
|
3
|
+
|
|
4
|
+
import click
|
|
5
|
+
import sentry_sdk
|
|
6
|
+
|
|
7
|
+
from codecov_cli.fallbacks import CodecovOption, FallbackFieldEnum
|
|
8
|
+
from codecov_cli.helpers.args import get_cli_args
|
|
9
|
+
from codecov_cli.helpers.options import global_options
|
|
10
|
+
from codecov_cli.services.commit import create_commit_logic
|
|
11
|
+
from codecov_cli.services.empty_upload import empty_upload_logic
|
|
12
|
+
from codecov_cli.types import CommandContext
|
|
13
|
+
|
|
14
|
+
logger = logging.getLogger("codecovcli")
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@click.command()
|
|
18
|
+
@click.option("--force", is_flag=True, default=False)
|
|
19
|
+
@click.option(
|
|
20
|
+
"--parent-sha",
|
|
21
|
+
help="SHA (with 40 chars) of what should be the parent of this commit",
|
|
22
|
+
)
|
|
23
|
+
@click.option(
|
|
24
|
+
"-P",
|
|
25
|
+
"--pr",
|
|
26
|
+
"--pull-request-number",
|
|
27
|
+
"pull_request_number",
|
|
28
|
+
help="Specify the pull request number manually. Used to override pre-existing CI environment variables",
|
|
29
|
+
cls=CodecovOption,
|
|
30
|
+
fallback_field=FallbackFieldEnum.pull_request_number,
|
|
31
|
+
)
|
|
32
|
+
@click.option(
|
|
33
|
+
"-B",
|
|
34
|
+
"--branch",
|
|
35
|
+
help="Branch to which this commit belongs to",
|
|
36
|
+
cls=CodecovOption,
|
|
37
|
+
fallback_field=FallbackFieldEnum.branch,
|
|
38
|
+
)
|
|
39
|
+
@global_options
|
|
40
|
+
@click.pass_context
|
|
41
|
+
def empty_upload(
|
|
42
|
+
ctx: CommandContext,
|
|
43
|
+
commit_sha: str,
|
|
44
|
+
force: bool,
|
|
45
|
+
slug: typing.Optional[str],
|
|
46
|
+
token: typing.Optional[str],
|
|
47
|
+
git_service: typing.Optional[str],
|
|
48
|
+
fail_on_error: typing.Optional[bool],
|
|
49
|
+
parent_sha: typing.Optional[str],
|
|
50
|
+
pull_request_number: typing.Optional[int],
|
|
51
|
+
branch: typing.Optional[str],
|
|
52
|
+
):
|
|
53
|
+
with sentry_sdk.start_transaction(op="task", name="Empty Upload"):
|
|
54
|
+
with sentry_sdk.start_span(name="empty_upload"):
|
|
55
|
+
enterprise_url = ctx.obj.get("enterprise_url")
|
|
56
|
+
args = get_cli_args(ctx)
|
|
57
|
+
|
|
58
|
+
logger.debug("Attempting to Create Commit before doing an empty upload.")
|
|
59
|
+
create_commit_logic(
|
|
60
|
+
commit_sha,
|
|
61
|
+
parent_sha,
|
|
62
|
+
pull_request_number,
|
|
63
|
+
branch,
|
|
64
|
+
slug,
|
|
65
|
+
token,
|
|
66
|
+
git_service,
|
|
67
|
+
enterprise_url,
|
|
68
|
+
fail_on_error,
|
|
69
|
+
args,
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
logger.debug(
|
|
73
|
+
"Starting empty upload process",
|
|
74
|
+
extra=dict(
|
|
75
|
+
extra_log_attributes=args,
|
|
76
|
+
),
|
|
77
|
+
)
|
|
78
|
+
return empty_upload_logic(
|
|
79
|
+
commit_sha, slug, token, git_service, enterprise_url, fail_on_error, force, args
|
|
80
|
+
)
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
|
|
3
|
+
import click
|
|
4
|
+
import sentry_sdk
|
|
5
|
+
|
|
6
|
+
from codecov_cli.helpers.args import get_cli_args
|
|
7
|
+
from codecov_cli.helpers.encoder import encode_slug
|
|
8
|
+
from codecov_cli.helpers.options import global_options
|
|
9
|
+
from codecov_cli.services.report import send_reports_result_get_request
|
|
10
|
+
from codecov_cli.types import CommandContext
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
logger = logging.getLogger("codecovcli")
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@click.command(hidden=True, deprecated=True)
|
|
17
|
+
@click.option(
|
|
18
|
+
"--code", help="The code of the report. If unsure, leave default", default="default"
|
|
19
|
+
)
|
|
20
|
+
@global_options
|
|
21
|
+
@click.pass_context
|
|
22
|
+
def get_report_results(
|
|
23
|
+
ctx: CommandContext,
|
|
24
|
+
commit_sha: str,
|
|
25
|
+
code: str,
|
|
26
|
+
slug: str,
|
|
27
|
+
git_service: str,
|
|
28
|
+
token: str,
|
|
29
|
+
fail_on_error: bool,
|
|
30
|
+
):
|
|
31
|
+
with sentry_sdk.start_transaction(op="task", name="Get Report Results"):
|
|
32
|
+
with sentry_sdk.start_span(name="get_report_results"):
|
|
33
|
+
enterprise_url = ctx.obj.get("enterprise_url")
|
|
34
|
+
args = get_cli_args(ctx)
|
|
35
|
+
logger.debug(
|
|
36
|
+
"Getting report results",
|
|
37
|
+
extra=dict(
|
|
38
|
+
extra_log_attributes=args,
|
|
39
|
+
),
|
|
40
|
+
)
|
|
41
|
+
encoded_slug = encode_slug(slug)
|
|
42
|
+
send_reports_result_get_request(
|
|
43
|
+
commit_sha=commit_sha,
|
|
44
|
+
report_code=code,
|
|
45
|
+
encoded_slug=encoded_slug,
|
|
46
|
+
service=git_service,
|
|
47
|
+
token=token,
|
|
48
|
+
enterprise_url=enterprise_url,
|
|
49
|
+
fail_on_error=fail_on_error,
|
|
50
|
+
)
|
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import logging
|
|
3
|
+
import pathlib
|
|
4
|
+
from typing import Dict, List, Optional
|
|
5
|
+
|
|
6
|
+
import click
|
|
7
|
+
import sentry_sdk
|
|
8
|
+
|
|
9
|
+
from codecov_cli.fallbacks import CodecovOption, FallbackFieldEnum
|
|
10
|
+
from codecov_cli.helpers.args import get_cli_args
|
|
11
|
+
from codecov_cli.helpers.validators import validate_commit_sha
|
|
12
|
+
from codecov_cli.runners import get_runner
|
|
13
|
+
from codecov_cli.runners.types import (
|
|
14
|
+
LabelAnalysisRequestResult,
|
|
15
|
+
LabelAnalysisRunnerInterface,
|
|
16
|
+
)
|
|
17
|
+
from codecov_cli.types import CommandContext
|
|
18
|
+
|
|
19
|
+
logger = logging.getLogger("codecovcli")
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
@click.command(hidden=True, deprecated=True)
|
|
23
|
+
@click.option(
|
|
24
|
+
"--token",
|
|
25
|
+
required=True,
|
|
26
|
+
envvar="CODECOV_STATIC_TOKEN",
|
|
27
|
+
help="The static analysis token (NOT the same token as upload)",
|
|
28
|
+
)
|
|
29
|
+
@click.option(
|
|
30
|
+
"--head-sha",
|
|
31
|
+
"head_commit_sha",
|
|
32
|
+
help="Commit SHA (with 40 chars)",
|
|
33
|
+
cls=CodecovOption,
|
|
34
|
+
fallback_field=FallbackFieldEnum.commit_sha,
|
|
35
|
+
callback=validate_commit_sha,
|
|
36
|
+
required=True,
|
|
37
|
+
)
|
|
38
|
+
@click.option(
|
|
39
|
+
"--base-sha",
|
|
40
|
+
"base_commit_sha",
|
|
41
|
+
help="Commit SHA (with 40 chars)",
|
|
42
|
+
cls=CodecovOption,
|
|
43
|
+
callback=validate_commit_sha,
|
|
44
|
+
required=True,
|
|
45
|
+
)
|
|
46
|
+
@click.option(
|
|
47
|
+
"--runner-name", "--runner", "runner_name", help="Runner to use", default="pytest"
|
|
48
|
+
)
|
|
49
|
+
@click.option(
|
|
50
|
+
"--max-wait-time",
|
|
51
|
+
"max_wait_time",
|
|
52
|
+
help="Max time (in seconds) to wait for the label analysis result before falling back to running all tests. Default is to wait forever.",
|
|
53
|
+
default=None,
|
|
54
|
+
type=int,
|
|
55
|
+
)
|
|
56
|
+
@click.option(
|
|
57
|
+
"--dry-run",
|
|
58
|
+
"dry_run",
|
|
59
|
+
help=(
|
|
60
|
+
"Print list of tests to run AND tests skipped AND options that need to be added to the test runner to stdout. "
|
|
61
|
+
+ "Choose format with --dry-run-format option. Default is JSON. "
|
|
62
|
+
),
|
|
63
|
+
is_flag=True,
|
|
64
|
+
)
|
|
65
|
+
@click.option(
|
|
66
|
+
"--dry-run-format",
|
|
67
|
+
"dry_run_format",
|
|
68
|
+
type=click.Choice(["json", "space-separated-list"]),
|
|
69
|
+
help="Format in which --dry-run data is printed. Default is JSON.",
|
|
70
|
+
default="json",
|
|
71
|
+
)
|
|
72
|
+
@click.option(
|
|
73
|
+
"--runner-param",
|
|
74
|
+
"runner_params",
|
|
75
|
+
multiple=True,
|
|
76
|
+
)
|
|
77
|
+
@click.pass_context
|
|
78
|
+
def label_analysis(
|
|
79
|
+
ctx: CommandContext,
|
|
80
|
+
token: str,
|
|
81
|
+
head_commit_sha: str,
|
|
82
|
+
base_commit_sha: str,
|
|
83
|
+
runner_name: str,
|
|
84
|
+
max_wait_time: str,
|
|
85
|
+
dry_run: bool,
|
|
86
|
+
dry_run_format: str,
|
|
87
|
+
runner_params: List[str],
|
|
88
|
+
):
|
|
89
|
+
with sentry_sdk.start_transaction(op="task", name="Label Analysis"):
|
|
90
|
+
with sentry_sdk.start_span(name="labelanalysis"):
|
|
91
|
+
args = get_cli_args(ctx)
|
|
92
|
+
logger.debug(
|
|
93
|
+
"Starting label analysis",
|
|
94
|
+
extra=dict(
|
|
95
|
+
extra_log_attributes=args,
|
|
96
|
+
),
|
|
97
|
+
)
|
|
98
|
+
if head_commit_sha == base_commit_sha:
|
|
99
|
+
logger.error(
|
|
100
|
+
"Base and head sha can't be the same",
|
|
101
|
+
extra=dict(
|
|
102
|
+
extra_log_attributes=dict(
|
|
103
|
+
head_commit_sha=head_commit_sha,
|
|
104
|
+
base_commit_sha=base_commit_sha,
|
|
105
|
+
)
|
|
106
|
+
),
|
|
107
|
+
)
|
|
108
|
+
raise click.ClickException(
|
|
109
|
+
click.style("Unable to run label analysis", fg="red")
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
codecov_yaml = ctx.obj["codecov_yaml"] or {}
|
|
113
|
+
cli_config = codecov_yaml.get("cli", {})
|
|
114
|
+
# Raises error if no runner is found
|
|
115
|
+
parsed_runner_params = _parse_runner_params(runner_params)
|
|
116
|
+
runner = get_runner(cli_config, runner_name, parsed_runner_params)
|
|
117
|
+
logger.debug(
|
|
118
|
+
f"Selected runner: {runner}",
|
|
119
|
+
extra=dict(extra_log_attributes=dict(config=runner.params)),
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
logger.info("Collecting labels...")
|
|
123
|
+
requested_labels = runner.collect_tests()
|
|
124
|
+
logger.info(f"Collected {len(requested_labels)} test labels")
|
|
125
|
+
logger.debug(
|
|
126
|
+
"Labels collected",
|
|
127
|
+
extra=dict(
|
|
128
|
+
extra_log_attributes=dict(labels_collected=requested_labels)
|
|
129
|
+
),
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
_fallback_to_collected_labels(
|
|
133
|
+
requested_labels,
|
|
134
|
+
runner,
|
|
135
|
+
dry_run=dry_run,
|
|
136
|
+
dry_run_format=dry_run_format,
|
|
137
|
+
fallback_reason="codecov_unavailable",
|
|
138
|
+
)
|
|
139
|
+
return
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
def _parse_runner_params(runner_params: List[str]) -> Dict[str, str]:
|
|
143
|
+
"""Parses the structured list of dynamic runner params into a dictionary.
|
|
144
|
+
Structure is `key=value`. If value is a list make it comma-separated.
|
|
145
|
+
If the list item doesn't have '=' we consider it the key and set to None.
|
|
146
|
+
|
|
147
|
+
EXAMPLE:
|
|
148
|
+
runner_params = ['key=value', 'null_item', 'list=item1,item2,item3']
|
|
149
|
+
_parse_runner_params(runner_params) == {
|
|
150
|
+
'key': 'value',
|
|
151
|
+
'null_item': None,
|
|
152
|
+
'list': ['item1', 'item2', 'item3']
|
|
153
|
+
}
|
|
154
|
+
"""
|
|
155
|
+
final_params = {}
|
|
156
|
+
for param in runner_params:
|
|
157
|
+
# Emit warning if param is not well formatted
|
|
158
|
+
# Using == 0 rather than != 1 because there might be
|
|
159
|
+
# a good reason for the param to include '=' in the value.
|
|
160
|
+
if param.count("=") == 0:
|
|
161
|
+
logger.warning(
|
|
162
|
+
f"Runner param {param} is not well formatted. Setting value to None. Use '--runner-param key=value' to set value"
|
|
163
|
+
)
|
|
164
|
+
final_params[param] = None
|
|
165
|
+
else:
|
|
166
|
+
key, value = param.split("=", 1)
|
|
167
|
+
# For list values we need to split the list too
|
|
168
|
+
if "," in value:
|
|
169
|
+
value = value.split(",")
|
|
170
|
+
final_params[key] = value
|
|
171
|
+
return final_params
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
def _dry_run_json_output(
|
|
175
|
+
labels_to_run: set,
|
|
176
|
+
labels_to_skip: set,
|
|
177
|
+
runner_options: List[str],
|
|
178
|
+
fallback_reason: str = None,
|
|
179
|
+
) -> None:
|
|
180
|
+
output_as_dict = dict(
|
|
181
|
+
runner_options=runner_options,
|
|
182
|
+
ats_tests_to_run=sorted(labels_to_run),
|
|
183
|
+
ats_tests_to_skip=sorted(labels_to_skip),
|
|
184
|
+
ats_fallback_reason=fallback_reason,
|
|
185
|
+
)
|
|
186
|
+
# ⚠️ DON'T use logger
|
|
187
|
+
# logger goes to stderr, we want it in stdout
|
|
188
|
+
click.echo(json.dumps(output_as_dict))
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
def _dry_run_list_output(
|
|
192
|
+
labels_to_run: set,
|
|
193
|
+
labels_to_skip: set,
|
|
194
|
+
runner_options: List[str],
|
|
195
|
+
fallback_reason: str = None,
|
|
196
|
+
) -> None:
|
|
197
|
+
if fallback_reason:
|
|
198
|
+
logger.warning(f"label-analysis didn't run correctly. Error: {fallback_reason}")
|
|
199
|
+
|
|
200
|
+
to_run_line = " ".join(
|
|
201
|
+
sorted(map(lambda option: f"'{option}'", runner_options))
|
|
202
|
+
+ sorted(map(lambda label: f"'{label}'", labels_to_run))
|
|
203
|
+
)
|
|
204
|
+
to_skip_line = " ".join(
|
|
205
|
+
sorted(map(lambda option: f"'{option}'", runner_options))
|
|
206
|
+
+ sorted(map(lambda label: f"'{label}'", labels_to_skip))
|
|
207
|
+
)
|
|
208
|
+
# ⚠️ DON'T use logger
|
|
209
|
+
# logger goes to stderr, we want it in stdout
|
|
210
|
+
click.echo(f"TESTS_TO_RUN={to_run_line}")
|
|
211
|
+
click.echo(f"TESTS_TO_SKIP={to_skip_line}")
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
def _dry_run_output(
|
|
215
|
+
result: LabelAnalysisRequestResult,
|
|
216
|
+
runner: LabelAnalysisRunnerInterface,
|
|
217
|
+
dry_run_format: str,
|
|
218
|
+
*,
|
|
219
|
+
# If we have a fallback reason it means that calculating the list of tests to run
|
|
220
|
+
# failed at some point. So it was not a completely successful task.
|
|
221
|
+
fallback_reason: str = None,
|
|
222
|
+
):
|
|
223
|
+
labels_to_run = set(
|
|
224
|
+
result.absent_labels + result.global_level_labels + result.present_diff_labels
|
|
225
|
+
)
|
|
226
|
+
labels_to_skip = set(result.present_report_labels) - labels_to_run
|
|
227
|
+
|
|
228
|
+
format_lookup = {
|
|
229
|
+
"json": _dry_run_json_output,
|
|
230
|
+
"space-separated-list": _dry_run_list_output,
|
|
231
|
+
}
|
|
232
|
+
# Because dry_run_format is a click.Choice we can
|
|
233
|
+
# be sure the value will be in the dict of choices
|
|
234
|
+
fn_to_use = format_lookup[dry_run_format]
|
|
235
|
+
fn_to_use(
|
|
236
|
+
labels_to_run, labels_to_skip, runner.dry_run_runner_options, fallback_reason
|
|
237
|
+
)
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
def _fallback_to_collected_labels(
|
|
241
|
+
collected_labels: List[str],
|
|
242
|
+
runner: LabelAnalysisRunnerInterface,
|
|
243
|
+
*,
|
|
244
|
+
fallback_reason: str = None,
|
|
245
|
+
dry_run: bool = False,
|
|
246
|
+
dry_run_format: Optional[pathlib.Path] = None,
|
|
247
|
+
) -> dict:
|
|
248
|
+
logger.info("Trying to fallback on collected labels")
|
|
249
|
+
if collected_labels:
|
|
250
|
+
logger.info("Using collected labels as tests to run")
|
|
251
|
+
fake_response = LabelAnalysisRequestResult(
|
|
252
|
+
{
|
|
253
|
+
"present_report_labels": [],
|
|
254
|
+
"absent_labels": collected_labels,
|
|
255
|
+
"present_diff_labels": [],
|
|
256
|
+
"global_level_labels": [],
|
|
257
|
+
}
|
|
258
|
+
)
|
|
259
|
+
if not dry_run:
|
|
260
|
+
return runner.process_labelanalysis_result(fake_response)
|
|
261
|
+
else:
|
|
262
|
+
return _dry_run_output(
|
|
263
|
+
LabelAnalysisRequestResult(fake_response),
|
|
264
|
+
runner,
|
|
265
|
+
dry_run_format,
|
|
266
|
+
fallback_reason=fallback_reason,
|
|
267
|
+
)
|
|
268
|
+
logger.error("Cannot fallback to collected labels because no labels were collected")
|
|
269
|
+
raise click.ClickException("Failed to get list of labels to run")
|