refactor!: separate runtime releases from panel source
This commit is contained in:
@@ -1,15 +0,0 @@
|
||||
#!/bin/bash
|
||||
set -Eeuo pipefail
|
||||
project_dir=$(CDPATH= cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." && pwd)
|
||||
version=${1:-}
|
||||
if [[ -z $version ]]; then
|
||||
version=$(npm view @deepseek-ai/dsh@latest version --registry=https://registry.npmjs.org)
|
||||
fi
|
||||
if [[ ! $version =~ ^[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z.-]+)?$ ]]; then
|
||||
echo 'Expected an exact DSH version, not a dist-tag or arbitrary build argument.' >&2
|
||||
exit 2
|
||||
fi
|
||||
tag="dsh-web:${version}-7"
|
||||
printf 'Building local image %s (no push)\n' "$tag"
|
||||
docker build --build-arg "DSH_VERSION=$version" --tag "$tag" "$project_dir/image"
|
||||
docker image inspect --format '{{.Id}}' "$tag"
|
||||
@@ -23,7 +23,6 @@ run go vet ./...
|
||||
run go build ./...
|
||||
run npm --prefix web test
|
||||
run npm --prefix web run build
|
||||
run node --test image/init-profile.test.mjs
|
||||
run node --check scripts/test-panel.mjs
|
||||
|
||||
printf '\nAll acceptance checks passed. 所有测试与检查均通过。\n'
|
||||
|
||||
@@ -12,7 +12,6 @@ const commands = [
|
||||
'go build ./...',
|
||||
'npm --prefix web test',
|
||||
'npm --prefix web run build',
|
||||
'node --test image/init-profile.test.mjs',
|
||||
'node --check scripts/test-panel.mjs',
|
||||
];
|
||||
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
import assert from 'node:assert/strict';
|
||||
import {readFileSync} from 'node:fs';
|
||||
const base=process.env.TEST_PANEL_URL;
|
||||
assert.ok(base && process.env.TEST_PASSWORD_FILE);
|
||||
let csrf='',cookie='';
|
||||
async function req(path,method='GET',body){
|
||||
const r=await fetch(base+path,{method,headers:{Cookie:cookie,Origin:base,'Content-Type':'application/json','X-CSRF-Token':csrf},body:body===undefined?undefined:JSON.stringify(body)});
|
||||
if(path==='/api/login')cookie=r.headers.getSetCookie().map(v=>v.split(';')[0]).join('; ');
|
||||
return {status:r.status,data:await r.json()};
|
||||
}
|
||||
const login=await req('/api/login','POST',{username:'admin',password:readFileSync(process.env.TEST_PASSWORD_FILE,'utf8').trim()});
|
||||
assert.equal(login.status,200);csrf=login.data.csrf_token;
|
||||
const before=(await req('/api/instances')).data;assert.equal(before.length,1,'run with exactly one retained test instance');
|
||||
const intent=await req('/api/intents','POST',{name:'Design real intent',version:'0.2.0-rc.2'});assert.equal(intent.status,202);
|
||||
let created;
|
||||
try {
|
||||
for(let n=0;n<60;n++){
|
||||
const item=(await req('/api/intents')).data.find(x=>x.id===intent.data.id);
|
||||
assert.notEqual(item.status,'failed');
|
||||
if(item.instance_id){created=item.instance_id;break;}
|
||||
await new Promise(r=>setTimeout(r,1000));
|
||||
}
|
||||
assert.ok(created,'intent must create a real instance');
|
||||
const list=(await req('/api/instances')).data;assert.equal(list.length,2);assert.ok(list.every(i=>i.status==='running'));
|
||||
const extra=await req('/api/instances','POST',{name:'must reject third',image_id:list[0].image_id});assert.equal(extra.status,409);
|
||||
assert.equal((await req('/api/intents','POST',{name:'must reject extra reservation',version:'0.2.0-rc.2'})).status,409);
|
||||
console.log('PASS persisted intent -> real runtime; two running instances; third create and reservation rejected');
|
||||
} finally {
|
||||
if(created)assert.equal((await req('/api/instances/'+created,'DELETE')).status,200);
|
||||
else await req('/api/intents/'+intent.data.id,'DELETE');
|
||||
}
|
||||
assert.equal((await req('/api/instances')).data.length,1);
|
||||
console.log('PASS deleted only this test runtime, retained data and prior instance');
|
||||
@@ -23,16 +23,12 @@ try {
|
||||
assert.equal((await request('/api/me')).data.user.username,process.env.TEST_USERNAME || 'testadmin');
|
||||
await request('/api/refresh','POST');
|
||||
assert.equal((await request('/api/me')).data.user.username,process.env.TEST_USERNAME || 'testadmin');
|
||||
let images=(await request('/api/images')).data;
|
||||
const build=(await request('/api/builds','POST',{version:process.env.TEST_FROM_VERSION || images[0]?.version || '0.2.0-rc.2'})).data;
|
||||
let buildSucceeded=false;
|
||||
for(let n=0;n<120;n++){let job;try{job=(await request('/api/builds/'+encodeURIComponent(build.id))).data;}catch(e){if(!(e instanceof Error))throw e;await new Promise(r=>setTimeout(r,1000));continue;}if(job?.status==='failed')throw new Error('build/validation failed: '+job.error);if(job?.status==='success'){buildSucceeded=true;break;}await new Promise(r=>setTimeout(r,1000));}
|
||||
assert.ok(buildSucceeded,'submitted build/validation job did not complete before timeout');
|
||||
images=(await request('/api/images')).data.filter(i=>i.status==='available');assert.ok(images.length,'validated image required');
|
||||
const images=(await request('/api/images')).data.filter(i=>i.status==='available' && i.selectable===true);
|
||||
assert.ok(images.length,'prepare a validated, admitted image through the admin Git release flow before running this test');
|
||||
const source=images.find(i=>!process.env.TEST_FROM_VERSION || i.version===process.env.TEST_FROM_VERSION);
|
||||
const target=images.find(i=>!process.env.TEST_TO_VERSION || i.version===process.env.TEST_TO_VERSION);
|
||||
assert.ok(source,'source image required');assert.ok(target,'target image required');
|
||||
console.log('PASS local image reuse, persistent build task and runtime verification');
|
||||
console.log('PASS validated and admitted local image selection');
|
||||
instance=(await request('/api/instances','POST',{name:'Integration check',image_id:source.image_id || source.id,version:source.version})).data;
|
||||
await request('/api/ws/mkdir','POST',{path:testDirectory});
|
||||
const form=new FormData();form.set('path',testDirectory);form.set('file',new Blob(['hello workspace']), 'hello.txt');await request('/api/ws/upload','POST',form);
|
||||
|
||||
Reference in New Issue
Block a user