openvibers/openvibe.sdk Commits

CI: the SDK's suite on Windows and macOS too (#94)

OP OpenVibers committed 17 days ago · fa17cbaa38 · 4 files, +34 −3

* CI: the SDK's suite on Windows and macOS too

Sites and apps built on the SDK run on every OS a developer uses (owner, 2026-10-27: "the shared SDK and API … work
well across multi-platform"). The PostgreSQL and Valkey tests skip themselves there; the rest, PGlite included, runs.

* Windows: LF line endings on every checkout (.gitattributes), POSIX names in the browser-entry check, npm spawned through a shell

The first Windows run: CRLF checkouts made the generated esm/, browser/ and types/ files read as stale and the README
and surface checks miss; Node refuses to spawn npm.cmd without a shell (EINVAL, since the April 2024 fix); the browser
entry check compared backslash paths with slash names.

Changes

ddiff --git a/.gitattributes b/.gitattributes
nnew file mode 100644
iindex 0000000..aa81184
---- /dev/null
++++ b/.gitattributes
@@@ -0,0 +1,10 @@
++# One line ending on every OS: generated files (esm/, browser/, types/) are compared byte for byte with what the
++# scripts write, and Windows checkouts used to turn them into CRLF (2026-10-27, the first Windows CI run).
++* text=auto eol=lf
++*.png binary
++*.jpg binary
++*.gif binary
++*.ico binary
++*.woff2 binary
++*.wasm binary
++*.tgz binary
ddiff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
iindex 900a1ad..c55dd01 100644
---- a/.github/workflows/ci.yml
++++ b/.github/workflows/ci.yml
@@@ -15,3 +15,22 @@ jobs:
# Secret scan (gitleaks) and dependency audit, shared by every OpenVibers repo.
security:
uses: OpenVibers/OpenVibe.Shared/.github/workflows/security.yml@66b76f868ea8228aad7811309eafef3726b036f3
++ # Sites and apps built on the SDK run on every OS a developer uses (owner, 2026-10-27: "the shared SDK and API … work
++ # well across multi-platform"): the whole suite on Windows and macOS too. The PostgreSQL and Valkey tests skip
++ # themselves there (no containers); everything else, the embedded PGlite database included, runs.
++ other-os:
++ name: test (${{ matrix.os }})
++ strategy:
++ fail-fast: false
++ matrix:
++ os: [windows-latest, macos-latest]
++ runs-on: ${{ matrix.os }}
++ steps:
++ - uses: actions/checkout@v4
++ - uses: actions/setup-node@v4
++ with:
++ node-version: 22
++ - run: npm ci --no-audit --no-fund
++ - run: npm test
++ env:
++ OV_ALLOW_SUITE: '1'
ddiff --git a/test/browser-entries.test.js b/test/browser-entries.test.js
iindex e97e006..c0dbea2 100644
---- a/test/browser-entries.test.js
++++ b/test/browser-entries.test.js
@@@ -77,7 +77,7 @@ run([
}
assert.deepEqual(problems, []);
assert.deepEqual(blocked.sort(), ['./account-data', './actor', './blog', './cache', './commerce', './cost', './coupons', './db', './deals', './delivery', './download', './events', './food', './govern', './host', './identity', './inventory', './limits', './live', './news', './node', './notifications', './openre', './placement', './play', './pubsub', './quest', './queue', './resources', './reviews', './run', './runtime', './service', './space', './sso', './storage', './telemetry', './testing', './tips', './trade', './usage', './valkey', './video', './vip', './wiki', './work', './zone']);
-- const rel = [...scanned].map((f) => path.relative(ROOT, f));
++ const rel = [...scanned].map((f) => path.relative(ROOT, f).split(path.sep).join('/')); // the same names on Windows
for (const must of ['browser.js', 'src/core/client.js', 'src/auth/browser.js', 'src/realtime.js', 'src/media.js', 'src/community.js', 'src/bot.js', 'src/modules.js', 'src/registry.js', 'src/jobs.js', 'src/tools.js', 'src/core/form.js', 'src/projects.js', 'browser/openvibe-sdk.mjs']) {
assert.ok(rel.includes(must), `${must} is scanned`);
}
ddiff --git a/test/pack.test.js b/test/pack.test.js
iindex 5f3d89d..74787a4 100644
---- a/test/pack.test.js
++++ b/test/pack.test.js
@@@ -12,6 +12,8 @@ const { run } = require('./helpers');
const ROOT = path.join(__dirname, '..');
const npm = process.platform === 'win32' ? 'npm.cmd' : 'npm';
++// Node refuses to start a .cmd without a shell since the April 2024 fix (EINVAL on Windows).
++const shell = process.platform === 'win32';
const pkg = require('../package.json');
run([
@@@ -19,7 +21,7 @@ run([
const tmp = fs.mkdtempSync(path.join(os.tmpdir(), 'openvibe-sdk-pack-'));
try {
const env = { ...process.env, npm_config_cache: path.join(tmp, '.npm-cache'), npm_config_audit: 'false', npm_config_fund: 'false', npm_config_update_notifier: 'false' };
-- const out = execFileSync(npm, ['pack', '--json', '--pack-destination', tmp], { cwd: ROOT, env, encoding: 'utf8' });
++ const out = execFileSync(npm, ['pack', '--json', '--pack-destination', tmp], { cwd: ROOT, env, encoding: 'utf8', shell });
const info = JSON.parse(out)[0];
const files = info.files.map((f) => f.path);
for (const must of ['package.json', 'index.js', 'browser.js', 'LICENSE', 'README.md', 'CHANGELOG.md', 'src/core/client.js', 'src/jobs.js', 'src/tools.js', 'src/core/form.js', 'src/projects.js', 'src/vip.js', 'esm/vip.mjs', 'types/vip.d.ts', 'src/bot.js', 'esm/bot.mjs', 'types/bot.d.ts', 'src/frame.js', 'esm/frame.mjs', 'types/frame.d.ts', 'src/service/index.js', 'esm/service.mjs', 'types/service.d.ts', 'docs/service.md', 'esm/core.mjs', 'esm/jobs.mjs', 'esm/tools.mjs', 'types/tools.d.ts', 'types/core.d.ts', 'types/contracts.d.ts', 'types/bundle.d.ts', 'src/resources.js', 'esm/resources.mjs', 'types/resources.d.ts', 'browser/openvibe-sdk.mjs']) {
@@@ -30,7 +32,7 @@ run([
const app = path.join(tmp, 'app');
fs.mkdirSync(app);
fs.writeFileSync(path.join(app, 'package.json'), JSON.stringify({ name: 'sdk-consumer', version: '1.0.0', private: true }));
-- execFileSync(npm, ['install', '--offline', '--no-package-lock', path.join(tmp, info.filename)], { cwd: app, env, stdio: 'pipe' });
++ execFileSync(npm, ['install', '--offline', '--no-package-lock', path.join(tmp, info.filename)], { cwd: app, env, stdio: 'pipe', shell });
const subpaths = Object.keys(pkg.exports).filter((s) => s !== './package.json' && !s.endsWith('.mjs')).map((s) => (s === '.' ? 'openvibe-sdk' : `openvibe-sdk/${s.slice(2)}`));
const script = `