mirror of https://github.com/garrytan/gstack.git
fix(timeline): validate read limit
This commit is contained in:
parent
cf50443b63
commit
80b0f3c73b
|
|
@ -17,12 +17,22 @@ BRANCH=""
|
||||||
while [[ $# -gt 0 ]]; do
|
while [[ $# -gt 0 ]]; do
|
||||||
case "$1" in
|
case "$1" in
|
||||||
--since) SINCE="$2"; shift 2 ;;
|
--since) SINCE="$2"; shift 2 ;;
|
||||||
--limit) LIMIT="$2"; shift 2 ;;
|
--limit)
|
||||||
|
if [[ $# -lt 2 ]]; then
|
||||||
|
echo "gstack-timeline-read: --limit requires a positive integer" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
LIMIT="$2"; shift 2 ;;
|
||||||
--branch) BRANCH="$2"; shift 2 ;;
|
--branch) BRANCH="$2"; shift 2 ;;
|
||||||
*) shift ;;
|
*) shift ;;
|
||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
|
|
||||||
|
if ! [[ "$LIMIT" =~ ^0*[1-9][0-9]*$ ]]; then
|
||||||
|
echo "gstack-timeline-read: --limit requires a positive integer" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
TIMELINE_FILE="$GSTACK_HOME/projects/$SLUG/timeline.jsonl"
|
TIMELINE_FILE="$GSTACK_HOME/projects/$SLUG/timeline.jsonl"
|
||||||
|
|
||||||
if [ ! -f "$TIMELINE_FILE" ]; then
|
if [ ! -f "$TIMELINE_FILE" ]; then
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { describe, test, expect, beforeEach, afterEach } from 'bun:test';
|
import { describe, test, expect, beforeEach, afterEach } from 'bun:test';
|
||||||
import { execFileSync, execSync, ExecSyncOptionsWithStringEncoding } from 'child_process';
|
import { execFileSync, execSync, ExecSyncOptionsWithStringEncoding, spawnSync } from 'child_process';
|
||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import * as os from 'os';
|
import * as os from 'os';
|
||||||
|
|
@ -56,6 +56,20 @@ function runReadArgs(args: string[] = []): string {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function runReadResult(args: string[] = []): { stdout: string; stderr: string; exitCode: number } {
|
||||||
|
const result = spawnSync(path.join(BIN, 'gstack-timeline-read'), args, {
|
||||||
|
cwd: ROOT,
|
||||||
|
env: { ...process.env, GSTACK_HOME: tmpDir },
|
||||||
|
encoding: 'utf-8',
|
||||||
|
timeout: 15000,
|
||||||
|
});
|
||||||
|
return {
|
||||||
|
stdout: (result.stdout || '').trim(),
|
||||||
|
stderr: (result.stderr || '').trim(),
|
||||||
|
exitCode: result.status ?? 1,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'gstack-timeline-'));
|
tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'gstack-timeline-'));
|
||||||
slugDir = path.join(tmpDir, 'projects');
|
slugDir = path.join(tmpDir, 'projects');
|
||||||
|
|
@ -176,4 +190,16 @@ describe('gstack-timeline-read', () => {
|
||||||
expect(unlimitedEvents).toBe(5);
|
expect(unlimitedEvents).toBe(5);
|
||||||
expect(limitedEvents).toBe(2);
|
expect(limitedEvents).toBe(2);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('rejects malformed --limit values', () => {
|
||||||
|
runLog(JSON.stringify({ skill: 'review', event: 'completed', branch: 'main', outcome: 'approved', ts: '2026-03-28T10:00:00Z' }));
|
||||||
|
|
||||||
|
for (const value of ['1abc', 'nope', '0', '-1', '1.5']) {
|
||||||
|
const result = runReadResult(['--limit', value]);
|
||||||
|
|
||||||
|
expect(result.exitCode).toBe(1);
|
||||||
|
expect(result.stdout).toBe('');
|
||||||
|
expect(result.stderr).toContain('gstack-timeline-read: --limit requires a positive integer');
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue