app.py 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. from flask import Flask, render_template, abort, send_file
  2. from flask_assets import Environment, Bundle
  3. import os
  4. import json
  5. from typing import List
  6. import markdown as md
  7. from dataclasses import dataclass
  8. from dataclasses_json import dataclass_json
  9. app = Flask(__name__)
  10. assets = Environment(app)
  11. assets.url = app.static_url_path
  12. scss = Bundle('style/main.scss', filters='libsass',
  13. output='all.css', depends='**/*.scss')
  14. assets.config['PYSCSS_LOAD_PATHS'] = assets.load_path
  15. assets.config['PYSCSS_STATIC_URL'] = assets.url
  16. assets.config['PYSCSS_STATIC_ROOT'] = assets.directory
  17. assets.config['PYSCSS_ASSETS_URL'] = assets.url
  18. assets.config['PYSCSS_ASSETS_ROOT'] = assets.directory
  19. assets.register('scss_all', scss)
  20. @dataclass
  21. @dataclass_json
  22. class ArtifactItem:
  23. file: str
  24. description: str
  25. width: int = 0
  26. @dataclass
  27. @dataclass_json
  28. class Artifact:
  29. id: str
  30. date: str
  31. changelog: str
  32. artifacts: List[ArtifactItem]
  33. hash: str = None
  34. @dataclass
  35. @dataclass_json
  36. class ProjectInfo:
  37. name: str
  38. commit_url: str
  39. class Project:
  40. id: str
  41. info: ProjectInfo
  42. def get_artifacts(self) -> List[Artifact]:
  43. result = []
  44. artifacts_path = os.path.join("../builds", self.id, "artifacts")
  45. artifact_folders = sorted([folder.path for folder in os.scandir(
  46. artifacts_path) if folder.is_dir()], reverse=True)
  47. for artifact_folder in artifact_folders:
  48. info_file_path = os.path.join(artifact_folder, "info.json")
  49. if not os.path.exists(info_file_path):
  50. continue
  51. try:
  52. with open(info_file_path, "r", encoding="utf-8") as f:
  53. artifact = Artifact.from_json(f.read())
  54. artifact.date = artifact.date.strip()
  55. maxwidth = max((len(a.file)
  56. for a in artifact.artifacts), default=0)
  57. for a in artifact.artifacts:
  58. a.width = maxwidth
  59. result.append(artifact)
  60. except:
  61. continue
  62. return result
  63. def get_projects() -> List[Project]:
  64. result = []
  65. projects = [f.path for f in os.scandir("../builds") if f.is_dir()]
  66. for project in projects:
  67. info_path = os.path.join(project, "info.json")
  68. if not os.path.exists(info_path):
  69. continue
  70. try:
  71. proj = Project()
  72. _, proj.id = os.path.split(project)
  73. with open(info_path, "r", encoding="utf-8") as f:
  74. proj.info = ProjectInfo.from_json(f.read())
  75. result.append(proj)
  76. except:
  77. continue
  78. return result
  79. @app.route("/projects/<string:project_id>/<string:artifact_id>/<string:download_item>")
  80. def download_item(project_id, artifact_id, download_item):
  81. file_path = os.path.join("../builds", project_id,
  82. "artifacts", artifact_id, download_item)
  83. if not os.path.exists(file_path):
  84. return abort(404)
  85. return send_file(file_path)
  86. @app.route("/projects/<string:project_id>")
  87. def display_project(project_id):
  88. projects = get_projects()
  89. selected_project = next(
  90. (project for project in projects if project.id == project_id), None)
  91. if not selected_project:
  92. return abort(404)
  93. info_path = os.path.join("../builds", selected_project.id, "info.md")
  94. readme = None
  95. try:
  96. if os.path.exists(info_path):
  97. with open(info_path, "r", encoding="utf-8") as f:
  98. readme = md.markdown(f.read())
  99. except:
  100. readme = None
  101. artifacts = selected_project.get_artifacts()
  102. return render_template("project_view.html", projects=projects, selected_project=selected_project, readme=readme, artifacts=artifacts)
  103. @app.route("/")
  104. def index():
  105. projects = get_projects()
  106. return render_template("main.html", projects=projects)
  107. if __name__ == "__main__":
  108. app.run(host='0.0.0.0')