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

Commit 7878c4d

Browse files
Merge branch 'main' into joseph/dedup
2 parents 7899cfb + e1f7b24 commit 7878c4d

File tree

17 files changed

+272
-28
lines changed

17 files changed

+272
-28
lines changed
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
name: Upload Overwatch
2+
3+
on:
4+
pull_request:
5+
types:
6+
- opened
7+
- synchronize
8+
9+
jobs:
10+
upload-overwatch:
11+
runs-on: ubuntu-latest
12+
steps:
13+
- uses: actions/checkout@v4
14+
- uses: actions/setup-python@v5
15+
with:
16+
python-version: '3.13'
17+
- name: Install UV
18+
run: pip install uv
19+
- name: Install Project Dependencies
20+
run: |
21+
uv export --format requirements-txt > requirements.txt
22+
uv pip install -r requirements.txt --system
23+
- name: Install Static Analysis Tools
24+
run: |
25+
pip install mypy==1.15.0
26+
pip install ruff==0.9.6
27+
- name: Install Build Dependencies
28+
run: |
29+
sudo apt-get update
30+
# Install libssl1.1 from Ubuntu 20.04 repositories
31+
wget http://archive.ubuntu.com/ubuntu/pool/main/o/openssl/libssl1.1_1.1.1f-1ubuntu2_amd64.deb
32+
sudo dpkg -i libssl1.1_1.1.1f-1ubuntu2_amd64.deb
33+
- name: Install Overwatch CLI
34+
run: |
35+
curl -o overwatch-cli https://overwatch.codecov.dev/linux/cli
36+
chmod +x overwatch-cli
37+
- name: Run Overwatch CLI
38+
run: |
39+
./overwatch-cli \
40+
--auth-token ${{ secrets.SENTRY_AUTH_TOKEN }} \
41+
--organization-slug codecov \
42+
python \
43+
--python-path $(which python3)

api/public/v2/report/views.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ def filter_report(
112112
# empty report since the path is not part of the component
113113
return Report()
114114

115-
component_flags = component.get_matching_flags(report.flags.keys())
115+
component_flags = component.get_matching_flags(report.get_flag_names())
116116
if flag and len(component.flag_regexes) > 0 and flag not in component_flags:
117117
# empty report since the flag is not part of the component
118118
return Report()

api/public/v2/tests/test_api_compare_viewset.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,7 @@
1313
)
1414
from shared.reports.api_report_service import SerializableReport
1515
from shared.reports.resources import Report, ReportFile
16-
from shared.reports.types import ReportLine
17-
from shared.reports.types import ReportTotals
16+
from shared.reports.types import ReportLine, ReportTotals
1817
from shared.utils.merge import LineType
1918
from shared.utils.sessions import Session
2019

