1k-create-pr

安装量: 42
排名: #17378

安装

npx skills add https://github.com/onekeyhq/app-monorepo --skill 1k-create-pr
Create OneKey App PR
Automates the complete PR creation workflow for OneKey app-monorepo changes.
Quick Reference
Step
Action
Commands
1
Check status
git status
,
git branch --show-current
2
Create branch (if on x)
git checkout -b
3
Lint fix
yarn lint --fix
4
Stage & commit
git add .
,
git commit -m "type: description"
5
Push to remote
git push -u origin
6
Extract context
Analyze conversation for intent, decisions, risks
7
Create PR
gh pr create --base x --title "..." --body "..."
8
Enable auto-merge
gh pr merge --auto --squash
Workflow
1. Check Current Branch Status
git
status
git
branch --show-current
2. Branch Handling
If on
x
branch:
Analyze current changes (staged and unstaged)
Generate descriptive branch name based on changes:
feat/
- new features
fix/
- bug fixes
refactor/
- refactoring
chore/
- maintenance tasks
Create and switch:
git checkout -b
If already on feature branch:
Skip branch creation
3. Run Lint Fix
yarn
lint
--fix
Fix any remaining lint errors before committing.
4. Stage and Commit Changes
git
add
.
git
commit
-m
": "
Commit format:
Follow conventional commits
Do NOT add Claude signatures or Co-Authored-By
5. Push to Remote
git
push
-u
origin
<
branch-name
>
6. Extract Context and Intent (CRITICAL)
Before creating the PR, analyze the full conversation history to extract:
Intent
Why were these changes made? What problem was being solved?
Root Cause
If this is a bug fix, what was the root cause?
Design Decisions
What approaches were considered? Why was this approach chosen?
Trade-offs
Any compromises or known limitations?
Risk Areas
Which parts of the change are riskiest or most complex?
Platform Impact
Which platforms are affected (desktop/mobile/web/extension)?
Related Issues
Any OK-{number} issue IDs mentioned in conversation Context extraction guidelines: User's original request - What did the user ask for? Quote key phrases if helpful. Problem diagnosis - How was the problem identified and understood? Implementation rationale - Why was this specific approach taken over alternatives? Constraints discussed - Any constraints or requirements the user mentioned. Edge cases considered - Any edge cases discussed during development. Security considerations - Any security implications discussed. Performance considerations - Any performance trade-offs discussed. 7. Create Pull Request with Context gh pr create --base x --title "" --body "<description>" Issue ID handling: Extract OK-{number} from commit summary/description and conversation history Append to PR title: fix: description(OK-49185) No space before opening parenthesis PR Body Template: The PR body MUST use this template. Omit sections that don't apply (don't write "N/A").</dd> </dl> </dd> </dl> </dd> </dl> </dd> </dl> </dd> </dl> </dd> </dl> </dd> </dl> <h2 id="_1"></h2> <p>Summary <1-3 bullet points describing WHAT changed></p> <h2 id="_2"></h2> <p>Intent & Context < WHY these changes were made. What problem was being solved? What was the user's original request or the bug report that triggered this work?</p> <blockquote></blockquote> <h2 id="_3"></h2> <p>Root Cause < For bug fixes: What was the root cause? How was it diagnosed?</p> <blockquote></blockquote> <h2 id="_4"></h2> <p>Design Decisions < Key decisions made during implementation and WHY. Alternatives considered and reasons for the chosen approach.</p> <blockquote></blockquote> <h2 id="_5"></h2> <p>Changes Detail < Brief description of each significant file change and its purpose</p> <blockquote></blockquote> <h2 id="_6"></h2> <h2 id="risk-assessment">Risk Assessment</h2> <dl> <dt>**</dt> <dt>Risk Level</dt> <dt>**</dt> <dd> <h2 id="low-medium-high">Low / Medium / High</h2> <dl> <dt>**</dt> <dt>Affected Platforms</dt> <dt>**</dt> <dd> <h2 id="extension-mobile-desktop-web">Extension / Mobile / Desktop / Web</h2> ** Risk Areas ** : < Which parts of the change are riskiest?<blockquote></blockquote> </dd> </dl> </dd> </dl> <h2 id="_7"></h2> <h2 id="test-plan">Test plan</h2> <dl> <dt>[ ]</dt> <dt><</dt> <dt>Testing</dt> <dt>steps</dt> <dt>to</dt> <dt>verify</dt> <dt>the</dt> <dt>changes</dt> <dt>></dt> <dt>8. Enable Auto-Merge</dt> <dt>gh</dt> <dt>pr</dt> <dt>update-branch</dt> <dt><</dt> <dt>PR_NUMBER</dt> <dt>></dt> <dt>gh</dt> <dt>pr</dt> <dt>merge</dt> <dt><</dt> <dt>PR_NUMBER</dt> <dt>></dt> <dt>--auto</dt> <dt>--squash</dt> <dt>9. Return PR URL</dt> <dt>Display PR URL to user and open in browser:</dt> <dt>open</dt> <dt><</dt> <dt>PR_URL</dt> <dt>></dt> <dt>Important Notes</dt> <dt>Always target</dt> <dt>x</dt> <dt>as base branch</dt> <dt>Use conventional commit format:</dt> <dt>type: description</dt> <dt>Extract and append issue IDs (OK-{number}) to PR title</dt> <dt>Context extraction is mandatory</dt> <dd> <dl> <dt>The PR description MUST reflect the conversation context. Do NOT create generic descriptions. The code review AI relies on this context to understand the intent behind changes.</dt> <dt>All PR content MUST be in English</dt> <dd>title, body (summary, changes, test plan), branch name, and commit messages. Never use Chinese or other languages.</dd> </dl> </dd> </dl> </article> <a href="/" class="back-link">← <span data-i18n="detail.backToLeaderboard">返回排行榜</span></a> </div> <aside class="sidebar"> <section class="related-skills" id="relatedSkillsSection"> <h2 class="related-title" data-i18n="detail.relatedSkills">相关 Skills</h2> <div class="related-list" id="relatedSkillsList"> <div class="skeleton-card"></div> <div class="skeleton-card"></div> <div class="skeleton-card"></div> </div> </section> </aside> </div> </div> <script src="https://unpkg.com/i18next@23.11.5/i18next.min.js" defer></script> <script src="https://unpkg.com/i18next-browser-languagedetector@7.2.1/i18nextBrowserLanguageDetector.min.js" defer></script> <script defer> // Language resources - same pattern as index page const resources = { 'zh-CN': null, 'en': null, 'ja': null, 'ko': null, 'zh-TW': null, 'es': null, 'fr': null }; // Load language files (only current + fallback for performance) async function loadLanguageResources() { const savedLang = localStorage.getItem('i18nextLng') || 'en'; const langsToLoad = new Set([savedLang, 'en']); // current + fallback await Promise.all([...langsToLoad].map(async (lang) => { try { const response = await fetch(`/locales/${lang}.json`); if (response.ok) { resources[lang] = { translation: await response.json() }; } } catch (error) { console.warn(`Failed to load ${lang} language file:`, error); } })); } // Load a single language on demand (for language switching) async function loadLanguage(lang) { if (resources[lang]) return; try { const response = await fetch(`/locales/${lang}.json`); if (response.ok) { resources[lang] = { translation: await response.json() }; i18next.addResourceBundle(lang, 'translation', resources[lang].translation); } } catch (error) { console.warn(`Failed to load ${lang} language file:`, error); } } // Initialize i18next async function initI18n() { try { await loadLanguageResources(); // Filter out null values from resources const validResources = {}; for (const [lang, data] of Object.entries(resources)) { if (data !== null) { validResources[lang] = data; } } console.log('Loaded languages:', Object.keys(validResources)); console.log('zh-CN resource:', validResources['zh-CN']); console.log('detail.home in resource:', validResources['zh-CN']?.translation?.detail?.home); // 检查是否有保存的语言偏好 const savedLang = localStorage.getItem('i18nextLng'); // 如果没有保存的语言偏好,默认使用英文 const defaultLang = savedLang && ['zh-CN', 'en', 'ja', 'ko', 'zh-TW', 'es', 'fr'].includes(savedLang) ? savedLang : 'en'; await i18next .use(i18nextBrowserLanguageDetector) .init({ lng: defaultLang, // 强制设置初始语言 fallbackLng: 'en', supportedLngs: ['zh-CN', 'en', 'ja', 'ko', 'zh-TW', 'es', 'fr'], resources: validResources, detection: { order: ['localStorage'], // 只使用 localStorage,不检测浏览器语言 caches: ['localStorage'], lookupLocalStorage: 'i18nextLng' }, interpolation: { escapeValue: false } }); console.log('i18next initialized, language:', i18next.language); console.log('Test translation:', i18next.t('detail.home')); // Set initial language in selector const langSwitcher = document.getElementById('langSwitcher'); langSwitcher.value = i18next.language; // Update page language updatePageLanguage(); // Language switch event langSwitcher.addEventListener('change', async (e) => { await loadLanguage(e.target.value); // load on demand i18next.changeLanguage(e.target.value).then(() => { updatePageLanguage(); localStorage.setItem('i18nextLng', e.target.value); }); }); } catch (error) { console.error('i18next init failed:', error); } } // Translation helper function t(key, options = {}) { return i18next.t(key, options); } // Update all translatable elements function updatePageLanguage() { // Update HTML lang attribute document.documentElement.lang = i18next.language; // Update elements with data-i18n attribute document.querySelectorAll('[data-i18n]').forEach(el => { const key = el.getAttribute('data-i18n'); el.textContent = t(key); }); } // Copy command function function copyCommand() { const command = document.getElementById('installCommand').textContent; const btn = document.getElementById('copyBtn'); navigator.clipboard.writeText(command).then(() => { btn.textContent = t('copied'); btn.classList.add('copied'); setTimeout(() => { btn.textContent = t('copy'); btn.classList.remove('copied'); }, 2000); }).catch(() => { // Fallback for non-HTTPS const textArea = document.createElement('textarea'); textArea.value = command; textArea.style.position = 'fixed'; textArea.style.left = '-9999px'; document.body.appendChild(textArea); textArea.select(); document.execCommand('copy'); document.body.removeChild(textArea); btn.textContent = t('copied'); btn.classList.add('copied'); setTimeout(() => { btn.textContent = t('copy'); btn.classList.remove('copied'); }, 2000); }); } // Initialize document.getElementById('copyBtn').addEventListener('click', copyCommand); initI18n(); // 异步加载相关 Skills async function loadRelatedSkills() { const owner = 'onekeyhq'; const skillName = '1k-create-pr'; const currentLang = 'en'; const listContainer = document.getElementById('relatedSkillsList'); const section = document.getElementById('relatedSkillsSection'); try { const response = await fetch(`/api/related-skills/${encodeURIComponent(owner)}/${encodeURIComponent(skillName)}?limit=6`); if (!response.ok) { throw new Error('Failed to load'); } const data = await response.json(); const relatedSkills = data.related_skills || []; if (relatedSkills.length === 0) { // 没有相关推荐时隐藏整个区域 section.style.display = 'none'; return; } // 渲染相关 Skills listContainer.innerHTML = relatedSkills.map(skill => { const desc = skill.description || ''; const truncatedDesc = desc.length > 60 ? desc.substring(0, 60) + '...' : desc; return ` <a href="${currentLang === 'en' ? '' : '/' + currentLang}/skill/${skill.owner}/${skill.repo}/${skill.skill_name}" class="related-card"> <div class="related-name">${escapeHtml(skill.skill_name)}</div> <div class="related-meta"> <span class="related-owner">${escapeHtml(skill.owner)}</span> <span class="related-installs">${skill.installs}</span> </div> <div class="related-desc">${escapeHtml(truncatedDesc)}</div> </a> `; }).join(''); } catch (error) { console.error('Failed to load related skills:', error); // 加载失败时显示提示或隐藏 listContainer.innerHTML = '<div class="related-empty">暂无相关推荐</div>'; } } // HTML 转义 function escapeHtml(text) { const div = document.createElement('div'); div.textContent = text; return div.innerHTML; } // 页面加载完成后异步加载相关 Skills if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', loadRelatedSkills); } else { loadRelatedSkills(); } </script> </body> </html>