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

Commit 3c39e1a

Browse files
authored
Merge branch 'main' into feature/remove-circle
2 parents 64ea1d6 + b09e9cc commit 3c39e1a

10 files changed

Lines changed: 90 additions & 36 deletions

File tree

.github/workflows/ci.yml

Lines changed: 12 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -20,43 +20,37 @@ jobs:
2020

2121
lint:
2222
name: Run Lint
23-
uses: codecov/gha-workflows/.github/workflows/lint.yml@v1.0.0
23+
uses: codecov/gha-workflows/.github/workflows/lint.yml@v1.2.0
2424

2525
build:
2626
name: Build API
27-
uses: codecov/gha-workflows/.github/workflows/build-app.yml@v1.0.0
27+
uses: codecov/gha-workflows/.github/workflows/build-app.yml@v1.2.0
2828
secrets: inherit
2929
with:
3030
repo: ${{ vars.CODECOV_IMAGE_V2 || 'codecov/self-hosted-api' }}
3131

32-
33-
codecovstartup:
34-
name: Codecov Startup
35-
needs: build
36-
uses: codecov/gha-workflows/.github/workflows/[email protected]
37-
secrets: inherit
38-
3932
ats:
4033
name: ATS
41-
needs: [build, codecovstartup]
34+
needs: [build]
4235
if: ${{ !github.event.pull_request.head.repo.fork && github.repository_owner == 'codecov' }}
43-
uses: codecov/gha-workflows/.github/workflows/run-ats.yml@v1.0.0
36+
uses: codecov/gha-workflows/.github/workflows/run-ats.yml@v1.2.0
4437
secrets: inherit
4538
with:
4639
repo: ${{ vars.CODECOV_IMAGE_V2 || 'codecov/self-hosted-api' }}
47-
40+
codecov_cli_upload_args: '--plugin pycoverage --plugin compress-pycoverage --flag smart-labels'
41+
app_container_name: api
4842
test:
4943
name: Test
50-
needs: [build, codecovstartup]
51-
uses: codecov/gha-workflows/.github/workflows/run-tests.yml@v1.0.0
44+
needs: [build]
45+
uses: codecov/gha-workflows/.github/workflows/run-tests.yml@v1.2.0
5246
secrets: inherit
5347
with:
5448
repo: ${{ vars.CODECOV_IMAGE_V2 || 'codecov/self-hosted-api' }}
5549

5650
build-self-hosted:
5751
name: Build Self Hosted API
5852
needs: [build, test]
59-
uses: codecov/gha-workflows/.github/workflows/self-hosted.yml@v1.0.0
53+
uses: codecov/gha-workflows/.github/workflows/self-hosted.yml@v1.2.0
6054
secrets: inherit
6155
with:
6256
repo: ${{ vars.CODECOV_IMAGE_V2 || 'codecov/self-hosted-api' }}
@@ -65,7 +59,7 @@ jobs:
6559
name: Push Staging Image
6660
needs: [build, test]
6761
if: ${{ github.event_name == 'push' && github.event.ref == 'refs/heads/staging' && github.repository_owner == 'codecov' }}
68-
uses: codecov/gha-workflows/.github/workflows/push-env.yml@v1.0.0
62+
uses: codecov/gha-workflows/.github/workflows/push-env.yml@v1.2.0
6963
secrets: inherit
7064
with:
7165
environment: staging
@@ -75,7 +69,7 @@ jobs:
7569
name: Push Production Image
7670
needs: [ build, test ]
7771
if: ${{ github.event_name == 'push' && github.event.ref == 'refs/heads/main' && github.repository_owner == 'codecov' }}
78-
uses: codecov/gha-workflows/.github/workflows/push-env.yml@v1.0.0
72+
uses: codecov/gha-workflows/.github/workflows/push-env.yml@v1.2.0
7973
secrets: inherit
8074
with:
8175
environment: production
@@ -86,7 +80,7 @@ jobs:
8680
needs: [ build-self-hosted, test ]
8781
secrets: inherit
8882
if: ${{ github.event_name == 'push' && github.event.ref == 'refs/heads/main' && github.repository_owner == 'codecov' }}
89-
uses: codecov/gha-workflows/.github/workflows/self-hosted.yml@v1.0.0
83+
uses: codecov/gha-workflows/.github/workflows/self-hosted.yml@v1.2.0
9084
with:
9185
push_rolling: true
9286
repo: ${{ vars.CODECOV_IMAGE_V2 || 'codecov/self-hosted-api' }}

