Skip to content

fix: add CI, GitHub API auth, and better YAML parse errors - #1

Open
okokkoko4414 wants to merge 1 commit into
leeknowsai:mainfrom
okokkoko4414:fix/add-ci-and-auth
Open

fix: add CI, GitHub API auth, and better YAML parse errors#1
okokkoko4414 wants to merge 1 commit into
leeknowsai:mainfrom
okokkoko4414:fix/add-ci-and-auth

Conversation

@okokkoko4414

@okokkoko4414 okokkoko4414 commented Aug 3, 2026

Copy link
Copy Markdown

Summary

This PR addresses three structural risks identified during a repository health review:

Changes

  1. Add CI workflow (.github/workflows/ci.yml)

    • Typecheck job (pnpm typecheck)
    • Build job (pnpm build)
    • Runs on push to main and all PRs
    • Previously: zero CI — no automated verification that the plugin compiles
  2. GitHub API authentication (src/sync/github-sync.ts)

    • fetchTree() and fetchRawContent() now read GITHUB_TOKEN from the environment
    • Unauthenticated requests hit GitHub's rate limit (60 req/hr) quickly during sync; authenticated requests get 5,000 req/hr
    • Improved error messages now include the response body for debugging
  3. Better YAML parse error messages (src/sync/github-sync.ts)

    • parseSkillFile() now logs a warning with the skill ID when frontmatter is missing or the required name field is absent
    • Previously: silent null return with no indication which skill failed

Repository Health Review

Full review available in the paperclip issue thread. Key findings addressed:

  • 🔴 No CI → ✅ Added
  • 🟡 GitHub API calls unauthenticated → ✅ Added GITHUB_TOKEN support
  • 🟡 Silent parse failures → ✅ Added warning logs

Model Used

Reasonix (Claude-based), via Paperclip agent runtime.

Summary by CodeRabbit

  • Bug Fixes

    • Improved GitHub synchronization reliability with optional authentication and clearer error details.
    • Added warnings when synchronized skill files have missing or incomplete metadata.
  • Tests

    • Added automated validation for type checking and production builds on code changes.

- Add .github/workflows/ci.yml for typecheck + build verification
- Support GITHUB_TOKEN env var in GitHub API calls to avoid rate limits
- Improve parse error messages when SKILL.md frontmatter is invalid
@coderabbitai

coderabbitai Bot commented Aug 3, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The pull request adds GitHub Actions checks for type checking and builds. It also adds optional GitHub API authentication, detailed fetch errors, and warnings for invalid skill metadata.

Changes

CI validation

Layer / File(s) Summary
Typecheck and build workflow
.github/workflows/ci.yml
The workflow runs separate typecheck and build jobs on pushes and pull requests to main. Both jobs use Node.js 22, pnpm caching, and frozen-lockfile installation.

GitHub sync diagnostics

Layer / File(s) Summary
Authenticated requests and parsing diagnostics
src/sync/github-sync.ts
GitHub tree and raw-content requests use an optional GITHUB_TOKEN bearer token and a JSON Accept header. Fetch errors include truncated response bodies. Skill parsing logs warnings for invalid YAML frontmatter and missing name metadata.

Estimated code review effort: 3 (Moderate) | ~20 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the pull request's three main changes: CI, GitHub API authentication, and improved YAML parse errors.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/ci.yml:
- Around line 9-11: Add a top-level permissions block before jobs in the
workflow, granting only read access to repository contents via contents: read;
leave the existing typecheck job unchanged.
- Line 13: Update both actions/checkout@v4 steps in the build and typecheck jobs
to set persist-credentials to false, ensuring neither checkout retains Git
credentials for later workflow steps.

In `@src/sync/github-sync.ts`:
- Around line 121-122: Update fetchTree() and fetchRawContent() to use a shared
bounded response-body helper that reads at most 200 bytes from res.body, cancels
the stream reader, and returns the truncated text. Replace both direct
res.text() calls in the non-2xx error paths while preserving the existing
status-specific error messages.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 211e47ef-ad2e-4583-86de-86c3ce357ac3

📥 Commits

Reviewing files that changed from the base of the PR and between 77b0147 and 96257c2.

📒 Files selected for processing (2)
  • .github/workflows/ci.yml
  • src/sync/github-sync.ts

Comment thread .github/workflows/ci.yml
Comment on lines +9 to +11
jobs:
typecheck:
runs-on: ubuntu-latest

Copy link
Copy Markdown

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:

#!/bin/bash
set -euo pipefail

echo "== workflow files =="
git ls-files .github/workflows || true

echo "== ci.yml outline =="
wc -l .github/workflows/ci.yml 2>/dev/null || true
cat -n .github/workflows/ci.yml 2>/dev/null | sed -n '1,220p'

echo "== permissions in workflows =="
rg -n '^\s*permissions:|^\s*pull_request:|uses:|run:|chmod|git (push|commit|create)' .github/workflows || true

echo "== repo default permissions references =="
rg -n 'GITHUB_TOKEN|contents:|pull_request_target|pull_request:' -S .github/workflows . 2>/dev/null | head -200 || true

Repository: leeknowsai/paperclip-plugin-superpowers

Length of output: 2117


Declare read-only GITHUB_TOKEN permissions.

