|
@@ -1,4 +1,4 @@
|
|
-from flask import Flask, render_template, abort
|
|
|
|
|
|
+from flask import Flask, render_template, abort, send_file
|
|
from flask_assets import Environment, Bundle
|
|
from flask_assets import Environment, Bundle
|
|
import os
|
|
import os
|
|
import json
|
|
import json
|
|
@@ -18,6 +18,34 @@ assets.config['PYSCSS_ASSETS_ROOT'] = assets.directory
|
|
assets.register('scss_all', scss)
|
|
assets.register('scss_all', scss)
|
|
|
|
|
|
|
|
|
|
|
|
+class ArtifactItem:
|
|
|
|
+ file: str
|
|
|
|
+ description: str
|
|
|
|
+
|
|
|
|
+ def __init__(self, file, description):
|
|
|
|
+ self.file = file
|
|
|
|
+ self.description = description
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+class Artifact:
|
|
|
|
+ id: str
|
|
|
|
+ date: str
|
|
|
|
+ changelog: str
|
|
|
|
+ artifacts: List[ArtifactItem]
|
|
|
|
+
|
|
|
|
+ def __init__(self, id, date, changelog, artifacts):
|
|
|
|
+ self.id = id
|
|
|
|
+ self.date = date
|
|
|
|
+ self.changelog = changelog
|
|
|
|
+ self.artifacts = [ArtifactItem(**item)
|
|
|
|
+ for item in artifacts]
|
|
|
|
+
|
|
|
|
+ @classmethod
|
|
|
|
+ def from_json(cls, json_str):
|
|
|
|
+ json_dict = json.loads(json_str)
|
|
|
|
+ return cls(**json_dict)
|
|
|
|
+
|
|
|
|
+
|
|
class ProjectInfo:
|
|
class ProjectInfo:
|
|
name: str
|
|
name: str
|
|
|
|
|
|
@@ -34,6 +62,24 @@ class Project:
|
|
id: str
|
|
id: str
|
|
info: ProjectInfo
|
|
info: ProjectInfo
|
|
|
|
|
|
|
|
+ def get_artifacts(self) -> List[Artifact]:
|
|
|
|
+ result = []
|
|
|
|
+ artifacts_path = os.path.join("../builds", self.id, "artifacts")
|
|
|
|
+ artifact_folders = sorted([folder.path for folder in os.scandir(
|
|
|
|
+ artifacts_path) if folder.is_dir()], reverse=True)
|
|
|
|
+
|
|
|
|
+ for artifact_folder in artifact_folders:
|
|
|
|
+ info_file_path = os.path.join(artifact_folder, "info.json")
|
|
|
|
+ if not os.path.exists(info_file_path):
|
|
|
|
+ continue
|
|
|
|
+ try:
|
|
|
|
+ with open(info_file_path, "r", encoding="utf-8") as f:
|
|
|
|
+ artifact = Artifact.from_json(f.read())
|
|
|
|
+ result.append(artifact)
|
|
|
|
+ except:
|
|
|
|
+ continue
|
|
|
|
+ return result
|
|
|
|
+
|
|
|
|
|
|
def get_projects() -> List[Project]:
|
|
def get_projects() -> List[Project]:
|
|
result = []
|
|
result = []
|
|
@@ -53,6 +99,15 @@ def get_projects() -> List[Project]:
|
|
return result
|
|
return result
|
|
|
|
|
|
|
|
|
|
|
|
+@app.route("/projects/<string:project_id>/<string:artifact_id>/<string:download_item>")
|
|
|
|
+def download_item(project_id, artifact_id, download_item):
|
|
|
|
+ file_path = os.path.join("../builds", project_id,
|
|
|
|
+ "artifacts", artifact_id, download_item)
|
|
|
|
+ if not os.path.exists(file_path):
|
|
|
|
+ return abort(404)
|
|
|
|
+ return send_file(file_path)
|
|
|
|
+
|
|
|
|
+
|
|
@app.route("/projects/<string:project_id>")
|
|
@app.route("/projects/<string:project_id>")
|
|
def display_project(project_id):
|
|
def display_project(project_id):
|
|
projects = get_projects()
|
|
projects = get_projects()
|
|
@@ -63,7 +118,6 @@ def display_project(project_id):
|
|
return abort(404)
|
|
return abort(404)
|
|
|
|
|
|
info_path = os.path.join("../builds", selected_project.id, "info.md")
|
|
info_path = os.path.join("../builds", selected_project.id, "info.md")
|
|
-
|
|
|
|
readme = None
|
|
readme = None
|
|
try:
|
|
try:
|
|
if os.path.exists(info_path):
|
|
if os.path.exists(info_path):
|
|
@@ -72,7 +126,9 @@ def display_project(project_id):
|
|
except:
|
|
except:
|
|
readme = None
|
|
readme = None
|
|
|
|
|
|
- return render_template("project_view.html", projects=projects, selected_project=selected_project, readme=readme)
|
|
|
|
|
|
+ artifacts = selected_project.get_artifacts()
|
|
|
|
+
|
|
|
|
+ return render_template("project_view.html", projects=projects, selected_project=selected_project, readme=readme, artifacts=artifacts)
|
|
|
|
|
|
|
|
|
|
@app.route("/")
|
|
@app.route("/")
|