@rigour-labs/cli 2.0.0 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -43,17 +43,20 @@ Examples:
43
43
  program
44
44
  .command('check')
45
45
  .description('Run quality gate checks')
46
+ .argument('[files...]', 'Specific files or directories to check')
46
47
  .option('--ci', 'CI mode (minimal output, non-zero exit on fail)')
47
48
  .option('--json', 'Output report in JSON format')
48
49
  .option('-i, --interactive', 'Run in interactive mode with rich output')
49
50
  .addHelpText('after', `
50
51
  Examples:
51
52
  $ rigour check # Run standard check
53
+ $ rigour check ./src # Check only the src directory
54
+ $ rigour check ./src/app.ts # Check only app.ts
52
55
  $ rigour check --interactive # Run with rich, interactive output
53
56
  $ rigour check --ci # Run in CI environment
54
57
  `)
55
- .action(async (options) => {
56
- await (0, check_js_1.checkCommand)(process.cwd(), options);
58
+ .action(async (files, options) => {
59
+ await (0, check_js_1.checkCommand)(process.cwd(), files, options);
57
60
  });
58
61
  program
59
62
  .command('explain')
@@ -3,4 +3,4 @@ export interface CheckOptions {
3
3
  json?: boolean;
4
4
  interactive?: boolean;
5
5
  }
6
- export declare function checkCommand(cwd: string, options?: CheckOptions): Promise<void>;
6
+ export declare function checkCommand(cwd: string, files?: string[], options?: CheckOptions): Promise<void>;
@@ -14,7 +14,7 @@ const EXIT_PASS = 0;
14
14
  const EXIT_FAIL = 1;
15
15
  const EXIT_CONFIG_ERROR = 2;
16
16
  const EXIT_INTERNAL_ERROR = 3;
17
- async function checkCommand(cwd, options = {}) {
17
+ async function checkCommand(cwd, files = [], options = {}) {
18
18
  const configPath = path_1.default.join(cwd, 'rigour.yml');
19
19
  if (!(await fs_extra_1.default.pathExists(configPath))) {
20
20
  if (options.json) {
@@ -33,7 +33,7 @@ async function checkCommand(cwd, options = {}) {
33
33
  console.log(chalk_1.default.blue('Running Rigour checks...\n'));
34
34
  }
35
35
  const runner = new core_1.GateRunner(config);
36
- const report = await runner.run(cwd);
36
+ const report = await runner.run(cwd, files.length > 0 ? files : undefined);
37
37
  // Write machine report
38
38
  const reportPath = path_1.default.join(cwd, config.output.report_path);
39
39
  await fs_extra_1.default.writeJson(reportPath, report, { spaces: 2 });
@@ -1,8 +1,63 @@
1
1
  "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
2
5
  Object.defineProperty(exports, "__esModule", { value: true });
3
6
  const vitest_1 = require("vitest");
7
+ const check_js_1 = require("./commands/check.js");
8
+ const fs_extra_1 = __importDefault(require("fs-extra"));
9
+ const path_1 = __importDefault(require("path"));
4
10
  (0, vitest_1.describe)('CLI Smoke Test', () => {
5
- (0, vitest_1.it)('should pass', async () => {
6
- (0, vitest_1.expect)(true).toBe(true);
11
+ const testDir = path_1.default.join(process.cwd(), 'temp-smoke-test');
12
+ (0, vitest_1.beforeEach)(async () => {
13
+ await fs_extra_1.default.ensureDir(testDir);
14
+ // @ts-ignore
15
+ vitest_1.vi.spyOn(process, 'exit').mockImplementation(() => { });
16
+ });
17
+ (0, vitest_1.afterEach)(async () => {
18
+ await fs_extra_1.default.remove(testDir);
19
+ vitest_1.vi.restoreAllMocks();
20
+ });
21
+ (0, vitest_1.it)('should respect ignore patterns and avoid EPERM', async () => {
22
+ const restrictedDir = path_1.default.join(testDir, '.restricted');
23
+ await fs_extra_1.default.ensureDir(restrictedDir);
24
+ await fs_extra_1.default.writeFile(path_1.default.join(restrictedDir, 'secret.js'), 'TODO: leak');
25
+ await fs_extra_1.default.writeFile(path_1.default.join(testDir, 'rigour.yml'), `
26
+ version: 1
27
+ ignore:
28
+ - ".restricted/**"
29
+ gates:
30
+ forbid_todos: true
31
+ required_files: []
32
+ `);
33
+ // Simulate EPERM by changing permissions
34
+ await fs_extra_1.default.chmod(restrictedDir, 0o000);
35
+ try {
36
+ // We need to mock process.exit or checkCommand should not exit if we want to test it easily
37
+ // For now, we'll just verify it doesn't throw before it would exit (internal logic)
38
+ // But checkCommand calls process.exit(1) on failure.
39
+ // Re-importing checkCommand to ensure it uses the latest core
40
+ await (0, vitest_1.expect)((0, check_js_1.checkCommand)(testDir, [], { ci: true })).resolves.not.toThrow();
41
+ }
42
+ finally {
43
+ await fs_extra_1.default.chmod(restrictedDir, 0o777);
44
+ }
45
+ });
46
+ (0, vitest_1.it)('should check specific files when provided', async () => {
47
+ await fs_extra_1.default.writeFile(path_1.default.join(testDir, 'bad.js'), 'TODO: fixme');
48
+ await fs_extra_1.default.writeFile(path_1.default.join(testDir, 'good.js'), 'console.log("hello")');
49
+ await fs_extra_1.default.writeFile(path_1.default.join(testDir, 'rigour.yml'), `
50
+ version: 1
51
+ gates:
52
+ forbid_todos: true
53
+ required_files: []
54
+ `);
55
+ // If we check ONLY good.js, it should PASS (exit PASS)
56
+ await (0, check_js_1.checkCommand)(testDir, [path_1.default.join(testDir, 'good.js')], { ci: true });
57
+ (0, vitest_1.expect)(process.exit).toHaveBeenCalledWith(0);
58
+ // If we check bad.js, it should FAIL (exit FAIL)
59
+ vitest_1.vi.clearAllMocks();
60
+ await (0, check_js_1.checkCommand)(testDir, [path_1.default.join(testDir, 'bad.js')], { ci: true });
61
+ (0, vitest_1.expect)(process.exit).toHaveBeenCalledWith(1);
7
62
  });
8
63
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rigour-labs/cli",
3
- "version": "2.0.0",
3
+ "version": "2.1.0",
4
4
  "bin": {
5
5
  "rigour": "dist/cli.js"
6
6
  },
@@ -20,7 +20,7 @@
20
20
  "fs-extra": "^11.2.0",
21
21
  "globby": "^14.0.1",
22
22
  "yaml": "^2.8.2",
23
- "@rigour-labs/core": "2.0.0"
23
+ "@rigour-labs/core": "2.1.0"
24
24
  },
25
25
  "devDependencies": {
26
26
  "@types/fs-extra": "^11.0.4",
package/src/cli.ts CHANGED
@@ -42,17 +42,20 @@ Examples:
42
42
  program
43
43
  .command('check')
44
44
  .description('Run quality gate checks')
45
+ .argument('[files...]', 'Specific files or directories to check')
45
46
  .option('--ci', 'CI mode (minimal output, non-zero exit on fail)')
46
47
  .option('--json', 'Output report in JSON format')
47
48
  .option('-i, --interactive', 'Run in interactive mode with rich output')
48
49
  .addHelpText('after', `
49
50
  Examples:
50
51
  $ rigour check # Run standard check
52
+ $ rigour check ./src # Check only the src directory
53
+ $ rigour check ./src/app.ts # Check only app.ts
51
54
  $ rigour check --interactive # Run with rich, interactive output
52
55
  $ rigour check --ci # Run in CI environment
53
56
  `)
54
- .action(async (options: any) => {
55
- await checkCommand(process.cwd(), options);
57
+ .action(async (files: string[], options: any) => {
58
+ await checkCommand(process.cwd(), files, options);
56
59
  });
57
60
 
58
61
  program
@@ -16,7 +16,7 @@ export interface CheckOptions {
16
16
  interactive?: boolean;
17
17
  }
18
18
 
19
- export async function checkCommand(cwd: string, options: CheckOptions = {}) {
19
+ export async function checkCommand(cwd: string, files: string[] = [], options: CheckOptions = {}) {
20
20
  const configPath = path.join(cwd, 'rigour.yml');
21
21
 
22
22
  if (!(await fs.pathExists(configPath))) {
@@ -38,7 +38,7 @@ export async function checkCommand(cwd: string, options: CheckOptions = {}) {
38
38
  }
39
39
 
40
40
  const runner = new GateRunner(config);
41
- const report = await runner.run(cwd);
41
+ const report = await runner.run(cwd, files.length > 0 ? files : undefined);
42
42
 
43
43
  // Write machine report
44
44
  const reportPath = path.join(cwd, config.output.report_path);
package/src/smoke.test.ts CHANGED
@@ -1,7 +1,68 @@
1
- import { describe, it, expect } from 'vitest';
1
+ import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
2
+ import { checkCommand } from './commands/check.js';
3
+ import fs from 'fs-extra';
4
+ import path from 'path';
2
5
 
3
6
  describe('CLI Smoke Test', () => {
4
- it('should pass', async () => {
5
- expect(true).toBe(true);
7
+ const testDir = path.join(process.cwd(), 'temp-smoke-test');
8
+
9
+ beforeEach(async () => {
10
+ await fs.ensureDir(testDir);
11
+ // @ts-ignore
12
+ vi.spyOn(process, 'exit').mockImplementation(() => { });
13
+ });
14
+
15
+ afterEach(async () => {
16
+ await fs.remove(testDir);
17
+ vi.restoreAllMocks();
18
+ });
19
+
20
+ it('should respect ignore patterns and avoid EPERM', async () => {
21
+ const restrictedDir = path.join(testDir, '.restricted');
22
+ await fs.ensureDir(restrictedDir);
23
+ await fs.writeFile(path.join(restrictedDir, 'secret.js'), 'TODO: leak');
24
+
25
+ await fs.writeFile(path.join(testDir, 'rigour.yml'), `
26
+ version: 1
27
+ ignore:
28
+ - ".restricted/**"
29
+ gates:
30
+ forbid_todos: true
31
+ required_files: []
32
+ `);
33
+
34
+ // Simulate EPERM by changing permissions
35
+ await fs.chmod(restrictedDir, 0o000);
36
+
37
+ try {
38
+ // We need to mock process.exit or checkCommand should not exit if we want to test it easily
39
+ // For now, we'll just verify it doesn't throw before it would exit (internal logic)
40
+ // But checkCommand calls process.exit(1) on failure.
41
+
42
+ // Re-importing checkCommand to ensure it uses the latest core
43
+ await expect(checkCommand(testDir, [], { ci: true })).resolves.not.toThrow();
44
+ } finally {
45
+ await fs.chmod(restrictedDir, 0o777);
46
+ }
47
+ });
48
+
49
+ it('should check specific files when provided', async () => {
50
+ await fs.writeFile(path.join(testDir, 'bad.js'), 'TODO: fixme');
51
+ await fs.writeFile(path.join(testDir, 'good.js'), 'console.log("hello")');
52
+ await fs.writeFile(path.join(testDir, 'rigour.yml'), `
53
+ version: 1
54
+ gates:
55
+ forbid_todos: true
56
+ required_files: []
57
+ `);
58
+
59
+ // If we check ONLY good.js, it should PASS (exit PASS)
60
+ await checkCommand(testDir, [path.join(testDir, 'good.js')], { ci: true });
61
+ expect(process.exit).toHaveBeenCalledWith(0);
62
+
63
+ // If we check bad.js, it should FAIL (exit FAIL)
64
+ vi.clearAllMocks();
65
+ await checkCommand(testDir, [path.join(testDir, 'bad.js')], { ci: true });
66
+ expect(process.exit).toHaveBeenCalledWith(1);
6
67
  });
7
68
  });