diff --git a/.gemini/skills/README.md b/.gemini/skills/README.md index 570ff03..27a62de 100644 --- a/.gemini/skills/README.md +++ b/.gemini/skills/README.md @@ -36,6 +36,33 @@ This folder contains reusable Agent Skills for GitHub Copilot / VS Code custom a - Purpose: Single-file spreadsheet operations workflow without LibreOffice. - Entry: `xlsx-single-file/SKILL.md` +--- + +## Release Pipeline Skills + +These four skills form a complete release pipeline and are designed to be used in sequence: + +``` +release-prep → pr-submitter → pr-reviewer → release-finalizer + (prepare) (push & PR) (respond to review) (merge & close issue) +``` + +- **release-prep** + - Purpose: Full release preparation — version sync across 7+ files, bilingual release notes creation, consistency check, and commit. + - Entry: `release-prep/SKILL.md` + +- **pr-submitter** + - Purpose: Shell-escape-safe PR submission — writes body to temp file, validates sections, pushes branch, creates PR via `gh pr create --body-file`. + - Entry: `pr-submitter/SKILL.md` + +- **pr-reviewer** + - Purpose: Fetch PR review comments, categorize feedback, implement fixes, commit and push, reply to reviewers. + - Entry: `pr-reviewer/SKILL.md` + +- **release-finalizer** + - Purpose: Merge release PR to main with proper commit message, auto-link and close related issues, post closing messages. + - Entry: `release-finalizer/SKILL.md` + ## Notes - Skill definitions follow the expected location pattern: diff --git a/.gemini/skills/pr-reviewer/SKILL.md b/.gemini/skills/pr-reviewer/SKILL.md new file mode 100644 index 0000000..6bb9af9 --- /dev/null +++ b/.gemini/skills/pr-reviewer/SKILL.md @@ -0,0 +1,180 @@ +--- +name: pr-reviewer +description: Fetches PR review comments, analyzes requested changes, implements fixes, commits and pushes the resolution. Use after a reviewer has left comments on an open PR to close the feedback loop efficiently. +--- + +# PR Reviewer + +## Overview + +This skill automates the response cycle for code review. When a reviewer leaves comments on a Pull Request, this skill fetches all pending feedback, categorizes issues by severity, implements fixes, and submits a follow-up commit with appropriate review response comments. + +## Prerequisites + +- An open PR exists with pending review comments +- The local branch matches the PR's head branch +- `gh` CLI is authenticated + +--- + +## Workflow + +### Step 1 — Fetch Review State + +Retrieve all review comments and overall review status: + +```bash +# Get overall review decisions +PAGER=cat GH_PAGER=cat gh pr view --json reviews,reviewDecision,headRefName \ + --jq '{decision: .reviewDecision, reviews: [.reviews[] | {author: .author.login, state: .state, body: .body}]}' + +# Get inline code comments (specific line comments) +PAGER=cat GH_PAGER=cat gh api repos/Fu-Jie/openwebui-extensions/pulls//comments \ + --jq '[.[] | {path: .path, line: .line, body: .body, author: .user.login, id: .id}]' + +# Get general issue comments +PAGER=cat GH_PAGER=cat gh issue view --comments --json comments \ + --jq '[.comments[] | {author: .author.login, body: .body}]' +``` + +Confirm the current local branch matches the PR head: +```bash +git branch --show-current +``` +If mismatched, checkout the correct branch first. + +### Step 2 — Categorize Review Feedback + +Group feedback into categories: + +| Category | Examples | Action | +|----------|---------|--------| +| **Code Bug** | Logic error, incorrect variable, broken condition | Fix code immediately | +| **Style / Formatting** | Indentation, naming convention, missing blank line | Fix code | +| **Documentation** | Missing i18n key, wrong version in README, typo | Fix docs | +| **Design Question** | Suggestion to restructure, alternative approach | Discuss with user before implementing | +| **Nitpick / Optional** | Minor style preferences reviewer marked as optional | Fix if quick; document if skipped | +| **Blocking** | Reviewer explicitly blocks merge | Must fix before proceeding | + +Present the full categorized list to the user and confirm the resolution plan. + +### Step 3 — Implement Fixes + +For each accepted fix: + +1. Read the affected file at the commented line for context: + ```bash + sed -n ',p' + ``` +2. Apply the fix using appropriate file edit tools +3. After editing, verify the specific area looks correct + +**For code changes that might affect behavior:** +- Check if tests exist: `ls tests/test_*.py` +- If tests exist, run them: `python -m pytest tests/ -v` + +**For documentation fixes:** +- If modifying README.md, check if `docs/` mirror needs the same fix +- Apply the same fix to both locations + +### Step 4 — Run Consistency Checks + +After all fixes are applied: + +```bash +# Version consistency (if any version files were touched) +python3 scripts/check_version_consistency.py + +# Quick syntax check for Python files +python3 -m py_compile plugins/{type}/{name}/{name}.py && echo "✅ Syntax OK" +``` + +### Step 5 — Stage and Commit + +Create a new commit (do NOT amend if the branch has already been pushed, to avoid force-push): + +```bash +git add -A +git status +``` + +Draft a Conventional Commits message for the fixup: + +Format: `fix(scope): address review feedback` + +Body should list what was fixed, referencing reviewer concerns: +``` +fix(github-copilot-sdk): address review feedback from @reviewer + +- Fix X per review comment on line Y of file Z +- Update README to clarify auth requirement +- Correct edge case in _parse_mcp_servers logic +``` + +```bash +git commit -m "" +``` + +### Step 6 — Push the Fix Commit + +```bash +git push origin $(git branch --show-current) +``` + +**Force-push policy:** +- Use `git push` (non-force) by default +- Only use `git push --force-with-lease` if: + 1. The user explicitly requests it, AND + 2. The only change is an amended commit squash (cosmetic, no logic change) + 3. Never use `--force` (without `--lease`) + +### Step 7 — Respond to Reviewers + +For each addressed review comment, post a reply: + +```bash +# Reply to inline comment +gh api repos/Fu-Jie/openwebui-extensions/pulls//comments//replies \ + -X POST -f body="Fixed in commit . " + +# General comment to summarize all fixes +gh issue comment --body "All review feedback addressed in commit : +- Fixed: +- Fixed: +Ready for re-review. 🙏" +``` + +### Step 8 — Re-Request Review (Optional) + +If the reviewer had submitted a `CHANGES_REQUESTED` review, request a new review after fixes: + +```bash +PAGER=cat GH_PAGER=cat gh api repos/Fu-Jie/openwebui-extensions/pulls//requested_reviewers \ + -X POST -f reviewers[]='' +``` + +--- + +## Decision Guide + +### When NOT to implement a suggestion immediately + +- **Design questions**: "Should this be a separate class?" — Present to user for decision +- **Optional nitpicks**: Reviewer marked as `nit:` — Ask user if they want to include it +- **Large refactors**: If fix would require changing >50 lines, propose a separate follow-up issue instead + +### When to ask the user before proceeding + +- Any fix involving behavioral changes to plugin logic +- Renaming Valve keys (breaking change — requires migration notes) +- Changes that affect the bilingual release notes already committed + +--- + +## Anti-Patterns to Avoid + +- ❌ Do NOT `git commit --amend` on a pushed commit without user approval for force-push +- ❌ Do NOT silently skip a reviewer's comment; always acknowledge it (implement or explain why not) +- ❌ Do NOT use `--force` (only `--force-with-lease` when absolutely necessary) +- ❌ Do NOT make unrelated changes in the fixup commit; keep scope focused on review feedback +- ❌ Do NOT respond to reviewer comments in Chinese if the PR language context is English diff --git a/.gemini/skills/pr-submitter/SKILL.md b/.gemini/skills/pr-submitter/SKILL.md new file mode 100644 index 0000000..c1f3d92 --- /dev/null +++ b/.gemini/skills/pr-submitter/SKILL.md @@ -0,0 +1,179 @@ +--- +name: pr-submitter +description: Submits a feature branch as a Pull Request with a validated, properly formatted bilingual PR body. Handles shell-escape-safe body writing via temp files. Use after release-prep has committed all changes. +--- + +# PR Submitter + +## Overview + +This skill handles the final step of pushing a feature branch and creating a validated Pull Request on GitHub. Its primary purpose is to avoid the shell-escaping pitfalls (backticks, special characters in `gh pr create --body`) by always writing the PR body to a **temp file** first. + +## Prerequisites + +- All changes are committed (use `release-prep` skill first) +- The `gh` CLI is authenticated (`gh auth status`) +- Current branch is NOT `main` or `master` + +--- + +## Workflow + +### Step 1 — Pre-Flight Checks + +Run these checks before any push: + +```bash +# 1. Confirm not on protected branch +git branch --show-current + +# 2. Verify there are commits to push +git log origin/$(git branch --show-current)..HEAD --oneline 2>/dev/null || echo "No remote tracking branch yet" + +# 3. Check gh CLI auth +gh auth status +``` + +If any check fails, stop and report clearly. + +### Step 2 — Collect PR Metadata + +Gather: +- **PR Title**: Must follow Conventional Commits format, English only (e.g., `feat(github-copilot-sdk): release v0.8.0 with conditional tool filtering`) +- **Target base branch**: Default is `main` +- **Plugin name + version** (to build body sections) +- **Key changes** (reuse from release-prep or the latest What's New section) + +### Step 3 — Build PR Body File (Shell-Escape-Safe) + +**Always write the body to a temp file.** Never embed multi-line markdown with special characters directly in a shell command. + +```bash +cat > /tmp/pr_body.md << 'HEREDOC' +## Summary + +Brief one-sentence description of what this PR accomplishes. + +## Changes + +### New Features +- Feature 1 description +- Feature 2 description + +### Bug Fixes +- Fix 1 description + +## Plugin Version +- `PluginName` bumped to `vX.X.X` + +## Documentation +- README.md / README_CN.md updated +- docs/ mirrors synced + +## Testing +- [ ] Tested locally in OpenWebUI +- [ ] i18n validated (all language keys present) +- [ ] Version consistency check passed (`python3 scripts/check_version_consistency.py`) + +--- + +## 变更摘要(中文) + +简要描述本次 PR 的改动内容。 + +### 新功能 +- 功能1描述 +- 功能2描述 + +### 问题修复 +- 修复1描述 +HEREDOC +``` + +**Critical rules for the body file:** +- Use `<< 'HEREDOC'` (quoted heredoc) to prevent variable expansion +- Keep all backticks literal — they are safe inside a heredoc +- Paths like `/api/v1/files/` are safe too since heredoc doesn't interpret them as commands + +### Step 4 — Validate PR Body + +Before submitting, verify the body file contains expected sections: + +```bash +# Check key sections exist +grep -q "## Summary" /tmp/pr_body.md && echo "✅ Summary" || echo "❌ Summary missing" +grep -q "## Changes" /tmp/pr_body.md && echo "✅ Changes" || echo "❌ Changes missing" +grep -q "## 变更摘要" /tmp/pr_body.md && echo "✅ CN Section" || echo "❌ CN Section missing" + +# Preview the body +cat /tmp/pr_body.md +``` + +Ask the user to confirm the body content before proceeding. + +### Step 5 — Push Branch + +```bash +git push -u origin $(git branch --show-current) +``` + +If push is rejected (non-fast-forward), report to user and ask whether to force-push. **Do NOT force-push without explicit confirmation.** + +### Step 6 — Create Pull Request + +```bash +gh pr create \ + --base main \ + --head $(git branch --show-current) \ + --title "" \ + --body-file /tmp/pr_body.md +``` + +Always use `--body-file`, never `--body` with inline markdown. + +### Step 7 — Verify PR Creation + +```bash +PAGER=cat GH_PAGER=cat gh pr view --json number,url,title,body --jq '{number: .number, url: .url, title: .title, body_preview: .body[:200]}' +``` + +Confirm: +- PR number and URL +- Title matches intended Conventional Commits format +- Body preview includes key sections (not truncated/corrupted) + +If the body appears corrupted (empty sections, missing backtick content), use edit: + +```bash +gh pr edit --body-file /tmp/pr_body.md +``` + +### Step 8 — Cleanup + +```bash +rm -f /tmp/pr_body.md +``` + +Report final PR URL to the user. + +--- + +## Shell-Escape Safety Rules + +| Risk | Safe Approach | +|------|--------------| +| Backticks in `--body` | Write to file, use `--body-file` | +| Paths like `/api/...` | Safe in heredoc; risky in inline `--body` | +| Newlines in `--body` | File-based only | +| `$variable` expansion | Use `<< 'HEREDOC'` (quoted) | +| Double quotes in body | Safe in heredoc file | + +--- + +## Anti-Patterns to Avoid + +- ❌ Never use `--body "..."` with multi-line content directly in shell command +- ❌ Never interpolate variables directly into heredoc without quoting the delimiter +- ❌ Never force-push (`--force`) without explicit user confirmation +- ❌ Never target `main` as the source branch (only as base) +- ❌ Never skip the body validation step — a PR with empty body is worse than a delayed PR diff --git a/.gemini/skills/release-finalizer/SKILL.md b/.gemini/skills/release-finalizer/SKILL.md new file mode 100644 index 0000000..f6e4f1f --- /dev/null +++ b/.gemini/skills/release-finalizer/SKILL.md @@ -0,0 +1,208 @@ +--- +name: release-finalizer +description: Merges a release PR, associates it with resolved issues, replies to issue reporters, and closes issues. Use after PR review is complete and ready for merge. Closes the release cycle. +--- + +# Release Finalizer + +## Overview + +This skill completes the final step of the release cycle: merging the release PR to `main`, replying to all related issues with solutions, and automatically closing them using GitHub's issue linking mechanism. + +## Prerequisites + +- The PR is in `OPEN` state and ready to merge +- All status checks have passed (CI green) +- All review feedback has been addressed +- The PR relates to one or more GitHub issues (either in PR description or through commits) + +--- + +## Workflow + +### Step 1 — Pre-Merge Verification + +Verify that the PR is ready: + +```bash +PAGER=cat GH_PAGER=cat gh pr view --json state,statusCheckRollup,reviewDecision +``` + +Checklist: +- ✅ `state` is `OPEN` +- ✅ `statusCheckRollup` all have `conclusion: SUCCESS` +- ✅ `reviewDecision` is `APPROVED` or empty (no blocking reviews) + +If any check fails, **do NOT merge**. Report the issue to the user. + +### Step 2 — Identify Related Issues + +Issues can be linked to a PR in multiple ways. Check the PR description and commit messages for keywords: + +```bash +PAGER=cat GH_PAGER=cat gh pr view --json body,commits +``` + +Look for patterns like: +- `Closes #XX`, `Fixes #XX`, `Resolves #XX` (in description or commit bodies) +- `#XX` mentioned as "related to" or "addresses" + +**Manual input**: If issue links are not in the PR, ask the user which issue(s) this PR resolves. + +Extract all issue numbers into a list: `[#48, #52, ...]` + +### Step 3 — Select Merge Strategy + +Offer the user three options: + +| Strategy | Git Behavior | Use Case | +|----------|-------------|----------| +| **Squash** | All commits squashed into one commit on main | Clean history, recommended for release PRs | +| **Rebase** | Linear history, no merge commit | Preserve commit granularity | +| **Merge** | Merge commit created | Preserve full PR context | + +**Recommendation for release PRs**: Use `--squash` to create a single clean commit. + +If user doesn't specify, default to `--squash`. + +### Step 4 — Prepare Merge Commit Message + +If using `--squash`, craft a single comprehensive commit message: + +**Format** (Conventional Commits + Github linking): +``` +type(scope): description + +- Bullet point 1 +- Bullet point 2 + +Closes #48 +Closes #52 +``` + +The `Closes #XX` keyword tells GitHub to automatically close those issues when the commit lands on `main`. + +Example: +``` +feat(pipes,filters): release Copilot SDK Pipe v0.8.0 and Files Filter v0.1.3 + +- Implement P1~P4 conditional tool filtering system +- Fix file publishing reliability across all storage backends +- Add strict file URL validation +- Update bilingual documentation + +Closes #48 +``` + +### Step 5 — Execute Merge + +```bash +gh pr merge \ + --squash \ + --delete-branch \ + -m "type(scope): description" \ + -b "- Bullet 1\n- Bullet 2\n\nCloses #48" +``` + +**Key flags:** +- `--squash`: Squash commits (recommended for releases) +- `--delete-branch`: Delete the feature branch after merge +- `-m`: Commit subject +- `-b`: Commit body (supports `\n` for newlines) + +Confirm the merge is successful; GitHub will automatically close related issues with `Closes #XX` keyword. + +### Step 6 — Verify Auto-Close + +GitHub automatically closes issues when a commit with `Closes #XX` lands on the default branch (`main`). + +To verify: +```bash +PAGER=cat GH_PAGER=cat gh issue view --json state +``` + +Should show `state: CLOSED`. + +### Step 7 — Post Closing Message (Optional but Recommended) + +For better UX, manually post a summary comment to **each issue** before it auto-closes (since auto-close happens silently): + +```bash +gh issue comment --body " +This has been fixed in PR #, which is now merged to main. + +**Solution Summary:** +- +- + +The fix will be available in the next plugin release. Thank you for reporting! ⭐ +" +``` + +### Step 8 — (Optional) Regenerate Release Notes + +If the merge revealed any final tweaks to release notes: + +```bash +# Re-export release notes from merged commit +git log --oneline -1 +``` + +If needed, create a follow-up PR with doc polish (do NOT force-push the merged commit). + +--- + +## Merge Strategy Decision Tree + +``` +Is this a patch/hotfix release? +├─ YES → Use --squash +└─ NO → Multi-feature release? + ├─ YES → Use --squash (cleaner history) + └─ NO → Preserve detail? + ├─ YES → Use --rebase + └─ NO → Use --merge (preserve PR context) +``` + +--- + +## Issue Auto-Close Keywords + +These keywords in commit/PR messages will auto-close issues when merged to `main`: + +- `Closes #XX` +- `Fixes #XX` +- `Resolves #XX` +- `close #XX` (case-insensitive) +- `fix #XX` +- `resolve #XX` + +**Important**: The keyword must be on the **final commit that lands on** `main`. For squash merges, it must be in the squash commit message body. + +--- + +## Anti-Patterns to Avoid + +- ❌ Do NOT merge if any status checks are PENDING or FAILED +- ❌ Do NOT merge if there are blocking reviews (reviewDecision: `CHANGES_REQUESTED`) +- ❌ Do NOT merge without verifying the Conventional Commits format in the merge message +- ❌ Do NOT merge without including `Closes #XX` keywords for all related issues +- ❌ Do NOT assume issues will auto-close silently — post a courtesy comment first +- ❌ Do NOT delete the branch if it might be needed for cherry-pick or hotfixes later + +--- + +## Troubleshooting + +### Issue did not auto-close after merge +- Verify the `Closes #XX` keyword is in the **final commit message** (use `git log` to check) +- Ensure the commit is on the `main` branch +- GitHub sometimes takes a few seconds to process; refresh the issue page + +### Multiple issues to close +- List all in separate `Closes #XX` lines in the commit body +- Each one will be independently auto-closed + +### Want to close issue without merge? +- Use `gh issue close ` manually +- Only recommended if the PR was manually reverted or deemed invalid diff --git a/.gemini/skills/release-prep/SKILL.md b/.gemini/skills/release-prep/SKILL.md new file mode 100644 index 0000000..a6e06f4 --- /dev/null +++ b/.gemini/skills/release-prep/SKILL.md @@ -0,0 +1,137 @@ +--- +name: release-prep +description: Orchestrates the full release preparation flow for a plugin — version sync across 7+ files, bilingual release notes creation, and commit message drafting. Use before submitting a PR. Does NOT push or create a PR; that is handled by pr-submitter. +--- + +# Release Prep + +## Overview + +This skill drives the complete pre-PR release pipeline. It enforces the repository rule that every release must synchronize the version number and changelog across **at least 7 locations** before a commit is created. + +## Scope + +This skill covers: +1. Version sync (delegates detail to `version-bumper` if needed) +2. Bilingual release notes file creation +3. 7-location consistency verification +4. Conventional Commits message drafting +5. `git add -A && git commit` execution + +It **stops before** `git push` or `gh pr create`. Use the `pr-submitter` skill for those steps. + +--- + +## Workflow + +### Step 1 — Collect Release Info + +Ask the user (or infer from current state) the following: +- **Plugin name** and **type** (actions / filters / pipes / tools) +- **New version number** (e.g., `0.8.0`) +- **Key changes** in English and Chinese (1-5 bullet points each) + +If a `What's New` section already exists in README.md, extract it as the source of truth. + +### Step 2 — Sync Version Across 7 Locations + +Verify AND update the version string in all of the following. Mark each as ✅ or ❌: + +| # | File | Location | +|---|------|----------| +| 1 | `plugins/{type}/{name}/{name}.py` | `version:` in docstring | +| 2 | `plugins/{type}/{name}/README.md` | `**Version:** x.x.x` metadata line | +| 3 | `plugins/{type}/{name}/README_CN.md` | `**Version:** x.x.x` metadata line | +| 4 | `docs/plugins/{type}/{name}.md` | `**Version:** x.x.x` metadata line | +| 5 | `docs/plugins/{type}/{name}.zh.md` | `**Version:** x.x.x` metadata line | +| 6 | `docs/plugins/{type}/index.md` | version badge for this plugin | +| 7 | `docs/plugins/{type}/index.zh.md` | version badge for this plugin | + +Additionally update the root-level **updated date badge** in: +- `README.md` — `![updated](https://img.shields.io/badge/YYYY--MM--DD-gray?style=flat)` +- `README_CN.md` — same badge format + +Use today's date (`YYYY-MM-DD`) for the badge. + +### Step 3 — Update What's New (All 4 Doc Files) + +The `What's New` / `最新更新` section must contain **only the most recent release's changes**. Previous entries should be removed from this section (they live in CHANGELOG or release notes files). + +Update these 4 files' `What's New` / `最新更新` block consistently: +- `plugins/{type}/{name}/README.md` +- `plugins/{type}/{name}/README_CN.md` +- `docs/plugins/{type}/{name}.md` +- `docs/plugins/{type}/{name}.zh.md` + +### Step 4 — Create Bilingual Release Notes Files + +Create two versioned release notes files: + +**Path**: `plugins/{type}/{name}/v{version}.md` +**Path**: `plugins/{type}/{name}/v{version}_CN.md` + +#### Required Sections + +Each file must include: +1. **Title**: `# v{version} Release Notes` (EN) / `# v{version} 版本发布说明` (CN) +2. **Overview**: One paragraph summarizing this release +3. **New Features** / **新功能**: Bulleted list of features +4. **Bug Fixes** / **问题修复**: Bulleted list of fixes +5. **Migration Notes** / **迁移说明**: Breaking changes or Valve key renames (omit section if none) +6. **Companion Plugins** / **配套插件** (optional): If a companion plugin was updated + +If a release notes file already exists for this version, update it rather than creating a new one. + +### Step 5 — Verify Consistency (Pre-Commit Check) + +Run the consistency check script: + +```bash +python3 scripts/check_version_consistency.py +``` + +If issues are found, fix them before proceeding. Do not commit with inconsistencies. + +### Step 6 — Draft Conventional Commits Message + +Generate the commit message following `commit-message.instructions.md` rules: +- **Language**: English ONLY +- **Format**: `type(scope): subject` + blank line + body bullets +- **Scope**: use plugin folder name (e.g., `github-copilot-sdk`) +- **Body**: 1-3 bullets summarizing key changes +- Explicitly mention "READMEs and docs synced" if version was bumped + +Present the full commit message to the user for review before executing. + +### Step 7 — Stage and Commit + +After user approval (or if user says "commit it"): + +```bash +git add -A +git commit -m "" +``` + +Confirm the commit hash and list the number of files changed. + +--- + +## Checklist (Auto-Verify Before Commit) + +- [ ] `version:` in `.py` docstring matches target version +- [ ] `**Version:**` in all 4 README/docs files matches +- [ ] Both `index.md` version badges updated +- [ ] Root `README.md` and `README_CN.md` date badges updated to today +- [ ] `What's New` / `最新更新` contains ONLY the latest release +- [ ] `v{version}.md` and `v{version}_CN.md` created or updated +- [ ] `python3 scripts/check_version_consistency.py` returns no errors +- [ ] Commit message is English-only Conventional Commits format + +--- + +## Anti-Patterns to Avoid + +- ❌ Do NOT add extra features or refactor code during release prep — only version/doc updates +- ❌ Do NOT push or create PR in this skill — use `pr-submitter` +- ❌ Do NOT use today's date in commit messages; only in badge URLs +- ❌ Do NOT leave stale What's New content from prior versions