codecov_auth/authentication/repo_auth.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,49 @@ def authenticate(
338338
raise exceptions.AuthenticationFailed(self.auth_failed_message)
339339

340340

341+
class TestAnalyticsTokenlessAuthentication(TokenlessAuthentication):
342+
def _get_info_from_request_path(
343+
self, request: HttpRequest
344+
) -> tuple[Repository, str | None]:
345+
try:
346+
body = json.loads(str(request.body, "utf8"))
347+
348+
# Validate provider
349+
service_enum = Service(body.get("service"))
350+
351+
# Validate that next group exists and decode slug
352+
repo = get_repository_from_string(service_enum, body.get("slug"))
353+
if repo is None:
354+
# Purposefully using the generic message so that we don't tell that
355+
# we don't have a certain repo
356+
raise exceptions.AuthenticationFailed(self.auth_failed_message)
357+
358+
return repo, body.get("commit")
359+
except json.JSONDecodeError:
360+
# Validate request body format
361+
raise exceptions.AuthenticationFailed(self.auth_failed_message)
362+
except ValueError:
363+
# Validate provider
364+
raise exceptions.AuthenticationFailed(self.auth_failed_message)
365+
366+
def get_branch(
367+
self,
368+
request: HttpRequest,
369+
repoid: Optional[int] = None,
370+
commitid: Optional[str] = None,
371+
) -> str:
372+
body = json.loads(str(request.body, "utf8"))
373+
374+
# If commit is not created yet (ie first upload for this commit), we just validate branch format.
375+
# However, if a commit exists already (ie not the first upload for this commit), we must additionally
376+
# validate the saved commit branch matches what is requested in this upload call.
377+
commit = Commit.objects.filter(repository_id=repoid, commitid=commitid).first()
378+
if commit and commit.branch != body.get("branch"):
379+
raise exceptions.AuthenticationFailed(self.auth_failed_message)
380+
381+
return body.get("branch")
382+
383+
341384
class BundleAnalysisTokenlessAuthentication(TokenlessAuthentication):
342385
def _get_info_from_request_path(
343386
self, request: HttpRequest

compare/commands/compare/interactors/fetch_impacted_files.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ def _apply_filters(
4141
components_flags = []
4242

4343
head_commit_report = comparison.head_report_without_applied_diff
44+
report_flags = head_commit_report and head_commit_report.get_flag_names()
4445
if components_filter:
4546
all_components = components.commit_components(
4647
comparison.head_commit, comparison.user
@@ -50,9 +51,7 @@ def _apply_filters(
5051
)
5152
for component in filtered_components:
5253
components_paths.extend(component.paths)
53-
components_flags.extend(
54-
component.get_matching_flags(head_commit_report.flags.keys())
55-
)
54+
components_flags.extend(component.get_matching_flags(report_flags))
5655

5756
# Flags & Components intersection
5857
if components_flags:
@@ -62,7 +61,7 @@ def _apply_filters(
6261
flags_filter = components_flags
6362

6463
if flags_filter:
65-
if set(flags_filter) & set(head_commit_report.flags):
64+
if set(flags_filter) & set(report_flags):
6665
files = files_belonging_to_flags(
6766
commit_report=head_commit_report, flags=flags_filter
6867
)

graphql_api/tests/test_branch.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,9 @@ def __iter__(self):
173173
for name in self.files:
174174
yield MockFile(name)
175175

176+
def get_flag_names(self):
177+
return ["flag_a"]
178+
176179
@property
177180
def flags(self):
178181
return {"flag-a": MockFlag()}
@@ -199,6 +202,9 @@ def __init__(self):
199202
def flags(self):
200203
return None
201204

205+
def get_flag_names(self):
206+
return []
207+
202208

203209
class TestBranch(GraphQLTestHelper, TransactionTestCase):
204210
def setUp(self):

graphql_api/tests/test_commit.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -97,9 +97,8 @@ def get(self, file, _else):
9797
def filter(self, **kwargs):
9898
return self
9999

100-
@property
101-
def flags(self):
102-
return {"flag_a": True, "flag_b": True}
100+
def get_flag_names(self):
101+
return ["flag_a", "flag_b"]
103102

104103

105104
class EmptyReport(MockReport):

graphql_api/tests/test_path_content.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,7 @@
33
from django.test import TransactionTestCase
44
from shared.django_apps.core.tests.factories import CommitFactory
55
from shared.reports.resources import Report, ReportFile
6-
from shared.reports.types import ReportLine
7-
from shared.reports.types import ReportTotals
6+
from shared.reports.types import ReportLine, ReportTotals
87
from shared.utils.sessions import Session
98

109
from services.path import Dir, File

graphql_api/types/commit/commit.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,8 @@ def get_sorted_path_contents(
160160
component_paths = []
161161
component_flags = []
162162

163+
report_flags = report.get_flag_names()
164+
163165
if component_filter:
164166
all_components = components_service.commit_components(commit, current_owner)
165167
filtered_components = components_service.filter_components_by_name_or_id(
@@ -173,18 +175,16 @@ def get_sorted_path_contents(
173175

174176
for component in filtered_components:
175177
component_paths.extend(component.paths)
176-
if report.flags:
177-
component_flags.extend(
178-
component.get_matching_flags(report.flags.keys())
179-
)
178+
if report_flags:
179+
component_flags.extend(component.get_matching_flags(report_flags))
180180

181181
if component_flags:
182182
if flags_filter:
183183
flags_filter = list(set(flags_filter) & set(component_flags))
184184
else:
185185
flags_filter = component_flags
186186

187-
if flags_filter and not report.flags:
187+
if flags_filter and not report_flags:
188188
return UnknownFlags(f"No coverage with chosen flags: {flags_filter}")
189189

190190
report_paths = ReportPaths(
@@ -325,8 +325,8 @@ def resolve_coverage_totals(
325325
@sentry_sdk.trace
326326
@commit_coverage_analytics_bindable.field("flagNames")
327327
@sync_to_async
328-
def resolve_coverage_flags(commit: Commit, info: GraphQLResolveInfo) -> List[str]:
329-
return commit.full_report.flags.keys()
328+
def resolve_coverage_flags(commit: Commit, info: GraphQLResolveInfo) -> list[str]:
329+
return commit.full_report.get_flag_names()
330330

331331

332332
@sentry_sdk.trace

graphql_api/types/comparison/comparison.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,9 @@ def resolve_impacted_files(
4545

4646
if filters and comparison:
4747
flags = filters.get("flags", [])
48-
if flags and set(flags).isdisjoint(set(comparison.head_report.flags)):
48+
if flags and set(flags).isdisjoint(
49+
set(comparison.head_report.get_flag_names())
50+
):
4951
return UnknownFlags()
5052

5153
return {

0 commit comments

Comments
 (0)