craft-dashboard 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (428) hide show
  1. craft_dashboard-0.1.0/.dockerignore +24 -0
  2. craft_dashboard-0.1.0/.env.example +65 -0
  3. craft_dashboard-0.1.0/.github/PULL_REQUEST_TEMPLATE.md +1 -0
  4. craft_dashboard-0.1.0/.github/renovate.json5 +3 -0
  5. craft_dashboard-0.1.0/.github/workflows/check-renovate.yaml +31 -0
  6. craft_dashboard-0.1.0/.github/workflows/ci.yml +89 -0
  7. craft_dashboard-0.1.0/.github/workflows/e2e.yml +23 -0
  8. craft_dashboard-0.1.0/.github/workflows/publish.yml +98 -0
  9. craft_dashboard-0.1.0/.github/workflows/release-publish.yaml +69 -0
  10. craft_dashboard-0.1.0/.github/workflows/release.yml +87 -0
  11. craft_dashboard-0.1.0/.gitignore +54 -0
  12. craft_dashboard-0.1.0/Dockerfile +51 -0
  13. craft_dashboard-0.1.0/LICENSE +165 -0
  14. craft_dashboard-0.1.0/Makefile +100 -0
  15. craft_dashboard-0.1.0/PKG-INFO +71 -0
  16. craft_dashboard-0.1.0/README.md +35 -0
  17. craft_dashboard-0.1.0/REPO_MAP.md +59 -0
  18. craft_dashboard-0.1.0/agents.md +185 -0
  19. craft_dashboard-0.1.0/alembic/env.py +75 -0
  20. craft_dashboard-0.1.0/alembic/script.py.mako +26 -0
  21. craft_dashboard-0.1.0/alembic/versions/.gitkeep +0 -0
  22. craft_dashboard-0.1.0/alembic/versions/04b321505716_add_evidence_generation_and_scanner_tables.py +102 -0
  23. craft_dashboard-0.1.0/alembic/versions/0a1b2c3d4e5f_remove_duplicate_detection_columns.py +54 -0
  24. craft_dashboard-0.1.0/alembic/versions/0d2e05caabfc_add_superseded_by_to_issue_links_kind_.py +39 -0
  25. craft_dashboard-0.1.0/alembic/versions/106bfe752b75_add_issue_search_embedding.py +41 -0
  26. craft_dashboard-0.1.0/alembic/versions/2b5dce17fece_add_llm_evaluation_cost_usd.py +28 -0
  27. craft_dashboard-0.1.0/alembic/versions/326fd64d080f_add_issue_links_table.py +75 -0
  28. craft_dashboard-0.1.0/alembic/versions/38a9bb474e97_add_issue_content_hash.py +28 -0
  29. craft_dashboard-0.1.0/alembic/versions/3bf712e6582b_add_eval_queue_snapshots_table.py +46 -0
  30. craft_dashboard-0.1.0/alembic/versions/42f5d054e245_add_forum_activity_tables.py +76 -0
  31. craft_dashboard-0.1.0/alembic/versions/444063d1b5b0_add_eval_api_tokens_and_evaluated_by.py +154 -0
  32. craft_dashboard-0.1.0/alembic/versions/4ae069e8c8f0_add_category_progress_to_forum_backfill_.py +48 -0
  33. craft_dashboard-0.1.0/alembic/versions/58e6ebac628e_add_open_poll_failure_tracking_to_.py +46 -0
  34. craft_dashboard-0.1.0/alembic/versions/5d2a2a5c1823_add_median_age_and_closed_counts_to_.py +72 -0
  35. craft_dashboard-0.1.0/alembic/versions/68de7346cc6d_add_issue_activities_table.py +63 -0
  36. craft_dashboard-0.1.0/alembic/versions/7f8e9d0c1b2a_fix_stale_content_hash.py +33 -0
  37. craft_dashboard-0.1.0/alembic/versions/9c0a9d2a88fe_backfill_bot_accounts.py +40 -0
  38. craft_dashboard-0.1.0/alembic/versions/9e37c633701b_add_embedding_tokens_and_ingestion_metrics.py +51 -0
  39. craft_dashboard-0.1.0/alembic/versions/a1b2c3d4e5f6_add_duplicate_detection_columns.py +70 -0
  40. craft_dashboard-0.1.0/alembic/versions/a3f9d2e1b5c8_add_dep_version_columns.py +36 -0
  41. craft_dashboard-0.1.0/alembic/versions/ab12cd34ef56_remove_duplicate_lp_issues_from_snapcraft.py +41 -0
  42. craft_dashboard-0.1.0/alembic/versions/acbc7fc12cd7_add_embed_queue_index.py +38 -0
  43. craft_dashboard-0.1.0/alembic/versions/b1c2d3e4f5a6_add_combined_median_age_columns.py +49 -0
  44. craft_dashboard-0.1.0/alembic/versions/b67acfce407c_releases_unique_by_project_branch.py +32 -0
  45. craft_dashboard-0.1.0/alembic/versions/b7c1d9e42f08_enforce_releases_branch_not_null.py +43 -0
  46. craft_dashboard-0.1.0/alembic/versions/c3e8f1a2b9d7_add_per_view_median_age_fields.py +67 -0
  47. craft_dashboard-0.1.0/alembic/versions/c4d5e6f7a8b9_add_collection_run_id_to_issues.py +40 -0
  48. craft_dashboard-0.1.0/alembic/versions/c51008987675_add_evaluation_transcripts_table.py +71 -0
  49. craft_dashboard-0.1.0/alembic/versions/c9f8a7b6e5d4_migrate_close_outdated.py +30 -0
  50. craft_dashboard-0.1.0/alembic/versions/d1b3f5a46924_add_eval_version.py +35 -0
  51. craft_dashboard-0.1.0/alembic/versions/d4e5f6a7b8c9_add_token_breakdown_and_backend.py +39 -0
  52. craft_dashboard-0.1.0/alembic/versions/d89e58e0a23e_add_comments_column.py +34 -0
  53. craft_dashboard-0.1.0/alembic/versions/dc49f831c706_rename_summary_and_add_run_id.py +46 -0
  54. craft_dashboard-0.1.0/alembic/versions/e728675ec251_add_eval_type_to_llm_evaluations.py +44 -0
  55. craft_dashboard-0.1.0/alembic/versions/e7f8a9b0c1d2_add_collection_tracking_tables.py +67 -0
  56. craft_dashboard-0.1.0/alembic/versions/e8f1a2b9c3d4_add_summary_embedding.py +44 -0
  57. craft_dashboard-0.1.0/alembic/versions/f1b467aa1a8f_initial.py +175 -0
  58. craft_dashboard-0.1.0/alembic/versions/f2a3b4c5d6e7_add_eval_locked_until_column.py +29 -0
  59. craft_dashboard-0.1.0/alembic/versions/f2b1e1807a8a_add_eval_queue_index.py +34 -0
  60. craft_dashboard-0.1.0/alembic/versions/f9a0b1c2d3e4_resize_summary_embedding_to_1024.py +67 -0
  61. craft_dashboard-0.1.0/alembic/versions/fa02b11af7dc_add_author_is_bot_and_snapshot_bot_fields.py +61 -0
  62. craft_dashboard-0.1.0/alembic.ini +36 -0
  63. craft_dashboard-0.1.0/craft-dashboard.toml +187 -0
  64. craft_dashboard-0.1.0/craft_dashboard/__init__.py +1 -0
  65. craft_dashboard-0.1.0/craft_dashboard/_version.py +24 -0
  66. craft_dashboard-0.1.0/craft_dashboard/app.py +324 -0
  67. craft_dashboard-0.1.0/craft_dashboard/auth.py +79 -0
  68. craft_dashboard-0.1.0/craft_dashboard/cli.py +267 -0
  69. craft_dashboard-0.1.0/craft_dashboard/collectors/AGENTS.md +48 -0
  70. craft_dashboard-0.1.0/craft_dashboard/collectors/__init__.py +48 -0
  71. craft_dashboard-0.1.0/craft_dashboard/collectors/dependencies.py +321 -0
  72. craft_dashboard-0.1.0/craft_dashboard/collectors/forum.py +532 -0
  73. craft_dashboard-0.1.0/craft_dashboard/collectors/github.py +916 -0
  74. craft_dashboard-0.1.0/craft_dashboard/collectors/github_adapters.py +150 -0
  75. craft_dashboard-0.1.0/craft_dashboard/collectors/github_graphql.py +768 -0
  76. craft_dashboard-0.1.0/craft_dashboard/collectors/github_issue_store.py +207 -0
  77. craft_dashboard-0.1.0/craft_dashboard/collectors/github_mapping.py +145 -0
  78. craft_dashboard-0.1.0/craft_dashboard/collectors/github_release_store.py +70 -0
  79. craft_dashboard-0.1.0/craft_dashboard/collectors/github_releases.py +67 -0
  80. craft_dashboard-0.1.0/craft_dashboard/collectors/github_rest.py +155 -0
  81. craft_dashboard-0.1.0/craft_dashboard/collectors/launchpad.py +343 -0
  82. craft_dashboard-0.1.0/craft_dashboard/collectors/scheduler.py +282 -0
  83. craft_dashboard-0.1.0/craft_dashboard/collectors/snapshots.py +529 -0
  84. craft_dashboard-0.1.0/craft_dashboard/commit_scanner/__init__.py +5 -0
  85. craft_dashboard-0.1.0/craft_dashboard/commit_scanner/parsing.py +112 -0
  86. craft_dashboard-0.1.0/craft_dashboard/commit_scanner/scanner.py +483 -0
  87. craft_dashboard-0.1.0/craft_dashboard/config.py +150 -0
  88. craft_dashboard-0.1.0/craft_dashboard/database.py +52 -0
  89. craft_dashboard-0.1.0/craft_dashboard/dependencies.py +33 -0
  90. craft_dashboard-0.1.0/craft_dashboard/enums.py +25 -0
  91. craft_dashboard-0.1.0/craft_dashboard/git_mirrors/__init__.py +6 -0
  92. craft_dashboard-0.1.0/craft_dashboard/git_mirrors/exceptions.py +21 -0
  93. craft_dashboard-0.1.0/craft_dashboard/git_mirrors/layout_cache.py +65 -0
  94. craft_dashboard-0.1.0/craft_dashboard/git_mirrors/paths.py +106 -0
  95. craft_dashboard-0.1.0/craft_dashboard/git_mirrors/reader.py +482 -0
  96. craft_dashboard-0.1.0/craft_dashboard/git_mirrors/sync.py +248 -0
  97. craft_dashboard-0.1.0/craft_dashboard/http_retry.py +125 -0
  98. craft_dashboard-0.1.0/craft_dashboard/llm/AGENTS.md +29 -0
  99. craft_dashboard-0.1.0/craft_dashboard/llm/__init__.py +1 -0
  100. craft_dashboard-0.1.0/craft_dashboard/llm/acp_client.py +364 -0
  101. craft_dashboard-0.1.0/craft_dashboard/llm/baseline.py +120 -0
  102. craft_dashboard-0.1.0/craft_dashboard/llm/client.py +651 -0
  103. craft_dashboard-0.1.0/craft_dashboard/llm/content_hash.py +93 -0
  104. craft_dashboard-0.1.0/craft_dashboard/llm/duplicate_detector.py +193 -0
  105. craft_dashboard-0.1.0/craft_dashboard/llm/embeddings.py +226 -0
  106. craft_dashboard-0.1.0/craft_dashboard/llm/evaluation_queue.py +207 -0
  107. craft_dashboard-0.1.0/craft_dashboard/llm/evaluator.py +1095 -0
  108. craft_dashboard-0.1.0/craft_dashboard/llm/exceptions.py +25 -0
  109. craft_dashboard-0.1.0/craft_dashboard/llm/preflight.py +56 -0
  110. craft_dashboard-0.1.0/craft_dashboard/llm/prompts.py +569 -0
  111. craft_dashboard-0.1.0/craft_dashboard/llm/tool_dispatch.py +306 -0
  112. craft_dashboard-0.1.0/craft_dashboard/llm/tools.py +210 -0
  113. craft_dashboard-0.1.0/craft_dashboard/models/__init__.py +46 -0
  114. craft_dashboard-0.1.0/craft_dashboard/models/base.py +26 -0
  115. craft_dashboard-0.1.0/craft_dashboard/models/collection_run.py +35 -0
  116. craft_dashboard-0.1.0/craft_dashboard/models/collection_watermark.py +24 -0
  117. craft_dashboard-0.1.0/craft_dashboard/models/commit_scan_evidence_path.py +42 -0
  118. craft_dashboard-0.1.0/craft_dashboard/models/commit_scan_run.py +57 -0
  119. craft_dashboard-0.1.0/craft_dashboard/models/dependency.py +55 -0
  120. craft_dashboard-0.1.0/craft_dashboard/models/eval_queue_snapshot.py +29 -0
  121. craft_dashboard-0.1.0/craft_dashboard/models/eval_token.py +54 -0
  122. craft_dashboard-0.1.0/craft_dashboard/models/evaluation_transcript.py +61 -0
  123. craft_dashboard-0.1.0/craft_dashboard/models/forum.py +95 -0
  124. craft_dashboard-0.1.0/craft_dashboard/models/issue.py +123 -0
  125. craft_dashboard-0.1.0/craft_dashboard/models/issue_activity.py +48 -0
  126. craft_dashboard-0.1.0/craft_dashboard/models/issue_link.py +107 -0
  127. craft_dashboard-0.1.0/craft_dashboard/models/llm_evaluation.py +125 -0
  128. craft_dashboard-0.1.0/craft_dashboard/models/project.py +42 -0
  129. craft_dashboard-0.1.0/craft_dashboard/models/refresh_schedule.py +68 -0
  130. craft_dashboard-0.1.0/craft_dashboard/models/release.py +44 -0
  131. craft_dashboard-0.1.0/craft_dashboard/models/snapshot.py +79 -0
  132. craft_dashboard-0.1.0/craft_dashboard/models/views.py +231 -0
  133. craft_dashboard-0.1.0/craft_dashboard/rate_limit.py +57 -0
  134. craft_dashboard-0.1.0/craft_dashboard/repositories/AGENTS.md +29 -0
  135. craft_dashboard-0.1.0/craft_dashboard/repositories/__init__.py +7 -0
  136. craft_dashboard-0.1.0/craft_dashboard/repositories/eval_token_repository.py +190 -0
  137. craft_dashboard-0.1.0/craft_dashboard/repositories/issue_filters.py +68 -0
  138. craft_dashboard-0.1.0/craft_dashboard/repositories/issue_link_repository.py +190 -0
  139. craft_dashboard-0.1.0/craft_dashboard/repositories/issue_repository.py +748 -0
  140. craft_dashboard-0.1.0/craft_dashboard/routes/AGENTS.md +27 -0
  141. craft_dashboard-0.1.0/craft_dashboard/routes/__init__.py +1 -0
  142. craft_dashboard-0.1.0/craft_dashboard/routes/admin.py +508 -0
  143. craft_dashboard-0.1.0/craft_dashboard/routes/dashboard.py +53 -0
  144. craft_dashboard-0.1.0/craft_dashboard/routes/engagement.py +110 -0
  145. craft_dashboard-0.1.0/craft_dashboard/routes/eval_api.py +1151 -0
  146. craft_dashboard-0.1.0/craft_dashboard/routes/issues.py +599 -0
  147. craft_dashboard-0.1.0/craft_dashboard/routes/stats.py +705 -0
  148. craft_dashboard-0.1.0/craft_dashboard/services/AGENTS.md +36 -0
  149. craft_dashboard-0.1.0/craft_dashboard/services/__init__.py +23 -0
  150. craft_dashboard-0.1.0/craft_dashboard/services/admin_service.py +949 -0
  151. craft_dashboard-0.1.0/craft_dashboard/services/dashboard/__init__.py +13 -0
  152. craft_dashboard-0.1.0/craft_dashboard/services/dashboard/badges.py +42 -0
  153. craft_dashboard-0.1.0/craft_dashboard/services/dashboard/common.py +41 -0
  154. craft_dashboard-0.1.0/craft_dashboard/services/dashboard/health.py +147 -0
  155. craft_dashboard-0.1.0/craft_dashboard/services/dashboard/projects.py +43 -0
  156. craft_dashboard-0.1.0/craft_dashboard/services/dashboard/releases.py +143 -0
  157. craft_dashboard-0.1.0/craft_dashboard/services/dashboard/spotlights.py +175 -0
  158. craft_dashboard-0.1.0/craft_dashboard/services/dashboard/throughput.py +74 -0
  159. craft_dashboard-0.1.0/craft_dashboard/services/dashboard/types.py +210 -0
  160. craft_dashboard-0.1.0/craft_dashboard/services/dashboard/untriaged.py +85 -0
  161. craft_dashboard-0.1.0/craft_dashboard/services/dashboard/velocity.py +277 -0
  162. craft_dashboard-0.1.0/craft_dashboard/services/dashboard/view_models.py +356 -0
  163. craft_dashboard-0.1.0/craft_dashboard/services/dashboard/volume.py +119 -0
  164. craft_dashboard-0.1.0/craft_dashboard/services/dashboard_service.py +484 -0
  165. craft_dashboard-0.1.0/craft_dashboard/services/eval_activity.py +105 -0
  166. craft_dashboard-0.1.0/craft_dashboard/services/eval_auth_service.py +150 -0
  167. craft_dashboard-0.1.0/craft_dashboard/services/evaluation_gc.py +131 -0
  168. craft_dashboard-0.1.0/craft_dashboard/services/transcript_gc.py +47 -0
  169. craft_dashboard-0.1.0/craft_dashboard/settings.py +142 -0
  170. craft_dashboard-0.1.0/craft_dashboard/static/css/custom.css +1424 -0
  171. craft_dashboard-0.1.0/craft_dashboard/static/favicon.ico +0 -0
  172. craft_dashboard-0.1.0/craft_dashboard/static/js/chart-a11y.js +80 -0
  173. craft_dashboard-0.1.0/craft_dashboard/static/js/chart-common.js +347 -0
  174. craft_dashboard-0.1.0/craft_dashboard/static/js/deps.js +133 -0
  175. craft_dashboard-0.1.0/craft_dashboard/static/js/engagement.js +234 -0
  176. craft_dashboard-0.1.0/craft_dashboard/static/js/issue-columns.js +90 -0
  177. craft_dashboard-0.1.0/craft_dashboard/static/js/issues-filters.js +153 -0
  178. craft_dashboard-0.1.0/craft_dashboard/static/js/multiselect.js +272 -0
  179. craft_dashboard-0.1.0/craft_dashboard/static/js/table-interact.js +90 -0
  180. craft_dashboard-0.1.0/craft_dashboard/static/js/table-paginate.js +92 -0
  181. craft_dashboard-0.1.0/craft_dashboard/static/js/table-sort.js +97 -0
  182. craft_dashboard-0.1.0/craft_dashboard/static/js/trends.js +543 -0
  183. craft_dashboard-0.1.0/craft_dashboard/static/vendor/README.md +15 -0
  184. craft_dashboard-0.1.0/craft_dashboard/static/vendor/chart.umd.min.js +20 -0
  185. craft_dashboard-0.1.0/craft_dashboard/static/vendor/marked.min.js +69 -0
  186. craft_dashboard-0.1.0/craft_dashboard/static/vendor/purify.min.js +3 -0
  187. craft_dashboard-0.1.0/craft_dashboard/templates/admin/_recent_activity_rows.html +51 -0
  188. craft_dashboard-0.1.0/craft_dashboard/templates/admin/_recent_evaluations_rows.html +51 -0
  189. craft_dashboard-0.1.0/craft_dashboard/templates/admin/collection_run_issues.html +42 -0
  190. craft_dashboard-0.1.0/craft_dashboard/templates/admin/evaluations.html +365 -0
  191. craft_dashboard-0.1.0/craft_dashboard/templates/admin/overview.html +306 -0
  192. craft_dashboard-0.1.0/craft_dashboard/templates/admin/partials/tabs.html +12 -0
  193. craft_dashboard-0.1.0/craft_dashboard/templates/admin/schedule.html +99 -0
  194. craft_dashboard-0.1.0/craft_dashboard/templates/base.html +343 -0
  195. craft_dashboard-0.1.0/craft_dashboard/templates/components/issue_cell.html +25 -0
  196. craft_dashboard-0.1.0/craft_dashboard/templates/components/pagination.html +14 -0
  197. craft_dashboard-0.1.0/craft_dashboard/templates/components/score_badge.html +15 -0
  198. craft_dashboard-0.1.0/craft_dashboard/templates/dashboard/index.html +499 -0
  199. craft_dashboard-0.1.0/craft_dashboard/templates/engagement/forums.html +99 -0
  200. craft_dashboard-0.1.0/craft_dashboard/templates/errors/404.html +9 -0
  201. craft_dashboard-0.1.0/craft_dashboard/templates/errors/500.html +9 -0
  202. craft_dashboard-0.1.0/craft_dashboard/templates/issues/detail.html +228 -0
  203. craft_dashboard-0.1.0/craft_dashboard/templates/issues/list.html +263 -0
  204. craft_dashboard-0.1.0/craft_dashboard/templates/issues/partials/issue_table.html +125 -0
  205. craft_dashboard-0.1.0/craft_dashboard/templates/stats/cadence.html +142 -0
  206. craft_dashboard-0.1.0/craft_dashboard/templates/stats/dependencies.html +11 -0
  207. craft_dashboard-0.1.0/craft_dashboard/templates/stats/partials/tabs.html +20 -0
  208. craft_dashboard-0.1.0/craft_dashboard/templates/stats/partials/trend_chart.html +22 -0
  209. craft_dashboard-0.1.0/craft_dashboard/templates/stats/releases.html +304 -0
  210. craft_dashboard-0.1.0/craft_dashboard/templates/stats/trends.html +238 -0
  211. craft_dashboard-0.1.0/craft_dashboard/templates/stats/triage.html +251 -0
  212. craft_dashboard-0.1.0/craft_dashboard/utils/__init__.py +23 -0
  213. craft_dashboard-0.1.0/craft_dashboard/utils/formatting.py +28 -0
  214. craft_dashboard-0.1.0/craft_dashboard/utils/retention.py +36 -0
  215. craft_dashboard-0.1.0/craft_dashboard.egg-info/PKG-INFO +71 -0
  216. craft_dashboard-0.1.0/craft_dashboard.egg-info/SOURCES.txt +426 -0
  217. craft_dashboard-0.1.0/craft_dashboard.egg-info/dependency_links.txt +1 -0
  218. craft_dashboard-0.1.0/craft_dashboard.egg-info/entry_points.txt +3 -0
  219. craft_dashboard-0.1.0/craft_dashboard.egg-info/requires.txt +19 -0
  220. craft_dashboard-0.1.0/craft_dashboard.egg-info/scm_file_list.json +421 -0
  221. craft_dashboard-0.1.0/craft_dashboard.egg-info/scm_version.json +8 -0
  222. craft_dashboard-0.1.0/craft_dashboard.egg-info/top_level.txt +2 -0
  223. craft_dashboard-0.1.0/docker-compose.yml +33 -0
  224. craft_dashboard-0.1.0/docker-entrypoint.sh +24 -0
  225. craft_dashboard-0.1.0/docs/architecture.md +78 -0
  226. craft_dashboard-0.1.0/docs/development.md +99 -0
  227. craft_dashboard-0.1.0/docs/operations.md +355 -0
  228. craft_dashboard-0.1.0/docs/reference.md +232 -0
  229. craft_dashboard-0.1.0/pyproject.toml +234 -0
  230. craft_dashboard-0.1.0/scripts/__init__.py +1 -0
  231. craft_dashboard-0.1.0/scripts/audit_launchpad_employees.py +424 -0
  232. craft_dashboard-0.1.0/scripts/backfill_closing_references.py +220 -0
  233. craft_dashboard-0.1.0/scripts/backfill_content_hash.py +171 -0
  234. craft_dashboard-0.1.0/scripts/backfill_embeddings.py +221 -0
  235. craft_dashboard-0.1.0/scripts/backfill_eval_queue_depth.py +219 -0
  236. craft_dashboard-0.1.0/scripts/backfill_launchpad_maintainers.py +104 -0
  237. craft_dashboard-0.1.0/scripts/backfill_opinion_status.py +149 -0
  238. craft_dashboard-0.1.0/scripts/backfill_search_embeddings.py +238 -0
  239. craft_dashboard-0.1.0/scripts/backfill_snapshots.py +471 -0
  240. craft_dashboard-0.1.0/scripts/benchmark_llm.py +112 -0
  241. craft_dashboard-0.1.0/scripts/check_docs.py +122 -0
  242. craft_dashboard-0.1.0/scripts/collect/AGENTS.md +35 -0
  243. craft_dashboard-0.1.0/scripts/collect/__init__.py +1 -0
  244. craft_dashboard-0.1.0/scripts/collect/github_pass.py +582 -0
  245. craft_dashboard-0.1.0/scripts/collect/launchpad_pass.py +123 -0
  246. craft_dashboard-0.1.0/scripts/collect/projects.py +68 -0
  247. craft_dashboard-0.1.0/scripts/collect/reporting.py +62 -0
  248. craft_dashboard-0.1.0/scripts/collect/retry.py +103 -0
  249. craft_dashboard-0.1.0/scripts/collect/runs.py +144 -0
  250. craft_dashboard-0.1.0/scripts/collect_data.py +387 -0
  251. craft_dashboard-0.1.0/scripts/collect_forum_data.py +272 -0
  252. craft_dashboard-0.1.0/scripts/dev_stack.py +135 -0
  253. craft_dashboard-0.1.0/scripts/eval_timing.py +113 -0
  254. craft_dashboard-0.1.0/scripts/gc.py +104 -0
  255. craft_dashboard-0.1.0/scripts/gc_transcripts.py +20 -0
  256. craft_dashboard-0.1.0/scripts/llm/AGENTS.md +38 -0
  257. craft_dashboard-0.1.0/scripts/llm/__init__.py +1 -0
  258. craft_dashboard-0.1.0/scripts/llm/canary.py +214 -0
  259. craft_dashboard-0.1.0/scripts/llm/cli.py +806 -0
  260. craft_dashboard-0.1.0/scripts/llm/console.py +343 -0
  261. craft_dashboard-0.1.0/scripts/llm/eval_failures.py +92 -0
  262. craft_dashboard-0.1.0/scripts/llm/eval_http.py +253 -0
  263. craft_dashboard-0.1.0/scripts/llm/eval_payload.py +149 -0
  264. craft_dashboard-0.1.0/scripts/llm/eval_startup.py +88 -0
  265. craft_dashboard-0.1.0/scripts/llm/eval_worker.py +1179 -0
  266. craft_dashboard-0.1.0/scripts/llm/ratelimit.py +107 -0
  267. craft_dashboard-0.1.0/scripts/llm/validation.py +145 -0
  268. craft_dashboard-0.1.0/scripts/llm/worker_runtime.py +201 -0
  269. craft_dashboard-0.1.0/scripts/llm/worker_version.py +20 -0
  270. craft_dashboard-0.1.0/scripts/lp_bug_report.py +56 -0
  271. craft_dashboard-0.1.0/scripts/manage_eval_tokens.py +195 -0
  272. craft_dashboard-0.1.0/scripts/run_llm.py +12 -0
  273. craft_dashboard-0.1.0/setup.cfg +4 -0
  274. craft_dashboard-0.1.0/tests/__init__.py +0 -0
  275. craft_dashboard-0.1.0/tests/conftest.py +95 -0
  276. craft_dashboard-0.1.0/tests/end_to_end/__init__.py +1 -0
  277. craft_dashboard-0.1.0/tests/end_to_end/conftest.py +153 -0
  278. craft_dashboard-0.1.0/tests/end_to_end/helpers.py +155 -0
  279. craft_dashboard-0.1.0/tests/end_to_end/seed_data.py +538 -0
  280. craft_dashboard-0.1.0/tests/end_to_end/test_engagement.py +380 -0
  281. craft_dashboard-0.1.0/tests/end_to_end/test_issue_detail.py +62 -0
  282. craft_dashboard-0.1.0/tests/end_to_end/test_multiselect_a11y.py +86 -0
  283. craft_dashboard-0.1.0/tests/end_to_end/test_navigation.py +151 -0
  284. craft_dashboard-0.1.0/tests/end_to_end/test_releases.py +65 -0
  285. craft_dashboard-0.1.0/tests/end_to_end/test_trends.py +475 -0
  286. craft_dashboard-0.1.0/tests/end_to_end/test_triage.py +375 -0
  287. craft_dashboard-0.1.0/tests/factories.py +156 -0
  288. craft_dashboard-0.1.0/tests/helpers/__init__.py +1 -0
  289. craft_dashboard-0.1.0/tests/helpers/html.py +148 -0
  290. craft_dashboard-0.1.0/tests/integration/__init__.py +0 -0
  291. craft_dashboard-0.1.0/tests/integration/conftest.py +90 -0
  292. craft_dashboard-0.1.0/tests/integration/test_admin_api.py +823 -0
  293. craft_dashboard-0.1.0/tests/integration/test_bugfix_regressions.py +155 -0
  294. craft_dashboard-0.1.0/tests/integration/test_dashboard_api.py +613 -0
  295. craft_dashboard-0.1.0/tests/integration/test_eval_api.py +2794 -0
  296. craft_dashboard-0.1.0/tests/integration/test_evaluation_gc.py +137 -0
  297. craft_dashboard-0.1.0/tests/integration/test_releases_api.py +299 -0
  298. craft_dashboard-0.1.0/tests/integration/test_retention.py +48 -0
  299. craft_dashboard-0.1.0/tests/integration/test_setuptools.py +71 -0
  300. craft_dashboard-0.1.0/tests/integration/test_smoketest.py +10 -0
  301. craft_dashboard-0.1.0/tests/integration/test_snapshot_computations.py +458 -0
  302. craft_dashboard-0.1.0/tests/integration/test_snapshot_generation.py +320 -0
  303. craft_dashboard-0.1.0/tests/integration/test_stats_aggregation_characterization.py +235 -0
  304. craft_dashboard-0.1.0/tests/integration/test_trends_api.py +424 -0
  305. craft_dashboard-0.1.0/tests/integration/test_version.py +70 -0
  306. craft_dashboard-0.1.0/tests/unit/__init__.py +0 -0
  307. craft_dashboard-0.1.0/tests/unit/collectors/__init__.py +0 -0
  308. craft_dashboard-0.1.0/tests/unit/collectors/test_dependencies.py +446 -0
  309. craft_dashboard-0.1.0/tests/unit/collectors/test_exports.py +49 -0
  310. craft_dashboard-0.1.0/tests/unit/collectors/test_forum.py +684 -0
  311. craft_dashboard-0.1.0/tests/unit/collectors/test_github.py +1672 -0
  312. craft_dashboard-0.1.0/tests/unit/collectors/test_github_collect.py +208 -0
  313. craft_dashboard-0.1.0/tests/unit/collectors/test_github_collect_characterization.py +464 -0
  314. craft_dashboard-0.1.0/tests/unit/collectors/test_github_collector_releases.py +31 -0
  315. craft_dashboard-0.1.0/tests/unit/collectors/test_github_graphql.py +981 -0
  316. craft_dashboard-0.1.0/tests/unit/collectors/test_github_graphql_characterization.py +300 -0
  317. craft_dashboard-0.1.0/tests/unit/collectors/test_github_rate_limit.py +223 -0
  318. craft_dashboard-0.1.0/tests/unit/collectors/test_launchpad.py +830 -0
  319. craft_dashboard-0.1.0/tests/unit/collectors/test_scheduler.py +274 -0
  320. craft_dashboard-0.1.0/tests/unit/collectors/test_snapshots.py +942 -0
  321. craft_dashboard-0.1.0/tests/unit/commit_scanner/__init__.py +0 -0
  322. craft_dashboard-0.1.0/tests/unit/commit_scanner/conftest.py +46 -0
  323. craft_dashboard-0.1.0/tests/unit/commit_scanner/test_parsing.py +88 -0
  324. craft_dashboard-0.1.0/tests/unit/commit_scanner/test_scanner.py +933 -0
  325. craft_dashboard-0.1.0/tests/unit/git_mirrors/__init__.py +0 -0
  326. craft_dashboard-0.1.0/tests/unit/git_mirrors/conftest.py +95 -0
  327. craft_dashboard-0.1.0/tests/unit/git_mirrors/test_layout_cache.py +68 -0
  328. craft_dashboard-0.1.0/tests/unit/git_mirrors/test_paths.py +106 -0
  329. craft_dashboard-0.1.0/tests/unit/git_mirrors/test_reader.py +447 -0
  330. craft_dashboard-0.1.0/tests/unit/git_mirrors/test_sync.py +216 -0
  331. craft_dashboard-0.1.0/tests/unit/llm/__init__.py +0 -0
  332. craft_dashboard-0.1.0/tests/unit/llm/test_acp_client.py +129 -0
  333. craft_dashboard-0.1.0/tests/unit/llm/test_baseline.py +193 -0
  334. craft_dashboard-0.1.0/tests/unit/llm/test_client.py +485 -0
  335. craft_dashboard-0.1.0/tests/unit/llm/test_client_protocol.py +55 -0
  336. craft_dashboard-0.1.0/tests/unit/llm/test_client_tool_calling.py +194 -0
  337. craft_dashboard-0.1.0/tests/unit/llm/test_closed_evaluation.py +159 -0
  338. craft_dashboard-0.1.0/tests/unit/llm/test_duplicate_detector.py +205 -0
  339. craft_dashboard-0.1.0/tests/unit/llm/test_duplicate_prompts.py +65 -0
  340. craft_dashboard-0.1.0/tests/unit/llm/test_embeddings.py +184 -0
  341. craft_dashboard-0.1.0/tests/unit/llm/test_evaluation_queue.py +372 -0
  342. craft_dashboard-0.1.0/tests/unit/llm/test_evaluation_queue_characterization.py +371 -0
  343. craft_dashboard-0.1.0/tests/unit/llm/test_evaluator.py +1534 -0
  344. craft_dashboard-0.1.0/tests/unit/llm/test_exceptions.py +27 -0
  345. craft_dashboard-0.1.0/tests/unit/llm/test_preflight.py +205 -0
  346. craft_dashboard-0.1.0/tests/unit/llm/test_prompts.py +476 -0
  347. craft_dashboard-0.1.0/tests/unit/llm/test_tool_dispatch.py +408 -0
  348. craft_dashboard-0.1.0/tests/unit/llm/test_tools.py +53 -0
  349. craft_dashboard-0.1.0/tests/unit/models/__init__.py +0 -0
  350. craft_dashboard-0.1.0/tests/unit/models/test_base.py +19 -0
  351. craft_dashboard-0.1.0/tests/unit/models/test_commit_scan_evidence_path.py +31 -0
  352. craft_dashboard-0.1.0/tests/unit/models/test_commit_scan_run.py +62 -0
  353. craft_dashboard-0.1.0/tests/unit/models/test_dependency.py +41 -0
  354. craft_dashboard-0.1.0/tests/unit/models/test_evaluation_transcript.py +62 -0
  355. craft_dashboard-0.1.0/tests/unit/models/test_issue.py +118 -0
  356. craft_dashboard-0.1.0/tests/unit/models/test_issue_activity.py +74 -0
  357. craft_dashboard-0.1.0/tests/unit/models/test_issue_link.py +109 -0
  358. craft_dashboard-0.1.0/tests/unit/models/test_llm_evaluation.py +104 -0
  359. craft_dashboard-0.1.0/tests/unit/models/test_project.py +36 -0
  360. craft_dashboard-0.1.0/tests/unit/models/test_refresh_schedule.py +41 -0
  361. craft_dashboard-0.1.0/tests/unit/models/test_release.py +96 -0
  362. craft_dashboard-0.1.0/tests/unit/models/test_snapshot.py +57 -0
  363. craft_dashboard-0.1.0/tests/unit/repositories/__init__.py +1 -0
  364. craft_dashboard-0.1.0/tests/unit/repositories/test_eval_token_repository.py +129 -0
  365. craft_dashboard-0.1.0/tests/unit/repositories/test_issue_link_repository.py +439 -0
  366. craft_dashboard-0.1.0/tests/unit/repositories/test_issue_repository.py +1373 -0
  367. craft_dashboard-0.1.0/tests/unit/routes/__init__.py +0 -0
  368. craft_dashboard-0.1.0/tests/unit/routes/test_admin.py +707 -0
  369. craft_dashboard-0.1.0/tests/unit/routes/test_admin_status.py +81 -0
  370. craft_dashboard-0.1.0/tests/unit/routes/test_dashboard.py +301 -0
  371. craft_dashboard-0.1.0/tests/unit/routes/test_engagement.py +203 -0
  372. craft_dashboard-0.1.0/tests/unit/routes/test_eval_api.py +156 -0
  373. craft_dashboard-0.1.0/tests/unit/routes/test_issue_detail.py +659 -0
  374. craft_dashboard-0.1.0/tests/unit/routes/test_issues.py +708 -0
  375. craft_dashboard-0.1.0/tests/unit/routes/test_issues_export.py +139 -0
  376. craft_dashboard-0.1.0/tests/unit/routes/test_issues_shareable_urls.py +75 -0
  377. craft_dashboard-0.1.0/tests/unit/routes/test_stats.py +152 -0
  378. craft_dashboard-0.1.0/tests/unit/routes/test_stats_deps_releases.py +546 -0
  379. craft_dashboard-0.1.0/tests/unit/routes/test_stats_trends.py +953 -0
  380. craft_dashboard-0.1.0/tests/unit/scripts/__init__.py +0 -0
  381. craft_dashboard-0.1.0/tests/unit/scripts/test_backfill_embeddings.py +98 -0
  382. craft_dashboard-0.1.0/tests/unit/scripts/test_backfill_eval_queue_depth.py +90 -0
  383. craft_dashboard-0.1.0/tests/unit/scripts/test_backfill_launchpad_maintainers.py +140 -0
  384. craft_dashboard-0.1.0/tests/unit/scripts/test_backfill_search_embeddings.py +216 -0
  385. craft_dashboard-0.1.0/tests/unit/scripts/test_backfill_snapshots.py +215 -0
  386. craft_dashboard-0.1.0/tests/unit/scripts/test_canary.py +145 -0
  387. craft_dashboard-0.1.0/tests/unit/scripts/test_collect_data_health.py +554 -0
  388. craft_dashboard-0.1.0/tests/unit/scripts/test_collect_data_watermarks.py +401 -0
  389. craft_dashboard-0.1.0/tests/unit/scripts/test_eval_http.py +114 -0
  390. craft_dashboard-0.1.0/tests/unit/scripts/test_eval_timing.py +180 -0
  391. craft_dashboard-0.1.0/tests/unit/scripts/test_eval_worker.py +1041 -0
  392. craft_dashboard-0.1.0/tests/unit/scripts/test_eval_worker_characterization.py +466 -0
  393. craft_dashboard-0.1.0/tests/unit/scripts/test_forum_backfill.py +167 -0
  394. craft_dashboard-0.1.0/tests/unit/scripts/test_llm_cli.py +264 -0
  395. craft_dashboard-0.1.0/tests/unit/scripts/test_llm_console.py +184 -0
  396. craft_dashboard-0.1.0/tests/unit/scripts/test_llm_http_evaluate_cli.py +388 -0
  397. craft_dashboard-0.1.0/tests/unit/scripts/test_llm_ratelimit.py +118 -0
  398. craft_dashboard-0.1.0/tests/unit/scripts/test_llm_validation.py +245 -0
  399. craft_dashboard-0.1.0/tests/unit/scripts/test_manage_eval_tokens.py +103 -0
  400. craft_dashboard-0.1.0/tests/unit/services/__init__.py +1 -0
  401. craft_dashboard-0.1.0/tests/unit/services/test_admin_collection_health.py +154 -0
  402. craft_dashboard-0.1.0/tests/unit/services/test_admin_service.py +1690 -0
  403. craft_dashboard-0.1.0/tests/unit/services/test_admin_status.py +128 -0
  404. craft_dashboard-0.1.0/tests/unit/services/test_dashboard_metrics_characterization.py +1609 -0
  405. craft_dashboard-0.1.0/tests/unit/services/test_dashboard_service.py +359 -0
  406. craft_dashboard-0.1.0/tests/unit/services/test_dashboard_view_models.py +530 -0
  407. craft_dashboard-0.1.0/tests/unit/services/test_eval_activity.py +61 -0
  408. craft_dashboard-0.1.0/tests/unit/services/test_eval_auth_service.py +153 -0
  409. craft_dashboard-0.1.0/tests/unit/services/test_stats_service_characterization.py +345 -0
  410. craft_dashboard-0.1.0/tests/unit/services/test_transcript_gc.py +113 -0
  411. craft_dashboard-0.1.0/tests/unit/test_app.py +249 -0
  412. craft_dashboard-0.1.0/tests/unit/test_auth.py +37 -0
  413. craft_dashboard-0.1.0/tests/unit/test_check_docs.py +61 -0
  414. craft_dashboard-0.1.0/tests/unit/test_cli.py +122 -0
  415. craft_dashboard-0.1.0/tests/unit/test_collect_data.py +718 -0
  416. craft_dashboard-0.1.0/tests/unit/test_config.py +188 -0
  417. craft_dashboard-0.1.0/tests/unit/test_config_validation.py +81 -0
  418. craft_dashboard-0.1.0/tests/unit/test_database.py +48 -0
  419. craft_dashboard-0.1.0/tests/unit/test_dependencies.py +42 -0
  420. craft_dashboard-0.1.0/tests/unit/test_factories.py +51 -0
  421. craft_dashboard-0.1.0/tests/unit/test_frontend_assets.py +46 -0
  422. craft_dashboard-0.1.0/tests/unit/test_http_retry.py +132 -0
  423. craft_dashboard-0.1.0/tests/unit/test_issue_age.py +18 -0
  424. craft_dashboard-0.1.0/tests/unit/test_rate_limit.py +38 -0
  425. craft_dashboard-0.1.0/tests/unit/test_seed_data.py +22 -0
  426. craft_dashboard-0.1.0/tests/unit/test_settings.py +184 -0
  427. craft_dashboard-0.1.0/tests/unit/test_stub.py +2 -0
  428. craft_dashboard-0.1.0/uv.lock +1977 -0
