Skip to content

notion-ios: the Plus & Notion AI purchase sheet, boards 16–18 #31

notion-ios: the Plus & Notion AI purchase sheet, boards 16–18

notion-ios: the Plus & Notion AI purchase sheet, boards 16–18 #31

Workflow file for this run

name: Validate
# The gates a release has to pass. Nothing here needs a secret, so it runs on
# every pull request; `release.yml` calls this same file before it prepares one,
# which is why `workflow_call` is in the trigger list.
on:
pull_request:
push:
branches: [main]
workflow_call:
workflow_dispatch:
permissions:
contents: read
jobs:
manifests:
name: Manifests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
persist-credentials: false
- uses: actions/setup-node@v4
with:
node-version: "22"
- name: Install Claude Code
run: npm install -g @anthropic-ai/claude-code
# --strict fails on warnings: an unrecognised field is how a manifest silently
# ships half its components (`mcpServer` for `mcpServers` validates as an
# unknown key and loads nothing).
- name: Validate the marketplace manifest
run: claude plugin validate . --strict
- name: Validate the plugin manifest
run: claude plugin validate .claude-plugin/plugin.json --strict
# Four other products read four other files, and `claude plugin validate` has
# no opinion about any of them. Parsing is the most this can check without
# each product's CLI on the runner; a broken one means that product's install
# fails, with nothing upstream to catch it.
- name: Parse the manifests Claude Code does not read
run: |
for f in plugin.json .codex-plugin/plugin.json .codebuddy-plugin/plugin.json \
.agents/plugins/marketplace.json .version-bump.json; do
echo "parsing $f"
python3 -m json.tool "$f" > /dev/null
done
# The portable manifest is schema'd, and its two required fields are the two
# a hand-edit is most likely to drop. `name` also has to match the other
# manifests, or a product installs a plugin under a name nothing else uses.
- name: The portable manifest is Agent Plugins v1
run: |
python3 - <<'PY'
import json
portable = json.load(open("plugin.json"))
claude = json.load(open(".claude-plugin/plugin.json"))
schema = "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json"
assert portable.get("$schema") == schema, portable.get("$schema")
assert portable.get("name") == claude["name"], portable.get("name")
# Skills are discovered from skills/*/SKILL.md; the schema forbids the key.
assert "skills" not in portable
print("plugin.json is a v1.0.0 manifest for", portable["name"])
PY
# The version is the cache key an install compares against, so two manifests
# disagreeing means half the install updates and half does not.
- name: Every manifest agrees on one version
run: scripts/bump-version.sh --check
- name: Shell scripts parse
run: |
bash -n scripts/bump-version.sh
bash -n scripts/install-skills.sh
canvas:
name: Canvas
runs-on: ubuntu-latest
defaults:
run:
working-directory: canvas
steps:
- uses: actions/checkout@v4
with:
persist-credentials: false
- uses: oven-sh/setup-bun@v2
- run: bun install --frozen-lockfile
- run: bun run lint
- run: bun run test
- run: bun run build
tools:
name: Toolkit
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
persist-credentials: false
- uses: astral-sh/setup-uv@v5
# The same two lines the README gives for running these locally.
- run: uv run --with pillow --with numpy python tools/test_refkit.py
- run: uv run python tools/test_sp_canvas.py
# The skills call these by name, so a syntax error in one is a broken install
# rather than a broken test.
- run: uv run python -m compileall -q tools