From f539a44cfd6ce216946a9a8f318e5ed5158d0289 Mon Sep 17 00:00:00 2001 From: AlexYue Date: Wed, 18 Mar 2026 23:49:54 +0800 Subject: [PATCH] docs: add issue/PR templates and contributing guide (#63) * docs: add issue/PR templates and contributing guide - Add GitHub Issue forms: bug report, feature request, new site adapter - Add PR template with CI-aligned checklist (typecheck, test, validate) - Add CONTRIBUTING.md with adapter development workflow and testing guide * docs: simplify adapter request and fix contributor example * docs: trim contribution and issue templates --------- Co-authored-by: jackwener --- .github/ISSUE_TEMPLATE/bug_report.yml | 83 ++++++++++ .github/ISSUE_TEMPLATE/config.yml | 8 + .github/ISSUE_TEMPLATE/feature_request.yml | 42 +++++ .github/ISSUE_TEMPLATE/new_site_adapter.yml | 57 +++++++ .github/pull_request_template.md | 24 +++ CONTRIBUTING.md | 167 ++++++++++++++++++++ 6 files changed, 381 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/bug_report.yml create mode 100644 .github/ISSUE_TEMPLATE/config.yml create mode 100644 .github/ISSUE_TEMPLATE/feature_request.yml create mode 100644 .github/ISSUE_TEMPLATE/new_site_adapter.yml create mode 100644 .github/pull_request_template.md create mode 100644 CONTRIBUTING.md diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 0000000..68c86dd --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,83 @@ +name: "๐Ÿ› Bug Report" +description: Report a bug or unexpected behavior in OpenCLI +title: "[Bug]: " +labels: ["bug"] +body: + - type: markdown + attributes: + value: | + Thanks for taking the time to report a bug. A short reproduction and any error output are usually enough. + + - type: textarea + id: description + attributes: + label: Description + description: A clear and concise description of the bug. + placeholder: What happened? + validations: + required: true + + - type: textarea + id: steps + attributes: + label: Steps to Reproduce + description: How can we reproduce this behavior? + value: | + 1. Run `opencli ...` + 2. ... + 3. See error + validations: + required: true + + - type: textarea + id: expected + attributes: + label: Expected Behavior + description: What did you expect to happen? + validations: + required: true + + - type: input + id: version + attributes: + label: OpenCLI Version + description: "Run `opencli --version` to find out." + placeholder: "0.8.0" + validations: + required: true + + - type: dropdown + id: node-version + attributes: + label: Node.js Version + options: + - "20.x" + - "22.x" + - Other + validations: + required: true + + - type: dropdown + id: os + attributes: + label: Operating System + options: + - macOS + - Linux + - Windows + - Other + validations: + required: true + + - type: textarea + id: logs + attributes: + label: Logs / Screenshots + description: | + Paste any relevant error output. Run with `-v` for verbose logs: + ``` + opencli -v + ``` + render: shell + validations: + required: false diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..a8bc2c2 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,8 @@ +blank_issues_enabled: true +contact_links: + - name: ๐Ÿ“– Documentation + url: https://github.com/jackwener/opencli#readme + about: Check the README and docs before opening an issue. + - name: ๐Ÿงช Testing Guide + url: https://github.com/jackwener/opencli/blob/main/TESTING.md + about: How to run and write tests for OpenCLI. diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml new file mode 100644 index 0000000..082cd34 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -0,0 +1,42 @@ +name: "โœจ Feature Request" +description: Suggest a new feature or improvement +title: "[Feature]: " +labels: ["enhancement"] +body: + - type: markdown + attributes: + value: | + Have an idea to make OpenCLI better? We'd love to hear it! + + - type: textarea + id: description + attributes: + label: Feature Description + description: A clear and concise description of the feature you'd like. + validations: + required: true + + - type: textarea + id: use-case + attributes: + label: Use Case + description: What problem does this solve? Who benefits from this feature? + placeholder: "As a user, I want to ... so that ..." + validations: + required: true + + - type: textarea + id: proposed-solution + attributes: + label: Proposed Solution + description: If you have a specific implementation in mind, describe it here. + validations: + required: false + + - type: textarea + id: alternatives + attributes: + label: Alternatives Considered + description: Any alternative approaches you've thought about? + validations: + required: false diff --git a/.github/ISSUE_TEMPLATE/new_site_adapter.yml b/.github/ISSUE_TEMPLATE/new_site_adapter.yml new file mode 100644 index 0000000..aa5c4e6 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/new_site_adapter.yml @@ -0,0 +1,57 @@ +name: "๐ŸŒ New Site Adapter Request" +description: Request support for a new website +title: "[Site]: " +labels: ["new-adapter"] +body: + - type: markdown + attributes: + value: | + Want OpenCLI to support a new site? Tell us about it! + + - type: input + id: site-name + attributes: + label: Site Name + description: The name of the website. + placeholder: "e.g. Product Hunt" + validations: + required: true + + - type: input + id: site-url + attributes: + label: Site URL + description: The main URL of the website. + placeholder: "https://www.producthunt.com" + validations: + required: true + + - type: textarea + id: commands + attributes: + label: Desired Commands + description: What commands would you like? List them with a brief description. + value: | + - `hot` โ€” trending / popular items + - `search` โ€” search the site + validations: + required: true + + - type: textarea + id: api-examples + attributes: + label: Example Links or API Endpoints + description: Share any example page URLs or API endpoints if you have them (optional). + placeholder: | + Example page: https://www.producthunt.com/posts/example + GET https://api.producthunt.com/v2/posts?order=votes + Response: { "posts": [{ "name": "...", "tagline": "..." }] } + validations: + required: false + + - type: checkboxes + id: contribution + attributes: + label: Willing to Contribute? + options: + - label: I'm willing to submit a PR for this adapter diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 0000000..c4917c3 --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,24 @@ +## Description + + + +Related issue: + +## Type of Change + +- [ ] ๐Ÿ› Bug fix +- [ ] โœจ New feature +- [ ] ๐ŸŒ New site adapter +- [ ] ๐Ÿ“ Documentation +- [ ] โ™ป๏ธ Refactor +- [ ] ๐Ÿ”ง CI / build / tooling + +## Checklist + +- [ ] I ran the checks relevant to this PR +- [ ] I updated tests or docs if needed +- [ ] I included output or screenshots when useful + +## Screenshots / Output + + diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..c2d14e2 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,167 @@ +# Contributing to OpenCLI + +Thanks for your interest in contributing to OpenCLI. + +## Quick Start + +```bash +# 1. Fork & clone +git clone git@github.com:/opencli.git +cd opencli + +# 2. Install dependencies +npm install + +# 3. Build +npm run build + +# 4. Run a few checks +npx tsc --noEmit +npx vitest run src/ + +# 5. Link globally (optional, for testing `opencli` command) +npm link +``` + +## Adding a New Site Adapter + +This is the most common type of contribution. Start with YAML when possible, and use TypeScript only when you need browser-side logic or multi-step flows. + +### YAML Adapter (Recommended for data-fetching commands) + +Create a file like `src/clis//.yaml`: + +```yaml +site: mysite +name: trending +description: Trending posts on MySite +domain: www.mysite.com +strategy: public # public | cookie | header +browser: false # true if browser session is needed + +args: + limit: + type: int + default: 20 + description: Number of items + +pipeline: + - fetch: + url: https://api.mysite.com/trending + + - map: + rank: ${{ index + 1 }} + title: ${{ item.title }} + score: ${{ item.score }} + url: ${{ item.url }} + + - limit: ${{ args.limit }} + +columns: [rank, title, score, url] +``` + +See [`hackernews/top.yaml`](src/clis/hackernews/top.yaml) for a real example. + +### TypeScript Adapter (For complex browser interactions) + +Create a file like `src/clis//.ts`: + +```typescript +import { cli, Strategy } from '../../registry.js'; + +cli({ + site: 'mysite', + name: 'search', + description: 'Search MySite', + domain: 'www.mysite.com', + strategy: Strategy.COOKIE, + args: [ + { name: 'query', required: true, help: 'Search query' }, + { name: 'limit', type: 'int', default: 10, help: 'Max results' }, + ], + columns: ['title', 'url', 'date'], + + func: async (page, kwargs) => { + const { query, limit = 10 } = kwargs; + await page.goto('https://www.mysite.com'); + + const data = await page.evaluate(` + (async () => { + const res = await fetch('/api/search?q=${encodeURIComponent(query)}', { + credentials: 'include' + }); + return (await res.json()).results; + })() + `); + + return data.slice(0, Number(limit)).map((item: any) => ({ + title: item.title, + url: item.url, + date: item.created_at, + })); + }, +}); +``` + +Use `opencli explore ` to discover APIs and see [CLI-EXPLORER.md](./CLI-EXPLORER.md) if you need the full adapter workflow. + +### Validate Your Adapter + +```bash +# Validate YAML syntax and schema +opencli validate + +# Test your command +opencli --limit 3 -f json + +# Verbose mode for debugging +opencli -v +``` + +## Testing + +See [TESTING.md](./TESTING.md) for the full guide and exact test locations. + +```bash +npx vitest run src/ # Unit tests +npx vitest run tests/e2e/ # E2E tests +npx vitest run # All tests +``` + +## Code Style + +- **TypeScript strict mode** โ€” avoid `any` where possible. +- **ES Modules** โ€” use `.js` extensions in imports (TypeScript output). +- **Naming**: `kebab-case` for files, `camelCase` for variables/functions, `PascalCase` for types/classes. +- **No default exports** โ€” use named exports. + +## Commit Convention + +We use [Conventional Commits](https://www.conventionalcommits.org/): + +``` +feat(twitter): add thread command +fix(browser): handle CDP timeout gracefully +docs: update CONTRIBUTING.md +test(reddit): add e2e test for save command +chore: bump vitest to v4 +``` + +Common scopes: site name (`twitter`, `reddit`) or module name (`browser`, `pipeline`, `engine`). + +## Submitting a Pull Request + +1. Create a feature branch: `git checkout -b feat/mysite-trending` +2. Make your changes and add tests when relevant +3. Run the checks that apply: + ```bash + npx tsc --noEmit # Type check + npx vitest run src/ # Unit tests + opencli validate # YAML validation (if applicable) + ``` +4. Commit using conventional commit format +5. Push and open a PR + +## License + +By contributing, you agree that your contributions will be licensed under the [Apache-2.0 License](./LICENSE).