Skip to content

Commit 3fb8f77

Browse files
authored
Merge branch 'alpha' into alpha-add-more-info-on-duplicate-key-error
2 parents 0473c90 + 98a42e5 commit 3fb8f77

File tree

147 files changed

+8781
-4060
lines changed

Some content is hidden

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

147 files changed

+8781
-4060
lines changed
Lines changed: 272 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,272 @@
1+
name: ci-performance
2+
on:
3+
pull_request:
4+
branches:
5+
- alpha
6+
- beta
7+
- release
8+
- 'release-[0-9]+.x.x'
9+
- next-major
10+
paths-ignore:
11+
- '**.md'
12+
- 'docs/**'
13+
14+
env:
15+
NODE_VERSION: 24.11.0
16+
MONGODB_VERSION: 8.0.4
17+
18+
permissions:
19+
contents: read
20+
21+
jobs:
22+
performance-check:
23+
name: Benchmarks
24+
runs-on: ubuntu-latest
25+
timeout-minutes: 30
26+
27+
steps:
28+
- name: Checkout PR branch (for benchmark script)
29+
uses: actions/checkout@v4
30+
with:
31+
ref: ${{ github.event.pull_request.head.sha }}
32+
fetch-depth: 1
33+
34+
- name: Save PR benchmark script
35+
run: |
36+
mkdir -p /tmp/pr-benchmark
37+
cp -r benchmark /tmp/pr-benchmark/ || echo "No benchmark directory"
38+
cp package.json /tmp/pr-benchmark/ || true
39+
40+
- name: Checkout base branch
41+
uses: actions/checkout@v4
42+
with:
43+
ref: ${{ github.base_ref }}
44+
fetch-depth: 1
45+
clean: true
46+
47+
- name: Restore PR benchmark script
48+
run: |
49+
if [ -d "/tmp/pr-benchmark/benchmark" ]; then
50+
rm -rf benchmark
51+
cp -r /tmp/pr-benchmark/benchmark .
52+
fi
53+
54+
- name: Setup Node.js
55+
uses: actions/setup-node@v4
56+
with:
57+
node-version: ${{ env.NODE_VERSION }}
58+
cache: 'npm'
59+
60+
- name: Install dependencies (base)
61+
run: npm ci
62+
63+
- name: Build Parse Server (base)
64+
run: npm run build
65+
66+
- name: Run baseline benchmarks
67+
id: baseline
68+
env:
69+
NODE_ENV: production
70+
run: |
71+
echo "Running baseline benchmarks..."
72+
if [ ! -f "benchmark/performance.js" ]; then
73+
echo "⚠️ Benchmark script not found - this is expected for new features"
74+
echo "Skipping baseline benchmark"
75+
echo '[]' > baseline.json
76+
echo "Baseline: N/A (no benchmark script)" > baseline-output.txt
77+
exit 0
78+
fi
79+
taskset -c 0 npm run benchmark > baseline-output.txt 2>&1 || npm run benchmark > baseline-output.txt 2>&1 || true
80+
echo "Benchmark command completed with exit code: $?"
81+
echo "Output file size: $(wc -c < baseline-output.txt) bytes"
82+
echo "--- Begin baseline-output.txt ---"
83+
cat baseline-output.txt
84+
echo "--- End baseline-output.txt ---"
85+
# Extract JSON from output (everything between first [ and last ])
86+
sed -n '/^\[/,/^\]/p' baseline-output.txt > baseline.json || echo '[]' > baseline.json
87+
echo "Extracted JSON size: $(wc -c < baseline.json) bytes"
88+
echo "Baseline benchmark results:"
89+
cat baseline.json
90+
continue-on-error: true
91+
92+
- name: Save baseline results to temp location
93+
run: |
94+
mkdir -p /tmp/benchmark-results
95+
cp baseline.json /tmp/benchmark-results/ || echo '[]' > /tmp/benchmark-results/baseline.json
96+
cp baseline-output.txt /tmp/benchmark-results/ || echo 'No baseline output' > /tmp/benchmark-results/baseline-output.txt
97+
98+
- name: Upload baseline results
99+
uses: actions/upload-artifact@v4
100+
with:
101+
name: baseline-benchmark
102+
path: |
103+
/tmp/benchmark-results/baseline.json
104+
/tmp/benchmark-results/baseline-output.txt
105+
retention-days: 7
106+
107+
- name: Checkout PR branch
108+
uses: actions/checkout@v4
109+
with:
110+
ref: ${{ github.event.pull_request.head.sha }}
111+
fetch-depth: 1
112+
clean: true
113+
114+
- name: Restore baseline results
115+
run: |
116+
cp /tmp/benchmark-results/baseline.json ./ || echo '[]' > baseline.json
117+
cp /tmp/benchmark-results/baseline-output.txt ./ || echo 'No baseline output' > baseline-output.txt
118+
119+
- name: Setup Node.js (PR)
120+
uses: actions/setup-node@v4
121+
with:
122+
node-version: ${{ env.NODE_VERSION }}
123+
cache: 'npm'
124+
125+
- name: Install dependencies (PR)
126+
run: npm ci
127+
128+
- name: Build Parse Server (PR)
129+
run: npm run build
130+
131+
- name: Run PR benchmarks
132+
id: pr-bench
133+
env:
134+
NODE_ENV: production
135+
run: |
136+
echo "Running PR benchmarks..."
137+
taskset -c 0 npm run benchmark > pr-output.txt 2>&1 || npm run benchmark > pr-output.txt 2>&1 || true
138+
echo "Benchmark command completed with exit code: $?"
139+
echo "Output file size: $(wc -c < pr-output.txt) bytes"
140+
echo "--- Begin pr-output.txt ---"
141+
cat pr-output.txt
142+
echo "--- End pr-output.txt ---"
143+
# Extract JSON from output (everything between first [ and last ])
144+
sed -n '/^\[/,/^\]/p' pr-output.txt > pr.json || echo '[]' > pr.json
145+
echo "Extracted JSON size: $(wc -c < pr.json) bytes"
146+
echo "PR benchmark results:"
147+
cat pr.json
148+
continue-on-error: true
149+
150+
- name: Upload PR results
151+
uses: actions/upload-artifact@v4
152+
with:
153+
name: pr-benchmark
154+
path: |
155+
pr.json
156+
pr-output.txt
157+
retention-days: 7
158+
159+
- name: Verify benchmark files exist
160+
run: |
161+
echo "Checking for benchmark result files..."
162+
if [ ! -f baseline.json ] || [ ! -s baseline.json ]; then
163+
echo "⚠️ baseline.json is missing or empty, creating empty array"
164+
echo '[]' > baseline.json
165+
fi
166+
if [ ! -f pr.json ] || [ ! -s pr.json ]; then
167+
echo "⚠️ pr.json is missing or empty, creating empty array"
168+
echo '[]' > pr.json
169+
fi
170+
echo "baseline.json size: $(wc -c < baseline.json) bytes"
171+
echo "pr.json size: $(wc -c < pr.json) bytes"
172+
173+
- name: Compare benchmark results
174+
id: compare
175+
run: |
176+
node -e "
177+
const fs = require('fs');
178+
179+
let baseline, pr;
180+
try {
181+
baseline = JSON.parse(fs.readFileSync('baseline.json', 'utf8'));
182+
pr = JSON.parse(fs.readFileSync('pr.json', 'utf8'));
183+
} catch (e) {
184+
console.log('⚠️ Could not parse benchmark results');
185+
process.exit(0);
186+
}
187+
188+
// Handle case where baseline doesn't exist (new feature)
189+
if (!Array.isArray(baseline) || baseline.length === 0) {
190+
if (!Array.isArray(pr) || pr.length === 0) {
191+
console.log('⚠️ Benchmark results are empty or invalid');
192+
process.exit(0);
193+
}
194+
console.log('# Performance Benchmark Results\n');
195+
console.log('> ℹ️ Baseline not available - this appears to be a new feature\n');
196+
console.log('| Benchmark | Value | Details |');
197+
console.log('|-----------|-------|---------|');
198+
pr.forEach(result => {
199+
console.log(\`| \${result.name} | \${result.value.toFixed(2)} ms | \${result.extra} |\`);
200+
});
201+
console.log('');
202+
console.log('✅ **New benchmarks established for this feature.**');
203+
process.exit(0);
204+
}
205+
206+
if (!Array.isArray(pr) || pr.length === 0) {
207+
console.log('⚠️ PR benchmark results are empty or invalid');
208+
process.exit(0);
209+
}
210+
211+
console.log('# Performance Comparison\n');
212+
console.log('| Benchmark | Baseline | PR | Change | Status |');
213+
console.log('|-----------|----------|----|---------| ------ |');
214+
215+
let hasRegression = false;
216+
let hasImprovement = false;
217+
218+
baseline.forEach(baseResult => {
219+
const prResult = pr.find(p => p.name === baseResult.name);
220+
if (!prResult) {
221+
console.log(\`| \${baseResult.name} | \${baseResult.value.toFixed(2)} ms | N/A | - | ⚠️ Missing |\`);
222+
return;
223+
}
224+
225+
const baseValue = parseFloat(baseResult.value);
226+
const prValue = parseFloat(prResult.value);
227+
const change = ((prValue - baseValue) / baseValue * 100);
228+
const changeStr = change > 0 ? \`+\${change.toFixed(1)}%\` : \`\${change.toFixed(1)}%\`;
229+
230+
let status = '✅';
231+
if (change > 50) {
232+
status = '❌ Much Slower';
233+
hasRegression = true;
234+
} else if (change > 25) {
235+
status = '⚠️ Slower';
236+
hasRegression = true;
237+
} else if (change < -25) {
238+
status = '🚀 Faster';
239+
hasImprovement = true;
240+
}
241+
242+
console.log(\`| \${baseResult.name} | \${baseValue.toFixed(2)} ms | \${prValue.toFixed(2)} ms | \${changeStr} | \${status} |\`);
243+
});
244+
245+
console.log('');
246+
if (hasRegression) {
247+
console.log('⚠️ **Performance regressions detected.** Please review the changes.');
248+
} else if (hasImprovement) {
249+
console.log('🚀 **Performance improvements detected!** Great work!');
250+
} else {
251+
console.log('✅ **No significant performance changes.**');
252+
}
253+
" | tee comparison.md
254+
255+
- name: Upload comparison
256+
uses: actions/upload-artifact@v4
257+
with:
258+
name: benchmark-comparison
259+
path: comparison.md
260+
retention-days: 30
261+
262+
- name: Generate job summary
263+
if: always()
264+
run: |
265+
if [ -f comparison.md ]; then
266+
cat comparison.md >> $GITHUB_STEP_SUMMARY
267+
else
268+
echo "⚠️ Benchmark comparison not available" >> $GITHUB_STEP_SUMMARY
269+
fi
270+
concurrency:
271+
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
272+
cancel-in-progress: true

.github/workflows/ci.yml

Lines changed: 10 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ on:
88
paths-ignore:
99
- '**/**.md'
1010
env:
11-
NODE_VERSION: 22.12.0
11+
NODE_VERSION: 24.11.0
1212
PARSE_SERVER_TEST_TIMEOUT: 20000
1313
permissions:
1414
actions: write
@@ -153,31 +153,27 @@ jobs:
153153
strategy:
154154
matrix:
155155
include:
156-
- name: MongoDB 6, ReplicaSet
157-
MONGODB_VERSION: 6.0.19
158-
MONGODB_TOPOLOGY: replset
159-
NODE_VERSION: 22.12.0
160156
- name: MongoDB 7, ReplicaSet
161157
MONGODB_VERSION: 7.0.16
162158
MONGODB_TOPOLOGY: replset
163-
NODE_VERSION: 22.12.0
159+
NODE_VERSION: 24.11.0
164160
- name: MongoDB 8, ReplicaSet
165161
MONGODB_VERSION: 8.0.4
166162
MONGODB_TOPOLOGY: replset
167-
NODE_VERSION: 22.12.0
163+
NODE_VERSION: 24.11.0
168164
- name: Redis Cache
169165
PARSE_SERVER_TEST_CACHE: redis
170166
MONGODB_VERSION: 8.0.4
171167
MONGODB_TOPOLOGY: standalone
172-
NODE_VERSION: 22.12.0
168+
NODE_VERSION: 24.11.0
173169
- name: Node 20
174170
MONGODB_VERSION: 8.0.4
175171
MONGODB_TOPOLOGY: standalone
176-
NODE_VERSION: 20.18.0
177-
- name: Node 18
172+
NODE_VERSION: 20.19.0
173+
- name: Node 22
178174
MONGODB_VERSION: 8.0.4
179175
MONGODB_TOPOLOGY: standalone
180-
NODE_VERSION: 18.20.4
176+
NODE_VERSION: 22.12.0
181177
fail-fast: false
182178
name: ${{ matrix.name }}
183179
timeout-minutes: 20
@@ -223,24 +219,15 @@ jobs:
223219
strategy:
224220
matrix:
225221
include:
226-
- name: PostgreSQL 15, PostGIS 3.3
227-
POSTGRES_IMAGE: postgis/postgis:15-3.3
228-
NODE_VERSION: 22.12.0
229-
- name: PostgreSQL 15, PostGIS 3.4
230-
POSTGRES_IMAGE: postgis/postgis:15-3.4
231-
NODE_VERSION: 22.12.0
232-
- name: PostgreSQL 15, PostGIS 3.5
233-
POSTGRES_IMAGE: postgis/postgis:15-3.5
234-
NODE_VERSION: 22.12.0
235222
- name: PostgreSQL 16, PostGIS 3.5
236223
POSTGRES_IMAGE: postgis/postgis:16-3.5
237-
NODE_VERSION: 22.12.0
224+
NODE_VERSION: 24.11.0
238225
- name: PostgreSQL 17, PostGIS 3.5
239226
POSTGRES_IMAGE: postgis/postgis:17-3.5
240-
NODE_VERSION: 22.12.0
227+
NODE_VERSION: 24.11.0
241228
- name: PostgreSQL 18, PostGIS 3.6
242229
POSTGRES_IMAGE: postgis/postgis:18-3.6
243-
NODE_VERSION: 22.12.0
230+
NODE_VERSION: 24.11.0
244231
fail-fast: false
245232
name: ${{ matrix.name }}
246233
timeout-minutes: 20
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# Trigger this workflow only to manually create a docs release; this should only be used
2+
# in extraordinary circumstances, as docs releases are normally created automatically as
3+
# part of the automated release workflow.
4+
5+
name: release-manual-docs
6+
on:
7+
workflow_dispatch:
8+
inputs:
9+
ref:
10+
default: ''
11+
description: 'Reference (tag / SHA):'
12+
required: true
13+
jobs:
14+
docs:
15+
runs-on: ubuntu-latest
16+
timeout-minutes: 15
17+
steps:
18+
- name: Checkout repository
19+
uses: actions/checkout@v4
20+
with:
21+
ref: ${{ github.event.inputs.ref }}
22+
- name: Use Node.js
23+
uses: actions/setup-node@v4
24+
with:
25+
node-version: 18.20.4
26+
- name: Cache Node.js modules
27+
uses: actions/cache@v4
28+
with:
29+
path: ~/.npm
30+
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
31+
restore-keys: |
32+
${{ runner.os }}-node-
33+
- name: Generate Docs
34+
run: |
35+
echo $SOURCE_TAG
36+
npm ci
37+
./release_docs.sh
38+
env:
39+
SOURCE_TAG: ${{ github.event.inputs.ref }}
40+
- name: Deploy
41+
uses: peaceiris/actions-gh-pages@v3.7.3
42+
with:
43+
github_token: ${{ secrets.GITHUB_TOKEN }}
44+
publish_dir: ./docs

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,3 +61,6 @@ lib/
6161

6262
# Redis Dump
6363
dump.rdb
64+
65+
# AI agents
66+
.claude

0 commit comments

Comments
 (0)