Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: Remove deprecated utcnow fn #757

Merged
merged 5 commits into from
Aug 19, 2024
Merged

Conversation

ajay-sentry
Copy link
Contributor

@ajay-sentry ajay-sentry commented Aug 16, 2024

Purpose/Motivation

Saw there was a python warning in my IDE that utcnow is a deprecated function

Related blog post from late 2023 -- https://blog.miguelgrinberg.com/post/it-s-time-for-a-change-datetime-utcnow-is-now-deprecated

correct way now is to use .now(UTC) instead; all the changes in this PR are basically just find and replace and import UTC when necessary

Relevant stackoverflow post: https://stackoverflow.com/questions/15307623/cant-compare-naive-and-aware-datetime-now-challenge-datetime-end for why we had to chain .replace(tzinfo=None) to some calls

Links to relevant tickets

What does this PR do?

Remove deprecation warnings related to utcnow()

Screenshot 2024-08-16 at 2 04 15 PM Screenshot 2024-08-16 at 2 04 29 PM

Notes to Reviewer

Anything to note to the team? Any tips on how to review, or where to start?

Legal Boilerplate

Look, I get it. The entity doing business as "Sentry" was incorporated in the State of Delaware in 2015 as Functional Software, Inc. In 2022 this entity acquired Codecov and as result Sentry is going to need some rights from me in order to utilize my contributions in this PR. So here's the deal: I retain all rights, title and interest in and to my contributions, and by keeping this boilerplate intact I confirm that Sentry can use, modify, copy, and redistribute my contributions, under Sentry's choice of terms.

@ajay-sentry ajay-sentry requested a review from a team as a code owner August 16, 2024 21:12
nora-codecov
nora-codecov previously approved these changes Aug 16, 2024
@nora-codecov nora-codecov dismissed their stale review August 16, 2024 21:18

unit tests failing - can re-review when they're passing

@codecov-staging
Copy link

codecov-staging bot commented Aug 16, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

✅ All tests successful. No failed tests found.

📢 Thoughts on this report? Let us know!

@codecov-qa
Copy link

codecov-qa bot commented Aug 16, 2024

❌ 10 Tests Failed:

Tests completed Failed Passed Skipped
2252 10 2242 6
View the top 3 failed tests by shortest run time
upload.tests.test_upload.UploadHandlerAzureTokenlessTest�test_azure_wrong_build_number
Stack Traces | 0.003s run time
self = <upload.tests.test_upload.UploadHandlerAzureTokenlessTest testMethod=test_azure_wrong_build_number>
mock_get = <MagicMock name='get' id='140530873407856'>

@patch.object(requests, "get")
def test_azure_wrong_build_number(self, mock_get):
expected_response = {
"finishTime": f"{datetime.now(UTC)}",
"buildNumber": "BADBUILDNUM",
"status": "completed",
"sourceVersion": "c739768fcac68144a3a6d82305b9c4106934d31a",
"project": {"visibility": "public"},
"repository": {"type": "GitHub"},
}
mock_get.return_value.status_code.return_value = 200
mock_get.return_value.json.return_value = expected_response

params = {
"project": "project123",
"job": 732059764,
"server_uri": "https://dev.azure.com/example/",
"commit": "c739768fcac68144a3a6d82305b9c4106934d31a",
"build": "20190725.8",
}

expected_error = """Build numbers do not match. Please upload with the Codecov repository upload token to resolve issue."""

with pytest.raises(NotFound) as e:
> TokenlessUploadHandler("azure_pipelines", params).verify_upload()

