Page MenuHomePhorge

D260.1767238218.diff
No OneTemporary

Size
5 KB
Referenced Files
None
Subscribers
None

D260.1767238218.diff

diff --git a/lilybuild/lilybuild/artifacts/resource.py b/lilybuild/lilybuild/artifacts/resource.py
--- a/lilybuild/lilybuild/artifacts/resource.py
+++ b/lilybuild/lilybuild/artifacts/resource.py
@@ -5,6 +5,7 @@
from twisted.web.static import File
from buildbot.data.resultspec import ResultSpec, Property
import os
+import re
POSSIBLE_ARTIFACT_TYPES = {
'archive': 'artifacts.tar',
@@ -16,6 +17,10 @@
def validate_artifact_type(at):
return at in POSSIBLE_ARTIFACT_TYPES
+REF_NAME_REGEX = re.compile(r'^[A-Za-z0-9_\-]+$')
+def validate_ref_name(ref_name):
+ return re.match(REF_NAME_REGEX, ref_name)
+
class Api:
app = Klein()
@@ -48,13 +53,18 @@
return json.dumps({'error': NOT_FOUND})
@defer.inlineCallbacks
- def get_artifact_location(self, request, build_id, job_index, artifact_type):
+ def get_artifact_location(self, request, build_id, job_index, artifact_type, job_name=None):
+ props_to_get = [
+ 'lilybuild_repo_id',
+ 'lilybuild_source',
+ ]
+ if job_index is None and job_name is None:
+ raise FileNotFoundError('Not Found')
+ if job_index is None and job_name is not None:
+ props_to_get.append('lilybuild_job_map')
result_spec = ResultSpec(
# see popProperties in ResultSpec
- properties=[Property(b'property', 'eq', [
- 'lilybuild_repo_id',
- 'lilybuild_source',
- ])]
+ properties=[Property(b'property', 'eq', props_to_get)]
)
build = yield self.ep.master.data.get_with_resultspec(
@@ -68,6 +78,13 @@
source = 'none'
else:
source = build['properties']['lilybuild_source'][0]
+ if job_index is None:
+ if 'lilybuild_job_map' not in build['properties']:
+ raise FileNotFoundError('Not Found')
+ job_map = build['properties']['lilybuild_job_map'][0]
+ if job_name not in job_map:
+ raise FileNotFoundError('Not Found')
+ job_index = job_map[job_name]
# Things not pushed to staging area is considered private
# and can only be seen by project members
if source == 'arc-patch':
@@ -83,3 +100,52 @@
'artifacts', fn
)
return res
+
+ @app.route('/repos/<int:repo_id>/latest/<ref_name>/artifacts/<artifact_type>', methods=['GET'])
+ @defer.inlineCallbacks
+ def getLatestArtifact(self, request, repo_id, ref_name, artifact_type):
+ if not validate_ref_name(ref_name):
+ request.setResponseCode(400)
+ request.setHeader('Content-Type', 'application/json')
+ return json.dumps({'error': f'Bad ref_name format: {ref_name}'})
+
+ if not validate_artifact_type(artifact_type):
+ request.setResponseCode(400)
+ request.setHeader('Content-Type', 'application/json')
+ return json.dumps({'error': BAD_REQUEST})
+
+ is_good = True
+ if b'good' in request.args:
+ good = request.args[b'good'][0]
+ if good == b'1':
+ is_good = True
+ elif good == b'0':
+ is_good = False
+ else:
+ request.setResponseCode(400)
+ request.setHeader('Content-Type', 'application/json')
+ return json.dumps({'error': 'query `good` must be 0 or 1'})
+
+ if b'job' not in request.args:
+ request.setResponseCode(400)
+ request.setHeader('Content-Type', 'application/json')
+ return json.dumps({'error': 'query `job` missing'})
+
+ job_name = request.args[b'job'][0].decode()
+ link_name = os.path.join(
+ self.lbc().storage_dir,
+ 'repos', str(repo_id),
+ 'latest-good' if is_good else 'latest', ref_name
+ )
+ try:
+ target = os.readlink(link_name)
+ build_id = int(os.path.basename(target))
+ artifact_file = yield self.get_artifact_location(request, build_id, None, artifact_type, job_name)
+ if os.path.exists(artifact_file):
+ return File(artifact_file)
+ else:
+ raise FileNotFoundError('Not Found')
+ except:
+ request.setResponseCode(404)
+ request.setHeader('Content-Type', 'application/json')
+ return json.dumps({'error': NOT_FOUND})
diff --git a/lilybuild/lilybuild/ci_steps.py b/lilybuild/lilybuild/ci_steps.py
--- a/lilybuild/lilybuild/ci_steps.py
+++ b/lilybuild/lilybuild/ci_steps.py
@@ -478,7 +478,7 @@
return trigger
- def get_steps(self, stdout):
+ def get_steps_and_job_map(self, stdout):
f = ci_file.CIFile(stdout)
stages = f.get_grouped_jobs()
@@ -490,7 +490,7 @@
steps = [self.stage_to_step(stage_name, stage_jobs, job_name_to_index_map, f) for (stage_name, stage_jobs) in stages]
print('steps:', steps)
- return steps
+ return (steps, job_name_to_index_map)
def get_is_phorge(self):
return not not self.getProperty(self.build_target_prop_name)
@@ -547,7 +547,9 @@
pipeline_vars = yield self.get_pipeline_ci_vars()
self.setProperty('lilybuild_pipeline_vars', pipeline_vars, self.__class__.__name__)
# create a ShellCommand for each stage and add them to the build
- self.build.addStepsAfterCurrentStep(self.get_steps(self.observer.getStdout()))
+ (steps, job_map) = self.get_steps_and_job_map(self.observer.getStdout())
+ self.setProperty('lilybuild_job_map', job_map, self.__class__.__name__)
+ self.build.addStepsAfterCurrentStep(steps)
latest_branch_map = self.get_cur_repo_config()['artifact_latest_branch_map']
ref, _ref_type = self.get_ref_and_type()

File Metadata

Mime Type
text/plain
Expires
Wed, Dec 31, 7:30 PM (22 h, 34 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
885525
Default Alt Text
D260.1767238218.diff (5 KB)

Event Timeline