.github/workflows/self-hosted-release-pr.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,5 @@ on:
1010
jobs:
1111
create-release-pr:
1212
name: Create PR for Release ${{ github.event.inputs.versionName }}
13-
uses: codecov/gha-workflows/.github/workflows/create-self-hosted-pr.yml@v1.0.0
13+
uses: codecov/gha-workflows/.github/workflows/create-release-pr.yml@v1.2.0
1414
secrets: inherit

.github/workflows/self-hosted-release.yml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,15 @@ jobs:
1414
create-release:
1515
name: Tag Release ${{ github.head_ref }} and Push Docker image to Docker Hub
1616
if: ${{ github.event.pull_request.merged == true && startsWith(github.head_ref, 'release/') && github.repository_owner == 'codecov' }}
17-
uses: codecov/gha-workflows/.github/workflows/[email protected]
17+
uses: codecov/gha-workflows/.github/workflows/[email protected]
18+
with:
19+
tag_to_prepend: self-hosted-
1820
secrets: inherit
1921

2022
push-image:
2123
needs: [create-release]
2224
if: ${{ github.event.pull_request.merged == true && startsWith(github.head_ref, 'release/') && github.repository_owner == 'codecov' }}
23-
uses: codecov/gha-workflows/.github/workflows/self-hosted.yml@v1.0.0
25+
uses: codecov/gha-workflows/.github/workflows/self-hosted.yml@v1.2.0
2426
secrets: inherit
2527
with:
2628
push_release: true

Makefile

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ test_env.install_cli:
182182
pip install codecov-cli
183183

184184
test_env.container_prepare:
185-
apk add -U curl git build-base
185+
apk add -U curl git build-base jq
186186
make test_env.install_cli
187187
git config --global --add safe.directory /app
188188

@@ -200,7 +200,7 @@ test_env.upload:
200200
docker-compose exec api make test_env.container_upload CODECOV_UPLOAD_TOKEN=${CODECOV_UPLOAD_TOKEN} CODECOV_URL=${CODECOV_URL}
201201

