mirror of
https://github.com/colbymchenry/codegraph.git
synced 2026-10-17 05:07:37 +08:00
fix(marketplace): flush registry files with Windows-compatible handles
This commit is contained in:
@@ -34,6 +34,9 @@ jobs:
|
||||
timeout-minutes: 35
|
||||
env:
|
||||
CODEGRAPH_TELEMETRY: '0'
|
||||
# This increment changes registry storage and hosted browser behavior.
|
||||
# Prior core lifecycle/native-path/70-kill matrices remain recorded.
|
||||
NATIVE_VALIDATION_SCOPE: marketplace
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
|
||||
@@ -168,4 +168,4 @@ async function cli(args, expected = 0) {
|
||||
await page?.screenshot({ path: path.join(out, 'failure.png'), fullPage: true }).catch(() => {});
|
||||
fs.writeFileSync(path.join(out, 'failure.json'), JSON.stringify({ checks, error: String(error.stack).replace(/token=[a-f0-9]+/g, 'token=[redacted]') }, null, 2)); throw error;
|
||||
} finally { await browser?.close(); await https?.close(); await bridge?.close(); await server?.close(); fs.rmSync(lab, { recursive: true, force: true }); }
|
||||
})().catch(error => { console.error(String(error.stack).replace(/token=[a-f0-9]+/g, 'token=[redacted]')); process.exitCode = 1; });
|
||||
})().catch(error => { console.error(String(error.stack).replace(/token=[a-f0-9]+/g, 'token=[redacted]')); if(error.cause) console.error(error.cause); process.exitCode = 1; });
|
||||
|
||||
@@ -20,7 +20,7 @@ exports.httpsMarketplace = async function(port, out) {
|
||||
try { const response = await fetch(url+'/api/health',{signal:AbortSignal.timeout(5000)}); if(response.ok && (await response.json()).ok) {
|
||||
fs.writeFileSync(path.join(out,'https-transport.json'),JSON.stringify({origin:url,kind:'temporary-public-tunnel',durableHosting:false,verifiedAt:new Date().toISOString()},null,2));
|
||||
return { origin:url, close };
|
||||
}} catch { /* Wait for public route propagation. */ }
|
||||
}} catch (error) { fs.appendFileSync(path.join(out,'https-network-errors.log'),new Date().toISOString()+' '+String(error)+' '+String(error.cause?.stack || '')+'\n'); }
|
||||
}
|
||||
await new Promise(resolve=>setTimeout(resolve,500));
|
||||
}
|
||||
|
||||
@@ -173,6 +173,7 @@ function routes(root) {
|
||||
await popup.close();
|
||||
await page.getByText('Reconnect CodeGraph', { exact: true }).waitFor();
|
||||
checks.push('closed local companion expires the connection visibly');
|
||||
await page.setViewportSize({ width: 1440, height: 1000 });
|
||||
await page.getByRole('link', { name: 'Publish an extension' }).click();
|
||||
await page.locator('#artifact').setInputFiles({ name: 'example.cgext', mimeType: 'application/json', buffer: artifact('4.0.0') });
|
||||
for (const [id, value] of Object.entries({ name: 'Browser example', publisher: 'Recovery publisher', description: 'Outage check', source: 'https://example.com/source', readme: 'Outage check' })) await page.locator('#'+id).fill(value);
|
||||
@@ -194,4 +195,4 @@ function routes(root) {
|
||||
if (attacker) await new Promise(resolve => attacker.close(resolve));
|
||||
fs.rmSync(temp, { recursive: true, force: true });
|
||||
}
|
||||
})().catch(error => { console.error(safeError(error)); process.exitCode = 1; });
|
||||
})().catch(error => { console.error(safeError(error)); if(error.cause) console.error(error.cause); process.exitCode = 1; });
|
||||
|
||||
@@ -83,6 +83,11 @@ async function main() {
|
||||
assert.deepEqual(await (await fetch(restart.origin+'/api/extensions')).json(),catalog);
|
||||
assert.equal(storage.openMarketplaceVolume(volume).id,initialized.id); passed('fresh production process and different deployment cwd preserve catalog/identity/artifacts');
|
||||
const backup = path.join(lab,'backup'); storage.backupMarketplaceVolume(volume,backup);
|
||||
const pending = publish('in-flight-demo','1.0.0','before-commit'); await waitFor(()=>fs.existsSync(pending.ready));
|
||||
const concurrentBackup = path.join(lab,'concurrent-backup'); storage.backupMarketplaceVolume(volume,concurrentBackup);
|
||||
pending.proc.kill('SIGKILL'); await pending.done;
|
||||
assert.deepEqual(storage.verifyMarketplaceDatabase(path.join(concurrentBackup,'registry.sqlite')),before);
|
||||
passed('backup concurrent with uncommitted publication captures only complete releases');
|
||||
const restored = path.join(lab,'restored'); storage.restoreMarketplaceVolume(backup,restored);
|
||||
assert.deepEqual(storage.verifyMarketplaceDatabase(path.join(restored,'registry.sqlite')),before);
|
||||
const isolated = await server(restored,lab);
|
||||
|
||||
@@ -8,6 +8,7 @@ const out = path.resolve(process.env.NATIVE_OUTPUT || `.qa/native/${process.plat
|
||||
fs.mkdirSync(out, { recursive: true });
|
||||
const version = execFileSync('git', ['rev-parse', 'HEAD'], { cwd: root, encoding: 'utf8' }).trim();
|
||||
const metadata = { revision: version, platform: process.platform, arch: process.arch, release: os.release(),
|
||||
scope: process.env.NATIVE_VALIDATION_SCOPE || 'full', notRun: [],
|
||||
node: process.version, runnerOS: process.env.RUNNER_OS, runnerArch: process.env.RUNNER_ARCH,
|
||||
imageOS: process.env.ImageOS, imageVersion: process.env.ImageVersion,
|
||||
githubRun: process.env.GITHUB_RUN_ID, githubAttempt: process.env.GITHUB_RUN_ATTEMPT,
|
||||
@@ -20,6 +21,9 @@ const playwright = process.env.PLAYWRIGHT_MODULE || path.join(root, '.qa/browser
|
||||
env.PLAYWRIGHT_MODULE = playwright;
|
||||
env.CHROME_PATH = process.env.CHROME_PATH || require(playwright).chromium.executablePath();
|
||||
async function run(name, command, args, timeout = 360000, overrides = {}) {
|
||||
if (metadata.scope === 'marketplace' && !['build','marketplace-build','focused','registry-storage','external-author','compatibility','browser'].includes(name)) {
|
||||
metadata.notRun.push({ name, reason: 'Unchanged core lifecycle; retain prior native evidence instead of rerunning' }); save(); return true;
|
||||
}
|
||||
const step = { name, command: [command, ...args], cwd: root, revision: version, overrides, started: new Date().toISOString(), status: 'running' };
|
||||
metadata.steps.push(step); save(); console.log('START', name);
|
||||
const logFile = path.join(out, name + '.log'); const log = fs.openSync(logFile, 'w');
|
||||
|
||||
@@ -8,11 +8,12 @@ import { parsePackage, sha256 } from './package';
|
||||
|
||||
const databaseName = 'registry.sqlite';
|
||||
const markerName = 'registry-volume.json';
|
||||
function sync(file: string): void {
|
||||
const fd = fs.openSync(file, 'r');
|
||||
function sync(file: string, directory = false): void {
|
||||
// Windows FlushFileBuffers requires a writable file handle.
|
||||
const fd = fs.openSync(file, directory ? 'r' : 'r+');
|
||||
try { fs.fsyncSync(fd); } finally { fs.closeSync(fd); }
|
||||
}
|
||||
function syncDir(directory: string): void { if (process.platform !== 'win32') sync(directory); }
|
||||
function syncDir(directory: string): void { if (process.platform !== 'win32') sync(directory, true); }
|
||||
function writeNew(file: string, data: string): void {
|
||||
const fd = fs.openSync(file, 'wx', 0o600);
|
||||
try { fs.writeFileSync(fd, data); fs.fsyncSync(fd); } finally { fs.closeSync(fd); }
|
||||
|
||||
Reference in New Issue
Block a user