Skip to content
This repository was archived by the owner on Jul 16, 2025. It is now read-only.

Commit 5fff113

Browse files
committed
Merge branch 'master' into dana/base-picking-command
2 parents 0b82e6b + ce8c3ea commit 5fff113

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+2317
-179
lines changed

.github/workflows/ci.yml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,10 @@ jobs:
1818
pip install black==22.3.0 isort==5.10.1
1919
- name: Check linting with black
2020
run: |
21-
black --check .
21+
black --check codecov_cli
2222
- name: Check imports order with isort
2323
run: |
24-
isort --check --profile=black .
24+
isort --check --profile=black codecov_cli
2525
2626
2727
build:
@@ -38,6 +38,9 @@ jobs:
3838
uses: actions/setup-python@v3
3939
with:
4040
python-version: "3.10"
41+
- name: Git Sumbodule Update
42+
run: |
43+
git pull --recurse-submodules
4144
- name: Install dependencies
4245
run: |
4346
python -m pip install --upgrade pip

.github/workflows/python-package.yml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,18 @@ jobs:
1414
runs-on: ubuntu-latest
1515
steps:
1616
- uses: actions/checkout@v3
17+
with:
18+
submodules: true
1719
- name: Install dependencies
1820
run: |
1921
python -m pip install --upgrade pip
2022
pip install black==22.3.0 isort==5.10.1
2123
- name: Check linting with black
2224
run: |
23-
black --check .
25+
black --check codecov_cli
2426
- name: Check imports order with isort
2527
run: |
26-
isort --check --profile=black .
28+
isort --check --profile=black codecov_cli -p staticcodecov_languages
2729
2830
2931
build:
@@ -35,6 +37,7 @@ jobs:
3537
steps:
3638
- uses: actions/checkout@v3
3739
with:
40+
submodules: true
3841
fetch-depth: 2
3942
- name: Set up Python 3.10
4043
uses: actions/setup-python@v3

.gitmodules

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
[submodule "languages/treesitterpython"]
2+
path = languages/treesitterpython
3+
url = [email protected]:tree-sitter/tree-sitter-python.git
4+
[submodule "languages/treesitterjavascript"]
5+
path = languages/treesitterjavascript
6+
url = [email protected]:tree-sitter/tree-sitter-javascript.git

Makefile

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
name ?= codecovcli
2+
3+
lint:
4+
pip install black==22.3.0 isort==5.10.1
5+
black .
6+
isort --profile black .

README.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,20 @@ WIP
4444

4545
# Development
4646

47+
## Requirements
48+
49+
To start, most of this package is a normal Python package. The main different thing is the static analysis tool that uses both git submodules and c code
50+
51+
Before installing, one should pull the submodules with
52+
53+
```
54+
git submodule update --init
55+
```
56+
57+
The c code shouldn't require anything on most places, but it might ask you to install compilers and stuff. Most of the times you can find the instructions online given the error messsage
58+
59+
## Guidelines
60+
4761
There are a few guidelines when developing in this systems. We have a few notable folders:
4862

4963
1. `commands` - It's the folder that interacts with the caller. This is where the commands themselves should live. They are not meant to do heavy lifting. They only do wiring, which is mostly parsing the input parameters

codecov_cli/commands/base_picking.py

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -72,9 +72,4 @@ def pr_base_picking(
7272
)
7373
return
7474

