-
Notifications
You must be signed in to change notification settings - Fork 1
fix: add CI, GitHub API auth, and better YAML parse errors #1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,32 @@ | ||||||||||
| name: CI | ||||||||||
|
|
||||||||||
| on: | ||||||||||
| push: | ||||||||||
| branches: [main] | ||||||||||
| pull_request: | ||||||||||
| branches: [main] | ||||||||||
|
|
||||||||||
| jobs: | ||||||||||
| typecheck: | ||||||||||
| runs-on: ubuntu-latest | ||||||||||
| steps: | ||||||||||
| - uses: actions/checkout@v4 | ||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. π Security & Privacy | π‘ Minor | β‘ Quick win π§© Analysis chainπ Script executed: #!/bin/bash
set -euo pipefail
echo "== workflow files =="
git ls-files .github/workflows || true
echo
echo "== ci.yml =="
if [ -f .github/workflows/ci.yml ]; then
cat -n .github/workflows/ci.yml | sed -n '1,80p'
fi
echo
echo "== package build script =="
if [ -f package.json ]; then
node -e "const p=require('./package.json'); console.log(JSON.stringify(p.scripts, null, 2))" 2>/dev/null || cat -n package.json | sed -n '1,40p'
fi
echo
echo "== build-ui script =="
for f in scripts/build-ui.mjs scripts/build-ui.js scripts/build-ui.ts; do
if [ -f "$f" ]; then
echo "-- $f --"
cat -n "$f" | sed -n '1,220p'
fi
done
echo
echo "== checkout occurrences =="
rg -n "actions/checkout|persist-credentials|pnpm build|build-ui|GITHUB_TOKEN|process\.env\." .github package.json scripts 2>/dev/null || trueRepository: leeknowsai/paperclip-plugin-superpowers Length of output: 2433 π Web query:
π‘ Result: In the actions/checkout v4 action, the persist-credentials input defaults to true [1][2]. When set to true (the default), the action configures the authentication token or SSH key into the local git configuration [1][2]. This allows your workflow scripts to run authenticated git commands, such as git push or git pull, during the job execution [1][3]. The credentials are removed automatically during the post-job cleanup process [1][3]. If you do not want these credentials to be persisted in the local git configuration, you can explicitly set persist-credentials to false [1][4]. Citations:
π Web query:
π‘ Result: In GitHub Actions, the Citations:
π Web query:
π‘ Result: In Citations:
Disable checkout credential persistence. Set Proposed fix- - uses: actions/checkout@v4
+ - uses: actions/checkout@v4
+ with:
+ persist-credentials: falseThe same change applies to the checkout step in the build job and the checkout step in the typecheck job. π Committable suggestion
Suggested change
π§° Toolsπͺ zizmor (1.28.0)[warning] 13-13: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false (artipacked) π€ Prompt for AI AgentsSource: Linters/SAST tools |
||||||||||
| - uses: pnpm/action-setup@v4 | ||||||||||
| - uses: actions/setup-node@v4 | ||||||||||
| with: | ||||||||||
| node-version: 22 | ||||||||||
| cache: pnpm | ||||||||||
| - run: pnpm install --frozen-lockfile | ||||||||||
| - run: pnpm typecheck | ||||||||||
|
|
||||||||||
| build: | ||||||||||
| runs-on: ubuntu-latest | ||||||||||
| steps: | ||||||||||
| - uses: actions/checkout@v4 | ||||||||||
| - uses: pnpm/action-setup@v4 | ||||||||||
| - uses: actions/setup-node@v4 | ||||||||||
| with: | ||||||||||
| node-version: 22 | ||||||||||
| cache: pnpm | ||||||||||
| - run: pnpm install --frozen-lockfile | ||||||||||
| - run: pnpm build | ||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -102,36 +102,58 @@ export class GitHubSync { | |
| return { synced, errors, total: synced + errors }; | ||
| } | ||
|
|
||
| /** Build auth headers from GITHUB_TOKEN env var (optional). */ | ||
| private authHeaders(): Record<string, string> { | ||
| const token = process.env.GITHUB_TOKEN; | ||
| const headers: Record<string, string> = { | ||
| Accept: "application/vnd.github+json", | ||
| }; | ||
| if (token) { | ||
| headers.Authorization = `Bearer ${token}`; | ||
| } | ||
| return headers; | ||
| } | ||
|
|
||
| private async fetchTree(): Promise<TreeEntry[]> { | ||
| const url = `https://api.github.com/repos/${this.repo}/git/trees/main?recursive=1`; | ||
| const res = await fetch(url, { | ||
| headers: { Accept: "application/vnd.github+json" }, | ||
| }); | ||
| const res = await fetch(url, { headers: this.authHeaders() }); | ||
| if (!res.ok) { | ||
| throw new Error(`GitHub tree API returned ${res.status}`); | ||
| const detail = await res.text().catch(() => ""); | ||
| throw new Error(`GitHub tree API returned ${res.status}: ${detail.slice(0, 200)}`); | ||
|
Comment on lines
+121
to
+122
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. π©Ί Stability & Availability | π Major | β‘ Quick win π§© Analysis chainπ Script executed: #!/usr/bin/env bash
set -euo pipefail
rg -n 'res\.text\(\)|detail\.slice\(0,\s*200\)' src/sync/github-sync.ts
node --input-type=module <<'EOF'
const size = 1024 * 1024;
const response = new Response("x".repeat(size), { status: 500 });
const body = await response.text();
if (body.length !== size) {
throw new Error("Response.text() did not consume the full body");
}
console.log("Response.text() consumes the full response body");
EOFRepository: leeknowsai/paperclip-plugin-superpowers Length of output: 722 π Script executed: #!/usr/bin/env bash
set -euo pipefail
printf 'Outline:\n'
ast-grep outline src/sync/github-sync.ts --view compact || true
printf '\nRelevant source:\n'
sed -n '1,170p' src/sync/github-sync.tsRepository: leeknowsai/paperclip-plugin-superpowers Length of output: 5916 Bound the error-body read before truncating it.
π€ Prompt for AI Agents |
||
| } | ||
| const data = (await res.json()) as { tree: TreeEntry[] }; | ||
| return data.tree; | ||
| } | ||
|
|
||
| private async fetchRawContent(path: string): Promise<string> { | ||
| const url = `https://raw.githubusercontent.com/${this.repo}/main/${path}`; | ||
| const res = await fetch(url); | ||
| const res = await fetch(url, { headers: this.authHeaders() }); | ||
| if (!res.ok) { | ||
| throw new Error(`Failed to fetch ${path}: ${res.status}`); | ||
| const detail = await res.text().catch(() => ""); | ||
| throw new Error(`Failed to fetch ${path}: ${res.status} β ${detail.slice(0, 200)}`); | ||
| } | ||
| return res.text(); | ||
| } | ||
|
|
||
| parseSkillFile(raw: string, skillId: string): Skill | null { | ||
| // Extract YAML frontmatter between --- markers | ||
| const fmMatch = raw.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/); | ||
| if (!fmMatch) return null; | ||
| if (!fmMatch) { | ||
| this.ctx.logger.warn( | ||
| `Skill "${skillId}" has no valid YAML frontmatter (expected ---\nname: ...\n---). Skipping.`, | ||
| ); | ||
| return null; | ||
| } | ||
|
|
||
| const frontmatter = fmMatch[1]; | ||
| const body = fmMatch[2].trim(); | ||
| const fm = this.parseSimpleYaml(frontmatter); | ||
| if (!fm.name) return null; | ||
| if (!fm.name) { | ||
| this.ctx.logger.warn( | ||
| `Skill "${skillId}" frontmatter is missing required "name" field. Skipping.`, | ||
| ); | ||
| return null; | ||
| } | ||
|
|
||
| return { | ||
| id: skillId, | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
π Security & Privacy | π Major | β‘ Quick win
π§© Analysis chain
π Script executed:
Repository: leeknowsai/paperclip-plugin-superpowers
Length of output: 2117
Declare read-only
GITHUB_TOKENpermissions.Add a top-level
permissionsblock beforejobsbecause this workflow lacks an explicit permission grant. Without it, repository or organization defaults can grant write access, even though this workflow only needs contents read access for checkout and reviewable repository code.Proposed fix
on: push: branches: [main] pull_request: branches: [main] +permissions: + contents: read + jobs:π€ Prompt for AI Agents
Source: Linters/SAST tools