@secureci/cli 0.0.0-stage → 0.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/LICENSE +21 -0
- package/README.md +201 -2
- package/dist/cli.js +545 -0
- package/dist/config.js +190 -0
- package/dist/index.js +23 -0
- package/dist/init.js +45 -0
- package/dist/inventory.js +212 -0
- package/dist/parser/pipeline-contract-parser.js +131 -0
- package/dist/parser/pipeline-contract-validator.js +448 -0
- package/dist/parser/validator.js +232 -0
- package/dist/parser/workflow-parser.js +122 -0
- package/dist/report.js +75 -0
- package/dist/runner/action-fetcher.js +431 -0
- package/dist/runner/actions.js +495 -0
- package/dist/runner/builtin-actions.js +484 -0
- package/dist/runner/checkout.js +142 -0
- package/dist/runner/container-runtime.js +374 -0
- package/dist/runner/docker-action.js +179 -0
- package/dist/runner/dry-run.js +142 -0
- package/dist/runner/executor.js +554 -0
- package/dist/runner/expression.js +676 -0
- package/dist/runner/github-context.js +235 -0
- package/dist/runner/hash-files.js +123 -0
- package/dist/runner/job-container.js +322 -0
- package/dist/runner/job-plan.js +138 -0
- package/dist/runner/job-runtime.js +338 -0
- package/dist/runner/node-action.js +278 -0
- package/dist/runner/runner-env.js +303 -0
- package/dist/runner/shell.js +61 -0
- package/dist/runner/steps.js +250 -0
- package/dist/types/index.js +10 -0
- package/dist/utils/key-value.js +33 -0
- package/dist/utils/logger.js +87 -0
- package/dist/utils/repository.js +51 -0
- package/package.json +77 -4
|
@@ -0,0 +1,250 @@
|
|
|
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.executeStep = executeStep;
|
|
37
|
+
exports.executeInJobContainer = executeInJobContainer;
|
|
38
|
+
const fs = __importStar(require("fs"));
|
|
39
|
+
const path = __importStar(require("path"));
|
|
40
|
+
const logger_1 = require("../utils/logger");
|
|
41
|
+
const child_process_1 = require("child_process");
|
|
42
|
+
const util_1 = require("util");
|
|
43
|
+
const expression_1 = require("./expression");
|
|
44
|
+
const container_runtime_1 = require("./container-runtime");
|
|
45
|
+
const runner_env_1 = require("./runner-env");
|
|
46
|
+
const shell_1 = require("./shell");
|
|
47
|
+
const job_runtime_1 = require("./job-runtime");
|
|
48
|
+
const actions_1 = require("./actions");
|
|
49
|
+
const execAsync = (0, util_1.promisify)(child_process_1.exec);
|
|
50
|
+
/**
|
|
51
|
+
* Execute a single step
|
|
52
|
+
*/
|
|
53
|
+
async function executeStep(step, options, runtime, ctx) {
|
|
54
|
+
const startTime = Date.now();
|
|
55
|
+
try {
|
|
56
|
+
const displayName = (0, job_runtime_1.stepDisplayName)(step, ctx);
|
|
57
|
+
// Don't echo a bare run: command before the step runs — it may contain
|
|
58
|
+
// a value the step is about to register with ::add-mask::. Named and
|
|
59
|
+
// uses steps have a safe label.
|
|
60
|
+
if (step.name || step.uses) {
|
|
61
|
+
logger_1.logger.info(`Running: ${displayName}`);
|
|
62
|
+
}
|
|
63
|
+
// Handle 'uses' actions - fetch and execute remote actions
|
|
64
|
+
if (step.uses) {
|
|
65
|
+
return await (0, actions_1.executeAction)(step, options, startTime, runtime, ctx);
|
|
66
|
+
}
|
|
67
|
+
// Handle 'run' commands
|
|
68
|
+
if (step.run) {
|
|
69
|
+
let command = step.run;
|
|
70
|
+
if (ctx) {
|
|
71
|
+
// Resolve all ${{ }} expressions (env/inputs/secrets/steps/
|
|
72
|
+
// github/matrix) against the full step context.
|
|
73
|
+
command = (0, expression_1.substituteExpressions)(command, ctx);
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
// No context available (e.g. action steps run outside a job) -
|
|
77
|
+
// fall back to direct inputs/secrets substitution.
|
|
78
|
+
if (options.inputs) {
|
|
79
|
+
for (const [key, value] of Object.entries(options.inputs)) {
|
|
80
|
+
command = command.replace(new RegExp(`\\$\\{\\{\\s*inputs\\.${key}\\s*\\}\\}`, 'g'), value);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
if (options.secrets) {
|
|
84
|
+
for (const [key, value] of Object.entries(options.secrets)) {
|
|
85
|
+
command = command.replace(new RegExp(`\\$\\{\\{\\s*secrets\\.${key}\\s*\\}\\}`, 'g'), value);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
logger_1.logger.debug(`Executing: ${command}`);
|
|
90
|
+
// ctx.env already combines workflow, job and step `env:` plus
|
|
91
|
+
// `$GITHUB_ENV` additions (see executeWorkflow). Fall back to
|
|
92
|
+
// step.env alone when no context is available.
|
|
93
|
+
const mergedEnv = ctx
|
|
94
|
+
? ctx.env
|
|
95
|
+
: { ...runtime.env, ...(0, expression_1.substituteRecord)(step.env, (0, expression_1.createContext)()) };
|
|
96
|
+
if (runtime.container) {
|
|
97
|
+
return await executeInJobContainer(runtime.container, runtime, step, options, command, startTime, mergedEnv, displayName);
|
|
98
|
+
}
|
|
99
|
+
const files = (0, runner_env_1.createStepFiles)();
|
|
100
|
+
const shell = (0, shell_1.resolveShell)(step.shell ?? runtime.defaults.shell, {
|
|
101
|
+
bashAvailable: (0, job_runtime_1.hostHasBash)()
|
|
102
|
+
});
|
|
103
|
+
const scriptPath = path.join(files.dir, `script${shell.extension}`);
|
|
104
|
+
fs.writeFileSync(scriptPath, command);
|
|
105
|
+
const workingDirectory = step['working-directory'] ?? runtime.defaults.workingDirectory;
|
|
106
|
+
const limit = (0, job_runtime_1.effectiveTimeout)(runtime);
|
|
107
|
+
try {
|
|
108
|
+
const { stdout, stderr } = await execAsync((0, shell_1.shellCommandLine)(shell.template, scriptPath), {
|
|
109
|
+
timeout: limit.ms,
|
|
110
|
+
killSignal: 'SIGKILL',
|
|
111
|
+
cwd: workingDirectory
|
|
112
|
+
? path.resolve(process.cwd(), workingDirectory)
|
|
113
|
+
: process.cwd(),
|
|
114
|
+
env: {
|
|
115
|
+
...(0, runner_env_1.hostBaseEnv)(),
|
|
116
|
+
...runtime.runnerEnv,
|
|
117
|
+
...runtime.actionEnv,
|
|
118
|
+
...mergedEnv,
|
|
119
|
+
PATH: (0, runner_env_1.prependPath)(runtime.path, mergedEnv.PATH ?? process.env.PATH),
|
|
120
|
+
...(0, job_runtime_1.fileCommandEnv)(files)
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
const { outputs } = (0, job_runtime_1.finishStepOutput)(stdout, files, runtime);
|
|
124
|
+
if (stderr) {
|
|
125
|
+
logger_1.logger.warn(stderr.trim());
|
|
126
|
+
}
|
|
127
|
+
logger_1.logger.success(`Step completed: ${displayName}`);
|
|
128
|
+
return {
|
|
129
|
+
step,
|
|
130
|
+
success: true,
|
|
131
|
+
output: stdout,
|
|
132
|
+
outputs,
|
|
133
|
+
duration: Date.now() - startTime
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
catch (execError) {
|
|
137
|
+
const error = execError;
|
|
138
|
+
if (error.killed && limit.ms)
|
|
139
|
+
error.message = limit.message;
|
|
140
|
+
logger_1.logger.error(`Step failed: ${error.message}`);
|
|
141
|
+
const { outputs } = (0, job_runtime_1.finishStepOutput)(error.stdout, files, runtime);
|
|
142
|
+
if (error.stderr) {
|
|
143
|
+
logger_1.logger.error(error.stderr.trim());
|
|
144
|
+
}
|
|
145
|
+
return {
|
|
146
|
+
step,
|
|
147
|
+
success: false,
|
|
148
|
+
error: error.message,
|
|
149
|
+
output: error.stdout,
|
|
150
|
+
outputs,
|
|
151
|
+
duration: Date.now() - startTime
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
finally {
|
|
155
|
+
(0, runner_env_1.cleanupStepFiles)(files);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
// No action to take
|
|
159
|
+
return {
|
|
160
|
+
step,
|
|
161
|
+
success: true,
|
|
162
|
+
output: 'No operation',
|
|
163
|
+
duration: Date.now() - startTime
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
catch (error) {
|
|
167
|
+
return {
|
|
168
|
+
step,
|
|
169
|
+
success: false,
|
|
170
|
+
error: error instanceof Error ? error.message : 'Unknown error',
|
|
171
|
+
duration: Date.now() - startTime
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Execute a `run:` step's command inside the job's container, so files and
|
|
177
|
+
* tools from earlier steps in the job are still there. File commands are
|
|
178
|
+
* exchanged through a per-step directory in the mounted exchange dir.
|
|
179
|
+
*/
|
|
180
|
+
async function executeInJobContainer(container, runtime, step, options, command, startTime, mergedEnv, displayName = (0, job_runtime_1.stepDisplayName)(step)) {
|
|
181
|
+
const { files, containerDir } = (0, job_runtime_1.createContainerStepFiles)(container);
|
|
182
|
+
try {
|
|
183
|
+
const workingDirectory = step['working-directory'] ?? runtime.defaults.workingDirectory;
|
|
184
|
+
const workingDir = workingDirectory
|
|
185
|
+
? path.posix.resolve(container_runtime_1.CONTAINER_WORKDIR, workingDirectory)
|
|
186
|
+
: container_runtime_1.CONTAINER_WORKDIR;
|
|
187
|
+
const shell = (0, shell_1.resolveShell)(step.shell ?? runtime.defaults.shell, {
|
|
188
|
+
bashAvailable: container.bash
|
|
189
|
+
});
|
|
190
|
+
const scriptName = `script${shell.extension}`;
|
|
191
|
+
fs.writeFileSync(path.join(files.dir, scriptName), command, {
|
|
192
|
+
mode: 0o644
|
|
193
|
+
});
|
|
194
|
+
const limit = (0, job_runtime_1.effectiveTimeout)(runtime, options.containerTimeoutMs);
|
|
195
|
+
const result = await container.runtime.exec(container.id, {
|
|
196
|
+
command: (0, job_runtime_1.containerPathPrefix)(runtime) +
|
|
197
|
+
(0, shell_1.shellCommandLine)(shell.template, `${containerDir}/${scriptName}`),
|
|
198
|
+
workingDir,
|
|
199
|
+
env: {
|
|
200
|
+
...(0, job_runtime_1.containerRunnerEnv)(runtime),
|
|
201
|
+
...runtime.actionEnv,
|
|
202
|
+
...mergedEnv,
|
|
203
|
+
...(0, job_runtime_1.fileCommandEnv)(files, containerDir),
|
|
204
|
+
SECURECI_STEP: path.basename(files.dir)
|
|
205
|
+
},
|
|
206
|
+
timeoutMs: limit.ms
|
|
207
|
+
});
|
|
208
|
+
if (result.timedOut) {
|
|
209
|
+
await (0, job_runtime_1.killStepProcesses)(container, path.basename(files.dir));
|
|
210
|
+
}
|
|
211
|
+
const { outputs } = (0, job_runtime_1.finishStepOutput)(result.stdout, files, runtime);
|
|
212
|
+
if (result.stderr) {
|
|
213
|
+
logger_1.logger[result.success ? 'warn' : 'error'](result.stderr.trim());
|
|
214
|
+
}
|
|
215
|
+
if (result.timedOut) {
|
|
216
|
+
logger_1.logger.error(`${limit.message} (container: ${container.runtime.name})`);
|
|
217
|
+
return {
|
|
218
|
+
step,
|
|
219
|
+
success: false,
|
|
220
|
+
error: limit.message,
|
|
221
|
+
output: result.stdout,
|
|
222
|
+
outputs,
|
|
223
|
+
duration: Date.now() - startTime
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
if (!result.success) {
|
|
227
|
+
logger_1.logger.error(`Step failed (container: ${container.runtime.name}, exit code: ${result.exitCode})`);
|
|
228
|
+
return {
|
|
229
|
+
step,
|
|
230
|
+
success: false,
|
|
231
|
+
error: `Command exited with code ${result.exitCode}`,
|
|
232
|
+
output: result.stdout,
|
|
233
|
+
outputs,
|
|
234
|
+
duration: Date.now() - startTime
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
logger_1.logger.success(`Step completed: ${displayName} (container: ${container.runtime.name})`);
|
|
238
|
+
return {
|
|
239
|
+
step,
|
|
240
|
+
success: true,
|
|
241
|
+
output: result.stdout,
|
|
242
|
+
outputs,
|
|
243
|
+
duration: Date.now() - startTime
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
finally {
|
|
247
|
+
(0, runner_env_1.cleanupStepFiles)(files);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
//# sourceMappingURL=steps.js.map
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// TypeScript types for GitHub Actions and Workflows
|
|
3
|
+
// Types are designed to align with the official GitHub Workflow schema:
|
|
4
|
+
// https://json.schemastore.org/github-workflow.json
|
|
5
|
+
// https://json.schemastore.org/github-action.json
|
|
6
|
+
//
|
|
7
|
+
// Note: These types focus on the subset of features needed for local execution.
|
|
8
|
+
// Full schema compliance would include additional properties not relevant for SecureCI's use case.
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseKeyValuePairs = parseKeyValuePairs;
|
|
4
|
+
/**
|
|
5
|
+
* Parse repeatable `key=value` CLI arguments (`--input`, `--secret`) into a
|
|
6
|
+
* record. Splits on the first `=` only, so values may themselves contain `=`
|
|
7
|
+
* (e.g. base64-padded tokens). Empty values are allowed; a missing `=` (unless
|
|
8
|
+
* `fromEnv` is set) or an empty key is an error.
|
|
9
|
+
*/
|
|
10
|
+
function parseKeyValuePairs(pairs, flagName, options = {}) {
|
|
11
|
+
const result = {};
|
|
12
|
+
if (pairs === undefined) {
|
|
13
|
+
return result;
|
|
14
|
+
}
|
|
15
|
+
for (const pair of Array.isArray(pairs) ? pairs : [pairs]) {
|
|
16
|
+
const separator = pair.indexOf('=');
|
|
17
|
+
if (separator === -1 && options.fromEnv && pair !== '') {
|
|
18
|
+
const value = options.fromEnv[pair];
|
|
19
|
+
if (value === undefined) {
|
|
20
|
+
throw new Error(`${flagName} ${pair}: environment variable ${pair} is not set`);
|
|
21
|
+
}
|
|
22
|
+
result[pair] = value;
|
|
23
|
+
continue;
|
|
24
|
+
}
|
|
25
|
+
if (separator <= 0) {
|
|
26
|
+
const shown = options.redact ? '' : ` "${pair}"`;
|
|
27
|
+
throw new Error(`Invalid ${flagName} argument${shown}: expected key=value`);
|
|
28
|
+
}
|
|
29
|
+
result[pair.slice(0, separator)] = pair.slice(separator + 1);
|
|
30
|
+
}
|
|
31
|
+
return result;
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=key-value.js.map
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.logger = exports.LogLevel = void 0;
|
|
7
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
8
|
+
var LogLevel;
|
|
9
|
+
(function (LogLevel) {
|
|
10
|
+
LogLevel[LogLevel["DEBUG"] = 0] = "DEBUG";
|
|
11
|
+
LogLevel[LogLevel["INFO"] = 1] = "INFO";
|
|
12
|
+
LogLevel[LogLevel["WARN"] = 2] = "WARN";
|
|
13
|
+
LogLevel[LogLevel["ERROR"] = 3] = "ERROR";
|
|
14
|
+
})(LogLevel || (exports.LogLevel = LogLevel = {}));
|
|
15
|
+
class Logger {
|
|
16
|
+
constructor() {
|
|
17
|
+
this.level = LogLevel.INFO;
|
|
18
|
+
this.secrets = new Set();
|
|
19
|
+
}
|
|
20
|
+
setLevel(level) {
|
|
21
|
+
this.level = level;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Register secret values so they get masked (replaced with `***`) in any
|
|
25
|
+
* subsequent log output, mirroring GitHub Actions' own secret masking.
|
|
26
|
+
* Short/empty values are ignored to avoid masking incidental characters.
|
|
27
|
+
*/
|
|
28
|
+
registerSecrets(values) {
|
|
29
|
+
if (!values)
|
|
30
|
+
return;
|
|
31
|
+
for (const value of Object.values(values)) {
|
|
32
|
+
if (value && value.length >= 3) {
|
|
33
|
+
this.secrets.add(value);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
clearSecrets() {
|
|
38
|
+
this.secrets.clear();
|
|
39
|
+
}
|
|
40
|
+
mask(text) {
|
|
41
|
+
if (this.secrets.size === 0)
|
|
42
|
+
return text;
|
|
43
|
+
let masked = text;
|
|
44
|
+
for (const secret of this.secrets) {
|
|
45
|
+
masked = masked.split(secret).join('***');
|
|
46
|
+
}
|
|
47
|
+
return masked;
|
|
48
|
+
}
|
|
49
|
+
maskArg(arg) {
|
|
50
|
+
return typeof arg === 'string' ? this.mask(arg) : arg;
|
|
51
|
+
}
|
|
52
|
+
debug(message, ...args) {
|
|
53
|
+
if (this.level <= LogLevel.DEBUG) {
|
|
54
|
+
console.log(chalk_1.default.gray(`[DEBUG] ${this.mask(message)}`), ...args.map((a) => this.maskArg(a)));
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
info(message, ...args) {
|
|
58
|
+
if (this.level <= LogLevel.INFO) {
|
|
59
|
+
console.log(chalk_1.default.blue(`[INFO] ${this.mask(message)}`), ...args.map((a) => this.maskArg(a)));
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
success(message, ...args) {
|
|
63
|
+
if (this.level <= LogLevel.INFO) {
|
|
64
|
+
console.log(chalk_1.default.green(`✓ ${this.mask(message)}`), ...args.map((a) => this.maskArg(a)));
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
warn(message, ...args) {
|
|
68
|
+
if (this.level <= LogLevel.WARN) {
|
|
69
|
+
console.warn(chalk_1.default.yellow(`[WARN] ${this.mask(message)}`), ...args.map((a) => this.maskArg(a)));
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
error(message, ...args) {
|
|
73
|
+
if (this.level <= LogLevel.ERROR) {
|
|
74
|
+
console.error(chalk_1.default.red(`[ERROR] ${this.mask(message)}`), ...args.map((a) => this.maskArg(a)));
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
step(message) {
|
|
78
|
+
console.log(chalk_1.default.cyan(`\n→ ${this.mask(message)}`));
|
|
79
|
+
}
|
|
80
|
+
result(message, success) {
|
|
81
|
+
const icon = success ? '✓' : '✗';
|
|
82
|
+
const color = success ? chalk_1.default.green : chalk_1.default.red;
|
|
83
|
+
console.log(color(`${icon} ${this.mask(message)}`));
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
exports.logger = new Logger();
|
|
87
|
+
//# sourceMappingURL=logger.js.map
|
|
@@ -0,0 +1,51 @@
|
|
|
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.repositoryRoot = repositoryRoot;
|
|
37
|
+
const path = __importStar(require("path"));
|
|
38
|
+
/**
|
|
39
|
+
* The repository root that `./` references in a workflow resolve against
|
|
40
|
+
* (as on GitHub, where they're relative to the repository, not the file):
|
|
41
|
+
* the directory holding `.github/workflows/<file>`, else the current
|
|
42
|
+
* directory.
|
|
43
|
+
*/
|
|
44
|
+
function repositoryRoot(workflowPath) {
|
|
45
|
+
const dir = path.dirname(path.resolve(workflowPath));
|
|
46
|
+
return path.basename(dir) === 'workflows' &&
|
|
47
|
+
path.basename(path.dirname(dir)) === '.github'
|
|
48
|
+
? path.dirname(path.dirname(dir))
|
|
49
|
+
: process.cwd();
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=repository.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,79 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@secureci/cli",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "SecureCI: validate, check against pipeline standards, and run GitHub Actions workflows locally",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"secureci": "./dist/cli.js"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"dist/**/*.js",
|
|
11
|
+
"!dist/**/*.test.js",
|
|
12
|
+
"README.md",
|
|
13
|
+
"LICENSE"
|
|
14
|
+
],
|
|
15
|
+
"scripts": {
|
|
16
|
+
"build": "tsc",
|
|
17
|
+
"test": "vitest run",
|
|
18
|
+
"test:watch": "vitest",
|
|
19
|
+
"test:coverage": "vitest run --coverage",
|
|
20
|
+
"dev": "tsc --watch",
|
|
21
|
+
"lint": "eslint src --ext .ts",
|
|
22
|
+
"format": "prettier --write .",
|
|
23
|
+
"prepare": "npm run build"
|
|
24
|
+
},
|
|
25
|
+
"keywords": [
|
|
26
|
+
"github-actions",
|
|
27
|
+
"workflow",
|
|
28
|
+
"ci",
|
|
29
|
+
"cli",
|
|
30
|
+
"security",
|
|
31
|
+
"policy-as-code",
|
|
32
|
+
"secureci"
|
|
33
|
+
],
|
|
34
|
+
"author": {
|
|
35
|
+
"name": "SecureCI",
|
|
36
|
+
"email": "hello@secure-ci.dev"
|
|
37
|
+
},
|
|
38
|
+
"contributors": [
|
|
39
|
+
{
|
|
40
|
+
"name": "Jabran Rafique",
|
|
41
|
+
"email": "hello@jabran.me"
|
|
42
|
+
}
|
|
43
|
+
],
|
|
44
|
+
"license": "MIT",
|
|
45
|
+
"homepage": "https://www.secure-ci.dev",
|
|
46
|
+
"repository": {
|
|
47
|
+
"type": "git",
|
|
48
|
+
"url": "git+https://github.com/secure-ci/cli.git"
|
|
49
|
+
},
|
|
50
|
+
"bugs": {
|
|
51
|
+
"url": "https://github.com/secure-ci/cli/issues"
|
|
52
|
+
},
|
|
53
|
+
"publishConfig": {
|
|
54
|
+
"access": "public"
|
|
55
|
+
},
|
|
56
|
+
"engines": {
|
|
57
|
+
"node": ">=20"
|
|
58
|
+
},
|
|
59
|
+
"prettier": "@jabraf/prettier",
|
|
60
|
+
"dependencies": {
|
|
61
|
+
"chalk": "^4.1.2",
|
|
62
|
+
"commander": "^11.1.0",
|
|
63
|
+
"yaml": "^2.3.4"
|
|
64
|
+
},
|
|
65
|
+
"devDependencies": {
|
|
66
|
+
"@jabraf/dev": "^0.1.4",
|
|
67
|
+
"@jabraf/prettier": "^3.0.1",
|
|
68
|
+
"@types/node": "^20.10.6",
|
|
69
|
+
"@typescript-eslint/eslint-plugin": "^8.71.1",
|
|
70
|
+
"@typescript-eslint/parser": "^8.71.1",
|
|
71
|
+
"@vitest/coverage-v8": "^4.1.11",
|
|
72
|
+
"eslint": "^8.56.0",
|
|
73
|
+
"typescript": "^5.3.3",
|
|
74
|
+
"vitest": "^4.1.11"
|
|
75
|
+
},
|
|
76
|
+
"volta": {
|
|
77
|
+
"node": "24.0.0"
|
|
78
|
+
}
|
|
79
|
+
}
|