tool-compass 2.2.1__tar.gz → 2.3.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- tool_compass-2.3.0/.dockerignore +84 -0
- tool_compass-2.3.0/.github/dependabot.yml +89 -0
- {tool_compass-2.2.1 → tool_compass-2.3.0}/.github/workflows/ci.yml +93 -6
- {tool_compass-2.2.1 → tool_compass-2.3.0}/.github/workflows/publish.yml +53 -4
- tool_compass-2.3.0/.github/workflows/release-binaries.yml +268 -0
- {tool_compass-2.2.1 → tool_compass-2.3.0}/.gitignore +14 -0
- tool_compass-2.3.0/.pre-commit-config.yaml +55 -0
- tool_compass-2.3.0/CHANGELOG.md +440 -0
- {tool_compass-2.2.1 → tool_compass-2.3.0}/CONTRIBUTING.md +45 -26
- {tool_compass-2.2.1 → tool_compass-2.3.0}/Dockerfile +26 -9
- {tool_compass-2.2.1 → tool_compass-2.3.0}/Makefile +15 -8
- {tool_compass-2.2.1 → tool_compass-2.3.0}/PKG-INFO +40 -13
- {tool_compass-2.2.1 → tool_compass-2.3.0}/README.es.md +53 -31
- {tool_compass-2.2.1 → tool_compass-2.3.0}/README.fr.md +57 -31
- tool_compass-2.3.0/README.hi.md +342 -0
- {tool_compass-2.2.1 → tool_compass-2.3.0}/README.it.md +72 -46
- {tool_compass-2.2.1 → tool_compass-2.3.0}/README.ja.md +65 -40
- {tool_compass-2.2.1 → tool_compass-2.3.0}/README.md +37 -11
- {tool_compass-2.2.1 → tool_compass-2.3.0}/README.pt-BR.md +53 -29
- {tool_compass-2.2.1 → tool_compass-2.3.0}/README.zh.md +73 -51
- tool_compass-2.3.0/SCORECARD.md +36 -0
- {tool_compass-2.2.1 → tool_compass-2.3.0}/SECURITY.md +22 -7
- {tool_compass-2.2.1 → tool_compass-2.3.0}/analytics.py +22 -0
- {tool_compass-2.2.1 → tool_compass-2.3.0}/backend_client_mcp.py +47 -6
- tool_compass-2.3.0/backend_client_simple.py +1804 -0
- {tool_compass-2.2.1 → tool_compass-2.3.0}/chain_indexer.py +75 -9
- tool_compass-2.3.0/cli.py +1598 -0
- {tool_compass-2.2.1 → tool_compass-2.3.0}/config.py +174 -11
- tool_compass-2.3.0/embedder.py +591 -0
- {tool_compass-2.2.1 → tool_compass-2.3.0}/gateway.py +896 -213
- {tool_compass-2.2.1 → tool_compass-2.3.0}/indexer.py +312 -147
- {tool_compass-2.2.1 → tool_compass-2.3.0}/llms.txt +20 -4
- {tool_compass-2.2.1 → tool_compass-2.3.0/npm}/CHANGELOG.md +93 -11
- tool_compass-2.3.0/npm/LICENSE +21 -0
- tool_compass-2.3.0/npm/README.md +171 -0
- tool_compass-2.3.0/npm/bin/tool-compass.js +14 -0
- tool_compass-2.3.0/npm/package.json +45 -0
- tool_compass-2.3.0/npm/test/smoke.test.js +54 -0
- {tool_compass-2.2.1 → tool_compass-2.3.0}/pyproject.toml +24 -6
- tool_compass-2.3.0/scripts/regenerate-scorecard.sh +110 -0
- tool_compass-2.3.0/scripts/verify-metrics.sh +125 -0
- tool_compass-2.3.0/site/astro.config.mjs +60 -0
- {tool_compass-2.2.1 → tool_compass-2.3.0}/site/src/content/docs/handbook/architecture.md +6 -3
- {tool_compass-2.2.1 → tool_compass-2.3.0}/site/src/content/docs/handbook/beginners.md +15 -6
- {tool_compass-2.2.1 → tool_compass-2.3.0}/site/src/content/docs/handbook/configuration.md +3 -3
- {tool_compass-2.2.1 → tool_compass-2.3.0}/site/src/content/docs/handbook/getting-started.md +26 -6
- tool_compass-2.3.0/site/src/content/docs/handbook/index.md +48 -0
- {tool_compass-2.2.1 → tool_compass-2.3.0}/sync_manager.py +29 -11
- {tool_compass-2.2.1 → tool_compass-2.3.0}/tool_manifest.py +16 -2
- tool_compass-2.3.0/ui.py +1851 -0
- tool_compass-2.2.1/.dockerignore +0 -56
- tool_compass-2.2.1/.github/dependabot.yml +0 -24
- tool_compass-2.2.1/AUDIT_REPORT.md +0 -245
- tool_compass-2.2.1/README.hi.md +0 -323
- tool_compass-2.2.1/SCORECARD.md +0 -36
- tool_compass-2.2.1/backend_client_simple.py +0 -861
- tool_compass-2.2.1/cli.py +0 -283
- tool_compass-2.2.1/embedder.py +0 -432
- tool_compass-2.2.1/site/astro.config.mjs +0 -30
- tool_compass-2.2.1/site/src/content/docs/handbook/index.md +0 -30
- tool_compass-2.2.1/ui.py +0 -1337
- {tool_compass-2.2.1 → tool_compass-2.3.0}/.env.example +0 -0
- {tool_compass-2.2.1 → tool_compass-2.3.0}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
- {tool_compass-2.2.1 → tool_compass-2.3.0}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
- {tool_compass-2.2.1 → tool_compass-2.3.0}/CODE_OF_CONDUCT.md +0 -0
- {tool_compass-2.2.1 → tool_compass-2.3.0}/LICENSE +0 -0
- {tool_compass-2.2.1 → tool_compass-2.3.0}/SHIP_GATE.md +0 -0
- {tool_compass-2.2.1 → tool_compass-2.3.0}/_version.py +0 -0
- {tool_compass-2.2.1 → tool_compass-2.3.0}/assets/logo.png +0 -0
- {tool_compass-2.2.1 → tool_compass-2.3.0}/bootstrap.py +0 -0
- {tool_compass-2.2.1 → tool_compass-2.3.0}/compass_config.example.json +0 -0
- {tool_compass-2.2.1 → tool_compass-2.3.0}/docker-compose.yml +0 -0
- {tool_compass-2.2.1 → tool_compass-2.3.0}/docs/assets/social-preview.png +0 -0
- {tool_compass-2.2.1 → tool_compass-2.3.0}/docs/assets/social-preview.svg +0 -0
- {tool_compass-2.2.1 → tool_compass-2.3.0}/docs/assets/tool-compass-logo-dark-bg.jpg +0 -0
- {tool_compass-2.2.1 → tool_compass-2.3.0}/docs/index.md +0 -0
- {tool_compass-2.2.1 → tool_compass-2.3.0}/fly.toml +0 -0
- {tool_compass-2.2.1 → tool_compass-2.3.0}/logo.png +0 -0
- {tool_compass-2.2.1 → tool_compass-2.3.0}/requirements-dev.txt +0 -0
- {tool_compass-2.2.1 → tool_compass-2.3.0}/requirements.txt +0 -0
- {tool_compass-2.2.1 → tool_compass-2.3.0}/scripts/check-org-urls.sh +0 -0
- {tool_compass-2.2.1 → tool_compass-2.3.0}/site/package-lock.json +0 -0
- {tool_compass-2.2.1 → tool_compass-2.3.0}/site/package.json +0 -0
- {tool_compass-2.2.1 → tool_compass-2.3.0}/site/src/content/docs/handbook/operations.md +0 -0
- {tool_compass-2.2.1 → tool_compass-2.3.0}/site/src/content/docs/handbook/tools.md +0 -0
- {tool_compass-2.2.1 → tool_compass-2.3.0}/site/src/content.config.ts +0 -0
- {tool_compass-2.2.1 → tool_compass-2.3.0}/site/src/pages/index.astro +0 -0
- {tool_compass-2.2.1 → tool_compass-2.3.0}/site/src/site-config.ts +0 -0
- {tool_compass-2.2.1 → tool_compass-2.3.0}/site/src/styles/global.css +0 -0
- {tool_compass-2.2.1 → tool_compass-2.3.0}/site/src/styles/starlight-custom.css +0 -0
- {tool_compass-2.2.1 → tool_compass-2.3.0}/site/tsconfig.json +0 -0
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# Git
|
|
2
|
+
.git
|
|
3
|
+
.gitignore
|
|
4
|
+
|
|
5
|
+
# Docker
|
|
6
|
+
Dockerfile
|
|
7
|
+
docker-compose.yml
|
|
8
|
+
.dockerignore
|
|
9
|
+
|
|
10
|
+
# Python
|
|
11
|
+
__pycache__
|
|
12
|
+
*.py[cod]
|
|
13
|
+
*$py.class
|
|
14
|
+
*.so
|
|
15
|
+
.Python
|
|
16
|
+
venv/
|
|
17
|
+
.venv/
|
|
18
|
+
ENV/
|
|
19
|
+
env/
|
|
20
|
+
.eggs/
|
|
21
|
+
*.egg-info/
|
|
22
|
+
*.egg
|
|
23
|
+
|
|
24
|
+
# IDE
|
|
25
|
+
.vscode/
|
|
26
|
+
.idea/
|
|
27
|
+
*.swp
|
|
28
|
+
*.swo
|
|
29
|
+
|
|
30
|
+
# Testing
|
|
31
|
+
.pytest_cache/
|
|
32
|
+
.coverage
|
|
33
|
+
htmlcov/
|
|
34
|
+
.tox/
|
|
35
|
+
.hypothesis/
|
|
36
|
+
.benchmarks/
|
|
37
|
+
|
|
38
|
+
# Build artifacts
|
|
39
|
+
dist/
|
|
40
|
+
build/
|
|
41
|
+
*.manifest
|
|
42
|
+
*.spec
|
|
43
|
+
|
|
44
|
+
# OS files
|
|
45
|
+
.DS_Store
|
|
46
|
+
Thumbs.db
|
|
47
|
+
|
|
48
|
+
# Local development files
|
|
49
|
+
*.local.json
|
|
50
|
+
.env.local
|
|
51
|
+
.env*
|
|
52
|
+
|
|
53
|
+
# Gradio cache
|
|
54
|
+
flagged/
|
|
55
|
+
|
|
56
|
+
# Keep db directory structure but not contents
|
|
57
|
+
db/*.db
|
|
58
|
+
db/*.hnsw
|
|
59
|
+
!db/.gitkeep
|
|
60
|
+
|
|
61
|
+
# Sources that don't belong in the production image (CT-B-004).
|
|
62
|
+
# These are intentionally excluded so a future regression to
|
|
63
|
+
# `COPY . .` doesn't silently ship them.
|
|
64
|
+
tests/
|
|
65
|
+
docs/
|
|
66
|
+
site/
|
|
67
|
+
archive/
|
|
68
|
+
.github/
|
|
69
|
+
.claude/
|
|
70
|
+
# Translation READMEs (re-run on TranslateGemma 12B; not runtime artifacts)
|
|
71
|
+
README.ja.md
|
|
72
|
+
README.zh.md
|
|
73
|
+
README.es.md
|
|
74
|
+
README.fr.md
|
|
75
|
+
README.hi.md
|
|
76
|
+
README.it.md
|
|
77
|
+
README.pt-BR.md
|
|
78
|
+
# Audit / governance docs — not needed at runtime
|
|
79
|
+
SCORECARD.md
|
|
80
|
+
SHIP_GATE.md
|
|
81
|
+
CODE_OF_CONDUCT.md
|
|
82
|
+
CONTRIBUTING.md
|
|
83
|
+
SECURITY.md
|
|
84
|
+
CHANGELOG.md
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
version: 2
|
|
2
|
+
updates:
|
|
3
|
+
# =============================================================================
|
|
4
|
+
# pip — Python runtime + dev dependencies
|
|
5
|
+
# =============================================================================
|
|
6
|
+
- package-ecosystem: "pip"
|
|
7
|
+
directory: "/"
|
|
8
|
+
schedule:
|
|
9
|
+
interval: "monthly"
|
|
10
|
+
open-pull-requests-limit: 3
|
|
11
|
+
groups:
|
|
12
|
+
# Minor + patch only so breaking majors open as SEPARATE PRs.
|
|
13
|
+
# (Avoids the ollama-intern PR #4 incident where 5 breaking majors
|
|
14
|
+
# shipped bundled under a wildcard group.)
|
|
15
|
+
all-pip:
|
|
16
|
+
patterns: ["*"]
|
|
17
|
+
update-types: ["minor", "patch"]
|
|
18
|
+
|
|
19
|
+
# Daily security-only overlay (CT-B-006) — CVE updates from the GitHub
|
|
20
|
+
# Advisory Database don't wait the monthly cadence. open-pull-requests-limit
|
|
21
|
+
# raised to 10 since these are infrequent and load-bearing.
|
|
22
|
+
# NOTE: Dependabot security advisories are auto-emitted; this second entry
|
|
23
|
+
# exists to give them their own schedule/labels/PR cap independent of the
|
|
24
|
+
# monthly version-update entry above. The `allow: dependency-type: all`
|
|
25
|
+
# block scopes this entry to all dependencies; security advisories are
|
|
26
|
+
# always opened regardless of the version-update grouping rules.
|
|
27
|
+
- package-ecosystem: "pip"
|
|
28
|
+
directory: "/"
|
|
29
|
+
schedule:
|
|
30
|
+
interval: "daily"
|
|
31
|
+
open-pull-requests-limit: 10
|
|
32
|
+
allow:
|
|
33
|
+
- dependency-type: "all"
|
|
34
|
+
labels:
|
|
35
|
+
- "security"
|
|
36
|
+
- "dependencies"
|
|
37
|
+
|
|
38
|
+
# =============================================================================
|
|
39
|
+
# github-actions — workflow file action references
|
|
40
|
+
# =============================================================================
|
|
41
|
+
- package-ecosystem: "github-actions"
|
|
42
|
+
directory: "/"
|
|
43
|
+
schedule:
|
|
44
|
+
interval: "monthly"
|
|
45
|
+
open-pull-requests-limit: 3
|
|
46
|
+
groups:
|
|
47
|
+
all-github-actions:
|
|
48
|
+
patterns: ["*"]
|
|
49
|
+
update-types: ["minor", "patch"]
|
|
50
|
+
|
|
51
|
+
# Daily security-only overlay for actions (CT-B-006).
|
|
52
|
+
- package-ecosystem: "github-actions"
|
|
53
|
+
directory: "/"
|
|
54
|
+
schedule:
|
|
55
|
+
interval: "daily"
|
|
56
|
+
open-pull-requests-limit: 10
|
|
57
|
+
allow:
|
|
58
|
+
- dependency-type: "all"
|
|
59
|
+
labels:
|
|
60
|
+
- "security"
|
|
61
|
+
- "dependencies"
|
|
62
|
+
|
|
63
|
+
# =============================================================================
|
|
64
|
+
# docker — Dockerfile base-image FROM directives (CT-B-005)
|
|
65
|
+
# =============================================================================
|
|
66
|
+
# Pairs with the digest-pinned `FROM python:3.11-slim@sha256:...` in
|
|
67
|
+
# Dockerfile (CT-B-003). Without this ecosystem entry the digest pin
|
|
68
|
+
# would become a stale anchor with no machine-readable refresh path.
|
|
69
|
+
- package-ecosystem: "docker"
|
|
70
|
+
directory: "/"
|
|
71
|
+
schedule:
|
|
72
|
+
interval: "monthly"
|
|
73
|
+
open-pull-requests-limit: 2
|
|
74
|
+
groups:
|
|
75
|
+
all-docker:
|
|
76
|
+
patterns: ["*"]
|
|
77
|
+
update-types: ["minor", "patch"]
|
|
78
|
+
|
|
79
|
+
# Daily security-only overlay for docker base images (CT-B-006).
|
|
80
|
+
- package-ecosystem: "docker"
|
|
81
|
+
directory: "/"
|
|
82
|
+
schedule:
|
|
83
|
+
interval: "daily"
|
|
84
|
+
open-pull-requests-limit: 10
|
|
85
|
+
allow:
|
|
86
|
+
- dependency-type: "all"
|
|
87
|
+
labels:
|
|
88
|
+
- "security"
|
|
89
|
+
- "dependencies"
|
|
@@ -35,9 +35,16 @@ on:
|
|
|
35
35
|
- cron: '0 9 * * 1,3,5'
|
|
36
36
|
workflow_dispatch:
|
|
37
37
|
|
|
38
|
-
concurrency
|
|
39
|
-
|
|
40
|
-
|
|
38
|
+
# NOTE: concurrency is intentionally NOT set at the workflow level.
|
|
39
|
+
# A workflow-level cancel-in-progress would cancel the whole run when a
|
|
40
|
+
# new push lands on the same ref — including the pages-deploy job that
|
|
41
|
+
# carries its own concurrency: pages / cancel-in-progress: false. The
|
|
42
|
+
# job-level setting cannot override workflow-level cancellation because
|
|
43
|
+
# the entire run is cancelled before per-job concurrency takes effect.
|
|
44
|
+
# Each test/lint/integration/docker job below carries its own
|
|
45
|
+
# concurrency block scoped to PR refs only (push events on main are
|
|
46
|
+
# never cancelled). The pages-build / pages-deploy jobs keep their
|
|
47
|
+
# dedicated concurrency: pages group with cancel-in-progress: false.
|
|
41
48
|
|
|
42
49
|
# Default least-privilege; individual jobs that need more elevate explicitly.
|
|
43
50
|
permissions:
|
|
@@ -47,6 +54,13 @@ jobs:
|
|
|
47
54
|
lint:
|
|
48
55
|
name: Org URL sanity check
|
|
49
56
|
runs-on: ubuntu-latest
|
|
57
|
+
# CT-B-011: lint is a sub-30-second shell check; 5 min is generous.
|
|
58
|
+
timeout-minutes: 5
|
|
59
|
+
# PR-scoped concurrency: a newer push to the same PR cancels the
|
|
60
|
+
# older run, but pushes to main never cancel themselves.
|
|
61
|
+
concurrency:
|
|
62
|
+
group: lint-${{ github.event.pull_request.number || github.run_id }}
|
|
63
|
+
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
|
|
50
64
|
permissions:
|
|
51
65
|
contents: read
|
|
52
66
|
steps:
|
|
@@ -56,6 +70,22 @@ jobs:
|
|
|
56
70
|
- name: Check for stale org/user URLs
|
|
57
71
|
run: bash scripts/check-org-urls.sh
|
|
58
72
|
|
|
73
|
+
- name: Set up Python (pre-commit)
|
|
74
|
+
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6
|
|
75
|
+
with:
|
|
76
|
+
python-version: '3.11'
|
|
77
|
+
|
|
78
|
+
# CT-B-018: run the pre-commit hooks (ruff format + ruff check +
|
|
79
|
+
# standard hygiene + gitleaks). Same hooks the contributor runs
|
|
80
|
+
# locally; this is the CI-side enforcement. Soft-fail for the first
|
|
81
|
+
# cycle to surface formatting drift without blocking PRs while
|
|
82
|
+
# contributors install pre-commit locally.
|
|
83
|
+
# TODO(swarm): flip continue-on-error to false after one full release
|
|
84
|
+
# cycle so the pre-commit gate becomes blocking.
|
|
85
|
+
- name: Run pre-commit hooks
|
|
86
|
+
continue-on-error: true
|
|
87
|
+
uses: pre-commit/action@2c7b3805fd2a0fd8c1884dcaebf91fc102a13ecd # v3.0.1
|
|
88
|
+
|
|
59
89
|
# CDS-FT-001: SCORECARD drift guard. Soft-fail for now — shipcheck
|
|
60
90
|
# markdown output is still settling. Flip continue-on-error to false
|
|
61
91
|
# once the format stabilizes.
|
|
@@ -69,9 +99,32 @@ jobs:
|
|
|
69
99
|
echo "Makefile verify-scorecard target missing — skipping"
|
|
70
100
|
fi
|
|
71
101
|
|
|
102
|
+
# CT-B-008 cross-domain: verify that /metrics emits the expected
|
|
103
|
+
# Four Golden Signals surface. Soft-fail because the saturation
|
|
104
|
+
# gauges land in BE-B-002 (backend domain); flip to fatal once that
|
|
105
|
+
# work merges.
|
|
106
|
+
- name: Verify metrics surface (Four Golden Signals)
|
|
107
|
+
continue-on-error: true
|
|
108
|
+
run: |
|
|
109
|
+
if [ -f Makefile ] && grep -q "^verify-metrics:" Makefile; then
|
|
110
|
+
python -m pip install --upgrade pip
|
|
111
|
+
pip install -r requirements.txt || true
|
|
112
|
+
make verify-metrics || true
|
|
113
|
+
else
|
|
114
|
+
echo "Makefile verify-metrics target missing — skipping"
|
|
115
|
+
fi
|
|
116
|
+
|
|
72
117
|
test:
|
|
73
118
|
name: Python ${{ matrix.python-version }} on ${{ matrix.os }}
|
|
74
119
|
runs-on: ${{ matrix.os }}
|
|
120
|
+
# CT-B-011: per-matrix-cell budget. pytest has its own 30s per-test cap
|
|
121
|
+
# (pyproject.toml [tool.pytest.ini_options]); 15 min envelope covers
|
|
122
|
+
# install + coverage + pip-audit with headroom for a slow runner.
|
|
123
|
+
timeout-minutes: 15
|
|
124
|
+
# PR-scoped concurrency (see workflow-top NOTE).
|
|
125
|
+
concurrency:
|
|
126
|
+
group: test-${{ matrix.python-version }}-${{ github.event.pull_request.number || github.run_id }}
|
|
127
|
+
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
|
|
75
128
|
permissions:
|
|
76
129
|
contents: read
|
|
77
130
|
|
|
@@ -116,6 +169,9 @@ jobs:
|
|
|
116
169
|
name: junit-reports-${{ matrix.python-version }}
|
|
117
170
|
path: junit-${{ matrix.python-version }}.xml
|
|
118
171
|
if-no-files-found: warn
|
|
172
|
+
# CT-B-012: JUnit reports are short-lived diagnostic data — only
|
|
173
|
+
# useful for the most recent few runs. Default 90d is wasted.
|
|
174
|
+
retention-days: 14
|
|
119
175
|
|
|
120
176
|
- name: Run tests with coverage
|
|
121
177
|
if: matrix.python-version == '3.11' && matrix.os == 'ubuntu-latest'
|
|
@@ -142,6 +198,9 @@ jobs:
|
|
|
142
198
|
name: pip-audit-report
|
|
143
199
|
path: pip-audit-report.json
|
|
144
200
|
if-no-files-found: ignore
|
|
201
|
+
# CT-B-012: CVE diagnostic snapshot — 14d aligns with the JUnit
|
|
202
|
+
# retention and is plenty of window for incident response.
|
|
203
|
+
retention-days: 14
|
|
145
204
|
|
|
146
205
|
- name: Audit dependencies for vulnerabilities
|
|
147
206
|
if: matrix.python-version == '3.11' && matrix.os == 'ubuntu-latest'
|
|
@@ -157,6 +216,9 @@ jobs:
|
|
|
157
216
|
name: Nightly Hypothesis fuzz
|
|
158
217
|
if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch'
|
|
159
218
|
runs-on: ubuntu-latest
|
|
219
|
+
# CT-B-011: Hypothesis nightly profile is deliberately slow — 45 min cap
|
|
220
|
+
# is wider than the test job because fuzz examples are unbounded.
|
|
221
|
+
timeout-minutes: 45
|
|
160
222
|
permissions:
|
|
161
223
|
contents: read
|
|
162
224
|
issues: write
|
|
@@ -184,9 +246,10 @@ jobs:
|
|
|
184
246
|
|
|
185
247
|
- name: Open tracking issue on failure
|
|
186
248
|
if: failure() && steps.fuzz.conclusion == 'failure'
|
|
187
|
-
#
|
|
188
|
-
#
|
|
189
|
-
|
|
249
|
+
# SHA-pinned per SLSA L3 supply-chain hygiene (CT-B-001). nightly-fuzz
|
|
250
|
+
# carries issues:write, so a compromised v7 mutable tag would inherit
|
|
251
|
+
# issue-creation capability. Bump via dependabot's github-actions sweep.
|
|
252
|
+
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
|
|
190
253
|
with:
|
|
191
254
|
script: |
|
|
192
255
|
const title = `[nightly-fuzz] Hypothesis failures on ${context.sha}`;
|
|
@@ -212,6 +275,13 @@ jobs:
|
|
|
212
275
|
name: Integration Tests
|
|
213
276
|
runs-on: ubuntu-latest
|
|
214
277
|
needs: test # Only run after unit tests pass
|
|
278
|
+
# CT-B-011: Ollama install + nomic-embed-text pull + integration suite
|
|
279
|
+
# dominates; 25 min envelope covers the cold-start pull path.
|
|
280
|
+
timeout-minutes: 25
|
|
281
|
+
# PR-scoped concurrency (see workflow-top NOTE).
|
|
282
|
+
concurrency:
|
|
283
|
+
group: integration-${{ github.event.pull_request.number || github.run_id }}
|
|
284
|
+
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
|
|
215
285
|
permissions:
|
|
216
286
|
contents: read
|
|
217
287
|
|
|
@@ -271,6 +341,12 @@ jobs:
|
|
|
271
341
|
name: Docker Build
|
|
272
342
|
runs-on: ubuntu-latest
|
|
273
343
|
needs: test
|
|
344
|
+
# CT-B-011: docker buildx + gha cache; 20 min covers a cold-cache build.
|
|
345
|
+
timeout-minutes: 20
|
|
346
|
+
# PR-scoped concurrency (see workflow-top NOTE).
|
|
347
|
+
concurrency:
|
|
348
|
+
group: docker-${{ github.event.pull_request.number || github.run_id }}
|
|
349
|
+
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
|
|
274
350
|
permissions:
|
|
275
351
|
contents: read
|
|
276
352
|
|
|
@@ -299,6 +375,8 @@ jobs:
|
|
|
299
375
|
name: Build site
|
|
300
376
|
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
|
|
301
377
|
runs-on: ubuntu-latest
|
|
378
|
+
# CT-B-011: Starlight npm ci + Astro build; 10 min is generous.
|
|
379
|
+
timeout-minutes: 10
|
|
302
380
|
permissions:
|
|
303
381
|
contents: read
|
|
304
382
|
steps:
|
|
@@ -308,6 +386,12 @@ jobs:
|
|
|
308
386
|
with:
|
|
309
387
|
node-version: 22
|
|
310
388
|
|
|
389
|
+
# CT-B-016: read repo-level Pages configuration so the build is not
|
|
390
|
+
# silently dependent on Settings → Pages UI state. configure-pages
|
|
391
|
+
# is idempotent and exposes the base path to downstream steps.
|
|
392
|
+
- name: Configure Pages
|
|
393
|
+
uses: actions/configure-pages@45bfe0192ca1faeb007ade9deae92b16b8254a0d # v6.0.0
|
|
394
|
+
|
|
311
395
|
- name: Install site dependencies
|
|
312
396
|
working-directory: site
|
|
313
397
|
run: npm ci
|
|
@@ -325,6 +409,9 @@ jobs:
|
|
|
325
409
|
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
|
|
326
410
|
needs: pages-build
|
|
327
411
|
runs-on: ubuntu-latest
|
|
412
|
+
# CT-B-011: deploy is a metadata operation against the Pages backend;
|
|
413
|
+
# 5 min is the fail-fast budget.
|
|
414
|
+
timeout-minutes: 5
|
|
328
415
|
# Dedicated concurrency group so a long deploy is never cancelled by a
|
|
329
416
|
# newer CI run (CDS-A-012).
|
|
330
417
|
concurrency:
|
|
@@ -20,6 +20,10 @@ jobs:
|
|
|
20
20
|
build:
|
|
21
21
|
name: Build package
|
|
22
22
|
runs-on: ubuntu-latest
|
|
23
|
+
# CT-B-011: fail-fast budgets per SRE 'fail fast' (Google SRE Book ch.21).
|
|
24
|
+
# Default GitHub timeout is 360 min; a wedged dependency install or twine
|
|
25
|
+
# check is well outside the legitimate envelope at 10 min.
|
|
26
|
+
timeout-minutes: 10
|
|
23
27
|
|
|
24
28
|
steps:
|
|
25
29
|
- name: Checkout repository
|
|
@@ -46,14 +50,26 @@ jobs:
|
|
|
46
50
|
with:
|
|
47
51
|
name: dist
|
|
48
52
|
path: dist/
|
|
53
|
+
# CT-B-012: dist/ is an ephemeral build-to-publish handoff; the
|
|
54
|
+
# canonical artifacts live at PyPI + GHCR after publish completes.
|
|
55
|
+
# Keep the workflow copy around 7 days for incident-response replays.
|
|
56
|
+
retention-days: 7
|
|
49
57
|
|
|
50
58
|
publish-pypi:
|
|
51
59
|
name: Publish to PyPI
|
|
52
60
|
runs-on: ubuntu-latest
|
|
53
61
|
needs: build
|
|
54
62
|
environment: pypi
|
|
63
|
+
# CT-B-011: PyPI upload + propagation; 10 min covers retries.
|
|
64
|
+
timeout-minutes: 10
|
|
55
65
|
permissions:
|
|
56
66
|
id-token: write
|
|
67
|
+
# CT-B-009: attestations:write enables SLSA provenance attestations on
|
|
68
|
+
# the published wheel + sdist via pypa/gh-action-pypi-publish v1.13+.
|
|
69
|
+
# Combined with `attestations: true` below, PyPI surfaces a verifiable
|
|
70
|
+
# build attestation tied to this commit + workflow run.
|
|
71
|
+
attestations: write
|
|
72
|
+
contents: read
|
|
57
73
|
|
|
58
74
|
steps:
|
|
59
75
|
- name: Download build artifacts
|
|
@@ -64,6 +80,12 @@ jobs:
|
|
|
64
80
|
|
|
65
81
|
- name: Publish to PyPI
|
|
66
82
|
uses: pypa/gh-action-pypi-publish@cef221092ed1bacb1cc03d23a2d87d1d172e277b # v1.14.0
|
|
83
|
+
with:
|
|
84
|
+
# CT-B-009: emit SLSA build provenance attestations for the wheel
|
|
85
|
+
# and sdist. PyPI verifies the attestation against the workflow's
|
|
86
|
+
# OIDC identity; downstream consumers can audit the chain from a
|
|
87
|
+
# specific commit -> workflow run -> published artifact.
|
|
88
|
+
attestations: true
|
|
67
89
|
|
|
68
90
|
docker:
|
|
69
91
|
name: Publish to GHCR
|
|
@@ -71,9 +93,16 @@ jobs:
|
|
|
71
93
|
# PyPI ships first (CDS-B-005). If PyPI fails, Docker must not ship a
|
|
72
94
|
# half-release; if PyPI succeeds, Docker becomes the recoverable tail.
|
|
73
95
|
needs: publish-pypi
|
|
96
|
+
# CT-B-011: multi-arch buildx (linux/amd64 + linux/arm64) + push to GHCR
|
|
97
|
+
# is the longest leg; 30 min covers the warm cache path with headroom.
|
|
98
|
+
timeout-minutes: 30
|
|
74
99
|
permissions:
|
|
75
100
|
contents: read
|
|
76
101
|
packages: write
|
|
102
|
+
# CT-B-009: id-token + attestations enable buildx SLSA provenance
|
|
103
|
+
# mode=max on the image manifest below.
|
|
104
|
+
id-token: write
|
|
105
|
+
attestations: write
|
|
77
106
|
|
|
78
107
|
steps:
|
|
79
108
|
- name: Checkout repository
|
|
@@ -99,8 +128,10 @@ jobs:
|
|
|
99
128
|
|
|
100
129
|
# QEMU is required to cross-build linux/arm64 from an amd64 runner.
|
|
101
130
|
- name: Set up QEMU
|
|
102
|
-
#
|
|
103
|
-
|
|
131
|
+
# SHA-pinned per SLSA L3 supply-chain hygiene (CT-B-002). publish job
|
|
132
|
+
# carries packages:write — a compromised mutable v3 tag would inherit
|
|
133
|
+
# GHCR write capability during a release window. Bump via dependabot.
|
|
134
|
+
uses: docker/setup-qemu-action@c7c53464625b32c7a7e944ae62b3e17d2b600130 # v3
|
|
104
135
|
|
|
105
136
|
- name: Set up Docker Buildx
|
|
106
137
|
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0
|
|
@@ -115,11 +146,21 @@ jobs:
|
|
|
115
146
|
labels: ${{ steps.meta.outputs.labels }}
|
|
116
147
|
cache-from: type=gha
|
|
117
148
|
cache-to: type=gha,mode=max
|
|
149
|
+
# CT-B-009: SLSA provenance mode=max emits buildx provenance
|
|
150
|
+
# attestation (including all input source digests) attached to the
|
|
151
|
+
# image manifest. sbom: true emits an SPDX SBOM attestation in the
|
|
152
|
+
# same manifest. Both consumable via `cosign verify-attestation`
|
|
153
|
+
# or `docker buildx imagetools inspect`.
|
|
154
|
+
provenance: mode=max
|
|
155
|
+
sbom: true
|
|
118
156
|
|
|
119
157
|
release-smoke:
|
|
120
158
|
name: Release smoke test
|
|
121
159
|
runs-on: ubuntu-latest
|
|
122
160
|
needs: [publish-pypi, docker]
|
|
161
|
+
# CT-B-011: PyPI propagation retry loop + docker pull + version handshake.
|
|
162
|
+
# 15 min is the propagation-retry window plus headroom.
|
|
163
|
+
timeout-minutes: 15
|
|
123
164
|
permissions:
|
|
124
165
|
contents: read
|
|
125
166
|
packages: read
|
|
@@ -141,14 +182,22 @@ jobs:
|
|
|
141
182
|
run: |
|
|
142
183
|
set -euo pipefail
|
|
143
184
|
VERSION="${{ steps.ver.outputs.version }}"
|
|
144
|
-
# PyPI propagation is fast but not instant; retry briefly.
|
|
185
|
+
# PyPI propagation is fast but not instant; retry briefly. If no
|
|
186
|
+
# iteration succeeds the loop falls through and the subsequent
|
|
187
|
+
# `tool-compass --version` invocation fails with a clear "command
|
|
188
|
+
# not found", which is the desired loud failure mode (CT-B-014).
|
|
189
|
+
install_ok=0
|
|
145
190
|
for _ in $(seq 1 12); do
|
|
146
191
|
if pip install "tool-compass==${VERSION}"; then
|
|
192
|
+
install_ok=1
|
|
147
193
|
break
|
|
148
194
|
fi
|
|
149
195
|
sleep 10
|
|
150
196
|
done
|
|
151
|
-
|
|
197
|
+
if [ "$install_ok" -ne 1 ]; then
|
|
198
|
+
echo "::error::PyPI smoke failed: tool-compass==${VERSION} did not become installable in the propagation window"
|
|
199
|
+
exit 1
|
|
200
|
+
fi
|
|
152
201
|
OUT="$(tool-compass --version 2>&1 || true)"
|
|
153
202
|
echo "tool-compass --version → $OUT"
|
|
154
203
|
echo "$OUT" | grep -Fq "${VERSION}" || {
|