Skip to content

Commit 61a474e

Browse files
committed
workers: revision worker implementation
- add abstract Worker class (bug 1744327) - add main worker flag and capacity/throttle flags - add many to many fields + association to revisions/landing jobs - add method to parse diff and list affected files - add more test coverage for revision_worker.py - add mots integration (bug 1740107) - add new RevisionWorker that pre-processes revisions (bug 1788728) - add new RevisionWorker that pre-processes revisions (bug 1788728) - add new start/stop commands to manage workers - add new flags to stop workers gracefully (*_WORKER_STOPPED) - add patch caching on disk - add proper loop/process functionality to workers - add repo.use_revision_worker feature flag (bug 1788732) - add mots hashes check - improved edge search functionality - implement stack hashes to detect changes in revisions (via get_stack_hashes) - include new Lando revision info via API endpoint - refactor dependency and stack fetching and parsing using networkx - refactored revision worker and landing worker to use Worker class - remove s3/boto/etc. dependencies (bug 1753728) - rename old command lando-cli landing-worker to lando-cli start-landing-worker - run pre/post mots query - store mots output in revision model
1 parent 58e7257 commit 61a474e

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+3166
-1538
lines changed

.flake8

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[flake8]
22
max-line-length = 88
33
select = C,E,F,W,B,B9
4-
ignore = E203, E501, W503, B006
4+
ignore = E203, E501, W503, B006, E712, E711
55
exclude =
66
.hg,
77
.git,

Dockerfile

+6-1
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,13 @@ RUN cd / && pip install --no-cache /app
5050
ENV PYTHONPATH /app
5151
RUN chown -R app:app /app
5252

53-
# Create repos directory for transplanting in landing-worker
53+
# Create repos directory for landing-worker and revision worker.
5454
RUN mkdir /repos
55+
RUN chown -R app:app /repos
56+
57+
# Create patches directory to cache patches.
58+
RUN mkdir /patches
59+
RUN chown -R app:app /patches
5560

5661
# Run as a non-privileged user
5762
USER app

Dockerfile-dev

+6
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ ENV PYTHONUNBUFFERED=1
2020
ENV FLASK_RUN_PORT=9000
2121
ENV FLASK_RUN_HOST=0.0.0.0
2222
ENV FLASK_DEBUG=1
23+
ENV HTTP_ALLOWED=1
2324

2425
ENTRYPOINT ["lando-cli"]
2526
CMD ["run"]
@@ -48,9 +49,14 @@ RUN cd / && pip install --no-cache /app
4849
ENV PYTHONPATH /app
4950
RUN chown -R app:app /app
5051

52+
# Create repos directory for landing worker and revision worker.
5153
RUN mkdir /repos
5254
RUN chown -R app:app /repos
5355

56+
# Create patches directory to store cached patches.
57+
RUN mkdir /patches
58+
RUN chown -R app:app /patches
59+
5460
# Run as a non-privileged user
5561
USER app
5662

docker-compose.yml

+13-12
Original file line numberDiff line numberDiff line change
@@ -131,25 +131,24 @@ services:
131131
- smtp
132132
lando-api.landing-worker:
133133
image: lando-api
134-
command: ["landing-worker"]
134+
command: ["start-landing-worker"]
135135
environment:
136-
- ENV=localdev
137-
- DATABASE_URL=postgresql://postgres:[email protected]/lando_api_dev
138-
- SENTRY_DSN=
139-
# See http://docs.celeryproject.org/en/stable/getting-started/brokers/redis.html#configuration
140-
# for the full URL format.
141-
- CELERY_BROKER_URL=redis://redis.queue/0
142-
- OIDC_IDENTIFIER=https://lando-api.test
143-
- OIDC_DOMAIN=https://auth0.test
144-
- LANDO_UI_URL=https://lando.test
145-
- REPO_CLONES_PATH=/repos
146-
- REPOS_TO_LAND=localdev
136+
CELERY_BROKER_URL: "redis://redis.queue/0"
137+
DATABASE_URL: "postgresql://postgres:[email protected]/lando_api_dev"
138+
ENV: "localdev"
139+
LANDO_UI_URL: "https://lando.test"
140+
OIDC_DOMAIN: "https://auth0.test"
141+
OIDC_IDENTIFIER: "https://lando-api.test"
142+
REPOS_TO_LAND: "localdev"
143+
REPO_CLONES_PATH: "/repos"
144+
SENTRY_DSN: ""
147145
user: root
148146
volumes:
149147
- ./:/app
150148
- ./migrations/:/migrations/
151149
# Prevent writing python cache to the host.
152150
- caches_cache:/app/.cache/
151+
- repos:/repos
153152
depends_on:
154153
- lando-api.db
155154
- redis.queue
@@ -177,3 +176,5 @@ volumes:
177176
caches_pycache:
178177
caches_cache:
179178
caches_pytest_cache:
179+
repos:
180+
patches:

landoapi/api/landing_jobs.py

+1-2
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,7 @@ def put(landing_job_id, data):
6262
)
6363

