Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ jobs:
runs-on: ${{ matrix.os }}
strategy:
matrix:
node-version: [18.x, 22.x]
node-version: [18.x, 22.x, 24.x]
os: [ubuntu-latest, macos-latest]
fail-fast: false

Expand Down
3 changes: 3 additions & 0 deletions __tests__/e2e/platforms-semver.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,9 @@ describe('E2E: SCM platform matrix', () => {
);

expect(exitCode).toBe(0);
// On some CI runners (Node 18 + macOS ARM64), child_process stdout
// may not be fully flushed before exit. Guard against empty output.
expect(stdout.trim().length).toBeGreaterThan(0);
const parsed = JSON.parse(stdout.trim());
expect(parsed.dryRun).toBe(true);
expect(parsed.pullRequest).toBeDefined();
Expand Down
9 changes: 9 additions & 0 deletions __tests__/properties/config/config.merger.property.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,15 @@ describe('Property 3: Priority and deep merge', () => {
if (val === undefined) continue;
const currentPath = [...path, key];

// If B has a scalar at this key, it replaces A's entire subtree — skip
if (bObj && key in bObj && bObj[key] !== undefined) {
const bVal = bObj[key];
if (typeof bVal !== 'object' || bVal === null || Array.isArray(bVal)) {
// B's scalar wins over A's value (object or scalar) — nothing to check
continue;
}
}

if (typeof val === 'object' && val !== null && !Array.isArray(val)) {
const bSub = bObj && typeof bObj[key] === 'object' && bObj[key] !== null ? bObj[key] : {};
const mSub = mergedObj && typeof mergedObj[key] === 'object' ? mergedObj[key] : {};
Expand Down
13 changes: 10 additions & 3 deletions __tests__/properties/lock.manager.property.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ const createLockManager = lockManagerMod.exports.createLockManager as
typeof import('../../src/core/lock.manager').createLockManager;

/** Arbitrary for lockTimeoutMs (positive integer, reasonable range) */
const arbLockTimeoutMs = fc.integer({ min: 1, max: 600_000 });
const arbLockTimeoutMs = fc.integer({ min: 100, max: 600_000 });

/** Arbitrary for a positive time delta in ms */
const arbPositiveDelta = fc.integer({ min: 50, max: 300_000 });
Expand Down Expand Up @@ -229,8 +229,11 @@ describe('Feature: operational-hardening, Property 8: Stale Detection по timeo
arbPositiveDelta,
(pid, operationId, command, hostname, lockTimeoutMs, delta) => {
// createdAt is recent enough that timeout is NOT exceeded
// Use lockTimeoutMs / 2 as the age to guarantee the lock is well within the timeout
// window, avoiding race conditions with very small lockTimeoutMs values.
const now = Date.now();
const createdAtMs = now - Math.max(0, lockTimeoutMs - delta); // guarantees now - createdAt < lockTimeoutMs
const age = Math.min(delta, Math.floor(lockTimeoutMs / 2));
const createdAtMs = now - age;
const createdAt = new Date(createdAtMs).toISOString();

const lockData: LockData = { pid, operationId, command, createdAt, hostname, ci: false };
Expand Down Expand Up @@ -350,8 +353,12 @@ describe('Feature: operational-hardening, Property 8: Stale Detection по timeo
arbPositiveDelta,
(pid, operationId, command, hostname, lockTimeoutMs, delta) => {
// Non-stale case in CI — timeout NOT exceeded
// Use lockTimeoutMs / 2 as the age to guarantee the lock is well within the timeout
// window, avoiding race conditions with very small lockTimeoutMs values where
// Date.now() drift between test setup and isTimedOut() check could push age past timeout.
const now = Date.now();
const createdAtMs = now - Math.max(0, lockTimeoutMs - delta);
const age = Math.min(delta, Math.floor(lockTimeoutMs / 2));
const createdAtMs = now - age;
const createdAt = new Date(createdAtMs).toISOString();

const lockData: LockData = { pid, operationId, command, createdAt, hostname, ci: true };
Expand Down
52 changes: 52 additions & 0 deletions examples/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
{
"env": {
"node": true,
"commonjs": true,
"es2020": true
},
"extends": "eslint:recommended",
"parserOptions": {
"ecmaVersion": 2020,
"sourceType": "module"
},
"rules": {
"no-unused-vars": [
"error",
{
"argsIgnorePattern": "^_",
"varsIgnorePattern": "^_"
}
]
},
"overrides": [
{
"files": [
"07-electron-desktop-app/src/renderer/**/*.js"
],
"env": {
"browser": true,
"node": false
}
},
{
"files": [
"09-next-webapp/**/*.js",
"09-next-webapp/**/*.jsx"
],
"parserOptions": {
"ecmaFeatures": {
"jsx": true
}
},
"rules": {
"no-unused-vars": [
"error",
{
"argsIgnorePattern": "^_",
"varsIgnorePattern": "^_|^[A-Z]"
}
]
}
}
]
}
2 changes: 1 addition & 1 deletion examples/04-cli-tool/src/commands/count.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
const fs = require('fs');
const { formatTable, formatPlain } = require('../utils/format');
const { formatTable } = require('../utils/format');

module.exports = {
command: 'count <file>',
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const { createOrder, ORDER_STATUSES, STATUS_TRANSITIONS } = require('./orders.model');
const { createOrder, STATUS_TRANSITIONS } = require('./orders.model');
const productsService = require('../products/products.service');

const orders = new Map();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ function register(data) {

users.set(user.id, user);

const { passwordHash, ...safeUser } = user;
const { passwordHash: _hash, ...safeUser } = user;
return safeUser;
}

Expand All @@ -58,7 +58,7 @@ function getProfile(id) {
if (!user) {
throw Object.assign(new Error('User not found'), { code: 'NOT_FOUND' });
}
const { passwordHash, ...safeUser } = user;
const { passwordHash: _hash, ...safeUser } = user;
return safeUser;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ const ERROR_STATUS_MAP = {
INVALID_TRANSITION: 422
};

function errorHandler(err, req, res, _next) {
// eslint-disable-next-line no-unused-vars
function errorHandler(err, req, res, next) {
const code = err.code || 'INTERNAL_ERROR';
const status = ERROR_STATUS_MAP[code] || 500;
const message = status === 500 ? 'Internal server error' : err.message;
Expand Down
Loading