Add a top-level permissions block before jobs because 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
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/ci.yml around lines 9 - 11, Add a top-level permissions
block before jobs in the workflow, granting only read access to repository
contents via contents: read; leave the existing typecheck job unchanged.

Source: Linters/SAST tools

Comment thread .github/workflows/ci.yml
typecheck:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

Copy link
Copy Markdown

Choose a reason for hiding this comment

The 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 || true

Repository: leeknowsai/paperclip-plugin-superpowers

Length of output: 2433


🌐 Web query:

actions/checkout v4 README persist-credentials default true

💡 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:

GitHub Actions GITHUB_TOKEN environment variable persist-credentials local git config

💡 Result:

In GitHub Actions, the persist-credentials input for the actions/checkout action controls whether the repository's authentication token (typically GITHUB_TOKEN) is configured for use by local git commands [1][2]. When persist-credentials is set to true (the default), actions/checkout configures the authentication credentials to allow subsequent steps in the job to run authenticated git commands like git fetch or git push without needing to manually re-authenticate [1][3]. Key details regarding this behavior include: 1. Credential Location: In older versions of actions/checkout (v5 and earlier), these credentials were stored directly in the local .git/config file [4][5]. Starting with actions/checkout v6, the action was updated to store these credentials in a separate file located in $RUNNER_TEMP instead of directly modifying .git/config, which improves security [3][5][6]. 2. Purpose: This persistence is what allows scripts within your workflow to execute authenticated git operations seamlessly using the environment's existing identity [1][3]. 3. Disabling Persistence: If your workflow does not require running authenticated git commands, or if you want to prevent the credentials from being available to subsequent steps, you can set persist-credentials: false in your workflow step [1][7][4]. 4. Security Considerations: Because these credentials allow authenticated git operations, they are sensitive. Historically, concerns were raised that persisting them in .git/config could lead to accidental leakage (e.g., if the workspace was uploaded as an artifact) [4]. While v6+ mitigates this by moving the storage location, security best practices still recommend setting persist-credentials: false if the functionality is not explicitly required, as well as applying the principle of least privilege to the GITHUB_TOKEN permissions [8][9][4]. Note that this configuration can also cause conflicts if you are using tools like gh auth setup-git to configure different credentials, as the existing actions/checkout configuration may take precedence [7].

Citations:


🌐 Web query:

actions/checkout github app token persist-credentials local git config v4

💡 Result:

In actions/checkout@v4, the persist-credentials input controls whether the authentication token (or SSH key) used to fetch the repository is configured in the local Git configuration [1][2]. Key details regarding this setting include: - Default Behavior: The input defaults to true [2][3]. When enabled, the action configures the Git credential (typically the GITHUB_TOKEN or a provided PAT/SSH key) into the local repository's .git/config file [2][4]. This allows subsequent steps in the same workflow job to perform authenticated Git operations (e.g., git push, git fetch) without needing to explicitly provide credentials again [1][5]. - Security Implications: Because the credentials are written to the .git/config file, they may be exposed if the workspace (including the .git directory) is handled by other processes or included in artifacts that are uploaded or shared [4]. - Opting Out: You can set persist-credentials: false to prevent the action from writing these credentials to the local Git configuration [1][3]. This is recommended as a security best practice if downstream steps do not require authenticated Git access, as it reduces the attack surface by ensuring no long-lived credentials remain in the environment's Git config [4]. - Cleanup: In actions/checkout@v4, the action includes a post-job step designed to remove these persisted credentials from the Git configuration after the job completes [1][2]. For environments requiring higher security or where credentials must not be stored on disk, persist-credentials: false is the standard configuration to ensure the runner environment remains isolated from the repository's access tokens [4][6].

Citations:


Disable checkout credential persistence.

Set persist-credentials: false on both checkout steps. actions/checkout@v4 persists the Git credentials by default, and this workflow does not need authenticated Git commands later.

Proposed fix
-      - uses: actions/checkout@v4
+      - uses: actions/checkout@v4
+        with:
+          persist-credentials: false

The same change applies to the checkout step in the build job and the checkout step in the typecheck job.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- uses: actions/checkout@v4
- uses: actions/checkout@v4
with:
persist-credentials: false
🧰 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 Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/ci.yml at line 13, Update both actions/checkout@v4 steps
in the build and typecheck jobs to set persist-credentials to false, ensuring
neither checkout retains Git credentials for later workflow steps.

Source: Linters/SAST tools

Comment thread src/sync/github-sync.ts
Comment on lines +121 to +122
const detail = await res.text().catch(() => "");
throw new Error(`GitHub tree API returned ${res.status}: ${detail.slice(0, 200)}`);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The 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");
EOF

Repository: 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.ts

Repository: leeknowsai/paperclip-plugin-superpowers

Length of output: 5916


Bound the error-body read before truncating it.

fetchTree() and fetchRawContent() call res.text() before using only the first 200 characters of the body. Use a bounded helper that reads at most 200 bytes from res.body, cancels the stream reader, and uses it for both non-2xx body reads.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/sync/github-sync.ts` around lines 121 - 122, Update fetchTree() and
fetchRawContent() to use a shared bounded response-body helper that reads at
most 200 bytes from res.body, cancels the stream reader, and returns the
truncated text. Replace both direct res.text() calls in the non-2xx error paths
while preserving the existing status-specific error messages.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant