Skip to content

Commit 4a010b6

Browse files
chore: sync with upstream main
2 parents 264d1aa + 7d2918b commit 4a010b6

70 files changed

Lines changed: 6491 additions & 1316 deletions

Some content is hidden

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

.env.example

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,4 +32,7 @@ MOBILE_REDIRECT_URI=devcard://oauth/callback
3232

3333
# ─── Server ───
3434
PORT=3000
35-
NODE_ENV=development
35+
NODE_ENV=development
36+
37+
# ─── Refresh Token Cleanup ───
38+
REFRESH_TOKEN_CLEANUP_INTERVAL_MS=86400000

.github/pull_request_template.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,10 @@ Closes #
4343

4444
## Checklist
4545

46-
- [ ] My code follows the project's coding style (`pnpm -r run lint` passes).
47-
- [ ] TypeScript compiles without errors (`pnpm -r run typecheck`).
46+
- [ ] My code follows the project's coding style (`npm run lint` passes).
47+
- [ ] TypeScript compiles without errors (`npm run typecheck --workspaces --if-present`).
4848
- [ ] I have added or updated tests for the changes I made.
49-
- [ ] All tests pass locally (`pnpm -r run test`).
49+
- [ ] All tests pass locally (`npm run test --workspaces --if-present`).
5050
- [ ] I have updated documentation where necessary.
5151
- [ ] No new `console.log` or debug statements left in the code.
5252
- [ ] Breaking changes are documented in this PR description.