upload/tests/test_upload.py:2303:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
upload/tokenless/tokenless.py:48: in verify_upload
return self.verifier(self.upload_params).verify()
upload/tokenless/azure.py:81: in verify
buildFinishDateObj = datetime.strptime(
.../local/lib/python3.12/_strptime.py:554: in _strptime_datetime
tt, fraction, gmtoff_fraction = _strptime(data_string, format)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

data_string = '2024-08-16 21:15:54.165404+00:00'
format = '%Y-%m-%d %H:%M:%S.%f'

def _strptime(data_string, format="%a %b %d %H:%M:%S %Y"):
"""Return a 2-tuple consisting of a time struct and an int containing
the number of microseconds based on the input string and the
format string."""

for index, arg in enumerate([data_string, format]):
if not isinstance(arg, str):
msg = "strptime() argument {} must be str, not {}"
raise TypeError(msg.format(index, type(arg)))

global _TimeRE_cache, _regex_cache
with _cache_lock:
locale_time = _TimeRE_cache.locale_time
if (_getlang() != locale_time.lang or
time.tzname != locale_time.tzname or
time.daylight != locale_time.daylight):
_TimeRE_cache = TimeRE()
_regex_cache.clear()
locale_time = _TimeRE_cache.locale_time
if len(_regex_cache) > _CACHE_MAX_SIZE:
_regex_cache.clear()
format_regex = _regex_cache.get(format)
if not format_regex:
try:
format_regex = _TimeRE_cache.compile(format)
# KeyError raised when a bad format is found; can be specified as
# \\, in which case it was a stray % but with a space after it
except KeyError as err:
bad_directive = err.args[0]
if bad_directive == "\\":
bad_directive = "%"
del err
raise ValueError("'%s' is a bad directive in format '%s'" %
(bad_directive, format)) from None
# IndexError only occurs when the format string is "%"
except IndexError:
raise ValueError("stray %% in format '%s'" % format) from None
_regex_cache[format] = format_regex
found = format_regex.match(data_string)
if not found:
raise ValueError("time data %r does not match format %r" %
(data_string, format))
if len(data_string) != found.end():
> raise ValueError("unconverted data remains: %s" %
data_string[found.end():])
E ValueError: unconverted data remains: +00:00

.../local/lib/python3.12/_strptime.py:336: ValueError
upload.tests.test_upload.UploadHandlerGithubActionsTokenlessTest�test_underscore_replace
Stack Traces | 0.003s run time
self = <upload.tokenless.tokenless.TokenlessUploadHandler object at 0x7fcff0554110>

def verify_upload(self):
log.info(
f"Started {self.ci_type} tokenless upload",
extra=dict(
commit=self.upload_params.get("commit"),
repo_name=self.upload_params.get("repo"),
job=self.upload_params.get("job"),
owner=self.upload_params.get("owner"),
),
)
try:
> return self.verifier(self.upload_params).verify()

upload/tokenless/tokenless.py:48:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <upload.tokenless.github_actions.TokenlessGithubActionsHandler object at 0x7fcff0556b70>

def verify(self):
if not self.upload_params.get("owner"):
raise NotFound(
'Missing "owner" argument. Please upload with the Codecov repository upload token to resolve issue.'
)
owner = self.upload_params.get("owner")

if not self.upload_params.get("repo"):
raise NotFound(
'Missing "repo" argument. Please upload with the Codecov repository upload token to resolve issue.'
)
repo = self.upload_params.get("repo")

build = self.get_build()

if (
build["public"] != True
or build["slug"] != f"{owner}/{repo}"
or (
build["commit_sha"] != self.upload_params.get("commit")
and self.upload_params.get("pr") is None
)
):
self.log_warning(
message="Repository slug or commit sha do not match Github actions arguments"
)
raise NotFound(
"Repository slug or commit sha do not match Github actions build. Please upload with the Codecov repository upload token to resolve issue."
)

# Check if current status is correct (not stale or in progress)
if build.get("status") not in ["in_progress", "queued"]:
# Verify workflow finished within the last 4 minutes because it's not in-progress
try:
build_finish_date_obj = datetime.strptime(
build["finish_time"], "%Y-%m-%dT%H:%M:%SZ"
)
except ValueError:
build_finish_date_obj = datetime.strptime(
build["finish_time"], "%Y-%m-%d %H:%M:%S"
)

finish_time_with_buffer = build_finish_date_obj + timedelta(minutes=10)
now = datetime.now(UTC)
> if not now <= finish_time_with_buffer:
E TypeError: can't compare offset-naive and offset-aware datetimes

upload/tokenless/github_actions.py:120: TypeError

During handling of the above exception, another exception occurred:

self = <upload.tests.test_upload.UploadHandlerGithubActionsTokenlessTest testMethod=test_underscore_replace>
mock_get = <PropertyMock name='get_build' id='140531067079040'>

@patch(
"upload.tokenless.github_actions.TokenlessGithubActionsHandler.get_build",
new_callable=PropertyMock,
)
def test_underscore_replace(self, mock_get):
expected_response = {
"commit_sha": "c739768fcac68144a3a6d82305b9c4106934d31a",
"slug": "owner/repo",
"public": True,
"finish_time": f"{datetime.now(UTC)}".split(".")[0],
}
mock_get.return_value.status_code.return_value = 200
mock_get.return_value.return_value = expected_response

params = {
"build": "12.34",
"owner": "owner",
"repo": "repo",
"commit": "c739768fcac68144a3a6d82305b9c4106934d31a",
}

> assert (
TokenlessUploadHandler("github-actions", params).verify_upload() == "github"
)

upload/tests/test_upload.py:2742:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <upload.tokenless.tokenless.TokenlessUploadHandler object at 0x7fcff0554110>

def verify_upload(self):
log.info(
f"Started {self.ci_type} tokenless upload",
extra=dict(
commit=self.upload_params.get("commit"),
repo_name=self.upload_params.get("repo"),
job=self.upload_params.get("job"),
owner=self.upload_params.get("owner"),
),
)
try:
return self.verifier(self.upload_params).verify()
except TypeError:
> raise NotFound(
"Your CI provider is not compatible with tokenless uploads, please upload using your repository token to resolve this."
)
E rest_framework.exceptions.NotFound: Your CI provider is not compatible with tokenless uploads, please upload using your repository token to resolve this.

upload/tokenless/tokenless.py:50: NotFound
upload.tests.test_upload.UploadHandlerTravisTokenlessTest�test_success
Stack Traces | 0.003s run time
self = <upload.tokenless.tokenless.TokenlessUploadHandler object at 0x7fcfe4e44c50>

def verify_upload(self):
log.info(
f"Started {self.ci_type} tokenless upload",
extra=dict(
commit=self.upload_params.get("commit"),
repo_name=self.upload_params.get("repo"),
job=self.upload_params.get("job"),
owner=self.upload_params.get("owner"),
),
)
try:
> return self.verifier(self.upload_params).verify()

upload/tokenless/tokenless.py:48:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <upload.tokenless.travis.TokenlessTravisHandler object at 0x7fcff031b0b0>

def verify(self):
# find repo in travis.com
job = self.get_build()

slug = f"{self.upload_params['owner']}/{self.upload_params['repo']}"

codecovUrl = f"https://codecov.io/gh/{self.upload_params['owner']}/{self.upload_params['repo']}/settings"

# Check repo slug and commit sha
# We check commit sha only for a push event since sha in arguments will not match if event type = pull request
if (
job["repository"]["slug"] != slug
or job["commit"]["sha"] != self.upload_params["commit"]
and job["build"]["event_type"] != "pull_request"
):
log.warning(
f"Repository slug: {slug} or commit sha: {self.upload_params['commit']} do not match travis arguments",
extra=dict(
commit=self.upload_params["commit"],
repo_name=self.upload_params["repo"],
job=self.upload_params["job"],
owner=self.upload_params["owner"],
),
)
raise NotFound(
errors["travis"]["tokenless-general-error"].format(codecovUrl)
)

# Verify job finished within the last 4 minutes or is still in progress
if job["finished_at"] is not None:
finishTimestamp = job["finished_at"].replace("T", " ").replace("Z", "")
buildFinishDateObj = datetime.strptime(finishTimestamp, "%Y-%m-%d %H:%M:%S")
finishTimeWithBuffer = buildFinishDateObj + timedelta(minutes=4)
now = datetime.now(UTC)
> if not now <= finishTimeWithBuffer:
E TypeError: can't compare offset-naive and offset-aware datetimes

upload/tokenless/travis.py:125: TypeError

During handling of the above exception, another exception occurred:

self = <upload.tests.test_upload.UploadHandlerTravisTokenlessTest testMethod=test_success>
mock_get = <MagicMock name='get' id='140530875130192'>

@patch.object(requests, "get")
def test_success(self, mock_get):
expected_response = {
"id": 732059764,
"allow_failure": None,
"number": "498.1",
"state": "passed",
"started_at": "2020-10-01T20:02:55Z",
"finished_at": f"{datetime.now(UTC)}".split(".")[0],
"build": {
"@type": "build",
"@href": "/build/732059763",
"@representation": "minimal",
"id": 732059763,
"number": "498",
"state": "passed",
"duration": 84,
"event_type": "push",
"previous_state": "passed",
"pull_request_title": None,
"pull_request_number": None,
"started_at": "2020-10-01T20:01:31Z",
"finished_at": "2020-10-01T20:02:55Z",
"private": False,
"priority": False,
},
"queue": "builds.gce",
"repository": {
"@type": "repository",
"@href": "/repo/25205338",
"@representation": "minimal",
"id": 25205338,
"name": "python-standard",
"slug": "codecov/codecov-api",
},
"commit": {
"@type": "commit",
"@representation": "minimal",
"id": 226208830,
"sha": "3be5c52bd748c508a7e96993c02cf3518c816e84",
"ref": "refs/heads/master",
"message": "New Build: 10/01/20 20:00:54",
"compare_url": "https://github..../python-standard/compare/28392734979c...2485b28f9862",
"committed_at": "2020-10-01T20:00:55Z",
},
}
mock_get.return_value.status_code.return_value = 200
mock_get.return_value.json.return_value = expected_response

params = {
"version": "v4",
"commit": "3be5c52bd748c508a7e96993c02cf3518c816e84",
"slug": "codecov/codecov-api",
"owner": "codecov",
"repo": "codecov-api",
"token": "4a24929b-9276-4784-8e85-a7a008a32037",
"service": "circleci",
"pr": None,
"pull_request": None,
"flags": "this-is-a-flag,this-is-another-flag",
"param_doesn't_exist_but_still_should_not_error": True,
"s3": 123,
"build_url": "https://thisisabuildurl.com",
"job": 732059764,
"using_global_token": False,
"branch": None,
"_did_change_merge_commit": False,
"parent": "123abc",
}

> res = TokenlessUploadHandler("travis", params).verify_upload()

upload/tests/test_upload.py:2057:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <upload.tokenless.tokenless.TokenlessUploadHandler object at 0x7fcfe4e44c50>

def verify_upload(self):
log.info(
f"Started {self.ci_type} tokenless upload",
extra=dict(
commit=self.upload_params.get("commit"),
repo_name=self.upload_params.get("repo"),
job=self.upload_params.get("job"),
owner=self.upload_params.get("owner"),
),
)
try:
return self.verifier(self.upload_params).verify()
except TypeError:
> raise NotFound(
"Your CI provider is not compatible with tokenless uploads, please upload using your repository token to resolve this."
)
E rest_framework.exceptions.NotFound: Your CI provider is not compatible with tokenless uploads, please upload using your repository token to resolve this.

upload/tokenless/tokenless.py:50: NotFound

To view individual test run time comparison to the main branch, go to the Test Analytics Dashboard

Copy link

Test Failures Detected: Due to failing tests, we cannot provide coverage reports at this time.

❌ Failed Test Results:

Completed 2258 tests with 10 failed, 2242 passed and 6 skipped.

View the full list of failed tests

pytest

  • Class name: codecov_auth.commands.owner.interactors.tests.test_cancel_trial.CancelTrialInteractorTest
    Test name: test_cancel_trial_starts_trial_for_org_that_has_trial_ongoing

    self = <codecov_auth.commands.owner.interactors.tests.test_cancel_trial.CancelTrialInteractorTest testMethod=test_cancel_trial_starts_trial_for_org_that_has_trial_ongoing>

    @freeze_time("2022-01-01T00:00:00")
    def test_cancel_trial_starts_trial_for_org_that_has_trial_ongoing(self):
    now = datetime.now(UTC)
    trial_start_date = now
    trial_end_date = now + timedelta(days=3)
    current_user: Owner = OwnerFactory(
    username="random-user-123",
    service="github",
    trial_start_date=trial_start_date,
    trial_end_date=trial_end_date,
    trial_status=TrialStatus.ONGOING.value,
    plan=PlanName.TRIAL_PLAN_NAME.value,
    )
    self.execute(current_user=current_user, org_username=current_user.username)
    current_user.refresh_from_db()

    now = datetime.now(UTC)
    > assert current_user.trial_end_date == now
    E assert datetime.datetime(2022, 1, 1, 0, 0) == FakeDatetime(2022, 1, 1, 0, 0, tzinfo=datetime.timezone.utc)
    E + where datetime.datetime(2022, 1, 1, 0, 0) = <Owner: Owner<github/random-user-123>>.trial_end_date

    .../interactors/tests/test_cancel_trial.py:90: AssertionError
  • Class name: codecov_auth.commands.owner.interactors.tests.test_start_trial.StartTrialInteractorTest
    Test name: test_start_trial_starts_trial_for_org_that_has_not_started_trial_before_and_calls_segment

    self = <codecov_auth.commands.owner.interactors.tests.test_start_trial.StartTrialInteractorTest testMethod=test_start_trial_starts_trial_for_org_that_has_not_started_trial_before_and_calls_segment>

    @freeze_time("2022-01-01T00:00:00")
    def test_start_trial_starts_trial_for_org_that_has_not_started_trial_before_and_calls_segment(
    self,
    ):
    current_user: Owner = OwnerFactory(
    username="random-user-123",
    service="github",
    trial_start_date=None,
    trial_end_date=None,
    trial_status=TrialStatus.NOT_STARTED.value,
    )
    self.execute(current_user=current_user, org_username=current_user.username)
    current_user.refresh_from_db()

    now = datetime.now(UTC)
    > assert current_user.trial_start_date == now
    E assert datetime.datetime(2022, 1, 1, 0, 0) == FakeDatetime(2022, 1, 1, 0, 0, tzinfo=datetime.timezone.utc)
    E + where datetime.datetime(2022, 1, 1, 0, 0) = <Owner: Owner<github/random-user-123>>.trial_start_date

    .../interactors/tests/test_start_trial.py:107: AssertionError
  • Class name: upload.tests.test_upload.UploadHandlerAzureTokenlessTest
    Test name: test_azure_expired_build

    self = <upload.tests.test_upload.UploadHandlerAzureTokenlessTest testMethod=test_azure_expired_build>
    mock_get = <MagicMock name='get' id='140530875782480'>

    @patch.object(requests, "get")
    def test_azure_expired_build(self, mock_get):
    expected_response = {
    "finishTime": f"{datetime.now(UTC) - timedelta(minutes=4)}",
    "buildNumber": "20190725.8",
    "status": "completed",
    "sourceVersion": "c739768fcac68144a3a6d82305b9c4106934d31a",
    "project": {"visibility": "public"},
    "repository": {"type": "GitHub"},
    }

    mock_get.return_value.status_code.return_value = 200
    mock_get.return_value.json.return_value = expected_response

    params = {
    "project": "project123",
    "job": 732059764,
    "server_uri": "https://dev.azure.com/example/",
    "commit": "c739768fcac68144a3a6d82305b9c4106934d31a",
    "build": "20190725.8",
    }

    expected_error = """Azure build has already finished. Please upload with the Codecov repository upload token to resolve issue."""

    with pytest.raises(NotFound) as e:
    > TokenlessUploadHandler("azure_pipelines", params).verify_upload()

    upload/tests/test_upload.py:2333:
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
    upload/tokenless/tokenless.py:48: in verify_upload
    return self.verifier(self.upload_params).verify()
    upload/tokenless/azure.py:81: in verify
    buildFinishDateObj = datetime.strptime(
    .../local/lib/python3.12/_strptime.py:554: in _strptime_datetime
    tt, fraction, gmtoff_fraction = _strptime(data_string, format)
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

    data_string = '2024-08-16 21:11:53.123655+00:00'
    format = '%Y-%m-%d %H:%M:%S.%f'

    def _strptime(data_string, format="%a %b %d %H:%M:%S %Y"):
    """Return a 2-tuple consisting of a time struct and an int containing
    the number of microseconds based on the input string and the
    format string."""

    for index, arg in enumerate([data_string, format]):
    if not isinstance(arg, str):
    msg = "strptime() argument {} must be str, not {}"
    raise TypeError(msg.format(index, type(arg)))

    global _TimeRE_cache, _regex_cache
    with _cache_lock:
    locale_time = _TimeRE_cache.locale_time
    if (_getlang() != locale_time.lang or
    time.tzname != locale_time.tzname or
    time.daylight != locale_time.daylight):
    _TimeRE_cache = TimeRE()
    _regex_cache.clear()
    locale_time = _TimeRE_cache.locale_time
    if len(_regex_cache) > _CACHE_MAX_SIZE:
    _regex_cache.clear()
    format_regex = _regex_cache.get(format)
    if not format_regex:
    try:
    format_regex = _TimeRE_cache.compile(format)
    # KeyError raised when a bad format is found; can be specified as
    # \\, in which case it was a stray % but with a space after it
    except KeyError as err:
    bad_directive = err.args[0]
    if bad_directive == "\\":
    bad_directive = "%"
    del err
    raise ValueError("'%s' is a bad directive in format '%s'" %
    (bad_directive, format)) from None
    # IndexError only occurs when the format string is "%"
    except IndexError:
    raise ValueError("stray %% in format '%s'" % format) from None
    _regex_cache[format] = format_regex
    found = format_regex.match(data_string)
    if not found:
    raise ValueError("time data %r does not match format %r" %
    (data_string, format))
    if len(data_string) != found.end():
    > raise ValueError("unconverted data remains: %s" %
    data_string[found.end():])
    E ValueError: unconverted data remains: +00:00

    .../local/lib/python3.12/_strptime.py:336: ValueError
  • Class name: upload.tests.test_upload.UploadHandlerAzureTokenlessTest
    Test name: test_azure_wrong_build_number

    self = <upload.tests.test_upload.UploadHandlerAzureTokenlessTest testMethod=test_azure_wrong_build_number>
    mock_get = <MagicMock name='get' id='140530873407856'>

    @patch.object(requests, "get")
    def test_azure_wrong_build_number(self, mock_get):
    expected_response = {
    "finishTime": f"{datetime.now(UTC)}",
    "buildNumber": "BADBUILDNUM",
    "status": "completed",
    "sourceVersion": "c739768fcac68144a3a6d82305b9c4106934d31a",
    "project": {"visibility": "public"},
    "repository": {"type": "GitHub"},
    }
    mock_get.return_value.status_code.return_value = 200
    mock_get.return_value.json.return_value = expected_response

    params = {
    "project": "project123",
    "job": 732059764,
    "server_uri": "https://dev.azure.com/example/",
    "commit": "c739768fcac68144a3a6d82305b9c4106934d31a",
    "build": "20190725.8",
    }

    expected_error = """Build numbers do not match. Please upload with the Codecov repository upload token to resolve issue."""

    with pytest.raises(NotFound) as e:
    > TokenlessUploadHandler("azure_pipelines", params).verify_upload()

    upload/tests/test_upload.py:2303:
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
    upload/tokenless/tokenless.py:48: in verify_upload
    return self.verifier(self.upload_params).verify()
    upload/tokenless/azure.py:81: in verify
    buildFinishDateObj = datetime.strptime(
    .../local/lib/python3.12/_strptime.py:554: in _strptime_datetime
    tt, fraction, gmtoff_fraction = _strptime(data_string, format)
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

    data_string = '2024-08-16 21:15:54.165404+00:00'
    format = '%Y-%m-%d %H:%M:%S.%f'

    def _strptime(data_string, format="%a %b %d %H:%M:%S %Y"):
    """Return a 2-tuple consisting of a time struct and an int containing
    the number of microseconds based on the input string and the
    format string."""

    for index, arg in enumerate([data_string, format]):
    if not isinstance(arg, str):
    msg = "strptime() argument {} must be str, not {}"
    raise TypeError(msg.format(index, type(arg)))

    global _TimeRE_cache, _regex_cache
    with _cache_lock:
    locale_time = _TimeRE_cache.locale_time
    if (_getlang() != locale_time.lang or
    time.tzname != locale_time.tzname or
    time.daylight != locale_time.daylight):
    _TimeRE_cache = TimeRE()
    _regex_cache.clear()
    locale_time = _TimeRE_cache.locale_time
    if len(_regex_cache) > _CACHE_MAX_SIZE:
    _regex_cache.clear()
    format_regex = _regex_cache.get(format)
    if not format_regex:
    try:
    format_regex = _TimeRE_cache.compile(format)
    # KeyError raised when a bad format is found; can be specified as
    # \\, in which case it was a stray % but with a space after it
    except KeyError as err:
    bad_directive = err.args[0]
    if bad_directive == "\\":
    bad_directive = "%"
    del err
    raise ValueError("'%s' is a bad directive in format '%s'" %
    (bad_directive, format)) from None
    # IndexError only occurs when the format string is "%"
    except IndexError:
    raise ValueError("stray %% in format '%s'" % format) from None
    _regex_cache[format] = format_regex
    found = format_regex.match(data_string)
    if not found:
    raise ValueError("time data %r does not match format %r" %
    (data_string, format))
    if len(data_string) != found.end():
    > raise ValueError("unconverted data remains: %s" %
    data_string[found.end():])
    E ValueError: unconverted data remains: +00:00

    .../local/lib/python3.12/_strptime.py:336: ValueError
  • Class name: upload.tests.test_upload.UploadHandlerGithubActionsTokenlessTest
    Test name: test_github_actions

    self = <upload.tokenless.tokenless.TokenlessUploadHandler object at 0x7fcfe4cda990>

    def verify_upload(self):
    log.info(
    f"Started {self.ci_type} tokenless upload",
    extra=dict(
    commit=self.upload_params.get("commit"),
    repo_name=self.upload_params.get("repo"),
    job=self.upload_params.get("job"),
    owner=self.upload_params.get("owner"),
    ),
    )
    try:
    > return self.verifier(self.upload_params).verify()

    upload/tokenless/tokenless.py:48:
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

    self = <upload.tokenless.github_actions.TokenlessGithubActionsHandler object at 0x7fcff0941fa0>

    def verify(self):
    if not self.upload_params.get("owner"):
    raise NotFound(
    'Missing "owner" argument. Please upload with the Codecov repository upload token to resolve issue.'
    )
    owner = self.upload_params.get("owner")

    if not self.upload_params.get("repo"):
    raise NotFound(
    'Missing "repo" argument. Please upload with the Codecov repository upload token to resolve issue.'
    )
    repo = self.upload_params.get("repo")

    build = self.get_build()

    if (
    build["public"] != True
    or build["slug"] != f"{owner}/{repo}"
    or (
    build["commit_sha"] != self.upload_params.get("commit")
    and self.upload_params.get("pr") is None
    )
    ):
    self.log_warning(
    message="Repository slug or commit sha do not match Github actions arguments"
    )
    raise NotFound(
    "Repository slug or commit sha do not match Github actions build. Please upload with the Codecov repository upload token to resolve issue."
    )

    # Check if current status is correct (not stale or in progress)
    if build.get("status") not in ["in_progress", "queued"]:
    # Verify workflow finished within the last 4 minutes because it's not in-progress
    try:
    build_finish_date_obj = datetime.strptime(
    build["finish_time"], "%Y-%m-%dT%H:%M:%SZ"
    )
    except ValueError:
    build_finish_date_obj = datetime.strptime(
    build["finish_time"], "%Y-%m-%d %H:%M:%S"
    )

    finish_time_with_buffer = build_finish_date_obj + timedelta(minutes=10)
    now = datetime.now(UTC)
    > if not now <= finish_time_with_buffer:
    E TypeError: can't compare offset-naive and offset-aware datetimes

    upload/tokenless/github_actions.py:120: TypeError

    During handling of the above exception, another exception occurred:

    self = <upload.tests.test_upload.UploadHandlerGithubActionsTokenlessTest testMethod=test_github_actions>
    mock_get = <PropertyMock name='get_build' id='140531065923216'>

    @patch(
    "upload.tokenless.github_actions.TokenlessGithubActionsHandler.get_build",
    new_callable=PropertyMock,
    )
    def test_github_actions(self, mock_get):
    expected_response = {
    "commit_sha": "c739768fcac68144a3a6d82305b9c4106934d31a",
    "slug": "owner/repo",
    "public": True,
    "finish_time": f"{datetime.now(UTC)}".split(".")[0],
    }
    mock_get.return_value.status_code.return_value = 200
    mock_get.return_value.return_value = expected_response

    params = {
    "build": "12.34",
    "owner": "owner",
    "repo": "repo",
    "commit": "c739768fcac68144a3a6d82305b9c4106934d31a",
    }

    > assert (
    TokenlessUploadHandler("github_actions", params).verify_upload() == "github"
    )

    upload/tests/test_upload.py:2960:
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

    self = <upload.tokenless.tokenless.TokenlessUploadHandler object at 0x7fcfe4cda990>

    def verify_upload(self):
    log.info(
    f"Started {self.ci_type} tokenless upload",
    extra=dict(
    commit=self.upload_params.get("commit"),
    repo_name=self.upload_params.get("repo"),
    job=self.upload_params.get("job"),
    owner=self.upload_params.get("owner"),
    ),
    )
    try:
    return self.verifier(self.upload_params).verify()
    except TypeError:
    > raise NotFound(
    "Your CI provider is not compatible with tokenless uploads, please upload using your repository token to resolve this."
    )
    E rest_framework.exceptions.NotFound: Your CI provider is not compatible with tokenless uploads, please upload using your repository token to resolve this.

    upload/tokenless/tokenless.py:50: NotFound
  • Class name: upload.tests.test_upload.UploadHandlerGithubActionsTokenlessTest
    Test name: test_github_actions_no_build_status

    self = <upload.tests.test_upload.UploadHandlerGithubActionsTokenlessTest testMethod=test_github_actions_no_build_status>
    mock_get = <PropertyMock name='get_build' id='140531069817616'>

    @patch(
    "upload.tokenless.github_actions.TokenlessGithubActionsHandler.get_build",
    new_callable=PropertyMock,
    )
    def test_github_actions_no_build_status(self, mock_get):
    expected_response = {
    "commit_sha": "c739768fcac68144a3a6d82305b9c4106934d31a",
    "slug": "owner/repo",
    "public": True,
    "finish_time": f"{datetime.now(UTC) - timedelta(minutes=10)}".split(".")[0],
    }
    mock_get.return_value.status_code.return_value = 200
    mock_get.return_value.return_value = expected_response

    params = {
    "build": "12.34",
    "owner": "owner",
    "repo": "repo",
    "commit": "c739768fcac68144a3a6d82305b9c4106934d31a",
    }

    expected_error = """Actions workflow run is stale"""

    with pytest.raises(NotFound) as e:
    TokenlessUploadHandler("github_actions", params).verify_upload()
    > assert [line.strip() for line in e.value.args[0].split("\n")] == [
    line.strip() for line in expected_error.split("\n")
    ]
    E AssertionError: assert ['Your CI pro...esolve this.'] == ['Actions wor...run is stale']
    E
    E At index 0 diff: 'Your CI provider is not compatible with tokenless uploads, please upload using your repository token to resolve this.' != 'Actions workflow run is stale'
    E Use -v to get more diff

    upload/tests/test_upload.py:2935: AssertionError
  • Class name: upload.tests.test_upload.UploadHandlerGithubActionsTokenlessTest
    Test name: test_underscore_replace

    self = <upload.tokenless.tokenless.TokenlessUploadHandler object at 0x7fcff0554110>

    def verify_upload(self):
    log.info(
    f"Started {self.ci_type} tokenless upload",
    extra=dict(
    commit=self.upload_params.get("commit"),
    repo_name=self.upload_params.get("repo"),
    job=self.upload_params.get("job"),
    owner=self.upload_params.get("owner"),
    ),
    )
    try:
    > return self.verifier(self.upload_params).verify()

    upload/tokenless/tokenless.py:48:
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

    self = <upload.tokenless.github_actions.TokenlessGithubActionsHandler object at 0x7fcff0556b70>

    def verify(self):
    if not self.upload_params.get("owner"):
    raise NotFound(
    'Missing "owner" argument. Please upload with the Codecov repository upload token to resolve issue.'
    )
    owner = self.upload_params.get("owner")

    if not self.upload_params.get("repo"):
    raise NotFound(
    'Missing "repo" argument. Please upload with the Codecov repository upload token to resolve issue.'
    )
    repo = self.upload_params.get("repo")

    build = self.get_build()

    if (
    build["public"] != True
    or build["slug"] != f"{owner}/{repo}"
    or (
    build["commit_sha"] != self.upload_params.get("commit")
    and self.upload_params.get("pr") is None
    )
    ):
    self.log_warning(
    message="Repository slug or commit sha do not match Github actions arguments"
    )
    raise NotFound(
    "Repository slug or commit sha do not match Github actions build. Please upload with the Codecov repository upload token to resolve issue."
    )

    # Check if current status is correct (not stale or in progress)
    if build.get("status") not in ["in_progress", "queued"]:
    # Verify workflow finished within the last 4 minutes because it's not in-progress
    try:
    build_finish_date_obj = datetime.strptime(
    build["finish_time"], "%Y-%m-%dT%H:%M:%SZ"
    )
    except ValueError:
    build_finish_date_obj = datetime.strptime(
    build["finish_time"], "%Y-%m-%d %H:%M:%S"
    )

    finish_time_with_buffer = build_finish_date_obj + timedelta(minutes=10)
    now = datetime.now(UTC)
    > if not now <= finish_time_with_buffer:
    E TypeError: can't compare offset-naive and offset-aware datetimes

    upload/tokenless/github_actions.py:120: TypeError

    During handling of the above exception, another exception occurred:

    self = <upload.tests.test_upload.UploadHandlerGithubActionsTokenlessTest testMethod=test_underscore_replace>
    mock_get = <PropertyMock name='get_build' id='140531067079040'>

    @patch(
    "upload.tokenless.github_actions.TokenlessGithubActionsHandler.get_build",
    new_callable=PropertyMock,
    )
    def test_underscore_replace(self, mock_get):
    expected_response = {
    "commit_sha": "c739768fcac68144a3a6d82305b9c4106934d31a",
    "slug": "owner/repo",
    "public": True,
    "finish_time": f"{datetime.now(UTC)}".split(".")[0],
    }
    mock_get.return_value.status_code.return_value = 200
    mock_get.return_value.return_value = expected_response

    params = {
    "build": "12.34",
    "owner": "owner",
    "repo": "repo",
    "commit": "c739768fcac68144a3a6d82305b9c4106934d31a",
    }

    > assert (
    TokenlessUploadHandler("github-actions", params).verify_upload() == "github"
    )

    upload/tests/test_upload.py:2742:
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

    self = <upload.tokenless.tokenless.TokenlessUploadHandler object at 0x7fcff0554110>

    def verify_upload(self):
    log.info(
    f"Started {self.ci_type} tokenless upload",
    extra=dict(
    commit=self.upload_params.get("commit"),
    repo_name=self.upload_params.get("repo"),
    job=self.upload_params.get("job"),
    owner=self.upload_params.get("owner"),
    ),
    )
    try:
    return self.verifier(self.upload_params).verify()
    except TypeError:
    > raise NotFound(
    "Your CI provider is not compatible with tokenless uploads, please upload using your repository token to resolve this."
    )
    E rest_framework.exceptions.NotFound: Your CI provider is not compatible with tokenless uploads, please upload using your repository token to resolve this.

    upload/tokenless/tokenless.py:50: NotFound
  • Class name: upload.tests.test_upload.UploadHandlerHelpersTest
    Test name: test_determine_repo_upload_tokenless

    self = <upload.tokenless.tokenless.TokenlessUploadHandler object at 0x7fcff059f1d0>

    def verify_upload(self):
    log.info(
    f"Started {self.ci_type} tokenless upload",
    extra=dict(
    commit=self.upload_params.get("commit"),
    repo_name=self.upload_params.get("repo"),
    job=self.upload_params.get("job"),
    owner=self.upload_params.get("owner"),
    ),
    )
    try:
    > return self.verifier(self.upload_params).verify()

    upload/tokenless/tokenless.py:48:
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

    self = <upload.tokenless.travis.TokenlessTravisHandler object at 0x7fcff08d2db0>

    def verify(self):
    # find repo in travis.com
    job = self.get_build()

    slug = f"{self.upload_params['owner']}/{self.upload_params['repo']}"

    codecovUrl = f"https://codecov.io/gh/{self.upload_params['owner']}/{self.upload_params['repo']}/settings"

    # Check repo slug and commit sha
    # We check commit sha only for a push event since sha in arguments will not match if event type = pull request
    if (
    job["repository"]["slug"] != slug
    or job["commit"]["sha"] != self.upload_params["commit"]
    and job["build"]["event_type"] != "pull_request"
    ):
    log.warning(
    f"Repository slug: {slug} or commit sha: {self.upload_params['commit']} do not match travis arguments",
    extra=dict(
    commit=self.upload_params["commit"],
    repo_name=self.upload_params["repo"],
    job=self.upload_params["job"],
    owner=self.upload_params["owner"],
    ),
    )
    raise NotFound(
    errors["travis"]["tokenless-general-error"].format(codecovUrl)
    )

    # Verify job finished within the last 4 minutes or is still in progress
    if job["finished_at"] is not None:
    finishTimestamp = job["finished_at"].replace("T", " ").replace("Z", "")
    buildFinishDateObj = datetime.strptime(finishTimestamp, "%Y-%m-%d %H:%M:%S")
    finishTimeWithBuffer = buildFinishDateObj + timedelta(minutes=4)
    now = datetime.now(UTC)
    > if not now <= finishTimeWithBuffer:
    E TypeError: can't compare offset-naive and offset-aware datetimes

    upload/tokenless/travis.py:125: TypeError

    During handling of the above exception, another exception occurred:

    self = <upload.tests.test_upload.UploadHandlerHelpersTest testMethod=test_determine_repo_upload_tokenless>
    mock_get = <MagicMock name='get' id='140531066396528'>

    @patch.object(requests, "get")
    def test_determine_repo_upload_tokenless(self, mock_get):
    org = G(Owner, username="codecov", service="github")
    repo = G(Repository, author=org)
    expected_response = {
    "id": 732059764,
    "finishTime": f"{datetime.now(UTC)}",
    "status": "inProgress",
    "sourceVersion": "3be5c52bd748c508a7e96993c02cf3518c816e84",
    "buildNumber": "732059764",
    "allow_failure": None,
    "number": "498.1",
    "state": "passed",
    "started_at": "2020-10-01T20:02:55Z",
    "finished_at": f"{datetime.now(UTC)}".split(".")[0],
    "project": {"visibility": "public", "repositoryType": "github"},
    "triggerInfo": {"pr.sourceSha": "3be5c52bd748c508a7e96993c02cf3518c816e84"},
    "build": {
    "@type": "build",
    "@href": "/build/732059763",
    "@representation": "minimal",
    "id": 732059763,
    "number": "498",
    "state": "passed",
    "duration": 84,
    "event_type": "push",
    "previous_state": "passed",
    "pull_request_title": None,
    "pull_request_number": None,
    "started_at": "2020-10-01T20:01:31Z",
    "finished_at": "2020-10-01T20:02:55Z",
    "private": False,
    "priority": False,
    "jobs": [{"jobId": "732059764"}],
    },
    "queue": "builds.gce",
    "repository": {
    "@type": "repository",
    "@href": "/repo/25205338",
    "@representation": "minimal",
    "id": 25205338,
    "type": "GitHub",
    "name": "python-standard",
    "slug": f"{org.username}/{repo.name}",
    },
    "commit": {
    "@type": "commit",
    "@representation": "minimal",
    "id": 226208830,
    "sha": "3be5c52bd748c508a7e96993c02cf3518c816e84",
    "ref": "refs/heads/master",
    "message": "New Build: 10/01/20 20:00:54",
    "compare_url": "https://github..../python-standard/compare/28392734979c...2485b28f9862",
    "committed_at": "2020-10-01T20:00:55Z",
    },
    }

    mock_get.return_value.status_code.return_value = 200
    mock_get.return_value.json.return_value = expected_response

    params = {
    "version": "v4",
    "commit": "3be5c52bd748c508a7e96993c02cf3518c816e84",
    "slug": f"{org.username}/{repo.name}",
    "owner": org.username,
    "repo": repo.name,
    "service": "travis",
    "pr": None,
    "pull_request": None,
    "flags": "this-is-a-flag,this-is-another-flag",
    "param_doesn't_exist_but_still_should_not_error": True,
    "s3": 123,
    "build_url": "https://thisisabuildurl.com",
    "job": "732059764",
    "build": "732059764",
    "using_global_token": False,
    "branch": None,
    "project": "p12",
    "server_uri": "https://dev.azure.com/example/",
    "_did_change_merge_commit": False,
    "parent": "123abc",
    }

    > assert repo == determine_repo_for_upload(params)

    upload/tests/test_upload.py:414:
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
    upload/helpers.py:284: in determine_repo_for_upload
    git_service = TokenlessUploadHandler(service, upload_params).verify_upload()
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

    self = <upload.tokenless.tokenless.TokenlessUploadHandler object at 0x7fcff059f1d0>

    def verify_upload(self):
    log.info(
    f"Started {self.ci_type} tokenless upload",
    extra=dict(
    commit=self.upload_params.get("commit"),
    repo_name=self.upload_params.get("repo"),
    job=self.upload_params.get("job"),
    owner=self.upload_params.get("owner"),
    ),
    )
    try:
    return self.verifier(self.upload_params).verify()
    except TypeError:
    > raise NotFound(
    "Your CI provider is not compatible with tokenless uploads, please upload using your repository token to resolve this."
    )
    E rest_framework.exceptions.NotFound: Your CI provider is not compatible with tokenless uploads, please upload using your repository token to resolve this.

    upload/tokenless/tokenless.py:50: NotFound
  • Class name: upload.tests.test_upload.UploadHandlerTravisTokenlessTest
    Test name: test_expired_build

    self = <upload.tests.test_upload.UploadHandlerTravisTokenlessTest testMethod=test_expired_build>
    mock_get = <MagicMock name='get' id='140530875102992'>

    @patch.object(requests, "get")
    def test_expired_build(self, mock_get):
    expected_response = {
    "id": 732059764,
    "allow_failure": None,
    "number": "498.1",
    "state": "passed",
    "started_at": "2020-10-01T20:02:55Z",
    "finished_at": "2020-10-01T20:02:55Z",
    "build": {
    "@type": "build",
    "@href": "/build/732059763",
    "@representation": "minimal",
    "id": 732059763,
    "number": "498",
    "state": "passed",
    "duration": 84,
    "event_type": "push",
    "previous_state": "passed",
    "pull_request_title": None,
    "pull_request_number": None,
    "started_at": "2020-10-01T20:01:31Z",
    "finished_at": "2020-10-01T20:02:55Z",
    "private": False,
    "priority": False,
    },
    "queue": "builds.gce",
    "repository": {
    "@type": "repository",
    "@href": "/repo/25205338",
    "@representation": "minimal",
    "id": 25205338,
    "name": "python-standard",
    "slug": "codecov/codecov-api",
    },
    "commit": {
    "@type": "commit",
    "@representation": "minimal",
    "id": 226208830,
    "sha": "3be5c52bd748c508a7e96993c02cf3518c816e84",
    "ref": "refs/heads/master",
    "message": "New Build: 10/01/20 20:00:54",
    "compare_url": "https://github..../python-standard/compare/28392734979c...2485b28f9862",
    "committed_at": "2020-10-01T20:00:55Z",
    },
    }
    mock_get.return_value.status_code.return_value = 200
    mock_get.return_value.json.return_value = expected_response

    params = {
    "version": "v4",
    "commit": "3be5c52bd748c508a7e96993c02cf3518c816e84",
    "slug": "codecov/codecov-api",
    "owner": "codecov",
    "repo": "codecov-api",
    "token": "4a24929b-9276-4784-8e85-a7a008a32037",
    "service": "circleci",
    "pr": None,
    "pull_request": None,
    "flags": "this-is-a-flag,this-is-another-flag",
    "param_doesn't_exist_but_still_should_not_error": True,
    "s3": 123,
    "build_url": "https://thisisabuildurl.com",
    "job": 732059764,
    "using_global_token": False,
    "branch": None,
    "_did_change_merge_commit": False,
    "parent": "123abc",
    }

    expected_error = """
    ERROR: The coverage upload was rejected because the build is out of date. Please make sure the build is not stale for uploads to process correctly."""

    with pytest.raises(NotFound) as e:
    TokenlessUploadHandler("travis", params).verify_upload()
    > assert [line.strip() for line in e.value.args[0].split("\n")] == [
    line.strip() for line in expected_error.split("\n")
    ]
    E AssertionError: assert ['Your CI pro...esolve this.'] == ['', 'ERROR: ...s correctly.']
    E
    E At index 0 diff: 'Your CI provider is not compatible with tokenless uploads, please upload using your repository token to resolve this.' != ''
    E Right contains one more item: 'ERROR: The coverage upload was rejected because the build is out of date. Please make sure the build is not stale for uploads to process correctly.'
    E Use -v to get more diff

    upload/tests/test_upload.py:2136: AssertionError
  • Class name: upload.tests.test_upload.UploadHandlerTravisTokenlessTest
    Test name: test_success

    self = <upload.tokenless.tokenless.TokenlessUploadHandler object at 0x7fcfe4e44c50>

    def verify_upload(self):
    log.info(
    f"Started {self.ci_type} tokenless upload",
    extra=dict(
    commit=self.upload_params.get("commit"),
    repo_name=self.upload_params.get("repo"),
    job=self.upload_params.get("job"),
    owner=self.upload_params.get("owner"),
    ),
    )
    try:
    > return self.verifier(self.upload_params).verify()

    upload/tokenless/tokenless.py:48:
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

    self = <upload.tokenless.travis.TokenlessTravisHandler object at 0x7fcff031b0b0>

    def verify(self):
    # find repo in travis.com
    job = self.get_build()

    slug = f"{self.upload_params['owner']}/{self.upload_params['repo']}"

    codecovUrl = f"https://codecov.io/gh/{self.upload_params['owner']}/{self.upload_params['repo']}/settings"

    # Check repo slug and commit sha
    # We check commit sha only for a push event since sha in arguments will not match if event type = pull request
    if (
    job["repository"]["slug"] != slug
    or job["commit"]["sha"] != self.upload_params["commit"]
    and job["build"]["event_type"] != "pull_request"
    ):
    log.warning(
    f"Repository slug: {slug} or commit sha: {self.upload_params['commit']} do not match travis arguments",
    extra=dict(
    commit=self.upload_params["commit"],
    repo_name=self.upload_params["repo"],
    job=self.upload_params["job"],
    owner=self.upload_params["owner"],
    ),
    )
    raise NotFound(
    errors["travis"]["tokenless-general-error"].format(codecovUrl)
    )

    # Verify job finished within the last 4 minutes or is still in progress
    if job["finished_at"] is not None:
    finishTimestamp = job["finished_at"].replace("T", " ").replace("Z", "")
    buildFinishDateObj = datetime.strptime(finishTimestamp, "%Y-%m-%d %H:%M:%S")
    finishTimeWithBuffer = buildFinishDateObj + timedelta(minutes=4)
    now = datetime.now(UTC)
    > if not now <= finishTimeWithBuffer:
    E TypeError: can't compare offset-naive and offset-aware datetimes

    upload/tokenless/travis.py:125: TypeError

    During handling of the above exception, another exception occurred:

    self = <upload.tests.test_upload.UploadHandlerTravisTokenlessTest testMethod=test_success>
    mock_get = <MagicMock name='get' id='140530875130192'>

    @patch.object(requests, "get")
    def test_success(self, mock_get):
    expected_response = {
    "id": 732059764,
    "allow_failure": None,
    "number": "498.1",
    "state": "passed",
    "started_at": "2020-10-01T20:02:55Z",
    "finished_at": f"{datetime.now(UTC)}".split(".")[0],
    "build": {
    "@type": "build",
    "@href": "/build/732059763",
    "@representation": "minimal",
    "id": 732059763,
    "number": "498",
    "state": "passed",
    "duration": 84,
    "event_type": "push",
    "previous_state": "passed",
    "pull_request_title": None,
    "pull_request_number": None,
    "started_at": "2020-10-01T20:01:31Z",
    "finished_at": "2020-10-01T20:02:55Z",
    "private": False,
    "priority": False,
    },
    "queue": "builds.gce",
    "repository": {
    "@type": "repository",
    "@href": "/repo/25205338",
    "@representation": "minimal",
    "id": 25205338,
    "name": "python-standard",
    "slug": "codecov/codecov-api",
    },
    "commit": {
    "@type": "commit",
    "@representation": "minimal",
    "id": 226208830,
    "sha": "3be5c52bd748c508a7e96993c02cf3518c816e84",
    "ref": "refs/heads/master",
    "message": "New Build: 10/01/20 20:00:54",
    "compare_url": "https://github..../python-standard/compare/28392734979c...2485b28f9862",
    "committed_at": "2020-10-01T20:00:55Z",
    },
    }
    mock_get.return_value.status_code.return_value = 200
    mock_get.return_value.json.return_value = expected_response

    params = {
    "version": "v4",
    "commit": "3be5c52bd748c508a7e96993c02cf3518c816e84",
    "slug": "codecov/codecov-api",
    "owner": "codecov",
    "repo": "codecov-api",
    "token": "4a24929b-9276-4784-8e85-a7a008a32037",
    "service": "circleci",
    "pr": None,
    "pull_request": None,
    "flags": "this-is-a-flag,this-is-another-flag",
    "param_doesn't_exist_but_still_should_not_error": True,
    "s3": 123,
    "build_url": "https://thisisabuildurl.com",
    "job": 732059764,
    "using_global_token": False,
    "branch": None,
    "_did_change_merge_commit": False,
    "parent": "123abc",
    }

    > res = TokenlessUploadHandler("travis", params).verify_upload()

    upload/tests/test_upload.py:2057:
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

    self = <upload.tokenless.tokenless.TokenlessUploadHandler object at 0x7fcfe4e44c50>

    def verify_upload(self):
    log.info(
    f"Started {self.ci_type} tokenless upload",
    extra=dict(
    commit=self.upload_params.get("commit"),
    repo_name=self.upload_params.get("repo"),
    job=self.upload_params.get("job"),
    owner=self.upload_params.get("owner"),
    ),
    )
    try:
    return self.verifier(self.upload_params).verify()
    except TypeError:
    > raise NotFound(
    "Your CI provider is not compatible with tokenless uploads, please upload using your repository token to resolve this."
    )
    E rest_framework.exceptions.NotFound: Your CI provider is not compatible with tokenless uploads, please upload using your repository token to resolve this.

    upload/tokenless/tokenless.py:50: NotFound

Copy link

codecov bot commented Aug 16, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 96.16%. Comparing base (a93299c) to head (4eb66ea).
Report is 4 commits behind head on main.

✅ All tests successful. No failed tests found.

Additional details and impacted files
@@               Coverage Diff                @@
##               main       #757        +/-   ##
================================================
+ Coverage   96.11000   96.16000   +0.05000     
================================================
  Files           815        814         -1     
  Lines         18442      18478        +36     
================================================
+ Hits          17725      17770        +45     
+ Misses          717        708         -9     
Flag Coverage Δ
unit 91.91% <100.00%> (+0.04%) ⬆️
unit-latest-uploader 91.91% <100.00%> (+0.04%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@@ -1,4 +1,4 @@
from datetime import datetime, timedelta
from datetime import UTC, datetime, timedelta
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don’t see this import being used.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed in 4eb66ea, thanks!

@ajay-sentry ajay-sentry added this pull request to the merge queue Aug 19, 2024
Merged via the queue into main with commit daea36e Aug 19, 2024
17 of 18 checks passed
@ajay-sentry ajay-sentry deleted the Ajay/update-deprecated-utc-now branch August 19, 2024 17:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants