Skip to content

Commit 2d80ed8

Browse files
author
Sameeksha Katiyar
committed
merge: sync tracking test configurations with upstream main updates
2 parents 480b1d6 + 6ede310 commit 2d80ed8

146 files changed

Lines changed: 16445 additions & 2175 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitattributes

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
* text=auto eol=lf

.github/scripts/issue-management/claim-handler.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,10 @@ async function handleClaim({ github, context }) {
3030

3131
const issueAuthor = context.payload.issue.user.login;
3232

33-
const isAuthorJhasourav07 = issueAuthor.toLowerCase() === 'jhasourav07';
33+
const MAINTAINERS = ['jhasourav07', 'aamod007', 'souravjhahind'];
34+
const isOpenedByMaintainer = MAINTAINERS.includes(issueAuthor.toLowerCase());
3435

35-
if (!isAuthorJhasourav07 && commenter.toLowerCase() !== issueAuthor.toLowerCase()) {
36+
if (!isOpenedByMaintainer && commenter.toLowerCase() !== issueAuthor.toLowerCase()) {
3637
await github.rest.issues.createComment({
3738
owner,
3839
repo,
@@ -89,7 +90,7 @@ async function handleClaim({ github, context }) {
8990
owner,
9091
repo,
9192
issue_number: issueNumber,
92-
body: `✅ Successfully assigned issue to @${commenter}\n\n> 💡 Please read [CONTRIBUTING.md](../blob/main/CONTRIBUTING.md) if you haven't already. Good luck! 🚀`,
93+
body: `🎉 **Assigned!** Welcome to the project, @${commenter}.\n\n⏳ **Reminder:** You have **2 days** to submit a Pull Request. After 2 days of inactivity, you will be automatically unassigned to give others a chance (as per our GSSoC anti-hoarding policy).\n\n> 💡 Please read [CONTRIBUTING.md](../blob/main/CONTRIBUTING.md) if you haven't already.\n\nHappy coding! 🚀`,
9394
});
9495
}
9596

.github/scripts/issue-management/stale-assignment.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
async function handleStaleAssignments({ github, context, core }) {
22
const { owner, repo } = context.repo;
3-
const THREE_DAYS_MS = 3 * 24 * 60 * 60 * 1000;
3+
const TWO_DAYS_MS = 2 * 24 * 60 * 60 * 1000;
44
const now = new Date();
55

66
console.log(`Starting stale assignment check for ${owner}/${repo}`);
@@ -27,7 +27,7 @@ async function handleStaleAssignments({ github, context, core }) {
2727
const updatedAt = new Date(issue.updated_at);
2828
const timeSinceUpdate = now.getTime() - updatedAt.getTime();
2929

30-
if (timeSinceUpdate > THREE_DAYS_MS) {
30+
if (timeSinceUpdate > TWO_DAYS_MS) {
3131
console.log(
3232
`Issue #${issue.number} has been inactive since ${issue.updated_at}. Removing assignees.`
3333
);

.github/workflows/assign-request-reminder.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ jobs:
4242
contains(github.event.comment.body, 'can i be assigned') ||
4343
contains(github.event.comment.body, 'assign me to this') ||
4444
contains(github.event.comment.body, 'assign me this') ||
45-
contains(github.event.comment.body, 'i will work on this') ||
45+
contains(github.event.comment.body, 'work on this') ||
4646
contains(github.event.comment.body, 'i''ll work on this') ||
4747
contains(github.event.comment.body, 'ill work on this') ||
4848
contains(github.event.comment.body, 'i can work on this') ||

.github/workflows/conflict-notifier.yml

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,12 @@ name: Merge Conflict Notifier
22

33
on:
44
schedule:
5-
- cron: '0 * * * *'
5+
- cron: '*/30 * * * *' # Hourly/half-hourly fallback
6+
push:
7+
branches:
8+
- main
9+
pull_request_target:
10+
types: [opened, synchronize, reopened, edited]
611
workflow_dispatch:
712

813
permissions:
@@ -76,20 +81,33 @@ jobs:
7681
});
7782
}
7883
79-
// Check if we've already posted a conflict comment to avoid spam
84+
// Check existing comments to enforce a 2-hour notification gap
8085
const { data: comments } = await github.rest.issues.listComments({
8186
owner: context.repo.owner,
8287
repo: context.repo.repo,
8388
issue_number: pr.number,
8489
per_page: 100,
8590
});
8691
87-
const alreadyCommented = comments.some(c =>
92+
const conflictComments = comments.filter(c =>
8893
c.user?.login === 'github-actions[bot]' &&
8994
c.body?.includes('merge conflicts with the main branch')
9095
);
9196
92-
if (!alreadyCommented) {
97+
let shouldComment = false;
98+
if (conflictComments.length === 0) {
99+
shouldComment = true;
100+
} else {
101+
const lastComment = conflictComments[conflictComments.length - 1];
102+
const lastCommentTime = new Date(lastComment.created_at).getTime();
103+
const nowTime = new Date().getTime();
104+
const TWO_HOURS_MS = 2 * 60 * 60 * 1000;
105+
if (nowTime - lastCommentTime >= TWO_HOURS_MS) {
106+
shouldComment = true;
107+
}
108+
}
109+
110+
if (shouldComment) {
93111
await github.rest.issues.createComment({
94112
owner: context.repo.owner,
95113
repo: context.repo.repo,

.gitignore

Lines changed: 42 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,42 @@
1-
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2-
3-
# dependencies
4-
/node_modules
5-
/.pnp
6-
.pnp.*
7-
.yarn/*
8-
!.yarn/patches
9-
!.yarn/plugins
10-
!.yarn/releases
11-
!.yarn/versions
12-
13-
# testing
14-
/coverage
15-
16-
# next.js
17-
/.next/
18-
/out/
19-
20-
# production
21-
/build
22-
23-
# misc
24-
.DS_Store
25-
*.pem
26-
27-
# debug
28-
npm-debug.log*
29-
yarn-debug.log*
30-
yarn-error.log*
31-
.pnpm-debug.log*
32-
33-
# env files — ignore all local secrets but commit the example template
34-
.env*
35-
!.env.local.example
36-
37-
# vercel
38-
.vercel
39-
40-
# typescript
41-
*.tsbuildinfo
42-
next-env.d.ts
1+
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2+
3+
# dependencies
4+
/node_modules
5+
/.pnp
6+
.pnp.*
7+
.yarn/*
8+
!.yarn/patches
9+
!.yarn/plugins
10+
!.yarn/releases
11+
!.yarn/versions
12+
13+
# testing
14+
/coverage
15+
16+
# next.js
17+
/.next/
18+
/out/
19+
20+
# production
21+
/build
22+
23+
# misc
24+
.DS_Store
25+
*.pem
26+
27+
# debug
28+
npm-debug.log*
29+
yarn-debug.log*
30+
yarn-error.log*
31+
.pnpm-debug.log*
32+
33+
# env files — ignore all local secrets but commit the example template
34+
.env*
35+
!.env.local.example
36+
.env.local
37+
# vercel
38+
.vercel
39+
40+
# typescript
41+
*.tsbuildinfo
42+
next-env.d.ts

CONTRIBUTING.md

Lines changed: 107 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
- [The Standard We Hold](#-the-standard-we-hold)
1111
- [Local Setup](#-local-setup)
12+
- [Testing Your Changes](#-testing-your-changes)
1213
- [What to Contribute](#-what-to-contribute)
1314
- [Automated Issue Management & Claiming](#-automated-issue-management--claiming)
1415
- [Branch & Commit Conventions](#-branch--commit-conventions)
@@ -88,6 +89,110 @@ http://localhost:3000/api/streak?user=YOUR_GITHUB_USERNAME
8889
8990
---
9091

92+
## 🧪 Testing Your Changes
93+
94+
This section covers everything you need to verify your changes work correctly **before opening a PR**. There are two layers of testing: visual browser preview and the automated test suite.
95+
96+
### 1. Visual Browser Preview
97+
98+
With your dev server running (`npm run dev`), open your browser and visit these URLs to preview the SVG output directly:
99+
100+
**Standard badge — valid username:**
101+
102+
```
103+
http://localhost:3000/api/streak?user=YOUR_GITHUB_USERNAME
104+
```
105+
106+
**Monthly view:**
107+
108+
```
109+
http://localhost:3000/api/streak?user=YOUR_GITHUB_USERNAME&view=monthly
110+
```
111+
112+
**Custom theme — test your color changes:**
113+
114+
```
115+
http://localhost:3000/api/streak?user=YOUR_GITHUB_USERNAME&theme=YOUR_THEME_NAME
116+
```
117+
118+
**Invalid username — must render a styled SVG error card, not raw JSON:**
119+
120+
```
121+
http://localhost:3000/api/streak?user=vivek%20Sangani
122+
```
123+
124+
**Non-existent username — must render the ghost-city not-found badge:**
125+
126+
```
127+
http://localhost:3000/api/streak?user=xyzabc999notreallll
128+
```
129+
130+
> **⚠️ Browser XML error warning:** If your browser shows an `EntityRef: expecting ';'` error instead of rendering the SVG, it means an unescaped `&` character exists somewhere in the SVG output. All `&` characters inside SVG `<style>` blocks (e.g. in Google Fonts `@import` URLs) must be written as `&amp;`. Check `lib/svg/generator.ts` for any raw `&` in template literals.
131+
132+
> **💡 Tip:** For a cleaner SVG preview, open the URL in **Firefox** — it renders SVG directly in the browser with no wrapper page. Chrome wraps it in an XML viewer which can show false parse warnings.
133+
134+
### 2. Running the Vitest Test Suite
135+
136+
CommitPulse uses **Vitest** for unit and integration tests. Run the full test suite with:
137+
138+
```bash
139+
npm run test
140+
```
141+
142+
To run tests in watch mode while you develop (reruns on every file save):
143+
144+
```bash
145+
npm run test -- --watch
146+
```
147+
148+
To run only a specific test file:
149+
150+
```bash
151+
npm run test -- lib/calculate.test.ts
152+
```
153+
154+
**What a passing run looks like:**
155+
156+
```
157+
✓ lib/calculate.test.ts (12 tests)
158+
✓ lib/svg/generator.test.ts (8 tests)
159+
✓ app/api/streak/route.test.ts (6 tests)
160+
161+
Test Files 3 passed (3)
162+
Tests 26 passed (26)
163+
```
164+
165+
> **🚨 All tests must pass before you open a PR.** The CI pipeline runs `npm run test` automatically on every pull request and will block merging if any test fails.
166+
167+
### 3. Interpreting SVG Output in the Browser
168+
169+
When you open a badge URL in your browser, here is what each response means:
170+
171+
| What you see | What it means |
172+
| -------------------------------------------- | ---------------------------------------------------------- |
173+
| Animated isometric city renders correctly | ✅ Everything is working |
174+
| Ghost-city badge with "NOT FOUND" label | ✅ Working — the username doesn't exist on GitHub |
175+
| Styled error card with "Invalid username" | ✅ Working — the username format was invalid |
176+
| Raw JSON `{"error":"Invalid parameters"...}` | ❌ Bug — validation errors must return SVG, not JSON |
177+
| Browser XML parse error / blank white page | ❌ Bug — unescaped `&` or malformed SVG in generator |
178+
| `401 Unauthorized` in the terminal | ❌ Your `GITHUB_PAT` in `.env.local` is missing or invalid |
179+
180+
### 4. Lint and Format
181+
182+
Run these before every commit:
183+
184+
```bash
185+
# Auto-format all files
186+
npm run format
187+
188+
# Check for linting errors
189+
npm run lint
190+
```
191+
192+
Fix every error before pushing. CI will fail if either check reports issues.
193+
194+
---
195+
91196
## 🤝 Contributor Onboarding
92197

93198
### 📁 Project Structure
@@ -241,7 +346,7 @@ Our automation runs entirely through issue comments. Here is how you interact wi
241346

242347
To keep the project moving, assignments are not permanent.
243348

244-
- **The 3-Day Rule:** If an issue has an assignee but sees **no activity for 3 days**, our automated background job will remove the assignment.
349+
- **The 2-Day Rule:** If an issue has an assignee but sees **no activity for 2 days**, our automated background job will remove the assignment.
245350
- **What counts as activity?** Posting a comment, opening a linked PR, or a maintainer adding a label.
246351
- **Why?** It frees up stale issues so other active contributors can pick them up. If your issue expires, you can always `/claim` it again if it's still available!
247352

@@ -250,7 +355,7 @@ To keep the project moving, assignments are not permanent.
250355
1. Create a new issue describing the bug or feature request you want to work on using our **Structured Issue Templates** (or find an open issue you authored).
251356
2. Comment `/claim` on the issue to lock it in.
252357
3. Need labels? Comment `/addlabel good-first-issue` (labels must already exist in the repo).
253-
4. Work on your code and submit a PR within 3 days to avoid expiry.
358+
4. Work on your code and submit a PR within 2 days to avoid expiry.
254359
5. Once your PR is merged and the issue is closed, you can create and `/claim` your next one!
255360

256361
### 🆘 Troubleshooting & Edge Cases

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2026 Sourav Jha
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

0 commit comments

Comments
 (0)