feat(n8n): add rotating provider access credential
This commit is contained in:
@@ -13,19 +13,30 @@ const engineRoot = resolve(platformRoot, "../NODEDC_ENGINE_INFRA");
|
||||
const artifactRoot = resolve(process.env.NODEDC_DEPLOY_ARTIFACT_DIR || join(here, "../deploy-artifacts"));
|
||||
const stageArtifact = resolve(
|
||||
process.env.NODEDC_N8N_EXTENSION_STAGE_ARTIFACT
|
||||
|| join(artifactRoot, "nodedc-n8n-private-extension-n8n-nodes-ndc-history-read-20260717-004.tgz"),
|
||||
|| join(artifactRoot, "nodedc-n8n-private-extension-n8n-nodes-ndc-provider-rotating-access-20260718-006.tgz"),
|
||||
);
|
||||
const predecessorArtifact = resolve(
|
||||
process.env.NODEDC_N8N_EXTENSION_PREDECESSOR_ARTIFACT
|
||||
|| join(artifactRoot, "nodedc-engine-n8n-private-extension-20260717-005.tgz"),
|
||||
);
|
||||
|
||||
const stageArtifactSha256 = "a78f8250704e4893eab727cdb862b69ce45a84310fbb73ecd3dfd968b72d12ee";
|
||||
const releaseId = "0.1.3-3354149b5245e39a";
|
||||
const packageVersion = "0.1.3";
|
||||
const packageSha256 = "3354149b5245e39a10f6f03a4b43796602d7e57ea1f91dcc6cb6774ead97501d";
|
||||
const stageArtifactSha256 = "2699e53c482f2d2bec6d13709a7e9b9a0bb3791ad2018c142e9bc4e7bf371e4a";
|
||||
const predecessorArtifactSha256 = "f0f687ddcc1bc006db56c75e73c8213e99298c31c2d881cde078e5ddc9600172";
|
||||
const releaseId = "0.1.4-59dc9f7882721d6a";
|
||||
const packageVersion = "0.1.4";
|
||||
const packageSha256 = "59dc9f7882721d6a5e2ae84ffa6aa8cd9bc5432f5904d24e70e363573ed2757f";
|
||||
const n8nVersion = "2.3.2";
|
||||
const baseImage = "docker.n8n.io/n8nio/n8n:2.3.2";
|
||||
const architecture = "amd64";
|
||||
const generatedAt = "2026-07-17T21:00:00.000Z";
|
||||
const predecessorGitRevision = "96ad46e3c62943f818233481957c62e5088ae35c";
|
||||
const previouslyIssuedTransitionIds = new Set(["20260715-002", "20260716-003", "20260717-004"]);
|
||||
const generatedAt = "2026-07-18T21:00:00.000Z";
|
||||
const previouslyIssuedTransitionIds = new Set([
|
||||
"20260715-002",
|
||||
"20260716-003",
|
||||
"20260717-004",
|
||||
"20260717-005",
|
||||
"20260718-006",
|
||||
"20260718-007",
|
||||
]);
|
||||
const transitionId = readTransitionId(process.argv.slice(2), process.env.NODEDC_N8N_TRANSITION_ID);
|
||||
const activationId = `engine-n8n-private-extension-${transitionId}`;
|
||||
const rollbackId = `engine-n8n-private-extension-rollback-${transitionId}`;
|
||||
@@ -51,7 +62,9 @@ const expectedCredentialTypes = [
|
||||
"ndcDataProductWriterApi",
|
||||
"ndcDataProductReaderApi",
|
||||
"ndcFoundryBindingApi",
|
||||
"ndcProviderRotatingAccessApi",
|
||||
];
|
||||
const predecessorCredentialTypes = expectedCredentialTypes.slice(0, 3);
|
||||
const nodeModules = [
|
||||
["dist/nodes/NdcDataProductPublish/NdcDataProductPublish.node.js", "NdcDataProductPublish"],
|
||||
["dist/nodes/NdcDataProductRead/NdcDataProductRead.node.js", "NdcDataProductRead"],
|
||||
@@ -61,12 +74,14 @@ const credentialModules = [
|
||||
["dist/credentials/NdcDataProductWriterApi.credentials.js", "NdcDataProductWriterApi"],
|
||||
["dist/credentials/NdcDataProductReaderApi.credentials.js", "NdcDataProductReaderApi"],
|
||||
["dist/credentials/NdcFoundryBindingApi.credentials.js", "NdcFoundryBindingApi"],
|
||||
["dist/credentials/NdcProviderRotatingAccessApi.credentials.js", "NdcProviderRotatingAccessApi"],
|
||||
];
|
||||
|
||||
await mkdir(artifactRoot, { recursive: true });
|
||||
await assertArtifactTargetFresh(join(artifactRoot, `nodedc-${activationId}.tgz`));
|
||||
await assertArtifactTargetFresh(join(artifactRoot, `nodedc-${rollbackId}.tgz`));
|
||||
assertSha(await readFile(stageArtifact), stageArtifactSha256, "staging artifact");
|
||||
assertSha(await readFile(predecessorArtifact), predecessorArtifactSha256, "predecessor artifact");
|
||||
assertEngineBaseline(await readFile(join(engineRoot, "docker-compose.yml"), "utf8"));
|
||||
|
||||
const work = await mkdtemp(join(tmpdir(), "nodedc-engine-n8n-sealed-"));
|
||||
@@ -111,10 +126,10 @@ try {
|
||||
assertExact(privateNodes.map((item) => item.name), expectedNodeTypes, "node types");
|
||||
assertExact(privateCredentials.map((item) => item.name), expectedCredentialTypes, "credential types");
|
||||
|
||||
const predecessorDescriptor = JSON.parse(gitFile(descriptorRel));
|
||||
const predecessorNodes = JSON.parse(gitFile(nodesCatalogRel));
|
||||
const predecessorCredentials = JSON.parse(gitFile(credentialsCatalogRel));
|
||||
const predecessorMeta = JSON.parse(gitFile(metaRel));
|
||||
const predecessorDescriptor = JSON.parse(predecessorArtifactFile(descriptorRel));
|
||||
const predecessorNodes = JSON.parse(predecessorArtifactFile(nodesCatalogRel));
|
||||
const predecessorCredentials = JSON.parse(predecessorArtifactFile(credentialsCatalogRel));
|
||||
const predecessorMeta = JSON.parse(predecessorArtifactFile(metaRel));
|
||||
assertPredecessorCatalogs(
|
||||
predecessorDescriptor,
|
||||
predecessorNodes,
|
||||
@@ -148,8 +163,18 @@ try {
|
||||
packageVersion: predecessorDescriptor.packageVersion,
|
||||
packageSha256: predecessorDescriptor.packageSha256,
|
||||
};
|
||||
const activationDescriptor = descriptor(target, predecessor.releaseId, predecessor.releaseId);
|
||||
const rollbackDescriptor = descriptor(predecessor, releaseId, releaseId);
|
||||
const activationDescriptor = descriptor(
|
||||
target,
|
||||
predecessor.releaseId,
|
||||
predecessor.releaseId,
|
||||
expectedCredentialTypes,
|
||||
);
|
||||
const rollbackDescriptor = descriptor(
|
||||
predecessor,
|
||||
releaseId,
|
||||
releaseId,
|
||||
predecessorCredentialTypes,
|
||||
);
|
||||
const override = composeOverride(target);
|
||||
const rollbackOverride = composeOverride(predecessor);
|
||||
|
||||
@@ -204,7 +229,7 @@ try {
|
||||
await rm(work, { recursive: true, force: true });
|
||||
}
|
||||
|
||||
function descriptor(target, expectedCurrent, rollbackBaseline) {
|
||||
function descriptor(target, expectedCurrent, rollbackBaseline, credentialTypes) {
|
||||
return {
|
||||
schemaVersion: "nodedc.engine-n8n-private-extension-transition/v1",
|
||||
action: "activate",
|
||||
@@ -221,7 +246,7 @@ function descriptor(target, expectedCurrent, rollbackBaseline) {
|
||||
topologyServices: ["n8n"],
|
||||
expectedCurrent,
|
||||
expectedNodeTypes,
|
||||
expectedCredentialTypes,
|
||||
expectedCredentialTypes: credentialTypes,
|
||||
rollbackBaseline,
|
||||
};
|
||||
}
|
||||
@@ -327,15 +352,15 @@ function assertPackage(value) {
|
||||
|
||||
function assertPredecessorCatalogs(descriptorValue, nodes, credentials, meta) {
|
||||
if (descriptorValue?.action !== "activate"
|
||||
|| descriptorValue?.releaseId !== "0.1.2-05e4b38b14b4a019"
|
||||
|| descriptorValue?.packageVersion !== "0.1.2"
|
||||
|| descriptorValue?.packageSha256 !== "05e4b38b14b4a019ce1f6eee27b9e320094cb3560903bd68074966b3a1267af5") {
|
||||
|| descriptorValue?.releaseId !== "0.1.3-3354149b5245e39a"
|
||||
|| descriptorValue?.packageVersion !== "0.1.3"
|
||||
|| descriptorValue?.packageSha256 !== "3354149b5245e39a10f6f03a4b43796602d7e57ea1f91dcc6cb6774ead97501d") {
|
||||
throw new Error("predecessor_descriptor_mismatch");
|
||||
}
|
||||
if (!Array.isArray(nodes) || nodes.length !== 437
|
||||
|| !Array.isArray(credentials) || credentials.length !== 388
|
||||
|| meta?.n8nVersion !== n8nVersion
|
||||
|| meta?.source !== "n8n-core+n8n-nodes-ndc@0.1.2"
|
||||
|| meta?.source !== "n8n-core+n8n-nodes-ndc@0.1.3"
|
||||
|| meta?.nodeCount !== 437
|
||||
|| meta?.credentialCount !== 388) {
|
||||
throw new Error("predecessor_catalog_mismatch");
|
||||
@@ -346,8 +371,8 @@ function assertPredecessorCatalogs(descriptorValue, nodes, credentials, meta) {
|
||||
"predecessor node types",
|
||||
);
|
||||
assertExact(
|
||||
credentials.filter((item) => expectedCredentialTypes.includes(String(item?.name || ""))).map((item) => item.name),
|
||||
expectedCredentialTypes,
|
||||
credentials.filter((item) => predecessorCredentialTypes.includes(String(item?.name || ""))).map((item) => item.name),
|
||||
predecessorCredentialTypes,
|
||||
"predecessor credential types",
|
||||
);
|
||||
}
|
||||
@@ -381,8 +406,17 @@ function assertSha(bytes, expected, label) {
|
||||
if (actual !== expected) throw new Error(`${label.replaceAll(" ", "_")}_sha256_mismatch:${actual}`);
|
||||
}
|
||||
|
||||
function gitFile(rel) {
|
||||
return run("git", ["show", `${predecessorGitRevision}:${rel}`], engineRoot).stdout;
|
||||
function predecessorArtifactFile(rel) {
|
||||
const script = [
|
||||
"import pathlib,sys,tarfile",
|
||||
"archive=pathlib.Path(sys.argv[1])",
|
||||
"member='payload/'+sys.argv[2]",
|
||||
"with tarfile.open(archive,'r:gz') as source:",
|
||||
" extracted=source.extractfile(member)",
|
||||
" if extracted is None: raise SystemExit('predecessor member missing')",
|
||||
" sys.stdout.buffer.write(extracted.read())",
|
||||
].join("\n");
|
||||
return run("python3", ["-c", script, predecessorArtifact, rel]).stdout;
|
||||
}
|
||||
|
||||
async function writeJson(path, value) {
|
||||
|
||||
Reference in New Issue
Block a user