ci: add fast test budget warning

This commit is contained in:
Tam Nhu Tran
2026-04-23 17:25:48 -04:00
parent 1852a9543c
commit 4c677507d0
4 changed files with 57 additions and 12 deletions
+27 -2
View File
@@ -95,6 +95,7 @@ jobs:
needs: [build]
env:
BUN_INSTALL_CACHE_DIR: ${{ github.workspace }}/.bun/install/cache
FAST_TEST_BUDGET_SECONDS: '90'
steps:
- name: Checkout code
uses: actions/checkout@v4
@@ -125,8 +126,32 @@ jobs:
name: dist
path: dist/
- name: Test
run: bun run test:all
- name: Test fast bucket with perf budget
shell: bash
run: |
set -euo pipefail
start_epoch=$(date +%s)
bun run test:fast
end_epoch=$(date +%s)
elapsed_seconds=$((end_epoch - start_epoch))
{
echo "### test:fast perf budget"
echo ""
echo "- Elapsed: ${elapsed_seconds}s"
echo "- Budget: ${FAST_TEST_BUDGET_SECONDS}s"
} >> "$GITHUB_STEP_SUMMARY"
if (( elapsed_seconds > FAST_TEST_BUDGET_SECONDS )); then
echo "::warning::test:fast took ${elapsed_seconds}s (budget ${FAST_TEST_BUDGET_SECONDS}s) - check for undeclared slow tests in scripts/run-test-bucket.js"
echo "- Result: warning emitted. Check for undeclared slow tests in scripts/run-test-bucket.js." >> "$GITHUB_STEP_SUMMARY"
else
echo "- Result: within budget." >> "$GITHUB_STEP_SUMMARY"
fi
- name: Test slow bucket
run: bun run test:slow
- name: Test CLI e2e
env:
@@ -256,12 +256,12 @@ describe('openai proxy daemon lifecycle', () => {
}, 35000);
it('fails when an explicit port is already occupied', async () => {
const occupiedPort = await getPort();
const server = Bun.serve({
port: occupiedPort,
port: 0,
hostname: '127.0.0.1',
fetch: () => new Response('busy'),
});
const occupiedPort = server.port;
try {
const settingsPath = path.join(tempDir, 'occupied-explicit.settings.json');
@@ -298,12 +298,12 @@ describe('openai proxy daemon lifecycle', () => {
});
it('fails when a configured profile port is already occupied', async () => {
const occupiedPort = await getPort();
const server = Bun.serve({
port: occupiedPort,
port: 0,
hostname: '127.0.0.1',
fetch: () => new Response('busy'),
});
const occupiedPort = server.port;
try {
mutateUnifiedConfig((config) => {
@@ -347,12 +347,12 @@ describe('openai proxy daemon lifecycle', () => {
});
it('falls back when a configured shared proxy.port is occupied', async () => {
const occupiedPort = await getPort();
const server = Bun.serve({
port: occupiedPort,
port: 0,
hostname: '127.0.0.1',
fetch: () => new Response('busy'),
});
const occupiedPort = server.port;
try {
mutateUnifiedConfig((config) => {
@@ -396,12 +396,12 @@ describe('openai proxy daemon lifecycle', () => {
it('keeps the existing proxy running if replacement startup fails', async () => {
const firstPort = await getPort();
const occupiedPort = await getPort();
const busyServer = Bun.serve({
port: occupiedPort,
port: 0,
hostname: '127.0.0.1',
fetch: () => new Response('busy'),
});
const occupiedPort = busyServer.port;
try {
const settingsPath = path.join(tempDir, 'rollback.settings.json');
@@ -27,7 +27,12 @@ describe('push ci workflow', () => {
expect(workflow).toContain("cmd: 'bun run lint'");
expect(workflow).toContain("cmd: 'bun run format:check'");
expect(workflow).toContain('run: bun run build:all');
expect(workflow).toContain('run: bun run test:all');
expect(workflow).toContain("FAST_TEST_BUDGET_SECONDS: '90'");
expect(workflow).toContain('name: Test fast bucket with perf budget');
expect(workflow).toContain('bun run test:fast');
expect(workflow).toContain('::warning::test:fast took ${elapsed_seconds}s');
expect(workflow).toContain('scripts/run-test-bucket.js');
expect(workflow).toContain('run: bun run test:slow');
expect(workflow).toContain("CCS_E2E_SKIP_BUILD: '1'");
expect(workflow).toContain('run: bun run test:e2e');
});
@@ -165,6 +165,7 @@ let stripAnthropicRoutingEnv: typeof import('../../../src/utils/shell-executor')
let stripClaudeCodeEnv: typeof import('../../../src/utils/shell-executor').stripClaudeCodeEnv;
let HeadlessExecutor: typeof import('../../../src/delegation/headless-executor').HeadlessExecutor;
let SharedManager: typeof import('../../../src/management/shared-manager').default;
let stopOpenAICompatProxy: typeof import('../../../src/proxy/proxy-daemon').stopOpenAICompatProxy;
beforeAll(async () => {
registerChildProcessMock();
@@ -179,6 +180,9 @@ beforeAll(async () => {
const headless = await import('../../../src/delegation/headless-executor');
HeadlessExecutor = headless.HeadlessExecutor;
const proxyDaemon = await import('../../../src/proxy/proxy-daemon');
stopOpenAICompatProxy = proxyDaemon.stopOpenAICompatProxy;
});
afterAll(() => {
@@ -208,7 +212,14 @@ describe('CLAUDECODE environment stripping', () => {
baselineSighupListeners = process.listeners('SIGHUP');
});
afterEach(() => {
afterEach(async () => {
const tempCcsHome = process.env.CCS_HOME?.startsWith(os.tmpdir())
? process.env.CCS_HOME
: undefined;
if (tempCcsHome) {
await stopOpenAICompatProxy();
}
Object.defineProperty(process, 'platform', { value: originalPlatform });
delete process.env.CLAUDECODE;
delete process.env.claudecode;
@@ -253,6 +264,10 @@ describe('CLAUDECODE environment stripping', () => {
process.removeListener('SIGHUP', listener as (...args: unknown[]) => void);
}
}
if (tempCcsHome) {
fs.rmSync(tempCcsHome, { recursive: true, force: true });
}
});
it('stripClaudeCodeEnv removes CLAUDECODE case-insensitively', () => {