123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172 |
- from flask import Flask, render_template, abort, send_file, jsonify
- import os
- import json
- from typing import List
- import markdown as md
- from dataclasses import dataclass
- from dataclasses_json import DataClassJsonMixin
- app = Flask(__name__)
- @dataclass
- class ArtifactItem(DataClassJsonMixin):
- file: str
- description: str
- @dataclass
- class Artifact(DataClassJsonMixin):
- id: str
- date: str
- changelog: str
- artifacts: List[ArtifactItem]
- hash: str = None
- @dataclass
- class ProjectInfo(DataClassJsonMixin):
- name: str
- commit_url: str
- class Project:
- id: str
- 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")
- artifact = self._parse_artifact(info_file_path)
- if artifact:
- result.append(artifact)
- return result
- def get_lastest_artifact(self) -> Artifact:
- 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)
- if not artifact_folders:
- return None
-
- latest_artifact_folder = max(artifact_folders)
- info_file_path = os.path.join(latest_artifact_folder, "info.json")
- return self._parse_artifact(info_file_path)
- def get_artifact(self, artifact_id) -> Artifact:
- artifact_folder = os.path.join("../builds", self.id, "artifacts", artifact_id)
- if not os.path.isdir(artifact_folder):
- return None
- info_file_path = os.path.join(artifact_folder, "info.json")
- return self._parse_artifact(info_file_path)
- def _parse_artifact(self, info_file_path):
- if not os.path.exists(info_file_path):
- return None
- try:
- with open(info_file_path, "r", encoding="utf-8") as f:
- artifact = Artifact.from_json(f.read())
- artifact.date = artifact.date.strip()
- return artifact
- except:
- return None
- def get_projects() -> List[Project]:
- result = []
- projects = [f.path for f in os.scandir("../builds") if f.is_dir()]
- for project in projects:
- info_path = os.path.join(project, "info.json")
- if not os.path.exists(info_path):
- continue
- try:
- proj = Project()
- _, proj.id = os.path.split(project)
- with open(info_path, "r", encoding="utf-8") as f:
- proj.info = ProjectInfo.from_json(f.read())
- result.append(proj)
- except:
- continue
- return result
- @app.route("/api/projects/<string:project_id>/artifacts/latest")
- def get_latest_artifact(project_id):
- projects = get_projects()
- selected_project = next(
- (project for project in projects if project.id == project_id), None)
- if not selected_project:
- return abort(404)
- artifact = selected_project.get_lastest_artifact()
- if not artifact:
- return abort(404)
-
- return jsonify(artifact)
- @app.route("/api/projects/<string:project_id>/artifacts/<string:artifact_id>")
- def get_artifact_by_id(project_id, artifact_id):
- projects = get_projects()
- selected_project = next(
- (project for project in projects if project.id == project_id), None)
- if not selected_project:
- return abort(404)
- artifact = selected_project.get_artifact(artifact_id)
- if not artifact:
- return abort(404)
-
- return jsonify(artifact)
- @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>")
- def display_project(project_id):
- projects = get_projects()
- selected_project = next(
- (project for project in projects if project.id == project_id), None)
- if not selected_project:
- return abort(404)
- info_path = os.path.join("../builds", selected_project.id, "info.md")
- readme = None
- try:
- if os.path.exists(info_path):
- with open(info_path, "r", encoding="utf-8") as f:
- readme = md.markdown(f.read())
- except:
- readme = None
- artifacts = selected_project.get_artifacts()
- return render_template("project_view.html", projects=projects, selected_project=selected_project, readme=readme, artifacts=artifacts)
- @app.route("/")
- def index():
- projects = get_projects()
- return render_template("main.html", projects=projects)
- if __name__ == "__main__":
- app.run(host='0.0.0.0')
|