ci: gate builds on the test suite and automate engine bumps

Runs typecheck and tests on every push and before publishing. A daily
job rebuilds both vendored tarballs from one commit of the engine fork,
verifies a single wasm ends up on disk, and opens a pull request.
This commit is contained in:
alam00000 committed 2026-08-21 12:50:08 +05:30
1 parent aee3e0a65a
commit c72185ed0b
3 files changed
+177 -83

No files matched your search

+3
View File
@@ -29,6 +29,9 @@ jobs:
- name: Install dependencies
run: npm ci
- name: Run tests
run: npm run test:run
- name: Build distribution
run: npm run build
+36
View File
@@ -0,0 +1,36 @@
name: Tests
on:
push:
branches:
- 'main'
pull_request:
workflow_dispatch:
concurrency:
group: tests-${{ github.ref }}
cancel-in-progress: true
jobs:
test:
runs-on: ubuntu-latest
env:
HUSKY: 0
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Typecheck
run: npx tsc --noEmit
- name: Run tests
run: npm run test:run
+138 -83
View File
@@ -1,60 +1,54 @@
name: Update BentoPDF Viewer
name: Update PDF Engine and Viewer
on:
workflow_dispatch:
schedule:
- cron: '17 4 * * *'
permissions:
contents: write
pull-requests: write
concurrency:
group: update-engine
cancel-in-progress: false
env:
FORK_URL: https://github.com/alam00000/bentopdf-pdfium-viewer
HUSKY: 0
jobs:
update-snippet:
update:
runs-on: ubuntu-latest
if: github.repository == 'alam00000/bentopdf'
steps:
- name: Checkout repo
uses: actions/checkout@v4
- name: Read current upstream version marker
id: current-version
- name: Read current upstream marker
id: current
run: |
if [ -f vendor/bentopdf-viewer/.upstream-version ]; then
CUR=$(cat vendor/bentopdf-viewer/.upstream-version)
echo "version=$(cat vendor/bentopdf-viewer/.upstream-version)" >> "$GITHUB_OUTPUT"
else
CUR=""
echo "version=" >> "$GITHUB_OUTPUT"
fi
echo "version=$CUR" >> "$GITHUB_OUTPUT"
- name: Read latest commit from our viewer fork
id: upstream-version
run: |
LATEST=$(git ls-remote https://github.com/alam00000/bentopdf-pdfium-viewer refs/heads/main | cut -c1-12)
echo "version=$LATEST" >> "$GITHUB_OUTPUT"
- name: Read fork HEAD
id: upstream
run: echo "version=$(git ls-remote "$FORK_URL" refs/heads/main | cut -c1-12)" >> "$GITHUB_OUTPUT"
- name: Should update?
id: gate
run: |
if [ "${{ steps.upstream-version.outputs.version }}" = "${{ steps.current-version.outputs.version }}" ]; then
if [ "${{ steps.upstream.outputs.version }}" = "${{ steps.current.outputs.version }}" ]; then
echo "run=false" >> "$GITHUB_OUTPUT"
echo "No upstream version change detected."
echo "Already on ${{ steps.current.outputs.version }}."
else
echo "run=true" >> "$GITHUB_OUTPUT"
echo "Updating from '${{ steps.current-version.outputs.version }}' to '${{ steps.upstream-version.outputs.version }}'"
echo "Updating ${{ steps.current.outputs.version }} -> ${{ steps.upstream.outputs.version }}"
fi
- name: Enable corepack (pnpm)
if: steps.gate.outputs.run == 'true'
run: corepack enable
- name: Prepare workspace
if: steps.gate.outputs.run == 'true'
run: |
mkdir -p vendor/bentopdf-viewer
npm config set cache ./\.npm-cache
- name: Clone our viewer fork
if: steps.gate.outputs.run == 'true'
run: git clone --depth 1 --branch main https://github.com/alam00000/bentopdf-pdfium-viewer ./_fork/bentopdf-pdfium-viewer
- name: Setup Node
if: steps.gate.outputs.run == 'true'
uses: actions/setup-node@v4
@@ -62,82 +56,143 @@ jobs:
node-version: 22
cache: npm
- name: Install upstream deps
- name: Enable corepack (pnpm)
if: steps.gate.outputs.run == 'true'
working-directory: ./_fork/bentopdf-pdfium-viewer
run: pnpm install --no-frozen-lockfile
run: corepack enable
- name: Build snippet
- name: Clone the viewer fork
if: steps.gate.outputs.run == 'true'
working-directory: ./_fork/bentopdf-pdfium-viewer
run: pnpm run build:snippet
run: git clone --depth 1 --branch main "$FORK_URL" ./_fork
- name: Pack snippet tarball
- name: Require a published engine
if: steps.gate.outputs.run == 'true'
working-directory: ./_fork/bentopdf-pdfium-viewer
run: |
npm pack ./viewers/snippet --pack-destination ../../vendor/bentopdf-viewer
ls -l ../../vendor/bentopdf-viewer
test -s ./_fork/packages/pdfium/src/vendor/pdfium.wasm
test -s ./_fork/packages/pdfium/src/vendor/pdfium.js
- name: Sanitize tarball (rename pkg and pin deps)
- name: Pack the engine
if: steps.gate.outputs.run == 'true'
env:
UPSTREAM_VERSION: ${{ steps.upstream-version.outputs.version }}
id: engine
run: |
TARBALL=$(ls vendor/bentopdf-viewer/*.tgz | sort | tail -n1)
set -euo pipefail
SHA=${{ steps.upstream.outputs.version }}
VENDOR=./_fork/packages/pdfium/src/vendor
STAGE=$(mktemp -d)/package
mkdir -p "$STAGE"
cp "$VENDOR/pdfium.js" "$STAGE/editcore.js"
cp "$VENDOR/pdfium.wasm" "$STAGE/editcore.wasm"
cat > "$STAGE/package.json" <<JSON
{
"name": "bentopdf-pdfium",
"version": "0.0.0-$SHA",
"type": "module",
"main": "editcore.js",
"exports": { ".": "./editcore.js", "./editcore.wasm": "./editcore.wasm" },
"license": "AGPL-3.0"
}
JSON
mkdir -p vendor/bentopdf-pdfium
OUT="vendor/bentopdf-pdfium/bentopdf-pdfium-$SHA.tgz"
tar -czf "$OUT" -C "$(dirname "$STAGE")" package
find vendor/bentopdf-pdfium -maxdepth 1 -name 'bentopdf-pdfium*.tgz' ! -name "$(basename "$OUT")" -delete
echo "tarball=$OUT" >> "$GITHUB_OUTPUT"
- name: Build the viewer
if: steps.gate.outputs.run == 'true'
working-directory: ./_fork
run: |
pnpm install --no-frozen-lockfile
pnpm run build:snippet
- name: Pack the viewer without a second engine
if: steps.gate.outputs.run == 'true'
id: viewer
run: |
set -euo pipefail
SHA=${{ steps.upstream.outputs.version }}
WORK=$(mktemp -d)
(cd ./_fork && npm pack ./viewers/snippet --pack-destination "$WORK" >/dev/null)
TMP=$(mktemp -d)
tar -xzf "$TARBALL" -C "$TMP"
PKG="$TMP/package/package.json"
PKG="$PKG" node - <<'NODE'
const fs = require("fs");
const path = process.env.PKG;
const pkg = JSON.parse(fs.readFileSync(path, "utf8"));
pkg.name = "bentopdf-viewer";
pkg.dependencies = pkg.dependencies || {};
// The rollup bundle inlines every @embedpdf/* package, so these
// declared deps would only pull unused copies from upstream npm.
for (const k of Object.keys(pkg.dependencies)) {
if (k.startsWith("@embedpdf/")) delete pkg.dependencies[k];
if (k === "preact") pkg.dependencies[k] = "^10.17.0";
}
fs.writeFileSync(path, JSON.stringify(pkg, null, 2) + "\n");
tar -xzf "$WORK"/*.tgz -C "$TMP"
rm -f "$TMP/package/dist/pdfium.wasm"
PKG="$TMP/package/package.json" node - <<'NODE'
const fs = require('fs');
const p = process.env.PKG;
const pkg = JSON.parse(fs.readFileSync(p, 'utf8'));
pkg.name = 'bentopdf-viewer';
pkg.dependencies = pkg.dependencies || {};
// The rollup bundle inlines every @embedpdf/* package, so these
// declared deps would only pull unused copies from upstream npm.
for (const k of Object.keys(pkg.dependencies)) {
if (k.startsWith('@embedpdf/')) delete pkg.dependencies[k];
if (k === 'preact') pkg.dependencies[k] = '^10.17.0';
}
fs.writeFileSync(p, JSON.stringify(pkg, null, 2) + '\n');
NODE
PKG_VERSION=$(node -p "require('./$TMP/package/package.json').version" 2>/dev/null || node -p "require('$TMP/package/package.json').version")
NEW=vendor/bentopdf-viewer/bentopdf-viewer-${PKG_VERSION}.tgz
tar -czf "$NEW" -C "$TMP" package
# Remove any older snippet tarballs, keep only the new one
find vendor/bentopdf-viewer -maxdepth 1 -name 'bentopdf-viewer-*.tgz' ! -name "$(basename "$NEW")" -delete
rm -rf "$TMP"
ls -l vendor/bentopdf-viewer
mkdir -p vendor/bentopdf-viewer
OUT="vendor/bentopdf-viewer/bentopdf-viewer-$SHA.tgz"
tar -czf "$OUT" -C "$TMP" package
find vendor/bentopdf-viewer -maxdepth 1 -name 'bentopdf-viewer-*.tgz' ! -name "$(basename "$OUT")" -delete
echo "tarball=$OUT" >> "$GITHUB_OUTPUT"
- name: Update package.json dependency path
- name: Point dependencies at the new tarballs
if: steps.gate.outputs.run == 'true'
run: |
TARBALL=$(ls vendor/bentopdf-viewer/bentopdf-viewer-*.tgz | sort | tail -n1)
node -e "const fs=require('fs');const pkg=require('./package.json');const tar=process.argv[1];pkg.dependencies['bentopdf-viewer']='file:'+tar;fs.writeFileSync('package.json',JSON.stringify(pkg,null,2)+'\n');" "$TARBALL"
- name: Refresh lockfile
if: steps.gate.outputs.run == 'true'
run: npm install --package-lock-only --ignore-scripts
- name: Write upstream version marker
if: steps.gate.outputs.run == 'true'
run: |
echo "${{ steps.upstream-version.outputs.version }}" > vendor/bentopdf-viewer/.upstream-version
node -e "
const fs = require('fs');
const pkg = JSON.parse(fs.readFileSync('package.json', 'utf8'));
pkg.dependencies['bentopdf-pdfium'] = 'file:' + process.argv[1];
pkg.dependencies['bentopdf-viewer'] = 'file:' + process.argv[2];
fs.writeFileSync('package.json', JSON.stringify(pkg, null, 2) + '\n');
" "${{ steps.engine.outputs.tarball }}" "${{ steps.viewer.outputs.tarball }}"
- name: Cleanup upstream clone
if: steps.gate.outputs.run == 'true'
run: rm -rf ./_fork
- name: Install and verify one shared engine
if: steps.gate.outputs.run == 'true'
run: |
set -euo pipefail
npm install
test -s node_modules/bentopdf-pdfium/editcore.wasm
if find node_modules/bentopdf-viewer -name '*.wasm' | grep -q .; then
echo "::error::viewer package still ships a wasm; the engine would be duplicated"
exit 1
fi
if ! grep -q "bentopdf-pdfium/editcore.wasm" src/js/logic/edit-pdf-page.ts; then
echo "::error::the PDF editor no longer points at the shared engine"
exit 1
fi
echo "engine sha256: $(sha256sum node_modules/bentopdf-pdfium/editcore.wasm | cut -c1-16)"
- name: Typecheck and test
if: steps.gate.outputs.run == 'true'
run: |
npx tsc --noEmit
npm run test:run
- name: Write upstream marker
if: steps.gate.outputs.run == 'true'
run: |
echo "${{ steps.upstream.outputs.version }}" > vendor/bentopdf-viewer/.upstream-version
echo "${{ steps.upstream.outputs.version }}" > vendor/bentopdf-pdfium/.upstream-version
- name: Create Pull Request
if: steps.gate.outputs.run == 'true'
uses: peter-evans/create-pull-request@v6
with:
commit-message: "build(deps): bump bentopdf-viewer from ${{ steps.current-version.outputs.version }} to ${{ steps.upstream-version.outputs.version }}"
title: "build(deps): bump bentopdf-viewer from ${{ steps.current-version.outputs.version }} to ${{ steps.upstream-version.outputs.version }}"
commit-message: 'build(deps): bump PDF engine and viewer to ${{ steps.upstream.outputs.version }}'
title: 'build(deps): bump PDF engine and viewer to ${{ steps.upstream.outputs.version }}'
body: |
- Build snippet from the BentoPDF viewer fork via `pnpm run build:snippet`
- Pack tarball into `vendor/bentopdf-viewer/` and point dependency to it
- Refresh package-lock.json
branch: chore/update-bentopdf-viewer
Both vendored packages built from one clone of the viewer fork at
`${{ steps.upstream.outputs.version }}`, so the text editor and the
PDF editor run the same engine.
- `bentopdf-pdfium` — the engine wasm, packed from the fork's published `src/vendor`
- `bentopdf-viewer` — the snippet bundle, packed **without** `dist/pdfium.wasm`
The viewer loads the shared engine through `EmbedPDF.init({ wasmUrl })`.
CI verified a single wasm on disk, typecheck, and the test suite.
branch: chore/update-pdf-engine
delete-branch: true