202202
test_env.container_upload:
203-
codecovcli -u ${CODECOV_URL} do-upload --flag unit-latest-uploader --flag unit \
203+
codecovcli -u ${CODECOV_URL} upload-process --flag unit-latest-uploader --flag unit \
204204
--coverage-files-search-exclude-folder=graphql_api/types/** \
205205
--coverage-files-search-exclude-folder=api/internal/tests/unit/views/cassetes/**
206206

@@ -218,12 +218,12 @@ test_env.container_static_analysis:
218218

219219
test_env.container_label_analysis:
220220
$(shell codecovcli label-analysis --base-sha=${merge_sha} --token=${CODECOV_STATIC_TOKEN} --dry-run --dry-run-output-path=tests_to_run > /dev/null)
221-
sed -i 's/--cov-context=test//g' tests_to_run
222-
sed -i 's/\s\+/\n/g' tests_to_run
223-
python -m pytest --cov=./ --cov-context=test `cat tests_to_run`
221+
jq -r '.ats_tests_to_run []' tests_to_run.json | sed s/\"//g > test_list
222+
jq -r '.runner_options | join(" ")' tests_to_run.json | sed s/\"//g > args
223+
python -m pytest --cov=./ `cat args` `cat test_list`
224224

225225
test_env.container_ats:
226-
codecovcli --codecov-yml-path=codecov_cli.yml do-upload --plugin pycoverage --plugin compress-pycoverage --flag smart-labels --fail-on-error
226+
codecovcli --codecov-yml-path=codecov_cli.yml upload-process --plugin pycoverage --plugin compress-pycoverage --flag smart-labels --fail-on-error
227227

228228
test_env:
229229
make test_env.up

graphql_api/tests/test_pull.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,7 @@ def test_when_pr_is_first_pr_in_repo(self):
195195
repository=self.repository,
196196
title="dummy-first-pr",
197197
author=self.owner,
198+
compared_to=None,
198199
)
199200

200201
res = self.fetch_one_pull_request(first_pr.pullid)

graphql_api/types/pull/pull.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,10 +54,11 @@ def is_first_pull_request(pull: Pull):
5454

5555
@pull_bindable.field("compareWithBase")
5656
async def resolve_compare_with_base(pull, info, **kwargs):
57-
if await is_first_pull_request(pull):
58-
return FirstPullRequest()
5957
if not pull.compared_to:
60-
return MissingBaseCommit()
58+
if await is_first_pull_request(pull):
59+
return FirstPullRequest()
60+
else:
61+
return MissingBaseCommit()
6162
if not pull.head:
6263
return MissingHeadCommit()
6364

labelanalysis/serializers.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from rest_framework import exceptions, serializers
2+
from shared.metrics import metrics
23

34
from core.models import Commit
45
from labelanalysis.models import (
@@ -22,21 +23,25 @@ def to_internal_value(self, commit_sha):
2223
commitid=commit_sha,
2324
).first()
2425
if commit is None:
26+
metrics.incr("label_analysis_request.errors.commit_not_found")
2527
raise exceptions.NotFound(f"Commit {commit_sha[:7]} not found.")
2628
if commit.staticanalysissuite_set.exists():
2729
return commit
2830
if not self.accepts_fallback:
31+
metrics.incr("label_analysis_request.errors.static_analysis_not_found")
2932
raise serializers.ValidationError("No static analysis found")
3033
attempted_commits = []
3134
for _ in range(10):
3235
attempted_commits.append(commit.commitid)
3336
commit = commit.parent_commit
3437
if commit is None:
38+
metrics.incr("label_analysis_request.errors.static_analysis_not_found")
3539
raise serializers.ValidationError(
3640
f"No possible commits have static analysis sent. Attempted commits: {','.join(attempted_commits)}"
3741
)
3842
if commit.staticanalysissuite_set.exists():
3943
return commit
44+
metrics.incr("label_analysis_request.errors.static_analysis_not_found")
4045
raise serializers.ValidationError(
4146
f"No possible commits have static analysis sent. Attempted too many commits: {','.join(attempted_commits)}"
4247
)
@@ -67,9 +72,11 @@ class LabelAnalysisRequestSerializer(serializers.ModelSerializer):
6772

6873
def validate(self, data):
6974
if data["base_commit"] == data["head_commit"]:
75+
metrics.incr("label_analysis_request.errors.base_head_equal")
7076
raise serializers.ValidationError(
7177
{"base_commit": "Base and head must be different commits"}
7278
)
79+
metrics.incr("label_analysis_request.count")
7380
return data
7481

7582
class Meta:

staticanalysis/serializers.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import math
33

44
from rest_framework import exceptions, serializers
5+
from shared.metrics import metrics
56

67
from core.models import Commit
78
from services.archive import ArchiveService, MinioEndpoints
@@ -153,4 +154,13 @@ def create(self, validated_data):
153154
created_ids=[f.id for f in created_filepaths], repoid=repository.repoid
154155
),
155156
)
157+
metrics.gauge(
158+
"static_analysis.suite.files_created",
159+
len(file_metadata_array) - len(existing_values_mapping),
160+
)
161+
metrics.gauge("static_analysis.suite.total_files", len(file_metadata_array))
162+
metrics.gauge(
163+
"static_analysis.suite.existing_files", len(existing_values_mapping)
164+
)
165+
metrics.incr("static_analysis.suite.count")
156166
return obj

upload/views/legacy.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,7 @@ def post(self, request, *args, **kwargs):
325325
analytics_upload_data["repository_name"] = repository.name
326326
analytics_upload_data["version"] = version
327327
analytics_upload_data["userid_type"] = "org"
328+
analytics_upload_data["uploader_type"] = "node uploader"
328329
AnalyticsService().account_uploaded_coverage_report(
329330
owner.ownerid, analytics_upload_data
330331
)

upload/views/uploads.py

Lines changed: 44 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,13 @@
1010
from codecov_auth.authentication.repo_auth import (
1111
GlobalTokenAuthentication,
1212
OrgLevelTokenAuthentication,
13+
OrgLevelTokenRepositoryAuth,
1314
RepositoryLegacyTokenAuthentication,
1415
)
16+
from codecov_auth.models import OrganizationLevelToken
1517
from core.models import Commit, Repository
1618
from reports.models import CommitReport, ReportSession
19+
from services.analytics import AnalyticsService
1720
from services.archive import ArchiveService, MinioEndpoints
1821
from services.redis_configuration import get_redis_connection
1922
from upload.helpers import dispatch_upload_task, validate_activated_repo
@@ -51,18 +54,21 @@ def perform_create(self, serializer: UploadSerializer):
5154
validate_activated_repo(repository)
5255
commit = self.get_commit(repository)
5356
report = self.get_report(commit)
57+
version = (
58+
serializer.validated_data["version"]
59+
if "version" in serializer.validated_data
60+
else None
61+
)
5462
log.info(
5563
"Request to create new upload",
5664
extra=dict(
5765
repo=repository.name,
5866
commit=commit.commitid,
59-
cli_version=serializer.validated_data["version"]
60-
if "version" in serializer.validated_data
61-
else None,
67+
cli_version=version,
6268
),
6369
)
64-
if "version" in serializer.validated_data:
65-
metrics.incr("upload.cli." + f"{serializer.validated_data['version']}")
70+
if version:
71+
metrics.incr("upload.cli." + f"{version}")
6672
archive_service = ArchiveService(repository)
6773
instance: ReportSession = serializer.save(
6874
report_id=report.id,
@@ -81,7 +87,7 @@ def perform_create(self, serializer: UploadSerializer):
8187
self.trigger_upload_task(repository, commit.commitid, instance, report)
8288
metrics.incr("uploads.accepted", 1)
8389
self.activate_repo(repository)
84-
90+
self.send_analytics_data(commit, instance, version)
8591
return instance
8692

8793
def list(
@@ -123,6 +129,38 @@ def activate_repo(self, repository):
123129
repository.deleted = False
124130
repository.save(update_fields=["activated", "active", "deleted", "updatestamp"])
125131

132+
def send_analytics_data(self, commit: Commit, upload: ReportSession, version):
133+
token = self.get_token(commit)
134+
analytics_upload_data = {
135+
"commit": commit.commitid,
136+
"branch": commit.branch,
137+
"pr": commit.pullid,
138+
"repo": commit.repository.name,
139+
"repository_name": commit.repository.name,
140+
"repository_id": commit.repository.repoid,
141+
"service": commit.repository.service,
142+
"build": upload.build_code,
143+
"build_url": upload.build_url,
144+
"flags": ",".join(upload.flag_names),
145+
"owner": commit.repository.author.ownerid,
146+
"token": str(token),
147+
"version": version,
148+
"uploader_type": "CLI",
149+
}
150+
AnalyticsService().account_uploaded_coverage_report(
151+
commit.repository.author.ownerid, analytics_upload_data
152+
)
153+
154+
def get_token(self, commit: Commit):
155+
repo = commit.repository
156+
if isinstance(self.request.auth, OrgLevelTokenRepositoryAuth):
157+
token = (
158+
OrganizationLevelToken.objects.filter(owner=repo.author).first().token
159+
)
160+
else:
161+
token = repo.upload_token
162+
return token
163+
126164
def get_repo(self) -> Repository:
127165
try:
128166
repo = super().get_repo()

0 commit comments

Comments
 (0)