Skip to content

Commit 5651001

Browse files
authored
fix: allow Ctrl+C to interrupt build-scss command (#4155)
* fix: allow Ctrl+C to interrupt build-scss command * refactor: after review * test: revert build-scss test to synchronous invocation
1 parent 9e806b3 commit 5651001

3 files changed

Lines changed: 45 additions & 15 deletions

File tree

bin/paragon-scripts.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,10 @@ const COMMANDS = {
265265
* @function executeParagonCommand
266266
*/
267267
(async () => {
268+
process.on('SIGINT', () => {
269+
process.exit(130);
270+
});
271+
268272
const [command, ...commandArgs] = process.argv.slice(2);
269273
const resolvedCommand = commandAliases[command] || command;
270274
const executor = COMMANDS[resolvedCommand];

lib/__tests__/build-scss.test.js

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
const fs = require('fs');
2+
const path = require('path');
3+
const { spawn } = require('child_process');
4+
const os = require('os');
25
const sass = require('sass');
36

47
const buildScssCommand = require('../build-scss');
@@ -135,17 +138,17 @@ describe('buildScssCommand', () => {
135138
);
136139
});
137140

138-
it('should use default arguments when none provided', () => {
139-
buildScssCommand([]);
141+
it('should use default arguments when none provided', async () => {
142+
await buildScssCommand([]);
140143

141144
expect(sass.compile).toHaveBeenCalledWith(
142145
expect.stringContaining('core.scss'),
143146
expect.any(Object),
144147
);
145148
});
146149

147-
it('should exclude core properly', () => {
148-
buildScssCommand(['--excludeCore']);
150+
it('should exclude core properly', async () => {
151+
await buildScssCommand(['--excludeCore']);
149152

150153
expect(sass.compile).not.toHaveBeenCalledWith(
151154
expect.stringContaining('core.scss'),
@@ -158,3 +161,25 @@ describe('buildScssCommand', () => {
158161
);
159162
});
160163
});
164+
165+
describe('SIGINT handling', () => {
166+
it('should exit with code 130 when SIGINT is received during build', async () => {
167+
const child = spawn(process.execPath, [
168+
path.resolve(__dirname, '../../bin/paragon-scripts.js'),
169+
'build-scss',
170+
`--outDir=${path.join(os.tmpdir(), 'build-scss-sigint-test')}`,
171+
], {
172+
cwd: path.resolve(__dirname, '../..'),
173+
stdio: 'ignore',
174+
});
175+
176+
const { code, signal } = await new Promise((resolve) => {
177+
child.on('exit', (exitCode, exitSignal) => resolve({ code: exitCode, signal: exitSignal }));
178+
setTimeout(() => child.kill('SIGINT'), 500);
179+
});
180+
181+
// Process was terminated by SIGINT — either our handler called process.exit(130)
182+
// or default signal handling killed it before the handler was registered
183+
expect(code === 130 || signal === 'SIGINT').toBe(true);
184+
}, 30000);
185+
});

lib/build-scss.js

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -177,18 +177,19 @@ function buildScssCommand(commandArgs) {
177177
});
178178
}
179179

180-
// Theme Variants CSS
181-
fs.readdirSync(themesPath, { withFileTypes: true })
182-
.filter((item) => item.isDirectory())
183-
.forEach((themeDir) => {
184-
compileAndWriteStyleSheets({
185-
name: themeDir.name,
186-
stylesPath: `${themesPath}/${themeDir.name}/index.css`,
187-
outDir,
188-
isThemeVariant: true,
189-
isDefaultThemeVariant: defaultThemeVariants.includes(themeDir.name),
190-
});
180+
// Theme variants CSS
181+
const themeDirs = fs.readdirSync(themesPath, { withFileTypes: true })
182+
.filter((item) => item.isDirectory());
183+
184+
for (const themeDir of themeDirs) {
185+
compileAndWriteStyleSheets({
186+
name: themeDir.name,
187+
stylesPath: `${themesPath}/${themeDir.name}/index.css`,
188+
outDir,
189+
isThemeVariant: true,
190+
isDefaultThemeVariant: defaultThemeVariants.includes(themeDir.name),
191191
});
192+
}
192193
}
193194

194195
module.exports = buildScssCommand;

0 commit comments

Comments
 (0)