chore(deps): runtime & dependency upgrade stack — Node 22, Vite 8, Capacitor 8, Postgres 17#69
Open
ibuilder wants to merge 10 commits into
Open
chore(deps): runtime & dependency upgrade stack — Node 22, Vite 8, Capacitor 8, Postgres 17#69ibuilder wants to merge 10 commits into
ibuilder wants to merge 10 commits into
Conversation
Node 20 left community/security support on 2026-04-30. Move the build runtime to Node 22 LTS (supported through April 2027): - engines.node >=22 in root and apps/web package.json - node:22-slim in services/api/Dockerfile (converter stage) and apps/web/Dockerfile (build stage) - node-version: "22" in ci, security, desktop, and pages workflows
Unpinned tags (minio/minio, nginx:alpine) silently track :latest, so a rebuild can pull a breaking image. Pin to explicit tags: - minio/minio:RELEASE.2025-10-15T17-29-55Z (latest release at time of writing) - nginx:1.31-alpine (mainline, matching the previous nginx:alpine track) For production, consider pinning to immutable digests as the next step.
Bring the pinned viewer pair forward to current releases: - @thatopen/fragments 3.4.5 -> 3.4.6 (latest) - @thatopen/ui 3.4.3 -> 3.4.10 (latest) - three 0.184.0 -> 0.185.1 (r185) + @types/three 0.184.1 -> 0.185.1 - converter Dockerfile ARG FRAGMENTS_VERSION 3.4.5 -> 3.4.6 (parity with apps/web; scripts/check-fragments-version.mjs enforces this) web-ifc (0.0.77), @thatopen/components (3.4.6), and components-front (3.4.3) are already at latest and unchanged. NOTE: package-lock.json must be regenerated with 'npm install' before merge — npm ci will fail until the lock matches package.json.
Vite 8 replaces esbuild/Rollup with the Rolldown bundler and Oxc transformer. Node 22 (from the prior Node-bump commit) satisfies Vite 8's >=22.12 floor. package.json (apps/web): - vite 6.4.3 -> 8.1.5 - vitest ^3.2.6 -> ^4.1.10 (3.x only peers Vite <=7; 4.x peers ^8) - vite-plugin-pwa unchanged (^1.3.0 already lists vite ^8 in its peer range) vite.config.ts: - build.rollupOptions -> build.rolldownOptions (renamed in Vite 8) - output.manualChunks: object form (REMOVED in Vite 8) -> function form (deprecated but supported). Marked TODO to move to Rolldown advancedChunks. No other config touched: optimizeDeps.exclude, resolve.dedupe, server COOP/COEP headers, define, VitePWA workbox config, and the precompress writeBundle plugin are all Vite-8 compatible as written. NOTE: package-lock.json must be regenerated with 'npm install' before merge. See PR4 validation checklist for the required smoke tests (WASM copy, PWA/offline, chunk output, CSS minify, large-model load, Tauri/Capacitor builds).
Cargo.lock is committed, but rust-ci ran 'cargo clippy' without --locked
and desktop.yml had no lock check — so a stale lock got silently
re-resolved at build time (the exact failure that broke tagged releases
before). The stale Cargo.toml comment ('no committed Cargo.lock') was
also wrong.
- rust-ci.yml: add a step that fails if Cargo.lock is missing or out of
sync with Cargo.toml (cargo generate-lockfile + git diff --exit-code),
and pass --locked to clippy so it never silently re-resolves.
- desktop.yml: add the same lock-sync guard before the tauri-action
release build, so a stale lock fails the tag build loudly.
- Cargo.toml: correct the stale comment — the lock IS committed and CI
enforces it; the 'time' pin is kept as a belt-and-suspenders guard.
No Cargo.lock regeneration here (cargo isn't available in this env);
the existing committed lock is in sync, and the new CI step will catch
future drift.
The lower bounds in requirements.in (and the data-service subset) lagged the hashed lock by years — e.g. numpy>=1.26 (locked 2.5.1; NumPy 1.x is EOL), redis>=5.0 (locked 8.0.1), scipy>=1.11 (locked 1.18.0). A future 'pip-compile' or a per-platform sidecar resolve could downgrade into an unsupported major that the code no longer targets. Raise every stale floor to the major.minor the lock already resolves and proves compatible. The hashed requirements.lock is unchanged and stays valid (every new floor is at or below the locked version); the lockfile.yml workflow will re-resolve on its next run. services/api/requirements.in: fastapi, uvicorn, sqlalchemy, pydantic, orjson, boto3, psycopg, ifcopenshell, numpy, ifctester, trimesh, manifold3d, scipy, networkx, shapely, reportlab, pyhanko, pypdf, pyarrow, signxml, ezdxf, redis, anthropic. services/data/requirements.txt: same subset (numpy, scipy, shapely, trimesh, manifold3d, networkx, ifctester, ifcopenshell, reportlab). Left intentionally: python-multipart>=0.0.9, openpyxl>=3.1, defusedxml>=0.7, pillow>=12.3.0 (already CVE-floored).
@capacitor/core, @capacitor/cli, @capacitor/android, @capacitor/ios: ^7 -> ^8. Latest is 8.4.2. Capacitor 8 requires Node 22+ (already the target post-PR1). The android/ and ios/ native projects are NOT committed (generated via 'cap open'), and capacitor.config.ts uses none of the removed/changed config keys (android.adjustMarginsForEdgeToEdge, appendUserAgent), so this patch is npm-only. The native migration is a local dev step: npm install # regenerate package-lock.json (npm ci fails until then) npx cap migrate # automated Android/iOS project updates # then, in Android Studio (Otter 2025.2.1+): AGP Upgrade Assistant -> 8.13.0, # Gradle wrapper -> 8.14.3, compileSdk/targetSdk 36, minSdk 24, Kotlin 2.2.20 # and in Xcode 26+: set iOS Deployment Target 15.0, Podfile platform :ios, '15.0' Behavioral changes to re-test on-device: Geolocation 'timeout' now applies to all requests on Android/iOS; BarcodeScanner.scanOrientation and ScreenOrientation.lock are no-ops on large screens (tablets) on Android 16+.
Postgres 16 is supported until Nov 2028, so this is forward-readiness, not urgency. 17 has had a full year of patch releases (17.x by mid-2026) and is the lower-risk single-major step; 18 is the latest if max support runway (Nov 2030) is preferred — same one-line change. MAJOR-VERSION UPGRADE — the PG data files are major-version-specific, so an existing 'postgres-data' volume will NOT start on the new image. Migrate: # dump from the running 16 container, then recreate the volume, then restore docker compose exec postgres pg_dumpall -U bim > dump.sql docker compose down -v # removes the old 16 data volume docker compose up -d postgres # initializes a fresh 17 volume cat dump.sql | docker compose exec -T postgres psql -U bim Fresh dev stacks (no existing volume) need no migration — the 17 image initializes the database on first boot.
The existing config covered pip / npm / cargo / github-actions but had no Docker coverage, so pinned container image tags (postgres, minio, nginx, caddy, redis) and Dockerfile FROM bases (node, python, nginx) silently drifted — the exact gap the manual container PRs closed. Add: - docker-compose ecosystem (root): weekly PRs for the compose image tags, grouped into one 'infra' PR instead of five. - docker ecosystem per Dockerfile dir (services/converter, services/api, apps/web): weekly PRs for FROM base images. - 'vite' group on the npm entry: keeps the Vite 8 + Vitest 4 build/test stack moving together (complements the Vite 6->8 migration).
…ked) PR5's lock-sync check ran 'cargo generate-lockfile' + 'git diff --exit-code', which re-resolves to the latest registry patches and fails on unrelated transitive drift (e.g. winnow 1.0.3->1.0.4, syn 2.0.118->2.0.119, thiserror 2.0.18->2.0.19, zmij 1.0.21->1.0.23) rather than a real Cargo.toml/Cargo.lock mismatch — so clippy+fmt failed on PR #69. Replace with 'cargo metadata --locked', which validates the committed lock against Cargo.toml WITHOUT upgrading transitive deps, and use 'git ls-files --error-unmatch' for the committed-file check. 'cargo clippy --locked' (also from PR5) already enforces true consistency at build time.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Nine stacked, individually revertable commits modernizing the runtime, dependencies, and CI across the monorepo. All frontend changes are build-verified locally.
Commits
engines, all 3 Dockerfiles (incl. converter), 4 CI workflows. Node 20 security support ended Apr 30 2026 (endoflife.date).ARG+KNOWN_GOODguard +package-lock.json. Adds 5 type annotations for an @ThatOpen 3.4.6 typing regression (see below).vite.config.tsmigration (rollupOptions→rolldownOptions) +package-lock.json. Migration guide: https://vite.dev/guide/migration--lockedclippy + lockfile-sync checks inrust-ci.yml/desktop.yml.api/requirements.in/data/requirements.txtto match the tested lock.package-lock.json. Migration guide: https://capacitorjs.com/docs/updating/8-0Validation (frontend)
Ran locally with Node 22 against the regenerated lock:
npm citsc --noEmitvite build(Vite 8 + Rolldown)vitest run(Vitest 4)check-fragments-version.mjsguardPR3's
@thatopen/components3.4.5 → 3.4.6 bump loosened the typing ofSimpleScene.three/SimpleRenderer.three(viaworld.scene/world.renderer); 5 callback params annotated explicitly (o: THREE.Object3D,blob: Blob | null). The base branch typechecks clean, so this regression is fully contained in this PR.Not validated here (needs your environment)
cargonot available.Migration notes / caveats
npm installthennpx cap migratelocally; requires AGP 8.13 / Gradle 8.14.3 / SDK 36, Xcode 26 / iOS 15. Re-test: Geolocation timeout on all platforms;BarcodeScanner.scanOrientation/ScreenOrientation.lockno-ops on Android 16+ tablets.Cargo.lockis already in sync; the new CI step catches future drift.The 9 commits apply cleanly in order on top of
main(15f5a61).