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.
- craft_dashboard-0.1.0/.dockerignore +24 -0
- craft_dashboard-0.1.0/.env.example +65 -0
- craft_dashboard-0.1.0/.github/PULL_REQUEST_TEMPLATE.md +1 -0
- craft_dashboard-0.1.0/.github/renovate.json5 +3 -0
- craft_dashboard-0.1.0/.github/workflows/check-renovate.yaml +31 -0
- craft_dashboard-0.1.0/.github/workflows/ci.yml +89 -0
- craft_dashboard-0.1.0/.github/workflows/e2e.yml +23 -0
- craft_dashboard-0.1.0/.github/workflows/publish.yml +98 -0
- craft_dashboard-0.1.0/.github/workflows/release-publish.yaml +69 -0
- craft_dashboard-0.1.0/.github/workflows/release.yml +87 -0
- craft_dashboard-0.1.0/.gitignore +54 -0
- craft_dashboard-0.1.0/Dockerfile +51 -0
- craft_dashboard-0.1.0/LICENSE +165 -0
- craft_dashboard-0.1.0/Makefile +100 -0
- craft_dashboard-0.1.0/PKG-INFO +71 -0
- craft_dashboard-0.1.0/README.md +35 -0
- craft_dashboard-0.1.0/REPO_MAP.md +59 -0
- craft_dashboard-0.1.0/agents.md +185 -0
- craft_dashboard-0.1.0/alembic/env.py +75 -0
- craft_dashboard-0.1.0/alembic/script.py.mako +26 -0
- craft_dashboard-0.1.0/alembic/versions/.gitkeep +0 -0
- craft_dashboard-0.1.0/alembic/versions/04b321505716_add_evidence_generation_and_scanner_tables.py +102 -0
- craft_dashboard-0.1.0/alembic/versions/0a1b2c3d4e5f_remove_duplicate_detection_columns.py +54 -0
- craft_dashboard-0.1.0/alembic/versions/0d2e05caabfc_add_superseded_by_to_issue_links_kind_.py +39 -0
- craft_dashboard-0.1.0/alembic/versions/106bfe752b75_add_issue_search_embedding.py +41 -0
- craft_dashboard-0.1.0/alembic/versions/2b5dce17fece_add_llm_evaluation_cost_usd.py +28 -0
- craft_dashboard-0.1.0/alembic/versions/326fd64d080f_add_issue_links_table.py +75 -0
- craft_dashboard-0.1.0/alembic/versions/38a9bb474e97_add_issue_content_hash.py +28 -0
- craft_dashboard-0.1.0/alembic/versions/3bf712e6582b_add_eval_queue_snapshots_table.py +46 -0
- craft_dashboard-0.1.0/alembic/versions/42f5d054e245_add_forum_activity_tables.py +76 -0
- craft_dashboard-0.1.0/alembic/versions/444063d1b5b0_add_eval_api_tokens_and_evaluated_by.py +154 -0
- craft_dashboard-0.1.0/alembic/versions/4ae069e8c8f0_add_category_progress_to_forum_backfill_.py +48 -0
- craft_dashboard-0.1.0/alembic/versions/58e6ebac628e_add_open_poll_failure_tracking_to_.py +46 -0
- craft_dashboard-0.1.0/alembic/versions/5d2a2a5c1823_add_median_age_and_closed_counts_to_.py +72 -0
- craft_dashboard-0.1.0/alembic/versions/68de7346cc6d_add_issue_activities_table.py +63 -0
- craft_dashboard-0.1.0/alembic/versions/7f8e9d0c1b2a_fix_stale_content_hash.py +33 -0
- craft_dashboard-0.1.0/alembic/versions/9c0a9d2a88fe_backfill_bot_accounts.py +40 -0
- craft_dashboard-0.1.0/alembic/versions/9e37c633701b_add_embedding_tokens_and_ingestion_metrics.py +51 -0
- craft_dashboard-0.1.0/alembic/versions/a1b2c3d4e5f6_add_duplicate_detection_columns.py +70 -0
- craft_dashboard-0.1.0/alembic/versions/a3f9d2e1b5c8_add_dep_version_columns.py +36 -0
- craft_dashboard-0.1.0/alembic/versions/ab12cd34ef56_remove_duplicate_lp_issues_from_snapcraft.py +41 -0
- craft_dashboard-0.1.0/alembic/versions/acbc7fc12cd7_add_embed_queue_index.py +38 -0
- craft_dashboard-0.1.0/alembic/versions/b1c2d3e4f5a6_add_combined_median_age_columns.py +49 -0
- craft_dashboard-0.1.0/alembic/versions/b67acfce407c_releases_unique_by_project_branch.py +32 -0
- craft_dashboard-0.1.0/alembic/versions/b7c1d9e42f08_enforce_releases_branch_not_null.py +43 -0
- craft_dashboard-0.1.0/alembic/versions/c3e8f1a2b9d7_add_per_view_median_age_fields.py +67 -0
- craft_dashboard-0.1.0/alembic/versions/c4d5e6f7a8b9_add_collection_run_id_to_issues.py +40 -0
- craft_dashboard-0.1.0/alembic/versions/c51008987675_add_evaluation_transcripts_table.py +71 -0
- craft_dashboard-0.1.0/alembic/versions/c9f8a7b6e5d4_migrate_close_outdated.py +30 -0
- craft_dashboard-0.1.0/alembic/versions/d1b3f5a46924_add_eval_version.py +35 -0
- craft_dashboard-0.1.0/alembic/versions/d4e5f6a7b8c9_add_token_breakdown_and_backend.py +39 -0
- craft_dashboard-0.1.0/alembic/versions/d89e58e0a23e_add_comments_column.py +34 -0
- craft_dashboard-0.1.0/alembic/versions/dc49f831c706_rename_summary_and_add_run_id.py +46 -0
- craft_dashboard-0.1.0/alembic/versions/e728675ec251_add_eval_type_to_llm_evaluations.py +44 -0
- craft_dashboard-0.1.0/alembic/versions/e7f8a9b0c1d2_add_collection_tracking_tables.py +67 -0
- craft_dashboard-0.1.0/alembic/versions/e8f1a2b9c3d4_add_summary_embedding.py +44 -0
- craft_dashboard-0.1.0/alembic/versions/f1b467aa1a8f_initial.py +175 -0
- craft_dashboard-0.1.0/alembic/versions/f2a3b4c5d6e7_add_eval_locked_until_column.py +29 -0
- craft_dashboard-0.1.0/alembic/versions/f2b1e1807a8a_add_eval_queue_index.py +34 -0
- craft_dashboard-0.1.0/alembic/versions/f9a0b1c2d3e4_resize_summary_embedding_to_1024.py +67 -0
- craft_dashboard-0.1.0/alembic/versions/fa02b11af7dc_add_author_is_bot_and_snapshot_bot_fields.py +61 -0
- craft_dashboard-0.1.0/alembic.ini +36 -0
- craft_dashboard-0.1.0/craft-dashboard.toml +187 -0
- craft_dashboard-0.1.0/craft_dashboard/__init__.py +1 -0
- craft_dashboard-0.1.0/craft_dashboard/_version.py +24 -0
- craft_dashboard-0.1.0/craft_dashboard/app.py +324 -0
- craft_dashboard-0.1.0/craft_dashboard/auth.py +79 -0
- craft_dashboard-0.1.0/craft_dashboard/cli.py +267 -0
- craft_dashboard-0.1.0/craft_dashboard/collectors/AGENTS.md +48 -0
- craft_dashboard-0.1.0/craft_dashboard/collectors/__init__.py +48 -0
- craft_dashboard-0.1.0/craft_dashboard/collectors/dependencies.py +321 -0
- craft_dashboard-0.1.0/craft_dashboard/collectors/forum.py +532 -0
- craft_dashboard-0.1.0/craft_dashboard/collectors/github.py +916 -0
- craft_dashboard-0.1.0/craft_dashboard/collectors/github_adapters.py +150 -0
- craft_dashboard-0.1.0/craft_dashboard/collectors/github_graphql.py +768 -0
- craft_dashboard-0.1.0/craft_dashboard/collectors/github_issue_store.py +207 -0
- craft_dashboard-0.1.0/craft_dashboard/collectors/github_mapping.py +145 -0
- craft_dashboard-0.1.0/craft_dashboard/collectors/github_release_store.py +70 -0
- craft_dashboard-0.1.0/craft_dashboard/collectors/github_releases.py +67 -0
- craft_dashboard-0.1.0/craft_dashboard/collectors/github_rest.py +155 -0
- craft_dashboard-0.1.0/craft_dashboard/collectors/launchpad.py +343 -0
- craft_dashboard-0.1.0/craft_dashboard/collectors/scheduler.py +282 -0
- craft_dashboard-0.1.0/craft_dashboard/collectors/snapshots.py +529 -0
- craft_dashboard-0.1.0/craft_dashboard/commit_scanner/__init__.py +5 -0
- craft_dashboard-0.1.0/craft_dashboard/commit_scanner/parsing.py +112 -0
- craft_dashboard-0.1.0/craft_dashboard/commit_scanner/scanner.py +483 -0
- craft_dashboard-0.1.0/craft_dashboard/config.py +150 -0
- craft_dashboard-0.1.0/craft_dashboard/database.py +52 -0
- craft_dashboard-0.1.0/craft_dashboard/dependencies.py +33 -0
- craft_dashboard-0.1.0/craft_dashboard/enums.py +25 -0
- craft_dashboard-0.1.0/craft_dashboard/git_mirrors/__init__.py +6 -0
- craft_dashboard-0.1.0/craft_dashboard/git_mirrors/exceptions.py +21 -0
- craft_dashboard-0.1.0/craft_dashboard/git_mirrors/layout_cache.py +65 -0
- craft_dashboard-0.1.0/craft_dashboard/git_mirrors/paths.py +106 -0
- craft_dashboard-0.1.0/craft_dashboard/git_mirrors/reader.py +482 -0
- craft_dashboard-0.1.0/craft_dashboard/git_mirrors/sync.py +248 -0
- craft_dashboard-0.1.0/craft_dashboard/http_retry.py +125 -0
- craft_dashboard-0.1.0/craft_dashboard/llm/AGENTS.md +29 -0
- craft_dashboard-0.1.0/craft_dashboard/llm/__init__.py +1 -0
- craft_dashboard-0.1.0/craft_dashboard/llm/acp_client.py +364 -0
- craft_dashboard-0.1.0/craft_dashboard/llm/baseline.py +120 -0
- craft_dashboard-0.1.0/craft_dashboard/llm/client.py +651 -0
- craft_dashboard-0.1.0/craft_dashboard/llm/content_hash.py +93 -0
- craft_dashboard-0.1.0/craft_dashboard/llm/duplicate_detector.py +193 -0
- craft_dashboard-0.1.0/craft_dashboard/llm/embeddings.py +226 -0
- craft_dashboard-0.1.0/craft_dashboard/llm/evaluation_queue.py +207 -0
- craft_dashboard-0.1.0/craft_dashboard/llm/evaluator.py +1095 -0
- craft_dashboard-0.1.0/craft_dashboard/llm/exceptions.py +25 -0
- craft_dashboard-0.1.0/craft_dashboard/llm/preflight.py +56 -0
- craft_dashboard-0.1.0/craft_dashboard/llm/prompts.py +569 -0
- craft_dashboard-0.1.0/craft_dashboard/llm/tool_dispatch.py +306 -0
- craft_dashboard-0.1.0/craft_dashboard/llm/tools.py +210 -0
- craft_dashboard-0.1.0/craft_dashboard/models/__init__.py +46 -0
- craft_dashboard-0.1.0/craft_dashboard/models/base.py +26 -0
- craft_dashboard-0.1.0/craft_dashboard/models/collection_run.py +35 -0
- craft_dashboard-0.1.0/craft_dashboard/models/collection_watermark.py +24 -0
- craft_dashboard-0.1.0/craft_dashboard/models/commit_scan_evidence_path.py +42 -0
- craft_dashboard-0.1.0/craft_dashboard/models/commit_scan_run.py +57 -0
- craft_dashboard-0.1.0/craft_dashboard/models/dependency.py +55 -0
- craft_dashboard-0.1.0/craft_dashboard/models/eval_queue_snapshot.py +29 -0
- craft_dashboard-0.1.0/craft_dashboard/models/eval_token.py +54 -0
- craft_dashboard-0.1.0/craft_dashboard/models/evaluation_transcript.py +61 -0
- craft_dashboard-0.1.0/craft_dashboard/models/forum.py +95 -0
- craft_dashboard-0.1.0/craft_dashboard/models/issue.py +123 -0
- craft_dashboard-0.1.0/craft_dashboard/models/issue_activity.py +48 -0
- craft_dashboard-0.1.0/craft_dashboard/models/issue_link.py +107 -0
- craft_dashboard-0.1.0/craft_dashboard/models/llm_evaluation.py +125 -0
- craft_dashboard-0.1.0/craft_dashboard/models/project.py +42 -0
- craft_dashboard-0.1.0/craft_dashboard/models/refresh_schedule.py +68 -0
- craft_dashboard-0.1.0/craft_dashboard/models/release.py +44 -0
- craft_dashboard-0.1.0/craft_dashboard/models/snapshot.py +79 -0
- craft_dashboard-0.1.0/craft_dashboard/models/views.py +231 -0
- craft_dashboard-0.1.0/craft_dashboard/rate_limit.py +57 -0
- craft_dashboard-0.1.0/craft_dashboard/repositories/AGENTS.md +29 -0
- craft_dashboard-0.1.0/craft_dashboard/repositories/__init__.py +7 -0
- craft_dashboard-0.1.0/craft_dashboard/repositories/eval_token_repository.py +190 -0
- craft_dashboard-0.1.0/craft_dashboard/repositories/issue_filters.py +68 -0
- craft_dashboard-0.1.0/craft_dashboard/repositories/issue_link_repository.py +190 -0
- craft_dashboard-0.1.0/craft_dashboard/repositories/issue_repository.py +748 -0
- craft_dashboard-0.1.0/craft_dashboard/routes/AGENTS.md +27 -0
- craft_dashboard-0.1.0/craft_dashboard/routes/__init__.py +1 -0
- craft_dashboard-0.1.0/craft_dashboard/routes/admin.py +508 -0
- craft_dashboard-0.1.0/craft_dashboard/routes/dashboard.py +53 -0
- craft_dashboard-0.1.0/craft_dashboard/routes/engagement.py +110 -0
- craft_dashboard-0.1.0/craft_dashboard/routes/eval_api.py +1151 -0
- craft_dashboard-0.1.0/craft_dashboard/routes/issues.py +599 -0
- craft_dashboard-0.1.0/craft_dashboard/routes/stats.py +705 -0
- craft_dashboard-0.1.0/craft_dashboard/services/AGENTS.md +36 -0
- craft_dashboard-0.1.0/craft_dashboard/services/__init__.py +23 -0
- craft_dashboard-0.1.0/craft_dashboard/services/admin_service.py +949 -0
- craft_dashboard-0.1.0/craft_dashboard/services/dashboard/__init__.py +13 -0
- craft_dashboard-0.1.0/craft_dashboard/services/dashboard/badges.py +42 -0
- craft_dashboard-0.1.0/craft_dashboard/services/dashboard/common.py +41 -0
- craft_dashboard-0.1.0/craft_dashboard/services/dashboard/health.py +147 -0
- craft_dashboard-0.1.0/craft_dashboard/services/dashboard/projects.py +43 -0
- craft_dashboard-0.1.0/craft_dashboard/services/dashboard/releases.py +143 -0
- craft_dashboard-0.1.0/craft_dashboard/services/dashboard/spotlights.py +175 -0
- craft_dashboard-0.1.0/craft_dashboard/services/dashboard/throughput.py +74 -0
- craft_dashboard-0.1.0/craft_dashboard/services/dashboard/types.py +210 -0
- craft_dashboard-0.1.0/craft_dashboard/services/dashboard/untriaged.py +85 -0
- craft_dashboard-0.1.0/craft_dashboard/services/dashboard/velocity.py +277 -0
- craft_dashboard-0.1.0/craft_dashboard/services/dashboard/view_models.py +356 -0
- craft_dashboard-0.1.0/craft_dashboard/services/dashboard/volume.py +119 -0
- craft_dashboard-0.1.0/craft_dashboard/services/dashboard_service.py +484 -0
- craft_dashboard-0.1.0/craft_dashboard/services/eval_activity.py +105 -0
- craft_dashboard-0.1.0/craft_dashboard/services/eval_auth_service.py +150 -0
- craft_dashboard-0.1.0/craft_dashboard/services/evaluation_gc.py +131 -0
- craft_dashboard-0.1.0/craft_dashboard/services/transcript_gc.py +47 -0
- craft_dashboard-0.1.0/craft_dashboard/settings.py +142 -0
- craft_dashboard-0.1.0/craft_dashboard/static/css/custom.css +1424 -0
- craft_dashboard-0.1.0/craft_dashboard/static/favicon.ico +0 -0
- craft_dashboard-0.1.0/craft_dashboard/static/js/chart-a11y.js +80 -0
- craft_dashboard-0.1.0/craft_dashboard/static/js/chart-common.js +347 -0
- craft_dashboard-0.1.0/craft_dashboard/static/js/deps.js +133 -0
- craft_dashboard-0.1.0/craft_dashboard/static/js/engagement.js +234 -0
- craft_dashboard-0.1.0/craft_dashboard/static/js/issue-columns.js +90 -0
- craft_dashboard-0.1.0/craft_dashboard/static/js/issues-filters.js +153 -0
- craft_dashboard-0.1.0/craft_dashboard/static/js/multiselect.js +272 -0
- craft_dashboard-0.1.0/craft_dashboard/static/js/table-interact.js +90 -0
- craft_dashboard-0.1.0/craft_dashboard/static/js/table-paginate.js +92 -0
- craft_dashboard-0.1.0/craft_dashboard/static/js/table-sort.js +97 -0
- craft_dashboard-0.1.0/craft_dashboard/static/js/trends.js +543 -0
- craft_dashboard-0.1.0/craft_dashboard/static/vendor/README.md +15 -0
- craft_dashboard-0.1.0/craft_dashboard/static/vendor/chart.umd.min.js +20 -0
- craft_dashboard-0.1.0/craft_dashboard/static/vendor/marked.min.js +69 -0
- craft_dashboard-0.1.0/craft_dashboard/static/vendor/purify.min.js +3 -0
- craft_dashboard-0.1.0/craft_dashboard/templates/admin/_recent_activity_rows.html +51 -0
- craft_dashboard-0.1.0/craft_dashboard/templates/admin/_recent_evaluations_rows.html +51 -0
- craft_dashboard-0.1.0/craft_dashboard/templates/admin/collection_run_issues.html +42 -0
- craft_dashboard-0.1.0/craft_dashboard/templates/admin/evaluations.html +365 -0
- craft_dashboard-0.1.0/craft_dashboard/templates/admin/overview.html +306 -0
- craft_dashboard-0.1.0/craft_dashboard/templates/admin/partials/tabs.html +12 -0
- craft_dashboard-0.1.0/craft_dashboard/templates/admin/schedule.html +99 -0
- craft_dashboard-0.1.0/craft_dashboard/templates/base.html +343 -0
- craft_dashboard-0.1.0/craft_dashboard/templates/components/issue_cell.html +25 -0
- craft_dashboard-0.1.0/craft_dashboard/templates/components/pagination.html +14 -0
- craft_dashboard-0.1.0/craft_dashboard/templates/components/score_badge.html +15 -0
- craft_dashboard-0.1.0/craft_dashboard/templates/dashboard/index.html +499 -0
- craft_dashboard-0.1.0/craft_dashboard/templates/engagement/forums.html +99 -0
- craft_dashboard-0.1.0/craft_dashboard/templates/errors/404.html +9 -0
- craft_dashboard-0.1.0/craft_dashboard/templates/errors/500.html +9 -0
- craft_dashboard-0.1.0/craft_dashboard/templates/issues/detail.html +228 -0
- craft_dashboard-0.1.0/craft_dashboard/templates/issues/list.html +263 -0
- craft_dashboard-0.1.0/craft_dashboard/templates/issues/partials/issue_table.html +125 -0
- craft_dashboard-0.1.0/craft_dashboard/templates/stats/cadence.html +142 -0
- craft_dashboard-0.1.0/craft_dashboard/templates/stats/dependencies.html +11 -0
- craft_dashboard-0.1.0/craft_dashboard/templates/stats/partials/tabs.html +20 -0
- craft_dashboard-0.1.0/craft_dashboard/templates/stats/partials/trend_chart.html +22 -0
- craft_dashboard-0.1.0/craft_dashboard/templates/stats/releases.html +304 -0
- craft_dashboard-0.1.0/craft_dashboard/templates/stats/trends.html +238 -0
- craft_dashboard-0.1.0/craft_dashboard/templates/stats/triage.html +251 -0
- craft_dashboard-0.1.0/craft_dashboard/utils/__init__.py +23 -0
- craft_dashboard-0.1.0/craft_dashboard/utils/formatting.py +28 -0
- craft_dashboard-0.1.0/craft_dashboard/utils/retention.py +36 -0
- craft_dashboard-0.1.0/craft_dashboard.egg-info/PKG-INFO +71 -0
- craft_dashboard-0.1.0/craft_dashboard.egg-info/SOURCES.txt +426 -0
- craft_dashboard-0.1.0/craft_dashboard.egg-info/dependency_links.txt +1 -0
- craft_dashboard-0.1.0/craft_dashboard.egg-info/entry_points.txt +3 -0
- craft_dashboard-0.1.0/craft_dashboard.egg-info/requires.txt +19 -0
- craft_dashboard-0.1.0/craft_dashboard.egg-info/scm_file_list.json +421 -0
- craft_dashboard-0.1.0/craft_dashboard.egg-info/scm_version.json +8 -0
- craft_dashboard-0.1.0/craft_dashboard.egg-info/top_level.txt +2 -0
- craft_dashboard-0.1.0/docker-compose.yml +33 -0
- craft_dashboard-0.1.0/docker-entrypoint.sh +24 -0
- craft_dashboard-0.1.0/docs/architecture.md +78 -0
- craft_dashboard-0.1.0/docs/development.md +99 -0
- craft_dashboard-0.1.0/docs/operations.md +355 -0
- craft_dashboard-0.1.0/docs/reference.md +232 -0
- craft_dashboard-0.1.0/pyproject.toml +234 -0
- craft_dashboard-0.1.0/scripts/__init__.py +1 -0
- craft_dashboard-0.1.0/scripts/audit_launchpad_employees.py +424 -0
- craft_dashboard-0.1.0/scripts/backfill_closing_references.py +220 -0
- craft_dashboard-0.1.0/scripts/backfill_content_hash.py +171 -0
- craft_dashboard-0.1.0/scripts/backfill_embeddings.py +221 -0
- craft_dashboard-0.1.0/scripts/backfill_eval_queue_depth.py +219 -0
- craft_dashboard-0.1.0/scripts/backfill_launchpad_maintainers.py +104 -0
- craft_dashboard-0.1.0/scripts/backfill_opinion_status.py +149 -0
- craft_dashboard-0.1.0/scripts/backfill_search_embeddings.py +238 -0
- craft_dashboard-0.1.0/scripts/backfill_snapshots.py +471 -0
- craft_dashboard-0.1.0/scripts/benchmark_llm.py +112 -0
- craft_dashboard-0.1.0/scripts/check_docs.py +122 -0
- craft_dashboard-0.1.0/scripts/collect/AGENTS.md +35 -0
- craft_dashboard-0.1.0/scripts/collect/__init__.py +1 -0
- craft_dashboard-0.1.0/scripts/collect/github_pass.py +582 -0
- craft_dashboard-0.1.0/scripts/collect/launchpad_pass.py +123 -0
- craft_dashboard-0.1.0/scripts/collect/projects.py +68 -0
- craft_dashboard-0.1.0/scripts/collect/reporting.py +62 -0
- craft_dashboard-0.1.0/scripts/collect/retry.py +103 -0
- craft_dashboard-0.1.0/scripts/collect/runs.py +144 -0
- craft_dashboard-0.1.0/scripts/collect_data.py +387 -0
- craft_dashboard-0.1.0/scripts/collect_forum_data.py +272 -0
- craft_dashboard-0.1.0/scripts/dev_stack.py +135 -0
- craft_dashboard-0.1.0/scripts/eval_timing.py +113 -0
- craft_dashboard-0.1.0/scripts/gc.py +104 -0
- craft_dashboard-0.1.0/scripts/gc_transcripts.py +20 -0
- craft_dashboard-0.1.0/scripts/llm/AGENTS.md +38 -0
- craft_dashboard-0.1.0/scripts/llm/__init__.py +1 -0
- craft_dashboard-0.1.0/scripts/llm/canary.py +214 -0
- craft_dashboard-0.1.0/scripts/llm/cli.py +806 -0
- craft_dashboard-0.1.0/scripts/llm/console.py +343 -0
- craft_dashboard-0.1.0/scripts/llm/eval_failures.py +92 -0
- craft_dashboard-0.1.0/scripts/llm/eval_http.py +253 -0
- craft_dashboard-0.1.0/scripts/llm/eval_payload.py +149 -0
- craft_dashboard-0.1.0/scripts/llm/eval_startup.py +88 -0
- craft_dashboard-0.1.0/scripts/llm/eval_worker.py +1179 -0
- craft_dashboard-0.1.0/scripts/llm/ratelimit.py +107 -0
- craft_dashboard-0.1.0/scripts/llm/validation.py +145 -0
- craft_dashboard-0.1.0/scripts/llm/worker_runtime.py +201 -0
- craft_dashboard-0.1.0/scripts/llm/worker_version.py +20 -0
- craft_dashboard-0.1.0/scripts/lp_bug_report.py +56 -0
- craft_dashboard-0.1.0/scripts/manage_eval_tokens.py +195 -0
- craft_dashboard-0.1.0/scripts/run_llm.py +12 -0
- craft_dashboard-0.1.0/setup.cfg +4 -0
- craft_dashboard-0.1.0/tests/__init__.py +0 -0
- craft_dashboard-0.1.0/tests/conftest.py +95 -0
- craft_dashboard-0.1.0/tests/end_to_end/__init__.py +1 -0
- craft_dashboard-0.1.0/tests/end_to_end/conftest.py +153 -0
- craft_dashboard-0.1.0/tests/end_to_end/helpers.py +155 -0
- craft_dashboard-0.1.0/tests/end_to_end/seed_data.py +538 -0
- craft_dashboard-0.1.0/tests/end_to_end/test_engagement.py +380 -0
- craft_dashboard-0.1.0/tests/end_to_end/test_issue_detail.py +62 -0
- craft_dashboard-0.1.0/tests/end_to_end/test_multiselect_a11y.py +86 -0
- craft_dashboard-0.1.0/tests/end_to_end/test_navigation.py +151 -0
- craft_dashboard-0.1.0/tests/end_to_end/test_releases.py +65 -0
- craft_dashboard-0.1.0/tests/end_to_end/test_trends.py +475 -0
- craft_dashboard-0.1.0/tests/end_to_end/test_triage.py +375 -0
- craft_dashboard-0.1.0/tests/factories.py +156 -0
- craft_dashboard-0.1.0/tests/helpers/__init__.py +1 -0
- craft_dashboard-0.1.0/tests/helpers/html.py +148 -0
- craft_dashboard-0.1.0/tests/integration/__init__.py +0 -0
- craft_dashboard-0.1.0/tests/integration/conftest.py +90 -0
- craft_dashboard-0.1.0/tests/integration/test_admin_api.py +823 -0
- craft_dashboard-0.1.0/tests/integration/test_bugfix_regressions.py +155 -0
- craft_dashboard-0.1.0/tests/integration/test_dashboard_api.py +613 -0
- craft_dashboard-0.1.0/tests/integration/test_eval_api.py +2794 -0
- craft_dashboard-0.1.0/tests/integration/test_evaluation_gc.py +137 -0
- craft_dashboard-0.1.0/tests/integration/test_releases_api.py +299 -0
- craft_dashboard-0.1.0/tests/integration/test_retention.py +48 -0
- craft_dashboard-0.1.0/tests/integration/test_setuptools.py +71 -0
- craft_dashboard-0.1.0/tests/integration/test_smoketest.py +10 -0
- craft_dashboard-0.1.0/tests/integration/test_snapshot_computations.py +458 -0
- craft_dashboard-0.1.0/tests/integration/test_snapshot_generation.py +320 -0
- craft_dashboard-0.1.0/tests/integration/test_stats_aggregation_characterization.py +235 -0
- craft_dashboard-0.1.0/tests/integration/test_trends_api.py +424 -0
- craft_dashboard-0.1.0/tests/integration/test_version.py +70 -0
- craft_dashboard-0.1.0/tests/unit/__init__.py +0 -0
- craft_dashboard-0.1.0/tests/unit/collectors/__init__.py +0 -0
- craft_dashboard-0.1.0/tests/unit/collectors/test_dependencies.py +446 -0
- craft_dashboard-0.1.0/tests/unit/collectors/test_exports.py +49 -0
- craft_dashboard-0.1.0/tests/unit/collectors/test_forum.py +684 -0
- craft_dashboard-0.1.0/tests/unit/collectors/test_github.py +1672 -0
- craft_dashboard-0.1.0/tests/unit/collectors/test_github_collect.py +208 -0
- craft_dashboard-0.1.0/tests/unit/collectors/test_github_collect_characterization.py +464 -0
- craft_dashboard-0.1.0/tests/unit/collectors/test_github_collector_releases.py +31 -0
- craft_dashboard-0.1.0/tests/unit/collectors/test_github_graphql.py +981 -0
- craft_dashboard-0.1.0/tests/unit/collectors/test_github_graphql_characterization.py +300 -0
- craft_dashboard-0.1.0/tests/unit/collectors/test_github_rate_limit.py +223 -0
- craft_dashboard-0.1.0/tests/unit/collectors/test_launchpad.py +830 -0
- craft_dashboard-0.1.0/tests/unit/collectors/test_scheduler.py +274 -0
- craft_dashboard-0.1.0/tests/unit/collectors/test_snapshots.py +942 -0
- craft_dashboard-0.1.0/tests/unit/commit_scanner/__init__.py +0 -0
- craft_dashboard-0.1.0/tests/unit/commit_scanner/conftest.py +46 -0
- craft_dashboard-0.1.0/tests/unit/commit_scanner/test_parsing.py +88 -0
- craft_dashboard-0.1.0/tests/unit/commit_scanner/test_scanner.py +933 -0
- craft_dashboard-0.1.0/tests/unit/git_mirrors/__init__.py +0 -0
- craft_dashboard-0.1.0/tests/unit/git_mirrors/conftest.py +95 -0
- craft_dashboard-0.1.0/tests/unit/git_mirrors/test_layout_cache.py +68 -0
- craft_dashboard-0.1.0/tests/unit/git_mirrors/test_paths.py +106 -0
- craft_dashboard-0.1.0/tests/unit/git_mirrors/test_reader.py +447 -0
- craft_dashboard-0.1.0/tests/unit/git_mirrors/test_sync.py +216 -0
- craft_dashboard-0.1.0/tests/unit/llm/__init__.py +0 -0
- craft_dashboard-0.1.0/tests/unit/llm/test_acp_client.py +129 -0
- craft_dashboard-0.1.0/tests/unit/llm/test_baseline.py +193 -0
- craft_dashboard-0.1.0/tests/unit/llm/test_client.py +485 -0
- craft_dashboard-0.1.0/tests/unit/llm/test_client_protocol.py +55 -0
- craft_dashboard-0.1.0/tests/unit/llm/test_client_tool_calling.py +194 -0
- craft_dashboard-0.1.0/tests/unit/llm/test_closed_evaluation.py +159 -0
- craft_dashboard-0.1.0/tests/unit/llm/test_duplicate_detector.py +205 -0
- craft_dashboard-0.1.0/tests/unit/llm/test_duplicate_prompts.py +65 -0
- craft_dashboard-0.1.0/tests/unit/llm/test_embeddings.py +184 -0
- craft_dashboard-0.1.0/tests/unit/llm/test_evaluation_queue.py +372 -0
- craft_dashboard-0.1.0/tests/unit/llm/test_evaluation_queue_characterization.py +371 -0
- craft_dashboard-0.1.0/tests/unit/llm/test_evaluator.py +1534 -0
- craft_dashboard-0.1.0/tests/unit/llm/test_exceptions.py +27 -0
- craft_dashboard-0.1.0/tests/unit/llm/test_preflight.py +205 -0
- craft_dashboard-0.1.0/tests/unit/llm/test_prompts.py +476 -0
- craft_dashboard-0.1.0/tests/unit/llm/test_tool_dispatch.py +408 -0
- craft_dashboard-0.1.0/tests/unit/llm/test_tools.py +53 -0
- craft_dashboard-0.1.0/tests/unit/models/__init__.py +0 -0
- craft_dashboard-0.1.0/tests/unit/models/test_base.py +19 -0
- craft_dashboard-0.1.0/tests/unit/models/test_commit_scan_evidence_path.py +31 -0
- craft_dashboard-0.1.0/tests/unit/models/test_commit_scan_run.py +62 -0
- craft_dashboard-0.1.0/tests/unit/models/test_dependency.py +41 -0
- craft_dashboard-0.1.0/tests/unit/models/test_evaluation_transcript.py +62 -0
- craft_dashboard-0.1.0/tests/unit/models/test_issue.py +118 -0
- craft_dashboard-0.1.0/tests/unit/models/test_issue_activity.py +74 -0
- craft_dashboard-0.1.0/tests/unit/models/test_issue_link.py +109 -0
- craft_dashboard-0.1.0/tests/unit/models/test_llm_evaluation.py +104 -0
- craft_dashboard-0.1.0/tests/unit/models/test_project.py +36 -0
- craft_dashboard-0.1.0/tests/unit/models/test_refresh_schedule.py +41 -0
- craft_dashboard-0.1.0/tests/unit/models/test_release.py +96 -0
- craft_dashboard-0.1.0/tests/unit/models/test_snapshot.py +57 -0
- craft_dashboard-0.1.0/tests/unit/repositories/__init__.py +1 -0
- craft_dashboard-0.1.0/tests/unit/repositories/test_eval_token_repository.py +129 -0
- craft_dashboard-0.1.0/tests/unit/repositories/test_issue_link_repository.py +439 -0
- craft_dashboard-0.1.0/tests/unit/repositories/test_issue_repository.py +1373 -0
- craft_dashboard-0.1.0/tests/unit/routes/__init__.py +0 -0
- craft_dashboard-0.1.0/tests/unit/routes/test_admin.py +707 -0
- craft_dashboard-0.1.0/tests/unit/routes/test_admin_status.py +81 -0
- craft_dashboard-0.1.0/tests/unit/routes/test_dashboard.py +301 -0
- craft_dashboard-0.1.0/tests/unit/routes/test_engagement.py +203 -0
- craft_dashboard-0.1.0/tests/unit/routes/test_eval_api.py +156 -0
- craft_dashboard-0.1.0/tests/unit/routes/test_issue_detail.py +659 -0
- craft_dashboard-0.1.0/tests/unit/routes/test_issues.py +708 -0
- craft_dashboard-0.1.0/tests/unit/routes/test_issues_export.py +139 -0
- craft_dashboard-0.1.0/tests/unit/routes/test_issues_shareable_urls.py +75 -0
- craft_dashboard-0.1.0/tests/unit/routes/test_stats.py +152 -0
- craft_dashboard-0.1.0/tests/unit/routes/test_stats_deps_releases.py +546 -0
- craft_dashboard-0.1.0/tests/unit/routes/test_stats_trends.py +953 -0
- craft_dashboard-0.1.0/tests/unit/scripts/__init__.py +0 -0
- craft_dashboard-0.1.0/tests/unit/scripts/test_backfill_embeddings.py +98 -0
- craft_dashboard-0.1.0/tests/unit/scripts/test_backfill_eval_queue_depth.py +90 -0
- craft_dashboard-0.1.0/tests/unit/scripts/test_backfill_launchpad_maintainers.py +140 -0
- craft_dashboard-0.1.0/tests/unit/scripts/test_backfill_search_embeddings.py +216 -0
- craft_dashboard-0.1.0/tests/unit/scripts/test_backfill_snapshots.py +215 -0
- craft_dashboard-0.1.0/tests/unit/scripts/test_canary.py +145 -0
- craft_dashboard-0.1.0/tests/unit/scripts/test_collect_data_health.py +554 -0
- craft_dashboard-0.1.0/tests/unit/scripts/test_collect_data_watermarks.py +401 -0
- craft_dashboard-0.1.0/tests/unit/scripts/test_eval_http.py +114 -0
- craft_dashboard-0.1.0/tests/unit/scripts/test_eval_timing.py +180 -0
- craft_dashboard-0.1.0/tests/unit/scripts/test_eval_worker.py +1041 -0
- craft_dashboard-0.1.0/tests/unit/scripts/test_eval_worker_characterization.py +466 -0
- craft_dashboard-0.1.0/tests/unit/scripts/test_forum_backfill.py +167 -0
- craft_dashboard-0.1.0/tests/unit/scripts/test_llm_cli.py +264 -0
- craft_dashboard-0.1.0/tests/unit/scripts/test_llm_console.py +184 -0
- craft_dashboard-0.1.0/tests/unit/scripts/test_llm_http_evaluate_cli.py +388 -0
- craft_dashboard-0.1.0/tests/unit/scripts/test_llm_ratelimit.py +118 -0
- craft_dashboard-0.1.0/tests/unit/scripts/test_llm_validation.py +245 -0
- craft_dashboard-0.1.0/tests/unit/scripts/test_manage_eval_tokens.py +103 -0
- craft_dashboard-0.1.0/tests/unit/services/__init__.py +1 -0
- craft_dashboard-0.1.0/tests/unit/services/test_admin_collection_health.py +154 -0
- craft_dashboard-0.1.0/tests/unit/services/test_admin_service.py +1690 -0
- craft_dashboard-0.1.0/tests/unit/services/test_admin_status.py +128 -0
- craft_dashboard-0.1.0/tests/unit/services/test_dashboard_metrics_characterization.py +1609 -0
- craft_dashboard-0.1.0/tests/unit/services/test_dashboard_service.py +359 -0
- craft_dashboard-0.1.0/tests/unit/services/test_dashboard_view_models.py +530 -0
- craft_dashboard-0.1.0/tests/unit/services/test_eval_activity.py +61 -0
- craft_dashboard-0.1.0/tests/unit/services/test_eval_auth_service.py +153 -0
- craft_dashboard-0.1.0/tests/unit/services/test_stats_service_characterization.py +345 -0
- craft_dashboard-0.1.0/tests/unit/services/test_transcript_gc.py +113 -0
- craft_dashboard-0.1.0/tests/unit/test_app.py +249 -0
- craft_dashboard-0.1.0/tests/unit/test_auth.py +37 -0
- craft_dashboard-0.1.0/tests/unit/test_check_docs.py +61 -0
- craft_dashboard-0.1.0/tests/unit/test_cli.py +122 -0
- craft_dashboard-0.1.0/tests/unit/test_collect_data.py +718 -0
- craft_dashboard-0.1.0/tests/unit/test_config.py +188 -0
- craft_dashboard-0.1.0/tests/unit/test_config_validation.py +81 -0
- craft_dashboard-0.1.0/tests/unit/test_database.py +48 -0
- craft_dashboard-0.1.0/tests/unit/test_dependencies.py +42 -0
- craft_dashboard-0.1.0/tests/unit/test_factories.py +51 -0
- craft_dashboard-0.1.0/tests/unit/test_frontend_assets.py +46 -0
- craft_dashboard-0.1.0/tests/unit/test_http_retry.py +132 -0
- craft_dashboard-0.1.0/tests/unit/test_issue_age.py +18 -0
- craft_dashboard-0.1.0/tests/unit/test_rate_limit.py +38 -0
- craft_dashboard-0.1.0/tests/unit/test_seed_data.py +22 -0
- craft_dashboard-0.1.0/tests/unit/test_settings.py +184 -0
- craft_dashboard-0.1.0/tests/unit/test_stub.py +2 -0
- 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,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"]
|