.github/scripts/commentResults.js

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ module.exports = async ({
99
backendTypecheck,
1010
mobileLint,
1111
mobileTest,
12-
webCheck,
1312
webBuild,
1413
backendLintOutput,
1514
mobileLintOutput,
@@ -57,7 +56,6 @@ ${mobileLint === 'failure' ? lintDetails(mobileLintOutput) : ''}
5756
5857
| Check | Result |
5958
|---|---|
60-
| Check | ${status(webCheck)} |
6159
| Build | ${status(webBuild)} |
6260
6361
---
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
module.exports = async ({ github, context }) => {
2+
const owner = context.repo.owner;
3+
const repo = context.repo.repo;
4+
5+
const EXCLUDED = new Set([
6+
'shantkhatri',
7+
'harxhit',
8+
'blankirigaya'
9+
]);
10+
11+
const contributors = new Map();
12+
13+
const ensure = (login, avatarUrl, profileUrl) => {
14+
if (!contributors.has(login)) {
15+
contributors.set(login, {
16+
login,
17+
avatarUrl,
18+
profileUrl,
19+
mergedPrs: 0,
20+
openPrs: 0,
21+
issues: 0
22+
});
23+
}
24+
25+
return contributors.get(login);
26+
};
27+
28+
const mergedPrs = await github.paginate(
29+
github.rest.pulls.list,
30+
{
31+
owner,
32+
repo,
33+
state: 'closed',
34+
per_page: 100
35+
}
36+
);
37+
38+
for (const pr of mergedPrs) {
39+
if (!pr.merged_at || !pr.user) continue;
40+
41+
const login = pr.user.login;
42+
43+
if (EXCLUDED.has(login.toLowerCase())) continue;
44+
45+
const user = ensure(
46+
login,
47+
pr.user.avatar_url,
48+
pr.user.html_url
49+
);
50+
51+
user.mergedPrs++;
52+
}
53+
54+
const openPrs = await github.paginate(
55+
github.rest.pulls.list,
56+
{
57+
owner,
58+
repo,
59+
state: 'open',
60+
per_page: 100
61+
}
62+
);
63+
64+
for (const pr of openPrs) {
65+
if (!pr.user) continue;
66+
67+
const login = pr.user.login;
68+
69+
if (EXCLUDED.has(login.toLowerCase())) continue;
70+
71+
const user = ensure(
72+
login,
73+
pr.user.avatar_url,
74+
pr.user.html_url
75+
);
76+
77+
user.openPrs++;
78+
}
79+
80+
const issues = await github.paginate(
81+
github.rest.issues.listForRepo,
82+
{
83+
owner,
84+
repo,
85+
state: 'all',
86+
per_page: 100
87+
}
88+
);
89+
90+
for (const issue of issues) {
91+
if (issue.pull_request || !issue.user) continue;
92+
93+
const login = issue.user.login;
94+
95+
if (EXCLUDED.has(login.toLowerCase())) continue;
96+
97+
const user = ensure(
98+
login,
99+
issue.user.avatar_url,
100+
issue.user.html_url
101+
);
102+
103+
user.issues++;
104+
}
105+
106+
const leaderboard = [...contributors.values()].sort(
107+
(a, b) =>
108+
b.mergedPrs - a.mergedPrs ||
109+
b.issues - a.issues ||
110+
b.openPrs - a.openPrs ||
111+
a.login.localeCompare(b.login)
112+
);
113+
114+
const fs = require('fs');
115+
const path = require('path');
116+
117+
const outputDir = path.join('apps', 'web', 'public');
118+
const outputFile = path.join(outputDir, 'leaderboard.json');
119+
120+
fs.mkdirSync(outputDir, { recursive: true });
121+
122+
fs.writeFileSync(
123+
outputFile,
124+
JSON.stringify(leaderboard, null, 2),
125+
'utf8'
126+
);
127+
128+
console.log(`Generated ${leaderboard.length} contributors`);
129+
console.log(`Leaderboard written to ${outputFile}`);
130+
};

.github/scripts/triagePr.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ module.exports = async ({github, context}) => {
1010
const mobileFiles = [];
1111
const devopsFiles = [];
1212

13-
const labels = [];
13+
const labels = ['gssoc:approved'];
1414
let primaryArea = null;
1515
let reviewer = null;
1616

.github/workflows/ci.yml

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,6 @@ jobs:
9393
runs-on: ubuntu-latest
9494

9595
outputs:
96-
check_result: ${{ steps.web_check.outcome }}
9796
build_result: ${{ steps.web_build.outcome }}
9897

9998
steps:
@@ -108,19 +107,13 @@ jobs:
108107
- name: Install web dependencies
109108
run: npm --prefix apps/web install
110109

111-
- name: Web check
112-
id: web_check
113-
continue-on-error: true
114-
run: npm --prefix apps/web run lint
115-
116110
- name: Web build
117111
id: web_build
118112
continue-on-error: true
119113
run: npm --prefix apps/web run build
120114

121115
- name: Fail job if any check failed
122116
if: >
123-
steps.web_check.outcome == 'failure' ||
124117
steps.web_build.outcome == 'failure'
125118
run: exit 1
126119

@@ -191,7 +184,6 @@ jobs:
191184
backendLint: '${{ needs.backend-ci.outputs.lint_result }}',
192185
backendTest: '${{ needs.backend-ci.outputs.test_result }}',
193186
backendTypecheck: '${{ needs.backend-ci.outputs.typecheck_result }}',
194-
webCheck: '${{ needs.web-ci.outputs.check_result }}',
195187
webBuild: '${{ needs.web-ci.outputs.build_result }}',
196188
mobileLint: '${{ needs.mobile-ci.outputs.lint_result }}',
197189
mobileTest: '${{ needs.mobile-ci.outputs.test_result }}',

.github/workflows/leaderboard.yml

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
name: Update Leaderboard
2+
3+
on:
4+
workflow_dispatch:
5+
schedule:
6+
- cron: '0 * * * *'
7+
8+
permissions:
9+
contents: write
10+
pull-requests: write
11+
issues: read
12+
13+
jobs:
14+
leaderboard:
15+
runs-on: ubuntu-latest
16+
17+
steps:
18+
- name: Checkout
19+
uses: actions/checkout@v4
20+
21+
- name: Setup Node
22+
uses: actions/setup-node@v4
23+
with:
24+
node-version: 22
25+
26+
- name: Generate leaderboard
27+
uses: actions/github-script@v7
28+
with:
29+
github-token: ${{ secrets.GITHUB_TOKEN }}
30+
script: |
31+
const script = require('./.github/scripts/generateLeaderboard.js');
32+
await script({ github, context });
33+
34+
- name: Create Pull Request
35+
uses: peter-evans/create-pull-request@v6
36+
with:
37+
token: ${{ secrets.GITHUB_TOKEN }}
38+
commit-message: "chore: update leaderboard"
39+
title: "chore: update leaderboard"
40+
body: "Automated update of contributor leaderboard data."
41+
branch: "automation/leaderboard-update"
42+
base: "main"
43+
delete-branch: true

.github/workflows/uat.yml

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
name: UAT Deploy
2+
3+
on:
4+
push:
5+
branches: [main]
6+
7+
jobs:
8+
detect-changes:
9+
runs-on: ubuntu-latest
10+
outputs:
11+
backend: ${{ steps.changes.outputs.backend }}
12+
steps:
13+
- uses: actions/checkout@v4
14+
15+
- uses: dorny/paths-filter@v3
16+
id: changes
17+
with:
18+
filters: |
19+
backend:
20+
- 'apps/backend/**'
21+
22+
backend-deploy:
23+
needs: detect-changes
24+
if: needs.detect-changes.outputs.backend == 'true'
25+
runs-on: ubuntu-latest
26+
permissions:
27+
contents: read
28+
id-token: write
29+
30+
steps:
31+
- name: Checkout app repo
32+
uses: actions/checkout@v4
33+
34+
- name: Checkout infra repo
35+
uses: actions/checkout@v4
36+
with:
37+
repository: Dev-Card/devcard-infra
38+
path: infra
39+
token: ${{ secrets.INFRA_REPO_TOKEN }}
40+
41+
- name: Authenticate to GCP
42+
uses: google-github-actions/auth@v2
43+
with:
44+
workload_identity_provider: ${{ secrets.WIF_PROVIDER }}
45+
service_account: ${{ secrets.WIF_SERVICE_ACCOUNT }}
46+
47+
- name: Setup gcloud
48+
uses: google-github-actions/setup-gcloud@v2
49+
50+
- name: Configure Docker for Artifact Registry
51+
run: gcloud auth configure-docker asia-south1-docker.pkg.dev
52+
53+
- name: Set image tag
54+
id: tag
55+
run: echo "sha=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
56+
57+
- name: Setup Node.js
58+
uses: actions/setup-node@v4
59+
with:
60+
node-version: 20
61+
cache: npm
62+
cache-dependency-path: apps/backend/package-lock.json
63+
64+
- name: Install dependencies
65+
working-directory: apps/backend
66+
run: npm ci
67+
68+
# TODO: Once tests are fixed, uncomment the following lines
69+
# - name: Run tests
70+
# working-directory: apps/backend
71+
# run: npm test
72+
73+
- name: Build and push Docker image
74+
run: |
75+
docker build \
76+
-f docker/backend.Dockerfile \
77+
-t asia-south1-docker.pkg.dev/devcard-prod/devcard/backend:${{ steps.tag.outputs.sha }} \
78+
.
79+
docker push asia-south1-docker.pkg.dev/devcard-prod/devcard/backend:${{ steps.tag.outputs.sha }}
80+
81+
- name: Get GKE credentials
82+
uses: google-github-actions/get-gke-credentials@v2
83+
with:
84+
cluster_name: devcard-cluster
85+
location: asia-south1
86+
87+
- name: Run Prisma migrations
88+
run: |
89+
cat <<EOF | kubectl apply -f -
90+
apiVersion: batch/v1
91+
kind: Job
92+
metadata:
93+
name: prisma-migrate-${{ steps.tag.outputs.sha }}
94+
namespace: uat
95+
spec:
96+
ttlSecondsAfterFinished: 300
97+
template:
98+
spec:
99+
restartPolicy: Never
100+
containers:
101+
- name: migrate
102+
image: asia-south1-docker.pkg.dev/devcard-prod/devcard/backend:${{ steps.tag.outputs.sha }}
103+
command: ["npx", "prisma", "migrate", "deploy"]
104+
env:
105+
- name: DATABASE_URL
106+
valueFrom:
107+
secretKeyRef:
108+
name: devcard-secret
109+
key: database-url
110+
EOF
111+
kubectl wait --for=condition=complete \
112+
job/prisma-migrate-${{ steps.tag.outputs.sha }} \
113+
-n uat --timeout=120s
114+
115+
- name: Update image tag in kustomize
116+
run: |
117+
cd infra/k8s/overlays/uat
118+
kustomize edit set image IMAGE_TAG_PLACEHOLDER=asia-south1-docker.pkg.dev/devcard-prod/devcard/backend:${{ steps.tag.outputs.sha }}
119+
120+
- name: Commit and push image tag to infra repo
121+
run: |
122+
cd infra
123+
git config user.name "github-actions[bot]"
124+
git config user.email "github-actions[bot]@users.noreply.github.com"
125+
git add k8s/overlays/uat/kustomization.yaml
126+
git commit -m "chore: update uat backend image to ${{ steps.tag.outputs.sha }}"
127+
git push
128+
129+
- name: Deploy to UAT
130+
run: kubectl apply -k infra/k8s/overlays/uat
131+
132+
- name: Wait for rollout
133+
run: |
134+
kubectl rollout status deployment/backend \
135+
-n uat --timeout=5m

0 commit comments

Comments
 (0)