From 414a419f18b4dec4845f6bc2a523404d155f8cd2 Mon Sep 17 00:00:00 2001 From: Denozordec Date: Tue, 3 Nov 2026 23:56:14 +0700 Subject: [PATCH] =?UTF-8?q?fix(ci):=20=D1=81=D0=B8=D0=BD=D1=85=D1=80=D0=BE?= =?UTF-8?q?=D0=BD=D0=B8=D0=B7=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D1=82=D1=8C=20?= =?UTF-8?q?=D1=81=D0=BE=D1=81=D1=82=D0=B0=D0=B2=20=D0=BE=D0=BF=D0=B5=D1=80?= =?UTF-8?q?=D0=B0=D1=82=D0=BE=D1=80=D0=B0=20=D0=B1=D0=B0=D0=B7=D1=8B=20?= =?UTF-8?q?=D0=B4=D0=BB=D1=8F=20=D0=BE=D0=B1=D1=80=D0=B0=D0=B7=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitea/workflows/docker.yml | 4 +-- .gitea/workflows/mcp-acceptance-preview.yml | 4 +-- backend/scripts/build-database-operator.mjs | 12 ++------ .../scripts/build-database-operator.test.mjs | 6 ++-- backend/scripts/database-operator-sources.mjs | 10 +++++++ backend/scripts/stage-database-operator.mjs | 29 +++++++++++++++++++ 6 files changed, 48 insertions(+), 17 deletions(-) create mode 100644 backend/scripts/database-operator-sources.mjs create mode 100644 backend/scripts/stage-database-operator.mjs diff --git a/.gitea/workflows/docker.yml b/.gitea/workflows/docker.yml index ae32687f..38c57dd0 100644 --- a/.gitea/workflows/docker.yml +++ b/.gitea/workflows/docker.yml @@ -155,9 +155,7 @@ jobs: cp -R packages/contracts/src "$STAGING/packages/contracts/" cp backend/package.json backend/tsconfig.json backend/mcp-coverage.json "$STAGING/backend/" cp -R backend/src "$STAGING/backend/" - mkdir -p "$STAGING/backend/scripts/writer-profile" - cp backend/scripts/build-database-operator.mjs backend/scripts/database-writer-bootstrap-operator.mjs backend/scripts/database-writer-profile-operator.mts "$STAGING/backend/scripts/" - cp backend/scripts/writer-profile/operator-files.mjs backend/scripts/writer-profile/operator-contract.mjs backend/scripts/writer-profile/publisher.mjs backend/scripts/writer-profile/context.mjs backend/scripts/writer-profile/catalogue.mts backend/scripts/writer-profile/catalogue-value-bridge.ts backend/scripts/writer-profile/catalogue-projection.ts backend/scripts/writer-profile/catalogue-leaves.ts backend/scripts/writer-profile/application-writer-profile-catalogue.ts backend/scripts/writer-profile/application-writer-profile-catalogue-values.ts backend/scripts/writer-profile/application-writer-profile-catalogue-parent-policy.ts backend/scripts/writer-profile/application-writer-profile-canonical.ts backend/scripts/writer-profile/fixed44-build-sql.ts backend/scripts/writer-profile/fixed44-build-definition.ts backend/scripts/writer-profile/expanded44-data-policy.ts "${STAGING}/backend/scripts/writer-profile/" + node backend/scripts/stage-database-operator.mjs "$STAGING/backend/scripts" mkdir -p "$STAGING/deploy/netflow-agent" cp deploy/netflow-agent/install.sh "$STAGING/deploy/netflow-agent/" if [ -d backend/drizzle ]; then diff --git a/.gitea/workflows/mcp-acceptance-preview.yml b/.gitea/workflows/mcp-acceptance-preview.yml index 05671f3a..3513aade 100644 --- a/.gitea/workflows/mcp-acceptance-preview.yml +++ b/.gitea/workflows/mcp-acceptance-preview.yml @@ -90,9 +90,7 @@ jobs: if [ -d backend/drizzle ]; then cp -R backend/drizzle "$STAGING/backend/" fi - mkdir -p "$STAGING/backend/scripts/writer-profile" - cp backend/scripts/build-database-operator.mjs backend/scripts/database-writer-bootstrap-operator.mjs backend/scripts/database-writer-profile-operator.mts "$STAGING/backend/scripts/" - cp backend/scripts/writer-profile/operator-files.mjs backend/scripts/writer-profile/operator-contract.mjs backend/scripts/writer-profile/publisher.mjs backend/scripts/writer-profile/context.mjs backend/scripts/writer-profile/catalogue.mts backend/scripts/writer-profile/catalogue-value-bridge.ts backend/scripts/writer-profile/catalogue-projection.ts backend/scripts/writer-profile/catalogue-leaves.ts backend/scripts/writer-profile/application-writer-profile-catalogue.ts backend/scripts/writer-profile/application-writer-profile-catalogue-values.ts backend/scripts/writer-profile/application-writer-profile-catalogue-parent-policy.ts backend/scripts/writer-profile/application-writer-profile-canonical.ts backend/scripts/writer-profile/fixed44-build-sql.ts backend/scripts/writer-profile/fixed44-build-definition.ts backend/scripts/writer-profile/expanded44-data-policy.ts "${STAGING}/backend/scripts/writer-profile/" + node backend/scripts/stage-database-operator.mjs "$STAGING/backend/scripts" - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - name: Log in to existing Gitea registry diff --git a/backend/scripts/build-database-operator.mjs b/backend/scripts/build-database-operator.mjs index b3ec2b43..688573c3 100644 --- a/backend/scripts/build-database-operator.mjs +++ b/backend/scripts/build-database-operator.mjs @@ -7,15 +7,9 @@ import path from 'node:path' import {fileURLToPath,pathToFileURL} from 'node:url' import ts from 'typescript' -export const OPERATOR_SOURCES=Object.freeze([ - 'database-writer-bootstrap-operator.mjs','database-writer-profile-operator.mts', - 'writer-profile/operator-files.mjs','writer-profile/operator-contract.mjs','writer-profile/publisher.mjs','writer-profile/context.mjs', - 'writer-profile/protected-source-registry.mts','writer-profile/maintenance-resolution.mts', - 'writer-profile/catalogue.mts','writer-profile/catalogue-value-bridge.ts','writer-profile/catalogue-projection.ts','writer-profile/catalogue-leaves.ts', - 'writer-profile/application-writer-profile-catalogue.ts','writer-profile/application-writer-profile-catalogue-values.ts', - 'writer-profile/application-writer-profile-catalogue-parent-policy.ts','writer-profile/application-writer-profile-canonical.ts', - 'writer-profile/fixed44-build-sql.ts','writer-profile/fixed44-build-definition.ts','writer-profile/expanded44-data-policy.ts', -]) +import {OPERATOR_SOURCES} from './database-operator-sources.mjs' +export {OPERATOR_SOURCES} + const emitted=source=>source.replace(/\.mts$/,'.mjs').replace(/\.ts$/,'.js') const digest=value=>createHash('sha256').update(value).digest('hex') const packageName=specifier=>specifier.startsWith('@')?specifier.split('/').slice(0,2).join('/'):specifier.split('/')[0] diff --git a/backend/scripts/build-database-operator.test.mjs b/backend/scripts/build-database-operator.test.mjs index 435cda00..abd86a6c 100644 --- a/backend/scripts/build-database-operator.test.mjs +++ b/backend/scripts/build-database-operator.test.mjs @@ -5,6 +5,7 @@ import {spawnSync} from 'node:child_process' import path from 'node:path' import {fileURLToPath,pathToFileURL} from 'node:url' import {buildDatabaseOperator,compileOperatorModule,moduleSpecifiers,OPERATOR_SOURCES} from './build-database-operator.mjs' +import {stageDatabaseOperatorScripts} from './stage-database-operator.mjs' const backend=process.env.OPERATOR_BUILD_TEST_BACKEND??path.resolve(path.dirname(fileURLToPath(import.meta.url)),'..') test('AST rewrite changes static/export/dynamic module specifiers and preserves SQL/string values',()=>{ @@ -34,8 +35,9 @@ test('fixed artifact is reproducible, resolves the compiled backend graph, and r for(const relative of first.backendDistImports)await copyDist(relative) assert.deepEqual([...copied].sort(),first.backendDistModules.map(item=>item.file).sort()) // Exercise the real build entry point with its default backend/output paths. - for(const file of OPERATOR_SOURCES){const target=path.join(projectBackend,'scripts',file);await mkdir(path.dirname(target),{recursive:true});await copyFile(path.join(backend,'scripts',file),target)} - const buildScript=path.join(projectBackend,'scripts','build-database-operator.mjs');await copyFile(fileURLToPath(new URL('./build-database-operator.mjs',import.meta.url)),buildScript) + const scripts=path.join(projectBackend,'scripts') + assert.equal(await stageDatabaseOperatorScripts(scripts,path.join(backend,'scripts')),21) + const buildScript=path.join(scripts,'build-database-operator.mjs') const built=spawnSync(process.execPath,[buildScript],{cwd:temporary,env:{...process.env,NODE_OPTIONS:''},encoding:'utf8',timeout:30000}) assert.equal(built.status,0,built.stderr);assert.equal(JSON.parse(built.stdout.trim()).modules,19) assert.deepEqual(JSON.parse(await readFile(path.join(output,'build-manifest.json'),'utf8')),first) diff --git a/backend/scripts/database-operator-sources.mjs b/backend/scripts/database-operator-sources.mjs new file mode 100644 index 00000000..a0cbb93e --- /dev/null +++ b/backend/scripts/database-operator-sources.mjs @@ -0,0 +1,10 @@ +/** The fixed build inputs shared by the operator and Docker staging. */ +export const OPERATOR_SOURCES=Object.freeze([ + 'database-writer-bootstrap-operator.mjs','database-writer-profile-operator.mts', + 'writer-profile/operator-files.mjs','writer-profile/operator-contract.mjs','writer-profile/publisher.mjs','writer-profile/context.mjs', + 'writer-profile/protected-source-registry.mts','writer-profile/maintenance-resolution.mts', + 'writer-profile/catalogue.mts','writer-profile/catalogue-value-bridge.ts','writer-profile/catalogue-projection.ts','writer-profile/catalogue-leaves.ts', + 'writer-profile/application-writer-profile-catalogue.ts','writer-profile/application-writer-profile-catalogue-values.ts', + 'writer-profile/application-writer-profile-catalogue-parent-policy.ts','writer-profile/application-writer-profile-canonical.ts', + 'writer-profile/fixed44-build-sql.ts','writer-profile/fixed44-build-definition.ts','writer-profile/expanded44-data-policy.ts', +]) diff --git a/backend/scripts/stage-database-operator.mjs b/backend/scripts/stage-database-operator.mjs new file mode 100644 index 00000000..19e93738 --- /dev/null +++ b/backend/scripts/stage-database-operator.mjs @@ -0,0 +1,29 @@ +/** Build-time only: copy the exact operator inputs into a scoped Docker context. */ +import assert from 'node:assert/strict' +import {constants} from 'node:fs' +import {copyFile,lstat,mkdir} from 'node:fs/promises' +import path from 'node:path' +import {fileURLToPath,pathToFileURL} from 'node:url' +import {OPERATOR_SOURCES} from './database-operator-sources.mjs' + +const scriptsDirectory=path.dirname(fileURLToPath(import.meta.url)) +const buildInputs=Object.freeze(['build-database-operator.mjs','database-operator-sources.mjs',...OPERATOR_SOURCES]) + +export async function stageDatabaseOperatorScripts(destination,source=scriptsDirectory){ + const from=path.resolve(source),to=path.resolve(destination) + assert(from!==to,'A separate operator staging directory is required') + // Refuse an incomplete source tree before writing any staged files. + for(const file of buildInputs)assert((await lstat(path.join(from,file))).isFile(),'Regular operator build input required: '+file) + for(const file of buildInputs){ + const target=path.join(to,file) + await mkdir(path.dirname(target),{recursive:true}) + await copyFile(path.join(from,file),target,constants.COPYFILE_EXCL) + } + return buildInputs.length +} + +if(process.argv[1]&&import.meta.url===pathToFileURL(path.resolve(process.argv[1])).href){ + assert(process.argv.length===3&&process.argv[2],'A single Docker scripts destination is required') + const files=await stageDatabaseOperatorScripts(process.argv[2]) + console.log(JSON.stringify({event:'database-operator-inputs-staged',files})) +}