Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ci(): add build.lock #8290

Merged
merged 30 commits into from
Sep 20, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
814abcb
feat(ci): `build.lock` file
ShaMan123 Sep 14, 2022
1272bf0
Update rollup.config.js
ShaMan123 Sep 14, 2022
15edc54
cleanup build logic
ShaMan123 Sep 14, 2022
9292989
feat(ci): await for build
ShaMan123 Sep 14, 2022
a2b5462
add ps-list
ShaMan123 Sep 14, 2022
8e34c29
safegaurd unlock from concurrenct watchers
ShaMan123 Sep 14, 2022
9fe7f92
extract build module
ShaMan123 Sep 14, 2022
d153ef2
modules
ShaMan123 Sep 14, 2022
9b47231
Update buildLock.mjs
ShaMan123 Sep 14, 2022
4450999
Update rollup.config.mjs
ShaMan123 Sep 14, 2022
6312bd4
Update buildLock.mjs
ShaMan123 Sep 14, 2022
dd3e759
hook
ShaMan123 Sep 15, 2022
72f21aa
Update build.mjs
ShaMan123 Sep 15, 2022
dd267f2
refactor(): use cli hooks
ShaMan123 Sep 15, 2022
0fda27f
revert rollup
ShaMan123 Sep 15, 2022
e9bef43
better docs
ShaMan123 Sep 15, 2022
388ff45
Update build.mjs
ShaMan123 Sep 15, 2022
b0e3c21
Update buildLock.mjs
ShaMan123 Sep 15, 2022
4c8fc86
subscriber on error
ShaMan123 Sep 15, 2022
9f8f5de
Update buildLock.mjs
ShaMan123 Sep 15, 2022
fb5bb7c
Update buildLock.mjs
ShaMan123 Sep 15, 2022
9c5b962
prettify
ShaMan123 Sep 15, 2022
684755d
Update buildReporter.mjs
ShaMan123 Sep 15, 2022
3b90811
Update buildReporter.mjs
ShaMan123 Sep 15, 2022
79b754b
Update buildLock.mjs
ShaMan123 Sep 15, 2022
5834360
Revert "Update buildLock.mjs"
ShaMan123 Sep 15, 2022
025a590
Update buildLock.mjs
ShaMan123 Sep 15, 2022
9977b10
Merge branch 'master' into ci-build-lock
ShaMan123 Sep 20, 2022
430dd32
Update CHANGELOG.md
ShaMan123 Sep 20, 2022
608715f
Update CHANGELOG.md
ShaMan123 Sep 20, 2022
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
3 changes: 1 addition & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
# Changelog

# Changelog

## [next]

