logodev-mcp 1.0.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.
- logodev_mcp-1.0.0/.copier-answers.yml +13 -0
- logodev_mcp-1.0.0/.env.example +30 -0
- logodev_mcp-1.0.0/.gemini/config.yaml +18 -0
- logodev_mcp-1.0.0/.gitattributes +3 -0
- logodev_mcp-1.0.0/.github/codeql/codeql-config.yml +7 -0
- logodev_mcp-1.0.0/.github/dependabot.yml +15 -0
- logodev_mcp-1.0.0/.github/workflows/ci.yml +332 -0
- logodev_mcp-1.0.0/.github/workflows/claude-code-review.yml +58 -0
- logodev_mcp-1.0.0/.github/workflows/claude.yml +55 -0
- logodev_mcp-1.0.0/.github/workflows/codeql.yml +31 -0
- logodev_mcp-1.0.0/.github/workflows/copier-update.yml +564 -0
- logodev_mcp-1.0.0/.github/workflows/coverage-status.yml +53 -0
- logodev_mcp-1.0.0/.github/workflows/docs.yml +118 -0
- logodev_mcp-1.0.0/.github/workflows/release.yml +485 -0
- logodev_mcp-1.0.0/.gitignore +48 -0
- logodev_mcp-1.0.0/.gitleaks.toml +8 -0
- logodev_mcp-1.0.0/.pre-commit-config.yaml +98 -0
- logodev_mcp-1.0.0/.vale/styles/config/vocabularies/Base/accept.txt +49 -0
- logodev_mcp-1.0.0/.vale.ini +52 -0
- logodev_mcp-1.0.0/CHANGELOG.md +4 -0
- logodev_mcp-1.0.0/CLAUDE.md +200 -0
- logodev_mcp-1.0.0/Dockerfile +72 -0
- logodev_mcp-1.0.0/FORKING.md +88 -0
- logodev_mcp-1.0.0/LICENSE +55 -0
- logodev_mcp-1.0.0/PKG-INFO +224 -0
- logodev_mcp-1.0.0/README.md +199 -0
- logodev_mcp-1.0.0/codecov.yml +33 -0
- logodev_mcp-1.0.0/compose.yml +23 -0
- logodev_mcp-1.0.0/docker-entrypoint.sh +48 -0
- logodev_mcp-1.0.0/docs/configuration-generator.md +11 -0
- logodev_mcp-1.0.0/docs/configuration.md +17 -0
- logodev_mcp-1.0.0/docs/deployment/claude-desktop.md +101 -0
- logodev_mcp-1.0.0/docs/deployment/docker.md +87 -0
- logodev_mcp-1.0.0/docs/deployment/oidc.md +209 -0
- logodev_mcp-1.0.0/docs/guides/authentication.md +237 -0
- logodev_mcp-1.0.0/docs/index.md +21 -0
- logodev_mcp-1.0.0/docs/installation.md +27 -0
- logodev_mcp-1.0.0/docs/javascripts/config-wizard/generators.js +210 -0
- logodev_mcp-1.0.0/docs/javascripts/config-wizard/wizard-spec-schema.json +116 -0
- logodev_mcp-1.0.0/docs/javascripts/config-wizard/wizard-spec.json +46 -0
- logodev_mcp-1.0.0/docs/javascripts/config-wizard/wizard.js +265 -0
- logodev_mcp-1.0.0/docs/prompts.md +25 -0
- logodev_mcp-1.0.0/docs/stylesheets/config-wizard.css +21 -0
- logodev_mcp-1.0.0/docs/tools/index.md +35 -0
- logodev_mcp-1.0.0/examples/bearer-auth.env +5 -0
- logodev_mcp-1.0.0/examples/oidc.env +9 -0
- logodev_mcp-1.0.0/mkdocs.yml +123 -0
- logodev_mcp-1.0.0/packaging/env.example +19 -0
- logodev_mcp-1.0.0/packaging/logodev-mcp.service +80 -0
- logodev_mcp-1.0.0/packaging/mcpb/.gitignore +3 -0
- logodev_mcp-1.0.0/packaging/mcpb/build.sh +53 -0
- logodev_mcp-1.0.0/packaging/mcpb/manifest.json.in +64 -0
- logodev_mcp-1.0.0/packaging/mcpb/pyproject.toml.in +12 -0
- logodev_mcp-1.0.0/packaging/mcpb/src/server.py +20 -0
- logodev_mcp-1.0.0/packaging/nfpm.yaml +68 -0
- logodev_mcp-1.0.0/packaging/scripts/postinstall.sh +53 -0
- logodev_mcp-1.0.0/packaging/scripts/postremove.sh +28 -0
- logodev_mcp-1.0.0/packaging/scripts/preinstall.sh +20 -0
- logodev_mcp-1.0.0/packaging/scripts/preremove.sh +24 -0
- logodev_mcp-1.0.0/packaging/test-install.sh +168 -0
- logodev_mcp-1.0.0/pyproject.toml +189 -0
- logodev_mcp-1.0.0/scripts/bump_manifests.py +108 -0
- logodev_mcp-1.0.0/scripts/copier_update_aggregator.py +573 -0
- logodev_mcp-1.0.0/scripts/copier_update_prompts/job_a.md +132 -0
- logodev_mcp-1.0.0/scripts/copier_update_prompts/job_b.md +81 -0
- logodev_mcp-1.0.0/scripts/copier_update_prompts/job_c.md +82 -0
- logodev_mcp-1.0.0/scripts/vendor_spa.py +18 -0
- logodev_mcp-1.0.0/server.json +172 -0
- logodev_mcp-1.0.0/src/logodev_mcp/__init__.py +6 -0
- logodev_mcp-1.0.0/src/logodev_mcp/_server_apps.py +37 -0
- logodev_mcp-1.0.0/src/logodev_mcp/_server_deps.py +49 -0
- logodev_mcp-1.0.0/src/logodev_mcp/cli.py +118 -0
- logodev_mcp-1.0.0/src/logodev_mcp/config.py +48 -0
- logodev_mcp-1.0.0/src/logodev_mcp/domain.py +270 -0
- logodev_mcp-1.0.0/src/logodev_mcp/prompts.py +21 -0
- logodev_mcp-1.0.0/src/logodev_mcp/resources.py +34 -0
- logodev_mcp-1.0.0/src/logodev_mcp/server.py +121 -0
- logodev_mcp-1.0.0/src/logodev_mcp/static/app.html +13 -0
- logodev_mcp-1.0.0/src/logodev_mcp/static/icons/.gitkeep +0 -0
- logodev_mcp-1.0.0/src/logodev_mcp/tools.py +163 -0
- logodev_mcp-1.0.0/tests/conftest.py +28 -0
- logodev_mcp-1.0.0/tests/test_cli.py +40 -0
- logodev_mcp-1.0.0/tests/test_config.py +23 -0
- logodev_mcp-1.0.0/tests/test_config_wizard_domain.py +30 -0
- logodev_mcp-1.0.0/tests/test_config_wizard_smoke.py +336 -0
- logodev_mcp-1.0.0/tests/test_config_wizard_spec_schema.py +178 -0
- logodev_mcp-1.0.0/tests/test_domain.py +421 -0
- logodev_mcp-1.0.0/tests/test_smoke.py +131 -0
- logodev_mcp-1.0.0/tests/test_tools.py +125 -0
- logodev_mcp-1.0.0/uv.lock +3097 -0
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Changes here will be overwritten by `copier update`.
|
|
2
|
+
_commit: v2.5.3
|
|
3
|
+
_src_path: gh:pvliesdonk/fastmcp-server-template
|
|
4
|
+
docker_registry: ghcr.io/pvliesdonk
|
|
5
|
+
domain_description: Look up company logos and brand data via the logo.dev API.
|
|
6
|
+
enable_authorization: false
|
|
7
|
+
env_prefix: LOGODEV_MCP
|
|
8
|
+
github_org: pvliesdonk
|
|
9
|
+
human_name: Logo.dev MCP
|
|
10
|
+
include_mcp_apps_scaffold: false
|
|
11
|
+
project_name: logodev-mcp
|
|
12
|
+
pypi_name: logodev-mcp
|
|
13
|
+
python_module: logodev_mcp
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Logo.dev MCP environment variables (copy to .env and fill in).
|
|
2
|
+
|
|
3
|
+
# --- Server ---
|
|
4
|
+
# LOGODEV_MCP_TRANSPORT=stdio # stdio | http | sse
|
|
5
|
+
# LOGODEV_MCP_HOST=127.0.0.1
|
|
6
|
+
# LOGODEV_MCP_PORT=8000
|
|
7
|
+
# LOGODEV_MCP_HTTP_PATH=/mcp
|
|
8
|
+
# LOGODEV_MCP_BASE_URL=https://mcp.example.com
|
|
9
|
+
|
|
10
|
+
# --- Authentication (pick one flavor) ---
|
|
11
|
+
# LOGODEV_MCP_BEARER_TOKEN=<secret>
|
|
12
|
+
|
|
13
|
+
# LOGODEV_MCP_BEARER_TOKENS_FILE=/etc/logodev-mcp/tokens.toml # mapped per-token subjects (overrides BEARER_TOKEN)
|
|
14
|
+
|
|
15
|
+
# LOGODEV_MCP_OIDC_CONFIG_URL=https://auth.example.com/.well-known/openid-configuration
|
|
16
|
+
# LOGODEV_MCP_OIDC_CLIENT_ID=<client-id>
|
|
17
|
+
# LOGODEV_MCP_OIDC_CLIENT_SECRET=<client-secret>
|
|
18
|
+
# LOGODEV_MCP_OIDC_AUDIENCE=
|
|
19
|
+
# LOGODEV_MCP_OIDC_REQUIRED_SCOPES=openid
|
|
20
|
+
# LOGODEV_MCP_OIDC_JWT_SIGNING_KEY=<hex-string>
|
|
21
|
+
|
|
22
|
+
# --- Remote debugger (development only — image must be built with --build-arg DEBUG=true) ---
|
|
23
|
+
# LOGODEV_MCP_DEBUG_PORT=5678
|
|
24
|
+
# LOGODEV_MCP_DEBUG_WAIT=false # set true to block startup until the IDE attaches
|
|
25
|
+
|
|
26
|
+
# --- Domain (populate from your ProjectConfig) ---
|
|
27
|
+
# logo.dev publishable key (pk_…) — enables the get_logo tool
|
|
28
|
+
# LOGODEV_MCP_PUBLISHABLE_KEY=pk_live_xxx
|
|
29
|
+
# logo.dev secret key (sk_…) — enables search_brands / describe_company / get_brand
|
|
30
|
+
# LOGODEV_MCP_SECRET_KEY=sk_live_xxx
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Gemini Code Assist — repo review config
|
|
2
|
+
# Reference: https://developers.google.com/gemini-code-assist/docs/customize-repo-review
|
|
3
|
+
#
|
|
4
|
+
# gemini-code-assist is a merge gate, not a pair reviewer. Local review (two
|
|
5
|
+
# subagent code-reviewers with different prompt templates) runs before any
|
|
6
|
+
# push; by the time the PR opens we expect the hosted bot to have nothing to
|
|
7
|
+
# flag. These settings narrow the bot's scope so it fires on flip-to-ready
|
|
8
|
+
# (not on every draft push) and only surfaces real issues.
|
|
9
|
+
|
|
10
|
+
code_review:
|
|
11
|
+
disable: false
|
|
12
|
+
comment_severity_threshold: HIGH
|
|
13
|
+
max_review_comments: 20
|
|
14
|
+
pull_request_opened:
|
|
15
|
+
help: false
|
|
16
|
+
summary: false
|
|
17
|
+
code_review: true
|
|
18
|
+
include_drafts: false
|
|
@@ -0,0 +1,332 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
workflow_dispatch:
|
|
9
|
+
|
|
10
|
+
jobs:
|
|
11
|
+
lint:
|
|
12
|
+
name: Lint
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
timeout-minutes: 10
|
|
15
|
+
steps:
|
|
16
|
+
- uses: actions/checkout@v7
|
|
17
|
+
|
|
18
|
+
- name: Install uv
|
|
19
|
+
uses: astral-sh/setup-uv@v8.2.0
|
|
20
|
+
with:
|
|
21
|
+
version: "latest"
|
|
22
|
+
|
|
23
|
+
- name: Cache Python interpreter
|
|
24
|
+
uses: actions/cache@v5
|
|
25
|
+
with:
|
|
26
|
+
path: ~/.local/share/uv/python
|
|
27
|
+
key: uv-python-3.12-${{ runner.os }}
|
|
28
|
+
|
|
29
|
+
- name: Set up Python
|
|
30
|
+
run: uv python install 3.12
|
|
31
|
+
|
|
32
|
+
- name: Install dependencies
|
|
33
|
+
run: uv sync --all-extras --all-groups
|
|
34
|
+
|
|
35
|
+
- name: Run ruff check
|
|
36
|
+
run: uv run ruff check src/ tests/
|
|
37
|
+
|
|
38
|
+
- name: Run ruff format check
|
|
39
|
+
run: uv run ruff format --check src/ tests/
|
|
40
|
+
|
|
41
|
+
typecheck:
|
|
42
|
+
name: Type Check
|
|
43
|
+
runs-on: ubuntu-latest
|
|
44
|
+
timeout-minutes: 10
|
|
45
|
+
steps:
|
|
46
|
+
- uses: actions/checkout@v7
|
|
47
|
+
|
|
48
|
+
- name: Install uv
|
|
49
|
+
uses: astral-sh/setup-uv@v8.2.0
|
|
50
|
+
with:
|
|
51
|
+
version: "latest"
|
|
52
|
+
|
|
53
|
+
- name: Cache Python interpreter
|
|
54
|
+
uses: actions/cache@v5
|
|
55
|
+
with:
|
|
56
|
+
path: ~/.local/share/uv/python
|
|
57
|
+
key: uv-python-3.12-${{ runner.os }}
|
|
58
|
+
|
|
59
|
+
- name: Set up Python
|
|
60
|
+
run: uv python install 3.12
|
|
61
|
+
|
|
62
|
+
- name: Install dependencies
|
|
63
|
+
run: uv sync --all-extras --all-groups
|
|
64
|
+
|
|
65
|
+
- name: Run mypy
|
|
66
|
+
run: uv run mypy src/ tests/
|
|
67
|
+
|
|
68
|
+
test:
|
|
69
|
+
name: Test (Python ${{ matrix.python-version }})
|
|
70
|
+
runs-on: ubuntu-latest
|
|
71
|
+
# Prevent a stalled `uv python install` from blocking the PR for hours.
|
|
72
|
+
# 20 min covers the full test matrix with headroom; cold interpreter
|
|
73
|
+
# downloads from python-build-standalone are the most likely stall source.
|
|
74
|
+
timeout-minutes: 20
|
|
75
|
+
continue-on-error: ${{ matrix.experimental || false }}
|
|
76
|
+
permissions:
|
|
77
|
+
contents: read
|
|
78
|
+
statuses: write
|
|
79
|
+
strategy:
|
|
80
|
+
fail-fast: false
|
|
81
|
+
matrix:
|
|
82
|
+
include:
|
|
83
|
+
- python-version: "3.11"
|
|
84
|
+
experimental: false
|
|
85
|
+
- python-version: "3.12"
|
|
86
|
+
experimental: false
|
|
87
|
+
- python-version: "3.13"
|
|
88
|
+
experimental: false
|
|
89
|
+
- python-version: "3.14"
|
|
90
|
+
experimental: true
|
|
91
|
+
steps:
|
|
92
|
+
- uses: actions/checkout@v7
|
|
93
|
+
|
|
94
|
+
- name: Install uv
|
|
95
|
+
uses: astral-sh/setup-uv@v8.2.0
|
|
96
|
+
with:
|
|
97
|
+
version: "latest"
|
|
98
|
+
|
|
99
|
+
- name: Cache Python interpreter
|
|
100
|
+
uses: actions/cache@v5
|
|
101
|
+
with:
|
|
102
|
+
# `uv python install` writes to UV_PYTHON_INSTALL_DIR, which is
|
|
103
|
+
# separate from the uv package cache and not covered by setup-uv's
|
|
104
|
+
# enable-cache. Caching by version + OS avoids re-downloading the
|
|
105
|
+
# python-build-standalone tarball on every run.
|
|
106
|
+
path: ~/.local/share/uv/python
|
|
107
|
+
key: uv-python-${{ matrix.python-version }}-${{ runner.os }}
|
|
108
|
+
|
|
109
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
110
|
+
run: uv python install ${{ matrix.python-version }}
|
|
111
|
+
|
|
112
|
+
- name: Install dependencies
|
|
113
|
+
run: uv sync --all-extras --all-groups
|
|
114
|
+
|
|
115
|
+
- name: Run tests with coverage
|
|
116
|
+
run: uv run pytest --cov --cov-report=xml
|
|
117
|
+
|
|
118
|
+
- name: Upload coverage to Codecov
|
|
119
|
+
if: matrix.python-version == '3.13'
|
|
120
|
+
uses: codecov/codecov-action@v6
|
|
121
|
+
with:
|
|
122
|
+
files: ./coverage.xml
|
|
123
|
+
fail_ci_if_error: false
|
|
124
|
+
override_pr: ${{ github.event.pull_request.number }}
|
|
125
|
+
env:
|
|
126
|
+
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
|
127
|
+
|
|
128
|
+
- name: Fetch base branch for diff-cover
|
|
129
|
+
if: matrix.python-version == '3.13' && github.event_name == 'pull_request'
|
|
130
|
+
run: git fetch origin ${{ github.base_ref }} --depth=50
|
|
131
|
+
|
|
132
|
+
- name: Check patch coverage
|
|
133
|
+
id: diffcover
|
|
134
|
+
if: matrix.python-version == '3.13' && github.event_name == 'pull_request'
|
|
135
|
+
env:
|
|
136
|
+
BASE_REF: ${{ github.base_ref }}
|
|
137
|
+
run: |
|
|
138
|
+
# Check if PR has Python source changes
|
|
139
|
+
HAS_PY=$(git diff --name-only "origin/${BASE_REF}...HEAD" | grep -c '\.py$' || true)
|
|
140
|
+
if [ "$HAS_PY" -eq 0 ]; then
|
|
141
|
+
echo "state=success" >> "$GITHUB_OUTPUT"
|
|
142
|
+
echo "description=Coverage not affected" >> "$GITHUB_OUTPUT"
|
|
143
|
+
echo "No Python source changes — skipping diff-cover"
|
|
144
|
+
else
|
|
145
|
+
OUTPUT=$(uv run diff-cover coverage.xml --compare-branch="origin/${BASE_REF}" --fail-under=80 2>&1) && RC=0 || RC=$?
|
|
146
|
+
echo "$OUTPUT"
|
|
147
|
+
TOTAL=$(echo "$OUTPUT" | grep -oP 'Total:\s+\K[\d.]+' || true)
|
|
148
|
+
if [ -z "$TOTAL" ] && [ "$RC" -ne 0 ]; then
|
|
149
|
+
echo "state=error" >> "$GITHUB_OUTPUT"
|
|
150
|
+
echo "description=diff-cover failed to compute patch coverage" >> "$GITHUB_OUTPUT"
|
|
151
|
+
elif [ -z "$TOTAL" ]; then
|
|
152
|
+
echo "state=success" >> "$GITHUB_OUTPUT"
|
|
153
|
+
echo "description=No coverable lines in diff" >> "$GITHUB_OUTPUT"
|
|
154
|
+
elif [ "$RC" -eq 0 ]; then
|
|
155
|
+
echo "state=success" >> "$GITHUB_OUTPUT"
|
|
156
|
+
echo "description=Patch coverage: ${TOTAL}%" >> "$GITHUB_OUTPUT"
|
|
157
|
+
else
|
|
158
|
+
echo "state=failure" >> "$GITHUB_OUTPUT"
|
|
159
|
+
echo "description=Patch coverage: ${TOTAL}% (minimum 80%)" >> "$GITHUB_OUTPUT"
|
|
160
|
+
fi
|
|
161
|
+
fi
|
|
162
|
+
|
|
163
|
+
- name: Save patch coverage result
|
|
164
|
+
if: matrix.python-version == '3.13' && github.event_name == 'pull_request'
|
|
165
|
+
env:
|
|
166
|
+
PATCH_STATE: ${{ steps.diffcover.outputs.state || 'error' }}
|
|
167
|
+
PATCH_DESC: ${{ steps.diffcover.outputs.description || 'diff-cover step did not run' }}
|
|
168
|
+
run: |
|
|
169
|
+
jq -n --arg state "$PATCH_STATE" --arg description "$PATCH_DESC" \
|
|
170
|
+
'{"state":$state,"description":$description}' > patch-coverage.json
|
|
171
|
+
|
|
172
|
+
- name: Upload patch coverage artifact
|
|
173
|
+
if: matrix.python-version == '3.13' && github.event_name == 'pull_request'
|
|
174
|
+
uses: actions/upload-artifact@v7
|
|
175
|
+
with:
|
|
176
|
+
name: patch-coverage
|
|
177
|
+
path: patch-coverage.json
|
|
178
|
+
retention-days: 1
|
|
179
|
+
|
|
180
|
+
- name: Post codecov/patch status
|
|
181
|
+
# Fork PRs: GITHUB_TOKEN is read-only for pull_request events from forks regardless
|
|
182
|
+
# of the permissions block — GitHub security restriction. continue-on-error prevents
|
|
183
|
+
# the job from failing; coverage-status.yml posts the status via workflow_run instead.
|
|
184
|
+
if: matrix.python-version == '3.13' && github.event_name == 'pull_request' && always()
|
|
185
|
+
continue-on-error: true
|
|
186
|
+
uses: actions/github-script@v9
|
|
187
|
+
env:
|
|
188
|
+
PATCH_STATE: ${{ steps.diffcover.outputs.state }}
|
|
189
|
+
PATCH_DESC: ${{ steps.diffcover.outputs.description }}
|
|
190
|
+
with:
|
|
191
|
+
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
192
|
+
script: |
|
|
193
|
+
const state = process.env.PATCH_STATE || 'error';
|
|
194
|
+
const description = process.env.PATCH_DESC || 'diff-cover step did not run';
|
|
195
|
+
const headSha = context.payload.pull_request.head.sha;
|
|
196
|
+
core.info(`Posting codecov/patch: ${state} — ${description} to ${headSha}`);
|
|
197
|
+
await github.rest.repos.createCommitStatus({
|
|
198
|
+
owner: context.repo.owner,
|
|
199
|
+
repo: context.repo.repo,
|
|
200
|
+
sha: headSha,
|
|
201
|
+
state,
|
|
202
|
+
context: 'codecov/patch',
|
|
203
|
+
description,
|
|
204
|
+
target_url: 'https://app.codecov.io/gh/pvliesdonk/logodev-mcp',
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
audit:
|
|
208
|
+
name: Dependency Audit
|
|
209
|
+
runs-on: ubuntu-latest
|
|
210
|
+
timeout-minutes: 10
|
|
211
|
+
permissions:
|
|
212
|
+
contents: read
|
|
213
|
+
steps:
|
|
214
|
+
- uses: actions/checkout@v7
|
|
215
|
+
|
|
216
|
+
- name: Install uv
|
|
217
|
+
uses: astral-sh/setup-uv@v8.2.0
|
|
218
|
+
with:
|
|
219
|
+
version: "latest"
|
|
220
|
+
|
|
221
|
+
- name: Cache Python interpreter
|
|
222
|
+
uses: actions/cache@v5
|
|
223
|
+
with:
|
|
224
|
+
path: ~/.local/share/uv/python
|
|
225
|
+
key: uv-python-3.12-${{ runner.os }}
|
|
226
|
+
|
|
227
|
+
- name: Set up Python
|
|
228
|
+
run: uv python install 3.12
|
|
229
|
+
|
|
230
|
+
- name: Export dependency list (excluding local project)
|
|
231
|
+
# `dev` is uv's only auto-activated default group, so --no-default-groups
|
|
232
|
+
# excludes it; `docs` is non-default and never exported unless explicitly
|
|
233
|
+
# requested via --group/--all-groups (neither passed here). Net effect:
|
|
234
|
+
# only runtime + user-defined extras land in the audit input — avoids
|
|
235
|
+
# spurious CVE reports against tooling (pip-audit's own `pip` dep, etc.)
|
|
236
|
+
# that does not run in production.
|
|
237
|
+
run: uv export --all-extras --no-default-groups --frozen --no-emit-project --no-hashes -o ${{ runner.temp }}/requirements.txt
|
|
238
|
+
|
|
239
|
+
- name: Run pip-audit
|
|
240
|
+
run: |
|
|
241
|
+
uvx pip-audit --strict --progress-spinner off \
|
|
242
|
+
--ignore-vuln CVE-2026-42561 \
|
|
243
|
+
-r ${{ runner.temp }}/requirements.txt
|
|
244
|
+
# CVE-2026-42561: python-multipart <0.0.27, pulled in transitively by
|
|
245
|
+
# fastmcp/starlette. Ignored until the upstream pin chain propagates
|
|
246
|
+
# the fix to 0.0.27. Remove once `uv lock` resolves >=0.0.27.
|
|
247
|
+
|
|
248
|
+
secrets:
|
|
249
|
+
name: Secret Detection
|
|
250
|
+
runs-on: ubuntu-latest
|
|
251
|
+
permissions:
|
|
252
|
+
contents: read
|
|
253
|
+
steps:
|
|
254
|
+
- uses: actions/checkout@v7
|
|
255
|
+
with:
|
|
256
|
+
fetch-depth: 0
|
|
257
|
+
|
|
258
|
+
- name: Run gitleaks
|
|
259
|
+
uses: gitleaks/gitleaks-action@ff98106e4c7b2bc287b24eaf42907196329070c7 # v2
|
|
260
|
+
env:
|
|
261
|
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
262
|
+
|
|
263
|
+
vale:
|
|
264
|
+
name: Docs Prose (Vale)
|
|
265
|
+
runs-on: ubuntu-latest
|
|
266
|
+
permissions:
|
|
267
|
+
contents: read
|
|
268
|
+
# vale-cli/vale-action posts findings as PR annotations via reviewdog.
|
|
269
|
+
# The default reporter (`github-pr-annotations`) uses the GitHub Checks
|
|
270
|
+
# API — `checks: write` is sufficient. If a downstream switches the
|
|
271
|
+
# reporter to `github-pr-review` (inline PR review comments), they
|
|
272
|
+
# need to add `pull-requests: write` here too.
|
|
273
|
+
checks: write
|
|
274
|
+
steps:
|
|
275
|
+
- uses: actions/checkout@v7
|
|
276
|
+
|
|
277
|
+
- name: Cache Vale style packages
|
|
278
|
+
# Cache only the downloaded pack directories — NOT .vale/styles/config/.
|
|
279
|
+
# The config/ subtree (accept.txt vocabulary) is tracked by git and must
|
|
280
|
+
# stay authoritative from checkout. Caching the whole .vale/styles tree
|
|
281
|
+
# would let restore-keys overwrite a newly-added vocab term with the
|
|
282
|
+
# stale snapshot on the exact PR that adds the term.
|
|
283
|
+
# Pack list mirrors the Packages = line in .vale.ini; if you add or
|
|
284
|
+
# remove a pack, update both. Bump the v1- prefix to evict all cached
|
|
285
|
+
# packs if Vale changes pack format backward-incompatibly.
|
|
286
|
+
uses: actions/cache@v5
|
|
287
|
+
with:
|
|
288
|
+
path: |
|
|
289
|
+
.vale/styles/Google
|
|
290
|
+
.vale/styles/proselint
|
|
291
|
+
.vale/styles/write-good
|
|
292
|
+
.vale/styles/ai-tells
|
|
293
|
+
key: vale-styles-v1-${{ hashFiles('.vale.ini') }}
|
|
294
|
+
# Warm-start fallback: restores the most recent pack snapshot when
|
|
295
|
+
# .vale.ini changes (e.g. URL bump). vale sync then only re-fetches
|
|
296
|
+
# the changed pack rather than re-downloading all four.
|
|
297
|
+
restore-keys: vale-styles-v1-
|
|
298
|
+
|
|
299
|
+
- name: Run Vale
|
|
300
|
+
# SHA pin matches the gitleaks-action pattern earlier in this file.
|
|
301
|
+
# The current release is named "v2.1.2" in the GitHub UI but the
|
|
302
|
+
# underlying git tag is `2.1.2` (no `v` prefix) — pinning to the
|
|
303
|
+
# SHA sidesteps that mismatch and provides supply-chain hygiene.
|
|
304
|
+
uses: vale-cli/vale-action@85f9f7f2c5f449ac0ae5b66662961bae3f77ca6a # v2.1.2
|
|
305
|
+
with:
|
|
306
|
+
# Pin Vale CLI version explicitly. Bump in lockstep with the
|
|
307
|
+
# pre-commit hook `rev:` in .pre-commit-config.yaml — template-ci
|
|
308
|
+
# asserts the two stay synchronized.
|
|
309
|
+
version: "3.14.2"
|
|
310
|
+
files: docs
|
|
311
|
+
# Working specs follow internal conventions, not user-facing prose
|
|
312
|
+
# style — exclude from linting. NO inner single quotes around the
|
|
313
|
+
# glob value: vale-action splits `vale_flags` on whitespace and
|
|
314
|
+
# passes argv elements directly (no shell), so literal quotes here
|
|
315
|
+
# would be passed through to Vale, the glob would match no files,
|
|
316
|
+
# and CI would silently exit 0. Verified empirically.
|
|
317
|
+
vale_flags: "--glob=!docs/superpowers/**"
|
|
318
|
+
# Failure gating is controlled by MinAlertLevel = error in
|
|
319
|
+
# .vale.ini (governs both what Vale prints AND its exit code)
|
|
320
|
+
# combined with fail_on_error below — only error-severity
|
|
321
|
+
# findings fail CI; warnings and suggestions surface as advisory
|
|
322
|
+
# annotations. (The action also accepts a `level:` input, but at
|
|
323
|
+
# the pinned SHA that input is declared but never read — the
|
|
324
|
+
# reviewdog level is derived from Vale's exit code and
|
|
325
|
+
# fail_on_error. Setting it here would be a no-op.)
|
|
326
|
+
fail_on_error: true
|
|
327
|
+
# filter_mode defaults to `added` — only findings on lines this PR
|
|
328
|
+
# adds or modifies fail the build. Pre-existing prose debt isn't a
|
|
329
|
+
# blocker for new contributions; downstream's own untouched docs
|
|
330
|
+
# don't gate PRs that don't touch them. To enforce repo-wide
|
|
331
|
+
# cleanliness, set this to `nofilter`.
|
|
332
|
+
filter_mode: added
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
name: Claude Code Review
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
types: [opened, synchronize, ready_for_review, reopened]
|
|
6
|
+
# Optional: Only run on specific file changes
|
|
7
|
+
# paths:
|
|
8
|
+
# - "src/**/*.ts"
|
|
9
|
+
# - "src/**/*.tsx"
|
|
10
|
+
# - "src/**/*.js"
|
|
11
|
+
# - "src/**/*.jsx"
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
claude-review:
|
|
15
|
+
# Skip PRs from forks: GitHub does not expose repository secrets
|
|
16
|
+
# (including CLAUDE_CODE_OAUTH_TOKEN) to workflows running in fork-PR
|
|
17
|
+
# context, regardless of maintainer approval. Running anyway produces
|
|
18
|
+
# a hard-failing check on every external contribution. Maintainers who
|
|
19
|
+
# want a bot review on a fork PR can push the contributor's branch to
|
|
20
|
+
# this repo under a topic name and the workflow will run.
|
|
21
|
+
if: github.event.pull_request.head.repo.full_name == github.repository
|
|
22
|
+
|
|
23
|
+
# Optional: Filter by PR author
|
|
24
|
+
# if: |
|
|
25
|
+
# github.event.pull_request.user.login == 'external-contributor' ||
|
|
26
|
+
# github.event.pull_request.user.login == 'new-developer' ||
|
|
27
|
+
# github.event.pull_request.author_association == 'FIRST_TIME_CONTRIBUTOR'
|
|
28
|
+
|
|
29
|
+
runs-on: ubuntu-latest
|
|
30
|
+
permissions:
|
|
31
|
+
contents: read
|
|
32
|
+
pull-requests: write # Required so the review action can post inline comments
|
|
33
|
+
issues: read
|
|
34
|
+
id-token: write
|
|
35
|
+
|
|
36
|
+
steps:
|
|
37
|
+
- name: Checkout repository
|
|
38
|
+
uses: actions/checkout@v7
|
|
39
|
+
with:
|
|
40
|
+
fetch-depth: 1
|
|
41
|
+
|
|
42
|
+
- name: Run Claude Code Review
|
|
43
|
+
id: claude-review
|
|
44
|
+
uses: anthropics/claude-code-action@v1
|
|
45
|
+
with:
|
|
46
|
+
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
|
|
47
|
+
plugin_marketplaces: 'https://github.com/anthropics/claude-code.git'
|
|
48
|
+
plugins: 'code-review@claude-code-plugins'
|
|
49
|
+
# `--comment` tells the plugin to actually post (without it, the plugin
|
|
50
|
+
# runs the full review and stops silently — burning ~$3/PR for no output).
|
|
51
|
+
prompt: '/code-review:code-review --comment ${{ github.repository }}/pull/${{ github.event.pull_request.number }}'
|
|
52
|
+
# Surface progress so a silent failure is visible: a sticky tracking
|
|
53
|
+
# comment updates during the run, and the Claude Code Report appears
|
|
54
|
+
# in the job's GitHub Step Summary.
|
|
55
|
+
track_progress: true
|
|
56
|
+
display_report: true
|
|
57
|
+
# See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md
|
|
58
|
+
# or https://code.claude.com/docs/en/cli-reference for available options
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
name: Claude Code
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
issue_comment:
|
|
5
|
+
types: [created]
|
|
6
|
+
pull_request_review_comment:
|
|
7
|
+
types: [created]
|
|
8
|
+
issues:
|
|
9
|
+
types: [opened, assigned]
|
|
10
|
+
pull_request_review:
|
|
11
|
+
types: [submitted]
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
claude:
|
|
15
|
+
# Trigger only on @claude mentions, AND on the two PR-context events
|
|
16
|
+
# (`pull_request_review*`) only when the PR head is in this repo. Those
|
|
17
|
+
# events run in PR context for fork PRs, where GitHub withholds repository
|
|
18
|
+
# secrets (incl. CLAUDE_CODE_OAUTH_TOKEN) and the action would auth-fail.
|
|
19
|
+
# `issues` and `issue_comment` always run in base-repo context, so secrets
|
|
20
|
+
# are available — no fork check needed there.
|
|
21
|
+
if: |
|
|
22
|
+
(github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) ||
|
|
23
|
+
(github.event_name == 'issues' && (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude'))) ||
|
|
24
|
+
(github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude') && github.event.pull_request.head.repo.full_name == github.repository) ||
|
|
25
|
+
(github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude') && github.event.pull_request.head.repo.full_name == github.repository)
|
|
26
|
+
runs-on: ubuntu-latest
|
|
27
|
+
permissions:
|
|
28
|
+
contents: read
|
|
29
|
+
pull-requests: read
|
|
30
|
+
issues: read
|
|
31
|
+
id-token: write
|
|
32
|
+
actions: read # Required for Claude to read CI results on PRs
|
|
33
|
+
steps:
|
|
34
|
+
- name: Checkout repository
|
|
35
|
+
uses: actions/checkout@v7
|
|
36
|
+
with:
|
|
37
|
+
fetch-depth: 1
|
|
38
|
+
|
|
39
|
+
- name: Run Claude Code
|
|
40
|
+
id: claude
|
|
41
|
+
uses: anthropics/claude-code-action@v1
|
|
42
|
+
with:
|
|
43
|
+
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
|
|
44
|
+
|
|
45
|
+
# This is an optional setting that allows Claude to read CI results on PRs
|
|
46
|
+
additional_permissions: |
|
|
47
|
+
actions: read
|
|
48
|
+
|
|
49
|
+
# Optional: Give a custom prompt to Claude. If this is not specified, Claude will perform the instructions specified in the comment that tagged it.
|
|
50
|
+
# prompt: 'Update the pull request description to include a summary of changes.'
|
|
51
|
+
|
|
52
|
+
# Optional: Add claude_args to customize behavior and configuration
|
|
53
|
+
# See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md
|
|
54
|
+
# or https://code.claude.com/docs/en/cli-reference for available options
|
|
55
|
+
# claude_args: '--allowed-tools Bash(gh pr *)'
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
name: CodeQL
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
schedule:
|
|
9
|
+
- cron: "0 6 * * 1" # Weekly on Monday at 06:00 UTC
|
|
10
|
+
|
|
11
|
+
permissions:
|
|
12
|
+
actions: read
|
|
13
|
+
contents: read
|
|
14
|
+
security-events: write
|
|
15
|
+
|
|
16
|
+
jobs:
|
|
17
|
+
analyze:
|
|
18
|
+
name: CodeQL Analysis
|
|
19
|
+
runs-on: ubuntu-latest
|
|
20
|
+
steps:
|
|
21
|
+
- uses: actions/checkout@v7
|
|
22
|
+
|
|
23
|
+
- name: Initialize CodeQL
|
|
24
|
+
uses: github/codeql-action/init@v4
|
|
25
|
+
with:
|
|
26
|
+
languages: python
|
|
27
|
+
queries: security-extended
|
|
28
|
+
config-file: .github/codeql/codeql-config.yml
|
|
29
|
+
|
|
30
|
+
- name: Perform CodeQL Analysis
|
|
31
|
+
uses: github/codeql-action/analyze@v4
|