feat(hooks): SessionStart hook auto-injects Purchasely skill pointers #18
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: validate | |
| on: | |
| push: | |
| branches: [main] | |
| pull_request: | |
| branches: [main] | |
| jobs: | |
| structure: | |
| name: Plugin structure & JSON | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Validate plugin.json | |
| run: | | |
| test -f .claude-plugin/plugin.json | |
| python3 -c "import json; json.load(open('.claude-plugin/plugin.json'))" | |
| - name: Validate marketplace.json | |
| run: | | |
| test -f .claude-plugin/marketplace.json | |
| python3 -c "import json; json.load(open('.claude-plugin/marketplace.json'))" | |
| - name: Validate package.json | |
| run: | | |
| test -f package.json | |
| python3 -c "import json; json.load(open('package.json'))" | |
| - name: Check required files | |
| run: | | |
| for f in README.md LICENSE CONTRIBUTING.md SECURITY.md CODE_OF_CONDUCT.md CHANGELOG.md .gitignore install.sh; do | |
| test -f "$f" || { echo "::error file=$f::Missing required file"; exit 1; } | |
| done | |
| - name: Check all skills have SKILL.md | |
| run: | | |
| for d in skills/*/; do | |
| test -f "$d/SKILL.md" || { echo "::error file=$d::Missing SKILL.md"; exit 1; } | |
| done | |
| - name: Validate SKILL.md front-matter | |
| run: | | |
| python3 <<'PY' | |
| import os, re, sys, glob | |
| required = ("name", "description") | |
| errors = [] | |
| for path in sorted(glob.glob("skills/*/SKILL.md")): | |
| with open(path) as f: | |
| content = f.read() | |
| m = re.match(r"^---\s*\n(.*?)\n---\s*\n", content, re.DOTALL) | |
| if not m: | |
| errors.append(f"{path}: missing YAML front-matter") | |
| continue | |
| fm = m.group(1) | |
| for key in required: | |
| if not re.search(rf"^{key}\s*:", fm, re.MULTILINE): | |
| errors.append(f"{path}: front-matter missing '{key}:'") | |
| if errors: | |
| for e in errors: | |
| print(f"::error::{e}") | |
| sys.exit(1) | |
| print("All SKILL.md front-matter OK") | |
| PY | |
| - name: Reject committed real API keys | |
| run: | | |
| if grep -rE 'pk_(live|test)_[A-Za-z0-9]{20,}|sk_(live|test)_[A-Za-z0-9]{20,}' \ | |
| --include='*.md' --include='*.json' --include='*.sh' --include='*.yml' \ | |
| --exclude-dir=.git . ; then | |
| echo "::error::Real-looking API key detected — refusing to merge." | |
| exit 1 | |
| fi | |
| markdownlint: | |
| name: Lint Markdown | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: DavidAnson/markdownlint-cli2-action@v17 | |
| with: | |
| globs: | | |
| **/*.md | |
| !node_modules | |
| !.github/PULL_REQUEST_TEMPLATE.md | |
| !.github/ISSUE_TEMPLATE/** | |
| shellcheck: | |
| name: ShellCheck install.sh | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Verify install.sh is executable | |
| run: | | |
| test -x install.sh || { echo "::error file=install.sh::Not executable"; exit 1; } | |
| - name: POSIX syntax check | |
| run: sh -n install.sh | |
| - uses: ludeeus/action-shellcheck@master | |
| with: | |
| scandir: '.' | |
| severity: warning | |
| additional_files: install.sh | |
| test-installer: | |
| name: Test installer (${{ matrix.tool }}) | |
| runs-on: ubuntu-latest | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| tool: [cursor, copilot, windsurf, codex, gemini, mistral] | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Prepare detection conditions | |
| run: | | |
| mkdir -p /tmp/test-project | |
| case "${{ matrix.tool }}" in | |
| cursor) mkdir -p /tmp/test-project/.cursor ;; | |
| copilot) mkdir -p /tmp/test-project/.github ;; | |
| windsurf) mkdir -p /tmp/test-project/.codeium ;; | |
| codex) touch /tmp/test-project/AGENTS.md ;; | |
| gemini) sudo ln -sf /bin/true /usr/local/bin/gemini ;; | |
| mistral) touch /tmp/test-project/AGENTS.md ;; | |
| esac | |
| - name: Run installer with auto-yes | |
| run: | | |
| # Pipe "y" repeatedly so confirm() prompts auto-accept | |
| yes | ./install.sh --tool ${{ matrix.tool }} --project /tmp/test-project || true | |
| - name: Show resulting test project | |
| run: | | |
| ls -la /tmp/test-project | |
| find /tmp/test-project -type f -maxdepth 3 |