@@ -0,0 +1,24 @@
1
+ .git
2
+ .github
3
+ .venv
4
+ .pytest_cache
5
+ .ruff_cache
6
+ __pycache__
7
+ *.pyc
8
+ .env
9
+ .env.example
10
+ .envrc
11
+ tests/
12
+ docs/
13
+ provisioning/
14
+ plans/
15
+ *.egg-info
16
+ logs.txt
17
+ *.sql.gz
18
+ .logs/
19
+ .local/
20
+ debug-evals/
21
+ *.pem
22
+ .token_cache*.json
23
+ htmlcov/
24
+ .coverage
@@ -0,0 +1,65 @@
1
+ # ===========================================================================
2
+ # General & Shared Configuration
3
+ # ===========================================================================
4
+ # Craft-dashboard server URL to pull evaluation jobs from
5
+ # Local Dev: https://craft-dashboard.name (or http://localhost:8000)
6
+ # Production VPS: http://craft-dashboard:8000
7
+ DASHBOARD_URL=
8
+
9
+ # Eval API bearer token (authenticates worker requests to /api/eval/*)
10
+ EVAL_API_TOKEN=
11
+
12
+ # GitHub token (shared: collector cron on server, local scripts/queries)
13
+ GITHUB_TOKEN=
14
+
15
+ DEBUG=false
16
+ LOG_LEVEL=INFO
17
+
18
+ # ===========================================================================
19
+ # LLM Backend Configuration
20
+ # ===========================================================================
21
+ # Choose a backend (OpenRouter or llama.cpp) by commenting/uncommenting.
22
+
23
+ # --- OpenRouter ---
24
+ LLM_BASE_URL=https://openrouter.ai/api/v1
25
+ LLM_API_KEY=
26
+ LLM_MODEL=
27
+ # LLM_MODEL_SUMMARY=
28
+ # LLM_MODEL_SCORING=
29
+
30
+ # --- llama.cpp (local OpenAI-compatible server) ---
31
+ # LLM_BASE_URL=http://localhost:8080/v1
32
+ # LLM_API_KEY=
33
+ # LLM_MODEL=
34
+
35
+ # LLM & worker tuning
36
+ # LLM_TIMEOUT=600.0
37
+ # LLM_CA_CERT=
38
+ # DASHBOARD_CA_CERT=
39
+
40
+ # Git mirror storage for evaluation tools (git grep, git log)
41
+ # CRAFT_DASHBOARD_MIRROR_DIR=~/.cache/craft-dashboard/mirrors
42
+ # CRAFT_DASHBOARD_GIT_CONCURRENCY=2
43
+
44
+ # ===========================================================================
45
+ # Server Only (Production VPS: /opt/vps-infra/.env)
46
+ # ===========================================================================
47
+ # PostgreSQL connection string (server only; local evals use HTTP)
48
+ # DATABASE_URL=postgresql+asyncpg://craft_dashboard:<DB_PASSWORD>@postgres/craft_dashboard
49
+
50
+ # Admin bearer token for /api/admin/* endpoints
51
+ # ADMIN_TOKEN=
52
+
53
+ # API key for server-side semantic search & eval embeddings
54
+ # EMBEDDING_API_KEY=
55
+
56
+ # Retention window in days for superseded evaluation transcripts
57
+ # EVAL_TRANSCRIPT_RETENTION_DAYS=30
58
+
59
+ # Auto-pause evaluation when today's USD spend cap is reached (0.0 = unlimited)
60
+ # EVAL_DAILY_SPEND_CAP_USD=0.0
61
+
62
+ # Related issues tuning on the issue detail page
63
+ # RELATED_ISSUES_TOP_N=10
64
+ # RELATED_ISSUES_SIMILARITY_THRESHOLD=0.70
65
+
@@ -0,0 +1 @@
1
+ - [ ] Have you successfully run `make lint && make test`?
@@ -0,0 +1,3 @@
1
+ {
2
+ extends: ["github>canonical/starflow:renovate.json5"],
3
+ }
@@ -0,0 +1,31 @@
1
+ name: Renovate check
2
+ on:
3
+ pull_request:
4
+ paths:
5
+ - ".github/workflows/check-renovate.yaml"
6
+ - ".github/renovate.json5"
7
+
8
+ # Allows triggering the workflow manually from the Actions tab
9
+ workflow_dispatch:
10
+ inputs:
11
+ enable_ssh_access:
12
+ type: boolean
13
+ description: "Enable ssh access"
14
+ required: false
15
+ default: false
16
+
17
+ jobs:
18
+ renovate:
19
+ runs-on: ubuntu-latest
20
+ steps:
21
+ - name: Checkout
22
+ uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
23
+ - name: Install renovate
24
+ run: npm install --global re2 renovate
25
+ - name: Check renovate config
26
+ run: renovate-config-validator .github/renovate.json5
27
+ - name: Renovate dry-run
28
+ run: renovate --dry-run=full --autodiscover --print-config
29
+ env:
30
+ RENOVATE_TOKEN: ${{ secrets.GITHUB_TOKEN }}
31
+ RENOVATE_USE_BASE_BRANCH_CONFIG: ${{ github.ref }}
@@ -0,0 +1,89 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+ workflow_call:
9
+
10
+ jobs:
11
+ lint:
12
+ runs-on: ubuntu-latest
13
+ steps:
14
+ - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
15
+ - uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
16
+ - run: |
17
+ uv sync --frozen
18
+ make setup
19
+ make lint
20
+
21
+ lockfile:
22
+ runs-on: ubuntu-latest
23
+ steps:
24
+ - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
25
+ - uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
26
+ # A lockfile that has drifted from pyproject.toml means CI and the
27
+ # published image resolve different dependency versions.
28
+ - run: uv lock --check
29
+
30
+ test:
31
+ runs-on: ubuntu-latest
32
+ steps:
33
+ - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
34
+ - uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
35
+ - run: |
36
+ uv sync --frozen
37
+ make setup
38
+ make test
39
+
40
+ migrations:
41
+ runs-on: ubuntu-latest
42
+ # The app runs `alembic upgrade head` at startup, so a migration that fails
43
+ # on PostgreSQL takes production down rather than failing a test. The unit
44
+ # suite runs on SQLite and cannot catch that.
45
+ services:
46
+ postgres:
47
+ # Must match the image vps-infra runs; migrations create the
48
+ # `vector` extension, which stock postgres does not ship.
49
+ image: pgvector/pgvector:pg16
50
+ env:
51
+ POSTGRES_USER: craft_dashboard
52
+ POSTGRES_PASSWORD: craft_dashboard
53
+ POSTGRES_DB: craft_dashboard
54
+ ports: ["5432:5432"]
55
+ options: >-
56
+ --health-cmd "pg_isready -U craft_dashboard"
57
+ --health-interval 5s
58
+ --health-timeout 5s
59
+ --health-retries 10
60
+ env:
61
+ DATABASE_URL: postgresql+asyncpg://craft_dashboard:craft_dashboard@localhost:5432/craft_dashboard
62
+ steps:
63
+ - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
64
+ - uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
65
+ - run: uv sync --frozen
66
+ - name: Upgrade an empty database to head
67
+ run: uv run alembic upgrade head
68
+ - name: Check for a missing migration
69
+ # Autogenerate must produce no operations once head is applied,
70
+ # otherwise a model change shipped without its migration.
71
+ run: |
72
+ uv run alembic check
73
+
74
+ image:
75
+ runs-on: ubuntu-latest
76
+ steps:
77
+ - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
78
+ with:
79
+ fetch-depth: 0 # needed for setuptools_scm versioning
80
+ - name: Build the runtime image
81
+ run: |
82
+ docker build --build-arg SETUPTOOLS_SCM_PRETEND_VERSION=0.0.0 \
83
+ -t craft-dashboard:ci .
84
+ - name: Smoke test the image
85
+ # Catches a broken entrypoint or a missing runtime dependency before
86
+ # the image reaches GHCR and the deploy workflow restarts production.
87
+ run: |
88
+ docker run --rm craft-dashboard:ci \
89
+ python -c "from craft_dashboard.app import create_app; create_app()"
@@ -0,0 +1,23 @@
1
+ name: E2E
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+ workflow_dispatch:
9
+ workflow_call:
10
+
11
+ jobs:
12
+ test-e2e:
13
+ runs-on: ubuntu-latest
14
+ steps:
15
+ - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
16
+ - uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
17
+ - uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6.5.0
18
+ with:
19
+ node-version: "22"
20
+ - run: |
21
+ uv sync --frozen
22
+ make setup
23
+ make test-e2e
@@ -0,0 +1,98 @@
1
+ name: Publish Docker Image
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+
7
+ env:
8
+ REGISTRY: ghcr.io
9
+ IMAGE_NAME: ${{ github.repository }}
10
+
11
+ jobs:
12
+ # Publishing to GHCR triggers a production deploy, so it must not run ahead
13
+ # of the checks. Calling the workflows here (rather than relying on branch
14
+ # protection) keeps the gate in version control.
15
+ ci:
16
+ uses: ./.github/workflows/ci.yml
17
+
18
+ e2e:
19
+ uses: ./.github/workflows/e2e.yml
20
+
21
+ publish:
22
+ needs: [ci, e2e]
23
+ runs-on: ubuntu-latest
24
+ permissions:
25
+ contents: read
26
+ packages: write
27
+ security-events: write # for the Trivy SARIF upload
28
+
29
+ steps:
30
+ - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
31
+ with:
32
+ fetch-depth: 0 # needed for setuptools_scm versioning
33
+
34
+ # The default docker driver cannot attach SBOM or provenance
35
+ # attestations; the container driver can.
36
+ - name: Set up Buildx
37
+ uses: docker/setup-buildx-action@f87e5991a6d7451dcb8d9637bfbc97413f497069 # v4.4.1
38
+
39
+ - name: Log in to GHCR
40
+ uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0
41
+ with:
42
+ registry: ${{ env.REGISTRY }}
43
+ username: ${{ github.actor }}
44
+ password: ${{ secrets.GITHUB_TOKEN }}
45
+
46
+ - name: Extract metadata
47
+ id: meta
48
+ uses: docker/metadata-action@80c7e94dd9b9319bd5eb7a0e0fe9291e23a2a2e9 # v6.1.0
49
+ with:
50
+ images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
51
+ tags: |
52
+ type=raw,value=latest
53
+ type=sha,prefix=
54
+
55
+ - name: Build and push
56
+ id: build
57
+ uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7.2.0
58
+ with:
59
+ context: .
60
+ push: true
61
+ tags: ${{ steps.meta.outputs.tags }}
62
+ labels: ${{ steps.meta.outputs.labels }}
63
+ provenance: mode=max
64
+ sbom: true
65
+ build-args: |
66
+ SETUPTOOLS_SCM_PRETEND_VERSION=0.0.0
67
+
68
+ - name: Scan the published image
69
+ continue-on-error: true
70
+ uses: aquasecurity/trivy-action@dc5a429b52fcf669ce959baa2c2dd26090d2a6c4 # v0.32.0
71
+ with:
72
+ image-ref: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@${{ steps.build.outputs.digest }}
73
+ format: sarif
74
+ output: trivy.sarif
75
+ severity: CRITICAL,HIGH
76
+ ignore-unfixed: true
77
+
78
+ - name: Upload scan results
79
+ # Informational: a base-image CVE must not block shipping an app fix.
80
+ continue-on-error: true
81
+ uses: github/codeql-action/upload-sarif@88585263c0627ee42c0e1c5143a112c8d6f4aa18 # v4.38.2
82
+ with:
83
+ sarif_file: trivy.sarif
84
+
85
+ - name: Trigger vps-infra deploy
86
+ uses: peter-evans/repository-dispatch@ff45666b9427631e3450c54a1bcbee4d9ff4d7c0 # v3.0.0
87
+ with:
88
+ token: ${{ secrets.VPSINFRA_PAT }}
89
+ repository: mr-cal/vps-infra
90
+ event-type: craft-dashboard-updated
91
+ # The digest makes a deploy reproducible and a rollback unambiguous;
92
+ # `latest` is a convenience tag only. vps-infra may pin to this.
93
+ client-payload: |
94
+ {
95
+ "image": "${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}",
96
+ "digest": "${{ steps.build.outputs.digest }}",
97
+ "sha": "${{ github.sha }}"
98
+ }
@@ -0,0 +1,69 @@
1
+ name: Release
2
+ on:
3
+ push:
4
+ tags:
5
+ - "[0-9]+.[0-9]+.[0-9]+"
6
+ pull_request:
7
+ paths:
8
+ - .github/workflows/release-publish.yaml
9
+
10
+ jobs:
11
+ source-wheel:
12
+ if: github.event_name == 'push' || (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository)
13
+ runs-on: ubuntu-latest
14
+ permissions:
15
+ contents: read
16
+ steps:
17
+ - name: Checkout
18
+ uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
19
+ with:
20
+ persist-credentials: false
21
+ - name: Install uv
22
+ uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
23
+ - name: Fetch tag annotations
24
+ if: ${{ github.event_name != 'pull_request' }}
25
+ run: |
26
+ git fetch --force --tags --depth 1
27
+ git describe --dirty --long --match '[0-9]*.[0-9]*.[0-9]*' --exclude '*[^0-9.]*'
28
+ - name: Build packages
29
+ run: |
30
+ uv build
31
+ uvx twine check dist/*
32
+ - name: Upload pypi packages artifact
33
+ uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
34
+ with:
35
+ name: pypi-packages
36
+ path: dist/
37
+
38
+ pypi:
39
+ needs: ["source-wheel"]
40
+ runs-on: ubuntu-latest
41
+ permissions:
42
+ id-token: write
43
+ steps:
44
+ - name: Get packages
45
+ uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
46
+ with:
47
+ name: pypi-packages
48
+ path: dist/
49
+ - name: Publish to pypi
50
+ if: ${{ startsWith(github.ref, 'refs/tags/') }}
51
+ uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # release/v1
52
+
53
+ github-release:
54
+ needs: ["source-wheel"]
55
+ runs-on: ubuntu-latest
56
+ permissions:
57
+ contents: write
58
+ steps:
59
+ - name: Get pypi artifacts
60
+ uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
61
+ with:
62
+ name: pypi-packages
63
+ - name: Release
64
+ if: ${{ startsWith(github.ref, 'refs/tags/') }}
65
+ env:
66
+ GH_REPO: ${{ github.repository }}
67
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
68
+ RELEASE_TAG: ${{ github.ref_name }}
69
+ run: gh release create "$RELEASE_TAG" --generate-notes -- *.whl *.tar.gz
@@ -0,0 +1,87 @@
1
+ name: Release
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "[0-9]+.[0-9]+.[0-9]+*"
7
+ workflow_dispatch:
8
+ inputs:
9
+ dry-run:
10
+ description: "Verify build without publishing to PyPI"
11
+ type: boolean
12
+ default: false
13
+
14
+ permissions:
15
+ contents: read
16
+
17
+ jobs:
18
+ ci:
19
+ uses: ./.github/workflows/ci.yml
20
+
21
+ build:
22
+ needs: [ci]
23
+ runs-on: ubuntu-latest
24
+ steps:
25
+ - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
26
+ with:
27
+ fetch-depth: 0
28
+
29
+ - name: Fetch tag annotations
30
+ run: |
31
+ git fetch --force --tags --depth 1
32
+
33
+ - uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
34
+
35
+ - name: Build packages
36
+ run: |
37
+ uv build
38
+ uvx twine check dist/*
39
+
40
+ - name: Upload pypi packages artifact
41
+ uses: actions/upload-artifact@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1 # v4.6.1
42
+ with:
43
+ name: pypi-packages
44
+ path: dist/
45
+ if-no-files-found: error
46
+
47
+ publish-pypi:
48
+ needs: [build]
49
+ if: startsWith(github.ref, 'refs/tags/') && !inputs.dry-run
50
+ runs-on: ubuntu-latest
51
+ permissions:
52
+ id-token: write # Mandatory for PyPI Trusted Publishing
53
+
54
+ steps:
55
+ - name: Get packages
56
+ uses: actions/download-artifact@cc203385981b70ca67e1cc392babf9cc229d5806 # v4.1.9
57
+ with:
58
+ name: pypi-packages
59
+ path: dist/
60
+
61
+ - name: Publish to PyPI
62
+ uses: pypa/gh-action-pypi-publish@release/v1
63
+
64
+ github-release:
65
+ needs: [publish-pypi]
66
+ if: startsWith(github.ref, 'refs/tags/')
67
+ runs-on: ubuntu-latest
68
+ permissions:
69
+ contents: write
70
+
71
+ steps:
72
+ - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
73
+
74
+ - name: Get packages
75
+ uses: actions/download-artifact@cc203385981b70ca67e1cc392babf9cc229d5806 # v4.1.9
76
+ with:
77
+ name: pypi-packages
78
+ path: dist/
79
+
80
+ - name: Create GitHub Release
81
+ env:
82
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
83
+ run: |
84
+ gh release create "${{ github.ref_name }}" \
85
+ --title "${{ github.ref_name }}" \
86
+ --generate-notes \
87
+ dist/*
@@ -0,0 +1,54 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+ *.egg-info/
6
+ *.egg
7
+ dist/
8
+ build/
9
+ .eggs/
10
+
11
+ # Version
12
+ craft_dashboard/_version.py
13
+
14
+ # Virtual environments
15
+ .venv/
16
+ venv/
17
+
18
+ # IDE
19
+ .idea/
20
+ .vscode/
21
+ *.swp
22
+ *.swo
23
+
24
+ # Tools
25
+ .cache/
26
+ .bakeoff/
27
+ .mypy_cache/
28
+ .ruff_cache/
29
+ .pytest_cache/
30
+ .coverage
31
+ htmlcov/
32
+
33
+ # Environment
34
+ .env*
35
+ !.env.example
36
+ .envrc
37
+ provisioning/secrets.env
38
+ *.sql.gz
39
+
40
+ # OS
41
+ .DS_Store
42
+
43
+ # uv
44
+ logs.txt
45
+
46
+ # plans
47
+ plans/
48
+
49
+ # LLM debug-eval scratch artifacts (local-only, not versioned)
50
+ debug-evals/
51
+ .logs/
52
+ .local/
53
+ *.pem
54
+ .token_cache*.json
@@ -0,0 +1,51 @@
1
+ # ---- Build stage ----
2
+ FROM python:3.12-slim AS builder
3
+
4
+ WORKDIR /build
5
+ RUN pip install --no-cache-dir uv
6
+
7
+ COPY pyproject.toml uv.lock ./
8
+ COPY craft_dashboard/ craft_dashboard/
9
+ COPY alembic/ alembic/
10
+ COPY alembic.ini ./
11
+ COPY scripts/ scripts/
12
+ COPY craft-dashboard.toml ./
13
+
14
+ # setuptools_scm needs .git; use a pretend version in Docker builds
15
+ ARG SETUPTOOLS_SCM_PRETEND_VERSION=0.0.0
16
+
17
+ # Install the app and its dependencies into a virtual environment
18
+ RUN uv venv /app/.venv \
19
+ && uv pip install --python /app/.venv/bin/python . psycopg2-binary
20
+
21
+ # ---- Runtime stage ----
22
+ FROM python:3.12-slim
23
+
24
+ RUN apt-get update && apt-get install -y --no-install-recommends libpq5 postgresql-client git \
25
+ && rm -rf /var/lib/apt/lists/*
26
+
27
+ # A fixed UID so bind-mounted host directories (the git mirror store) can be
28
+ # chowned to match. Keep in sync with vps-infra's mirror volume ownership.
29
+ RUN useradd --create-home --uid 10001 --user-group app
30
+
31
+ COPY --from=builder /app/.venv /app/.venv
32
+ COPY --from=builder /build /app
33
+ COPY docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh
34
+ WORKDIR /app
35
+
36
+ ENV PATH="/app/.venv/bin:$PATH" \
37
+ PYTHONUNBUFFERED=1 \
38
+ HOME=/home/app
39
+
40
+ RUN chown -R app:app /app
41
+
42
+ USER app
43
+
44
+ EXPOSE 8000
45
+
46
+ # Declared here as well as in compose, so `podman run` and any orchestrator
47
+ # that ignores compose still get a liveness signal. curl is not installed.
48
+ HEALTHCHECK --interval=30s --timeout=5s --start-period=60s --retries=3 \
49
+ CMD python -c "import urllib.request; urllib.request.urlopen('http://localhost:8000/health')" || exit 1
50
+
51
+ CMD ["/usr/local/bin/docker-entrypoint.sh"]