75-
res = base_picking_logic(base_sha, pr, slug, token, service)
76-
if not res.error:
77-
logger.info(
78-
"Base picking finished successfully",
79-
extra=dict(extra_log_attributes=dict(response=res.text)),
80-
)
75+
base_picking_logic(base_sha, pr, slug, token, service)
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
import logging
2+
import pprint
3+
import subprocess
4+
import time
5+
6+
import click
7+
import requests
8+
9+
from codecov_cli.fallbacks import CodecovOption, FallbackFieldEnum
10+
11+
logger = logging.getLogger("codecovcli")
12+
13+
14+
@click.command()
15+
@click.option("--token", required=True)
16+
@click.option(
17+
"--head-sha",
18+
"head_commit_sha",
19+
help="Commit SHA (with 40 chars)",
20+
cls=CodecovOption,
21+
fallback_field=FallbackFieldEnum.commit_sha,
22+
required=True,
23+
)
24+
@click.option(
25+
"--base-sha",
26+
"base_commit_sha",
27+
help="Commit SHA (with 40 chars)",
28+
cls=CodecovOption,
29+
required=True,
30+
)
31+
def label_analysis(token, head_commit_sha, base_commit_sha):
32+
url = "https://api.codecov.io/labels/labels-analysis"
33+
token_header = f"Repotoken {token}"
34+
# this needs to be more flexible to support multiple elements
35+
runner = ThisRunner()
36+
requested_labels = runner.collect_tests()
37+
payload = {
38+
"base_commit": base_commit_sha,
39+
"head_commit": head_commit_sha,
40+
"requested_labels": requested_labels,
41+
}
42+
try:
43+
response = requests.post(
44+
url, json=payload, headers={"Authorization": token_header}
45+
)
46+
if response.status_code >= 500:
47+
raise click.ClickException("Sorry. Codecov is having problems")
48+
if response.status_code >= 400:
49+
logger.warning(
50+
"Got a 4XX status code back from Codecov",
51+
extra=dict(
52+
extra_log_attributes=dict(
53+
status_code=response.status_code, response_json=response.json()
54+
)
55+
),
56+
)
57+
raise click.ClickException(
58+
"There is some problem with the submitted information"
59+
)
60+
except requests.RequestException:
61+
raise click.ClickException(click.style("Unable to reach Codecov", fg="red"))
62+
eid = response.json()["external_id"]
63+
has_result = False
64+
logger.info("Label request sent")
65+
time.sleep(2)
66+
while not has_result:
67+
resp_data = requests.get(
68+
f"https://api.codecov.io/labels/labels-analysis/{eid}",
69+
headers={"Authorization": token_header},
70+
)
71+
resp_json = resp_data.json()
72+
if resp_json["state"] == "finished":
73+
runner.do_something_with_result(resp_data.json()["result"])
74+
return
75+
if resp_json["state"] == "error":
76+
logger.error(
77+
"Request had problems calculating",
78+
extra=dict(extra_log_attributes=dict(resp_json=resp_json)),
79+
)
80+
return
81+
logger.info("Waiting more time for result")
82+
time.sleep(5)
83+
84+
85+
class ThisRunner(object):
86+
def collect_tests(self):
87+
return [
88+
x
89+
for x in subprocess.run(
90+
["python", "-m", "pytest", "-q", "--collect-only"],
91+
capture_output=True,
92+
check=True,
93+
)
94+
.stdout.decode()
95+
.split()
96+
if "::" in x
97+
]
98+
99+
def do_something_with_result(self, result):
100+
command_array = ["python", "-m", "pytest", "--cov=./", "--cov-context=test"]
101+
all_labels = (
102+
result["absent_labels"]
103+
+ result["present_diff_labels"]
104+
+ result["global_level_labels"]
105+
)
106+
all_labels = set(all_labels)
107+
all_labels = [x.rsplit("[", 1)[0] if "[" in x else x for x in all_labels]
108+
# Not safe from the customer perspective, in general, probably.
109+
# This is just to check it working
110+
command_array.extend(all_labels)
111+
logger.info(
112+
"Running Pytest command",
113+
extra=dict(extra_log_attributes=dict(command_array=command_array)),
114+
)
115+
subprocess.run(command_array, check=True)
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import asyncio
2+
import pathlib
3+
4+
import click
5+
6+
from codecov_cli.fallbacks import CodecovOption, FallbackFieldEnum
7+
from codecov_cli.services.staticanalysis import run_analysis_entrypoint
8+
9+
10+
@click.command()
11+
@click.option(
12+
"--foldertosearch",
13+
default=".",
14+
help="Folder to search",
15+
type=click.Path(path_type=pathlib.Path),
16+
)
17+
@click.option(
18+
"--numberprocesses", type=click.INT, default=None, help="number of processes to use"
19+
)
20+
@click.option("--pattern", default="*", help="file pattern to search for")
21+
@click.option("--force/--no-force", default=False)
22+
@click.option(
23+
"--commit-sha",
24+
"commit",
25+
help="Commit SHA (with 40 chars)",
26+
cls=CodecovOption,
27+
fallback_field=FallbackFieldEnum.commit_sha,
28+
required=True,
29+
)
30+
@click.option("--token")
31+
@click.pass_context
32+
def static_analysis(
33+
ctx, foldertosearch, numberprocesses, pattern, commit, token, force
34+
):
35+
return asyncio.run(
36+
run_analysis_entrypoint(
37+
ctx.obj["codecov_yaml"],
38+
foldertosearch,
39+
numberprocesses,
40+
pattern,
41+
commit,
42+
token,
43+
force,
44+
)
45+
)

codecov_cli/commands/upload.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,13 @@ def _turn_env_vars_into_dict(ctx, params, value):
153153
is_flag=True,
154154
help="Exit with non-zero code in case of error uploading.",
155155
)
156+
@click.option(
157+
"-d",
158+
"--dry-run",
159+
"dry_run",
160+
is_flag=True,
161+
help="Don't upload files to Codecov",
162+
)
156163
@click.option("--use-new-uploader", "is_using_new_uploader", default=False)
157164
@click.pass_context
158165
def do_upload(
@@ -176,6 +183,7 @@ def do_upload(
176183
pull_request_number: typing.Optional[str],
177184
is_using_new_uploader: bool,
178185
fail_on_error: bool,
186+
dry_run: bool,
179187
):
180188
versioning_system = ctx.obj["versioning_system"]
181189
codecov_yaml = ctx.obj["codecov_yaml"] or {}
@@ -228,4 +236,5 @@ def do_upload(
228236
pull_request_number=pull_request_number,
229237
is_using_new_uploader=is_using_new_uploader,
230238
fail_on_error=fail_on_error,
239+
dry_run=dry_run,
231240
)

codecov_cli/helpers/ci_adapters/__init__.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,14 @@ def get_ci_adapter(provider_name: str = None):
2424
if provider_name:
2525
for provider in get_ci_providers_list():
2626
if provider.get_service_name().lower() == provider_name.lower():
27+
logger.debug(f"Using ci service from provider name: {provider_name}")
2728
return provider
2829
else:
2930
for provider in get_ci_providers_list():
3031
if provider.detect():
31-
logger.info(f"Found ci service {provider._get_service()}")
32+
logger.info(f"ci service found: {provider._get_service()}")
3233
return provider
34+
logger.warning("No ci adapter found")
3335
return None
3436

3537

0 commit comments

Comments
 (0)