stackvitals 0.1.0__py3-none-any.whl
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.
- mergescout/__init__.py +1 -0
- mergescout/archive/__init__.py +0 -0
- mergescout/archive/__main__.py +30 -0
- mergescout/archive/convert.py +83 -0
- mergescout/archive/events.py +55 -0
- mergescout/archive/manifest.py +45 -0
- mergescout/archive/stream.py +83 -0
- mergescout/bench/__init__.py +1 -0
- mergescout/bench/__main__.py +135 -0
- mergescout/bench/ci.py +257 -0
- mergescout/bench/deploys.py +115 -0
- mergescout/bench/matched.py +22 -0
- mergescout/bench/prior.py +42 -0
- mergescout/bench/report.py +230 -0
- mergescout/bench/shared.py +112 -0
- mergescout/bench/stars.py +57 -0
- mergescout/cli.py +89 -0
- mergescout/config.py +35 -0
- mergescout/crawl/__init__.py +0 -0
- mergescout/crawl/__main__.py +97 -0
- mergescout/crawl/chain.py +34 -0
- mergescout/crawl/fetch.py +146 -0
- mergescout/crawl/outcomes.py +69 -0
- mergescout/crawl/queries.py +250 -0
- mergescout/crawl/runner.py +176 -0
- mergescout/crawl/seed.py +77 -0
- mergescout/crawl/state.py +169 -0
- mergescout/crawl/writer.py +87 -0
- mergescout/discover/__init__.py +0 -0
- mergescout/discover/__main__.py +58 -0
- mergescout/discover/sweep.py +286 -0
- mergescout/github/__init__.py +0 -0
- mergescout/github/graphql.py +202 -0
- mergescout/github/identities.py +35 -0
- mergescout/github/releases.py +137 -0
- mergescout/labels.py +20 -0
- mergescout/mcp_server.py +228 -0
- mergescout/measure/__init__.py +0 -0
- mergescout/measure/__main__.py +75 -0
- mergescout/measure/api_cost.py +91 -0
- mergescout/measure/count_repos.py +30 -0
- mergescout/measure/jsonl.py +14 -0
- mergescout/measure/report.py +56 -0
- mergescout/measure/sample.py +37 -0
- mergescout/owners.py +22 -0
- mergescout/setup_check.py +64 -0
- mergescout/signals/__init__.py +0 -0
- mergescout/signals/__main__.py +96 -0
- mergescout/signals/bump_ledger.py +258 -0
- mergescout/signals/bumps.py +104 -0
- mergescout/signals/check.py +141 -0
- mergescout/signals/community_bench.py +149 -0
- mergescout/signals/delivery_bench.py +103 -0
- mergescout/signals/deps_map.py +261 -0
- mergescout/signals/deps_trends.py +117 -0
- mergescout/signals/evidence.py +94 -0
- mergescout/signals/exploits.py +43 -0
- mergescout/signals/flow_bench.py +258 -0
- mergescout/signals/identity.py +73 -0
- mergescout/signals/issues.py +76 -0
- mergescout/signals/labels.py +79 -0
- mergescout/signals/osv.py +232 -0
- mergescout/signals/owners_watch.py +80 -0
- mergescout/signals/repo_stats.py +96 -0
- mergescout/signals/rules.py +70 -0
- mergescout/signals/silver.py +33 -0
- mergescout/signals/top_packages.py +26 -0
- mergescout/signals/triage.py +71 -0
- mergescout/signals/triage_math.py +120 -0
- mergescout/signals/walls.py +91 -0
- mergescout/snapshot/__init__.py +0 -0
- mergescout/snapshot/__main__.py +215 -0
- mergescout/snapshot/build.py +147 -0
- mergescout/snapshot/publish.py +70 -0
- mergescout/snapshot/schema.py +34 -0
- mergescout/snapshot/score.py +30 -0
- mergescout/store/__init__.py +0 -0
- mergescout/store/__main__.py +46 -0
- mergescout/store/sync.py +148 -0
- mergescout/timeutil.py +11 -0
- mergescout/tool/__init__.py +0 -0
- mergescout/tool/action_pack.py +62 -0
- mergescout/tool/live.py +201 -0
- mergescout/tool/queries.py +293 -0
- mergescout/tool/refs.py +31 -0
- mergescout/tool/store.py +129 -0
- mergescout/tool/tracking.py +83 -0
- stackvitals/__init__.py +2 -0
- stackvitals/__main__.py +4 -0
- stackvitals/ci/__init__.py +1 -0
- stackvitals/ci/action.py +574 -0
- stackvitals/ci/analyze.py +577 -0
- stackvitals/ci/api.py +218 -0
- stackvitals/ci/automation.py +212 -0
- stackvitals/ci/bench.py +195 -0
- stackvitals/ci/burnin.py +102 -0
- stackvitals/ci/cli.py +570 -0
- stackvitals/ci/collect.py +239 -0
- stackvitals/ci/cost.py +107 -0
- stackvitals/ci/coverage.py +155 -0
- stackvitals/ci/feedback.py +699 -0
- stackvitals/ci/fingerprint.py +220 -0
- stackvitals/ci/gitlab.py +121 -0
- stackvitals/ci/gitlab_action.py +125 -0
- stackvitals/ci/impact.py +125 -0
- stackvitals/ci/investigate.py +59 -0
- stackvitals/ci/kinds.py +52 -0
- stackvitals/ci/monitors.py +105 -0
- stackvitals/ci/owners.py +116 -0
- stackvitals/ci/quarantine_runtime.py +90 -0
- stackvitals/ci/report.py +435 -0
- stackvitals/ci/retry.py +67 -0
- stackvitals/ci/selfheal.py +102 -0
- stackvitals/ci/shards.py +120 -0
- stackvitals/ci/share.py +59 -0
- stackvitals/ci/store.py +93 -0
- stackvitals/ci/testreports.py +351 -0
- stackvitals/ci/tickets.py +106 -0
- stackvitals/ci/track_record.json +11 -0
- stackvitals/ci/triage.py +130 -0
- stackvitals/ci/triggers.py +147 -0
- stackvitals/ci/upload.py +85 -0
- stackvitals/ci/validate.py +91 -0
- stackvitals/cli.py +111 -0
- stackvitals/codeowners.py +69 -0
- stackvitals/community/__init__.py +0 -0
- stackvitals/community/action.py +140 -0
- stackvitals/community/affiliation.py +51 -0
- stackvitals/community/analyze.py +507 -0
- stackvitals/community/build.py +56 -0
- stackvitals/community/chaoss.py +70 -0
- stackvitals/community/cli.py +79 -0
- stackvitals/community/collect.py +240 -0
- stackvitals/community/context.py +54 -0
- stackvitals/community/report.py +250 -0
- stackvitals/connectors/__init__.py +244 -0
- stackvitals/connectors/ai_spend.py +190 -0
- stackvitals/connectors/base.py +82 -0
- stackvitals/connectors/check.py +686 -0
- stackvitals/connectors/copilot.py +104 -0
- stackvitals/connectors/discord.py +103 -0
- stackvitals/connectors/discourse.py +117 -0
- stackvitals/connectors/incident_io.py +106 -0
- stackvitals/connectors/jira.py +210 -0
- stackvitals/connectors/linear.py +140 -0
- stackvitals/connectors/pagerduty.py +96 -0
- stackvitals/connectors/slack.py +110 -0
- stackvitals/connectors/sonar.py +77 -0
- stackvitals/connectors/store.py +120 -0
- stackvitals/connectors/tracker.py +108 -0
- stackvitals/connectors/writeback.py +105 -0
- stackvitals/contribute/__init__.py +1 -0
- stackvitals/contribute/brief.py +297 -0
- stackvitals/contribute/cli.py +64 -0
- stackvitals/core/__init__.py +1 -0
- stackvitals/core/actors.py +103 -0
- stackvitals/core/agent_ledger.py +120 -0
- stackvitals/core/agreements.py +95 -0
- stackvitals/core/ai_outcomes.py +276 -0
- stackvitals/core/alerts.py +224 -0
- stackvitals/core/appdata.py +112 -0
- stackvitals/core/bucket.py +190 -0
- stackvitals/core/bugs.py +43 -0
- stackvitals/core/calendar.py +34 -0
- stackvitals/core/capex.py +57 -0
- stackvitals/core/change_risk.py +181 -0
- stackvitals/core/changes.py +133 -0
- stackvitals/core/chat.py +143 -0
- stackvitals/core/config.py +373 -0
- stackvitals/core/dataflow.py +168 -0
- stackvitals/core/decisions.py +275 -0
- stackvitals/core/delivery.py +954 -0
- stackvitals/core/delivery_peers.py +98 -0
- stackvitals/core/delivery_report.py +429 -0
- stackvitals/core/deliverycli.py +147 -0
- stackvitals/core/devlake_dora.sql +485 -0
- stackvitals/core/digest.py +333 -0
- stackvitals/core/explaincli.py +107 -0
- stackvitals/core/explore.py +296 -0
- stackvitals/core/export.py +342 -0
- stackvitals/core/exportcli.py +117 -0
- stackvitals/core/findings.py +350 -0
- stackvitals/core/health.py +94 -0
- stackvitals/core/identity.py +82 -0
- stackvitals/core/insights.py +365 -0
- stackvitals/core/insightscli.py +43 -0
- stackvitals/core/installdoc.py +69 -0
- stackvitals/core/investment.py +187 -0
- stackvitals/core/joins.py +43 -0
- stackvitals/core/llmsdoc.py +40 -0
- stackvitals/core/merge_queue.py +70 -0
- stackvitals/core/metrics.py +109 -0
- stackvitals/core/model.py +285 -0
- stackvitals/core/projectcli.py +66 -0
- stackvitals/core/propose.py +86 -0
- stackvitals/core/pulse.py +85 -0
- stackvitals/core/recorded.py +145 -0
- stackvitals/core/releases.py +39 -0
- stackvitals/core/requests.py +528 -0
- stackvitals/core/resync.py +35 -0
- stackvitals/core/schema.py +205 -0
- stackvitals/core/services.py +203 -0
- stackvitals/core/settings.py +96 -0
- stackvitals/core/sqlcli.py +111 -0
- stackvitals/core/stats.py +222 -0
- stackvitals/core/store.py +125 -0
- stackvitals/core/summary.py +104 -0
- stackvitals/core/time.py +29 -0
- stackvitals/core/tomledit.py +149 -0
- stackvitals/core/uicli.py +138 -0
- stackvitals/core/webapp.py +79 -0
- stackvitals/core/what_changed.py +76 -0
- stackvitals/core/workspace.py +194 -0
- stackvitals/deps/__init__.py +1 -0
- stackvitals/deps/action.py +299 -0
- stackvitals/deps/actions_vulns.py +89 -0
- stackvitals/deps/cli.py +77 -0
- stackvitals/deps/dossier.py +341 -0
- stackvitals/deps/evidence.py +44 -0
- stackvitals/deps/fixplan.py +40 -0
- stackvitals/deps/guarddog.py +32 -0
- stackvitals/deps/hygiene.py +47 -0
- stackvitals/deps/imports.py +113 -0
- stackvitals/deps/lockfiles.py +198 -0
- stackvitals/deps/lookalike.py +80 -0
- stackvitals/deps/reach.py +59 -0
- stackvitals/deps/release.py +110 -0
- stackvitals/deps/runtimes.py +161 -0
- stackvitals/deps/supply.py +454 -0
- stackvitals/deps/vulns.py +588 -0
- stackvitals/editors/__init__.py +40 -0
- stackvitals/editors/vscode/extension.js +101 -0
- stackvitals/editors/vscode/marks.js +92 -0
- stackvitals/editors/vscode/package.json +26 -0
- stackvitals/flow/__init__.py +1 -0
- stackvitals/flow/action.py +178 -0
- stackvitals/flow/analyze.py +418 -0
- stackvitals/flow/automate.py +72 -0
- stackvitals/flow/build.py +46 -0
- stackvitals/flow/cli.py +93 -0
- stackvitals/flow/code_hosts.py +146 -0
- stackvitals/flow/collect.py +451 -0
- stackvitals/flow/gitlab_mr.py +75 -0
- stackvitals/flow/knowledge.py +202 -0
- stackvitals/flow/peers.py +90 -0
- stackvitals/flow/preflight.py +210 -0
- stackvitals/flow/report.py +253 -0
- stackvitals/flow/rules.py +135 -0
- stackvitals/flow/store.py +108 -0
- stackvitals/flow/survival.py +84 -0
- stackvitals/flow/triage.py +62 -0
- stackvitals/mcp_server.py +670 -0
- stackvitals/portal/__init__.py +0 -0
- stackvitals/portal/action.py +205 -0
- stackvitals/portal/batch.py +80 -0
- stackvitals/portal/campaigns.py +104 -0
- stackvitals/portal/catalog.py +104 -0
- stackvitals/portal/checks.py +63 -0
- stackvitals/portal/cli.py +172 -0
- stackvitals/portal/descriptor.py +105 -0
- stackvitals/portal/export.py +43 -0
- stackvitals/portal/github.py +48 -0
- stackvitals/portal/golden.py +95 -0
- stackvitals/portal/history.py +30 -0
- stackvitals/portal/inventory.py +264 -0
- stackvitals/portal/owners.py +78 -0
- stackvitals/portal/pages.py +153 -0
- stackvitals/portal/rollup.py +32 -0
- stackvitals/portal/scorecard.py +366 -0
- stackvitals/security/__init__.py +2 -0
- stackvitals/security/probes.py +154 -0
- stackvitals/security/repo_checks.py +132 -0
- stackvitals/security/workflows.py +111 -0
- stackvitals/shell.py +107 -0
- stackvitals/site.py +51 -0
- stackvitals/web/app/LICENSES.md +428 -0
- stackvitals/web/app/boot.js +1 -0
- stackvitals/web/app/chunks/AddRepo-KRPZXWCY.js +1 -0
- stackvitals/web/app/chunks/SetupRunning-XWFQAKRZ.js +1 -0
- stackvitals/web/app/chunks/accuracy-data-OQTDXI7Y.js +1 -0
- stackvitals/web/app/chunks/agents-data-BAL6QAOF.js +11 -0
- stackvitals/web/app/chunks/chunk-24LFKFZ6.js +1 -0
- stackvitals/web/app/chunks/chunk-3G4SQNUC.js +1 -0
- stackvitals/web/app/chunks/chunk-3IXWEOIJ.js +154 -0
- stackvitals/web/app/chunks/chunk-3ROQFHPV.js +1 -0
- stackvitals/web/app/chunks/chunk-45PGAQRO.js +8 -0
- stackvitals/web/app/chunks/chunk-4H53OYLG.js +1 -0
- stackvitals/web/app/chunks/chunk-4LUI7O5P.js +1 -0
- stackvitals/web/app/chunks/chunk-4SQPQ5TB.js +1 -0
- stackvitals/web/app/chunks/chunk-4WKQTWUC.js +2 -0
- stackvitals/web/app/chunks/chunk-576YHDEK.js +8 -0
- stackvitals/web/app/chunks/chunk-6BDBXA6V.js +1 -0
- stackvitals/web/app/chunks/chunk-6RLVD2DT.js +1 -0
- stackvitals/web/app/chunks/chunk-763NH7PP.js +1 -0
- stackvitals/web/app/chunks/chunk-76WAVKUG.js +1 -0
- stackvitals/web/app/chunks/chunk-7II2BD5F.js +1 -0
- stackvitals/web/app/chunks/chunk-7TJCBOAY.js +1 -0
- stackvitals/web/app/chunks/chunk-ASYNLVOP.js +1 -0
- stackvitals/web/app/chunks/chunk-CTKDYZMG.js +1 -0
- stackvitals/web/app/chunks/chunk-CVB26NMC.js +1 -0
- stackvitals/web/app/chunks/chunk-G7NGB5UX.js +1 -0
- stackvitals/web/app/chunks/chunk-GPVLJRZD.js +1 -0
- stackvitals/web/app/chunks/chunk-GQYFN4PE.js +75 -0
- stackvitals/web/app/chunks/chunk-GT4EAKAO.js +2 -0
- stackvitals/web/app/chunks/chunk-IYMBFPCV.js +1 -0
- stackvitals/web/app/chunks/chunk-LAAGCPU3.js +1 -0
- stackvitals/web/app/chunks/chunk-MAPYGK3P.js +1 -0
- stackvitals/web/app/chunks/chunk-P5TXDD45.js +1 -0
- stackvitals/web/app/chunks/chunk-PABICGBL.js +1 -0
- stackvitals/web/app/chunks/chunk-RPXHAG6F.js +1 -0
- stackvitals/web/app/chunks/chunk-RQZPSJ2Y.js +1 -0
- stackvitals/web/app/chunks/chunk-S2ZBMEVA.js +1 -0
- stackvitals/web/app/chunks/chunk-S654BBEP.js +6 -0
- stackvitals/web/app/chunks/chunk-T7QVTNXF.js +1 -0
- stackvitals/web/app/chunks/chunk-THFUOCPC.js +273 -0
- stackvitals/web/app/chunks/chunk-TO4VVRZ7.js +1 -0
- stackvitals/web/app/chunks/chunk-VQ5YXO54.js +1 -0
- stackvitals/web/app/chunks/chunk-VWKSMFWJ.js +1 -0
- stackvitals/web/app/chunks/chunk-Y6LUXDM6.js +1 -0
- stackvitals/web/app/chunks/chunk-YTANGYYH.js +1 -0
- stackvitals/web/app/chunks/connect-KONYWYTT.js +1 -0
- stackvitals/web/app/chunks/connections-data-2DYS4UVW.js +32 -0
- stackvitals/web/app/chunks/logos-N5IINUAM.js +1 -0
- stackvitals/web/app/chunks/more-KMJMJQD3.js +10 -0
- stackvitals/web/app/chunks/more-PC6FVS3P.js +1 -0
- stackvitals/web/app/chunks/more-RCIVCUDE.js +2 -0
- stackvitals/web/app/chunks/more-ZKKRY6NO.css +1 -0
- stackvitals/web/app/chunks/sealbox-35YL4EUH.js +3 -0
- stackvitals/web/app/chunks/session-DYYTOE2K.js +1 -0
- stackvitals/web/app/chunks/settingsApply-2HRJEZYM.js +1 -0
- stackvitals/web/app/chunks/settingsReview-GX2FZQ4M.js +3 -0
- stackvitals/web/app/chunks/uPlot.esm-OIWT3AHJ.js +3 -0
- stackvitals/web/app/demo/ci/impact.json +1 -0
- stackvitals/web/app/demo/ci/quarantine.json +1 -0
- stackvitals/web/app/demo/ci/tickets.json +1 -0
- stackvitals/web/app/demo/mobile/alerts.json +1 -0
- stackvitals/web/app/demo/mobile/app.json +1 -0
- stackvitals/web/app/demo/mobile/community.json +1 -0
- stackvitals/web/app/demo/mobile/connectors.json +1 -0
- stackvitals/web/app/demo/mobile/data.json +1 -0
- stackvitals/web/app/demo/mobile/decisions.json +1 -0
- stackvitals/web/app/demo/mobile/delivery.json +1 -0
- stackvitals/web/app/demo/mobile/deps.json +1 -0
- stackvitals/web/app/demo/mobile/flow.json +1 -0
- stackvitals/web/app/demo/mobile/health.json +1 -0
- stackvitals/web/app/demo/mobile/insights.json +1 -0
- stackvitals/web/app/demo/mobile/pulse.json +1 -0
- stackvitals/web/app/demo/mobile/security.json +1 -0
- stackvitals/web/app/demo/mobile/summary/ci_jobs.jsonl +5 -0
- stackvitals/web/app/demo/mobile/summary/devlake_project_pr_metrics.jsonl +14 -0
- stackvitals/web/app/demo/mobile/summary/devlake_pull_requests.jsonl +14 -0
- stackvitals/web/app/demo/mobile/summary/manifest.json +1 -0
- stackvitals/web/app/demo/mobile/summary/prs.jsonl +19 -0
- stackvitals/web/app/demo/mobile/summary/tests.jsonl +1 -0
- stackvitals/web/app/demo/mobile/supply.json +1 -0
- stackvitals/web/app/demo/mobile/vulns.json +1 -0
- stackvitals/web/app/demo/payments-api/alerts.json +1 -0
- stackvitals/web/app/demo/payments-api/app.json +1 -0
- stackvitals/web/app/demo/payments-api/community.json +1 -0
- stackvitals/web/app/demo/payments-api/connectors.json +1 -0
- stackvitals/web/app/demo/payments-api/data.json +1 -0
- stackvitals/web/app/demo/payments-api/decisions.json +1 -0
- stackvitals/web/app/demo/payments-api/delivery.json +1 -0
- stackvitals/web/app/demo/payments-api/deps.json +1 -0
- stackvitals/web/app/demo/payments-api/flow.json +1 -0
- stackvitals/web/app/demo/payments-api/health.json +1 -0
- stackvitals/web/app/demo/payments-api/insights.json +1 -0
- stackvitals/web/app/demo/payments-api/pulse.json +1 -0
- stackvitals/web/app/demo/payments-api/security.json +1 -0
- stackvitals/web/app/demo/payments-api/summary/ci_jobs.jsonl +5 -0
- stackvitals/web/app/demo/payments-api/summary/devlake_project_pr_metrics.jsonl +14 -0
- stackvitals/web/app/demo/payments-api/summary/devlake_pull_requests.jsonl +14 -0
- stackvitals/web/app/demo/payments-api/summary/manifest.json +1 -0
- stackvitals/web/app/demo/payments-api/summary/prs.jsonl +22 -0
- stackvitals/web/app/demo/payments-api/summary/tests.jsonl +3 -0
- stackvitals/web/app/demo/payments-api/supply.json +1 -0
- stackvitals/web/app/demo/payments-api/vulns.json +1 -0
- stackvitals/web/app/demo/portal.json +1 -0
- stackvitals/web/app/demo/settings.json +1 -0
- stackvitals/web/app/demo/web-app/alerts.json +1 -0
- stackvitals/web/app/demo/web-app/app.json +1 -0
- stackvitals/web/app/demo/web-app/community.json +1 -0
- stackvitals/web/app/demo/web-app/connectors.json +1 -0
- stackvitals/web/app/demo/web-app/data.json +1 -0
- stackvitals/web/app/demo/web-app/decisions.json +1 -0
- stackvitals/web/app/demo/web-app/delivery.json +1 -0
- stackvitals/web/app/demo/web-app/deps.json +1 -0
- stackvitals/web/app/demo/web-app/flow.json +1 -0
- stackvitals/web/app/demo/web-app/health.json +1 -0
- stackvitals/web/app/demo/web-app/insights.json +1 -0
- stackvitals/web/app/demo/web-app/pulse.json +1 -0
- stackvitals/web/app/demo/web-app/security.json +1 -0
- stackvitals/web/app/demo/web-app/summary/ci_jobs.jsonl +5 -0
- stackvitals/web/app/demo/web-app/summary/devlake_project_pr_metrics.jsonl +14 -0
- stackvitals/web/app/demo/web-app/summary/devlake_pull_requests.jsonl +14 -0
- stackvitals/web/app/demo/web-app/summary/manifest.json +1 -0
- stackvitals/web/app/demo/web-app/summary/prs.jsonl +18 -0
- stackvitals/web/app/demo/web-app/summary/tests.jsonl +2 -0
- stackvitals/web/app/demo/web-app/supply.json +1 -0
- stackvitals/web/app/demo/web-app/vulns.json +1 -0
- stackvitals/web/app/fonts/plex-mono-400.woff2 +0 -0
- stackvitals/web/app/fonts/plex-sans-400.woff2 +0 -0
- stackvitals/web/app/fonts/plex-sans-600.woff2 +0 -0
- stackvitals/web/app/fonts/plex-sans-condensed-700.woff2 +0 -0
- stackvitals/web/app/help/accuracy.json +1 -0
- stackvitals/web/app/help/connectors.json +1 -0
- stackvitals/web/app/help/getting-started.json +1 -0
- stackvitals/web/app/help/index.json +1 -0
- stackvitals/web/app/help/modules.json +1 -0
- stackvitals/web/app/help/privacy-and-security.json +1 -0
- stackvitals/web/app/help/reference.json +1 -0
- stackvitals/web/app/main.css +1 -0
- stackvitals/web/app/main.js +1 -0
- stackvitals/web/app/pages/about.css +1 -0
- stackvitals/web/app/pages/about.js +1 -0
- stackvitals/web/app/pages/activity.css +1 -0
- stackvitals/web/app/pages/activity.js +1 -0
- stackvitals/web/app/pages/agents.css +1 -0
- stackvitals/web/app/pages/agents.js +2 -0
- stackvitals/web/app/pages/ci.css +1 -0
- stackvitals/web/app/pages/ci.js +1 -0
- stackvitals/web/app/pages/community.css +1 -0
- stackvitals/web/app/pages/community.js +1 -0
- stackvitals/web/app/pages/connections.css +1 -0
- stackvitals/web/app/pages/connections.js +6 -0
- stackvitals/web/app/pages/delivery.css +1 -0
- stackvitals/web/app/pages/delivery.js +45 -0
- stackvitals/web/app/pages/deps.css +1 -0
- stackvitals/web/app/pages/deps.js +7 -0
- stackvitals/web/app/pages/explore.css +1 -0
- stackvitals/web/app/pages/explore.js +7 -0
- stackvitals/web/app/pages/health.css +1 -0
- stackvitals/web/app/pages/health.js +1 -0
- stackvitals/web/app/pages/help.css +1 -0
- stackvitals/web/app/pages/help.js +6 -0
- stackvitals/web/app/pages/insights.css +1 -0
- stackvitals/web/app/pages/insights.js +1 -0
- stackvitals/web/app/pages/investment.css +1 -0
- stackvitals/web/app/pages/investment.js +3 -0
- stackvitals/web/app/pages/overview.css +1 -0
- stackvitals/web/app/pages/overview.js +1 -0
- stackvitals/web/app/pages/portal.css +1 -0
- stackvitals/web/app/pages/portal.js +51 -0
- stackvitals/web/app/pages/prs.css +1 -0
- stackvitals/web/app/pages/prs.js +4 -0
- stackvitals/web/app/pages/settings.css +1 -0
- stackvitals/web/app/pages/settings.js +1 -0
- stackvitals/web/app/pages/setup.css +1 -0
- stackvitals/web/app/pages/setup.js +2 -0
- stackvitals/web/app/pages/standing.css +1 -0
- stackvitals/web/app/pages/standing.js +1 -0
- stackvitals/web/app/pages/welcome-sheet.js +1 -0
- stackvitals/web/app/pages/welcome.js +1 -0
- stackvitals/web/app/settings-workflow.json +1 -0
- stackvitals/web/index.html +34 -0
- stackvitals/web/site/index.html +108 -0
- stackvitals/web/site/integrations.html +15 -0
- stackvitals/web/site/setup.html +15 -0
- stackvitals/web/site/site.css +68 -0
- stackvitals-0.1.0.dist-info/METADATA +134 -0
- stackvitals-0.1.0.dist-info/RECORD +465 -0
- stackvitals-0.1.0.dist-info/WHEEL +4 -0
- stackvitals-0.1.0.dist-info/entry_points.txt +3 -0
- stackvitals-0.1.0.dist-info/licenses/LICENSE +202 -0
- stackvitals-0.1.0.dist-info/licenses/NOTICE +16 -0
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import{c as k,d as y,e as g}from"./chunk-P5TXDD45.js";import{d as m}from"./chunk-S654BBEP.js";import{f as u}from"./chunk-4WKQTWUC.js";import"./chunk-VQ5YXO54.js";import{H as h,n as d,o as p,q as o}from"./chunk-GT4EAKAO.js";import{d as i}from"./chunk-G7NGB5UX.js";i();i();var w={github:["GitHub","#181717","","M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"],jira:["Jira","#0052CC","#3375D6","M11.571 11.513H0a5.218 5.218 0 0 0 5.232 5.215h2.13v2.057A5.215 5.215 0 0 0 12.575 24V12.518a1.005 1.005 0 0 0-1.005-1.005zm5.723-5.756H5.736a5.215 5.215 0 0 0 5.215 5.214h2.129v2.058a5.218 5.218 0 0 0 5.215 5.214V6.758a1.001 1.001 0 0 0-1.001-1.001zM23.013 0H11.455a5.215 5.215 0 0 0 5.215 5.215h2.129v2.057A5.215 5.215 0 0 0 24 12.483V1.005A1.001 1.001 0 0 0 23.013 0Z"],linear:["Linear","#5E6AD2","#5E6AD2","M2.886 4.18A11.982 11.982 0 0 1 11.99 0C18.624 0 24 5.376 24 12.009c0 3.64-1.62 6.903-4.18 9.105L2.887 4.18ZM1.817 5.626l16.556 16.556c-.524.33-1.075.62-1.65.866L.951 7.277c.247-.575.537-1.126.866-1.65ZM.322 9.163l14.515 14.515c-.71.172-1.443.282-2.195.322L0 11.358a12 12 0 0 1 .322-2.195Zm-.17 4.862 9.823 9.824a12.02 12.02 0 0 1-9.824-9.824Z"],pagerduty:["PagerDuty","#059B32","#06AC38","M16.965 1.18C15.085.164 13.769 0 10.683 0H3.73v14.55h6.926c2.743 0 4.8-.164 6.61-1.37 1.975-1.303 3.004-3.484 3.004-6.007 0-2.716-1.262-4.896-3.305-5.994zm-5.5 10.326h-4.21V3.113l3.977-.027c3.62-.028 5.43 1.234 5.43 4.128 0 3.113-2.248 4.292-5.197 4.292zM3.73 17.61h3.525V24H3.73Z"],sonarqubeserver:["SonarQube Server","#126ED3","#1E75D5","M12 0a.774.774 0 0 0-.775.775c0 .43.346.776.775.776 5.762 0 10.45 4.687 10.45 10.449 0 .43.345.775.775.775A.774.774 0 0 0 24 12c0-6.616-5.384-12-12-12zm0 3.932a.774.774 0 0 0-.775.775c0 .43.346.775.775.775A6.524 6.524 0 0 1 18.518 12c0 .43.346.775.775.775.43 0 .775-.346.775-.775 0-4.448-3.62-8.068-8.068-8.068zm0 3.925a.774.774 0 0 0-.775.776c0 .43.346.775.775.775A2.597 2.597 0 0 1 14.592 12c0 .43.346.775.775.775.43 0 .776-.346.776-.775A4.145 4.145 0 0 0 12 7.857zM.775 11.225A.774.774 0 0 0 0 12c0 6.616 5.384 12 12 12 .43 0 .775-.346.775-.775a.774.774 0 0 0-.775-.776C6.238 22.45 1.55 17.762 1.55 12a.774.774 0 0 0-.775-.775zm3.932 0a.774.774 0 0 0-.775.775c0 4.448 3.62 8.068 8.068 8.068.43 0 .775-.346.775-.775a.774.774 0 0 0-.775-.775A6.524 6.524 0 0 1 5.482 12a.774.774 0 0 0-.775-.775zm3.926 0a.774.774 0 0 0-.776.775A4.145 4.145 0 0 0 12 16.143c.43 0 .775-.347.775-.776a.774.774 0 0 0-.775-.775A2.597 2.597 0 0 1 9.408 12a.774.774 0 0 0-.775-.775z"],argo:["Argo","#CB6941","#EF7B4D","M12.581 0c.436.037.871.1 1.299.186 1.679.383 3.121 1.213 4.382 2.365 1.161 1.06 1.917 2.372 2.335 3.881.089.321.216.56.586.624.205.035.238.245.239.43.003.646.002 1.294.002 1.94l-.002 1.21c-.001.356-.116.479-.466.474-.211-.003-.293.119-.344.291-.146.489-.33.966-.552 1.426-.818 1.682-2.084 2.938-3.688 3.87-.077.045-.155.088-.233.131-.252.137-.258.146-.155.415.114.299.358.529.664.625.269.096.553.134.827.21a.672.672 0 0 1 .236.094c-.066.082-.156.067-.231.082-.36.073-.713.184-1.086.17a1.275 1.275 0 0 1-.438-.064c-.114-.045-.152-.006-.176.109a5.354 5.354 0 0 0-.084.92c-.015.617-.071 1.23-.112 1.844-.042.598-.018.651.558.842.281.094.563.187.842.286.069.024.15.038.192.117-.04.057-.098.035-.146.035-.493.003-.985.005-1.478.001-.524-.005-.806-.282-.845-.803-.055-.762-.12-1.524-.182-2.286a.947.947 0 0 0-.026-.12c-.079.455-.065.879-.084 1.298-.023.528-.008 1.057-.007 1.584 0 .27.086.388.335.483.359.135.711.295 1.114.262.141-.012.276.062.402.129.032.017.073.033.069.073-.004.043-.049.047-.084.045-.657-.019-1.317.065-1.972-.028-.323-.046-.533-.236-.631-.552-.094-.303-.114-.617-.137-.93-.046-.626-.078-1.253-.116-1.88a.222.222 0 0 0-.061-.171.282.282 0 0 0-.031.193c-.002.956-.002 1.911-.001 2.866 0 .388.123.575.494.708.481.172.976.298 1.47.423.11.028.225.047.242.192h-1.852c-.051-.01-.103-.022-.155-.03-.701-.1-1.001-.372-1.143-1.042l-.067-.331-.226-1.103c-.069.12-.118.25-.144.386-.083.399-.151.802-.243 1.2-.113.493-.444.763-.932.857l-.33.063H8.558c.057-.171.216-.185.355-.221.476-.127.96-.223 1.417-.409a.603.603 0 0 0 .397-.521c.058-.435.002-.865-.013-1.296a1.528 1.528 0 0 0-.078-.315.405.405 0 0 0-.071.207c-.026.296-.049.591-.075.886-.038.432-.273.716-.679.81a1.702 1.702 0 0 1-.37.045c-.557.003-1.115-.001-1.673-.005-.048 0-.109.019-.148-.065.178-.103.377-.168.582-.187a5.67 5.67 0 0 0 .939-.193c.42-.114.522-.249.512-.687-.023-.931-.091-1.86-.069-2.791.004-.184.001-.368.001-.551a2.387 2.387 0 0 0-.05.385 40.299 40.299 0 0 1-.186 2.623c-.052.513-.296.748-.804.805-.446.051-.889.002-1.332-.02-.108-.006-.234.012-.339-.064.043-.066.106-.07.16-.087.362-.115.725-.224 1.086-.344.246-.081.35-.235.355-.492a2.241 2.241 0 0 0-.003-.232 45.315 45.315 0 0 1-.105-2.149 5.487 5.487 0 0 0-.035-.478c-.024-.188-.131-.287-.295-.258-.505.092-.99-.006-1.473-.139-.059-.016-.134-.007-.178-.088a.986.986 0 0 1 .285-.09c.255-.052.507-.121.753-.208.312-.112.564-.347.695-.651.089-.203.056-.317-.112-.398-1.418-.683-2.512-1.73-3.391-3.017a8.152 8.152 0 0 1-1.123-2.447c-.067-.246-.156-.3-.383-.26-.306.053-.401.006-.535-.273v-3.49c.144-.303.205-.341.534-.329.235.01.247-.004.309-.242.396-1.508 1.082-2.861 2.171-3.988C6.9 1.42 8.523.631 10.34.203c.456-.108.922-.15 1.387-.203h.854Zm7.974 8.948a7.34 7.34 0 0 0-.048-.938 8.353 8.353 0 0 0-.099-.65c-.598-2.964-2.344-5.02-5.051-6.268-1.553-.715-3.21-.835-4.878-.511-3.248.633-5.396 2.583-6.539 5.652-.436 1.173-.495 2.406-.37 3.65.087.935.339 1.846.745 2.694.585 1.213 1.444 2.207 2.477 3.058.343.286.719.528 1.121.719.235.111.247.105.245-.146.006-.16.003-.32-.009-.48-.125-1.02-.142-2.045-.169-3.069a.392.392 0 0 0-.184-.353c-.385-.268-.713-.592-.921-1.019-.474-.97-.372-2.361.813-3.215.136-.097.217-.19.198-.373a1.724 1.724 0 0 1 .031-.442c.177-1.187.748-2.138 1.722-2.84.68-.492 1.442-.772 2.286-.782.483-.007.953.11 1.414.244 1.609.467 2.846 2.07 2.845 3.697a.64.64 0 0 0 .268.565c.463.371.821.83.943 1.426.22 1.077-.083 1.982-.979 2.634-.266.194-.347.406-.333.698.002.047 0 .095-.002.142l-.062 1.439c-.025.586-.138 1.165-.117 1.754.008.223.006.226.201.128a7.46 7.46 0 0 0 2.393-1.903c1.32-1.577 2.074-3.372 2.059-5.511ZM9.117 12.102c1.489.021 2.443-1.578 1.716-2.879a1.937 1.937 0 0 0-1.699-.991c-1.094-.004-1.954.822-1.958 1.881-.005 1.148.813 1.985 1.941 1.989Zm5.794 0c1.101.002 1.935-.823 1.935-1.917 0-1.091-.846-1.949-1.92-1.947-1.064.003-1.94.866-1.943 1.915-.003 1.105.831 1.948 1.928 1.949Zm-1.472 1.937c-.208.128-.407.277-.63.384-.536.257-1.063.257-1.579-.048-.158-.094-.308-.201-.464-.298-.047-.028-.092-.103-.15-.062-.044.03-.01.1-.001.151.037.179.064.362.082.544.027.565.293.992.742 1.31a.984.984 0 0 0 .791.186c.565-.119 1.025-.614 1.124-1.218.043-.266.005-.544.109-.803a.133.133 0 0 0-.024-.146Zm-8.78-4.92c-.012-1.102.143-2.055.54-2.961.633-1.443 1.642-2.553 2.98-3.374a.378.378 0 0 1 .459.067c.06.06.036.118.01.178a1.09 1.09 0 0 1-.48.51c-1.079.639-1.829 1.571-2.357 2.688a6.325 6.325 0 0 0-.618 2.986c.055 1.309.439 2.516 1.213 3.588.088.104.148.23.173.365.01.08.059.168-.031.228a.312.312 0 0 1-.288.041.502.502 0 0 1-.234-.185c-.72-.979-1.193-2.056-1.331-3.273-.036-.326-.004-.653-.036-.858ZM8.94 2.34a.373.373 0 0 1 .378-.382c.211.001.409.226.416.473.004.138-.309.39-.476.386-.189-.005-.318-.2-.318-.477Zm-.465 7.48a.609.609 0 0 1 .586-.631c.38-.003.671.271.675.633.004.356-.27.622-.639.621-.38-.002-.621-.241-.622-.623Zm6.496.623c-.381-.002-.625-.255-.621-.646a.635.635 0 0 1 .596-.613.656.656 0 0 1 .669.643c.001.354-.275.618-.644.616Z"],bitbucket:["Bitbucket","#0052CC","#3375D6","M.778 1.213a.768.768 0 00-.768.892l3.263 19.81c.084.5.515.868 1.022.873H19.95a.772.772 0 00.77-.646l3.27-20.03a.768.768 0 00-.768-.891zM14.52 15.53H9.522L8.17 8.466h7.561z"],discourse:["Discourse","#000000","","M12.103 0C18.666 0 24 5.485 24 11.997c0 6.51-5.33 11.99-11.9 11.99L0 24V11.79C0 5.28 5.532 0 12.103 0zm.116 4.563c-2.593-.003-4.996 1.352-6.337 3.57-1.33 2.208-1.387 4.957-.148 7.22L4.4 19.61l4.794-1.074c2.745 1.225 5.965.676 8.136-1.39 2.17-2.054 2.86-5.228 1.737-7.997-1.135-2.778-3.84-4.59-6.84-4.585h-.008z"],discord:["Discord","#5865F2","#5865F2","M20.317 4.3698a19.7913 19.7913 0 00-4.8851-1.5152.0741.0741 0 00-.0785.0371c-.211.3753-.4447.8648-.6083 1.2495-1.8447-.2762-3.68-.2762-5.4868 0-.1636-.3933-.4058-.8742-.6177-1.2495a.077.077 0 00-.0785-.037 19.7363 19.7363 0 00-4.8852 1.515.0699.0699 0 00-.0321.0277C.5334 9.0458-.319 13.5799.0992 18.0578a.0824.0824 0 00.0312.0561c2.0528 1.5076 4.0413 2.4228 5.9929 3.0294a.0777.0777 0 00.0842-.0276c.4616-.6304.8731-1.2952 1.226-1.9942a.076.076 0 00-.0416-.1057c-.6528-.2476-1.2743-.5495-1.8722-.8923a.077.077 0 01-.0076-.1277c.1258-.0943.2517-.1923.3718-.2914a.0743.0743 0 01.0776-.0105c3.9278 1.7933 8.18 1.7933 12.0614 0a.0739.0739 0 01.0785.0095c.1202.099.246.1981.3728.2924a.077.077 0 01-.0066.1276 12.2986 12.2986 0 01-1.873.8914.0766.0766 0 00-.0407.1067c.3604.698.7719 1.3628 1.225 1.9932a.076.076 0 00.0842.0286c1.961-.6067 3.9495-1.5219 6.0023-3.0294a.077.077 0 00.0313-.0552c.5004-5.177-.8382-9.6739-3.5485-13.6604a.061.061 0 00-.0312-.0286zM8.02 15.3312c-1.1825 0-2.1569-1.0857-2.1569-2.419 0-1.3332.9555-2.4189 2.157-2.4189 1.2108 0 2.1757 1.0952 2.1568 2.419 0 1.3332-.9555 2.4189-2.1569 2.4189zm7.9748 0c-1.1825 0-2.1569-1.0857-2.1569-2.419 0-1.3332.9554-2.4189 2.1569-2.4189 1.2108 0 2.1757 1.0952 2.1568 2.419 0 1.3332-.946 2.4189-2.1568 2.4189Z"],githubcopilot:["GitHub Copilot","#000000","","M23.922 16.997C23.061 18.492 18.063 22.02 12 22.02 5.937 22.02.939 18.492.078 16.997A.641.641 0 0 1 0 16.741v-2.869a.883.883 0 0 1 .053-.22c.372-.935 1.347-2.292 2.605-2.656.167-.429.414-1.055.644-1.517a10.098 10.098 0 0 1-.052-1.086c0-1.331.282-2.499 1.132-3.368.397-.406.89-.717 1.474-.952C7.255 2.937 9.248 1.98 11.978 1.98c2.731 0 4.767.957 6.166 2.093.584.235 1.077.546 1.474.952.85.869 1.132 2.037 1.132 3.368 0 .368-.014.733-.052 1.086.23.462.477 1.088.644 1.517 1.258.364 2.233 1.721 2.605 2.656a.841.841 0 0 1 .053.22v2.869a.641.641 0 0 1-.078.256Zm-11.75-5.992h-.344a4.359 4.359 0 0 1-.355.508c-.77.947-1.918 1.492-3.508 1.492-1.725 0-2.989-.359-3.782-1.259a2.137 2.137 0 0 1-.085-.104L4 11.746v6.585c1.435.779 4.514 2.179 8 2.179 3.486 0 6.565-1.4 8-2.179v-6.585l-.098-.104s-.033.045-.085.104c-.793.9-2.057 1.259-3.782 1.259-1.59 0-2.738-.545-3.508-1.492a4.359 4.359 0 0 1-.355-.508Zm2.328 3.25c.549 0 1 .451 1 1v2c0 .549-.451 1-1 1-.549 0-1-.451-1-1v-2c0-.549.451-1 1-1Zm-5 0c.549 0 1 .451 1 1v2c0 .549-.451 1-1 1-.549 0-1-.451-1-1v-2c0-.549.451-1 1-1Zm3.313-6.185c.136 1.057.403 1.913.878 2.497.442.544 1.134.938 2.344.938 1.573 0 2.292-.337 2.657-.751.384-.435.558-1.15.558-2.361 0-1.14-.243-1.847-.705-2.319-.477-.488-1.319-.862-2.824-1.025-1.487-.161-2.192.138-2.533.529-.269.307-.437.808-.438 1.578v.021c0 .265.021.562.063.893Zm-1.626 0c.042-.331.063-.628.063-.894v-.02c-.001-.77-.169-1.271-.438-1.578-.341-.391-1.046-.69-2.533-.529-1.505.163-2.347.537-2.824 1.025-.462.472-.705 1.179-.705 2.319 0 1.211.175 1.926.558 2.361.365.414 1.084.751 2.657.751 1.21 0 1.902-.394 2.344-.938.475-.584.742-1.44.878-2.497Z"],anthropic:["Anthropic","#191919","","M17.3041 3.541h-3.6718l6.696 16.918H24Zm-10.6082 0L0 20.459h3.7442l1.3693-3.5527h7.0052l1.3693 3.5528h3.7442L10.5363 3.5409Zm-.3712 10.2232 2.2914-5.9456 2.2914 5.9456Z"],cursor:["Cursor","#000000","","M11.503.131 1.891 5.678a.84.84 0 0 0-.42.726v11.188c0 .3.162.575.42.724l9.609 5.55a1 1 0 0 0 .998 0l9.61-5.55a.84.84 0 0 0 .42-.724V6.404a.84.84 0 0 0-.42-.726L12.497.131a1.01 1.01 0 0 0-.996 0M2.657 6.338h18.55c.263 0 .43.287.297.515L12.23 22.918c-.062.107-.229.064-.229-.06V12.335a.59.59 0 0 0-.295-.51l-9.11-5.257c-.109-.063-.064-.23.061-.23"],googlegemini:["Google Gemini","#8E75B2","#8E75B2","M11.04 19.32Q12 21.51 12 24q0-2.49.93-4.68.96-2.19 2.58-3.81t3.81-2.55Q21.51 12 24 12q-2.49 0-4.68-.93a12.3 12.3 0 0 1-3.81-2.58 12.3 12.3 0 0 1-2.58-3.81Q12 2.49 12 0q0 2.49-.96 4.68-.93 2.19-2.55 3.81a12.3 12.3 0 0 1-3.81 2.58Q2.49 12 0 12q2.49 0 4.68.96 2.19.93 3.81 2.55t2.55 3.81"],gitlab:["GitLab","#D65D20","#FC6D26","m23.6004 9.5927-.0337-.0862L20.3.9814a.851.851 0 0 0-.3362-.405.8748.8748 0 0 0-.9997.0539.8748.8748 0 0 0-.29.4399l-2.2055 6.748H7.5375l-2.2057-6.748a.8573.8573 0 0 0-.29-.4412.8748.8748 0 0 0-.9997-.0537.8585.8585 0 0 0-.3362.4049L.4332 9.5015l-.0325.0862a6.0657 6.0657 0 0 0 2.0119 7.0105l.0113.0087.03.0213 4.976 3.7264 2.462 1.8633 1.4995 1.1321a1.0085 1.0085 0 0 0 1.2197 0l1.4995-1.1321 2.4619-1.8633 5.006-3.7489.0125-.01a6.0682 6.0682 0 0 0 2.0094-7.003z"],jenkins:["Jenkins","#D24939","#D24939","M2.872 24h-.975a3.866 3.866 0 01-.07-.197c-.215-.666-.594-1.49-.692-2.154-.146-.984.78-1.039 1.374-1.465.915-.66 1.635-1.025 2.627-1.62.295-.179 1.182-.624 1.281-.829.201-.408-.345-.982-.49-1.3-.225-.507-.345-.937-.376-1.435-.824-.13-1.455-.627-1.844-1.185-.63-.925-1.066-2.635-.525-3.936.045-.103.254-.305.285-.463.06-.308-.105-.72-.12-1.048-.06-1.692.284-3.15 1.425-3.66.463-1.84 2.113-2.453 3.673-3.367.58-.342 1.224-.562 1.89-.807 2.372-.877 6.027-.712 7.994.783.836.633 2.176 1.97 2.656 2.939 1.262 2.555 1.17 6.825.287 9.934-.12.421-.29 1.032-.533 1.533-.168.35-.689 1.05-.625 1.36.064.314 1.19 1.17 1.432 1.395.434.422 1.26.975 1.324 1.5.07.557-.248 1.336-.41 1.875-.217.721-.436 1.441-.654 2.131H2.87zm11.104-3.54c-.545-.3-1.361-.622-2.065-.757-.87-.164-.78 1.188-.75 1.994.03.643.36 1.316.51 1.744.076.197.09.41.256.449.3.068 1.29-.326 1.575-.479.6-.328 1.064-.844 1.574-1.189.016-.17.016-.34.03-.508a2.648 2.648 0 00-1.095-.277c.314-.15.75-.15 1.035-.332l.016-.193c-.496-.03-.69-.254-1.021-.436zm7.454 2.935a17.78 17.78 0 00.465-1.752c.06-.287.215-.918.178-1.176-.059-.459-.684-.799-1.004-1.086-.584-.525-.95-.975-1.56-1.469-.249.375-.78.615-.983.914 1.447-.689 1.71 2.625 1.141 3.69.09.329.391.45.514.735l-.086.166h1.29c.013 0 .03 0 .044.014zm-6.634-.012c-.05-.074-.1-.135-.15-.209l-.301.195h.45zm2.77 0c.008-.209.018-.404.03-.598-.53.029-.825-.48-1.196-.527-.324-.045-.6.361-1.02.195-.095.105-.183.227-.284.316.154.18.295.375.424.584h.815c.014-.164.135-.285.3-.285.165 0 .284.121.284.27h.66zm2.116 0c-.314-.479-.947-.898-1.68-.555l-.03.541h1.71zm-8.51 0l-.104-.344c-.225-.72-.36-1.26-.405-1.68-.914-.436-1.875-.87-2.654-1.426-.15-.105-1.109-1.35-1.23-1.305-1.739.676-3.359 1.86-4.814 2.984.256.557.48 1.141.69 1.74h8.505zm8.265-2.113c-.029-.512-.164-1.56-.48-1.74-.66-.39-1.846.78-2.34.943.045.15.135.271.15.48.285-.074.645-.029.898.092-.299.03-.629.03-.824.164-.074.195.016.48-.029.764.69.197 1.5.303 2.385.332.164-.227.225-.645.211-1.082zm-4.08-.36c-.044.375.046.51.12.943 1.26.391 1.034-1.74-.135-.959zM8.76 19.5c-.45.457 1.27 1.082 1.814 1.115 0-.29.165-.564.135-.77-.65-.118-1.502-.042-1.945-.347zm5.565.215c0 .043-.061.03-.068.064.58.451 1.014.545 1.802.51.354-.262.67-.563 1.043-.807-.855.074-1.931.607-2.774.23zm3.42-17.726c-1.606-.906-4.35-1.591-6.076-.731-1.38.692-3.27 1.84-3.899 3.292.6 1.402-.166 2.686-.226 4.109-.018.757.36 1.42.391 2.242-.2.338-.825.38-1.26.356-.146-.729-.4-1.549-1.155-1.63-1.064-.116-1.845.764-1.89 1.683-.06 1.08.833 2.864 2.085 2.745.488-.046.608-.54 1.139-.54.285.57-.445.75-.523 1.154-.016.105.06.511.104.705.233.944.744 2.16 1.245 2.88.635.9 1.884 1.051 3.229 1.141.24-.525 1.125-.48 1.706-.346-.691-.27-1.336-.945-1.875-1.529-.615-.676-1.23-1.41-1.261-2.28 1.155 1.604 2.1 3 4.2 3.704 1.59.525 3.45-.254 4.664-1.109.51-.359.811-.93 1.17-1.439 1.35-1.936 1.98-4.71 1.846-7.394-.06-1.111-.06-2.221-.436-2.955-.389-.781-1.695-1.471-2.475-.781-.15-.764.63-1.23 1.545-.96-.66-.854-1.336-1.858-2.266-2.384zM13.58 14.896c.615 1.544 2.724 1.363 4.505 1.323-.084.194-.256.435-.465.515-.57.232-2.145.408-2.937-.012-.506-.27-.824-.873-1.102-1.227-.137-.172-.795-.608-.012-.609zm.164-.87c.893.464 2.52.517 3.731.48.066.267.066.593.068.913-1.55.08-3.386-.304-3.794-1.395h-.005zm6.675-.586c-.473.9-1.145 1.897-2.539 1.928-.023-.284-.045-.735 0-.904 1.064-.103 1.727-.646 2.543-1.017zm-.649-.667c-1.02.66-2.154 1.375-3.824 1.21-.351-.31-.485-1-.14-1.458.181.313.06.885.57.97.944.165 2.038-.579 2.73-.84.42-.713-.046-.976-.42-1.433-.782-.93-1.83-2.1-1.802-3.51.314-.224.346.346.391.45.404.96 1.424 2.175 2.174 3 .18.21.48.39.51.524.092.39-.254.854-.209 1.11zm-13.439-.675c-.314-.184-.393-.99-.768-1.01-.535-.03-.438 1.05-.436 1.68-.37-.33-.435-1.365-.164-1.89-.308-.15-.445.164-.618.284.22-1.59 2.34-.734 1.99.96zM4.713 5.995c-.685.756-.54 2.174-.459 3.188 1.244-.785 2.898.06 2.883 1.394.595-.016.223-.744.115-1.215-.353-1.528.592-3.187.041-4.59-1.064.084-1.939.52-2.578 1.215zm9.12 1.113c.307.562.404 1.148.84 1.57.195.19.574.424.387.95-.045.121-.365.391-.551.45-.674.195-2.254.03-1.721-.81.563.015 1.314.36 1.732-.045-.314-.524-.885-1.53-.674-2.13zm6.198-.013h.068c.33.668.6 1.375 1.004 1.965-.27.628-2.053 1.19-2.023.057.39-.17 1.05-.035 1.395-.25-.193-.556-.48-1.006-.434-1.771zm-6.927-1.617c-1.422-.33-2.131.592-2.56 1.553-.384-.094-.231-.615-.135-.883.255-.701 1.28-1.633 2.119-1.506.359.057.848.386.576.834zM9.642 1.593c-1.56.44-3.56 1.574-4.2 2.974.495-.07.84-.321 1.33-.351.186-.016.428.074.641.015.424-.104.78-1.065 1.102-1.41.31-.345.685-.496.94-.81.167-.09.409-.074.42-.33-.073-.075-.15-.135-.232-.105v.017z"],circleci:["CircleCI","#343434","","M8.963 12c0-1.584 1.284-2.855 2.855-2.855 1.572 0 2.856 1.284 2.856 2.855 0 1.572-1.284 2.856-2.856 2.856-1.57 0-2.855-1.284-2.855-2.856zm2.855-12C6.215 0 1.522 3.84.19 9.025c-.01.036-.01.07-.01.12 0 .313.252.576.575.576H5.59c.23 0 .433-.13.517-.333.997-2.16 3.18-3.672 5.712-3.672 3.466 0 6.286 2.82 6.286 6.287 0 3.47-2.82 6.29-6.29 6.29-2.53 0-4.714-1.5-5.71-3.673-.097-.19-.29-.336-.517-.336H.755c-.312 0-.575.253-.575.576 0 .037.014.072.014.12C1.514 20.16 6.214 24 11.818 24c6.624 0 12-5.375 12-12 0-6.623-5.376-12-12-12z"],buildkite:["Buildkite","#0F9960","#14CC80","M23.613 8.143l-7.668-3.856v7.712l7.668-3.855zM8.166 15.857V8.143L.387 4.287V12l7.78 3.857zM.183 3.958a.382.382 0 01.377-.017l7.606 3.771 7.607-3.771a.386.386 0 01.346 0l7.668 3.857a.386.386 0 01.213.345v7.71a.388.388 0 01-.213.346l-7.668 3.86a.389.389 0 01-.562-.345v-7.09l-7.219 3.58a.392.392 0 01-.344 0L.215 12.346A.387.387 0 010 12V4.287a.385.385 0 01.183-.329z"],modelcontextprotocol:["Model Context Protocol","#000000","","M13.85 0a4.16 4.16 0 0 0-2.95 1.217L1.456 10.66a.835.835 0 0 0 0 1.18.835.835 0 0 0 1.18 0l9.442-9.442a2.49 2.49 0 0 1 3.541 0 2.49 2.49 0 0 1 0 3.541L8.59 12.97l-.1.1a.835.835 0 0 0 0 1.18.835.835 0 0 0 1.18 0l.1-.098 7.03-7.034a2.49 2.49 0 0 1 3.542 0l.049.05a2.49 2.49 0 0 1 0 3.54l-8.54 8.54a1.96 1.96 0 0 0 0 2.755l1.753 1.753a.835.835 0 0 0 1.18 0 .835.835 0 0 0 0-1.18l-1.753-1.753a.266.266 0 0 1 0-.394l8.54-8.54a4.185 4.185 0 0 0 0-5.9l-.05-.05a4.16 4.16 0 0 0-2.95-1.218c-.2 0-.401.02-.6.048a4.17 4.17 0 0 0-1.17-3.552A4.16 4.16 0 0 0 13.85 0m0 3.333a.84.84 0 0 0-.59.245L6.275 10.56a4.186 4.186 0 0 0 0 5.902 4.186 4.186 0 0 0 5.902 0L19.16 9.48a.835.835 0 0 0 0-1.18.835.835 0 0 0-1.18 0l-6.985 6.984a2.49 2.49 0 0 1-3.54 0 2.49 2.49 0 0 1 0-3.54l6.983-6.985a.835.835 0 0 0 0-1.18.84.84 0 0 0-.59-.245"],opentelemetry:["OpenTelemetry","#000000","","M12.6974 13.1173c-1.0224 1.0224-1.0224 2.68 0 3.7024 1.0224 1.0224 2.68 1.0224 3.7024 0 1.0224-1.0223 1.0224-2.68 0-3.7024-1.0223-1.0223-2.68-1.0223-3.7024 0zm2.7677 2.7701c-.5063.5063-1.3267.5063-1.833 0s-.5063-1.3266 0-1.833c.5063-.5062 1.3267-.5062 1.833 0 .5063.504.5063 1.3267 0 1.833zM16.356.2355l-1.6041 1.6042c-.314.314-.314.83 0 1.144L21.015 9.247c.314.314.83.314 1.144 0l1.6042-1.6041c.314-.314.314-.83 0-1.144L17.4976.2354c-.314-.314-.8276-.314-1.1416 0zM5.1173 20.734c.2848-.2848.2848-.7497 0-1.0345l-.8155-.8155c-.2848-.2848-.7497-.2848-1.0345 0l-1.6845 1.6845-.0024.0024-.4625-.4625c-.2556-.2556-.6718-.2556-.925 0-.2556.2556-.2556.6718 0 .925l2.775 2.775c.2556.2556.6718.2556.925 0 .2532-.2556.2556-.6718 0-.925l-.4625-.4625.0024-.0024zm8.4856-15.893-3.5637 3.5637c-.3164.3164-.3164.8374 0 1.1538l2.2006 2.2005c1.5554-1.1197 3.7365-.981 5.1361.4187l1.7819-1.7818c.3164-.3165.3164-.8374 0-1.1538l-4.401-4.401c-.3165-.319-.8374-.319-1.1539 0zm-2.2881 7.8455-1.2999-1.2999c-.3043-.3043-.8033-.3043-1.1076 0l-4.5836 4.586c-.3042.3043-.3042.8033 0 1.1076l2.5973 2.5973c.3043.3043.8033.3043 1.1076 0l2.9478-2.9527c-.6231-1.2877-.5112-2.8431.3384-4.0383z"],backstage:["Backstage","#5D9087","#9BF0E1","M19.5188 9.3003a4.5194 4.5194 0 0 0 .7533-.5808 7.0485 7.0485 0 0 0 .1289-.1288 4.6555 4.6555 0 0 0 .4441-.5254 3.5672 3.5672 0 0 0 .354-.6032 2.721 2.721 0 0 0 .2436-.9185c.0835-1.086-.56-2.166-1.995-3.0369L13.6692 0 6.9335 6.454 2.548 10.6558l6.0826 3.6916a6.25 6.25 0 0 0 3.2351.919c1.3958 0 2.7333-.4928 3.7201-1.4388 1.0732-1.0283 1.4294-2.3591.7674-3.4653a2.7568 2.7568 0 0 0-.3809-.4968 4.9944 4.9944 0 0 0 1.0821.1204h.0084a4.7653 4.7653 0 0 0 1.7363-.3243 4.53 4.53 0 0 0 .7197-.3613Zm-5.6317 3.35c-1.0821 1.0367-2.8229 1.189-4.24.3304l-4.2085-2.5546 3.7779-3.6204 4.2796 2.5977c1.542.9348 1.4574 2.2247.391 3.2469zm.5001-4.6051-3.957-2.4023 3.6075-3.4585 3.8854 2.358c1.4529.8804 1.6416 2.0723.591 3.0805a3.3992 3.3992 0 0 1-4.1269.4223Zm1.6725 10.6418c-1.0961 1.0501-2.586 1.6293-4.194 1.6293a6.93 6.93 0 0 1-3.5902-1.0194L2.548 15.8238v1.3817l6.0826 3.6916a6.2506 6.2506 0 0 0 3.2351.9197c1.3958 0 2.7333-.4935 3.7201-1.439.7214-.691 1.1202-1.5195 1.1023-2.3237v-.1003a4.888 4.888 0 0 1-.6284.7354zm0-2.1844c-1.0961 1.0502-2.586 1.6287-4.194 1.6287a6.9345 6.9345 0 0 1-3.5902-1.0188L2.548 13.64v1.3824l6.0826 3.6915a6.2506 6.2506 0 0 0 3.2351.9197c1.3958 0 2.7333-.4934 3.7201-1.4389.7214-.6911 1.1202-1.5195 1.1023-2.3244v-.0997a4.888 4.888 0 0 1-.6284.7354zm0-2.1844c-1.0961 1.0508-2.586 1.6293-4.194 1.6293a6.9345 6.9345 0 0 1-3.5902-1.0188l-5.7275-3.472v1.3823l6.0826 3.6916a6.25 6.25 0 0 0 3.2351.9191c1.3958 0 2.7333-.4929 3.7201-1.4383.7214-.6917 1.1202-1.5195 1.1023-2.3244v-.102a4.8218 4.8218 0 0 1-.6284.7371zm4.688 1.4417a5.2733 5.2733 0 0 1-3.3718 1.4484v1.4988a4.5704 4.5704 0 0 0 2.898-1.253c.784-.7493 1.184-1.5743 1.1761-2.3882v-.1226a5.3164 5.3164 0 0 1-.7023.8205zm-4.688 5.1086c-1.0961 1.0508-2.586 1.6293-4.194 1.6293a6.93 6.93 0 0 1-3.5902-1.0193L2.548 18.007v1.3823l6.0826 3.691A6.2506 6.2506 0 0 0 11.8657 24c1.3958 0 2.7333-.4929 3.7201-1.4389.7214-.6911 1.1202-1.5195 1.1023-2.3238v-.1003a4.833 4.833 0 0 1-.6284.7354zM20.863 9.0987c-.038.0386-.0756.0773-.1148.1154a5.2856 5.2856 0 0 1-.596.4845 5.1165 5.1165 0 0 1-.6496.392 5.2946 5.2946 0 0 1-1.4697.4879 5.4716 5.4716 0 0 1-.7931.088 3.07 3.07 0 0 1 .07.2744 2.9836 2.9836 0 0 1 .0638.672v.5411h.0032a4.7277 4.7277 0 0 0 1.4198-.3108 4.5368 4.5368 0 0 0 1.478-.9421c.0449-.043.084-.0874.1267-.131a4.5972 4.5972 0 0 0 .4441-.5254 3.5712 3.5712 0 0 0 .354-.6016 2.7193 2.7193 0 0 0 .242-.9213c.0046-.0689.0111-.1384.0106-.2073v-.1131q-.0605.0863-.126.173a5.4178 5.4178 0 0 1-.4627.5243zm0 4.3643c-.0386.0392-.0733.079-.112.1176a5.276 5.276 0 0 1-3.3717 1.4484v1.4938a4.5704 4.5704 0 0 0 2.8979-1.253 4.1172 4.1172 0 0 0 .9219-1.2602 2.7198 2.7198 0 0 0 .242-.9208c.0047-.0694.0111-.1383.0106-.2078v-.1226c-.0414.06-.0818.1204-.1272.1798a5.359 5.359 0 0 1-.4615.5248zm0-2.1844c-.0386.0392-.0733.079-.112.1176a5.219 5.219 0 0 1-.5954.4845 5.1321 5.1321 0 0 1-.6513.392 5.3472 5.3472 0 0 1-2.125.5702v1.4955a4.5732 4.5732 0 0 0 2.8979-1.253c.0448-.0431.084-.0873.1266-.131a4.5972 4.5972 0 0 0 .4441-.5254 3.5712 3.5712 0 0 0 .3512-.6026 2.7198 2.7198 0 0 0 .242-.9208c.0047-.0694.0111-.139.0106-.2078v-.1232c-.0414.0604-.0818.121-.1272.1803a5.359 5.359 0 0 1-.4615.5248z"]};var D={github:["github"],ghes:["github"],sarif:["github"],copilot:["githubcopilot"],jira:["jira"],linear:["linear"],pagerduty:["pagerduty"],sonar:["sonarqubeserver"],record:["argo"],bitbucket:["bitbucket"],discourse:["discourse"],discord:["discord"],chat:"chat",ai_spend:["anthropic","cursor"],triage:["googlegemini"],gitlab:["gitlab"],otherci:["jenkins","circleci","buildkite"],agents:["modelcontextprotocol"],otel:["opentelemetry"],backstage:["backstage"]},r="The StackVitals workflow",t="connectors.md",R=[["CI Health","actions: read (write to re-run flaky jobs)"],["Team Flow and Delivery","pull-requests, checks, statuses, deployments: read"],["Community","issues: read"],["Dependencies","contents: read"],["Portal","an org App token for private repos"]],P=[{id:"github",name:"GitHub",glyph:"GH",cat:"github",kind:"builtin",tested:"Live",doc:t+"#github-built-in",unlocks:["CI runs, jobs and test reports (JUnit, CTRF)","Pull requests, reviews and checks","Deployments, releases and issues","Org repos, owners and scorecards (Portal)"],steps:()=>[{text:"Nothing to add: the workflow's own token reads them. Without a permission, that part is skipped and the job summary names the permission to add."}]},{id:"ghes",name:"GitHub Enterprise Server",glyph:"GE",cat:"github",kind:"builtin",tested:"Recorded",doc:"faq.md#does-it-work-on-github-enterprise-server",unlocks:["The same modules on your own GitHub server","The Action talks to your server, never github.com"],steps:()=>[{text:"Nothing to add: the Action reads the API addresses GitHub Actions gives every job (GITHUB_API_URL and GITHUB_GRAPHQL_URL)."},{text:"From your machine, set the same two variables:",file:"Terminal",code:`export GITHUB_API_URL=https://<your-server>/api/v3
|
|
2
|
+
export GITHUB_GRAPHQL_URL=https://<your-server>/api/graphql
|
|
3
|
+
stackvitals delivery owner/repo`},{text:"Two limits: links in the app point to github.com pages, and peer comparisons cover public github.com repos only."}]},{id:"scorecard",name:"OpenSSF Scorecard",glyph:"Sc",cat:"security",kind:"builtin",tested:"Live",doc:"modules.md#dependency-steward",unlocks:["This repo's own Scorecard-style checks, private repos too, with a fix for each (Dependencies page)","The Scorecard of each project behind your dependencies, with drops of a point or more","Public repos' published Scorecards in the Portal rules"],steps:()=>[{text:"Nothing to add. The workflow runs the checks itself; published scores come from api.scorecard.dev for public projects only, never this repo's name."},{text:"To keep every name in the repo, turn outside lookups off:",file:".github/stackvitals.toml",code:`[deps]
|
|
4
|
+
outside_lookups = false`},{text:"See this repo's checks and score.",to:"#/deps",action:"Open Dependencies"}]},{id:"sarif",name:"GitHub code scanning (Security tab)",glyph:"Cs",cat:"security",kind:"local",doc:"modules.md#dependency-steward",unlocks:["Known vulnerabilities in every lockfile as code scanning alerts (vulns.sarif)","Workflow security findings (security.sarif) beside CodeQL's"],steps:()=>[{text:"Each run writes docs/vulns.sarif and docs/security.sarif to the stackvitals-data branch. The Dependencies page makes the workflow that uploads them (.github/workflows/stackvitals-code-scanning.yml, with github/codeql-action/upload-sarif@v4) and adds it in one click: GitHub's editor with no token, or a pull request with a token. It runs after each StackVitals run on the default branch and needs security-events: write.",to:"#/deps",action:"Open Dependencies"},{text:"Code scanning is free on public repos; private repos need GitHub Code Security."}]},{id:"licences",name:"Licence rule on pull requests",glyph:"Lc",cat:"security",kind:"nokey",tested:"Live",prefix:"deps.licenses",doc:"modules.md#dependency-steward",unlocks:["Each package version a pull request brings in has its licence looked up on deps.dev","A denied licence is named in the check, the job summary and the PR note before it merges","The same rule over the whole dependency graph each week"],steps:()=>[{text:"List the SPDX licences your dependencies must not use under Settings below (* is allowed, like GPL-3.0*). Empty is off."},{text:"Accept one package with a reason and an end date:",file:"Pull request comment",code:"/stackvitals accept package:<name> for 30d because <reason>"}]},{id:"jira",name:"Jira Cloud",glyph:"Ji",cat:"work",kind:"key",check:"jira",tested:"Live, write-back recorded",prefix:"connectors.jira",doc:t+"#issue-trackers-jira-cloud-and-linear-one-optional-key-each",secrets:[{name:"JIRA_EMAIL"},{name:"JIRA_API_TOKEN"}],unlocks:["Issue lead and cycle time by type","Sprints: scope, done, carried over, added late","Incidents from a JQL query in DORA's failure rate and recovery","Pull requests linked to issues by key","DevLake's issue and sprint tables"],steps:()=>[{text:"Create an API token for the account StackVitals reads as (a read-only account is best) and note when it expires.",href:"https://id.atlassian.com/manage-profile/security/api-tokens",action:"Create a Jira token"},{text:"Save JIRA_EMAIL (that account's email) and JIRA_API_TOKEN below."},{text:`${r} passes them (new installs already have these lines):`,file:"stackvitals.yml",code:"jira-email: ${{ secrets.JIRA_EMAIL }}\njira-token: ${{ secrets.JIRA_API_TOKEN }}"},{text:"Name your site and the issues to read under Settings below."},{text:"The next scheduled run reads up to 180 days of issues, then only what changed."}]},{id:"linear",name:"Linear",glyph:"Li",cat:"work",kind:"key",check:"linear",tested:"Live sign-in and read",prefix:"connectors.linear",doc:t+"#issue-trackers-jira-cloud-and-linear-one-optional-key-each",secrets:[{name:"LINEAR_API_KEY",browser:"linear"}],unlocks:["Issue lead and cycle time","Cycles: scope, done, carried over, added late","Incidents from labels in DORA","Pull requests linked to issues by identifier","DevLake's issue and sprint tables"],steps:()=>[{text:"In Linear, open Settings, Account, Security and access, and create a personal API key with read access.",href:"https://linear.app/settings/account/security",action:"Open Linear settings"},{text:"Save it as LINEAR_API_KEY below."},{text:`${r} passes it (new installs already have this line):`,file:"stackvitals.yml",code:"linear-token: ${{ secrets.LINEAR_API_KEY }}"},{text:"Choose the teams to read under Settings below."}]},{id:"pagerduty",name:"PagerDuty",glyph:"PD",cat:"incidents",kind:"key",check:"pagerduty",tested:"Live sign-in and read",prefix:"connectors.pagerduty",doc:t+"#incidents-pagerduty-and-incidentio",secrets:[{name:"PAGERDUTY_API_KEY"}],unlocks:["Incidents in DORA's change failure rate and time to restore, instead of labels, reverts and hotfixes","Time to resolve, linked to the deployment before each incident","DevLake's incidents table"],steps:()=>[{text:"In PagerDuty, open Integrations, API Access Keys, and create a read-only key.",href:"https://support.pagerduty.com/main/docs/api-access-keys",action:"PagerDuty's guide"},{text:"Save it as PAGERDUTY_API_KEY below."},{text:`${r} passes it (new installs already have this line):`,file:"stackvitals.yml",code:"pagerduty-token: ${{ secrets.PAGERDUTY_API_KEY }}"},{text:"Optional: only some services, or low urgency too, under Settings below."}]},{id:"incident_io",name:"incident.io",glyph:"io",cat:"incidents",kind:"key",check:"incident_io",tested:"Recorded",prefix:"connectors.incident_io",doc:t+"#incidents-pagerduty-and-incidentio",secrets:[{name:"INCIDENT_IO_API_KEY"}],unlocks:["Incidents in DORA's change failure rate and time to restore, instead of labels, reverts and hotfixes","Time to resolve from the incident's Resolved at","DevLake's incidents table"],steps:()=>[{text:"In incident.io, open Settings, API keys, and create a key that can view incidents.",href:"https://app.incident.io/settings/api-keys",action:"Open incident.io"},{text:"Save it as INCIDENT_IO_API_KEY below."},{text:`${r} passes it (new installs already have this line):`,file:"stackvitals.yml",code:"incident-io-token: ${{ secrets.INCIDENT_IO_API_KEY }}"},{text:"Optional: only this repo's incident types, under Settings below."}]},{id:"sonar",name:"SonarQube or SonarCloud",glyph:"Sq",cat:"code",kind:"nokey",check:"sonar",tested:"Live read of a public SonarCloud project",prefix:"connectors.sonar",doc:t+"#code-quality-sonarqube-or-sonarcloud",secrets:[{name:"SONAR_TOKEN",optional:!0}],unlocks:["The quality gate, read once a day and kept day by day","Bugs, vulnerabilities, code smells, security hotspots, coverage and duplication, with how each moved over a month","Coverage by day beside the delivery numbers, on Delivery's Code quality tab"],steps:()=>[{text:"Set the project key (like myorg_myrepo) under Settings below, and the server's address if it is your own SonarQube."},{text:"A public SonarCloud project needs nothing more. For a private project or a SonarQube server, create a token, save it as SONAR_TOKEN below and pass it:",file:"stackvitals.yml",code:"sonar-token: ${{ secrets.SONAR_TOKEN }}"},{text:"After the next run, the gate and measures show on Delivery's Code quality tab.",to:"#/delivery?tab=quality",action:"Open Code quality"}]},{id:"record",name:"Deployments and incidents from any tool",glyph:"CD",cat:"incidents",kind:"local",tested:"Recorded",doc:t+"#deployments-and-incidents-from-elsewhere",unlocks:["Deployments from Argo CD, Jenkins, Spinnaker, Octopus or a script, counted in DORA like GitHub's own","Incidents from Opsgenie, Rootly or any pager, in change failure rate and recovery","Sending the same id again updates it (a deploy's status, an incident's resolved time)"],steps:e=>[{text:"Each tool sends a repository_dispatch event to this repo with a token that can write its contents; the workflow keeps it on the data branch and the next run counts it. No server of ours is involved."},{text:"From a pipeline step, after the deploy has finished:",file:"Terminal",code:`pip install stackvitals
|
|
5
|
+
stackvitals record deployment ${e||"owner/repo"} --id "jenkins-$BUILD_TAG" --sha "$GIT_COMMIT" --environment production --tool jenkins
|
|
6
|
+
stackvitals record incident ${e||"owner/repo"} --id INC-42 --at 2026-10-29T09:12:00Z --resolved-at 2026-10-29T10:03:00Z`},{text:"Or without StackVitals installed (Spinnaker, Octopus, any script):",file:"Terminal",code:`curl -X POST -H "Authorization: Bearer $TOKEN" https://api.github.com/repos/${e||"owner/repo"}/dispatches \\
|
|
7
|
+
-d '{"event_type":"stackvitals-deployment","client_payload":{"id":"argo-1287","sha":"'"$GIT_SHA"'","finished_at":"2026-10-29T09:00:00Z"}}'`},{text:"Argo CD: a webhook in its notifications engine, subscribed to on-deployed. The ready template and the Jenkins and GitLab lines are in the guide.",href:`${h}${t}#deployments-and-incidents-from-elsewhere`,action:"Ready recipes"},{text:"Workflows set up before this need the repository_dispatch trigger; the current template has it."}]},{id:"bitbucket",name:"Bitbucket Cloud",glyph:"Bb",cat:"code",kind:"local",tested:"Live read of a public repo",doc:t+"#bitbucket-and-azure-devops",unlocks:["Review phases for merged pull requests: first answer from someone else, approvals, merge","DORA from Bitbucket Pipelines' production deployments","Bots (Renovate, Dependabot) left out of people's numbers"],steps:()=>[{text:"Read-only, from your machine or any CI. A public repo needs no token; a private one needs an access token in BITBUCKET_TOKEN:",file:"Terminal",code:`pip install stackvitals
|
|
8
|
+
export BITBUCKET_TOKEN=... # private repos only
|
|
9
|
+
stackvitals delivery workspace/repo --bitbucket`}]},{id:"azure",name:"Azure DevOps",glyph:"Az",cat:"code",kind:"local",tested:"Live read of a public project",doc:t+"#bitbucket-and-azure-devops",unlocks:["Review phases for completed pull requests: first answer, votes, merge","DORA once deployments are sent with stackvitals record (release pipelines sit outside the Git API), or with every merge counted"],steps:()=>[{text:"Read-only, from your machine or any CI. A public project needs no token; a private one needs a PAT with Code read in AZURE_DEVOPS_TOKEN:",file:"Terminal",code:`pip install stackvitals
|
|
10
|
+
export AZURE_DEVOPS_TOKEN=... # private projects only
|
|
11
|
+
stackvitals delivery org/project/repo --azure`},{text:"For deployments, add a step to the release pipeline that sends each one.",to:"#/connections/record",action:"From any tool"}]},{id:"discourse",name:"Discourse",glyph:"Fo",cat:"community",kind:"nokey",check:"discourse",tested:"Live",prefix:"connectors.discourse",doc:t+"#community-channels-discourse-slack-and-discord",unlocks:["How fast the team answers questions asked on the forum, with topics still waiting counted","How many forum questions anyone answered, and how many were solved"],steps:()=>[{text:"Name the forum and, if its staff aren't the only ones answering for the project, who else is, under Settings below."},{text:"No key is needed: its public topics are read, and only times and flags are kept."}]},{id:"slack",name:"Slack support channels",glyph:"Sl",cat:"community",kind:"key",check:"slack",tested:"Live sign-in and channel read",prefix:"connectors.slack",doc:t+"#community-channels-discourse-slack-and-discord",secrets:[{name:"SLACK_BOT_TOKEN"}],unlocks:["How fast the team answers in the support channels, with questions still waiting counted","How many questions anyone answered"],steps:()=>[{text:"Create a Slack app with the channels:history scope, install it, and invite it to each support channel.",href:"https://api.slack.com/apps",action:"Slack apps"},{text:"Save its bot token as SLACK_BOT_TOKEN below."},{text:"Pass it in the workflow:",file:"stackvitals.yml",code:"slack-token: ${{ secrets.SLACK_BOT_TOKEN }}"},{text:"Name the channels and who answers for the project under Settings below (only times and flags are kept)."}]},{id:"discord",name:"Discord support channels",glyph:"Di",cat:"community",kind:"key",check:"discord",tested:"Live sign-in and channel read",prefix:"connectors.discord",doc:t+"#community-channels-discourse-slack-and-discord",secrets:[{name:"DISCORD_BOT_TOKEN"}],unlocks:["How fast the team answers in the support channels, with questions still waiting counted","How many questions anyone answered"],steps:()=>[{text:"Create a Discord bot with View Channel and Read Message History (no message content needed) and add it to the server.",href:"https://discord.com/developers/applications",action:"Discord developers"},{text:"Save its token as DISCORD_BOT_TOKEN below."},{text:"Pass it in the workflow:",file:"stackvitals.yml",code:"discord-token: ${{ secrets.DISCORD_BOT_TOKEN }}"},{text:"Name the channels and who answers for the project under Settings below (only times and flags are kept)."}]},{id:"chat",name:"Chat alerts (Slack, Teams, Discord)",glyph:"Wh",cat:"alerts",kind:"key",check:"webhook",tested:"Live for Slack and Discord, Teams recorded",doc:t+"#chat-slack-microsoft-teams-discord",secrets:[{name:"STACKVITALS_WEBHOOK"},{name:"STACKVITALS_TEAM_WEBHOOKS",optional:!0,multiline:!0}],unlocks:["A message when something newly turns flaky","Delivery alerts when a number crosses its threshold","The weekly digest"],steps:()=>[{text:`Create an incoming webhook: a Slack app's incoming webhook, a Teams Workflows "post to a channel" flow, or a Discord channel webhook.`,href:"https://api.slack.com/messaging/webhooks",action:"Slack's guide"},{text:"Save its address as STACKVITALS_WEBHOOK below."},{text:"Pass it to the workflow:",file:"stackvitals.yml",code:"webhook: ${{ secrets.STACKVITALS_WEBHOOK }}"},{text:"Choose what goes there under Alerts and Weekly digest in Settings.",to:"#/settings"},{text:"Optional, one chat per team: STACKVITALS_TEAM_WEBHOOKS with one line per CODEOWNERS team, and a team's newly flaky tests go to its own chat:",file:"stackvitals.yml",code:"team-webhooks: ${{ secrets.STACKVITALS_TEAM_WEBHOOKS }}\n# secret: @acme/web = https://hooks.slack.com/services/..."}]},{id:"copilot",name:"GitHub Copilot",glyph:"Co",cat:"github",kind:"key",check:"copilot",tested:"Recorded",prefix:"connectors.copilot",doc:t+"#github-copilot-usage-reports",secrets:[{name:"COPILOT_CLIENT_ID",kind:"variable"},{name:"COPILOT_PRIVATE_KEY",multiline:!0}],unlocks:["The org's active users and suggestions accepted, day by day","Pull requests by Copilot, org-wide and in this repo","History past GitHub's own retention, beside AI-assisted outcomes"],steps:e=>[{text:'An org owner registers a private GitHub App for the org, with no webhook, and under Organization permissions sets "Copilot metrics" to Read; then installs it on the org.',href:e?`https://github.com/organizations/${e.split("/")[0]}/settings/apps/new`:"https://docs.github.com/apps/creating-github-apps",action:"Register an App"},{text:"Save its client id as the variable COPILOT_CLIENT_ID and its private key as COPILOT_PRIVATE_KEY, then let the workflow make a token:",file:"stackvitals.yml",code:`- uses: actions/create-github-app-token@v3
|
|
12
|
+
id: copilot
|
|
13
|
+
with:
|
|
14
|
+
client-id: \${{ vars.COPILOT_CLIENT_ID }}
|
|
15
|
+
private-key: \${{ secrets.COPILOT_PRIVATE_KEY }}
|
|
16
|
+
owner: \${{ github.repository_owner }}
|
|
17
|
+
# and in the StackVitals step:
|
|
18
|
+
copilot-token: \${{ steps.copilot.outputs.token }}`},{text:"Optional: another org than this repo's owner, under Settings below."}]},{id:"ai_spend",name:"AI spend and Claude Code use (Anthropic, OpenAI, Cursor)",glyph:"$",cat:"work",kind:"key",check:"ai_spend",tested:"Live for OpenAI; Anthropic and Cursor recorded",prefix:"connectors.ai_spend",doc:t+"#ai-spend",secrets:[{name:"ANTHROPIC_ADMIN_KEY"},{name:"OPENAI_ADMIN_KEY"},{name:"CURSOR_ADMIN_KEY"}],unlocks:["What the AI tools cost each day (Cursor: this billing cycle)","Spend per merged AI-involved pull request, beside its outcomes","Claude Code's daily sessions, lines, commits and pull requests (Anthropic key), beside Cursor's agent requests and accepted lines"],steps:()=>[{text:"Make an admin key for each tool you pay for (any one is enough): an Anthropic Admin API key in the Claude Console's organization settings, an OpenAI admin key in its organization settings, a Cursor admin API key in its team settings."},{text:"Save each as a repository secret below, then add these lines to the StackVitals step's with: in the workflow:",file:"stackvitals.yml",code:"anthropic-admin-key: ${{ secrets.ANTHROPIC_ADMIN_KEY }}\nopenai-admin-key: ${{ secrets.OPENAI_ADMIN_KEY }}\ncursor-admin-key: ${{ secrets.CURSOR_ADMIN_KEY }}"}]},{id:"traffic",name:"Traffic history",glyph:"Tr",cat:"github",kind:"key",doc:"install.md",example:!0,secrets:[{name:"TRAFFIC_CLIENT_ID",kind:"variable"},{name:"TRAFFIC_PRIVATE_KEY",multiline:!0}],unlocks:["Views, clones and referrers kept past GitHub's 14 days"],steps:()=>[{text:"Create your own GitHub App with the repository permission Administration: read, and install it on the repo.",href:"https://docs.github.com/apps/creating-github-apps",action:"GitHub's guide"},{text:"Store its id and private key, then pass a token from actions/create-github-app-token:",file:"stackvitals.yml",code:`- uses: actions/create-github-app-token@v3
|
|
19
|
+
id: app
|
|
20
|
+
with:
|
|
21
|
+
client-id: \${{ vars.TRAFFIC_CLIENT_ID }}
|
|
22
|
+
private-key: \${{ secrets.TRAFFIC_PRIVATE_KEY }}
|
|
23
|
+
# and in the StackVitals step:
|
|
24
|
+
traffic-token: \${{ steps.app.outputs.token }}`}]},{id:"triage",name:"Model triage (Gemini)",glyph:"Ai",cat:"ai",kind:"key",check:"triage",tested:"Live",prefix:"ci.triage",doc:"triage.md",example:!0,secrets:[{name:"GEMINI_API_KEY"}],unlocks:["A model's view on up to 3 failures a run that history can't decide","Shown beside the verdict, never in it"],steps:()=>[{text:"Create a free Google AI Studio key (no card).",href:"https://aistudio.google.com/apikey",action:"Google AI Studio"},{text:"Save it as GEMINI_API_KEY below. New installs already pass it:",file:"stackvitals.yml",code:"triage-key: ${{ secrets.GEMINI_API_KEY }}"},{text:"Pick the provider under Settings below. A private repo's logs are sent only with allow_private on."}]},{id:"gitlab",name:"GitLab (CI and merge requests)",glyph:"GL",cat:"ci",kind:"key",check:"gitlab",tested:"Live reading and token check; the job tested against a stand-in API",doc:t+"#gitlab",secrets:[{name:"GITLAB_TOKEN",kind:"gitlab"}],unlocks:["Flaky jobs, slow jobs and re-run share for GitLab pipelines","History in the project's stackvitals-data branch, CI Health on GitLab Pages","One note on a failed merge request pipeline","Delivery for merge requests: review phases, and DORA from the project's production deployments"],steps:()=>[{text:"In .gitlab-ci.yml, include the StackVitals job:",file:".gitlab-ci.yml",code:`include:
|
|
25
|
+
- remote: https://raw.githubusercontent.com/stackvitals/stackvitals/v0/templates/gitlab/stackvitals.yml`},{text:"Add a masked CI/CD variable GITLAB_TOKEN in GitLab: a project access token with the api and write_repository scopes."},{text:"Preview: until the v0 tag exists, use main in the URL and set the STACKVITALS_REF variable to main."},{text:"Read-only from your machine instead:",file:"Terminal",code:"stackvitals ci gitlab group/project"},{text:"Delivery from merge requests and deployments (gitlab.com shows merge request notes only with GITLAB_TOKEN, even on public projects):",file:"Terminal",code:"stackvitals delivery group/project --gitlab"}]},{id:"otherci",name:"Test reports from Jenkins, CircleCI, Buildkite",glyph:"Ts",cat:"ci",kind:"local",tested:"Recorded",doc:t+"#other-ci-systems",unlocks:["Flaky tests, failure groups and monitors for tests that run outside GitHub Actions"],steps:()=>[{text:"At the end of the job, with STACKVITALS_TOKEN set to a token that can write the repo:",file:"Terminal",code:`pip install stackvitals
|
|
26
|
+
stackvitals ci upload --repo owner/name --sha "$SHA" --branch "$BRANCH" --run-id "$BUILD_ID" --provider jenkins test-results/*.xml`}]},{id:"agents",name:"AI agents (MCP)",glyph:"Ag",cat:"ai",kind:"local",doc:"modules.md",unlocks:['Agents check CI history before "fixing" a flaky test',"Who should review, what to fix first, package checks","Investigation prompts per failure group"],steps:()=>[{text:"Pick your agent and copy its config on the Agents page.",to:"#/agents",action:"Open Agents"}]},{id:"s3",name:"S3-compatible storage",glyph:"S3",cat:"data",kind:"key",check:"s3",doc:"install.md",example:!0,secrets:[{name:"S3_KEY_ID"},{name:"S3_SECRET"}],unlocks:["History in your own bucket (AWS S3, Cloudflare R2, MinIO)","For very busy repos and big orgs"],steps:()=>[{text:"The bucket service must support replace-only-if-unchanged writes (If-Match). Switching starts a fresh history."},{text:"Save an access key that can read, write, delete and list the prefix as the two secrets below."},{text:"Set the storage inputs, and publish with pages deploy or artifact:",file:"stackvitals.yml",code:`storage: s3://my-bucket/stackvitals
|
|
27
|
+
s3-endpoint: https://<account>.r2.cloudflarestorage.com
|
|
28
|
+
s3-region: auto
|
|
29
|
+
s3-key-id: \${{ secrets.S3_KEY_ID }}
|
|
30
|
+
s3-secret: \${{ secrets.S3_SECRET }}
|
|
31
|
+
pages: artifact`},{text:"stackvitals ui and sql, Explore, the MCP server and the Portal org view don't read a bucket yet."}]},{id:"devlake",name:"DevLake and Postgres export",glyph:"DL",cat:"data",kind:"local",tested:"Recorded",doc:"scaling.md",unlocks:["DevLake's own DORA dashboard SQL on your data","Any SQL over every repo's tables","Your tables in Neon, Supabase or any Postgres"],steps:()=>[{text:"Export DevLake's tables with its DORA SQL, or query the summaries directly:",file:"Terminal",code:`stackvitals export owner/repo --format devlake --out ./devlake
|
|
32
|
+
stackvitals sql --repo owner/repo "select role, count(*) from prs group by role"`}]},{id:"otel",name:"OpenTelemetry export",glyph:"OT",cat:"data",kind:"local",tested:"Recorded",doc:"modules.md",unlocks:["CI runs, jobs and steps as traces","OTLP JSON for Grafana Tempo, Honeycomb, Datadog or any collector","Failed and flaky tests as events with --tests"],steps:()=>[{text:"Export from your machine; the file is written locally and sent nowhere:",file:"Terminal",code:"stackvitals export owner/repo --format otel --tests"}]},{id:"backstage",name:"Backstage catalog",glyph:"Bs",cat:"data",kind:"builtin",tested:"Live",doc:"modules.md",unlocks:["Each repo's catalog-info.yaml as a typed catalog in Portal","Owners checked against CODEOWNERS","portal/entities.yaml with a Component for repos without one"],steps:()=>[{text:"Portal reads catalog-info.yaml files by itself (Backstage's format, which Port and Cortex also read)."},{text:"To see Portal's view in Backstage, register the URL of portal/entities.yaml on the data branch as one location."}]}];function A(e,s){return s[e.check||e.id]||s[e.id]||null}function I(e,s){let a={};for(let n of e?.settings||[])s&&n.key.startsWith(s+".")&&(a[n.key.slice(s.length+1)]=n.default);return a}function N(e,s){let a=e.prefix?m(s.settings?.values,e.prefix):void 0;return y(e,A(e,s.entries),s.secrets,g(a,I(s.settings,e.prefix)))}function z(e,s,a,n){if(e.id==="github")return`${Object.keys(n.app.modules||{}).length} modules ran; last run ${o(u(n.app))}.`;if(s==="builtin")return e.id==="backstage"?"Read by Portal on its own; nothing to add.":"Works on its own; nothing to add.";if(s==="failed")return a?.error||a?.check?.detail||"The last check failed.";let c=k(e,n.secrets);if(s==="recorded")return`History is kept, but the repo no longer has ${c.join(" and ")}, so nothing new is read.`;if(s==="key")return a?.expiring?`The key expires on ${p(a.key_expires)}: create a new one and update the secret.`:c.length?`Missing ${c.join(" and ")}.`:"Settings are filled in; the key isn't there yet.";if(s==="connected"){if(!a?.as_of)return a?.check?.ok?`The last test passed ${o(a.check.checked_at)}.`:"Everything is in place; the next run reads it.";let l=Object.values(a.rows||{}).reduce((f,b)=>f+b,0);return`Last read ${o(a.as_of)}${l?`, ${d(l,"record")} kept`:""}${a.complete===!1?", still catching up":""}.`}return e.kind==="local"?"Runs from your machine or your CI; nothing here shows whether it is set up.":"Not set up yet."}export{w as BRANDS,P as CONNS,D as LOGOS,R as PERMS,z as detail,A as entryOf,N as statusFor};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{a as e,b as o,c as r}from"./chunk-MAPYGK3P.js";import{d as t}from"./chunk-G7NGB5UX.js";t();var n=[o,{id:"ascent",name:"Ascent",note:"Three bars climbing",body:'<rect x="7" y="17" width="4.6" height="8" rx="2.2" fill="F"/><rect x="13.7" y="12" width="4.6" height="13" rx="2.2" fill="F"/><rect x="20.4" y="7" width="4.6" height="18" rx="2.2" fill="A"/>'},{id:"gauge",name:"Gauge",note:"A dial reading high",body:e("M9.6 23.4A9 9 0 1 1 22.4 23.4","F",2.6,' opacity=".4"')+e("M9.6 23.4A9 9 0 0 1 22.4 10.6","A",2.8)+e("M16 17 20.6 12.4","F",2.4)+'<circle cx="16" cy="17" r="2.3" fill="F"/>'},{id:"ring",name:"Segments",note:"A ring of checks, most of them green",body:'<circle cx="16" cy="16" r="9" fill="none" stroke="F" stroke-width="3" opacity=".35" stroke-dasharray="5.07 2" transform="rotate(-81 16 16)"/><circle cx="16" cy="16" r="9" fill="none" stroke="A" stroke-width="3" stroke-dasharray="5.07 2 5.07 2 5.07 2 5.07 2 5.07 30" transform="rotate(-81 16 16)"/><circle cx="16" cy="16" r="3" fill="F"/>'},{id:"iso",name:"Iso block",note:"An isometric stack, top face lit",body:'<path d="M16 6 25 10.5 16 15 7 10.5Z" fill="A"/><path d="M7 10.5 16 15v11l-9-4.5Z" fill="F"/><path d="M16 15l9-4.5v11L16 26Z" fill="F" opacity=".72"/>'+e("M7 16 16 20.5 25 16","T",1.4)},{id:"cross",name:"Vital cross",note:"Five tiles, the heart one lit",body:'<rect x="13" y="5.5" width="6" height="6" rx="1.8" fill="F"/><rect x="5.5" y="13" width="6" height="6" rx="1.8" fill="F"/><rect x="13" y="13" width="6" height="6" rx="1.8" fill="A"/><rect x="20.5" y="13" width="6" height="6" rx="1.8" fill="F"/><rect x="13" y="20.5" width="6" height="6" rx="1.8" fill="F"/>'},{id:"mono",name:"Monogram",note:"S and V, the V in green",body:e("M14.6 10.5h-4.4a2.8 2.8 0 0 0 0 5.6h2.6a2.8 2.8 0 0 1 0 5.6H7.6")+e("M17.4 10.5 21 21.7l3.6-11.2","A")},{id:"keystone",name:"Keystone",note:"A package holding layered lines",body:e("M16 5.8 24.8 10.9v10.2L16 26.2l-8.8-5.1V10.9Z","F",2.2)+e("M11.6 13.4h8.8","A",2.6)+e("M11.6 17h8.8")+e("M11.6 20.6h8.8","F",2.6,' opacity=".55"')},{id:"beacon",name:"Beacon",note:"Layers with a signal rising above",body:e("M7 19.8 16 24.4l9-4.6")+e("M7 14.8 16 19.4l9-4.6")+'<circle cx="16" cy="9" r="3.3" fill="A"/>'},{id:"summit",name:"Summit",note:"Three chevrons pointing up",body:e("M8.5 24 16 18.4 23.5 24","F",2.6,' opacity=".55"')+e("M8.5 18.6 16 13 23.5 18.6")+e("M8.5 13.2 16 7.6 23.5 13.2","A",2.8)}];function h(l){return n.find(i=>i.id===l)||n.find(i=>i.id===r)}export{n as LOGOS,h as logoById};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import{a as j,b as Q,c as U,f as Ne}from"./chunk-CTKDYZMG.js";import{f as Oe}from"./chunk-PABICGBL.js";import{d as he,i as Ae,j as Ue}from"./chunk-GQYFN4PE.js";import{d as Z}from"./chunk-S654BBEP.js";import{a as Ie,b as pe,d as Pe}from"./chunk-ASYNLVOP.js";import{a as A}from"./chunk-6RLVD2DT.js";import{f as Ee}from"./chunk-T7QVTNXF.js";import{a as Ce}from"./chunk-RPXHAG6F.js";import{d as ue}from"./chunk-4WKQTWUC.js";import{k as _e}from"./chunk-VQ5YXO54.js";import{c as z,d as je,e as Y,h as ce,i as C}from"./chunk-76WAVKUG.js";import{b as qe,c as de,d as M,e as L,h as Fe}from"./chunk-VWKSMFWJ.js";import{I as N,N as Se,O as _,P as K,S as xe,a as T,c as R,d as V,g as ie,h as oe,i as D,o as Te,r as X,w as e,x as le,z as x}from"./chunk-GT4EAKAO.js";import{d as P}from"./chunk-G7NGB5UX.js";P();P();P();var q=".github/workflows/stackvitals-tests.yml",se="Tests (StackVitals)",ge="stackvitals-tests",B=["retry","burnin","impact","shards","quarantine","validate"],Le=["pytest","jest","vitest","go","maven","gradle","dotnet","rspec","playwright"],nt="actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4",rt="actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5",at="actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4",it="actions/setup-java@b843ebf9b913146b38da2eaa7aeddf76074ae1ad # v6.1.0",ot="actions/setup-dotnet@a98b56852c35b8e3190ac28c8c2271da59106c68 # v6.0.0",lt="ruby/setup-ruby@7f797815d8adceb1c412e7abefdd1ab4abc47a5f # v1.335.0",Be="actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4",fe=[`- uses: ${at}`," with:"," node-version: 22"," cache: npm"],Je=t=>[`- uses: ${it}`," with:"," distribution: temurin"," java-version: 21",` cache: ${t}`],me='case "$a" in */*|*.java|*.kt|*.cs) b=$(basename "$a"); n="${b%.*}" ;; *) n="$a" ;; esac',S={pytest:{id:"pytest",name:"pytest",lang:"Python",setup:[`- uses: ${rt}`," with:",' python-version: "3.12"'," cache: pip"],install:"if [ -f requirements.txt ]; then pip install -r requirements.txt; else pip install -e .; fi; pip install pytest",reports:"reports/*.xml",tests:"tests/**/test_*.py",run:['pytest "$@" --junitxml=reports/junit.xml{X}'],rerun:["pytest --lf --junitxml=reports/junit.xml{X}"],shardFlags:"--py-paths",check:"The install line: requirements.txt if there is one, else the package itself."},jest:{id:"jest",name:"Jest",lang:"JavaScript",setup:fe,install:"npm ci",reports:"reports/*.json",tests:"src/**/*.test.*",run:['npx jest --ci --json --outputFile=reports/jest.json{X} "$@"'],rerun:["npx jest --ci --onlyFailures --json --outputFile=reports/jest.json{X}"],shardFlags:"",check:"npm ci needs a package-lock.json; change it for yarn or pnpm."},vitest:{id:"vitest",name:"Vitest",lang:"JavaScript",setup:fe,install:"npm ci",reports:"reports/*.xml",tests:"src/**/*.test.*",run:['npx vitest run --reporter=default --reporter=junit --outputFile.junit=reports/vitest.xml{X} "$@"'],rerun:null,shardFlags:"",check:"npm ci needs a package-lock.json; change it for yarn or pnpm. Vitest can't re-run only failed tests, so a retry runs the same tests again."},go:{id:"go",name:"go test",lang:"Go",setup:[`- uses: ${Ae}`," with:"," go-version-file: go.mod"],install:"go mod download",reports:"reports/*.json",tests:"**/*_test.go",run:["pkgs=()",'for a in "$@"; do case "$a" in *.go) pkgs+=("./$(dirname "$a")") ;; *) pkgs+=("$a") ;; esac; done',"[ ${#pkgs[@]} -gt 0 ] || pkgs=(./...)",`go test -count=1 -json{X} $(printf '%s\\n' "\${pkgs[@]}" | sort -u) > reports/go.json || { grep '"Action":"fail"' reports/go.json || true; exit 1; }`],rerun:[`tests=$(grep '"Action":"fail"' reports/go.json | grep -o '"Test":"[^"/]*' | cut -d'"' -f4 | sort -u | paste -sd'|' -)`,`pkgs=$(grep '"Action":"fail"' reports/go.json | grep '"Test":' | grep -o '"Package":"[^"]*' | cut -d'"' -f4 | sort -u)`,'[ -n "$tests" ] || exit 1',`go test -count=1 -json{X} -run "^($tests)$" $pkgs > reports/go.json || { grep '"Action":"fail"' reports/go.json || true; exit 1; }`],shardFlags:"",check:"Test results go to reports/go.json; failures are printed in the log."},maven:{id:"maven",name:"Maven (Surefire)",lang:"Java or Kotlin",setup:Je("maven"),install:"",reports:"**/target/surefire-reports/*.xml",tests:"**/src/test/**/*Test.*",run:["names=()",'for a in "$@"; do '+me+'; names+=("$n"); done','if [ ${#names[@]} -gt 0 ]; then set -- "-Dtest=$(IFS=,; echo "${names[*]}")" -Dsurefire.failIfNoSpecifiedTests=false; fi','mvn -B test{X} "$@"'],rerun:null,shardFlags:"",check:"Java 21: change java-version if the project needs another. Maven can't re-run only failed tests, so a retry runs the same tests again."},gradle:{id:"gradle",name:"Gradle",lang:"Java or Kotlin",setup:Je("gradle"),install:"",reports:"**/build/test-results/test/*.xml",tests:"**/src/test/**/*Test.*",run:["args=()",'for a in "$@"; do '+me+'; args+=(--tests "$n"); done','./gradlew test --continue{X} "${args[@]}"'],rerun:null,shardFlags:"",check:"Uses ./gradlew test; an Android project may want testDebugUnitTest. Gradle can't re-run only failed tests, so a retry runs the same tests again."},dotnet:{id:"dotnet",name:"dotnet test",lang:"C#",setup:[`- uses: ${ot}`," with:"," dotnet-version: 10.0.x"],install:"dotnet restore",reports:"reports/*.trx",tests:"**/*Tests.cs",run:['filter=""','for a in "$@"; do '+me+'; filter="${filter:+$filter|}FullyQualifiedName~$n"; done','if [ -n "$filter" ]; then set -- --filter "$filter"; fi','dotnet test --logger trx --results-directory reports{X} "$@"'],rerun:null,shardFlags:"",check:"The .NET 10 SDK builds older targets too. dotnet test can't re-run only failed tests, so a retry runs the same tests again."},rspec:{id:"rspec",name:"RSpec",lang:"Ruby",setup:[`- uses: ${lt}`," with:"," bundler-cache: true"],install:"",reports:"reports/*.xml",tests:"spec/**/*_spec.rb",run:["mkdir -p tmp",`echo 'RSpec.configure { |c| c.example_status_persistence_file_path = "tmp/rspec-status.txt" }' > "$RUNNER_TEMP/sv_rspec.rb"`,"paths=()",'for a in "$@"; do case "$a" in */*|*.rb) paths+=("$a") ;; *) paths+=("$(echo "$a" | tr . /).rb") ;; esac; done','bundle exec rspec --require "$RUNNER_TEMP/sv_rspec.rb" --format progress --format RspecJunitFormatter --out reports/rspec.xml{X} "${paths[@]}"'],rerun:['bundle exec rspec --require "$RUNNER_TEMP/sv_rspec.rb" --only-failures --format progress --format RspecJunitFormatter --out reports/rspec.xml{X}'],shardFlags:"",check:"The Gemfile needs rspec_junit_formatter (it writes the report); Ruby comes from .ruby-version."},playwright:{id:"playwright",name:"Playwright",lang:"JavaScript",setup:fe,install:"npm ci && npx playwright install --with-deps",reports:"reports/*.xml",tests:"tests/**/*.spec.*",run:['PLAYWRIGHT_JUNIT_OUTPUT_NAME=reports/playwright.xml npx playwright test --reporter=line,junit{X} "$@"'],rerun:["PLAYWRIGHT_JUNIT_OUTPUT_NAME=reports/playwright.xml npx playwright test --last-failed --reporter=line,junit{X}"],shardFlags:"",check:"npm ci needs a package-lock.json; the browsers install on each run."}},O={retry:["Re-run only failed tests","When tests fail, only those run again in the same job, so one flake doesn't fail the build; a test StackVitals knows is broken fails at once."],burnin:["Catch new flaky tests on pull requests","Runs the tests a pull request adds or changes several times and fails if one both passes and fails, before it merges."],impact:["Run only affected tests on pull requests","Runs only the test files a change can affect, learned from this repo's own history; build or settings changes run everything."],shards:["Split into even shards","Splits the tests into parallel jobs by their recorded times, so every shard ends at about the same time."],quarantine:["Skip quarantined tests","Known flaky tests on the quarantine list still run and report, but can't fail the build."],validate:["Check the test reports","Reads each report the way StackVitals does and warns about missing names, times or counts; it never fails the build."]},b=(t,n)=>t.features.includes(n),E=t=>`'${t.replace(/'/g,"'\\''")}'`,ee=(t,n)=>t.map(a=>a.replace("{X}",n.trim()?" "+n.trim():""));function be(t,n="",a=!1){let r=S[t],c=["#!/usr/bin/env bash","set -eu",...a&&[...r.run,...r.rerun||[]].some(o=>o.includes("RUNNER_TEMP"))?['RUNNER_TEMP="${RUNNER_TEMP:-${TMPDIR:-/tmp}}"']:[],"mkdir -p reports"];return{run:[...c,...ee(r.run,n)],rerun:r.rerun?[...c,...ee(r.rerun,n)]:null}}function ke(t,n=""){let a=S[t];if(a.run.length!==1)return{all:"run-tests",some:"run-tests {files}",failed:a.rerun?"rerun-failed":"run-tests",script:!0};let r=ee(a.run,n)[0];return{all:r.replace(/ ?"\$@"/,""),some:r.replace('"$@"',"{files}"),failed:a.rerun?ee(a.rerun,n)[0]:r.replace(/ ?"\$@"/,""),script:!1}}function ut(t){let n=S[t.runner],a=E(n.reports),r=b(t,"impact")||b(t,"shards")?"run-tests $FILES":"run-tests",s=r;b(t,"retry")&&(s=`stackvitals ci retry --reports ${a} -- ${s} --then ${n.rerun?"rerun-failed":r}`),b(t,"quarantine")&&(s=`stackvitals ci quarantine --reports ${a} -- ${s}`);let c=[];return b(t,"impact")&&c.push(`stackvitals ci impact --base "origin/$BASE" --tests ${E(t.tests)}`),b(t,"shards")&&c.push(`stackvitals ci shards "$GITHUB_REPOSITORY" --n ${t.shards} --index "$SHARD"${n.shardFlags?" "+n.shardFlags:""}`+(["pytest","jest","vitest","playwright"].includes(t.runner)?` --files ${E(t.tests)}`:"")),{test:s,pick:c,burnin:`stackvitals ci burn-in --base "origin/$BASE" --times ${t.times} --reports ${a} -- run-tests {files}`,validate:`stackvitals ci validate ${a}`}}function te(t){let n=S[t.runner],a=t.comments!==!1,r=[],s=(p,k,$)=>r.push(" ".repeat(p)+k+(a&&$?` # ${$}`:"")),c=(p,k)=>{a&&r.push(" ".repeat(p)+"# "+k)},o=(p,k)=>{for(let $ of k)r.push($?" ".repeat(p)+$:"")},u=(p,k)=>s(p,"- uses: "+(a?k:k.split(" # ")[0])),d=ut(t),m=t.features.length>0,f=b(t,"burnin")||b(t,"impact"),h=b(t,"retry")||b(t,"burnin")||b(t,"impact"),i=b(t,"shards")?Math.max(2,Math.min(16,Math.round(t.shards))):0,g=b(t,"impact")||i>0;if(a){r.push(`# Made in the StackVitals app (CI Health, "Set up in your CI") for ${t.repo}: runs your tests with ${n.name}`),r.push("# and keeps the test reports, so StackVitals can tell flaky tests from real failures.");for(let p of B)b(t,p)&&r.push(`# ${O[p][0]}: ${O[p][1]}`)}s(0,`name: ${se}`),s(0,"on:"),s(2,"push:"),s(4,`branches: [${he(t.branch)}]`),s(2,"pull_request:"),s(2,"workflow_dispatch:"),s(0,"permissions:"),s(2,"contents: read","check out the code; read the quarantine list on the stackvitals-data branch"),s(2,"actions: read","read the test times recorded in earlier runs (shards)"),s(0,"concurrency:"),s(2,"group: tests-${{ github.ref }}"),s(2,"cancel-in-progress: ${{ github.event_name == 'pull_request' }}","a new push to a pull request stops its older run"),s(0,"jobs:");let F=()=>{u(6,nt),f&&(s(8,"with:"),s(10,"fetch-depth: 0","the whole history, to compare a pull request with its base")),h&&(s(6,"- name: Read what StackVitals learned"),c(8,"Known broken and flaky tests and the learned test map, from the data branch; without it the commands still run."),s(8,"run: |"),s(10,`git fetch --no-tags${f?"":" --depth=1"} origin stackvitals-data:refs/remotes/origin/stackvitals-data || echo "No stackvitals-data branch yet."`));for(let[k,$]of n.setup.entries())s(6,k===0?$.replace(/^- uses: (.*)$/,(ne,H)=>"- uses: "+(a?H:H.split(" # ")[0])):$);t.install.trim()&&(s(6,"- name: Install dependencies"),s(8,"run: |"),s(10,t.install.trim())),m&&r.push(...Ue(6,a)),s(6,"- name: Write the test commands"),c(8,`run-tests runs the files it is given (all tests with none) and writes ${n.reports}${n.rerun&&b(t,"retry")?"; rerun-failed runs only what failed":""}.`),s(8,"run: |");let p=be(t.runner,t.extra);o(10,['mkdir -p "$RUNNER_TEMP/bin"',`cat > "$RUNNER_TEMP/bin/run-tests" <<'EOF'`,...p.run,"EOF"]),p.rerun&&b(t,"retry")&&o(10,[`cat > "$RUNNER_TEMP/bin/rerun-failed" <<'EOF'`,...p.rerun,"EOF"]),o(10,['chmod +x "$RUNNER_TEMP"/bin/*','echo "$RUNNER_TEMP/bin" >> "$GITHUB_PATH"'])};if(s(2,"tests:"),i&&(s(4,`name: tests (shard \${{ matrix.shard }} of ${i})`),s(4,"strategy:"),s(6,"fail-fast: false"),s(6,"matrix:"),s(8,`shard: [${Array.from({length:i},(p,k)=>k+1).join(", ")}]`)),s(4,"runs-on: ubuntu-latest"),s(4,"steps:"),F(),g){s(6,"- name: Pick the tests"),s(8,"id: pick"),s(8,"env:"),s(10,"GITHUB_TOKEN: ${{ github.token }}"),s(10,"EVENT: ${{ github.event_name }}"),s(10,"BASE: ${{ github.base_ref }}"),i&&s(10,"SHARD: ${{ matrix.shard }}"),s(8,"run: |");let p=['files=""',"skip=false"];b(t,"impact")&&p.push('if [ "$EVENT" = pull_request ]; then',` if picked=$(${d.pick[0]}); then`,' if [ -z "$picked" ]; then echo "No test can be affected by this change, so none run."; skip=true',' elif [ "$picked" != all ]; then files="$picked"; fi',' else echo "Test impact could not run; every test runs."; fi',"fi"),i&&p.push('if [ "$skip" = false ] && [ -z "$files" ]; then',` if out=$(${d.pick[d.pick.length-1]}); then`,' if [ -n "$out" ]; then files="$out"; else skip=true; fi',' else echo "No recorded test times yet: shard 1 runs every test this time."; [ "$SHARD" = 1 ] || skip=true; fi',...b(t,"impact")?['elif [ -n "$files" ] && [ "$SHARD" != 1 ]; then skip=true']:[],"fi"),p.push('echo "files=$files" >> "$GITHUB_OUTPUT"','echo "skip=$skip" >> "$GITHUB_OUTPUT"'),o(10,p)}let v=g?"steps.pick.outputs.skip != 'true'":"";return s(6,"- name: Run the tests"),v&&s(8,`if: ${v}`),(g||b(t,"quarantine"))&&(s(8,"env:"),g&&s(10,"FILES: ${{ steps.pick.outputs.files }}"),b(t,"quarantine")&&s(10,"GITHUB_TOKEN: ${{ github.token }}","reads the quarantine list")),s(8,"run: |"),s(10,d.test),b(t,"validate")&&(s(6,"- name: Check the test reports"),s(8,`if: always()${v?` && ${v}`:""}`),s(8,"continue-on-error: true","a report problem is a warning, never a failed build"),s(8,"run: |"),s(10,d.validate)),s(6,"- name: Keep the test reports"),c(8,"StackVitals reads test reports from artifacts whose name says test-results."),s(8,`if: always()${v?` && ${v}`:""}`),s(8,"uses: "+(a?Be:Be.split(" # ")[0])),s(8,"with:"),s(10,`name: test-results${i?"-${{ matrix.shard }}":""}`),s(10,`path: ${he(n.reports)}`),s(10,"if-no-files-found: ignore"),s(10,"retention-days: 14"),b(t,"burnin")&&(s(6,`- name: Run new and changed tests ${t.times} times`),c(8,"On pull requests: fails when one of them both passes and fails (after the reports above are kept)."),s(8,`if: always() && github.event_name == 'pull_request'${i?" && matrix.shard == 1":""}`),s(8,"env:"),s(10,"BASE: ${{ github.base_ref }}"),s(8,"run: |"),s(10,d.burnin)),r.join(`
|
|
2
|
+
`)+`
|
|
3
|
+
`}function He(t){let n=te(t),a=pe(t.repo,t.branch,q,n);if(!a.paste)return{...a,comments:!0};let r=pe(t.repo,t.branch,q,te({...t,comments:!1}),n);return{...r,comments:!!r.paste}}var ct=[["pytest",/\bpytest\b|\bpython\b|\btox\b|\bnox\b|\bpy3\d*\b/i],["vitest",/\bvitest\b/i],["jest",/\bjest\b/i],["playwright",/\bplaywright\b/i],["go",/\bgo[- ]?test\b|\bgolang(ci)?\b|\bgotestsum\b/i],["gradle",/gradle|\bassemble|\bdetekt\b|\bktlint\b|connectedAndroidTest|\bandroid\b/i],["maven",/\bmvn\b|\bmaven\b|\bsurefire\b/i],["dotnet",/\bdotnet\b|\.net\b|\bxunit\b|\bnunit\b|\bmstest\b/i],["rspec",/\brspec\b|\bruby\b|\brails\b/i]],dt=[["pytest",/\.py::|(^|[/.])test_\w+\.py|::test_\w+/],["go",/^Test[A-Z0-9_]\w*(\/|$)|::Test[A-Z0-9_]\w*(\/|$)/],["vitest",/\.(test|spec)\.[cm]?[jt]sx? > /],["jest",/\.(test|spec)\.[cm]?[jt]sx?(::| )/],["playwright",/ › /],["rspec",/_spec\.rb|^\.\/spec\//],["maven",/^([a-z_]\w*\.)+[A-Z]\w*Tests?\.\w+$|^[A-Z]\w*Test\.\w+$/],["dotnet",/^([A-Z]\w*\.){2,}[A-Z]\w*Tests?\.\w+$/]];function We(t,n){let a={},r={},s=(o,u,d,m)=>{a[o]=(a[o]||0)+u;let f=r[o]||(r[o]={ids:[],names:[]});f[d].length<2&&!f[d].includes(m)&&f[d].push(m)};for(let o of t.slice(0,200))for(let[u,d]of dt)if(d.test(o)){s(u,3,"ids",o);break}for(let o of n)for(let[u,d]of ct)d.test(o)&&s(u,2,"names",o);a.maven&&(a.gradle||0)>0&&(a.gradle+=a.maven,r.gradle.ids=r.maven.ids,delete a.maven);let c=Object.entries(a).sort((o,u)=>u[1]-o[1])[0];return c?{runner:c[0],...r[c[0]]}:{runner:null,ids:[],names:[]}}function Ge(t){return t?Math.max(2,Math.min(8,Math.ceil(t/5))):2}var ye=oe(null);function we(t){ye.set(null),ye.set(t),Ne("ci-setup")}var pt=/test|unit|integration|e2e|spec|pytest|jest|vitest|playwright|rspec|surefire|connected/i,Ve=t=>(t||"").split("/").pop().replace(/\.ya?ml$/,""),De=oe(null),Xe=t=>We([...t.tests||[],...t.new_tests||[]].map(n=>n.id||"").concat((t.slow_tests||[]).map(n=>n.id)).filter(Boolean),[...(t.jobs||[]).map(n=>`${Ve(n.workflow)} / ${n.job}`),...(t.tests||[]).map(n=>n.suite||"")]);function Ke(t,n){let a=D(De),r=ie(()=>Xe(n).runner,[n]);return a&&a.repo===t.repo?a:{runner:r,tests:r?S[r].tests:null}}function ht(t,n,a,r,s){let c=[["Read any repo's CI from your machine",`stackvitals ci report ${t} --tests`,"Nothing installed in the repo; read-only."],["Read a GitLab project","stackvitals ci gitlab group/project","The same flaky and slow job checks for GitLab pipelines (GITLAB_TOKEN if private)."]];if(!a)return c;let o=S[a],u=ke(a,s),d=E(o.reports);return[["Re-run only the failed tests",`stackvitals ci retry --reports ${d} -- ${u.all} --then ${u.failed}`,"Inside the same job; a test the data branch calls broken fails the job at once instead of being retried."+(o.rerun?"":` ${o.name} can't re-run only failed tests, so the retry runs the same tests again.`)],["Catch a new flaky test before it merges",`stackvitals ci burn-in --base origin/${n} --times 5 --reports ${d} -- ${u.some}`,"Runs the tests a pull request adds or changes several times and fails when one both passes and fails. A known flaky test that passes every repeat is shown as fixed, with the chance it was luck."],["Run only the tests a change can affect",`stackvitals ci impact --base origin/${n} --tests ${E(r)}`,'Prints the test files to run, or "all" when a build or settings file changed. Uses the learned map from the data branch.'],["Split tests into even shards",`stackvitals ci shards ${t} --n 4 --index 1${o.shardFlags?" "+o.shardFlags:""}${["pytest","jest","vitest","playwright"].includes(a)?` --files ${E(r)}`:""}`,"By the times recorded on the default branch; one shard per matrix job."],["Check test reports before CI does",`stackvitals ci validate ${d}`,"Read as the Action reads them; warns about missing file names, durations or counts that don't add up."],["Skip quarantined tests",`stackvitals ci quarantine --reports ${d} -- ${u.all}`,"Passes when only quarantined (known flaky) tests failed."],...c]}function ft(t){return`https://github.com/settings/personal-access-tokens/new?${new URLSearchParams({name:"StackVitals tests",description:`Lets the StackVitals app open one pull request in ${t}`,target_name:t.split("/")[0],expires_in:"7",contents:"write",workflows:"write",pull_requests:"write"})}`}function ze({app:t,ci:n}){let a=n,r=t.default_branch||"main",c=(n.jobs||[]).map(l=>({name:`${Ve(l.workflow)} / ${l.job}`,min:(l.median_s||0)/60})).filter(l=>pt.test(l.name)),o=ie(()=>Xe(n),[n]),u=c.reduce((l,y)=>Math.max(l,y.min),0)||null,d=[...n.tests||[],...n.jobs||[]].filter(l=>l.state==="flaky").length,m=(n.tests||[]).filter(l=>l.state==="flaky").length,f=a.impact,[h,i]=R(o.runner||""),[g,F]=R(()=>B.filter(l=>({retry:!0,validate:!0,quarantine:d>0,burnin:m>0,impact:(f?.recall??0)>=.9,shards:(u??0)>=10})[l])),[v,p]=R({}),[k,$]=R(""),[ne,H]=R(Ge(u)),[ve,et]=R(5),W=D(ye);V(()=>{W&&F(l=>l.includes(W)?l:B.filter(y=>y===W||l.includes(y)))},[W]);let w=h?S[h]:null,J=w?{repo:t.repo,branch:r,runner:h,features:g,install:v.install??w.install,tests:v.tests??w.tests,extra:k,shards:ne,times:ve}:null,re=v.tests??(w?w.tests:"");V(()=>{De.set({repo:t.repo,runner:h||null,tests:h?re:null})},[t.repo,h,re]);let ae=J?te(J):"",tt=h?ke(h,k):null,G=tt?.script&&h?be(h,k,!0):null,$e=J?He(J):null,st=(l,y)=>F(B.filter(I=>I===l?y:g.includes(I))),Re={retry:d?`${d} flaky test${d===1?"":"s or jobs"} here in the last ${n.window_days??30} days.`:null,burnin:m?`${m} flaky test${m===1?"":"s"} got in already; this stops the next one at the pull request.`:null,impact:f?.failures?`On ${f.prs} past pull requests it would have run ${f.caught} of ${f.failures} real failures and skipped ${Math.round((f.skipped_share??0)*100)}% of test files.`:"Not measured here yet: treat it as a fast first pass until the replay below shows it catches real failures.",shards:u?`The slowest test job takes about ${Math.round(u)} minutes.`:null,quarantine:d?"Tests someone quarantines (Decide, or /stackvitals quarantine) stop failing builds at once.":null,validate:n.has_test_reports?null:"No test reports were read here yet; this step says why."};return e("div",{class:"ci-setup",children:[e("div",{class:"ci-setup-strip",children:[e("span",{children:"Workflow builder"}),e("span",{children:[t.repo," \xB7 ",r]})]}),e("div",{class:"ci-setup-form form",children:[e(M,{label:"1. Test runner",hint:o.runner?e(T,{children:["Guessed from ",[o.ids.length?`test names like ${o.ids[0]}`:"",o.names.length?`job names like ${o.names[0]}`:""].filter(Boolean).join(" and "),". Change it if that's wrong."]}):"This repo's data doesn't say which runner it uses, so pick it.",children:l=>e(Fe,{id:l,value:h,onChange:y=>{i(y),p({})},options:[...h?[]:[{value:"",label:"Pick your test runner"}],...Le.map(y=>({value:y,label:`${S[y].name} (${S[y].lang})`}))]})}),o.runner?null:e("p",{class:"ci-say",children:[e("span",{class:"sv-mark sv-mark-watch","aria-hidden":"true"}),"Couldn't tell the runner from the test or job names here."]}),e("fieldset",{class:"ci-feats",children:[e("legend",{class:"field-label",children:"2. What it should do"}),B.map(l=>{let y=`ci-feat-${l}`;return e("div",{class:"ci-feat"+(g.includes(l)?" is-on":""),children:[e(qe,{checked:g.includes(l),onChange:I=>st(l,I),labelledBy:y}),e("div",{class:"ci-feat-text",children:[e("b",{id:y,children:O[l][0]}),e("span",{children:O[l][1]}),Re[l]?e("small",{children:Re[l]}):null]})]})})]}),w?e(T,{children:[e("p",{class:"field-label ci-step",children:"3. Details"}),e(M,{label:"Install dependencies",hint:"A first guess at how this repo installs what its tests need; change it if yours differs.",children:l=>e(L,{id:l,mono:!0,value:v.install??w.install,onInput:y=>p({...v,install:y}),placeholder:"Nothing to install first"})}),g.includes("impact")||g.includes("shards")?e(M,{label:"Test files",hint:"A glob of this repo's test files; test impact and shards place them.",children:l=>e(L,{id:l,mono:!0,value:v.tests??w.tests,onInput:y=>p({...v,tests:y})})}):null,e(M,{label:"Extra test arguments",hint:`Added to every ${w.name} run, for example a config file or a project.`,children:l=>e(L,{id:l,mono:!0,value:k,onInput:$,placeholder:"None"})}),e("div",{class:"ci-steppers",children:[g.includes("shards")?e("div",{class:"field",children:[e("span",{class:"field-label",children:"Shards"}),e(de,{label:"Shards",value:ne,onChange:H,min:2,max:16}),e("p",{class:"field-hint",children:u?"Suggested from the slowest test job: about one per five minutes.":"Two to start; more once times are recorded."})]}):null,g.includes("burnin")?e("div",{class:"field",children:[e("span",{class:"field-label",children:"Burn-in runs"}),e(de,{label:"Burn-in runs",value:ve,onChange:et,min:2,max:20}),e("p",{class:"field-hint",children:"How many times new and changed tests run on a pull request."})]}):null]})]}):null,c.length?e("div",{class:"ci-jobs-now",children:[e("p",{class:"field-label",children:"Your test jobs now"}),e("ul",{children:c.slice(0,6).map(l=>e("li",{children:[e("code",{children:l.name}),l.min?e("span",{class:"muted",children:[" about ",Math.round(l.min)," min"]}):null]}))})]}):null]}),e("div",{class:"ci-setup-out",children:[J&&w?e(T,{children:[e("p",{class:"ci-setup-h",children:"What you get"}),e(U,{rows:[["File",e("code",{children:q})],["Workflow",se],["Runs on",`pushes to ${r}, pull requests, and by hand`],["Test reports",e(T,{children:[e("code",{children:w.reports}),", kept as test-results artifacts for StackVitals"]})],["Turned on",g.length?g.map(l=>O[l][0]).join(", "):"Nothing extra: runs the tests and keeps their reports"]]}),$e?e(mt,{app:t,branch:r,yaml:ae,link:$e}):null,e("details",{class:"ci-yaml",children:[e("summary",{children:["Show the file (",ae.split(`
|
|
4
|
+
`).length-1," lines)"]}),e(_,{title:q,code:ae})]}),e(j,{title:"What you still do",children:e("ul",{class:"ci-todo",children:[e("li",{children:[e("b",{children:"Review and merge it."})," Nothing reaches your default branch until you press Commit or merge the pull request."]}),e("li",{children:[e("b",{children:"Check the runner details."})," ",w.check]}),c.length?e("li",{children:[e("b",{children:"Retire the old test job"})," (",c.slice(0,2).map(l=>l.name).join(", "),") once this one is green, so tests don't run twice."]}):null,e("li",{children:[e("b",{children:"Read it right away."}),' Add "',se,'" to the workflows list at the top of ',e("code",{children:".github/workflows/stackvitals.yml"}),", so StackVitals reads each run as it ends."]})]})})]}):e("p",{class:"ci-say",children:[e("span",{class:"sv-mark sv-mark-neutral","aria-hidden":"true"}),"Pick the test runner to see the workflow file."]}),e("details",{class:"ci-manual",children:[e("summary",{children:"The commands one by one, for a workflow you keep yourself or for your machine"}),e("p",{class:"muted small",children:["Install with pip install stackvitals (or uv tool install stackvitals), then",w?`, for ${w.name}`:"",":"]}),w?null:e("p",{class:"ci-say",children:[e("span",{class:"sv-mark sv-mark-neutral","aria-hidden":"true"}),"Pick the test runner above to fill in the test commands."]}),e("div",{class:"ci-manual-list",children:[ht(t.repo,r,h||null,re,k).map(([l,y,I])=>e("div",{children:[e("h4",{children:l}),e(_,{inline:!0,code:y,note:I})]})),G&&w?e("div",{children:[e("h4",{children:"The run-tests script"}),e(_,{title:"run-tests",code:G.run.join(`
|
|
5
|
+
`)+`
|
|
6
|
+
`,note:`Save it as run-tests on your PATH (the workflow writes the same): it turns test files into what ${w.name} takes.`})]}):null,G?.rerun&&w?e("div",{children:[e("h4",{children:"The rerun-failed script"}),e(_,{title:"rerun-failed",code:G.rerun.join(`
|
|
7
|
+
`)+`
|
|
8
|
+
`,note:"Save it as rerun-failed next to run-tests; it runs only what failed last time."})]}):null]})]})]})]})}function mt({app:t,branch:n,yaml:a,link:r}){let s=D(_e),[c,o]=R("idle"),[u,d]=R(""),[m,f]=R(null),[h,i]=R(null),[g,F]=R("");V(()=>{(c==="done"||c==="error")&&o("idle")},[a]);let v=async p=>{let k=p||m||(s?await Ee(t):void 0);if(!k){o("token");return}o("sending");try{let $=await Oe(Ce(k),{repo:t.repo,base:n,branch:ge,file:q,content:a,message:"Run the tests with StackVitals",title:"Run the tests with StackVitals",body:`Adds \`${q}\`, made in the StackVitals app (CI Health, Set up in your CI). Review it: the tests run on this pull request first, and merging turns it on for ${n}.`});i($),o("done"),xe(`Pull request #${$.number} is open`)}catch($){F($ instanceof Error?$.message:String($)),o("error")}};return e("div",{class:"ci-add",children:[e("div",{class:"ci-add-paths",children:[e("div",{class:"ci-add-path",children:[e("p",{class:"ci-add-k",children:"No token needed"}),e(x,{variant:"filled",href:r.url,external:!0,iconEnd:"external",onClick:Pe(r,"GitHub opened with the file: press Commit changes there"),children:"Open it on GitHub"}),e("p",{class:"ci-add-note",children:r.paste?e(T,{children:[Ie," It lands on ",n,", or on a new branch you pick there, which opens a pull request."]}):e(T,{children:["GitHub's editor opens with the file filled in",r.comments?"":" (comments left out so the link fits; Copy the file has them)",". Press ",e("b",{children:"Commit changes"}),": commit it to ",n,", or pick a new branch to open a pull request."]})})]}),e("div",{class:"ci-add-path",children:[e("p",{class:"ci-add-k",children:"With a token that can write"}),e(x,{variant:"tinted",icon:"prs",loading:c==="sending",onClick:()=>v(),children:"Open the pull request for me"}),e("p",{class:"ci-add-note",children:["Makes the branch ",ge,", commits the file there and opens a pull request",s?` as ${s.login||"you"}`:"",". You review and merge it; nothing lands on ",n," by itself."]})]})]}),c==="token"?e("div",{class:"ci-token",children:[e("p",{children:["Paste a fine-grained token for ",e("b",{children:t.repo})," with ",e("b",{children:"Contents"}),", ",e("b",{children:"Workflows"})," and ",e("b",{children:"Pull requests"})," set to read and write (",e("a",{href:ft(t.repo),target:"_blank",rel:"noopener noreferrer",children:"make one, 7 days"}),"). It stays in this page's memory and goes only to api.github.com."]}),e("div",{class:"inline-form",children:[e(L,{type:"password",mono:!0,value:u,onInput:p=>d(p.trim()),placeholder:"github_pat_\u2026",label:"Fine-grained GitHub token"}),e(x,{variant:"filled",disabled:!u,onClick:()=>{f(u);let p=u;d(""),v(p)},children:"Use it"})]})]}):null,e("div",{role:"status",children:c==="done"&&h?e("p",{class:"note note-good",children:[e(le,{name:"check"}),e("span",{children:["Pull request ",e("a",{href:h.url,target:"_blank",rel:"noopener noreferrer",children:["#",h.number]})," is open. Its checks run the new workflow first; merge it when they pass."]})]}):null}),e("div",{role:"alert",children:c==="error"?e("p",{class:"note note-bad",children:[e(le,{name:"warn"}),e("span",{children:["Not opened: ",g," The token needs Contents, Workflows and Pull requests (read and write) on ",t.repo,"; the GitHub link works without one."]})]}):null}),e("div",{class:"ci-add-more",children:[e(Se,{text:a,label:"Copy the file"}),e("span",{class:"ci-add-save",children:["Save it as ",e("code",{children:q})]})]})]})}var Qe={target:"_blank",rel:"noopener noreferrer"},Ze={infrastructure:"the runner itself (disk, shutdown, service busy)",network:"a host or connection that didn't answer",concurrency:"a race or deadlock between threads",timing:"a wait or timeout that ran out","resource leak":"files or sockets left open","async wait":"a UI or async step checked too early",time:"time zones, daylight saving or the clock",randomness:"a random seed or input","floating point":"rounding in a numeric comparison","shared state":"data left behind by another test",io:"a file or permission on disk",ordering:"results compared in a fixed order that isn't guaranteed"},Ye=t=>t?Ze[t]||t:"";function Xt({b:t,app:n}){let a=t.landed||[];return e(Q,{title:"Before and after the first flake",state:t.clear?e(N,{tone:"watch",children:"Began with a change"}):e(N,{tone:"neutral",icon:null,children:"May have flaked all along"}),children:e(U,{rows:[["First flake",e("span",{class:"num",children:Te(t.first)})],["Runs before it",e("span",{class:"num",children:[t.runs_before," runs, none flaked"]})],["Runs since",e("span",{class:"num",children:[t.flakes," flakes in ",t.runs_after," runs"]})],["Chance it's luck",e("span",{class:"num",children:["p = ",t.p,t.clear?": unlikely, so something that landed around then probably started it":": too few runs before the first flake to say"]})],t.clear&&["Pushed the day before",a.length?e("ul",{class:"ci-landed",children:a.map(r=>e("li",{children:e("a",{class:"mono-soft",href:`https://github.com/${n.repo}/commit/${r}`,...Qe,children:r.slice(0,7)})}))}):"Nothing reached the default branch: look at what changed outside the code (runners, services, data)."]]})})}function Kt({ci:t}){let n=ue({q:"../ci/quarantine.json",tk:"../ci/tickets.json",settings:"settings.json"}),[a,r]=R(!1),s=new Set((t.tests||[]).map(i=>i.id)),c=t.quarantine_expired||[],o=n.settings?.values,u=Z(o,"ci.quarantine.max_days"),d=Z(o,"automation.quarantine"),m=(n.q||[]).filter(i=>s.has(i)||!s.size),f=Object.entries(n.tk||{}).filter(([i])=>s.has(i)).map(([i,g])=>({...g,ticket:g.id,id:i})),h=Z(o,"connectors.jira.url");return e(z,{title:"Quarantine and tickets",description:"Flaky tests can stop failing builds while they wait for a fix; each can get its own Jira or Linear ticket.",children:[e(ce,{children:[e(C,{label:"In quarantine now",value:n.ready?n.q?m.length:"\u2013":"\u2026",note:n.q?"known flaky, still run and reported":"the list lives on the data branch"}),e(C,{label:"Past the time limit",value:c.length,note:u?`out after ${u} days: they fail builds again`:"no limit set ([ci.quarantine] max_days)"}),e(C,{label:"Flaky-test tickets",value:f.length?`${f.filter(i=>i.open).length} open`:"\u2013",note:f.length?`${f.length} filed, closed once fixed`:"off: set flaky_tickets under Jira or Linear"})]}),d===!1||d==="off"?e("p",{class:"ci-say",children:[e("span",{class:"sv-mark sv-mark-neutral","aria-hidden":"true"}),"Quarantine is turned off in the settings."]}):null,e(je,{children:[e(j,{title:"Quarantined tests",note:u?`${u}-day limit`:void 0,children:e(A,{name:"quarantine",caption:"Quarantined tests",search:!1,rows:m.map(i=>({id:i,overdue:c.includes(i)})),columns:[{key:"id",label:"Test",primary:!0,render:i=>e("a",{class:"mono-soft",href:`#/ci/test/${encodeURIComponent(i.id)}`,children:X(i.id,70)})},{key:"overdue",label:"Time limit",raw:i=>i.overdue?"overdue":"within",render:i=>i.overdue?e(N,{tone:"watch",children:"Overdue"}):e(N,{tone:"neutral",icon:null,children:"Within"})}],empty:e(Y,{children:e(K,{icon:"check",title:n.q?"Nothing is quarantined.":"No quarantine list readable here.",children:n.q?"":"It's written to ci/quarantine.json on the data branch when quarantine is on."})})})}),e(j,{title:"Tickets per flaky test",children:e(A,{name:"flaky-tickets",caption:"Tickets per flaky test",search:!1,rows:f,columns:[{key:"key",label:"Ticket",primary:!0,render:i=>i.tracker==="jira"&&h?e("a",{href:`${h.replace(/\/$/,"")}/browse/${i.key}`,...Qe,children:i.key}):e("span",{children:i.key})},{key:"tracker",label:"Tracker",raw:i=>i.tracker==="jira"?"Jira":i.tracker==="linear"?"Linear":i.tracker||"\u2013"},{key:"id",label:"Test",render:i=>e("span",{class:"mono-soft",children:X(i.id,50)})},{key:"open",label:"State",filter:!0,raw:i=>i.open?"open":"closed",render:i=>e(N,{tone:i.open?"watch":"good",children:i.open?"Open":"Closed when fixed"})}],empty:e(Y,{children:e(K,{icon:"about",title:"No tickets filed here.",children:"Set flaky_tickets = true and ticket_project (Jira) or ticket_team (Linear) in Settings; a ticket opens when a test turns flaky and closes when it's fixed."})})})})]}),e(Q,{title:"Apply it in your test command",class:"ci-apply",bar:e(T,{children:[e(x,{size:"sm",variant:"tinted",iconEnd:"down",onClick:()=>we("quarantine"),children:"Add it to your CI"}),e(x,{size:"sm",variant:"plain",expanded:a,onClick:()=>r(!a),iconEnd:a?"up":"down",children:"The commands"})]}),children:[e(U,{rows:[["pytest","Still runs a quarantined test, but it can't fail the run"],["Jest, Vitest, go test, Playwright, Maven Surefire, dotnet test","Leave it out by name"],["Any other runner (RSpec, Gradle)","Wrap the test command: it passes when only quarantined tests failed"]]}),a?e(_,{title:"Workflow step",code:`pytest $(stackvitals ci quarantine --print pytest)
|
|
9
|
+
npx jest $(stackvitals ci quarantine --print jest)
|
|
10
|
+
stackvitals ci quarantine --reports 'out/*.xml' -- bundle exec rspec`}):null]})]})}function zt({app:t,ci:n}){let a=Ke(t,n),r=t.default_branch||"main",s=ue({im:"../ci/impact.json"}),[c,o]=R(!1),u=n.impact,d=Object.entries(s.im?.learned||{}).map(([m,f])=>{let h=Object.entries(f).sort((i,g)=>g[1]-i[1]);return{folder:m||"(top level)",tests:h.length,failures:h.reduce((i,[,g])=>i+g,0),top:h.slice(0,3)}}).sort((m,f)=>f.failures-m.failures);return e(z,{title:"Test impact",description:"Run only the tests a change can affect. Each past pull request is judged with only what was known before it.",children:[u&&u.failures?e(ce,{children:[e(C,{label:"Real failures it would have run",value:`${u.caught} of ${u.failures}`,note:u.recall!=null?`${Math.round(u.recall*100)}%`:void 0}),e(C,{label:"Test files it would have skipped",value:u.skipped_share!=null?`${Math.round(u.skipped_share*100)}%`:"\u2013",note:`over ${u.prs} pull requests`})]}):e(Y,{children:e(K,{icon:"clock",title:u?"No real test failure on past pull requests to replay yet.":"Not replayed yet.",children:u?`${u.prs} pull requests read; the replay needs pull requests whose tests failed for real (flaky ones don't count).`:"It needs test reports in CI and the Team Flow module (for each pull request's changed files); the next run with both fills it in."})}),d.length?e(j,{title:"What it learned",note:"A change in this folder has failed these test files.",children:e(A,{name:"impact-learned",caption:"What it learned: a change in this folder has failed these test files",search:!1,rows:d.slice(0,15),columns:[{key:"folder",label:"Changed folder",primary:!0,render:m=>e("span",{class:"mono-soft",children:m.folder})},{key:"top",label:"Test files that failed",raw:m=>m.tests,render:m=>e("ul",{class:"ci-cell-list",children:m.top.map(([f,h])=>e("li",{children:[e("span",{class:"mono-soft",children:X(f,60)})," ",e("span",{class:"muted num",children:[h,"\xD7"]})]}))})},{key:"tests",label:"Test files",num:!0},{key:"failures",label:"Failures",num:!0}]})}):null,e(Q,{title:"Pick the tests for a pull request",class:"ci-apply",bar:e(T,{children:[e(x,{size:"sm",variant:"tinted",iconEnd:"down",onClick:()=>we("impact"),children:"Add it to your CI"}),e(x,{size:"sm",variant:"plain",expanded:c,onClick:()=>o(!c),iconEnd:c?"up":"down",children:"The command"})]}),children:[e(U,{rows:[["What it prints",'The test files to run, "all" when a build or settings file changed, or nothing when no test is touched'],["What it reads","The pull request's changed files and the learned map above, from the data branch"]]}),c?e(_,{inline:!0,code:`stackvitals ci impact --base origin/${r} --tests ${E(a.tests||"<your test files glob>")}`,note:a.runner?`The test files glob for ${S[a.runner].name}, as in the workflow builder below.`:"Pick the test runner in the builder below to fill in the test files glob."}):null]})]})}function Yt({ci:t}){let n=t,a=n.pr_edit_workflows||[],r=[n.test_outages?{id:"outage",what:"Runs where most tests failed at once",n:n.test_outages,means:"An outage, not flakes: left out of every test's flake count."}:null,n.infra_events?{id:"infra",what:"Runs that hit runner or service trouble",n:n.infra_events,means:"Disk full, runner shut down or rate limits."}:null,a.length?{id:"edits",what:"Workflows that re-run when a pull request's title or labels change",n:a.length,means:e(T,{children:["A pass and a fail on the same code there aren't counted as flakes: ",a.map((s,c)=>e(T,{children:[c?", ":"",e("code",{class:"code-inline",children:s})]}))]})}:null].filter(s=>!!s);return r.length?e(j,{title:"Left out of the flake counts",note:"What keeps the flake numbers honest.",children:e(A,{name:"ci-signals",caption:"Left out of the flake counts",search:!1,rows:r,columns:[{key:"what",label:"What",primary:!0},{key:"n",label:"Count",num:!0},{key:"means",label:"What it means",raw:s=>typeof s.means=="string"?s.means:"",render:s=>s.means}]})}):null}function Qt({rows:t}){let n={};for(let r of t)r.state==="flaky"&&(n[r.flake||"not recognised"]=(n[r.flake||"not recognised"]||0)+1);let a=Object.entries(n).sort((r,s)=>s[1]-r[1]).map(([r,s])=>({id:r,kind:r,n:s}));return a.length?e(j,{title:"Likely causes",note:"From each flaky item's usual error.",children:e(A,{name:"likely-causes",caption:"Likely causes",search:!1,rows:a,columns:[{key:"kind",label:"Cause",primary:!0,render:r=>e("span",{class:"ci-cap",children:r.kind})},{key:"n",label:"Flaky tests and jobs",num:!0},{key:"help",label:"What it usually means",raw:r=>Ye(r.kind),render:r=>Ze[r.kind]?Ye(r.kind):"\u2013"}]})}):null}function Zt({app:t,ci:n}){return e(z,{id:"ci-setup",title:"Set up in your CI",description:"Pick what your test runs should do; the page writes the workflow file and adds it to the repo in one click, through GitHub or as a pull request.",children:e(ze,{app:t,ci:n})})}export{Xt as Began,Qt as Causes,zt as Impact,Kt as Quarantine,Zt as Setup,Yt as Signals,Ye as kindHelp};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{a as f}from"./chunk-3ROQFHPV.js";import{a as b,c as _,d as k,e as p}from"./chunk-4H53OYLG.js";import{a as y}from"./chunk-6RLVD2DT.js";import{e as s,h as m,i as o}from"./chunk-76WAVKUG.js";import"./chunk-VWKSMFWJ.js";import{P as n,a as i,l as u,m as d,n as g,w as e}from"./chunk-GT4EAKAO.js";import{d as w}from"./chunk-G7NGB5UX.js";w();function P({k:t}){let a=t.areas||[],l=t.hotspots||[],h=a.filter(r=>r.single_owner),c=a.some(r=>r.owner);return!a.length&&!l.length?e(s,{children:e(n,{icon:"prs",title:"Not enough merged work to map yet.",children:"Each folder's main author shows once pull requests touching it have merged."})}):e(i,{children:[e(m,{children:[e(o,{label:"Areas mapped",value:a.length,note:"folders with merged pull requests"}),e(o,{label:"Known by one person",value:h.length,note:"one author behind most of an area's merged PRs (3 or more)"}),e(o,{label:"That person quiet 30+ days",value:h.filter(r=>(r.owner_quiet_days??0)>=30).length,note:"route reviews there before it bites"})]}),e(b,{title:"Who knows each area",note:"busiest first; an area one person carries is marked",children:e(y,{name:"knowledge",caption:"Who knows each area",rows:a,initialSort:{key:"prs",desc:!0},columns:[{key:"area",label:"Area",primary:!0,render:r=>e("span",{class:"mono-soft",children:r.area})},{key:"single_owner",label:"Carried by",filter:!0,raw:r=>r.single_owner?"One person":"Several people",render:r=>r.single_owner?e(p,{tone:"watch",children:"One person"}):e(p,{tone:"good",children:"Several people"})},{key:"prs",label:"Merged PRs",num:!0},...c?[{key:"owner",label:"Main author",render:r=>r.owner||"\u2013"}]:[],{key:"share",label:"Their share",num:!0,render:r=>d(r.share)},{key:"owner_quiet_days",label:"Last active",num:!0,raw:r=>r.owner_quiet_days??-1,render:r=>r.owner_quiet_days==null?"\u2013":r.owner_quiet_days===0?"today":`${g(r.owner_quiet_days,"day")} ago`}],empty:e(s,{children:e(n,{icon:"check",title:"No area mapped yet."})})})}),l.length?e(_,{title:"Busiest areas",state:e("span",{class:"muted",children:"merged PRs, last 90 days"}),children:e(f,{label:"Busiest areas: merged pull requests in the last 90 days",height:200,bars:l.map(r=>({label:r.area,value:r.prs_90d,tone:"accent"}))})}):null,c?null:e(k,{rows:[["Names",e(i,{children:["Hidden: this repo is public, so areas are shown without the person behind them. Set ",e("code",{children:"knowledge_names = true"})," under ",e("code",{children:"[identity]"})," to name them."]})]]})]})}function $({d:t}){if(t.source!=="releases")return e(s,{children:e(n,{icon:"clock",title:"No release in the window.",children:[t.per_week!=null?`${t.per_week} pull requests merge a week. `:"","Publishing GitHub releases (or turning on Delivery with deployments) gives merge-to-release time and how often a release needed a fix."]})});let a=t.change_fail;return e(m,{children:[e(o,{label:"Releases",value:t.releases,note:`${t.per_week} a week`}),e(o,{label:"Merge to release, median",value:u(t.lead_time_median_s),note:"from merge to the next published release"}),e(o,{label:"Releases followed by a fix",value:a?d(a.rate):"\u2013",note:a?`${a.failed} of ${a.of}${a.proxy?"; a revert or hotfix merged before the next release (an estimate)":""}`:null}),e(o,{label:"Release to the fixing release, median",value:u(t.recovery_median_s)})]})}export{P as Knowledge,$ as Releases};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{a as T}from"./chunk-3ROQFHPV.js";import{a as b,b as S,c as N,e as O}from"./chunk-4H53OYLG.js";import{a as g}from"./chunk-6RLVD2DT.js";import{d as L,e as _,h as k,i}from"./chunk-76WAVKUG.js";import"./chunk-VWKSMFWJ.js";import{P,a as c,c as F,k as y,m,o as v,s as I,w as e,y as E}from"./chunk-GT4EAKAO.js";import{d as z}from"./chunk-G7NGB5UX.js";z();var H=(t,a)=>`https://github.com/${t.repo}${a}`,q={target:"_blank",rel:"noopener noreferrer"},W=t=>t??"\u2013",J=[["n","Merged PRs",W],["merge_rate","Merge rate",m],["pickup_p75_h","Pickup P75",y],["review_p75_h","Review P75",y],["size_p75","Size P75, lines",W],["ci_n","Merged since the CI history began",W],["ci_failed_share","A CI run on the PR failed",m],["flaky_share","A failed run passed on re-run",m],["reverted_share","Reverted later",m],["failed_deploy_share","Shipped in a deployment with an incident",m]],K=[["reverted","Reverted"],["ci_failed","A CI run failed"],["failed_deploy","Shipped in a failed deployment"],["merged","Merged"],["merged_by_others","Merged by someone else"]],Q={REQUIREMENT:"Stories and features",BUG:"Bugs",TASK:"Tasks",INCIDENT:"Incidents"};function G(t){if(!t||t.verdict==="too few"||t.gap==null)return["too few to compare",!1];let a=s=>`${s>=0?"+":""}${Math.round(s*100)}`,l=s=>Math.abs(Math.round(s*100))===1?"point":"points";return t.verdict==="no measurable difference"?[`no measurable difference (could detect ${Math.round(t.detectable*100)} ${l(t.detectable)} or more)`,!1]:[`${t.verdict==="higher"?"more often":"less often"}: ${a(t.gap)} ${l(t.gap)}, likely ${a(t.low)} to ${a(t.high)}`,t.verdict==="higher"]}function B({title:t,rows:a,peers:l}){return e("div",{children:[e(b,{title:t,children:e(g,{name:`ai-${t.slice(0,12)}`,search:!1,rows:K.filter(([s])=>a?.[s]).map(([s,n])=>{let o=a[s],[p,d]=G(o);return{label:n,text:p,warn:d,matched:o.of?`${o.matched} of ${o.of}${o.matched_share!=null?` (${m(o.matched_share)})`:""}`:"\u2013"}}),columns:[{key:"label",label:"Outcome",primary:!0},{key:"text",label:"Against like for like",render:s=>s.warn?e(O,{tone:"watch",children:s.text}):s.text},{key:"matched",label:"Matched",num:!0}],empty:e(_,{children:e("p",{class:"blk-note",children:"Too few to compare yet."})})})}),l?e("p",{class:"blk-note dl-after",children:l}):null]})}function x({load:t,expected:a}){let l=t.weeks||[],s=l[l.length-1]||{},n=t.reviewers||{},o=d=>(d?.agent||0)+(d?.person||0),p=a.filter(d=>d.p50_h!=null).sort((d,C)=>(C.p75_h||0)-(d.p75_h||0));return e(c,{children:[e(S,{title:"Review load",note:"agents add pull requests faster than reviewers grow"}),e(k,{children:[e(i,{label:"Opened this week",value:o(s.opened),note:`${s.opened?.agent??0} by agents; ${o(s.merged)} merged`}),e(i,{label:"Waiting for a first review",value:o(t.waiting),note:`${t.waiting?.agent??0} from agents, drafts left out`}),e(i,{label:"Reviewers with open requests",value:n.n??0,note:`the busiest holds ${n.max_open??0}; ${m(n.agent_share)} of requests are for agents' PRs`})]}),e(b,{title:"Week by week",note:"opened and merged, agents and people",children:e(g,{name:"review-weeks",search:!1,rows:[...l].reverse(),columns:[{key:"week_end",label:"Week to",primary:!0,raw:d=>v(d.week_end)},{key:"oa",label:"Opened by agents",num:!0,raw:d=>d.opened?.agent??0},{key:"op",label:"Opened by people",num:!0,raw:d=>d.opened?.person??0},{key:"ma",label:"Merged, agents",num:!0,raw:d=>d.merged?.agent??0},{key:"mp",label:"Merged, people",num:!0,raw:d=>d.merged?.person??0}]})}),p.length?e(b,{title:"Review an open pull request can expect",note:"from similar ones merged here (same kind and size)",children:e(g,{name:"expected-review",search:!1,rows:p.slice(0,50),columns:[{key:"pr",label:"Pull request",primary:!0,raw:d=>`#${d.pr}`},{key:"kind",label:"By",filter:!0,raw:d=>d.kind==="agent"?"Agent":d.kind==="person"?"Person":d.kind},{key:"p50_h",label:"Review, typical",num:!0,render:d=>y(d.p50_h)},{key:"p75_h",label:"Review, 3 in 4 within",num:!0,render:d=>y(d.p75_h)},{key:"similar",label:"Similar PRs",num:!0}]})}):null]})}function Z({s:t}){let a=(l,s)=>{let n=t[l]?.[s];return n?`${m(n.share)} (${n.prs} PRs)`:"\u2013"};return e(c,{children:[e(S,{title:"Code that lasted",note:"lines still in the default branch, by git blame; squash-merged PRs only"}),e(k,{children:[e(i,{label:"People's PRs, 30 days",value:a("30","people")}),e(i,{label:"Agents' PRs, 30 days",value:a("30","agents")}),e(i,{label:"People's PRs, 90 days",value:a("90","people")}),e(i,{label:"Agents' PRs, 90 days",value:a("90","agents")})]})]})}function le({ai:t,survival:a}){let l=t.outcomes||{},s=l.window,n=t.baseline,o=t.agent_prs||{},p=l.coverage||{},d=l.matched||{};if(!s||!(r=>(r?.agent?.n||0)+(r?.assisted?.n||0)+(r?.others?.n||0))(s))return e(_,{children:e(P,{icon:"delivery",title:"No merged pull requests in the last 6 months.",children:"This fills in after Team Flow reads some."})});let A=l.monthly||[],R=r=>s[r]||{},f=n?.matched?.merged_by_others,$=r=>`${r>=0?"+":""}${Math.round(r*100)}`,M=f?`Similar public repos (${n.matched.repos} ${n.group}): merged by someone else ${$(f.gap)} ${Math.abs(Math.round(f.gap*100))===1?"point":"points"} (likely ${$(f.low)} to ${$(f.high)}) against people's PRs of the same repo, month and size.`:null,u=t.copilot;return e(c,{children:[e(k,{children:[e(i,{label:"People's PRs with an AI marker",value:m(p.marked_share),note:`${p.marked??0} of ${p.people_prs??0}; ${p.authors_marking??0} of ${p.authors??0} authors`}),e(i,{label:"Coding agents' PRs merged",value:R("agent").n??0,note:`last 6 months; from an agent's account or branch (codex/, claude/, copilot/)${o.n?`; ${m(o.merged_share)} of the account's ${o.n} PRs merged`:""}`}),e(i,{label:"Agents' PRs merged, similar repos",value:n?m(n.agent_merged):"\u2013",note:n?`the crawl's median of ${n.repos} ${n.group}; outside contributors ${m(n.outsider_merged)}`:"no crawl file yet"}),e(i,{label:"Reviewed by an AI bot",value:t.ai_reviewed_prs?.n??0,note:"merged PRs"})]}),u?e(c,{children:[e(S,{title:`Copilot in ${u.org}, last ${u.window_days} days`,note:`GitHub's reports, ${u.days_kept} days kept since ${v(u.first_day)}`}),e(k,{children:[e(i,{label:"Monthly active users",value:u.monthly_active_users??"\u2013",note:`${u.monthly_active_agent_users??0} used the agent`}),e(i,{label:"Suggestions accepted",value:m(u.acceptance)}),e(i,{label:"PRs by Copilot, org",value:u.org_prs_by_copilot,note:`${u.org_prs_merged_by_copilot} merged`}),e(i,{label:"PRs by Copilot, this repo",value:u.repo_prs_by_copilot,note:`${u.repo_prs_merged_by_copilot} merged`})]})]}):null,e(L,{children:[e(B,{title:"AI-marked PRs against the same authors' other PRs",rows:d.assisted}),e(B,{title:"Coding agents' PRs against people's of the same month and size",rows:d.agent,peers:M})]}),e(L,{children:[e(b,{title:"Raw shares, not matched",children:e(g,{name:"ai-after",search:!1,rows:J.map(([r,h,D])=>{let w=j=>D(j[r])+(r==="merge_rate"&&j.merge_rate_n?` of ${j.merge_rate_n}`:"");return{k:r,label:h,g:w(R("agent")),a:w(R("assisted")),o:w(R("others"))}}),columns:[{key:"label",label:"Measure",primary:!0},{key:"g",label:"Agents",num:!0},{key:"a",label:"AI-marked",num:!0},{key:"o",label:"Others",num:!0}]})}),e(N,{title:"People's merged PRs with an AI marker",state:e("span",{class:"muted",children:"per month"}),children:[A.length?e(T,{label:"Share of people's merged PRs with an AI marker, per month",kind:"share",height:180,bars:A.map(r=>{let h=(r.assisted?.n||0)+(r.others?.n||0);return{label:I(r.month),value:h?(r.assisted?.n||0)/h:0}})}):e("p",{class:"blk-note",children:"No months yet."}),e(g,{name:"ai-months",search:!1,rows:[...A].reverse(),columns:[{key:"month",label:"Month",primary:!0},{key:"gn",label:"Agents",num:!0,raw:r=>r.agent?.n||0},{key:"an",label:"AI-marked",num:!0,raw:r=>r.assisted?.n||0},{key:"on",label:"Others",num:!0,raw:r=>r.others?.n||0}]})]})]}),t.spend?e(c,{children:[e(S,{title:"What the AI tools cost",note:`last ${t.spend.window_days} days; Cursor: its current billing cycle`}),e(k,{children:[e(i,{label:"AI spend",value:`$${Number(t.spend.total_usd).toLocaleString()}`,note:Object.entries(t.spend.providers||{}).map(([r,h])=>`${r} $${Number(h).toLocaleString()}`).join(", ")}),e(i,{label:"Per merged AI-involved PR",value:t.spend.per_ai_pr_usd==null?"\u2013":`$${Number(t.spend.per_ai_pr_usd).toLocaleString()}`,note:`${t.spend.ai_prs} agents' and AI-marked PRs merged; all API use counts, not only coding`}),t.spend.cursor_agent_requests!=null?e(i,{label:"Cursor agent requests",value:t.spend.cursor_agent_requests}):null]}),t.spend.tools?e(b,{title:"The coding tools side by side",note:"same days",children:e(g,{name:"ai-tools",search:!1,caption:"The coding tools side by side, same days",rows:Object.entries(t.spend.tools).map(([r,h])=>({k:r==="claude_code"?"Claude Code":"Cursor",...h})),columns:[{key:"k",label:"Tool",primary:!0},{key:"lines_added",label:"Lines added",num:!0},{key:"commits",label:"Commits",num:!0,render:r=>r.commits==null?"\u2013":String(r.commits)},{key:"prs",label:"PRs opened",num:!0,render:r=>r.prs==null?"\u2013":String(r.prs)},{key:"acceptance",label:"Edits accepted",num:!0,render:r=>r.acceptance==null?"\u2013":m(r.acceptance)},{key:"use",label:"Use",num:!0,raw:r=>r.sessions??r.agent_requests,render:r=>r.sessions!=null?`${r.sessions} sessions`:`${r.agent_requests} agent requests`}]})}):null]}):null,Object.keys(t.by_agent||{}).length?e(b,{title:"Each coding agent",note:"last 6 months; rates need 10 PRs",children:e(g,{name:"ai-agents",search:!1,rows:Object.entries(t.by_agent).map(([r,h])=>({k:r,...h})),columns:[{key:"k",label:"Agent",primary:!0,raw:r=>{let h=String(r.k).replace(/ agent$/,"");return h.charAt(0).toUpperCase()+h.slice(1)}},{key:"prs",label:"Merged PRs",num:!0},{key:"merge_rate",label:"Merge rate",num:!0,render:r=>m(r.merge_rate)},{key:"rounds",label:"Review rounds, median",num:!0,raw:r=>r.review_rounds_p50,render:r=>r.review_rounds_p50??"\u2013"},{key:"review",label:"Review P75",num:!0,raw:r=>r.window?.review_p75_h,render:r=>y(r.window?.review_p75_h)},{key:"ci",label:"CI failed",num:!0,raw:r=>r.window?.ci_failed_share,render:r=>m(r.window?.ci_failed_share)},{key:"rev",label:"Reverted",num:!0,raw:r=>r.window?.reverted_share,render:r=>m(r.window?.reverted_share)}]})}):null,t.leaderboard?e(c,{children:[e(b,{title:"Coding agents across public repos",note:`the crawl's last ${t.leaderboard.window_days??180} days; agents seen in 10+ repos`,children:e(g,{name:"ai-leaderboard",search:!1,rows:Object.entries(t.leaderboard.agents||{}).map(([r,h])=>({k:r,...h})),columns:[{key:"k",label:"Agent",primary:!0,raw:r=>{let h=String(r.k);return h.charAt(0).toUpperCase()+h.slice(1)}},{key:"repos",label:"Repos",num:!0},{key:"prs",label:"Decided PRs",num:!0},{key:"merged",label:"Merged",num:!0,render:r=>m(r.merged)},{key:"others",label:"Merged by someone else",num:!0,raw:r=>r.merged_by_others,render:r=>m(r.merged_by_others)},{key:"gap",label:"Against people's PRs",num:!0,raw:r=>r.vs_people?.gap,render:r=>r.vs_people?`${r.vs_people.gap>=0?"+":""}${Math.round(r.vs_people.gap*100)} pts`:"\u2013"},{key:"here",label:"Here",num:!0,raw:r=>(t.by_agent||{})[`${r.k} agent`]?.merge_rate,render:r=>m((t.by_agent||{})[`${r.k} agent`]?.merge_rate)}]})}),e("p",{class:"blk-note",children:`Against people's PRs: the gap in merged share with people's pull requests of the same repo, month and size. "Here" is this repo's own merge rate for that agent.`})]}):null,t.review_load?e(x,{load:t.review_load,expected:t.expected_review||[]}):null,e("p",{class:"blk-note",children:`Totals only, never a person, and an association rather than a cause. Like-for-like comparisons follow AIDev's and Watanabe's designs: a person's AI-marked PRs against the same person's other PRs of a similar size; coding agents' PRs (their account, or an agent's branch such as codex/) against people's PRs of the same month and size, since an agent has no "same author". Unmarked PRs can still have had AI help. CI shares cover PRs merged since the CI history began; failed deployments only deployments of up to 5 PRs.`}),a?e(Z,{s:a}):null]})}function oe({t}){return e(c,{children:[e(k,{children:[e(i,{label:"Issues read",value:t.issues,note:`from ${(t.sources||[]).map(a=>a==="jira"?"Jira":a==="linear"?"Linear":a).join(" and ")}`}),e(i,{label:"Merged PRs naming an issue",value:m(t.merged_prs?t.linked_prs/t.merged_prs:null),note:`${t.linked_prs} of ${t.merged_prs}`}),e(i,{label:"Tracker incidents",value:t.incidents,note:"in DORA's failure rate and recovery"})]}),e(b,{title:"Lead and cycle time, finished issues",note:"lead from created, cycle from the first in-progress status",children:e(g,{name:"issue-times",search:!1,rows:Object.entries(t.lead_time||{}).map(([a,l])=>({k:a,...l})),columns:[{key:"k",label:"Type",primary:!0,raw:a=>Q[a.k]||a.k},{key:"n",label:"Done",num:!0},...["lead_p50_h","lead_p75_h","cycle_p50_h","cycle_p75_h"].map(a=>({key:a,label:a.replace(/_h$/,"").replace("_p"," P").replace(/^./,l=>l.toUpperCase()),num:!0,render:l=>y(l[a])}))]})}),e(b,{title:"Sprints and cycles",note:"carried over: still open when it closed",children:e(g,{name:"sprints",search:!1,rows:[...t.planning||[]].reverse(),columns:[{key:"name",label:"Sprint",primary:!0},{key:"state",label:"State",raw:a=>String(a.state||"").toLowerCase()},{key:"scope",label:"Scope",num:!0},{key:"done",label:"Done",num:!0},{key:"carried_over",label:"Carried over",num:!0},{key:"added_after_start",label:"Added after start",num:!0},{key:"points_done",label:"Points done",num:!0,render:a=>a.points_scope==null?"\u2013":`${a.points_done} of ${a.points_scope}`}],empty:e(_,{children:e(P,{icon:"clock",title:"No sprints or cycles in the last 180 days.",children:"Teams that work without them see lead and cycle time only."})})})}),t.by_field_team?e(b,{title:"Issues done by the tracker's team field",children:e(g,{name:"issue-field-teams",search:!1,caption:"Issues done by the tracker's team field",rows:Object.entries(t.by_field_team).map(([a,l])=>({k:a,done:l})),columns:[{key:"k",label:"Team",primary:!0},{key:"done",label:"Done",num:!0}]})}):null,t.by_team?e(c,{children:[e(b,{title:"Issues done by team",note:"each assignee named by an [identity] alias",children:e(g,{name:"issue-teams",search:!1,rows:Object.entries(t.by_team.teams||{}).map(([a,l])=>({k:a,...l})),columns:[{key:"k",label:"Team",primary:!0},{key:"done",label:"Done",num:!0}],empty:e(_,{children:e(P,{icon:"community",title:"No assignee is matched to a team yet.",children:'Map each one under [identity] aliases, like "jira:<account id>" = "their-login".'})})})}),t.by_team.by_email?e("p",{class:"blk-note",children:[t.by_team.by_email," of them matched because the assignee's email name is their GitHub login."]}):null,t.by_team.unmatched?e("p",{class:"blk-note",children:[t.by_team.unmatched," done issue(s) have an assignee no alias names; add them under [identity] aliases to count them for a team."]}):null,(t.by_team.suggested||[]).length?e(c,{children:[e("p",{class:"blk-note",children:"These look like the same person but are not counted until you confirm them. Paste the lines you agree with under [identity.aliases]:"}),e("pre",{class:"diff",tabIndex:0,style:{overflow:"auto",fontSize:"0.8125rem"},children:e("code",{children:t.by_team.suggested.map(a=>`${a.line} # ${a.issues} issue(s)`).join(`
|
|
2
|
+
`)})})]}):null]}):null]})}function ie({r:t,repo:a}){let l=t.backtest;return e(c,{children:[e(k,{children:[e(i,{label:"Needed a fix or were reverted",value:t.troubled??0,note:"merged PRs a fix soon changed, or a revert undid"}),e(i,{label:"Ranks trouble here (AUC)",value:l?l.auc.toFixed(2):"\u2013",note:l?`0.5 is chance; learnt on ${l.train} older PRs, checked on ${l.test} newer (${l.test_troubled??0} of them needed a fix)`:"not enough history yet"}),e(i,{label:"Trouble in its riskiest fifth",value:l?m(l.top_fifth_trouble):"\u2013",note:l?`against ${m(l.overall_trouble)} of all newer PRs`:""})]}),t.open?e(b,{title:"Open pull requests by change risk",note:"riskiest first",children:e(g,{name:"change-risk",caption:"Open pull requests by change risk",rows:t.open,initialSort:{key:"risk",desc:!0},columns:[{key:"pr",label:"Pull request",primary:!0,raw:s=>s.pr,render:s=>a?e("a",{href:`https://github.com/${a}/pull/${s.pr}`,target:"_blank",rel:"noopener noreferrer",children:["#",s.pr]}):`#${s.pr}`},{key:"level",label:"Risk",filter:!0,render:s=>e(O,{tone:s.level==="high"?"bad":s.level==="medium"?"watch":"good",children:String(s.level).charAt(0).toUpperCase()+String(s.level).slice(1)})},{key:"risk",label:"Chance it needs a fix",num:!0,render:s=>m(s.risk)},{key:"reasons",label:"Why",render:s=>e("span",{class:"muted",children:(s.reasons||[]).join("; ")||"nothing stands out"})}]})}):e(_,{children:e(P,{icon:"clock",title:"No score shown.",children:t.note})}),e("p",{class:"blk-note",children:"A pull request counts as having needed a fix when a fix (by its title or a label) changed the same files within 14 days, or a revert undid it, the lightweight form of SZZ. On 13 public repos the score ranked trouble with AUC 0.72 to 0.80 on six and near chance on three, so each repo is checked on its own history first."})]})}function de({timelines:t,repo:a}){let l=n=>a&&n.startsWith("#")?e("a",{href:`https://github.com/${a}/pull/${n.slice(1)}`,target:"_blank",rel:"noopener noreferrer",children:n}):n,s=n=>n==="deployment"?"accent":n==="dependency"||n==="config"?"watch":"neutral";return e(c,{children:[e(S,{title:"What changed before each incident",note:`the ${t[0]?.window_hours??72} hours before it began; likeliest first`}),t.map(n=>e(b,{title:`${n.incident.source==="issue"?"Issue":"Pull request"} #${n.incident.number}`,note:`began ${v(n.incident.created)}`,children:e(g,{name:`changed-${n.incident.number}`,search:!1,rows:n.candidates.slice(0,6).map((o,p)=>({...o,rank:p+1,id:`${p}`})),columns:[{key:"rank",label:"Rank",num:!0},{key:"kind",label:"Kind",render:o=>e(O,{tone:s(o.kind),children:String(o.kind).charAt(0).toUpperCase()+String(o.kind).slice(1)})},{key:"ref",label:"Change",primary:!0,render:o=>e(c,{children:[l(o.ref),o.title?e("span",{class:"muted",children:[" ",o.title]}):null]})},{key:"why",label:"Why it's here",render:o=>e("span",{class:"muted",children:o.why})}],empty:e(_,{children:e("p",{class:"blk-note",children:["Nothing was deployed or merged in the ",n.window_hours??72," hours before it."]})})})})),e("p",{class:"blk-note",children:"Ranked by: the deployment the incident is tied to (or the last one before it), pull requests a revert later undid, the ones that shipped in that deployment, then closeness in time. Dependency and configuration changes are marked. A starting point, not a verdict."})]})}function ue({app:t,q:a}){let l=Object.entries(a.removals||{});return e(c,{children:[e(k,{children:[e(i,{label:"Through the queue",value:a.prs,note:`${a.merged} merged, last ${a.window_days} days`}),e(i,{label:"Entering to merge, median",value:y(a.p50_h),note:`9 in 10 within ${y(a.p90_h)}`}),e(i,{label:"Taken out",value:l.reduce((s,[,n])=>s+n,0),note:l.map(([s,n])=>`${s.toLowerCase().replace(/_/g," ")} ${n}`).join(", ")||"none"}),e(i,{label:"Taken out by a flaky job",value:(a.removed_by_flakes||[]).length,note:`${a.failed_runs} of ${a.runs} merge-group runs failed`})]}),e(b,{title:"Removals that a flaky job caused",children:e(g,{name:"queue-flakes",search:!1,rows:a.removed_by_flakes||[],columns:[{key:"pr",label:"Pull request",primary:!0,render:s=>e("a",{href:H(t,`/pull/${s.pr}`),...q,children:["#",s.pr]})},{key:"at",label:"Taken out",render:s=>v(s.at)},{key:"jobs",label:"Flaky jobs",raw:s=>s.jobs.join(", ")}],empty:e(_,{children:e(P,{icon:"check",title:"No removal followed a flaky job.",children:"A pull request taken out after a merge-group run that failed only on known flaky jobs shows here."})})})})]})}function me({b:t,repo:a}){let l=t.weeks||[],s=l[l.length-1]||{},n=o=>E(o.url)?e("a",{href:E(o.url),children:o.id}):o.src==="github"&&a?e("a",{href:`https://github.com/${a}/issues/${o.id}`,children:["#",o.id]}):String(o.id);return e(c,{children:[e(k,{children:[e(i,{label:"Open bugs",value:t.open??0,note:t.median_open_days==null?"none open":`half older than ${t.median_open_days} days`}),e(i,{label:"Opened this week",value:s.opened??0}),e(i,{label:"Closed this week",value:s.closed??0})]}),e(N,{title:"Bugs still open at the end of each week",children:e(T,{label:"Bugs still open at the end of each week",kind:"count",height:160,bars:l.map(o=>({label:I(o.week),value:o.open}))})}),e(b,{title:"Week by week",note:"newest first",children:e(g,{name:"bug-weeks",search:!1,rows:[...l].reverse(),columns:[{key:"week",label:"Week of",primary:!0,render:o=>I(o.week)},{key:"opened",label:"Opened",num:!0},{key:"closed",label:"Closed",num:!0},{key:"open",label:"Open at the end",num:!0}]})}),(t.oldest||[]).length?e(b,{title:"Oldest open bugs",note:`from ${(t.sources||[]).join(", ")}`,children:e(g,{name:"bug-oldest",search:!1,rows:t.oldest,columns:[{key:"id",label:"Bug",primary:!0,render:n},{key:"days",label:"Open for (days)",num:!0}]})}):null]})}function pe({rows:t,repo:a}){let l=s=>a?e("a",{href:`https://github.com/${a}/pull/${s}`,children:["#",s]}):`#${s}`;return e(b,{title:"What each release shipped",note:"and what followed it in the next two weeks",children:e(g,{name:"releases",search:!1,caption:"What each release shipped and what followed it (two weeks)",rows:t,columns:[{key:"tag",label:"Release",primary:!0,render:s=>a?e("a",{href:`https://github.com/${a}/releases/tag/${encodeURIComponent(s.tag)}`,children:s.tag}):s.tag},{key:"at",label:"Out",render:s=>v(s.at)},{key:"prs",label:"PRs",num:!0},{key:"fix_share",label:"Fixes",num:!0,render:s=>s.fix_share==null?"\u2013":m(s.fix_share)},{key:"reverted",label:"Its PRs reverted",raw:s=>s.reverted.length,render:s=>s.reverted.length?e(c,{children:s.reverted.map((n,o)=>e(c,{children:[o?", ":"",l(n)]}))}):"none"},{key:"incidents_after",label:"Incidents after",num:!0,render:s=>`${s.incidents_after}${s.settled?"":" so far"}`}]})})}function ce({rows:t,repo:a}){let l=n=>a?e("a",{href:`https://github.com/${a}/pull/${n}`,children:["#",n]}):`#${n}`,s=n=>n.length?e(c,{children:[n.slice(0,8).map((o,p)=>e(c,{children:[p?", ":"",l(o)]})),n.length>8?` +${n.length-8}`:""]}):"none";return e(b,{title:"Deployments in the window",note:"newest first; what each shipped, its lead time and incidents",children:e(g,{name:"deploys",search:!1,caption:"Deployments in the window, newest first",rows:t,columns:[{key:"finished",label:"Finished",primary:!0,render:n=>v(n.finished)},{key:"sha",label:"Commit",render:n=>n.sha&&a?e("a",{href:`https://github.com/${a}/commit/${n.sha}`,children:e("code",{children:String(n.sha).slice(0,7)})}):n.name||"\u2013"},{key:"prs",label:"Pull requests",raw:n=>n.prs.length,render:n=>s(n.prs)},{key:"authors",label:"Authors",num:!0},{key:"lead_hours",label:"Lead time",num:!0,render:n=>n.lead_hours==null?"\u2013":y(n.lead_hours)},{key:"incidents",label:"Incidents",raw:n=>n.incidents.length,render:n=>n.incidents.length?n.incidents.join(", "):"none"}]})})}var U=t=>{let a=[...t].sort((l,s)=>l-s);return a.length?a[Math.floor((a.length-1)/2)]:null};function he({rows:t}){let a=u=>u.toISOString().slice(0,10),[l,s]=F(a(new Date(Date.now()-2592e6))),[n,o]=F(a(new Date)),p=a(new Date(new Date(n).getTime()+864e5)),d=(t.deployments||[]).filter(([u])=>u>=l&&u<p),C=(t.prs||[]).filter(([u])=>u>=l&&u<p),A=Math.max(1,Math.ceil((new Date(p).getTime()-new Date(l).getTime())/(7*864e5))),R=Array.from({length:A},(u,r)=>{let h=a(new Date(new Date(l).getTime()+r*7*864e5)),D=a(new Date(new Date(l).getTime()+(r+1)*7*864e5));return new Set(d.filter(([w])=>w>=h&&w<D).map(([w])=>w.slice(0,10))).size}),f=d.filter(([,u])=>u),$=U(f.map(([,,u])=>u).filter(u=>u!=null)),M=U(C.map(([,u])=>u));return e(c,{children:[e("p",{class:"blk-note",children:"Any dates in the last year. Deployment days a week is the median week (weeks with none count), as DevLake counts it."}),e("div",{class:"range-pick",children:[e("label",{children:["From ",e("input",{type:"date",value:l,max:n,onInput:u=>s(u.target.value)})]})," ",e("label",{children:["To ",e("input",{type:"date",value:n,min:l,onInput:u=>o(u.target.value)})]})]}),e(k,{children:[e(i,{label:"Deployments",value:d.length,note:`${U(R)??0} deployment days in the median week`}),e(i,{label:"Lead time",value:M==null?"\u2013":y(M),note:`median of ${C.length} PRs shipped`}),e(i,{label:"Change fail rate",value:d.length?m(f.length/d.length):"\u2013",note:`${f.length} deployments followed by an incident`}),e(i,{label:"Recovery",value:$==null?"\u2013":y($),note:"median, failed deployments"})]})]})}function ge({q:t}){let a=t.measures||{},l=t.month_ago||{},s=(n,o=!0)=>l[n]==null||a[n]==null?void 0:`${a[n]-l[n]>=0?"+":""}${Math.round((a[n]-l[n])*10)/10} in a month${a[n]>l[n]===o&&a[n]!==l[n]?" (worse)":""}`;return e(c,{children:[e(k,{children:[e(i,{label:"Quality gate",value:e("span",{class:`dl-gate dl-gate-${t.gate==="OK"?"good":t.gate==="ERROR"?"bad":"none"}`,children:t.gate==="OK"?"passed":t.gate==="ERROR"?"failed":t.gate||"none"}),note:(t.failing||[]).length?`failing: ${t.failing.join(", ")}`:`${t.project}, read ${t.day}`}),e(i,{label:"Bugs",value:a.bugs??"\u2013",note:s("bugs")}),e(i,{label:"Vulnerabilities",value:a.vulnerabilities??"\u2013",note:s("vulnerabilities")}),e(i,{label:"Code smells",value:a.code_smells??"\u2013",note:s("code_smells")}),e(i,{label:"Coverage",value:a.coverage==null?"\u2013":`${a.coverage}%`,note:s("coverage",!1)}),e(i,{label:"Duplication",value:a.duplicated_lines_density==null?"\u2013":`${a.duplicated_lines_density}%`,note:s("duplicated_lines_density")})]}),(t.days||[]).length>7?e(T,{label:"Coverage by week",kind:"count",height:140,bars:t.days.filter(n=>n.coverage!=null).filter((n,o,p)=>(p.length-1-o)%7===0).map(n=>({label:I(n.day),value:n.coverage}))}):null]})}export{le as AI,me as Bugs,de as Changed,ce as Deploys,oe as Issues,ge as Quality,ue as Queue,he as Range,pe as Releases,ie as Risk};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.blk-tbl{min-width:0}.blk-tbl+.blk-tbl,.stats+.blk-tbl,.blk-tbl+.stats,.blk-facts+.blk-tbl,.blk-tbl+.blk-facts,.blk-panel+.blk-tbl,.blk-tbl+.blk-panel,.dl-strip+.blk-tbl,.blk-tbl+.blk-grid,.blk-grid+.blk-tbl,.stats+.blk-panel,.blk-panel+.blk-panel,.stats+.blk-grid{margin-top:18px}.blk-tbl-h{display:flex;gap:4px 12px;align-items:baseline;flex-wrap:wrap;padding:10px 14px;background:var(--surface);border:1px solid var(--line);border-bottom:0;border-radius:var(--r-lg) var(--r-lg) 0 0}.blk-tbl-h h3{margin:0;font-size:15.5px;font-weight:700}.blk-tbl-note{font-size:13px;color:var(--ink-2)}.blk-tbl-act{margin-left:auto;display:inline-flex;gap:8px;align-items:center}.blk-tbl .table-wrap{border-top-left-radius:0;border-top-right-radius:0}.blk-tbl>.card:not(.table-wrap){border-top-left-radius:0;border-top-right-radius:0}@media(min-width:641px){.blk-tbl .table :is(th,td)+:is(th,td){border-left:1px solid var(--line)}}.blk-h{display:flex;gap:4px 12px;align-items:baseline;flex-wrap:wrap;margin:26px 0 10px;font-size:16px;font-weight:700}.blk-h:first-child{margin-top:0}.blk-h-note{font-size:13.5px;font-weight:400;color:var(--ink-2)}.blk-panel{display:flex;flex-direction:column;min-width:0;background:var(--surface);border:1px solid var(--line);border-radius:var(--r-lg);overflow:hidden}.blk-panel-h{display:flex;gap:6px 12px;align-items:center;justify-content:space-between;flex-wrap:wrap;min-height:44px;padding:10px 16px;background:var(--surface-2);border-bottom:1px solid var(--line)}.blk-panel-h h3{margin:0;font-size:15.5px;font-weight:700;overflow-wrap:anywhere;min-width:0}.blk-panel-state{font-size:14px;font-weight:600}.blk-panel-b{flex:1;display:flex;flex-direction:column;gap:14px;padding:14px 16px 16px;min-width:0}.blk-panel-b>*{margin:0}.blk-bar{display:flex;gap:8px;align-items:center;flex-wrap:wrap;padding:10px 16px;border-top:1px solid var(--line);background:var(--surface-2)}.blk-panel.blk-good{border-top:4px solid var(--good)}.blk-panel.blk-watch{border-top:4px solid var(--watch)}.blk-panel.blk-bad{border-top:4px solid var(--bad)}.blk-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,320px),1fr));gap:12px;align-items:stretch}.blk-grid>:is(.blk-tbl,.blk-panel){margin-top:0}.blk-facts{display:grid;grid-template-columns:max-content minmax(0,1fr);gap:8px 18px;margin:0;font-size:14px}.blk-fact{display:contents}.blk-fact dt{font-weight:650;color:var(--ink-2)}.blk-fact dd{margin:0;min-width:0;overflow-wrap:anywhere}@media(max-width:520px){.blk-facts{grid-template-columns:minmax(0,1fr);gap:2px}.blk-fact dd{margin-bottom:8px}}.blk-mark{display:inline-flex;align-items:center;gap:7px;font-weight:650;white-space:nowrap}.blk-mark i{width:9px;height:9px;border-radius:50%;flex:none;background:var(--ink-3)}.blk-mark-good i{background:var(--good)}.blk-mark-watch i{background:var(--watch)}.blk-mark-bad i{background:var(--bad)}.blk-mark-accent i{background:var(--accent)}.blk-mark-neutral i{background:none;border:1.5px solid var(--ink-2)}.blk-mark-good{color:var(--good)}.blk-mark-bad{color:var(--bad)}.blk-mark-watch{color:var(--watch)}.blk-mark-neutral{color:var(--ink-2)}.blk-machine .blk-machine-cmd{display:flex;flex-direction:column;gap:10px;min-width:0}.blk-form{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,220px),1fr));gap:12px 16px;align-items:start}.blk-form .field{min-width:0}.blk-form textarea.input{min-height:96px;padding:10px 12px;resize:vertical;font:400 14px/1.5 var(--mono);width:100%}.blk-note{font-size:13.5px;color:var(--ink-2);margin:0;max-width:80ch}.blk-list{margin:0;padding-left:20px;display:grid;gap:4px;font-size:14px}[data-design=sheet]:is([data-page=prs],[data-page=delivery],[data-page=investment]) .blk-tbl-h{min-height:42px;padding:9px 14px;background:var(--strip);border:1.5px solid var(--frame);border-bottom:1px solid var(--line-strong);border-radius:0}[data-design=sheet]:is([data-page=prs],[data-page=delivery],[data-page=investment]) .blk-tbl-h h3{font-size:15.5px;font-weight:700;color:var(--ink)}[data-design=sheet]:is([data-page=prs],[data-page=delivery],[data-page=investment]) .blk-tbl-note{font-size:14px;color:var(--ink-2)}[data-design=sheet]:is([data-page=prs],[data-page=delivery],[data-page=investment]) .blk-tbl>:is(.table-wrap,.card){border:1.5px solid var(--frame);border-top:0}@media(min-width:641px){[data-design=sheet]:is([data-page=prs],[data-page=delivery],[data-page=investment]) .blk-tbl .table :is(th,td)+:is(th,td){border-left-color:var(--line)}}[data-design=sheet]:is([data-page=prs],[data-page=delivery],[data-page=investment]) .blk-panel{border:1.5px solid var(--frame);border-radius:0}[data-design=sheet]:is([data-page=prs],[data-page=delivery],[data-page=investment]) .blk-panel.blk-good{border-top:5px solid var(--sv-mint)}[data-design=sheet]:is([data-page=prs],[data-page=delivery],[data-page=investment]) .blk-panel.blk-watch{border-top:5px solid var(--sv-amber)}[data-design=sheet]:is([data-page=prs],[data-page=delivery],[data-page=investment]) .blk-panel.blk-bad{border-top:5px solid var(--sv-coral)}[data-design=sheet]:is([data-page=prs],[data-page=delivery],[data-page=investment]) .blk-panel-h{min-height:42px;padding:9px 14px;background:var(--strip);border-bottom:1px solid var(--line-strong)}[data-design=sheet]:is([data-page=prs],[data-page=delivery],[data-page=investment]) .blk-panel-h h3{font-size:15.5px;color:var(--ink)}[data-design=sheet]:is([data-page=prs],[data-page=delivery],[data-page=investment]) .blk-panel-state{font-size:15px}[data-design=sheet]:is([data-page=prs],[data-page=delivery],[data-page=investment]) .blk-panel-b{padding:14px;font-size:15px}[data-design=sheet]:is([data-page=prs],[data-page=delivery],[data-page=investment]) .blk-bar{padding:10px 14px;background:var(--surface);border-top:1px solid var(--line-strong)}[data-design=sheet]:is([data-page=prs],[data-page=delivery],[data-page=investment]) .blk-facts{font-size:15px;gap:8px 20px}[data-design=sheet]:is([data-page=prs],[data-page=delivery],[data-page=investment]) .blk-fact dt{font-weight:600;color:var(--ink-2)}[data-design=sheet]:is([data-page=prs],[data-page=delivery],[data-page=investment]) .blk-mark{font-size:15px;font-weight:700;color:var(--ink)}[data-design=sheet]:is([data-page=prs],[data-page=delivery],[data-page=investment]) .blk-mark i{width:13px;height:13px;border:0;border-radius:0;background:center / contain no-repeat}[data-design=sheet]:is([data-page=prs],[data-page=delivery],[data-page=investment]) .blk-mark-good i{background-image:var(--mark-good)}[data-design=sheet]:is([data-page=prs],[data-page=delivery],[data-page=investment]) .blk-mark-watch i{background-image:var(--mark-watch)}[data-design=sheet]:is([data-page=prs],[data-page=delivery],[data-page=investment]) .blk-mark-bad i{background-image:var(--mark-bad)}[data-design=sheet]:is([data-page=prs],[data-page=delivery],[data-page=investment]) .blk-mark-good{color:var(--good)}[data-design=sheet]:is([data-page=prs],[data-page=delivery],[data-page=investment]) .blk-mark-bad{color:var(--bad)}[data-design=sheet]:is([data-page=prs],[data-page=delivery],[data-page=investment]) .blk-mark-watch{color:var(--watch)}[data-design=sheet]:is([data-page=prs],[data-page=delivery],[data-page=investment]) .blk-mark-neutral{color:var(--ink-2)}[data-design=sheet]:is([data-page=prs],[data-page=delivery],[data-page=investment]) .blk-mark-neutral i{width:10px;height:10px;border:1.5px solid currentColor}[data-design=sheet]:is([data-page=prs],[data-page=delivery],[data-page=investment]) .blk-mark-accent i{width:10px;height:10px;background:var(--sv-blue)}[data-design=sheet]:is([data-page=prs],[data-page=delivery],[data-page=investment]) .blk-note{font-size:15px}[data-design=sheet]:is([data-page=prs],[data-page=delivery],[data-page=investment]) .blk-list{font-size:15px}[data-design=sheet]:is([data-page=prs],[data-page=delivery],[data-page=investment]) .blk-form textarea.input{border-radius:0}[data-design=sheet]:is([data-page=prs],[data-page=delivery],[data-page=investment]) .blk-h{padding-bottom:6px;border-bottom:1.5px solid var(--frame);font-size:17px;color:var(--ink)}[data-design=sheet]:is([data-page=prs],[data-page=delivery],[data-page=investment]) .blk-h-note{font-size:15px}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import{a as ce,b as wr,c as Q,d as _}from"./chunk-G7NGB5UX.js";var we=wr(()=>{_()});var W=wr((Oe,lr)=>{_();(function(u){"use strict";var f=function(r,n){this.hi=0|r,this.lo=0|n},i=function(r){var n,e=new Float64Array(16);if(r)for(n=0;n<r.length;n++)e[n]=r[n];return e},y=function(){throw new Error("no PRNG")},v=new Uint8Array(16),x=new Uint8Array(32);x[0]=9;var E=i(),R=i([1]),D=i([56129,1]),C=i([30883,4953,19914,30187,55467,16705,2637,112,59544,30585,16505,36039,65139,11119,27886,20995]),S=i([61785,9906,39828,60374,45398,33411,5274,224,53552,61171,33010,6542,64743,22239,55772,9222]),B=i([54554,36645,11616,51542,42930,38181,51040,26924,56412,64982,57905,49316,21502,52590,14035,8553]),Gr=i([26200,26214,26214,26214,26214,26214,26214,26214,26214,26214,26214,26214,26214,26214,26214,26214]),Ee=i([41136,18958,6951,50414,58488,44335,6150,12099,55207,15867,153,11085,57099,20417,9344,11139]);function er(r,n){return r<<n|r>>>32-n}function O(r,n){var e=255&r[n+3];return(e=(e=e<<8|255&r[n+2])<<8|255&r[n+1])<<8|255&r[n+0]}function Dr(r,n){var e=r[n]<<24|r[n+1]<<16|r[n+2]<<8|r[n+3],t=r[n+4]<<24|r[n+5]<<16|r[n+6]<<8|r[n+7];return new f(e,t)}function gr(r,n,e){var t;for(t=0;t<4;t++)r[n+t]=255&e,e>>>=8}function Or(r,n,e){r[n]=e.hi>>24&255,r[n+1]=e.hi>>16&255,r[n+2]=e.hi>>8&255,r[n+3]=255&e.hi,r[n+4]=e.lo>>24&255,r[n+5]=e.lo>>16&255,r[n+6]=e.lo>>8&255,r[n+7]=255&e.lo}function pr(r,n,e,t,o){var a,s=0;for(a=0;a<o;a++)s|=r[n+a]^e[t+a];return(1&s-1>>>8)-1}function Fr(r,n,e,t){return pr(r,n,e,t,16)}function vr(r,n,e,t){return pr(r,n,e,t,32)}function Nr(r,n,e,t,o){var a,s,l,c=new Uint32Array(16),w=new Uint32Array(16),g=new Uint32Array(16),h=new Uint32Array(4);for(a=0;a<4;a++)w[5*a]=O(t,4*a),w[1+a]=O(e,4*a),w[6+a]=O(n,4*a),w[11+a]=O(e,16+4*a);for(a=0;a<16;a++)g[a]=w[a];for(a=0;a<20;a++){for(s=0;s<4;s++){for(l=0;l<4;l++)h[l]=w[(5*s+4*l)%16];for(h[1]^=er(h[0]+h[3]|0,7),h[2]^=er(h[1]+h[0]|0,9),h[3]^=er(h[2]+h[1]|0,13),h[0]^=er(h[3]+h[2]|0,18),l=0;l<4;l++)c[4*s+(s+l)%4]=h[l]}for(l=0;l<16;l++)w[l]=c[l]}if(o){for(a=0;a<16;a++)w[a]=w[a]+g[a]|0;for(a=0;a<4;a++)w[5*a]=w[5*a]-O(t,4*a)|0,w[6+a]=w[6+a]-O(n,4*a)|0;for(a=0;a<4;a++)gr(r,4*a,w[5*a]),gr(r,16+4*a,w[6+a])}else for(a=0;a<16;a++)gr(r,4*a,w[a]+g[a]|0)}function Hr(r,n,e,t){Nr(r,n,e,t,!1)}function nr(r,n,e,t){return Nr(r,n,e,t,!0),0}var q=new Uint8Array([101,120,112,97,110,100,32,51,50,45,98,121,116,101,32,107]);function Ar(r,n,e,t,o,a,s){var l,c,w=new Uint8Array(16),g=new Uint8Array(64);if(!o)return 0;for(c=0;c<16;c++)w[c]=0;for(c=0;c<8;c++)w[c]=a[c];for(;64<=o;){for(Hr(g,w,s,q),c=0;c<64;c++)r[n+c]=(e?e[t+c]:0)^g[c];for(l=1,c=8;c<16;c++)l=l+(255&w[c])|0,w[c]=255&l,l>>>=8;o-=64,n+=64,e&&(t+=64)}if(0<o)for(Hr(g,w,s,q),c=0;c<o;c++)r[n+c]=(e?e[t+c]:0)^g[c];return 0}function Zr(r,n,e,t,o){return Ar(r,n,null,0,e,t,o)}function qr(r,n,e,t,o){var a=new Uint8Array(32);return nr(a,t,o,q),Zr(r,n,e,t.subarray(16),a)}function Ur(r,n,e,t,o,a,s){var l=new Uint8Array(32);return nr(l,a,s,q),Ar(r,n,e,t,o,a.subarray(16),l)}function xr(r,n){var e,t=0;for(e=0;e<17;e++)t=t+(r[e]+n[e]|0)|0,r[e]=255&t,t>>>=8}var Be=new Uint32Array([5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,252]);function mr(r,n,e,t,o,a){var s,l,c,w,g=new Uint32Array(17),h=new Uint32Array(17),p=new Uint32Array(17),U=new Uint32Array(17),m=new Uint32Array(17);for(c=0;c<17;c++)h[c]=p[c]=0;for(c=0;c<16;c++)h[c]=a[c];for(h[3]&=15,h[4]&=252,h[7]&=15,h[8]&=252,h[11]&=15,h[12]&=252,h[15]&=15;0<o;){for(c=0;c<17;c++)U[c]=0;for(c=0;c<16&&c<o;++c)U[c]=e[t+c];for(U[c]=1,t+=c,o-=c,xr(p,U),l=0;l<17;l++)for(c=g[l]=0;c<17;c++)g[l]=g[l]+p[c]*(c<=l?h[l-c]:320*h[l+17-c]|0)|0;for(l=0;l<17;l++)p[l]=g[l];for(c=w=0;c<16;c++)w=w+p[c]|0,p[c]=255&w,w>>>=8;for(w=w+p[16]|0,p[16]=3&w,w=5*(w>>>2)|0,c=0;c<16;c++)w=w+p[c]|0,p[c]=255&w,w>>>=8;w=w+p[16]|0,p[16]=w}for(c=0;c<17;c++)m[c]=p[c];for(xr(p,Be),s=0|-(p[16]>>>7),c=0;c<17;c++)p[c]^=s&(m[c]^p[c]);for(c=0;c<16;c++)U[c]=a[c+16];for(U[16]=0,xr(p,U),c=0;c<16;c++)r[n+c]=p[c];return 0}function Vr(r,n,e,t,o,a){var s=new Uint8Array(16);return mr(s,0,e,t,o,a),Fr(r,n,s,0)}function _r(r,n,e,t,o){var a;if(e<32)return-1;for(Ur(r,0,n,0,e,t,o),mr(r,16,r,32,e-32,r),a=0;a<16;a++)r[a]=0;return 0}function dr(r,n,e,t,o){var a,s=new Uint8Array(32);if(e<32||(qr(s,0,32,t,o),Vr(n,16,n,32,e-32,s)!==0))return-1;for(Ur(r,0,n,0,e,t,o),a=0;a<32;a++)r[a]=0;return 0}function I(r,n){var e;for(e=0;e<16;e++)r[e]=0|n[e]}function V(r){var n,e;for(e=0;e<16;e++)r[e]+=65536,n=Math.floor(r[e]/65536),r[(e+1)*(e<15?1:0)]+=n-1+37*(n-1)*(e===15?1:0),r[e]-=65536*n}function F(r,n,e){for(var t,o=~(e-1),a=0;a<16;a++)t=o&(r[a]^n[a]),r[a]^=t,n[a]^=t}function N(r,n){var e,t,o,a=i(),s=i();for(e=0;e<16;e++)s[e]=n[e];for(V(s),V(s),V(s),t=0;t<2;t++){for(a[0]=s[0]-65517,e=1;e<15;e++)a[e]=s[e]-65535-(a[e-1]>>16&1),a[e-1]&=65535;a[15]=s[15]-32767-(a[14]>>16&1),o=a[15]>>16&1,a[14]&=65535,F(s,a,1-o)}for(e=0;e<16;e++)r[2*e]=255&s[e],r[2*e+1]=s[e]>>8}function jr(r,n){var e=new Uint8Array(32),t=new Uint8Array(32);return N(e,r),N(t,n),vr(e,0,t,0)}function Xr(r){var n=new Uint8Array(32);return N(n,r),1&n[0]}function Er(r,n){var e;for(e=0;e<16;e++)r[e]=n[2*e]+(n[2*e+1]<<8);r[15]&=32767}function L(r,n,e){var t;for(t=0;t<16;t++)r[t]=n[t]+e[t]|0}function T(r,n,e){var t;for(t=0;t<16;t++)r[t]=n[t]-e[t]|0}function A(r,n,e){var t,o,a=new Float64Array(31);for(t=0;t<31;t++)a[t]=0;for(t=0;t<16;t++)for(o=0;o<16;o++)a[t+o]+=n[t]*e[o];for(t=0;t<15;t++)a[t]+=38*a[t+16];for(t=0;t<16;t++)r[t]=a[t];V(r),V(r)}function K(r,n){A(r,n,n)}function Jr(r,n){var e,t=i();for(e=0;e<16;e++)t[e]=n[e];for(e=253;0<=e;e--)K(t,t),e!==2&&e!==4&&A(t,t,n);for(e=0;e<16;e++)r[e]=t[e]}function Qr(r,n){var e,t=i();for(e=0;e<16;e++)t[e]=n[e];for(e=250;0<=e;e--)K(t,t),e!==1&&A(t,t,n);for(e=0;e<16;e++)r[e]=t[e]}function tr(r,n,e){var t,o,a=new Uint8Array(32),s=new Float64Array(80),l=i(),c=i(),w=i(),g=i(),h=i(),p=i();for(o=0;o<31;o++)a[o]=n[o];for(a[31]=127&n[31]|64,a[0]&=248,Er(s,e),o=0;o<16;o++)c[o]=s[o],g[o]=l[o]=w[o]=0;for(l[0]=g[0]=1,o=254;0<=o;--o)F(l,c,t=a[o>>>3]>>>(7&o)&1),F(w,g,t),L(h,l,w),T(l,l,w),L(w,c,g),T(c,c,g),K(g,h),K(p,l),A(l,w,l),A(w,c,h),L(h,l,w),T(l,l,w),K(c,l),T(w,g,p),A(l,w,D),L(l,l,g),A(w,w,l),A(l,g,p),A(g,c,s),K(c,h),F(l,c,t),F(w,g,t);for(o=0;o<16;o++)s[o+16]=l[o],s[o+32]=w[o],s[o+48]=c[o],s[o+64]=g[o];var U=s.subarray(32),m=s.subarray(16);return Jr(U,U),A(m,m,U),N(r,m),0}function or(r,n){return tr(r,n,x)}function Wr(r,n){return y(n,32),or(r,n)}function ar(r,n,e){var t=new Uint8Array(32);return tr(t,e,n),nr(r,v,t,q)}var $r=_r,ke=dr;function j(){var r,n,e,t=0,o=0,a=0,s=0,l=65535;for(e=0;e<arguments.length;e++)t+=(r=arguments[e].lo)&l,o+=r>>>16,a+=(n=arguments[e].hi)&l,s+=n>>>16;return new f((a+=(o+=t>>>16)>>>16)&l|(s+=a>>>16)<<16,t&l|o<<16)}function re(r,n){return new f(r.hi>>>n,r.lo>>>n|r.hi<<32-n)}function fr(){var r,n=0,e=0;for(r=0;r<arguments.length;r++)n^=arguments[r].lo,e^=arguments[r].hi;return new f(e,n)}function Y(r,n){var e,t,o=32-n;return n<32?(e=r.hi>>>n|r.lo<<o,t=r.lo>>>n|r.hi<<o):n<64&&(e=r.lo>>>n|r.hi<<o,t=r.hi>>>n|r.lo<<o),new f(e,t)}var Se=[new f(1116352408,3609767458),new f(1899447441,602891725),new f(3049323471,3964484399),new f(3921009573,2173295548),new f(961987163,4081628472),new f(1508970993,3053834265),new f(2453635748,2937671579),new f(2870763221,3664609560),new f(3624381080,2734883394),new f(310598401,1164996542),new f(607225278,1323610764),new f(1426881987,3590304994),new f(1925078388,4068182383),new f(2162078206,991336113),new f(2614888103,633803317),new f(3248222580,3479774868),new f(3835390401,2666613458),new f(4022224774,944711139),new f(264347078,2341262773),new f(604807628,2007800933),new f(770255983,1495990901),new f(1249150122,1856431235),new f(1555081692,3175218132),new f(1996064986,2198950837),new f(2554220882,3999719339),new f(2821834349,766784016),new f(2952996808,2566594879),new f(3210313671,3203337956),new f(3336571891,1034457026),new f(3584528711,2466948901),new f(113926993,3758326383),new f(338241895,168717936),new f(666307205,1188179964),new f(773529912,1546045734),new f(1294757372,1522805485),new f(1396182291,2643833823),new f(1695183700,2343527390),new f(1986661051,1014477480),new f(2177026350,1206759142),new f(2456956037,344077627),new f(2730485921,1290863460),new f(2820302411,3158454273),new f(3259730800,3505952657),new f(3345764771,106217008),new f(3516065817,3606008344),new f(3600352804,1432725776),new f(4094571909,1467031594),new f(275423344,851169720),new f(430227734,3100823752),new f(506948616,1363258195),new f(659060556,3750685593),new f(883997877,3785050280),new f(958139571,3318307427),new f(1322822218,3812723403),new f(1537002063,2003034995),new f(1747873779,3602036899),new f(1955562222,1575990012),new f(2024104815,1125592928),new f(2227730452,2716904306),new f(2361852424,442776044),new f(2428436474,593698344),new f(2756734187,3733110249),new f(3204031479,2999351573),new f(3329325298,3815920427),new f(3391569614,3928383900),new f(3515267271,566280711),new f(3940187606,3454069534),new f(4118630271,4000239992),new f(116418474,1914138554),new f(174292421,2731055270),new f(289380356,3203993006),new f(460393269,320620315),new f(685471733,587496836),new f(852142971,1086792851),new f(1017036298,365543100),new f(1126000580,2618297676),new f(1288033470,3409855158),new f(1501505948,4234509866),new f(1607167915,987167468),new f(1816402316,1246189591)];function ee(r,n,e){var t,o,a,s=[],l=[],c=[],w=[];for(o=0;o<8;o++)s[o]=c[o]=Dr(r,8*o);for(var g,h,p,U,m,H,X,Z,J,Yr,zr,fe,ie,Ir,ue=0;128<=e;){for(o=0;o<16;o++)w[o]=Dr(n,8*o+ue);for(o=0;o<80;o++){for(a=0;a<8;a++)l[a]=c[a];for(t=j(c[7],fr(Y(Ir=c[4],14),Y(Ir,18),Y(Ir,41)),(J=c[4],Yr=c[5],zr=c[6],fe=J.hi&Yr.hi^~J.hi&zr.hi,ie=J.lo&Yr.lo^~J.lo&zr.lo,new f(fe,ie)),Se[o],w[o%16]),l[7]=j(t,fr(Y(Z=c[0],28),Y(Z,34),Y(Z,39)),(p=c[0],U=c[1],m=c[2],H=p.hi&U.hi^p.hi&m.hi^U.hi&m.hi,X=p.lo&U.lo^p.lo&m.lo^U.lo&m.lo,new f(H,X))),l[3]=j(l[3],t),a=0;a<8;a++)c[(a+1)%8]=l[a];if(o%16==15)for(a=0;a<16;a++)w[a]=j(w[a],w[(a+9)%16],fr(Y(h=w[(a+1)%16],1),Y(h,8),re(h,7)),fr(Y(g=w[(a+14)%16],19),Y(g,61),re(g,6)))}for(o=0;o<8;o++)c[o]=j(c[o],s[o]),s[o]=c[o];ue+=128,e-=128}for(o=0;o<8;o++)Or(r,8*o,s[o]);return e}var Ke=new Uint8Array([106,9,230,103,243,188,201,8,187,103,174,133,132,202,167,59,60,110,243,114,254,148,248,43,165,79,245,58,95,29,54,241,81,14,82,127,173,230,130,209,155,5,104,140,43,62,108,31,31,131,217,171,251,65,189,107,91,224,205,25,19,126,33,121]);function G(r,n,e){var t,o=new Uint8Array(64),a=new Uint8Array(256),s=e;for(t=0;t<64;t++)o[t]=Ke[t];for(ee(o,n,e),e%=128,t=0;t<256;t++)a[t]=0;for(t=0;t<e;t++)a[t]=n[s-e+t];for(a[e]=128,a[(e=256-128*(e<112?1:0))-9]=0,Or(a,e-8,new f(s/536870912|0,s<<3)),ee(o,a,e),t=0;t<64;t++)r[t]=o[t];return 0}function ir(r,n){var e=i(),t=i(),o=i(),a=i(),s=i(),l=i(),c=i(),w=i(),g=i();T(e,r[1],r[0]),T(g,n[1],n[0]),A(e,e,g),L(t,r[0],r[1]),L(g,n[0],n[1]),A(t,t,g),A(o,r[3],n[3]),A(o,o,S),A(a,r[2],n[2]),L(a,a,a),T(s,t,e),T(l,a,o),L(c,a,o),L(w,t,e),A(r[0],s,l),A(r[1],w,c),A(r[2],c,l),A(r[3],s,w)}function ne(r,n,e){var t;for(t=0;t<4;t++)F(r[t],n[t],e)}function Br(r,n){var e=i(),t=i(),o=i();Jr(o,n[2]),A(e,n[0],o),A(t,n[1],o),N(r,t),r[31]^=Xr(e)<<7}function kr(r,n,e){var t,o;for(I(r[0],E),I(r[1],R),I(r[2],R),I(r[3],E),o=255;0<=o;--o)ne(r,n,t=e[o/8|0]>>(7&o)&1),ir(n,r),ir(r,r),ne(r,n,t)}function ur(r,n){var e=[i(),i(),i(),i()];I(e[0],B),I(e[1],Gr),I(e[2],R),A(e[3],B,Gr),kr(r,e,n)}function Sr(r,n,e){var t,o=new Uint8Array(64),a=[i(),i(),i(),i()];for(e||y(n,32),G(o,n,32),o[0]&=248,o[31]&=127,o[31]|=64,ur(a,o),Br(r,a),t=0;t<32;t++)n[t+32]=r[t];return 0}var cr=new Float64Array([237,211,245,92,26,99,18,88,214,156,247,162,222,249,222,20,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16]);function Kr(r,n){var e,t,o,a;for(t=63;32<=t;--t){for(e=0,o=t-32,a=t-12;o<a;++o)n[o]+=e-16*n[t]*cr[o-(t-32)],e=Math.floor((n[o]+128)/256),n[o]-=256*e;n[o]+=e,n[t]=0}for(o=e=0;o<32;o++)n[o]+=e-(n[31]>>4)*cr[o],e=n[o]>>8,n[o]&=255;for(o=0;o<32;o++)n[o]-=e*cr[o];for(t=0;t<32;t++)n[t+1]+=n[t]>>8,r[t]=255&n[t]}function Lr(r){var n,e=new Float64Array(64);for(n=0;n<64;n++)e[n]=r[n];for(n=0;n<64;n++)r[n]=0;Kr(r,e)}function te(r,n,e,t){var o,a,s=new Uint8Array(64),l=new Uint8Array(64),c=new Uint8Array(64),w=new Float64Array(64),g=[i(),i(),i(),i()];G(s,t,32),s[0]&=248,s[31]&=127,s[31]|=64;var h=e+64;for(o=0;o<e;o++)r[64+o]=n[o];for(o=0;o<32;o++)r[32+o]=s[32+o];for(G(c,r.subarray(32),e+32),Lr(c),ur(g,c),Br(r,g),o=32;o<64;o++)r[o]=t[o];for(G(l,r,e+64),Lr(l),o=0;o<64;o++)w[o]=0;for(o=0;o<32;o++)w[o]=c[o];for(o=0;o<32;o++)for(a=0;a<32;a++)w[o+a]+=l[o]*s[a];return Kr(r.subarray(32),w),h}function Tr(r,n,e,t){var o,a=new Uint8Array(32),s=new Uint8Array(64),l=[i(),i(),i(),i()],c=[i(),i(),i(),i()];if(e<64||(function(w,g){var h=i(),p=i(),U=i(),m=i(),H=i(),X=i(),Z=i();if(I(w[2],R),Er(w[1],g),K(U,w[1]),A(m,U,C),T(U,U,w[2]),L(m,w[2],m),K(H,m),K(X,H),A(Z,X,H),A(h,Z,U),A(h,h,m),Qr(h,h),A(h,h,U),A(h,h,m),A(h,h,m),A(w[0],h,m),K(p,w[0]),A(p,p,m),jr(p,U)&&A(w[0],w[0],Ee),K(p,w[0]),A(p,p,m),jr(p,U))return 1;Xr(w[0])===g[31]>>7&&T(w[0],E,w[0]),A(w[3],w[0],w[1])})(c,t))return-1;for(o=0;o<e;o++)r[o]=n[o];for(o=0;o<32;o++)r[o+32]=t[o];if(G(s,r,e),Lr(s),kr(l,c,s),ur(c,n.subarray(32)),ir(l,c),Br(a,l),e-=64,vr(n,0,a,0)){for(o=0;o<e;o++)r[o]=0;return-1}for(o=0;o<e;o++)r[o]=n[o+64];return e}function oe(r,n){if(r.length!==32)throw new Error("bad key size");if(n.length!==24)throw new Error("bad nonce size")}function k(){for(var r=0;r<arguments.length;r++)if(!(arguments[r]instanceof Uint8Array))throw new TypeError("unexpected type, use Uint8Array")}function ae(r){for(var n=0;n<r.length;n++)r[n]=0}u.lowlevel={crypto_core_hsalsa20:nr,crypto_stream_xor:Ur,crypto_stream:qr,crypto_stream_salsa20_xor:Ar,crypto_stream_salsa20:Zr,crypto_onetimeauth:mr,crypto_onetimeauth_verify:Vr,crypto_verify_16:Fr,crypto_verify_32:vr,crypto_secretbox:_r,crypto_secretbox_open:dr,crypto_scalarmult:tr,crypto_scalarmult_base:or,crypto_box_beforenm:ar,crypto_box_afternm:$r,crypto_box:function(r,n,e,t,o,a){var s=new Uint8Array(32);return ar(s,o,a),$r(r,n,e,t,s)},crypto_box_open:function(r,n,e,t,o,a){var s=new Uint8Array(32);return ar(s,o,a),ke(r,n,e,t,s)},crypto_box_keypair:Wr,crypto_hash:G,crypto_sign:te,crypto_sign_keypair:Sr,crypto_sign_open:Tr,crypto_secretbox_KEYBYTES:32,crypto_secretbox_NONCEBYTES:24,crypto_secretbox_ZEROBYTES:32,crypto_secretbox_BOXZEROBYTES:16,crypto_scalarmult_BYTES:32,crypto_scalarmult_SCALARBYTES:32,crypto_box_PUBLICKEYBYTES:32,crypto_box_SECRETKEYBYTES:32,crypto_box_BEFORENMBYTES:32,crypto_box_NONCEBYTES:24,crypto_box_ZEROBYTES:32,crypto_box_BOXZEROBYTES:16,crypto_sign_BYTES:64,crypto_sign_PUBLICKEYBYTES:32,crypto_sign_SECRETKEYBYTES:64,crypto_sign_SEEDBYTES:32,crypto_hash_BYTES:64,gf:i,D:C,L:cr,pack25519:N,unpack25519:Er,M:A,A:L,S:K,Z:T,pow2523:Qr,add:ir,set25519:I,modL:Kr,scalarmult:kr,scalarbase:ur},u.randomBytes=function(r){var n=new Uint8Array(r);return y(n,r),n},u.secretbox=function(r,n,e){k(r,n,e),oe(e,n);for(var t=new Uint8Array(32+r.length),o=new Uint8Array(t.length),a=0;a<r.length;a++)t[a+32]=r[a];return _r(o,t,t.length,n,e),o.subarray(16)},u.secretbox.open=function(r,n,e){k(r,n,e),oe(e,n);for(var t=new Uint8Array(16+r.length),o=new Uint8Array(t.length),a=0;a<r.length;a++)t[a+16]=r[a];return t.length<32||dr(o,t,t.length,n,e)!==0?null:o.subarray(32)},u.secretbox.keyLength=32,u.secretbox.nonceLength=24,u.secretbox.overheadLength=16,u.scalarMult=function(r,n){if(k(r,n),r.length!==32)throw new Error("bad n size");if(n.length!==32)throw new Error("bad p size");var e=new Uint8Array(32);return tr(e,r,n),e},u.scalarMult.base=function(r){if(k(r),r.length!==32)throw new Error("bad n size");var n=new Uint8Array(32);return or(n,r),n},u.scalarMult.scalarLength=32,u.scalarMult.groupElementLength=32,u.box=function(r,n,e,t){var o=u.box.before(e,t);return u.secretbox(r,n,o)},u.box.before=function(r,n){k(r,n),(function(t,o){if(t.length!==32)throw new Error("bad public key size");if(o.length!==32)throw new Error("bad secret key size")})(r,n);var e=new Uint8Array(32);return ar(e,r,n),e},u.box.after=u.secretbox,u.box.open=function(r,n,e,t){var o=u.box.before(e,t);return u.secretbox.open(r,n,o)},u.box.open.after=u.secretbox.open,u.box.keyPair=function(){var r=new Uint8Array(32),n=new Uint8Array(32);return Wr(r,n),{publicKey:r,secretKey:n}},u.box.keyPair.fromSecretKey=function(r){if(k(r),r.length!==32)throw new Error("bad secret key size");var n=new Uint8Array(32);return or(n,r),{publicKey:n,secretKey:new Uint8Array(r)}},u.box.publicKeyLength=32,u.box.secretKeyLength=32,u.box.sharedKeyLength=32,u.box.nonceLength=24,u.box.overheadLength=u.secretbox.overheadLength,u.sign=function(r,n){if(k(r,n),n.length!==64)throw new Error("bad secret key size");var e=new Uint8Array(64+r.length);return te(e,r,r.length,n),e},u.sign.open=function(r,n){if(k(r,n),n.length!==32)throw new Error("bad public key size");var e=new Uint8Array(r.length),t=Tr(e,r,r.length,n);if(t<0)return null;for(var o=new Uint8Array(t),a=0;a<o.length;a++)o[a]=e[a];return o},u.sign.detached=function(r,n){for(var e=u.sign(r,n),t=new Uint8Array(64),o=0;o<t.length;o++)t[o]=e[o];return t},u.sign.detached.verify=function(r,n,e){if(k(r,n,e),n.length!==64)throw new Error("bad signature size");if(e.length!==32)throw new Error("bad public key size");var t,o=new Uint8Array(64+r.length),a=new Uint8Array(64+r.length);for(t=0;t<64;t++)o[t]=n[t];for(t=0;t<r.length;t++)o[t+64]=r[t];return 0<=Tr(a,o,o.length,e)},u.sign.keyPair=function(){var r=new Uint8Array(32),n=new Uint8Array(64);return Sr(r,n),{publicKey:r,secretKey:n}},u.sign.keyPair.fromSecretKey=function(r){if(k(r),r.length!==64)throw new Error("bad secret key size");for(var n=new Uint8Array(32),e=0;e<n.length;e++)n[e]=r[32+e];return{publicKey:n,secretKey:new Uint8Array(r)}},u.sign.keyPair.fromSeed=function(r){if(k(r),r.length!==32)throw new Error("bad seed size");for(var n=new Uint8Array(32),e=new Uint8Array(64),t=0;t<32;t++)e[t]=r[t];return Sr(n,e,!0),{publicKey:n,secretKey:e}},u.sign.publicKeyLength=32,u.sign.secretKeyLength=64,u.sign.seedLength=32,u.sign.signatureLength=64,u.hash=function(r){k(r);var n=new Uint8Array(64);return G(n,r,r.length),n},u.hash.hashLength=64,u.verify=function(r,n){return k(r,n),r.length!==0&&n.length!==0&&r.length===n.length&&pr(r,0,n,0,r.length)===0},u.setPRNG=function(r){y=r},(function(){var r=typeof self<"u"?self.crypto||self.msCrypto:null;r&&r.getRandomValues?u.setPRNG(function(n,e){var t,o=new Uint8Array(e);for(t=0;t<e;t+=65536)r.getRandomValues(o.subarray(t,t+Math.min(e-t,65536)));for(t=0;t<e;t++)n[t]=o[t];ae(o)}):typeof ce<"u"&&(r=we())&&r.randomBytes&&u.setPRNG(function(n,e){var t,o=r.randomBytes(e);for(t=0;t<e;t++)n[t]=o[t];ae(o)})})()})(typeof lr<"u"&&lr.exports?lr.exports:self.nacl=self.nacl||{})});var ye=wr((qe,se)=>{_();var Le="Input must be an string, Buffer or Uint8Array";function Te(u){let f;if(u instanceof Uint8Array)f=u;else if(typeof u=="string")f=new TextEncoder().encode(u);else throw new Error(Le);return f}function Ye(u){return Array.prototype.map.call(u,function(f){return(f<16?"0":"")+f.toString(16)}).join("")}function sr(u){return(4294967296+u).toString(16).substring(1)}function ze(u,f,i){let y=`
|
|
2
|
+
`+u+" = ";for(let v=0;v<f.length;v+=2){if(i===32)y+=sr(f[v]).toUpperCase(),y+=" ",y+=sr(f[v+1]).toUpperCase();else if(i===64)y+=sr(f[v+1]).toUpperCase(),y+=sr(f[v]).toUpperCase();else throw new Error("Invalid size "+i);v%6===4?y+=`
|
|
3
|
+
`+new Array(u.length+4).join(" "):v<f.length-2&&(y+=" ")}console.log(y)}function Ie(u,f,i){let y=new Date().getTime(),v=new Uint8Array(f);for(let E=0;E<f;E++)v[E]=E%256;let x=new Date().getTime();console.log("Generated random input in "+(x-y)+"ms"),y=x;for(let E=0;E<i;E++){let R=u(v),D=new Date().getTime(),C=D-y;y=D,console.log("Hashed in "+C+"ms: "+R.substring(0,20)+"..."),console.log(Math.round(f/(1<<20)/(C/1e3)*100)/100+" MB PER SECOND")}}se.exports={normalizeInput:Te,toHex:Ye,debugPrint:ze,testSpeed:Ie}});var me=wr((je,xe)=>{_();var hr=ye();function yr(u,f,i){let y=u[f]+u[i],v=u[f+1]+u[i+1];y>=4294967296&&v++,u[f]=y,u[f+1]=v}function he(u,f,i,y){let v=u[f]+i;i<0&&(v+=4294967296);let x=u[f+1]+y;v>=4294967296&&x++,u[f]=v,u[f+1]=x}function be(u,f){return u[f]^u[f+1]<<8^u[f+2]<<16^u[f+3]<<24}function M(u,f,i,y,v,x){let E=$[v],R=$[v+1],D=$[x],C=$[x+1];yr(b,u,f),he(b,u,E,R);let S=b[y]^b[u],B=b[y+1]^b[u+1];b[y]=B,b[y+1]=S,yr(b,i,y),S=b[f]^b[i],B=b[f+1]^b[i+1],b[f]=S>>>24^B<<8,b[f+1]=B>>>24^S<<8,yr(b,u,f),he(b,u,D,C),S=b[y]^b[u],B=b[y+1]^b[u+1],b[y]=S>>>16^B<<16,b[y+1]=B>>>16^S<<16,yr(b,i,y),S=b[f]^b[i],B=b[f+1]^b[i+1],b[f]=B>>>31^S<<1,b[f+1]=S>>>31^B<<1}var ge=new Uint32Array([4089235720,1779033703,2227873595,3144134277,4271175723,1013904242,1595750129,2773480762,2917565137,1359893119,725511199,2600822924,4215389547,528734635,327033209,1541459225]),Re=[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,14,10,4,8,9,15,13,6,1,12,0,2,11,7,5,3,11,8,12,0,5,2,15,13,10,14,3,6,7,1,9,4,7,9,3,1,13,12,11,14,2,6,5,10,4,0,15,8,9,0,5,7,2,4,10,15,14,1,11,12,6,8,3,13,2,12,6,10,0,11,8,3,4,13,7,5,15,14,1,9,12,5,1,15,14,13,4,10,0,7,6,3,9,2,8,11,13,11,7,14,12,1,3,9,5,0,15,4,8,6,2,10,6,15,14,9,11,3,0,8,12,2,13,7,1,4,10,5,10,2,8,4,7,6,1,5,15,11,9,14,3,12,13,0,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,14,10,4,8,9,15,13,6,1,12,0,2,11,7,5,3],d=new Uint8Array(Re.map(function(u){return u*2})),b=new Uint32Array(32),$=new Uint32Array(32);function pe(u,f){let i=0;for(i=0;i<16;i++)b[i]=u.h[i],b[i+16]=ge[i];for(b[24]=b[24]^u.t,b[25]=b[25]^u.t/4294967296,f&&(b[28]=~b[28],b[29]=~b[29]),i=0;i<32;i++)$[i]=be(u.b,4*i);for(i=0;i<12;i++)M(0,8,16,24,d[i*16+0],d[i*16+1]),M(2,10,18,26,d[i*16+2],d[i*16+3]),M(4,12,20,28,d[i*16+4],d[i*16+5]),M(6,14,22,30,d[i*16+6],d[i*16+7]),M(0,10,20,30,d[i*16+8],d[i*16+9]),M(2,12,22,24,d[i*16+10],d[i*16+11]),M(4,14,16,26,d[i*16+12],d[i*16+13]),M(6,8,18,28,d[i*16+14],d[i*16+15]);for(i=0;i<16;i++)u.h[i]=u.h[i]^b[i]^b[i+16]}var P=new Uint8Array([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]);function ve(u,f,i,y){if(u===0||u>64)throw new Error("Illegal output length, expected 0 < length <= 64");if(f&&f.length>64)throw new Error("Illegal key, expected Uint8Array with 0 < length <= 64");if(i&&i.length!==16)throw new Error("Illegal salt, expected Uint8Array with length is 16");if(y&&y.length!==16)throw new Error("Illegal personal, expected Uint8Array with length is 16");let v={b:new Uint8Array(128),h:new Uint32Array(16),t:0,c:0,outlen:u};P.fill(0),P[0]=u,f&&(P[1]=f.length),P[2]=1,P[3]=1,i&&P.set(i,32),y&&P.set(y,48);for(let x=0;x<16;x++)v.h[x]=ge[x]^be(P,x*4);return f&&(Mr(v,f),v.c=128),v}function Mr(u,f){for(let i=0;i<f.length;i++)u.c===128&&(u.t+=u.c,pe(u,!1),u.c=0),u.b[u.c++]=f[i]}function Ae(u){for(u.t+=u.c;u.c<128;)u.b[u.c++]=0;pe(u,!0);let f=new Uint8Array(u.outlen);for(let i=0;i<u.outlen;i++)f[i]=u.h[i>>2]>>8*(i&3);return f}function Ue(u,f,i,y,v){i=i||64,u=hr.normalizeInput(u),y&&(y=hr.normalizeInput(y)),v&&(v=hr.normalizeInput(v));let x=ve(i,f,y,v);return Mr(x,u),Ae(x)}function Me(u,f,i,y,v){let x=Ue(u,f,i,y,v);return hr.toHex(x)}xe.exports={blake2b:Ue,blake2bHex:Me,blake2bInit:ve,blake2bUpdate:Mr,blake2bFinal:Ae}});_();_();_();var Rr=Q(W()),le=Rr.default.box.publicKeyLength+Rr.default.box.overheadLength;_();var Pr=Q(W());_();var _e=Q(W()),rr=Q(me());function br(u,f){var i=rr.default.blake2bInit(_e.default.box.nonceLength,null);return rr.default.blake2bUpdate(i,u),rr.default.blake2bUpdate(i,f),rr.default.blake2bFinal(i)}_();function de(u){for(var f=0;f<u.length;f++)u[f]=0}function Cr(u,f){var i=new Uint8Array(le+u.length),y=Pr.default.box.keyPair();i.set(y.publicKey);var v=br(y.publicKey,f),x=Pr.default.box(u,v,f,y.secretKey);return i.set(x,y.publicKey.length),de(y.secretKey),i}_();var Pe=Q(W());export{Cr as seal};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{d as a,e as b,f as c}from"./chunk-T7QVTNXF.js";import"./chunk-VQ5YXO54.js";import"./chunk-GT4EAKAO.js";import"./chunk-G7NGB5UX.js";export{b as freshAccount,a as retoken,c as writeToken};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{d as a,e as b,f as c,g as d,h as e,i as f,j as g,k as h}from"./chunk-576YHDEK.js";import"./chunk-T7QVTNXF.js";import"./chunk-RPXHAG6F.js";import"./chunk-45PGAQRO.js";import"./chunk-VQ5YXO54.js";import"./chunk-GT4EAKAO.js";import"./chunk-G7NGB5UX.js";export{a as SETTINGS_FILE,d as commitFile,e as dispatchRequest,c as isProtected,f as runStatus,b as tokenNow,h as workflowNow,g as workflowText};
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import{b as E}from"./chunk-7II2BD5F.js";import{d as Z,f as tt,i as R,k as et}from"./chunk-S654BBEP.js";import{a as Q}from"./chunk-S2ZBMEVA.js";import{d as X,e as Y}from"./chunk-ASYNLVOP.js";import{a as ot,b as nt,c as it,d as v,e as st,g as W,h as lt,i as rt}from"./chunk-576YHDEK.js";import"./chunk-T7QVTNXF.js";import"./chunk-RPXHAG6F.js";import{b as z}from"./chunk-45PGAQRO.js";import{c as V}from"./chunk-4WKQTWUC.js";import{a as j,b as F,q as U}from"./chunk-VQ5YXO54.js";import{G as M,M as J,N as K,O as T,S as B,a as y,c as x,w as e,x as k,y as L,z as l}from"./chunk-GT4EAKAO.js";import{d as H}from"./chunk-G7NGB5UX.js";H();var at={committed:"Committed. The workflow runs on the push and publishes it in a few minutes.",pr:"The branch is protected, so the change waits in a pull request.",compare:"The branch is protected and Actions can't open pull requests here; open it from the branch.",same:"The file already says that; nothing to change."};function At({open:ct,onClose:S,app:o,defs:P,changes:r,values:dt,wf:ut,replays:mt,onSent:$}){let[a,A]=x(null),[s,u]=x(null),C=Object.fromEntries(P.map(t=>[t.key,t])),c=Object.keys(r),d=c.filter(t=>!t.startsWith("wf:")),f=c.filter(t=>t.startsWith("wf:")),m=Object.fromEntries(d.map(t=>[t,r[t]])),I=Object.fromEntries(f.map(t=>[t.slice(3),r[t]])),N=Object.fromEntries(P.filter(t=>!t.key.startsWith("wf:")).map(t=>[t.key,t.kind])),_=et(m,N),q=f.map(t=>r[t]===null?`# ${t.slice(3)}: remove the line (back to "${C[t]?.default}")`:`${t.slice(3)}: ${nt(String(r[t]))}`).join(`
|
|
2
|
+
`)+`
|
|
3
|
+
`,D=z([],m),p=Q(o,`StackVitals: change ${d.length} setting${d.length===1?"":"s"}`,D),w=o.default_branch||"main",g=`.github/workflows/${F(o.links?.workflow)?o.links.workflow:"stackvitals.yml"}`,h=!!st()&&!U&&j(o.repo),ht=t=>t.startsWith("wf:")?ut?.[t.slice(3)]??C[t]?.default:Z(dt,t),b=t=>{E(o.repo,{settings:m,at:new Date().toISOString(),...t}),$(d)},O=async(t,n)=>{A(t),u(null);try{await n()}catch(i){u({tone:"bad",text:`Not saved: ${i instanceof Error?i.message:String(i)}`})}A(null)},ft=()=>O("commit",async()=>{let t=await W(o,v,n=>ot(n,m,N),"settings");t.kind!=="same"?b({via:t.kind,...t.url?{url:t.url}:{}}):$(d),u({tone:"good",text:at[t.kind],...t.url?{url:t.url}:{}}),B(t.kind==="committed"?"Saved to "+w:t.kind==="same"?"Nothing to change":"Pull request opened")}),pt=()=>O("dispatch",async()=>{let t=await lt(o,D);b({via:"dispatch",...t?{run:t,url:t.html_url}:{}}),u({tone:"good",text:t?`Run #${t.run_number} is applying it; it shows in Activity with your name.`:"The workflow started; it shows in the Actions tab in a moment.",...t?{url:t.html_url}:{}});for(let n=0;t&&t.status!=="completed"&&n<60;n++)await new Promise(i=>setTimeout(i,5e3)),t=await rt(o,t.id).catch(()=>t);t?.status==="completed"&&(E(o.repo,{settings:m,at:new Date().toISOString(),via:"dispatch",run:t,url:t.html_url}),V())}),wt=()=>O("wf",async()=>{let t=await W(o,g,n=>it(n,I),"workflow inputs");$(f,I),u({tone:"good",text:at[t.kind],...t.url?{url:t.url}:{}})});return e(M,{open:ct,onClose:S,title:`Review ${c.length} change${c.length===1?"":"s"}`,description:`Writes to ${o.repo}`,size:"lg",footer:e(l,{variant:s?.tone==="good"?"filled":"plain",onClick:S,children:s?.tone==="good"?"Done":"Keep editing"}),children:[c.length?e("ul",{class:"diff","aria-label":"Changes",children:c.map(t=>{let n=C[t],i=mt[t],G=r[t]===null?n?.default:r[t];return e("li",{children:[e("span",{class:"diff-t",children:[tt(t),e("small",{class:"mono",children:t.replace(/^wf:/,"")})]}),e("span",{class:"diff-v",children:[e("s",{children:R(ht(t),n?.kind||"",n?.unit)}),e(k,{name:"right"}),e("b",{children:R(G,n?.kind||"",n?.unit)})]}),i?e("span",{class:"replay",children:[e(k,{name:"refresh"}),i[2]?G===0?"Turns this alert off.":`Last 90 days: ${i[1]} alert${i[1]===1?"":"s"} instead of ${i[0]}.`:"Not enough data to replay."]}):null]})})}):e("p",{class:"muted",children:"Nothing left to send."}),s?e("div",{class:`note note-${s.tone}`,role:s.tone==="bad"?"alert":"status",children:[e(k,{name:s.tone==="bad"?"warn":"check"}),e("span",{children:[s.text,s.url?e(y,{children:[" ",e("a",{href:L(s.url),target:"_blank",rel:"noopener noreferrer",children:"Open on GitHub"})]}):null]})]}):null,d.length?e("section",{class:"how","aria-labelledby":"how-s",children:[e("h3",{id:"how-s",class:"sheet-h3",children:"Settings file"}),e("dl",{class:"kv",children:[e("dt",{children:"Where"}),e("dd",{children:[e("code",{children:v})," on ",w,", edited in place (comments stay)"]}),e("dt",{children:"Who can"}),e("dd",{children:["anyone with write access to ",o.repo]}),e("dt",{children:"When"}),e("dd",{children:"the next run, a few minutes after saving"})]}),e("div",{class:"how-actions",children:[h?e(y,{children:[e(l,{variant:"filled",icon:"check",loading:a==="commit",disabled:!!a,onClick:ft,children:["Save to ",w," in ",o.repo]}),e(l,{variant:"tinted",icon:"bolt",loading:a==="dispatch",disabled:!!a,onClick:pt,children:["Run ",o.repo,"'s workflow with it"]})]}):e(y,{children:[p?e(l,{variant:"filled",icon:"external",href:p.url,external:!0,onClick:()=>{b({via:"issue"}),X(p,"Opened on GitHub: press Submit there")()},children:"Open as a GitHub issue"}):null,e(l,{variant:"tinted",icon:"link",href:"#/settings/account",onClick:S,children:"Connect GitHub to save in one click"})]}),e(l,{variant:"plain",icon:"copy",onClick:async()=>{let t=await J(_);B(t?"TOML copied":"Copy failed: select the text below",t?"good":"bad"),t&&!h&&b({via:"copy"})},children:"Copy TOML"})]}),h?null:e(Y,{link:p}),e(T,{code:_,title:v})]}):null,f.length?e("section",{class:"how","aria-labelledby":"how-w",children:[e("h3",{id:"how-w",class:"sheet-h3",children:"Workflow file"}),e("p",{class:"field-hint",children:["These are inputs of the StackVitals step in ",e("code",{children:g}),", under ",e("code",{children:"with:"}),".",h?" Saving needs the Workflows permission on your token.":""]}),e("div",{class:"how-actions",children:[h?e(l,{variant:"filled",icon:"check",loading:a==="wf",disabled:!!a,onClick:wt,children:["Save to the workflow in ",o.repo]}):e(l,{variant:"filled",icon:"external",href:`https://github.com/${o.repo}/edit/${encodeURIComponent(w)}/${g}`,external:!0,children:"Edit the workflow on GitHub"}),e(K,{text:q,label:"Copy the lines"})]}),e(T,{code:q,title:`${g}, under with:`})]}):null]})}export{At as ReviewSheet};
|