@danielszlaski/envguard 0.1.4 → 0.1.5
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/README.md +42 -0
- package/dist/cli.js +33 -0
- package/dist/cli.js.map +1 -1
- package/dist/commands/install-hook.d.ts +18 -0
- package/dist/commands/install-hook.d.ts.map +1 -0
- package/dist/commands/install-hook.js +148 -0
- package/dist/commands/install-hook.js.map +1 -0
- package/package.json +1 -1
- package/src/cli.ts +33 -0
- package/src/commands/install-hook.ts +128 -0
package/README.md
CHANGED
|
@@ -44,6 +44,43 @@ npx @danielszlaski/envguard scan
|
|
|
44
44
|
|
|
45
45
|
> **Note:** The examples below use `envguard` (short form), which works after installation. If using npx without installation, use `npx @danielszlaski/envguard` instead.
|
|
46
46
|
|
|
47
|
+
### Git Hook Integration (Pre-commit/Pre-push)
|
|
48
|
+
|
|
49
|
+
Automatically run envguard before every commit or push to catch environment variable issues early:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
# Install a pre-commit hook (runs before each commit)
|
|
53
|
+
envguard install-hook
|
|
54
|
+
|
|
55
|
+
# Or install a pre-push hook (runs before each push)
|
|
56
|
+
envguard install-hook --type pre-push
|
|
57
|
+
|
|
58
|
+
# Force overwrite existing hook
|
|
59
|
+
envguard install-hook --force
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Once installed, the hook will automatically run `envguard check` before each commit (or push). If issues are found, the commit/push will be blocked until you fix them.
|
|
63
|
+
|
|
64
|
+
**Bypass the hook** when needed:
|
|
65
|
+
```bash
|
|
66
|
+
git commit --no-verify
|
|
67
|
+
git push --no-verify
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
**Remove the hook:**
|
|
71
|
+
```bash
|
|
72
|
+
envguard uninstall-hook
|
|
73
|
+
|
|
74
|
+
# Or for pre-push hook
|
|
75
|
+
envguard uninstall-hook --type pre-push
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
**How it works:**
|
|
79
|
+
- The hook creates a script in `.git/hooks/pre-commit` (or `pre-push`)
|
|
80
|
+
- Before each commit/push, it runs `envguard check`
|
|
81
|
+
- If issues are found, the operation is blocked
|
|
82
|
+
- Team members need to install the hook individually (it's not tracked in git)
|
|
83
|
+
|
|
47
84
|
### Scan for issues
|
|
48
85
|
|
|
49
86
|
```bash
|
|
@@ -514,6 +551,11 @@ Checking src/lambda/serverless.yml
|
|
|
514
551
|
- `envguard check` - Alias for `scan --ci`
|
|
515
552
|
- `envguard check --strict` - Check with strict mode enabled
|
|
516
553
|
- `envguard check --no-detect-fallbacks` - Check without fallback detection
|
|
554
|
+
- `envguard install-hook` - Install a Git pre-commit hook to run checks automatically
|
|
555
|
+
- `envguard install-hook --type pre-push` - Install a pre-push hook instead
|
|
556
|
+
- `envguard install-hook --force` - Overwrite existing hook if present
|
|
557
|
+
- `envguard uninstall-hook` - Remove the envguard Git hook
|
|
558
|
+
- `envguard uninstall-hook --type pre-push` - Remove the pre-push hook
|
|
517
559
|
|
|
518
560
|
### Strict Mode
|
|
519
561
|
|
package/dist/cli.js
CHANGED
|
@@ -4,6 +4,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
4
4
|
const commander_1 = require("commander");
|
|
5
5
|
const scan_1 = require("./commands/scan");
|
|
6
6
|
const fix_1 = require("./commands/fix");
|
|
7
|
+
const install_hook_1 = require("./commands/install-hook");
|
|
7
8
|
const logger_1 = require("./utils/logger");
|
|
8
9
|
const program = new commander_1.Command();
|
|
9
10
|
program
|
|
@@ -71,5 +72,37 @@ program
|
|
|
71
72
|
process.exit(1);
|
|
72
73
|
}
|
|
73
74
|
});
|
|
75
|
+
program
|
|
76
|
+
.command('install-hook')
|
|
77
|
+
.description('Install a Git hook to run envguard automatically')
|
|
78
|
+
.option('--type <type>', 'Hook type: pre-commit or pre-push (default: pre-commit)')
|
|
79
|
+
.option('--force', 'Overwrite existing hook if present')
|
|
80
|
+
.action(async (cmd) => {
|
|
81
|
+
try {
|
|
82
|
+
await (0, install_hook_1.installHookCommand)({
|
|
83
|
+
type: cmd.type,
|
|
84
|
+
force: cmd.force
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
catch (error) {
|
|
88
|
+
logger_1.Logger.error(`${error}`);
|
|
89
|
+
process.exit(1);
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
program
|
|
93
|
+
.command('uninstall-hook')
|
|
94
|
+
.description('Remove the envguard Git hook')
|
|
95
|
+
.option('--type <type>', 'Hook type: pre-commit or pre-push (default: pre-commit)')
|
|
96
|
+
.action(async (cmd) => {
|
|
97
|
+
try {
|
|
98
|
+
await (0, install_hook_1.uninstallHookCommand)({
|
|
99
|
+
type: cmd.type
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
catch (error) {
|
|
103
|
+
logger_1.Logger.error(`${error}`);
|
|
104
|
+
process.exit(1);
|
|
105
|
+
}
|
|
106
|
+
});
|
|
74
107
|
program.parse();
|
|
75
108
|
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";;;AAEA,yCAAoC;AACpC,0CAA8C;AAC9C,wCAA4C;AAE5C,0DAAmF;AACnF,2CAAwC;AAExC,MAAM,OAAO,GAAG,IAAI,mBAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,UAAU,CAAC;KAChB,WAAW,CAAC,4DAA4D,CAAC;KACzE,OAAO,CAAC,OAAO,CAAC,CAAC;AAEpB,OAAO;KACJ,OAAO,CAAC,MAAM,CAAC;KACf,WAAW,CAAC,2CAA2C,CAAC;KACxD,MAAM,CAAC,MAAM,EAAE,kDAAkD,CAAC;KAClE,MAAM,CAAC,UAAU,EAAE,qFAAqF,CAAC;KACzG,MAAM,CAAC,uBAAuB,EAAE,oEAAoE,CAAC;KACrG,MAAM,CAAC,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,EAAE;IAC7B,IAAI,CAAC;QACH,4EAA4E;QAC5E,MAAM,OAAO,GAAQ;YACnB,EAAE,EAAE,GAAG,CAAC,EAAE;YACV,MAAM,EAAE,GAAG,CAAC,MAAM;SACnB,CAAC;QAEF,kEAAkE;QAClE,mEAAmE;QACnE,MAAM,YAAY,GAAG,OAAO,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,GAAW,EAAE,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,iBAAiB,CAAC,CAAC,CAAC;QACpG,IAAI,YAAY,EAAE,CAAC;YACjB,OAAO,CAAC,eAAe,GAAG,GAAG,CAAC,eAAe,CAAC;QAChD,CAAC;QAED,MAAM,IAAA,kBAAW,EAAC,OAAO,CAAC,CAAC;IAC7B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,eAAM,CAAC,KAAK,CAAC,GAAG,KAAK,EAAE,CAAC,CAAC;QACzB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC,CAAC;AAEL,OAAO;KACJ,OAAO,CAAC,KAAK,CAAC;KACd,WAAW,CAAC,0CAA0C,CAAC;KACvD,MAAM,CAAC,KAAK,IAAI,EAAE;IACjB,IAAI,CAAC;QACH,MAAM,IAAA,gBAAU,GAAE,CAAC;IACrB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,eAAM,CAAC,KAAK,CAAC,GAAG,KAAK,EAAE,CAAC,CAAC;QACzB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC,CAAC;AAEL,OAAO;KACJ,OAAO,CAAC,OAAO,CAAC;KAChB,WAAW,CAAC,wCAAwC,CAAC;KACrD,MAAM,CAAC,UAAU,EAAE,qFAAqF,CAAC;KACzG,MAAM,CAAC,uBAAuB,EAAE,oEAAoE,CAAC;KACrG,MAAM,CAAC,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,EAAE;IAC7B,IAAI,CAAC;QACH,MAAM,OAAO,GAAQ;YACnB,EAAE,EAAE,IAAI;YACR,MAAM,EAAE,GAAG,CAAC,MAAM;SACnB,CAAC;QAEF,kEAAkE;QAClE,MAAM,YAAY,GAAG,OAAO,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,GAAW,EAAE,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,iBAAiB,CAAC,CAAC,CAAC;QACpG,IAAI,YAAY,EAAE,CAAC;YACjB,OAAO,CAAC,eAAe,GAAG,GAAG,CAAC,eAAe,CAAC;QAChD,CAAC;QAED,MAAM,IAAA,kBAAW,EAAC,OAAO,CAAC,CAAC;IAC7B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,eAAM,CAAC,KAAK,CAAC,GAAG,KAAK,EAAE,CAAC,CAAC;QACzB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC,CAAC;AAEL,OAAO;KACJ,OAAO,CAAC,cAAc,CAAC;KACvB,WAAW,CAAC,kDAAkD,CAAC;KAC/D,MAAM,CAAC,eAAe,EAAE,yDAAyD,CAAC;KAClF,MAAM,CAAC,SAAS,EAAE,oCAAoC,CAAC;KACvD,MAAM,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE;IACpB,IAAI,CAAC;QACH,MAAM,IAAA,iCAAkB,EAAC;YACvB,IAAI,EAAE,GAAG,CAAC,IAAI;YACd,KAAK,EAAE,GAAG,CAAC,KAAK;SACjB,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,eAAM,CAAC,KAAK,CAAC,GAAG,KAAK,EAAE,CAAC,CAAC;QACzB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC,CAAC;AAEL,OAAO;KACJ,OAAO,CAAC,gBAAgB,CAAC;KACzB,WAAW,CAAC,8BAA8B,CAAC;KAC3C,MAAM,CAAC,eAAe,EAAE,yDAAyD,CAAC;KAClF,MAAM,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE;IACpB,IAAI,CAAC;QACH,MAAM,IAAA,mCAAoB,EAAC;YACzB,IAAI,EAAE,GAAG,CAAC,IAAI;SACf,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,eAAM,CAAC,KAAK,CAAC,GAAG,KAAK,EAAE,CAAC,CAAC;QACzB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC,CAAC;AAEL,OAAO,CAAC,KAAK,EAAE,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
declare const HOOK_TYPES: readonly ["pre-commit", "pre-push"];
|
|
2
|
+
type HookType = typeof HOOK_TYPES[number];
|
|
3
|
+
interface InstallHookOptions {
|
|
4
|
+
type?: HookType;
|
|
5
|
+
force?: boolean;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Install a Git hook that runs envguard before commits or pushes
|
|
9
|
+
*/
|
|
10
|
+
export declare function installHookCommand(options?: InstallHookOptions): Promise<void>;
|
|
11
|
+
/**
|
|
12
|
+
* Uninstall a Git hook
|
|
13
|
+
*/
|
|
14
|
+
export declare function uninstallHookCommand(options?: {
|
|
15
|
+
type?: HookType;
|
|
16
|
+
}): Promise<void>;
|
|
17
|
+
export {};
|
|
18
|
+
//# sourceMappingURL=install-hook.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"install-hook.d.ts","sourceRoot":"","sources":["../../src/commands/install-hook.ts"],"names":[],"mappings":"AAIA,QAAA,MAAM,UAAU,qCAAsC,CAAC;AACvD,KAAK,QAAQ,GAAG,OAAO,UAAU,CAAC,MAAM,CAAC,CAAC;AAE1C,UAAU,kBAAkB;IAC1B,IAAI,CAAC,EAAE,QAAQ,CAAC;IAChB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CAAC,OAAO,GAAE,kBAAuB,iBA8CxE;AAED;;GAEG;AACH,wBAAsB,oBAAoB,CAAC,OAAO,GAAE;IAAE,IAAI,CAAC,EAAE,QAAQ,CAAA;CAAO,iBA6B3E"}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.installHookCommand = installHookCommand;
|
|
37
|
+
exports.uninstallHookCommand = uninstallHookCommand;
|
|
38
|
+
const fs = __importStar(require("fs"));
|
|
39
|
+
const path = __importStar(require("path"));
|
|
40
|
+
const logger_1 = require("../utils/logger");
|
|
41
|
+
const HOOK_TYPES = ['pre-commit', 'pre-push'];
|
|
42
|
+
/**
|
|
43
|
+
* Install a Git hook that runs envguard before commits or pushes
|
|
44
|
+
*/
|
|
45
|
+
async function installHookCommand(options = {}) {
|
|
46
|
+
const rootDir = process.cwd();
|
|
47
|
+
const gitDir = path.join(rootDir, '.git');
|
|
48
|
+
const hooksDir = path.join(gitDir, 'hooks');
|
|
49
|
+
// Check if this is a git repository
|
|
50
|
+
if (!fs.existsSync(gitDir)) {
|
|
51
|
+
logger_1.Logger.error('Not a git repository. Please run this command in a git repository.');
|
|
52
|
+
logger_1.Logger.blank();
|
|
53
|
+
process.exit(1);
|
|
54
|
+
}
|
|
55
|
+
// Ensure hooks directory exists
|
|
56
|
+
if (!fs.existsSync(hooksDir)) {
|
|
57
|
+
fs.mkdirSync(hooksDir, { recursive: true });
|
|
58
|
+
logger_1.Logger.success('Created .git/hooks directory');
|
|
59
|
+
}
|
|
60
|
+
const hookType = options.type || 'pre-commit';
|
|
61
|
+
const hookPath = path.join(hooksDir, hookType);
|
|
62
|
+
// Check if hook already exists
|
|
63
|
+
if (fs.existsSync(hookPath) && !options.force) {
|
|
64
|
+
logger_1.Logger.warning(`${hookType} hook already exists.`);
|
|
65
|
+
logger_1.Logger.info('Use --force to overwrite the existing hook', true);
|
|
66
|
+
logger_1.Logger.blank();
|
|
67
|
+
process.exit(1);
|
|
68
|
+
}
|
|
69
|
+
// Create the hook script
|
|
70
|
+
const hookContent = generateHookScript(hookType);
|
|
71
|
+
try {
|
|
72
|
+
fs.writeFileSync(hookPath, hookContent, { mode: 0o755 });
|
|
73
|
+
logger_1.Logger.success(`Installed ${hookType} hook successfully!`);
|
|
74
|
+
logger_1.Logger.blank();
|
|
75
|
+
logger_1.Logger.info('The hook will run `envguard check` automatically before each ' +
|
|
76
|
+
(hookType === 'pre-commit' ? 'commit' : 'push'), true);
|
|
77
|
+
logger_1.Logger.info('To bypass the hook, use: git ' +
|
|
78
|
+
(hookType === 'pre-commit' ? 'commit' : 'push') + ' --no-verify', true);
|
|
79
|
+
logger_1.Logger.blank();
|
|
80
|
+
}
|
|
81
|
+
catch (error) {
|
|
82
|
+
logger_1.Logger.error(`Failed to install hook: ${error}`);
|
|
83
|
+
logger_1.Logger.blank();
|
|
84
|
+
process.exit(1);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Uninstall a Git hook
|
|
89
|
+
*/
|
|
90
|
+
async function uninstallHookCommand(options = {}) {
|
|
91
|
+
const rootDir = process.cwd();
|
|
92
|
+
const hookType = options.type || 'pre-commit';
|
|
93
|
+
const hookPath = path.join(rootDir, '.git', 'hooks', hookType);
|
|
94
|
+
if (!fs.existsSync(hookPath)) {
|
|
95
|
+
logger_1.Logger.warning(`No ${hookType} hook found.`);
|
|
96
|
+
logger_1.Logger.blank();
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
// Check if it's our hook
|
|
100
|
+
const hookContent = fs.readFileSync(hookPath, 'utf-8');
|
|
101
|
+
if (!hookContent.includes('envguard check')) {
|
|
102
|
+
logger_1.Logger.warning(`The ${hookType} hook exists but was not created by envguard.`);
|
|
103
|
+
logger_1.Logger.info('Manual removal required if you want to delete it.', true);
|
|
104
|
+
logger_1.Logger.blank();
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
try {
|
|
108
|
+
fs.unlinkSync(hookPath);
|
|
109
|
+
logger_1.Logger.success(`Removed ${hookType} hook successfully!`);
|
|
110
|
+
logger_1.Logger.blank();
|
|
111
|
+
}
|
|
112
|
+
catch (error) {
|
|
113
|
+
logger_1.Logger.error(`Failed to remove hook: ${error}`);
|
|
114
|
+
logger_1.Logger.blank();
|
|
115
|
+
process.exit(1);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Generate the hook script content
|
|
120
|
+
*/
|
|
121
|
+
function generateHookScript(hookType) {
|
|
122
|
+
const hookMessage = hookType === 'pre-commit' ? 'commit' : 'push';
|
|
123
|
+
return `#!/bin/sh
|
|
124
|
+
# EnvGuard ${hookType} hook
|
|
125
|
+
# This hook runs envguard to check environment variables before ${hookMessage}
|
|
126
|
+
# To bypass this hook, use: git ${hookMessage} --no-verify
|
|
127
|
+
|
|
128
|
+
echo "Running EnvGuard environment variable check..."
|
|
129
|
+
|
|
130
|
+
# Run envguard check
|
|
131
|
+
npx envguard check
|
|
132
|
+
|
|
133
|
+
# Capture the exit code
|
|
134
|
+
EXIT_CODE=$?
|
|
135
|
+
|
|
136
|
+
if [ $EXIT_CODE -ne 0 ]; then
|
|
137
|
+
echo ""
|
|
138
|
+
echo "❌ EnvGuard check failed. Please fix the issues above before ${hookMessage}ing."
|
|
139
|
+
echo " Or run: git ${hookMessage} --no-verify to bypass this check."
|
|
140
|
+
echo ""
|
|
141
|
+
exit 1
|
|
142
|
+
fi
|
|
143
|
+
|
|
144
|
+
echo "✓ EnvGuard check passed!"
|
|
145
|
+
exit 0
|
|
146
|
+
`;
|
|
147
|
+
}
|
|
148
|
+
//# sourceMappingURL=install-hook.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"install-hook.js","sourceRoot":"","sources":["../../src/commands/install-hook.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/src/cli.ts
CHANGED
|
@@ -4,6 +4,7 @@ import { Command } from 'commander';
|
|
|
4
4
|
import { scanCommand } from './commands/scan';
|
|
5
5
|
import { fixCommand } from './commands/fix';
|
|
6
6
|
import { checkCommand } from './commands/check';
|
|
7
|
+
import { installHookCommand, uninstallHookCommand } from './commands/install-hook';
|
|
7
8
|
import { Logger } from './utils/logger';
|
|
8
9
|
|
|
9
10
|
const program = new Command();
|
|
@@ -78,4 +79,36 @@ program
|
|
|
78
79
|
}
|
|
79
80
|
});
|
|
80
81
|
|
|
82
|
+
program
|
|
83
|
+
.command('install-hook')
|
|
84
|
+
.description('Install a Git hook to run envguard automatically')
|
|
85
|
+
.option('--type <type>', 'Hook type: pre-commit or pre-push (default: pre-commit)')
|
|
86
|
+
.option('--force', 'Overwrite existing hook if present')
|
|
87
|
+
.action(async (cmd) => {
|
|
88
|
+
try {
|
|
89
|
+
await installHookCommand({
|
|
90
|
+
type: cmd.type,
|
|
91
|
+
force: cmd.force
|
|
92
|
+
});
|
|
93
|
+
} catch (error) {
|
|
94
|
+
Logger.error(`${error}`);
|
|
95
|
+
process.exit(1);
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
program
|
|
100
|
+
.command('uninstall-hook')
|
|
101
|
+
.description('Remove the envguard Git hook')
|
|
102
|
+
.option('--type <type>', 'Hook type: pre-commit or pre-push (default: pre-commit)')
|
|
103
|
+
.action(async (cmd) => {
|
|
104
|
+
try {
|
|
105
|
+
await uninstallHookCommand({
|
|
106
|
+
type: cmd.type
|
|
107
|
+
});
|
|
108
|
+
} catch (error) {
|
|
109
|
+
Logger.error(`${error}`);
|
|
110
|
+
process.exit(1);
|
|
111
|
+
}
|
|
112
|
+
});
|
|
113
|
+
|
|
81
114
|
program.parse();
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import * as fs from 'fs';
|
|
2
|
+
import * as path from 'path';
|
|
3
|
+
import { Logger } from '../utils/logger';
|
|
4
|
+
|
|
5
|
+
const HOOK_TYPES = ['pre-commit', 'pre-push'] as const;
|
|
6
|
+
type HookType = typeof HOOK_TYPES[number];
|
|
7
|
+
|
|
8
|
+
interface InstallHookOptions {
|
|
9
|
+
type?: HookType;
|
|
10
|
+
force?: boolean;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Install a Git hook that runs envguard before commits or pushes
|
|
15
|
+
*/
|
|
16
|
+
export async function installHookCommand(options: InstallHookOptions = {}) {
|
|
17
|
+
const rootDir = process.cwd();
|
|
18
|
+
const gitDir = path.join(rootDir, '.git');
|
|
19
|
+
const hooksDir = path.join(gitDir, 'hooks');
|
|
20
|
+
|
|
21
|
+
// Check if this is a git repository
|
|
22
|
+
if (!fs.existsSync(gitDir)) {
|
|
23
|
+
Logger.error('Not a git repository. Please run this command in a git repository.');
|
|
24
|
+
Logger.blank();
|
|
25
|
+
process.exit(1);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// Ensure hooks directory exists
|
|
29
|
+
if (!fs.existsSync(hooksDir)) {
|
|
30
|
+
fs.mkdirSync(hooksDir, { recursive: true });
|
|
31
|
+
Logger.success('Created .git/hooks directory');
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const hookType = options.type || 'pre-commit';
|
|
35
|
+
const hookPath = path.join(hooksDir, hookType);
|
|
36
|
+
|
|
37
|
+
// Check if hook already exists
|
|
38
|
+
if (fs.existsSync(hookPath) && !options.force) {
|
|
39
|
+
Logger.warning(`${hookType} hook already exists.`);
|
|
40
|
+
Logger.info('Use --force to overwrite the existing hook', true);
|
|
41
|
+
Logger.blank();
|
|
42
|
+
process.exit(1);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Create the hook script
|
|
46
|
+
const hookContent = generateHookScript(hookType);
|
|
47
|
+
|
|
48
|
+
try {
|
|
49
|
+
fs.writeFileSync(hookPath, hookContent, { mode: 0o755 });
|
|
50
|
+
Logger.success(`Installed ${hookType} hook successfully!`);
|
|
51
|
+
Logger.blank();
|
|
52
|
+
Logger.info('The hook will run `envguard check` automatically before each ' +
|
|
53
|
+
(hookType === 'pre-commit' ? 'commit' : 'push'), true);
|
|
54
|
+
Logger.info('To bypass the hook, use: git ' +
|
|
55
|
+
(hookType === 'pre-commit' ? 'commit' : 'push') + ' --no-verify', true);
|
|
56
|
+
Logger.blank();
|
|
57
|
+
} catch (error) {
|
|
58
|
+
Logger.error(`Failed to install hook: ${error}`);
|
|
59
|
+
Logger.blank();
|
|
60
|
+
process.exit(1);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Uninstall a Git hook
|
|
66
|
+
*/
|
|
67
|
+
export async function uninstallHookCommand(options: { type?: HookType } = {}) {
|
|
68
|
+
const rootDir = process.cwd();
|
|
69
|
+
const hookType = options.type || 'pre-commit';
|
|
70
|
+
const hookPath = path.join(rootDir, '.git', 'hooks', hookType);
|
|
71
|
+
|
|
72
|
+
if (!fs.existsSync(hookPath)) {
|
|
73
|
+
Logger.warning(`No ${hookType} hook found.`);
|
|
74
|
+
Logger.blank();
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Check if it's our hook
|
|
79
|
+
const hookContent = fs.readFileSync(hookPath, 'utf-8');
|
|
80
|
+
if (!hookContent.includes('envguard check')) {
|
|
81
|
+
Logger.warning(`The ${hookType} hook exists but was not created by envguard.`);
|
|
82
|
+
Logger.info('Manual removal required if you want to delete it.', true);
|
|
83
|
+
Logger.blank();
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
try {
|
|
88
|
+
fs.unlinkSync(hookPath);
|
|
89
|
+
Logger.success(`Removed ${hookType} hook successfully!`);
|
|
90
|
+
Logger.blank();
|
|
91
|
+
} catch (error) {
|
|
92
|
+
Logger.error(`Failed to remove hook: ${error}`);
|
|
93
|
+
Logger.blank();
|
|
94
|
+
process.exit(1);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Generate the hook script content
|
|
100
|
+
*/
|
|
101
|
+
function generateHookScript(hookType: HookType): string {
|
|
102
|
+
const hookMessage = hookType === 'pre-commit' ? 'commit' : 'push';
|
|
103
|
+
|
|
104
|
+
return `#!/bin/sh
|
|
105
|
+
# EnvGuard ${hookType} hook
|
|
106
|
+
# This hook runs envguard to check environment variables before ${hookMessage}
|
|
107
|
+
# To bypass this hook, use: git ${hookMessage} --no-verify
|
|
108
|
+
|
|
109
|
+
echo "Running EnvGuard environment variable check..."
|
|
110
|
+
|
|
111
|
+
# Run envguard check
|
|
112
|
+
npx envguard check
|
|
113
|
+
|
|
114
|
+
# Capture the exit code
|
|
115
|
+
EXIT_CODE=$?
|
|
116
|
+
|
|
117
|
+
if [ $EXIT_CODE -ne 0 ]; then
|
|
118
|
+
echo ""
|
|
119
|
+
echo "❌ EnvGuard check failed. Please fix the issues above before ${hookMessage}ing."
|
|
120
|
+
echo " Or run: git ${hookMessage} --no-verify to bypass this check."
|
|
121
|
+
echo ""
|
|
122
|
+
exit 1
|
|
123
|
+
fi
|
|
124
|
+
|
|
125
|
+
echo "✓ EnvGuard check passed!"
|
|
126
|
+
exit 0
|
|
127
|
+
`;
|
|
128
|
+
}
|