mirror of
https://github.com/garrytan/gstack.git
synced 2026-11-05 16:34:00 +01:00
* fix(cso): unblock native runtime qualification (v1.91.28.0) Fixes the qualify-native failures from main run 37345275258: - re-bind promotion evidence for staged runtimes in cold-start tests - give npm a distinct empty global config (npm 11 refuses double-loading) - export /archives and /work through tmpfs-backed local volumes (docker cp cannot read tmpfs), with exec on /work - keep the offline seed process alive - end broker/forwarder tunnels explicitly under Bun - batch gem fetch per platform - wait for run-app's source copy before Rails db:prepare and tests - fix the Python cold fixture and add bin/rails to the Rails cold fixture * fix(cso): bounded 900 s ceiling for preparation dependency commands - PREPARATION_COMMAND_TIMEOUT_MS (900 s) applies only to acquisition and offline dependency commands; everything else keeps COMMAND_TIMEOUT_MS (300 s), and both are cut to the journey deadline - prepared-tree export refusals fail with PREPARED_EXPORT_REJECTED and the helper's fixed reason or errno, never target paths, with no retry - free tests pin the ceiling, its callers, and the rejection parser * Take v1.91.29.0 (1.91.28.0 is claimed by #3032 and #3033) * cso-diff-mode accepts every correct name for the unauthenticated webhook finding
60 lines
5.6 KiB
TypeScript
60 lines
5.6 KiB
TypeScript
import { afterEach, describe, expect, spyOn, test } from 'bun:test';
|
|
import * as fs from 'node:fs';
|
|
import * as os from 'node:os';
|
|
import * as path from 'node:path';
|
|
import { DockerGroup } from '../lib/cso/docker';
|
|
import { DockerVerificationExecutor } from '../lib/cso/verification';
|
|
|
|
const roots:string[]=[];
|
|
afterEach(()=>{for(const root of roots.splice(0))fs.rmSync(root,{recursive:true,force:true});});
|
|
|
|
describe('CSO Rails database verification lifecycle',()=>{
|
|
test('creates fresh multi-database PostgreSQL per phase and prepares every private work tree',async()=>{
|
|
const root=fs.mkdtempSync(path.join(os.tmpdir(),'cso-rails-verification-'));roots.push(root);
|
|
const source=path.join(root,'source'),work=path.join(root,'work'),control=path.join(root,'control');for(const dir of [source,work,control])fs.mkdirSync(dir);
|
|
const events:string[]=[],policies:string[][]=[];let groupNumber=0;
|
|
const create=spyOn(DockerGroup,'create').mockImplementation(async()=>{
|
|
const group=++groupNumber;let next=0;
|
|
return {
|
|
anchor:`anchor-${group}`,
|
|
createContainer:async(spec:any)=>{const id=`${group}-${spec.role}-${++next}`;events.push(`create:${id}:${spec.command.join(' ')}`);if(spec.postgresDatabasePolicy){policies.push(fs.readFileSync(spec.postgresDatabasePolicy,'utf8').trim().split('\n'));expect(fs.statSync(spec.postgresDatabasePolicy).mode&0o777).toBe(0o444);}return id;},
|
|
start:async(id:string)=>{events.push(`start:${id}`);},startHeldApplication:async(id:string)=>{events.push(`held:${id}`);},
|
|
execCapture:async(id:string,command:string[])=>{events.push(`exec:${id}:${command.join(' ')}`);return{code:0,stdout:'',stderr:''};},
|
|
execDetached:async(id:string,command:string[])=>{events.push(`detach:${id}:${command.join(' ')}`);},
|
|
startAttach:async(id:string)=>{events.push(`attach:${id}`);return{code:0,output:JSON.stringify({booted:true,legitimate:true,security:'pass',existingTests:false,output:'ok',inputHash:''})};},
|
|
removeContainer:async(id:string)=>{events.push(`remove:${id}`);},cleanup:async()=>{events.push(`cleanup:${group}`);},
|
|
} as any;
|
|
});
|
|
try{
|
|
const runtime:any={id:'rails',stack:'rails',image:`runtime@sha256:${'a'.repeat(64)}`,platform:'linux/amd64'};
|
|
const request:any={findingId:'b'.repeat(32),port:3456,start:{executable:'/usr/local/bin/bundle',args:['exec','rails','server']},
|
|
legitimate:[],security:{},fixtures:{},existingTests:[{executable:'/usr/local/bin/bundle',args:['exec','rspec']},{executable:'/usr/local/bin/bundle',args:['exec','rails','test']}]};
|
|
const executor=new DockerVerificationExecutor({} as any,'/watchdog',Date.now()+60_000);
|
|
const execution:any={environment:{BUNDLE_PATH:'/work/vendor/bundle'},database:{adapter:'postgresql',connections:['primary','queue'],sidecar:{id:'postgresql-17',image:`postgres@sha256:${'c'.repeat(64)}`}}};
|
|
await executor.observe(source,'before',request,runtime,runtime,work,control,execution);
|
|
await executor.observe(source,'after',request,runtime,runtime,work,control,execution);
|
|
}finally{create.mockRestore();}
|
|
expect(policies).toEqual([['cso_primary','cso_queue'],['cso_primary','cso_queue']]);
|
|
expect(events.filter(event=>event.includes('/opt/cso/postgresql-ready'))).toHaveLength(2);
|
|
expect(events.filter(event=>event.includes('/usr/local/bin/bundle exec rails db:prepare'))).toHaveLength(6);
|
|
for(const [index,event] of events.entries())if(event.includes('exec rails db:prepare'))expect(events.slice(0,index)).toContain(`held:${event.split(':')[1]}`);
|
|
expect(events.some(event=>/^start:\d-(app|tests)-/.test(event))).toBe(false);
|
|
for(const group of [1,2]){
|
|
const removeApp=events.findIndex(event=>event===`remove:${group}-app-2`),createFirstTest=events.findIndex(event=>event.startsWith(`create:${group}-tests-4:`));
|
|
expect(removeApp).toBeGreaterThan(-1);expect(createFirstTest).toBeGreaterThan(removeApp);
|
|
}
|
|
});
|
|
|
|
test('SQLite prepares the app and each test copy without a sidecar',async()=>{
|
|
const root=fs.mkdtempSync(path.join(os.tmpdir(),'cso-rails-sqlite-'));roots.push(root);for(const name of ['source','work','control'])fs.mkdirSync(path.join(root,name));
|
|
const commands:string[]=[];let next=0;
|
|
const create=spyOn(DockerGroup,'create').mockResolvedValue({
|
|
createContainer:async(spec:any)=>{commands.push(`create:${spec.role}`);return`${spec.role}-${++next}`;},start:async()=>{},startHeldApplication:async(id:string)=>{commands.push(`held:${id}`);},
|
|
execCapture:async(_id:string,command:string[])=>{commands.push(command.join(' '));return{code:0,stdout:'',stderr:''};},execDetached:async()=>{},
|
|
startAttach:async()=>({code:0,output:JSON.stringify({booted:true,legitimate:true,security:'pass',existingTests:false,output:'ok',inputHash:''})}),removeContainer:async()=>{},cleanup:async()=>{},
|
|
} as any);
|
|
try{const runtime:any={stack:'rails',image:`runtime@sha256:${'a'.repeat(64)}`},request:any={findingId:'d'.repeat(32),port:3456,start:{executable:'/usr/local/bin/bundle',args:['exec','rails','server']},legitimate:[],security:{},fixtures:{},existingTests:[{executable:'/usr/local/bin/bundle',args:['exec','rails','test']}]};await new DockerVerificationExecutor({} as any,'/watchdog',Date.now()+60_000).observe(path.join(root,'source'),'before',request,runtime,runtime,path.join(root,'work'),path.join(root,'control'),{environment:{},database:{adapter:'sqlite',connections:['primary']}});}finally{create.mockRestore();}
|
|
expect(commands.some(command=>command==='create:postgres')).toBe(false);expect(commands.filter(command=>command.includes('exec rails db:prepare'))).toHaveLength(2);expect(commands.filter(command=>command.startsWith('held:'))).toHaveLength(2);
|
|
});
|
|
});
|