@lumpcode/core 0.1.0 → 0.1.1
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 +3 -3
- package/dist/helpers/executeStepsForContextList/main.d.ts.map +1 -1
- package/dist/helpers/getContextStatus/main.d.ts.map +1 -1
- package/dist/index.cjs +206 -107
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +204 -108
- package/dist/index.js.map +1 -1
- package/dist/types/PostCommandExecFn.d.ts +2 -0
- package/dist/types/PostCommandExecFn.d.ts.map +1 -1
- package/dist/utils/commitMessageIncludesMarker/index.d.ts +2 -0
- package/dist/utils/commitMessageIncludesMarker/index.d.ts.map +1 -0
- package/dist/utils/commitMessageIncludesMarker/main.d.ts +3 -0
- package/dist/utils/commitMessageIncludesMarker/main.d.ts.map +1 -0
- package/dist/utils/index.d.ts +2 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/parseGitLogHashBodyRecords/index.d.ts +2 -0
- package/dist/utils/parseGitLogHashBodyRecords/index.d.ts.map +1 -0
- package/dist/utils/parseGitLogHashBodyRecords/main.d.ts +8 -0
- package/dist/utils/parseGitLogHashBodyRecords/main.d.ts.map +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -422,7 +422,7 @@ const steps: Steps = [
|
|
|
422
422
|
|
|
423
423
|
## Context Tracking with Git Commits
|
|
424
424
|
|
|
425
|
-
Lumpcode uses normalized git commit messages to record which contexts have already been processed. Each completed context contributes **exactly one commit** whose
|
|
425
|
+
Lumpcode uses normalized git commit messages to record which contexts have already been processed. Each completed context contributes **exactly one commit** whose message contains the string returned by `gitCommitMessageFn({ context, ... })` (written as the subject; still matched if squash moves it into the body). On every subsequent call to `runLump`, contexts whose marker is already present on a remote branch are skipped so the run only works on what remains. This lets you call `runLump` repeatedly (e.g. in a cron job) and each invocation picks up where the previous one left off, progressively working through the full context list without ever re-processing a context.
|
|
426
426
|
|
|
427
427
|
> If you'd rather not wire up your own scheduler, [@lumpcode/cli](https://www.npmjs.com/package/@lumpcode/cli) ships a built-in daemon (`lumpcode start`) that calls `runLump` on a tick, with concurrent-branch limits and per-lump enable/disable already wired in.
|
|
428
428
|
|
|
@@ -434,7 +434,7 @@ By default, a context named `my_component_ts` produces a commit with the subject
|
|
|
434
434
|
LUMP:my_component_ts
|
|
435
435
|
```
|
|
436
436
|
|
|
437
|
-
You can customize this via the `[gitCommitMessageFn](#gitcommitmessagefn)` parameter. The returned
|
|
437
|
+
You can customize this via the `[gitCommitMessageFn](#gitcommitmessagefn)` parameter. The returned string **must be unique per context** -- it is the only thing tying the commit back to its context. Status matches that string anywhere in the full commit message, as long as it is not a prefix of a longer `[A-Za-z0-9_-]*` token (`foo` does not match `foo-bar`).
|
|
438
438
|
|
|
439
439
|
### Context statuses
|
|
440
440
|
|
|
@@ -458,7 +458,7 @@ A context with `dependsOnContexts` is only eligible when **all** of its listed d
|
|
|
458
458
|
|
|
459
459
|
```bash
|
|
460
460
|
git fetch --all
|
|
461
|
-
git log --remotes=origin --grep="
|
|
461
|
+
git log --remotes=origin -F --grep="LUMP:" --format='%H %s'
|
|
462
462
|
```
|
|
463
463
|
|
|
464
464
|
**Check if a specific context has been processed (any remote ref):**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../../../src/helpers/executeStepsForContextList/main.ts"],"names":[],"mappings":"AAEA,OAAO,EACH,WAAW,EACX,eAAe,EACf,uBAAuB,EACvB,OAAO,EACP,MAAM,EACN,aAAa,EAMb,aAAa,EAChB,MAAM,aAAa,CAAC;AASrB,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../../../src/helpers/executeStepsForContextList/main.ts"],"names":[],"mappings":"AAEA,OAAO,EACH,WAAW,EACX,eAAe,EACf,uBAAuB,EACvB,OAAO,EACP,MAAM,EACN,aAAa,EAMb,aAAa,EAChB,MAAM,aAAa,CAAC;AASrB,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AA0FjD,MAAM,MAAM,gCAAgC,CACxC,CAAC,SAAS,aAAa,GAAG,aAAa,EACvC,EAAE,SAAS,aAAa,GAAG,aAAa,IACxC,QAAQ,CAAC,IAAI,CACb,YAAY,CAAC,CAAC,EAAE,EAAE,CAAC,EACjB,YAAY,GACZ,UAAU,GACV,eAAe,GACf,OAAO,GACP,SAAS,GACT,YAAY,GACZ,iBAAiB,GACjB,oBAAoB,GACpB,kBAAkB,GAClB,oBAAoB,GACpB,aAAa,GACb,kBAAkB,GAClB,qBAAqB,GACrB,0BAA0B,CAC/B,CAAC,GAAG;IACD,WAAW,EAAE,WAAW,CAAC;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,qGAAqG;IACrG,MAAM,CAAC,EAAE,WAAW,CAAC;CACxB,CAAA;AAED,wBAAsB,0BAA0B,CAC5C,CAAC,SAAS,aAAa,GAAG,aAAa,EACvC,EAAE,SAAS,aAAa,GAAG,aAAa,EAC1C,EACE,UAAU,EACV,QAAQ,EACR,aAAa,EACb,WAAW,EACX,eAAe,EACf,kBAAkB,EAClB,gBAAgB,EAChB,kBAAkB,EAClB,WAAW,EACX,KAAK,EACL,OAAO,EACP,gBAAgB,EAChB,UAAU,EACV,mBAAmB,EACnB,wBAAwB,EACxB,MAAM,EAAE,WAAW,EACnB,MAAM,GACT,EAAE,gCAAgC,CAAC,CAAC,EAAE,EAAE,CAAC;;;;;;;;;;;IAkWzC;AAED,MAAM,MAAM,gCAAgC,GAAG,OAAO,CAAC,UAAU,CAAC,OAAO,0BAA0B,CAAC,CAAC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../../../src/helpers/getContextStatus/main.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACnE,OAAO,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAC;
|
|
1
|
+
{"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../../../src/helpers/getContextStatus/main.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACnE,OAAO,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAC;AAUpE,wBAAsB,gBAAgB,CAAC,CAAC,SAAS,aAAa,GAAG,aAAa,EAAE,MAAM,EAAE;IACpF,WAAW,EAAE,MAAM,CAAC;IACpB,kBAAkB,EAAE,kBAAkB,CAAC,CAAC,CAAC,CAAC;IAC1C,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,CAAC,CAAC;IAClB,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC1C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;CACvB,GAAG,OAAO,CAAC,aAAa,CAAC,CAwEzB"}
|
package/dist/index.cjs
CHANGED
|
@@ -3424,6 +3424,40 @@ function parseGitLogHashSubjectLines(stdout) {
|
|
|
3424
3424
|
});
|
|
3425
3425
|
}
|
|
3426
3426
|
|
|
3427
|
+
const GIT_LOG_HASH_BODY_FORMAT = '%x1e%H%x00%B';
|
|
3428
|
+
const RECORD_SEPARATOR = '\x1e';
|
|
3429
|
+
const HASH_MESSAGE_SEPARATOR = '\x00';
|
|
3430
|
+
/** Parses `git log --format='%x1e%H%x00%B'` stdout into commit hash and full-message pairs. */
|
|
3431
|
+
function parseGitLogHashBodyRecords(stdout) {
|
|
3432
|
+
const records = [];
|
|
3433
|
+
for (const record of stdout.split(RECORD_SEPARATOR)) {
|
|
3434
|
+
if (!record)
|
|
3435
|
+
continue;
|
|
3436
|
+
const nul = record.indexOf(HASH_MESSAGE_SEPARATOR);
|
|
3437
|
+
if (nul === -1)
|
|
3438
|
+
continue;
|
|
3439
|
+
const hash = record.slice(0, nul).trim();
|
|
3440
|
+
if (!hash)
|
|
3441
|
+
continue;
|
|
3442
|
+
records.push({
|
|
3443
|
+
hash,
|
|
3444
|
+
message: record.slice(nul + 1),
|
|
3445
|
+
});
|
|
3446
|
+
}
|
|
3447
|
+
return records;
|
|
3448
|
+
}
|
|
3449
|
+
|
|
3450
|
+
const MARKER_CONTINUE = '[A-Za-z0-9_-]';
|
|
3451
|
+
function escapeRegExp(value) {
|
|
3452
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
3453
|
+
}
|
|
3454
|
+
/** True when `marker` occurs in `message` and is not a prefix of a longer `[A-Za-z0-9_-]*` token. */
|
|
3455
|
+
function commitMessageIncludesMarker(message, marker) {
|
|
3456
|
+
if (marker.length === 0)
|
|
3457
|
+
return false;
|
|
3458
|
+
return new RegExp(`${escapeRegExp(marker)}(?!${MARKER_CONTINUE})`).test(message);
|
|
3459
|
+
}
|
|
3460
|
+
|
|
3427
3461
|
/** Node-style `code` from a caught unknown error (e.g. `ENOENT`), or undefined. */
|
|
3428
3462
|
function nodeErrnoCode(error) {
|
|
3429
3463
|
if (error && typeof error === 'object' && 'code' in error) {
|
|
@@ -3766,6 +3800,54 @@ async function collectStepsForContext(params) {
|
|
|
3766
3800
|
return collectedSteps;
|
|
3767
3801
|
}
|
|
3768
3802
|
|
|
3803
|
+
const ABORT_STEP_WALK_MESSAGE = 'Process aborted';
|
|
3804
|
+
function stepWalkAbortedFailure() {
|
|
3805
|
+
return {
|
|
3806
|
+
success: false,
|
|
3807
|
+
data: {
|
|
3808
|
+
message: ABORT_STEP_WALK_MESSAGE,
|
|
3809
|
+
reason: 'stepWalkFailed',
|
|
3810
|
+
},
|
|
3811
|
+
};
|
|
3812
|
+
}
|
|
3813
|
+
function createStepWalkAbortError() {
|
|
3814
|
+
const error = new Error(ABORT_STEP_WALK_MESSAGE);
|
|
3815
|
+
error.name = 'AbortError';
|
|
3816
|
+
return error;
|
|
3817
|
+
}
|
|
3818
|
+
function isStepWalkAbortError(error) {
|
|
3819
|
+
return (typeof error === 'object'
|
|
3820
|
+
&& error !== null
|
|
3821
|
+
&& 'name' in error
|
|
3822
|
+
&& error.name === 'AbortError');
|
|
3823
|
+
}
|
|
3824
|
+
/**
|
|
3825
|
+
* Await user-hook work, but stop waiting once `signal` aborts so the walk can
|
|
3826
|
+
* unwind (locks/teardown). Does not cancel sync busy-loops on the event loop.
|
|
3827
|
+
*/
|
|
3828
|
+
async function awaitUnlessAborted(work, signal) {
|
|
3829
|
+
if (!signal) {
|
|
3830
|
+
return await work;
|
|
3831
|
+
}
|
|
3832
|
+
signal.throwIfAborted();
|
|
3833
|
+
return new Promise((resolve, reject) => {
|
|
3834
|
+
const onAbort = () => {
|
|
3835
|
+
cleanup();
|
|
3836
|
+
reject(createStepWalkAbortError());
|
|
3837
|
+
};
|
|
3838
|
+
const cleanup = () => {
|
|
3839
|
+
signal.removeEventListener('abort', onAbort);
|
|
3840
|
+
};
|
|
3841
|
+
signal.addEventListener('abort', onAbort, { once: true });
|
|
3842
|
+
Promise.resolve(work).then((value) => {
|
|
3843
|
+
cleanup();
|
|
3844
|
+
resolve(value);
|
|
3845
|
+
}, (error) => {
|
|
3846
|
+
cleanup();
|
|
3847
|
+
reject(error);
|
|
3848
|
+
});
|
|
3849
|
+
});
|
|
3850
|
+
}
|
|
3769
3851
|
async function runOptionalGitCommand(input) {
|
|
3770
3852
|
const { label, getCommand, cwd, logger } = input;
|
|
3771
3853
|
try {
|
|
@@ -3825,6 +3907,10 @@ async function executeStepsForContextList({ baseBranch, branchFn, lumpVariables,
|
|
|
3825
3907
|
let runFailure;
|
|
3826
3908
|
try {
|
|
3827
3909
|
for (let i = 0; i < contextList.length; i++) {
|
|
3910
|
+
if (signal?.aborted) {
|
|
3911
|
+
runFailure = stepWalkAbortedFailure();
|
|
3912
|
+
break;
|
|
3913
|
+
}
|
|
3828
3914
|
const context = contextList[i];
|
|
3829
3915
|
logger.info(contextList.length > 1
|
|
3830
3916
|
? `Running context "${context.name}" (${i + 1}/${contextList.length})`
|
|
@@ -3837,127 +3923,137 @@ async function executeStepsForContextList({ baseBranch, branchFn, lumpVariables,
|
|
|
3837
3923
|
const contextRunState = setupResult?.contextRunState || {};
|
|
3838
3924
|
let stepWalkFailure;
|
|
3839
3925
|
async function walkAndExecuteSteps(stepsToExec, currStepIndex) {
|
|
3840
|
-
|
|
3841
|
-
|
|
3842
|
-
|
|
3843
|
-
|
|
3844
|
-
|
|
3845
|
-
|
|
3846
|
-
|
|
3847
|
-
|
|
3848
|
-
|
|
3849
|
-
if (typeof step === 'function') {
|
|
3850
|
-
subSteps =
|
|
3926
|
+
try {
|
|
3927
|
+
for (let stepIndex = 0; stepIndex < stepsToExec.length; stepIndex++) {
|
|
3928
|
+
if (stepWalkFailure) {
|
|
3929
|
+
return;
|
|
3930
|
+
}
|
|
3931
|
+
signal?.throwIfAborted();
|
|
3932
|
+
const step = stepsToExec[stepIndex];
|
|
3933
|
+
const nextCallHeadIndex = [...currStepIndex, stepIndex];
|
|
3934
|
+
const compositeStepIndex = nextCallHeadIndex.length === 1 ? nextCallHeadIndex[0] : nextCallHeadIndex;
|
|
3935
|
+
if (typeof step === 'function' || Array.isArray(step)) {
|
|
3936
|
+
const subSteps = typeof step === 'function'
|
|
3937
|
+
? await awaitUnlessAborted(step({
|
|
3938
|
+
context,
|
|
3939
|
+
stepIndex: compositeStepIndex,
|
|
3940
|
+
contextRunState,
|
|
3941
|
+
lumpVariables,
|
|
3942
|
+
}), signal)
|
|
3943
|
+
: step;
|
|
3944
|
+
await walkAndExecuteSteps(subSteps, nextCallHeadIndex);
|
|
3945
|
+
continue;
|
|
3946
|
+
}
|
|
3947
|
+
logger.verbose(`step ${JSON.stringify(step)}`);
|
|
3948
|
+
const { commandFn = () => null, stepVariables, promptFn, postCommandExecFn, continueOnError, timeoutMillis = 1000 * 60 * 30, } = step;
|
|
3949
|
+
const prompt = promptFn
|
|
3950
|
+
? await awaitUnlessAborted(promptFn({
|
|
3851
3951
|
context,
|
|
3852
3952
|
stepIndex: compositeStepIndex,
|
|
3853
3953
|
contextRunState,
|
|
3854
3954
|
lumpVariables,
|
|
3955
|
+
stepVariables,
|
|
3956
|
+
}), signal)
|
|
3957
|
+
: '';
|
|
3958
|
+
const command = await awaitUnlessAborted(commandFn({
|
|
3959
|
+
context,
|
|
3960
|
+
prompt,
|
|
3961
|
+
stepIndex: compositeStepIndex,
|
|
3962
|
+
contextRunState,
|
|
3963
|
+
lumpVariables,
|
|
3964
|
+
stepVariables,
|
|
3965
|
+
projectRoot,
|
|
3966
|
+
workspacePath,
|
|
3967
|
+
}), signal);
|
|
3968
|
+
let commandResult = '';
|
|
3969
|
+
let commandSucceeded = true;
|
|
3970
|
+
if (command != null) {
|
|
3971
|
+
const { executable, args, env } = command;
|
|
3972
|
+
logger.verbose(`command for prompt ${executable} ${args.join(' ')}`);
|
|
3973
|
+
if (env != null) {
|
|
3974
|
+
logger.verbose(`command env overrides ${JSON.stringify(env)}`);
|
|
3975
|
+
}
|
|
3976
|
+
logger.verbose(`workspacePath ${workspacePath}`);
|
|
3977
|
+
const commandExec = await execBinary({
|
|
3978
|
+
binaryPath: executable,
|
|
3979
|
+
args,
|
|
3980
|
+
timeoutMillis,
|
|
3981
|
+
stdio: ['inherit', 'pipe', 'pipe'],
|
|
3982
|
+
cwd: workspacePath,
|
|
3983
|
+
signal,
|
|
3984
|
+
...(env != null ? { env: { ...process.env, ...env } } : {}),
|
|
3855
3985
|
});
|
|
3986
|
+
logger.verbose(`commandExec ${JSON.stringify(commandExec)}`);
|
|
3987
|
+
if (!commandExec.success) {
|
|
3988
|
+
const aborted = commandExec.data.reason === 'aborted';
|
|
3989
|
+
if (aborted || !continueOnError) {
|
|
3990
|
+
stepWalkFailure = {
|
|
3991
|
+
success: false,
|
|
3992
|
+
data: {
|
|
3993
|
+
message: `Failed to run the command: ${commandExec.data.message}. Command: ${executable} ${args.join(' ')}`,
|
|
3994
|
+
reason: 'stepWalkFailed',
|
|
3995
|
+
},
|
|
3996
|
+
};
|
|
3997
|
+
return;
|
|
3998
|
+
}
|
|
3999
|
+
commandSucceeded = false;
|
|
4000
|
+
commandResult = (commandExec.data.stdout
|
|
4001
|
+
|| commandExec.data.stderr
|
|
4002
|
+
|| commandExec.data.message
|
|
4003
|
+
|| '').toString();
|
|
4004
|
+
logger.verbose(`commandResult ${commandResult}`);
|
|
4005
|
+
}
|
|
4006
|
+
else {
|
|
4007
|
+
commandResult = (commandExec.data.stdout || commandExec.data.stderr || '').toString();
|
|
4008
|
+
logger.verbose(`commandResult ${commandResult}`);
|
|
4009
|
+
}
|
|
4010
|
+
if (commandSucceeded) {
|
|
4011
|
+
const gitStatusAfterCommand = await execAsync(`git status`, { cwd: workspacePath });
|
|
4012
|
+
logger.verbose(`gitStatusCommand ${JSON.stringify(gitStatusAfterCommand.data)}`);
|
|
4013
|
+
}
|
|
3856
4014
|
}
|
|
3857
|
-
|
|
3858
|
-
|
|
3859
|
-
|
|
3860
|
-
await walkAndExecuteSteps(subSteps, nextCallHeadIndex);
|
|
3861
|
-
continue;
|
|
3862
|
-
}
|
|
3863
|
-
logger.verbose(`step ${JSON.stringify(step)}`);
|
|
3864
|
-
const { commandFn = () => null, stepVariables, promptFn, postCommandExecFn, continueOnError, timeoutMillis = 1000 * 60 * 30, } = step;
|
|
3865
|
-
const prompt = promptFn
|
|
3866
|
-
? await promptFn({
|
|
4015
|
+
const historyEntry = {
|
|
4016
|
+
commandResult,
|
|
4017
|
+
commandSucceeded,
|
|
3867
4018
|
context,
|
|
4019
|
+
prompt,
|
|
3868
4020
|
stepIndex: compositeStepIndex,
|
|
3869
4021
|
contextRunState,
|
|
3870
4022
|
lumpVariables,
|
|
3871
4023
|
stepVariables,
|
|
3872
|
-
|
|
3873
|
-
|
|
3874
|
-
|
|
3875
|
-
|
|
3876
|
-
prompt,
|
|
3877
|
-
stepIndex: compositeStepIndex,
|
|
3878
|
-
contextRunState,
|
|
3879
|
-
lumpVariables,
|
|
3880
|
-
stepVariables,
|
|
3881
|
-
projectRoot,
|
|
3882
|
-
workspacePath,
|
|
3883
|
-
});
|
|
3884
|
-
let commandResult = '';
|
|
3885
|
-
let commandSucceeded = true;
|
|
3886
|
-
if (command != null) {
|
|
3887
|
-
const { executable, args, env } = command;
|
|
3888
|
-
logger.verbose(`command for prompt ${executable} ${args.join(' ')}`);
|
|
3889
|
-
if (env != null) {
|
|
3890
|
-
logger.verbose(`command env overrides ${JSON.stringify(env)}`);
|
|
3891
|
-
}
|
|
3892
|
-
logger.verbose(`workspacePath ${workspacePath}`);
|
|
3893
|
-
const commandExec = await execBinary({
|
|
3894
|
-
binaryPath: executable,
|
|
3895
|
-
args,
|
|
3896
|
-
timeoutMillis,
|
|
3897
|
-
stdio: ['inherit', 'pipe', 'pipe'],
|
|
3898
|
-
cwd: workspacePath,
|
|
4024
|
+
projectRoot,
|
|
4025
|
+
};
|
|
4026
|
+
const postCommandExecFnInput = {
|
|
4027
|
+
...historyEntry,
|
|
3899
4028
|
signal,
|
|
3900
|
-
|
|
3901
|
-
});
|
|
3902
|
-
|
|
3903
|
-
|
|
3904
|
-
|
|
3905
|
-
|
|
3906
|
-
|
|
3907
|
-
|
|
3908
|
-
|
|
3909
|
-
|
|
3910
|
-
|
|
3911
|
-
|
|
3912
|
-
};
|
|
3913
|
-
return;
|
|
4029
|
+
};
|
|
4030
|
+
logger.verbose(`context is ${JSON.stringify(context)}`);
|
|
4031
|
+
const keepHistoryFilePath = getKeepHistoryFilePathFn(context) || '';
|
|
4032
|
+
logger.verbose(`keepHistoryFilePath ${keepHistoryFilePath}`);
|
|
4033
|
+
if (!!command && keepHistoryFilePath.length > 0) {
|
|
4034
|
+
const appendResult = await appendHistoryEntry({
|
|
4035
|
+
filePath: keepHistoryFilePath,
|
|
4036
|
+
entry: historyEntry,
|
|
4037
|
+
});
|
|
4038
|
+
if (!appendResult.success) {
|
|
4039
|
+
// TODO: sanitize history appending to avoid this warning for certain commands outputs
|
|
4040
|
+
logger.warn(`Failed to append history entry to ${keepHistoryFilePath}: ${appendResult.data}`);
|
|
3914
4041
|
}
|
|
3915
|
-
commandSucceeded = false;
|
|
3916
|
-
commandResult = (commandExec.data.stdout
|
|
3917
|
-
|| commandExec.data.stderr
|
|
3918
|
-
|| commandExec.data.message
|
|
3919
|
-
|| '').toString();
|
|
3920
|
-
logger.verbose(`commandResult ${commandResult}`);
|
|
3921
|
-
}
|
|
3922
|
-
else {
|
|
3923
|
-
commandResult = (commandExec.data.stdout || commandExec.data.stderr || '').toString();
|
|
3924
|
-
logger.verbose(`commandResult ${commandResult}`);
|
|
3925
|
-
}
|
|
3926
|
-
if (commandSucceeded) {
|
|
3927
|
-
const gitStatusAfterCommand = await execAsync(`git status`, { cwd: workspacePath });
|
|
3928
|
-
logger.verbose(`gitStatusCommand ${JSON.stringify(gitStatusAfterCommand.data)}`);
|
|
3929
4042
|
}
|
|
3930
|
-
|
|
3931
|
-
|
|
3932
|
-
|
|
3933
|
-
|
|
3934
|
-
|
|
3935
|
-
prompt,
|
|
3936
|
-
stepIndex: compositeStepIndex,
|
|
3937
|
-
contextRunState,
|
|
3938
|
-
lumpVariables,
|
|
3939
|
-
stepVariables,
|
|
3940
|
-
projectRoot,
|
|
3941
|
-
};
|
|
3942
|
-
logger.verbose(`context is ${JSON.stringify(context)}`);
|
|
3943
|
-
const keepHistoryFilePath = getKeepHistoryFilePathFn(context) || '';
|
|
3944
|
-
logger.verbose(`keepHistoryFilePath ${keepHistoryFilePath}`);
|
|
3945
|
-
if (!!command && keepHistoryFilePath.length > 0) {
|
|
3946
|
-
const appendResult = await appendHistoryEntry({
|
|
3947
|
-
filePath: keepHistoryFilePath,
|
|
3948
|
-
entry: postCommandExecFnInput,
|
|
3949
|
-
});
|
|
3950
|
-
if (!appendResult.success) {
|
|
3951
|
-
// TODO: sanitize history appending to avoid this warning for certain commands outputs
|
|
3952
|
-
logger.warn(`Failed to append history entry to ${keepHistoryFilePath}: ${appendResult.data}`);
|
|
4043
|
+
if (postCommandExecFn) {
|
|
4044
|
+
const returnedSteps = await awaitUnlessAborted(postCommandExecFn(postCommandExecFnInput), signal);
|
|
4045
|
+
if (returnedSteps != null && returnedSteps.length > 0) {
|
|
4046
|
+
await walkAndExecuteSteps(returnedSteps, nextCallHeadIndex);
|
|
4047
|
+
}
|
|
3953
4048
|
}
|
|
3954
4049
|
}
|
|
3955
|
-
|
|
3956
|
-
|
|
3957
|
-
|
|
3958
|
-
|
|
3959
|
-
|
|
4050
|
+
}
|
|
4051
|
+
catch (error) {
|
|
4052
|
+
if (isStepWalkAbortError(error)) {
|
|
4053
|
+
stepWalkFailure = stepWalkAbortedFailure();
|
|
4054
|
+
return;
|
|
3960
4055
|
}
|
|
4056
|
+
throw error;
|
|
3961
4057
|
}
|
|
3962
4058
|
}
|
|
3963
4059
|
try {
|
|
@@ -4159,13 +4255,13 @@ async function getContextStatus(params) {
|
|
|
4159
4255
|
if (!fetchResult.success)
|
|
4160
4256
|
return 'toDo';
|
|
4161
4257
|
}
|
|
4162
|
-
const logResult = await execAsync(`git log --remotes=${remoteName} -F --grep=${shellSingleQuote(commitMessage)} --format=${shellSingleQuote(
|
|
4258
|
+
const logResult = await execAsync(`git log --remotes=${remoteName} -F --grep=${shellSingleQuote(commitMessage)} --format=${shellSingleQuote(GIT_LOG_HASH_BODY_FORMAT)}`, { cwd: projectRoot });
|
|
4163
4259
|
if (!logResult.success)
|
|
4164
4260
|
return 'toDo';
|
|
4165
4261
|
logger?.verbose(`logResult ${JSON.stringify(logResult.data)}`);
|
|
4166
4262
|
const logResultOutput = logResult.data.stdout || logResult.data.stderr || '';
|
|
4167
|
-
const matchingHashes =
|
|
4168
|
-
.filter((entry) => entry.
|
|
4263
|
+
const matchingHashes = parseGitLogHashBodyRecords(logResultOutput)
|
|
4264
|
+
.filter((entry) => commitMessageIncludesMarker(entry.message, commitMessage))
|
|
4169
4265
|
.map((entry) => entry.hash);
|
|
4170
4266
|
logger?.verbose(`contextName ${contextName}`);
|
|
4171
4267
|
logger?.verbose(`remoteName ${remoteName}`);
|
|
@@ -4384,8 +4480,10 @@ async function runLump(input) {
|
|
|
4384
4480
|
});
|
|
4385
4481
|
}
|
|
4386
4482
|
|
|
4483
|
+
exports.GIT_LOG_HASH_BODY_FORMAT = GIT_LOG_HASH_BODY_FORMAT;
|
|
4387
4484
|
exports.appendHistoryEntry = appendHistoryEntry;
|
|
4388
4485
|
exports.collectStepsForContext = collectStepsForContext;
|
|
4486
|
+
exports.commitMessageIncludesMarker = commitMessageIncludesMarker;
|
|
4389
4487
|
exports.contextStatus = contextStatus;
|
|
4390
4488
|
exports.createConsoleLogger = createConsoleLogger;
|
|
4391
4489
|
exports.defaultGitAddCommandFn = defaultGitAddCommandFn;
|
|
@@ -4408,6 +4506,7 @@ exports.historyFormatFromPath = historyFormatFromPath;
|
|
|
4408
4506
|
exports.isProcessAlive = isProcessAlive;
|
|
4409
4507
|
exports.killProcessTree = killProcessTree;
|
|
4410
4508
|
exports.nodeErrnoCode = nodeErrnoCode;
|
|
4509
|
+
exports.parseGitLogHashBodyRecords = parseGitLogHashBodyRecords;
|
|
4411
4510
|
exports.parseGitLogHashSubjectLines = parseGitLogHashSubjectLines;
|
|
4412
4511
|
exports.pathExists = pathExists;
|
|
4413
4512
|
exports.readHistoryFile = readHistoryFile;
|