Skip to content

Foreman 1.4.0: stop the skip to build, and stop shipping dead pages #17

Foreman 1.4.0: stop the skip to build, and stop shipping dead pages

Foreman 1.4.0: stop the skip to build, and stop shipping dead pages #17

Workflow file for this run

name: validate
on:
push:
branches: [main]
pull_request:
workflow_dispatch:
jobs:
validate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Manifests are valid JSON with the required keys
run: |
python3 - <<'PY'
import json, sys
fail = []
mk = json.load(open('.claude-plugin/marketplace.json'))
for k in ('name', 'owner', 'plugins'):
if k not in mk:
fail.append(f'marketplace.json missing "{k}"')
for p in mk.get('plugins', []):
for k in ('name', 'source', 'description'):
if k not in p:
fail.append(f'marketplace plugin entry missing "{k}"')
pl = json.load(open('plugins/foreman/.claude-plugin/plugin.json'))
if 'name' not in pl:
fail.append('plugin.json missing "name"')
entry = next((p for p in mk['plugins'] if p['name'] == pl['name']), None)
if entry is None:
fail.append('plugin.json name is not listed in marketplace.json')
elif entry.get('version') != pl.get('version'):
fail.append('version disagrees between marketplace.json and plugin.json')
if fail:
print('\n'.join(fail)); sys.exit(1)
print('manifests ok')
PY
- name: Skill frontmatter is present and within the description limit
run: |
python3 - <<'PY'
import re, sys
t = open('plugins/foreman/skills/foreman/SKILL.md').read()
m = re.match(r'^---\n(.*?)\n---\n', t, re.S)
if not m:
print('SKILL.md has no frontmatter'); sys.exit(1)
fm = m.group(1)
fail = []
if not re.search(r'^name:\s*foreman\s*$', fm, re.M):
fail.append('frontmatter name is not "foreman"')
d = re.search(r'^description:\s*(.+)$', fm, re.M)
if not d:
fail.append('frontmatter has no description')
elif len(d.group(1)) > 1024:
fail.append(f'description is {len(d.group(1))} chars, limit is 1024')
if fail:
print('\n'.join(fail)); sys.exit(1)
print('frontmatter ok')
PY
- name: No unreplaced placeholders
run: |
# Bracketed last letter so this step does not match its own pattern.
# CHANGELOG.md is excluded: it describes placeholders that were removed,
# so quoting one there is correct rather than a defect.
if grep -rn 'GH_HANDL[E]\|LINKEDIN_UR[L]\|SITE_UR[L]\|\[X\] MB' \
--include='*.md' --include='*.json' --include='*.yml' --include='*.html' \
--exclude='CHANGELOG.md' . ; then
echo "unreplaced placeholder above"; exit 1
fi
echo "no placeholders"
- name: No em dashes or en dashes in shipped text
run: |
# .github is excluded so this step does not match its own pattern.
if grep -rn '—\|–' \
README.md CHANGELOG.md CONTRIBUTING.md AGENTS.md plugins/ docs/ ; then
echo "em dash or en dash above"; exit 1
fi
echo "punctuation ok"
- name: Every file SKILL.md names actually exists
run: |
cd plugins/foreman/skills/foreman
missing=0
for f in $(grep -o '`[a-z0-9./-]*\.\(md\|html\|txt\|xml\)`' SKILL.md | tr -d '`' | sort -u); do
case "$f" in
CHANGELOG.md|brand.html) continue ;;
esac
if [ ! -f "references/$f" ] && [ ! -f "assets/$f" ] && [ ! -f "$f" ]; then
echo "SKILL.md references a file that does not exist: $f"; missing=1
fi
done
[ "$missing" = 0 ] && echo "all referenced files present"
exit $missing
- name: Nothing in the plugin executes
run: |
# The only <script> allowed anywhere is the JSON-LD data block.
if grep -rno '<script[^>]*>' plugins/ | grep -v 'application/ld+json' ; then
echo "script tag above"; exit 1
fi
if grep -rniE 'onclick=|onerror=|onload=|eval\(|new Function|document\.write' plugins/ ; then
echo "executable content above"; exit 1
fi
if find plugins -type f \( -name '*.sh' -o -name '*.py' -o -name '*.js' -o -name '*.mjs' \) | grep . ; then
echo "script file above"; exit 1
fi
echo "no executable content"
- name: dist/foreman.skill matches the source skill
run: |
rm -rf /tmp/unpacked && mkdir -p /tmp/unpacked
unzip -q dist/foreman.skill -d /tmp/unpacked
if diff -r --exclude='.DS_Store' \
plugins/foreman/skills/foreman /tmp/unpacked/foreman ; then
echo "dist archive is in sync"
else
echo "dist/foreman.skill has drifted from plugins/foreman/skills/foreman/"
echo "rebuild it, then commit:"
echo " cd plugins/foreman/skills && zip -r ../../../dist/foreman.skill foreman -x '*.DS_Store'"
exit 1
fi