Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 25 additions & 2 deletions libmozevent/mercurial.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
import os
import tempfile
import time
from datetime import datetime
from datetime import datetime, timedelta

import hglib
import requests
Expand Down Expand Up @@ -335,12 +335,20 @@ class MercurialWorker(object):
]
]

def __init__(self, queue_name, queue_phabricator, repositories, skippable_files=[]):
def __init__(
self,
queue_name,
queue_phabricator,
repositories,
diff_expiry=timedelta(hours=24),
skippable_files=[],
):
assert all(map(lambda r: isinstance(r, Repository), repositories.values()))
self.queue_name = queue_name
self.queue_phabricator = queue_phabricator
self.repositories = repositories
self.skippable_files = skippable_files
self.diff_expiry = diff_expiry

def register(self, bus):
self.bus = bus
Expand Down Expand Up @@ -448,6 +456,21 @@ async def handle_build(self, repository, build):
build,
{"message": error_log, "duration": time.time() - start},
)
if (
build.diff.get("fields")
and build.diff["fields"].get("dateCreated")
and (
datetime.now()
- datetime.fromtimestamp(build.diff["fields"]["dateCreated"])
> self.diff_expiry
)
):
error_log = "This build is too old to push to try repository"
return (
"fail:mercurial",
build,
{"message": error_log, "duration": time.time() - start},
)
elif build.retries:
logger.warning(
"Trying to apply build's diff after a remote push error "
Expand Down
61 changes: 61 additions & 0 deletions tests/test_mercurial.py
Original file line number Diff line number Diff line change
Expand Up @@ -917,3 +917,64 @@ def test_get_base_identifier(mock_mc):
assert (
mock_mc.get_base_identifier(stack) == "tip"
), "`tip` commit should be used when `use_latest_revision` is `True`."


@responses.activate
@pytest.mark.asyncio
async def test_push_failure_diff_expiry(PhabricatorMock, mock_mc):
diff = {
"revisionPHID": "PHID-DREV-badutf8",
"baseRevision": "missing",
"phid": "PHID-DIFF-badutf8",
"id": 555,
# a date in 2017
"fields": {"dateCreated": 1510251135},
}
build = MockBuild(4444, "PHID-REPO-mc", 5555, "PHID-build-badutf8", diff)
with PhabricatorMock as phab:
phab.load_patches_stack(build)

bus = MessageBus()
bus.add_queue("phabricator")

from libmozevent import mercurial

mercurial.TRY_STATUS_URL = "http://test.status/try"

sleep_history = []

class AsyncioMock(object):
async def sleep(self, value):
nonlocal sleep_history
sleep_history.append(value)

mercurial.asyncio = AsyncioMock()

responses.get(
"http://test.status/try", status=200, json={"result": {"status": "open"}}
)

repository_mock = MagicMock(spec=Repository)

worker = MercurialWorker(
"mercurial", "phabricator", repositories={"PHID-REPO-mc": repository_mock}
)
worker.register(bus)

await bus.send("mercurial", build)
assert bus.queues["mercurial"].qsize() == 1
task = asyncio.create_task(worker.run())

# Check the treeherder link was queued
mode, out_build, details = await bus.receive("phabricator")
task.cancel()

assert build.retries == 0

assert mode == "fail:mercurial"
assert out_build == build
assert details["duration"] > 0
assert details["message"] == "This build is too old to push to try repository"

# no call sent to TRY_STATUS_URL
assert len(responses.calls) == 0