diff --git a/.github/workflows/pr-check.yml b/.github/workflows/pr-check.yml new file mode 100644 index 0000000..e027731 --- /dev/null +++ b/.github/workflows/pr-check.yml @@ -0,0 +1,148 @@ +name: PR Review + +on: + pull_request: + branches: [main, dev] + types: [opened, edited, synchronize, reopened] + pull_request_target: + branches: [main, dev] + types: [opened] + +permissions: + pull-requests: write + contents: read + +jobs: + # ── 1. Validate PR title follows Conventional Commits ───────────────────── + lint-pr-title: + name: Lint PR Title + runs-on: ubuntu-latest + steps: + - uses: amannn/action-semantic-pull-request@v5 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + types: | + feat + fix + docs + test + refactor + style + chore + ci + perf + requireScope: false + subjectPattern: ^(?![A-Z]).+$ + subjectPatternError: | + The PR title "{subject}" should start with a lowercase letter. + Example: "feat: add dark mode" not "feat: Add dark mode" + + # ── 2. Check PR description is not empty ────────────────────────────────── + check-pr-description: + name: Check PR Description + runs-on: ubuntu-latest + steps: + - name: Check description is not empty + uses: actions/github-script@v7 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const body = context.payload.pull_request.body; + if (!body || body.trim().length < 20) { + core.setFailed( + 'PR description is too short or empty. ' + + 'Please describe what this PR does and why. ' + + 'See CONTRIBUTING.md for guidelines.' + ); + } + + # ── 3. Auto-label PRs based on conventional commit prefix ───────────────── + auto-label: + name: Auto Label + runs-on: ubuntu-latest + steps: + - name: Apply label based on PR title prefix + uses: actions/github-script@v7 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const title = context.payload.pull_request.title || ''; + const pr = context.payload.pull_request.number; + const owner = context.repo.owner; + const repo = context.repo.repo; + + const labelMap = { + 'feat': 'enhancement', + 'fix': 'bug', + 'docs': 'documentation', + 'test': 'testing', + 'refactor': 'refactor', + 'style': 'style', + 'chore': 'chore', + 'ci': 'ci/cd', + 'perf': 'performance', + }; + + const match = title.match(/^(\w+)(?:\(.+\))?!?:/); + if (!match) return; + + const label = labelMap[match[1]]; + if (!label) return; + + // Create label if it doesn't exist, then apply it + try { + await github.rest.issues.getLabel({ owner, repo, name: label }); + } catch { + const colors = { + 'enhancement': '84b6eb', + 'bug': 'ee0701', + 'documentation':'0075ca', + 'testing': 'bfd4f2', + 'refactor': 'e4e669', + 'style': 'fef2c0', + 'chore': 'c2e0c6', + 'ci/cd': 'f9d0c4', + 'performance': 'cfd3d7', + }; + await github.rest.issues.createLabel({ + owner, repo, name: label, + color: colors[label] || 'ededed', + }); + } + + await github.rest.issues.addLabels({ + owner, repo, issue_number: pr, labels: [label], + }); + + # ── 4. Post a helpful checklist comment on first-time PR open ───────────── + welcome-comment: + name: Post Contribution Checklist + runs-on: ubuntu-latest + if: github.event.action == 'opened' + steps: + - name: Post checklist comment + uses: actions/github-script@v7 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const author = context.payload.pull_request.user.login; + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.payload.pull_request.number, + body: `Thanks for the PR, @${author}! 🎉 + + Before this gets reviewed, please make sure the following are checked: + + - [ ] Tests pass locally (\`npm test\`) + - [ ] Type check passes (\`npm run typecheck\`) + - [ ] Lint passes (\`npm run lint\`) + - [ ] New features include tests + - [ ] Documentation updated if needed + - [ ] PR targets the \`dev\` branch (not \`main\`) + + > See [CONTRIBUTING.md](https://github.com/night-slayer18/leetcode-cli/blob/dev/CONTRIBUTING.md) for full guidelines. + + The CI pipeline will also run build, test, lint, and typecheck automatically.` + }); diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..6076d70 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,202 @@ +# Contributing to leetcode-cli + +Thank you for taking the time to contribute! This guide will help you get started. + +--- + +## Table of Contents + +- [Getting Started](#getting-started) +- [Development Setup](#development-setup) +- [Making Changes](#making-changes) +- [Commit Messages](#commit-messages) +- [Pull Request Guidelines](#pull-request-guidelines) +- [Running Tests](#running-tests) +- [Reporting Issues](#reporting-issues) + +--- + +## Getting Started + +1. **Fork** the repository on GitHub. +2. **Clone** your fork locally: + ```bash + git clone https://github.com//leetcode-cli.git + cd leetcode-cli + ``` +3. Add the upstream remote so you can keep your fork in sync: + ```bash + git remote add upstream https://github.com/night-slayer18/leetcode-cli.git + ``` + +--- + +## Development Setup + +**Requirements**: Node.js ≥ 20 and npm. + +```bash +# Install dependencies +npm install + +# Build the project +npm run build + +# Run tests +npm test + +# Type check +npm run typecheck + +# Lint +npm run lint +``` + +For a live rebuild during development: +```bash +npm run dev +``` + +--- + +## Making Changes + +1. **Sync with upstream** before branching: + ```bash + git checkout dev + git pull upstream dev + ``` + +2. **Create a branch** from `dev` (not `main`): + ```bash + git checkout -b feat/my-feature + ``` + > All PRs should target the `dev` branch. `main` is release-only. + +3. Make your changes, then **verify everything passes**: + ```bash + npm run typecheck + npm run lint + npm run build + npm test + ``` + +4. **Push** your branch and open a PR against `dev`. + +--- + +## Commit Messages + +We follow the **[Conventional Commits](https://www.conventionalcommits.org/)** specification. This keeps the changelog clean and makes it easy to understand what changed and why. + +**Format:** +``` +(): + + +``` + +**Types:** + +| Type | When to use | +|------|-------------| +| `feat` | A new feature | +| `fix` | A bug fix | +| `docs` | Documentation changes only | +| `test` | Adding or updating tests | +| `refactor` | Code change that is neither a fix nor a feature | +| `style` | Formatting, whitespace (no logic change) | +| `chore` | Build process, tooling, dependency updates | +| `ci` | CI/CD workflow changes | +| `perf` | Performance improvements | + +**Examples:** +```bash +feat(tui): add dark mode toggle to config screen +fix(submit): handle null percentile from leetcode API +docs: update installation instructions for Windows +test(star-prompt): add coverage for 30-day reset window +chore: bump got to v14 +``` + +> **Note on signing commits**: We recommend signing commits with GPG (`git commit -s`) as a good practice, +> but it is **not required**. Please don't let that stop you from contributing. + +--- + +## Pull Request Guidelines + +### Title + +Your PR title must follow the same Conventional Commits format: +``` +feat: add random problem filter by topic tag +fix(login): handle expired session gracefully +``` + +An automated check will validate this and fail if the format is incorrect. + +### Description + +Please include in your PR description: +- **What** the change does +- **Why** it is needed (link to an issue if applicable) +- **How** to test it manually (if applicable) + +Empty PR descriptions are not accepted. + +### Checklist + +Before submitting, make sure: + +- [ ] Tests pass locally (`npm test`) +- [ ] Type check passes (`npm run typecheck`) +- [ ] Lint passes (`npm run lint`) +- [ ] New features include tests +- [ ] Documentation is updated if needed +- [ ] PR targets the `dev` branch (not `main`) + +### PR Size + +Keep PRs focused. A PR that does one thing well is much easier to review than one that does five. +If your change is large, consider breaking it into smaller PRs. + +--- + +## Running Tests + +```bash +# Run all tests +npm test + +# Run a specific test file +npx vitest run src/__tests__/commands/submit.test.ts + +# Watch mode during development +npm run test:watch +``` + +When adding a new feature, please add tests. When fixing a bug, add a test that would have caught it. + +--- + +## Reporting Issues + +When filing a bug report, please include: + +1. **CLI version** (`leetcode --version`) +2. **Operating system and version** +3. **Node.js version** (`node --version`) +4. **Steps to reproduce** the issue +5. **Expected** vs **actual** behaviour +6. Any **error output** from the terminal + +For feature requests, describe the use case and what problem it solves for you. + +--- + +## Questions? + +Feel free to open a [Discussion](https://github.com/night-slayer18/leetcode-cli/discussions) if you have questions that don't fit an issue. + +Thank you for contributing! ⭐