Skip to content

Commit

Permalink
update the task save to update and to store timestamp
Browse files Browse the repository at this point in the history
while leaving the timestamp just being crafted on our side
before the actual request is being made so it is at or before
the actual Jira timestamp not preventing the task sync-back
by the collector which will eventually correct the timestamp
in case it is in a bit of desync

this may result in a second or a few seconds desync for a short
while on the task update timestamp which is however acceptable
and will save us some Jira calls syncing the task back
synchronously which happens async by the collector later anyway
  • Loading branch information
osoukup committed Dec 3, 2024
1 parent 99fe664 commit a396209
Show file tree
Hide file tree
Showing 9 changed files with 1,646 additions and 5,836 deletions.
3 changes: 3 additions & 0 deletions apps/bbsync/tests/test_integration.py
Original file line number Diff line number Diff line change
Expand Up @@ -918,6 +918,9 @@ def test_bz_id(self):


class TestFlawDraftBBSyncIntegration:
@freeze_time(
timezone.datetime(2020, 12, 12)
) # freeze against top of the second crossing
@pytest.mark.vcr
@pytest.mark.enable_signals
@pytest.mark.parametrize(
Expand Down
4 changes: 4 additions & 0 deletions apps/workflows/tests/test_endpoints.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
from datetime import datetime

import pytest
from django.conf import settings
from freezegun import freeze_time

from apps.taskman.service import JiraTaskmanQuerier
from apps.workflows.models import State, Workflow
Expand Down Expand Up @@ -426,6 +429,7 @@ class TestFlawDraft:
def mock_create_task(self, flaw):
return "OSIM-123"

@freeze_time(datetime(2020, 12, 12)) # freeze against top of the second crossing
@pytest.mark.vcr
def test_promote(
self,
Expand Down

Large diffs are not rendered by default.

25 changes: 16 additions & 9 deletions collectors/jiraffe/tests/test_collectors.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,11 @@ def test_collect(self, enable_jira_task_sync, jira_token):
uuid = "fb145b06-82a7-4851-a429-541288633d16"
flaw = FlawFactory(uuid=uuid, embargoed=False, impact=Impact.IMPORTANT)
AffectFactory(flaw=flaw)
flaw.tasksync(force_creation=True, jira_token=jira_token)
assert flaw.impact == Impact.IMPORTANT

# freeze the time so NOW corresponds to the Jira as it is split
with freeze_time(datetime(2024, 11, 26, 12, 6, 0)):
flaw.tasksync(force_creation=True, jira_token=jira_token)
assert flaw.impact == Impact.IMPORTANT

assert flaw.task_key

Expand Down Expand Up @@ -102,35 +105,39 @@ def test_outdated_query(self, enable_jira_task_sync, jira_token, monkeypatch):

jtq = JiraTaskmanQuerier(token=jira_token)

# 1 - create a flaw with task
# 1 - create a flaw
# remove randomness for VCR usage
uuid = "e49a732a-06fe-4942-94d8-3a8b0407e827"
flaw = FlawFactory(uuid=uuid, embargoed=False, impact=Impact.IMPORTANT)
AffectFactory(flaw=flaw)
flaw.tasksync(force_creation=True, jira_token=jira_token)
assert flaw.task_key

# 2 - get the current Jira task and make sure db is in-sync
# 2 - create a task
# freezing the time so NOW corresponds to the Jira as it is split
with freeze_time(datetime(2024, 7, 22, 14, 30, 14, 665000)):
flaw.tasksync(force_creation=True, jira_token=jira_token)
assert flaw.task_key

# 3 - get the current Jira task and make sure db is in-sync
issue = jtq.jira_conn.issue(flaw.task_key)
last_update = datetime.strptime(issue.fields.updated, "%Y-%m-%dT%H:%M:%S.%f%z")
assert last_update == flaw.task_updated_dt
assert issue.fields.status.name == "New"

# 3 - freeze the issue in time to simulate long queries being outdated
# 4 - freeze the issue in time to simulate long queries being outdated
def mock_get_issue(self, jira_id: str):
return issue

monkeypatch.setattr(JiraQuerier, "get_issue", mock_get_issue)

# 4 - simulate user promoting a flaw
# 5 - simulate user promoting a flaw
flaw.workflow_state = WorkflowModel.WorkflowState.TRIAGE
# provide a fake diff just to pretend that the workflow state has changed
flaw.tasksync(diff={"workflow_state": None}, jira_token=jira_token)
flaw = Flaw.objects.get(uuid=flaw.uuid)
assert last_update < flaw.task_updated_dt
assert flaw.workflow_state == "TRIAGE"

# 5 - make sure collector does not change flaw if it is holding outdated issue
# 6 - make sure collector does not change flaw if it is holding outdated issue
collector = JiraTaskCollector()
collector.collect(flaw.task_key)
flaw = Flaw.objects.get(uuid=flaw.uuid)
Expand Down
2 changes: 2 additions & 0 deletions collectors/osv/tests/test_collectors.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from datetime import datetime, timezone

import pytest
from freezegun import freeze_time
from jira.exceptions import JIRAError

from apps.taskman.service import JiraTaskmanQuerier
Expand All @@ -13,6 +14,7 @@


class TestOSVCollector:
@freeze_time(datetime(2020, 12, 12)) # freeze against top of the second crossing
@pytest.mark.vcr
def test_collect_osv_record_without_cve(self):
"""
Expand Down
20 changes: 18 additions & 2 deletions osidb/models/flaw/flaw.py
Original file line number Diff line number Diff line change
Expand Up @@ -1051,9 +1051,14 @@ def tasksync(
old_flaw = Flaw.objects.get(uuid=self.uuid)

def _create_task():
self.task_updated_dt = timezone.now() # timestamp at or before the change
self.task_key = jtq.create_or_update_task(self)
self.workflow_state = WorkflowModel.WorkflowState.NEW
self.save(no_alerts=True, *args, **kwargs)
Flaw.objects.filter(uuid=self.uuid).update(
task_key=self.task_key,
task_updated_dt=self.task_updated_dt,
workflow_state=self.workflow_state,
)

if not JIRA_TASKMAN_AUTO_SYNC_FLAW or not jira_token:
return
Expand Down Expand Up @@ -1084,15 +1089,26 @@ def _create_task():
diff is not None
and any(field in diff.keys() for field in SYNC_REQUIRED_FIELDS)
):
self.task_updated_dt = timezone.now() # timestamp at or before the change
jtq.create_or_update_task(self)
Flaw.objects.filter(uuid=self.uuid).update(
task_updated_dt=self.task_updated_dt
)

if force_update or (
diff is not None
and any(field in diff.keys() for field in TRANSITION_REQUIRED_FIELDS)
):
self.task_updated_dt = timezone.now() # timestamp at or before the change
jtq.transition_task(self)
self.adjust_acls(save=False)
self.save(no_alerts=True, *args, **kwargs)
Flaw.objects.filter(uuid=self.uuid).update(
acl_read=self.acl_read,
acl_write=self.acl_write,
task_updated_dt=self.task_updated_dt,
workflow_name=self.workflow_name,
workflow_state=self.workflow_state,
)

download_manager = models.ForeignKey(
FlawDownloadManager, null=True, blank=True, on_delete=models.CASCADE
Expand Down
Loading

0 comments on commit a396209

Please sign in to comment.