6464
if landing_job.status in (LandingJobStatus.SUBMITTED, LandingJobStatus.DEFERRED):
65-
landing_job.transition_status(LandingJobAction.CANCEL)
66-
db.session.commit()
65+
landing_job.transition_status(LandingJobAction.CANCEL, commit=True, db=db)
6766
return {"id": landing_job.id}, 200
6867
else:
6968
raise ProblemException(

landoapi/api/revisions.py

+13
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
from landoapi import auth
1111
from landoapi.decorators import require_phabricator_api_key
1212
from landoapi.models import SecApprovalRequest
13+
from landoapi.models.revisions import Revision
1314
from landoapi.projects import get_secure_project_phid
1415
from landoapi.revisions import revision_is_secure
1516
from landoapi.secapproval import send_sanitized_commit_message_for_review
@@ -90,3 +91,15 @@ def request_sec_approval(data=None):
9091
db.session.commit()
9192

9293
return {}, 200
94+
95+
96+
def get_stack_hashes(revision_id):
97+
"""
98+
Given a revision, returns revision stack hashes.
99+
100+
A stack hash is used to detect a change in a revision.
101+
"""
102+
revision = Revision.query.filter(Revision.id == revision_id).one_or_none()
103+
if revision:
104+
return revision.stack_hashes, 200
105+
return {}, 404

landoapi/api/stacks.py

+22-18
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88
from flask import current_app, g
99
from landoapi.commit_message import format_commit_message
1010
from landoapi.decorators import require_phabricator_api_key
11-
from landoapi.phabricator import PhabricatorClient, PhabricatorAPIException
11+
from landoapi.models.revisions import Revision
12+
from landoapi.phabricator import PhabricatorClient
1213
from landoapi.projects import (
1314
get_sec_approval_project_phid,
1415
get_secure_project_phid,
@@ -69,12 +70,7 @@ def get(revision_id):
6970
if revision is None:
7071
return not_found_problem
7172

72-
try:
73-
nodes, edges = build_stack_graph(phab, phab.expect(revision, "phid"))
74-
except PhabricatorAPIException:
75-
# If a revision within the stack causes an API exception, treat the whole stack
76-
# as not found.
77-
return not_found_problem
73+
nodes, edges = build_stack_graph(revision)
7874
stack_data = request_extended_revision_data(phab, [phid for phid in nodes])
7975

8076
supported_repos = get_repos_for_env(current_app.config.get("ENVIRONMENT"))
@@ -111,20 +107,25 @@ def get(revision_id):
111107
}
112108

113109
revisions_response = []
114-
for _phid, revision in stack_data.revisions.items():
115-
revision_phid = PhabricatorClient.expect(revision, "phid")
116-
fields = PhabricatorClient.expect(revision, "fields")
110+
for _phid, phab_revision in stack_data.revisions.items():
111+
lando_revision = Revision.query.filter(
112+
Revision.revision_id == phab_revision["id"]
113+
).one_or_none()
114+
revision_phid = PhabricatorClient.expect(phab_revision, "phid")
115+
fields = PhabricatorClient.expect(phab_revision, "fields")
117116
diff_phid = PhabricatorClient.expect(fields, "diffPHID")
118117
repo_phid = PhabricatorClient.expect(fields, "repositoryPHID")
119118
diff = stack_data.diffs[diff_phid]
120-
human_revision_id = "D{}".format(PhabricatorClient.expect(revision, "id"))
119+
human_revision_id = "D{}".format(PhabricatorClient.expect(phab_revision, "id"))
121120
revision_url = urllib.parse.urljoin(
122121
current_app.config["PHABRICATOR_URL"], human_revision_id
123122
)
124-
secure = revision_is_secure(revision, secure_project_phid)
125-
commit_description = find_title_and_summary_for_display(phab, revision, secure)
126-
bug_id = get_bugzilla_bug(revision)
127-
reviewers = get_collated_reviewers(revision)
123+
secure = revision_is_secure(phab_revision, secure_project_phid)
124+
commit_description = find_title_and_summary_for_display(
125+
phab, phab_revision, secure
126+
)
127+
bug_id = get_bugzilla_bug(phab_revision)
128+
reviewers = get_collated_reviewers(phab_revision)
128129
accepted_reviewers = reviewers_for_commit_message(
129130
reviewers, users, projects, sec_approval_project_phid
130131
)
@@ -159,16 +160,16 @@ def get(revision_id):
159160
{
160161
"id": human_revision_id,
161162
"phid": revision_phid,
162-
"status": serialize_status(revision),
163+
"status": serialize_status(phab_revision),
163164
"blocked_reason": blocked.get(revision_phid, ""),
164165
"bug_id": bug_id,
165166
"title": commit_description.title,
166167
"url": revision_url,
167168
"date_created": PhabricatorClient.to_datetime(
168-
PhabricatorClient.expect(revision, "fields", "dateCreated")
169+
PhabricatorClient.expect(phab_revision, "fields", "dateCreated")
169170
).isoformat(),
170171
"date_modified": PhabricatorClient.to_datetime(
171-
PhabricatorClient.expect(revision, "fields", "dateModified")
172+
PhabricatorClient.expect(phab_revision, "fields", "dateModified")
172173
).isoformat(),
173174
"summary": commit_description.summary,
174175
"commit_message_title": commit_message_title,
@@ -179,6 +180,9 @@ def get(revision_id):
179180
"reviewers": serialize_reviewers(reviewers, users, projects, diff_phid),
180181
"is_secure": secure,
181182
"is_using_secure_commit_message": commit_description.sanitized,
183+
"lando_revision": lando_revision.serialize()
184+
if lando_revision
185+
else None,
182186
}
183187
)
184188

0 commit comments

Comments
 (0)