- ci(): adds a lock file to the repo when build is in progress, makes local testing wait for the build to complete [#8290](https://github.com/fabricjs/fabric.js/pull/8290)
- fix(`WebGLProbe`): regression caused by [#8199](https://github.com/fabricjs/fabric.js/pull/8199), [#8301](https://github.com/fabricjs/fabric.js/pull/8301)
- fix(fabric.utils) added missing import in dom_misc [#8293](https://github.com/fabricjs/fabric.js/pull/8293)
- fix(Object): `extraParam` should not be passed to options [#8295](https://github.com/fabricjs/fabric.js/pull/8295)
Expand Down
19 changes: 19 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@
"nyc": "^15.1.0",
"pixelmatch": "^4.0.2",
"prettier": "2.7.1",
"ps-list": "^8.1.0",
"qunit": "^2.17.2",
"rollup": "^2.75.6",
"rollup-plugin-terser": "^7.0.2",
Expand Down
56 changes: 56 additions & 0 deletions scripts/build.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import cp from 'child_process';
import path from 'node:path';
import process from 'node:process';
import { wd } from './dirname.mjs';

/**
* Handles rollup build
*
* Hooks to build events to create `cli_output/build-lock.json`
* @see https://rollupjs.org/guide/en/#--watchonstart-cmd---watchonbundlestart-cmd---watchonbundleend-cmd---watchonend-cmd---watchonerror-cmd
* @param {*} options
*/
export function build({ watch, fast, input, output } = {}) {
const cmd = [
'rollup',
'-c',
watch ? '--watch' : '',
'--no-watch.clearScreen',
...['onStart', 'onError', 'onEnd'].map(
(type) =>
`--watch.${type} "node ./scripts/buildReporter.mjs ${type
.toLowerCase()
.slice(2)}"`
),
].join(' ');
const processOptions = {
stdio: 'inherit',
shell: true,
cwd: wd,
env: {
...process.env,
MINIFY: Number(!fast),
BUILD_INPUT: input,
BUILD_OUTPUT: output,
BUILD_MIN_OUTPUT:
output && !fast
? path.resolve(
path.dirname(output),
`${path.basename(output, '.js')}.min.js`
)
: undefined,
},
};
if (watch) {
cp.spawn(cmd, processOptions);
} else {
try {
cp.execSync(cmd, processOptions);
} catch (error) {
// minimal logging, no need for stack trace
console.error(error.message);
// inform ci
process.exit(1);
}
}
}
115 changes: 115 additions & 0 deletions scripts/buildLock.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
import chalk from 'chalk';
import fs from 'fs-extra';
import _ from 'lodash';
import moment from 'moment';
import path from 'node:path';
import process from 'node:process';
import psList from 'ps-list';
import { dumpsPath } from './dirname.mjs';

export const lockFile = path.resolve(dumpsPath, 'build-lock.json');

/**
*
* @returns {{start:{pid:number,timestamp:string},error?:{pid:number,timestamp:string}} | null}
*/
function readLockFile() {
return fs.existsSync(lockFile) ? JSON.parse(fs.readFileSync(lockFile)) : null;
}

/**
* For concurrency reasons, the last process to lock is granted permission to unlock.
* If the process died the next process to try to unlock will be granted permission.
*/
export async function unlock() {
const lock = readLockFile();
if (!lock) return;
const lockPID = lock.start.pid;
const hasPermissionToUnlock =
process.pid === lockPID ||
!(await psList()).find(({ pid }) => pid === lockPID);
try {
hasPermissionToUnlock && fs.unlinkSync(lockFile);
} catch (error) {}
}

export function isLocked() {
return fs.existsSync(lockFile);
}

export function awaitBuild() {
return new Promise((resolve) => {
if (isLocked()) {
console.log(chalk.cyanBright('> waiting for build to finish...'));
const watcher = subscribe((locked) => {
if (!locked) {
watcher.close();
resolve();
}
}, 500);
} else {
resolve();
}
});
}

/**
* Subscribe to build start/error/completion.
*
* @param {(locked: boolean, error: boolean) => any} cb
* @param {number} [debounce]
* @returns
*/
export function subscribe(cb, debounce) {
return fs.watch(
path.dirname(lockFile),
_.debounce((type, file) => {
if (file !== path.basename(lockFile)) return;
cb(isLocked(), !!(readLockFile() ?? {}).error);
}, debounce)
);
}

/**
*
* @param {'start'|'error'|'end'} type
* @param {*} [data]
*/
export function report(type, data) {
switch (type) {
case 'start':
fs.writeFileSync(
lockFile,
JSON.stringify(
{
start: {
timestamp: moment().format('YYYY-MM-DD HH:mm:ss'),
pid: process.pid,
},
},
null,
'\t'
)
);
break;
case 'error':
fs.writeFileSync(
lockFile,
JSON.stringify(
{
...readLockFile(),
error: {
timestamp: moment().format('YYYY-MM-DD HH:mm:ss'),
pid: process.pid,
data,
},
},
null,
'\t'
)
);
break;
case 'end':
!readLockFile().error && unlock();
}
}
15 changes: 15 additions & 0 deletions scripts/buildReporter.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/**
* This file is used by `./build` to create `cli_output/build-lock.json`
*/

import { Command } from 'commander';
import { report } from './buildLock.mjs';

const program = new Command();

program
.command('report <type>', { isDefault: true })
.action((type) => {
report(type);
})
.parse(process.argv);
14 changes: 14 additions & 0 deletions scripts/dirname.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import fs from 'fs-extra';
import path from 'node:path';
import { fileURLToPath } from 'node:url';

const __filename = fileURLToPath(import.meta.url);
export const __dirname = path.dirname(__filename);

export const wd = path.resolve(__dirname, '..');
export const dumpsPath = path.resolve(wd, 'cli_output');
export const CLI_CACHE = path.resolve(dumpsPath, 'cli_cache.json');

if (!fs.existsSync(dumpsPath)) {
fs.mkdirSync(dumpsPath);
}
78 changes: 4 additions & 74 deletions scripts/index.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -23,25 +23,15 @@ import _ from 'lodash';
import moment from 'moment';
import path from 'node:path';
import process from 'node:process';
import { fileURLToPath } from 'node:url';
import os from 'os';
import { build } from './build.mjs';
import { awaitBuild } from './buildLock.mjs';
import { CLI_CACHE, wd } from './dirname.mjs';
import { listFiles, transform as transformFiles } from './transform_files.mjs';

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

// import rollup from 'rollup';
// import loadConfigFile from 'rollup/loadConfigFile';

const program = new commander.Command();

const wd = path.resolve(__dirname, '..');
const dumpsPath = path.resolve(wd, 'cli_output');
const CLI_CACHE = path.resolve(dumpsPath, 'cli_cache.json');
const websiteDir = path.resolve(wd, '../fabricjs.com');
if (!fs.existsSync(dumpsPath)) {
fs.mkdirSync(dumpsPath);
}

function execGitCommand(cmd) {
return cp
Expand Down Expand Up @@ -109,67 +99,6 @@ class ICheckbox extends Checkbox {
}
inquirer.registerPrompt('test-selection', ICheckbox);

// async function rollupBuild(options = {}, onComplete) {
// const { options: buildOptions, warnings } = await loadConfigFile(path.resolve(__dirname, '..', 'rollup.config.js'), { format: 'es' });
// warnings.flush();
// if (options.output) {
// buildOptions.output = [options.output];
// }
// if (options.watch) {
// const watcher = rollup.watch(buildOptions);
// watcher.on('END', () => {
// onComplete && onComplete();
// });
// watcher.on('event', ({ result }) => {
// if (result) {
// result.close();
// }
// });
// process.on('beforeExit', () => watcher.close());
// }
// else {
// for (const optionsObj of buildOptions) {
// const bundle = await rollup.rollup(optionsObj);
// await Promise.all(optionsObj.output.map(bundle.write));
// }

// onComplete && onComplete();
// }
// }

function build(options = {}) {
const cmd = ['rollup', '-c', options.watch ? '--watch' : ''].join(' ');
let minDest;
if (options.output && !options.fast) {
const { name, base, ...rest } = path.parse(path.resolve(options.output));
minDest = path.format({ name: `${name}.min`, ...rest });
}
const processOptions = {
stdio: 'inherit',
shell: true,
cwd: wd,
env: {
...process.env,
MINIFY: Number(!options.fast),
BUILD_INPUT: options.input,
BUILD_OUTPUT: options.output,
BUILD_MIN_OUTPUT: minDest,
},
};
if (options.watch) {
cp.spawn(cmd, processOptions);
} else {
try {
cp.execSync(cmd, processOptions);
} catch (error) {
// minimal logging, no need for stack trace
console.error(error.message);
// inform ci
process.exit(1);
}
}
}

function startWebsite() {
if (
JSON.parse(fs.readFileSync(path.resolve(websiteDir, 'package.json')))
Expand Down Expand Up @@ -372,6 +301,7 @@ async function runTestem({
*/
async function test(suite, tests, options = {}) {
let failed = false;
await awaitBuild();
const qunitEnv = {
QUNIT_DEBUG_VISUAL_TESTS: Number(options.debug),
QUNIT_RECREATE_VISUAL_REFS: Number(options.recreate),
Expand Down