@@ -12,11 +12,15 @@ concurrency:
1212 group : ${{ github.workflow }}-${{ github.ref }}
1313 cancel-in-progress : ${{ github.ref == 'refs/heads/main' }}
1414
15+ env :
16+ JS_ROOT : js
17+
1518jobs :
1619 detect-changes :
1720 name : Detect Changes
1821 runs-on : ubuntu-latest
1922 outputs :
23+ mjs-changed : ${{ steps.changes.outputs.mjs-changed }}
2024 js-changed : ${{ steps.changes.outputs.js-changed }}
2125 package-changed : ${{ steps.changes.outputs.package-changed }}
2226 docs-changed : ${{ steps.changes.outputs.docs-changed }}
@@ -27,51 +31,13 @@ jobs:
2731 with :
2832 fetch-depth : 0
2933
30- - name : Detect changed files
34+ - name : Detect JavaScript changes
3135 id : changes
32- shell : bash
33- run : |
34- if [ "${{ github.event_name }}" = "pull_request" ]; then
35- BASE_SHA="${{ github.event.pull_request.base.sha }}"
36- HEAD_SHA="${{ github.event.pull_request.head.sha }}"
37- git fetch origin "$BASE_SHA"
38- CHANGED_FILES=$(git diff --name-only "$BASE_SHA" "$HEAD_SHA")
39- else
40- CHANGED_FILES=$(git diff --name-only HEAD^ HEAD 2>/dev/null || git ls-tree --name-only -r HEAD)
41- fi
42-
43- echo "Changed files:"
44- echo "$CHANGED_FILES"
45-
46- if echo "$CHANGED_FILES" | grep -qE '^js/'; then
47- echo "js-changed=true" >> "$GITHUB_OUTPUT"
48- else
49- echo "js-changed=false" >> "$GITHUB_OUTPUT"
50- fi
51-
52- if echo "$CHANGED_FILES" | grep -qE '^js/(package\.json|package-lock\.json|bun\.lock)$'; then
53- echo "package-changed=true" >> "$GITHUB_OUTPUT"
54- else
55- echo "package-changed=false" >> "$GITHUB_OUTPUT"
56- fi
57-
58- if echo "$CHANGED_FILES" | grep -qE '(^docs/|\.md$)'; then
59- echo "docs-changed=true" >> "$GITHUB_OUTPUT"
60- else
61- echo "docs-changed=false" >> "$GITHUB_OUTPUT"
62- fi
63-
64- if echo "$CHANGED_FILES" | grep -qE '^\.github/workflows/js\.yml$'; then
65- echo "workflow-changed=true" >> "$GITHUB_OUTPUT"
66- else
67- echo "workflow-changed=false" >> "$GITHUB_OUTPUT"
68- fi
69-
70- if echo "$CHANGED_FILES" | grep -qE '^(js/|\.github/workflows/js\.yml$)'; then
71- echo "any-code-changed=true" >> "$GITHUB_OUTPUT"
72- else
73- echo "any-code-changed=false" >> "$GITHUB_OUTPUT"
74- fi
36+ env :
37+ GITHUB_EVENT_NAME : ${{ github.event_name }}
38+ GITHUB_BASE_SHA : ${{ github.event.pull_request.base.sha || '' }}
39+ GITHUB_HEAD_SHA : ${{ github.event.pull_request.head.sha || '' }}
40+ run : node scripts/detect-js-changes.mjs
7541
7642 test-compilation :
7743 name : Test Compilation
@@ -80,19 +46,14 @@ jobs:
8046 if : |
8147 github.event_name == 'push' ||
8248 github.event_name == 'workflow_dispatch' ||
49+ needs.detect-changes.outputs.mjs-changed == 'true' ||
8350 needs.detect-changes.outputs.js-changed == 'true' ||
8451 needs.detect-changes.outputs.workflow-changed == 'true'
8552 steps :
8653 - uses : actions/checkout@v6
8754
8855 - name : Check JavaScript syntax
89- working-directory : js
90- shell : bash
91- run : |
92- find src tests examples benchmarks -name "*.js" -type f -print0 | while IFS= read -r -d '' file; do
93- echo "Checking $file"
94- node --check "$file"
95- done
56+ run : bash scripts/check-mjs-syntax.sh
9657
9758 check-file-line-limits :
9859 name : Check File Line Limits
10162 if : |
10263 github.event_name == 'push' ||
10364 github.event_name == 'workflow_dispatch' ||
65+ needs.detect-changes.outputs.mjs-changed == 'true' ||
10466 needs.detect-changes.outputs.js-changed == 'true' ||
10567 needs.detect-changes.outputs.docs-changed == 'true' ||
10668 needs.detect-changes.outputs.workflow-changed == 'true'
@@ -111,37 +73,12 @@ jobs:
11173
11274 - name : Simulate fresh merge with base branch
11375 if : github.event_name == 'pull_request'
114- shell : bash
115- run : |
116- git fetch origin "${{ github.base_ref }}"
117- git merge --no-commit --no-ff "origin/${{ github.base_ref }}"
76+ env :
77+ BASE_REF : ${{ github.base_ref }}
78+ run : bash scripts/simulate-fresh-merge.sh
11879
11980 - name : Enforce file line limits
120- shell : bash
121- run : |
122- failures=0
123- while IFS= read -r file; do
124- limit=1500
125- case "$file" in
126- docs/*.md) limit=2500 ;;
127- esac
128- line_count=$(wc -l < "$file")
129- echo "$file: $line_count lines"
130- if [ "$line_count" -gt "$limit" ]; then
131- echo "::error file=$file::File has $line_count lines (limit: $limit)"
132- failures=$((failures + 1))
133- fi
134- done < <(
135- find js docs .github/workflows -type f \( \
136- -name "*.js" -o \
137- -name "*.mjs" -o \
138- -name "*.cjs" -o \
139- -name "*.md" -o \
140- -name "*.yml" -o \
141- -name "*.yaml" \
142- \) 2>/dev/null | grep -vE '/(node_modules|\.git)/'
143- )
144- test "$failures" -eq 0
81+ run : bash scripts/check-file-line-limits.sh
14582
14683 version-check :
14784 name : Check npm Version
15087 if : |
15188 github.event_name == 'push' ||
15289 github.event_name == 'workflow_dispatch' ||
90+ needs.detect-changes.outputs.mjs-changed == 'true' ||
15391 needs.detect-changes.outputs.js-changed == 'true' ||
15492 needs.detect-changes.outputs.package-changed == 'true' ||
15593 needs.detect-changes.outputs.workflow-changed == 'true'
@@ -161,32 +99,17 @@ jobs:
16199 steps :
162100 - uses : actions/checkout@v6
163101
102+ - name : Setup Node.js
103+ uses : actions/setup-node@v6
104+ with :
105+ node-version : ' 24.x'
106+
164107 - name : Check package version
165108 id : check
166- working-directory : js
167- shell : bash
168- run : |
169- CURRENT_VERSION=$(node -p "require('./package.json').version")
170- PACKAGE_NAME=$(node -p "require('./package.json').name")
171- NPM_VERSION=$(npm view "$PACKAGE_NAME" version 2>/dev/null || echo "not-found")
172-
173- echo "Package: $PACKAGE_NAME"
174- echo "Current version: $CURRENT_VERSION"
175- echo "NPM version: $NPM_VERSION"
176- echo "package-name=$PACKAGE_NAME" >> "$GITHUB_OUTPUT"
177- echo "version=$CURRENT_VERSION" >> "$GITHUB_OUTPUT"
178- echo "npm-version=$NPM_VERSION" >> "$GITHUB_OUTPUT"
179-
180- if [ "${{ github.event_name }}" = "pull_request" ] && [ "$NPM_VERSION" = "$CURRENT_VERSION" ]; then
181- echo "::error::Version must be bumped for PR. Current version ($CURRENT_VERSION) is already published to npm"
182- exit 1
183- fi
184-
185- if [ "${{ github.event_name }}" = "push" ] && [ "${{ github.ref }}" = "refs/heads/main" ] && [ "$NPM_VERSION" != "$CURRENT_VERSION" ]; then
186- echo "should-publish=true" >> "$GITHUB_OUTPUT"
187- else
188- echo "should-publish=false" >> "$GITHUB_OUTPUT"
189- fi
109+ env :
110+ GITHUB_EVENT_NAME : ${{ github.event_name }}
111+ GITHUB_REF : ${{ github.ref }}
112+ run : node scripts/check-npm-version.mjs
190113
191114 lint :
192115 name : Lint and Typecheck
@@ -196,6 +119,7 @@ jobs:
196119 !cancelled() &&
197120 (github.event_name == 'push' ||
198121 github.event_name == 'workflow_dispatch' ||
122+ needs.detect-changes.outputs.mjs-changed == 'true' ||
199123 needs.detect-changes.outputs.js-changed == 'true' ||
200124 needs.detect-changes.outputs.docs-changed == 'true' ||
201125 needs.detect-changes.outputs.package-changed == 'true' ||
@@ -208,10 +132,9 @@ jobs:
208132
209133 - name : Simulate fresh merge with base branch
210134 if : github.event_name == 'pull_request'
211- shell : bash
212- run : |
213- git fetch origin "${{ github.base_ref }}"
214- git merge --no-commit --no-ff "origin/${{ github.base_ref }}"
135+ env :
136+ BASE_REF : ${{ github.base_ref }}
137+ run : bash scripts/simulate-fresh-merge.sh
215138
216139 - name : Setup Bun
217140 uses : oven-sh/setup-bun@v2
@@ -256,10 +179,10 @@ jobs:
256179
257180 - name : Simulate fresh merge with base branch
258181 if : github.event_name == 'pull_request'
182+ env :
183+ BASE_REF : ${{ github.base_ref }}
259184 shell : bash
260- run : |
261- git fetch origin "${{ github.base_ref }}"
262- git merge --no-commit --no-ff "origin/${{ github.base_ref }}"
185+ run : bash scripts/simulate-fresh-merge.sh
263186
264187 - name : Setup Bun
265188 if : matrix.runtime == 'bun'
@@ -341,6 +264,33 @@ jobs:
341264 working-directory : js
342265 run : bun test --coverage
343266
267+ validate-docs :
268+ name : Validate Documentation
269+ runs-on : ubuntu-latest
270+ needs : [detect-changes, check-file-line-limits]
271+ if : |
272+ !cancelled() &&
273+ (github.event_name == 'push' ||
274+ github.event_name == 'workflow_dispatch' ||
275+ needs.detect-changes.outputs.docs-changed == 'true' ||
276+ needs.detect-changes.outputs.workflow-changed == 'true') &&
277+ (needs.check-file-line-limits.result == 'success' || needs.check-file-line-limits.result == 'skipped')
278+ steps :
279+ - uses : actions/checkout@v6
280+
281+ - name : Check required documentation files
282+ run : |
283+ missing=0
284+ for file in README.md CONTRIBUTING.md LICENSE js/README.md rust/README.md; do
285+ if [ -f "$file" ]; then
286+ echo "Found $file"
287+ else
288+ echo "::error file=$file::Required documentation file is missing"
289+ missing=$((missing + 1))
290+ fi
291+ done
292+ test "$missing" -eq 0
293+
344294 benchmark :
345295 name : Benchmarks
346296 runs-on : ubuntu-latest
@@ -399,8 +349,8 @@ jobs:
399349
400350 publish :
401351 name : Publish npm Package
402- needs : [version-check, lint, test, benchmark, build]
403352 runs-on : ubuntu-latest
353+ needs : [version-check, lint, test, benchmark, build]
404354 if : |
405355 !cancelled() &&
406356 github.event_name == 'push' &&
@@ -427,33 +377,45 @@ jobs:
427377 run : npm ci
428378
429379 - name : Publish to npm
430- working-directory : js
431- run : npm publish --access public
380+ id : publish
432381 env :
433382 NODE_AUTH_TOKEN : ${{ secrets.NPM_TOKEN }}
383+ run : node scripts/publish-to-npm.mjs
434384
435385 - name : Create GitHub release
386+ if : steps.publish.outputs.published == 'true'
436387 env :
437388 GH_TOKEN : ${{ secrets.GITHUB_TOKEN }}
438389 run : |
439- VERSION="${{ needs.version-check.outputs.version }}"
440- git tag -a "js-v$VERSION" -m "JavaScript release v$VERSION"
441- git push origin "js-v$VERSION"
442- gh release create "js-v$VERSION" \
443- --title "JavaScript v$VERSION" \
444- --notes "npm: https://www.npmjs.com/package/${{ needs.version-check.outputs.package-name }}/v/$VERSION"
390+ node scripts/create-js-github-release.mjs \
391+ --release-version "${{ steps.publish.outputs.published_version }}" \
392+ --package-name "${{ needs.version-check.outputs.package-name }}" \
393+ --repository "${{ github.repository }}"
445394
446395 summary :
447396 name : Summary
448397 runs-on : ubuntu-latest
449- needs : [detect-changes, test-compilation, check-file-line-limits, version-check, lint, test, benchmark, build, publish]
398+ needs :
399+ [
400+ detect-changes,
401+ test-compilation,
402+ check-file-line-limits,
403+ version-check,
404+ lint,
405+ test,
406+ validate-docs,
407+ benchmark,
408+ build,
409+ publish,
410+ ]
450411 if : always()
451412 steps :
452413 - name : Workflow summary
453414 run : |
454415 echo "## JavaScript Workflow Summary"
455416 echo "- Event: ${{ github.event_name }}"
456417 echo "- Ref: ${{ github.ref_name }}"
418+ echo "- MJS changed: ${{ needs.detect-changes.outputs.mjs-changed }}"
457419 echo "- JS changed: ${{ needs.detect-changes.outputs.js-changed }}"
458420 echo "- Package changed: ${{ needs.detect-changes.outputs.package-changed }}"
459421 echo "- Docs changed: ${{ needs.detect-changes.outputs.docs-changed }}"
@@ -463,6 +425,7 @@ jobs:
463425 echo "- Version check: ${{ needs.version-check.result }}"
464426 echo "- Lint: ${{ needs.lint.result }}"
465427 echo "- Test: ${{ needs.test.result }}"
428+ echo "- Docs: ${{ needs.validate-docs.result }}"
466429 echo "- Benchmarks: ${{ needs.benchmark.result }}"
467430 echo "- Build: ${{ needs.build.result }}"
468431 echo "- Publish: ${{ needs.publish.result }}"
0 commit comments