From 5cdb5e6d0c989f7a3b2470a3975ea6f7bc1d4521 Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Mon, 21 Jul 2025 12:38:25 -0500 Subject: [PATCH 001/142] test --- app/v4/src/functions/storageBlobTrigger.ts | 24 +-- .../functions/storageBlobTriggerAndOutput.ts | 34 ++-- .../storageBlobTriggerSharedOutputBug.ts | 52 +++--- .../templates/test-node-version.yml | 3 + azure-pipelines/templates/test.yml | 12 +- src/index.ts | 9 +- src/storage.test.ts | 150 +++++++++--------- src/utils/servicebus/config.json | 28 ++++ src/utils/servicebus/docker-compose.yml | 0 9 files changed, 175 insertions(+), 137 deletions(-) create mode 100644 src/utils/servicebus/config.json create mode 100644 src/utils/servicebus/docker-compose.yml diff --git a/app/v4/src/functions/storageBlobTrigger.ts b/app/v4/src/functions/storageBlobTrigger.ts index 20a42f63..709421d8 100644 --- a/app/v4/src/functions/storageBlobTrigger.ts +++ b/app/v4/src/functions/storageBlobTrigger.ts @@ -1,15 +1,15 @@ -// // Copyright (c) .NET Foundation. All rights reserved. -// // Licensed under the MIT License. +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT License. -// import { app, InvocationContext } from '@azure/functions'; +import { app, InvocationContext } from '@azure/functions'; -// export async function storageBlobTrigger(blob: Buffer, context: InvocationContext): Promise { -// const blobPath = context.triggerMetadata.blobTrigger; -// context.log(`storageBlobTrigger was triggered by blob "${blobPath}" with content "${blob.toString()}"`); -// } +export async function storageBlobTrigger(blob: Buffer, context: InvocationContext): Promise { + const blobPath = context.triggerMetadata.blobTrigger; + context.log(`storageBlobTrigger was triggered by blob "${blobPath}" with content "${blob.toString()}"`); +} -// app.storageBlob('storageBlobTrigger', { -// path: 'e2e-test-container/e2e-test-blob-trigger', -// connection: 'AzureWebJobsStorage', -// handler: storageBlobTrigger, -// }); +app.storageBlob('storageBlobTrigger', { + path: 'e2e-test-container/e2e-test-blob-trigger', + connection: 'AzureWebJobsStorage', + handler: storageBlobTrigger, +}); diff --git a/app/v4/src/functions/storageBlobTriggerAndOutput.ts b/app/v4/src/functions/storageBlobTriggerAndOutput.ts index 01d16a0e..8948fb04 100644 --- a/app/v4/src/functions/storageBlobTriggerAndOutput.ts +++ b/app/v4/src/functions/storageBlobTriggerAndOutput.ts @@ -1,20 +1,20 @@ -// // Copyright (c) .NET Foundation. All rights reserved. -// // Licensed under the MIT License. +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT License. -// import { app, InvocationContext, output } from '@azure/functions'; +import { app, InvocationContext, output } from '@azure/functions'; -// export async function storageBlobTriggerAndOutput(blob: Buffer, context: InvocationContext): Promise { -// const blobPath = context.triggerMetadata.blobTrigger; -// context.log(`storageBlobTriggerAndOutput was triggered by blob "${blobPath}" with content "${blob.toString()}"`); -// return blob; -// } +export async function storageBlobTriggerAndOutput(blob: Buffer, context: InvocationContext): Promise { + const blobPath = context.triggerMetadata.blobTrigger; + context.log(`storageBlobTriggerAndOutput was triggered by blob "${blobPath}" with content "${blob.toString()}"`); + return blob; +} -// app.storageBlob('storageBlobTriggerAndOutput', { -// path: 'e2e-test-container/e2e-test-blob-trigger-and-output', -// connection: 'AzureWebJobsStorage', -// return: output.storageBlob({ -// path: 'e2e-test-container/e2e-test-blob-trigger', -// connection: 'AzureWebJobsStorage', -// }), -// handler: storageBlobTriggerAndOutput, -// }); +app.storageBlob('storageBlobTriggerAndOutput', { + path: 'e2e-test-container/e2e-test-blob-trigger-and-output', + connection: 'AzureWebJobsStorage', + return: output.storageBlob({ + path: 'e2e-test-container/e2e-test-blob-trigger', + connection: 'AzureWebJobsStorage', + }), + handler: storageBlobTriggerAndOutput, +}); diff --git a/app/v4/src/functions/storageBlobTriggerSharedOutputBug.ts b/app/v4/src/functions/storageBlobTriggerSharedOutputBug.ts index afd3694c..99d1eb1c 100644 --- a/app/v4/src/functions/storageBlobTriggerSharedOutputBug.ts +++ b/app/v4/src/functions/storageBlobTriggerSharedOutputBug.ts @@ -1,31 +1,31 @@ -// // Copyright (c) .NET Foundation. All rights reserved. -// // Licensed under the MIT License. +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT License. -// import { app, InvocationContext, output } from '@azure/functions'; +import { app, InvocationContext, output } from '@azure/functions'; -// // Test for bug https://github.com/Azure/azure-functions-nodejs-library/issues/179 +// Test for bug https://github.com/Azure/azure-functions-nodejs-library/issues/179 -// const queueOutput = output.storageQueue({ -// queueName: 'e2e-test-queue-trigger', -// connection: 'e2eTest_storage', -// }); +const queueOutput = output.storageQueue({ + queueName: 'e2e-test-queue-trigger', + connection: 'AzureWebJobsStorage', +}); -// app.storageBlob('storageBlobTriggerReturnOutput', { -// path: 'e2e-test-container/e2e-test-blob-trigger-shared-output-bug', -// connection: 'e2eTest_storage', -// return: queueOutput, -// handler: (blob: Buffer, context: InvocationContext) => { -// context.log(`storageBlobTriggerReturnOutput was triggered`); -// return `${blob.toString()}-returnOutput`; -// }, -// }); +app.storageBlob('storageBlobTriggerReturnOutput', { + path: 'e2e-test-container/e2e-test-blob-trigger-shared-output-bug', + connection: 'AzureWebJobsStorage', + return: queueOutput, + handler: (blob: Buffer, context: InvocationContext) => { + context.log(`storageBlobTriggerReturnOutput was triggered`); + return `${blob.toString()}-returnOutput`; + }, +}); -// app.storageBlob('storageBlobTriggerExtraOutput', { -// path: 'e2e-test-container/e2e-test-blob-trigger-shared-output-bug', -// connection: 'e2eTest_storage', -// extraOutputs: [queueOutput], -// handler: (blob: Buffer, context: InvocationContext) => { -// context.log(`storageBlobTriggerExtraOutput was triggered`); -// context.extraOutputs.set(queueOutput, `${blob.toString()}-extraOutput`); -// }, -// }); +app.storageBlob('storageBlobTriggerExtraOutput', { + path: 'e2e-test-container/e2e-test-blob-trigger-shared-output-bug', + connection: 'AzureWebJobsStorage', + extraOutputs: [queueOutput], + handler: (blob: Buffer, context: InvocationContext) => { + context.log(`storageBlobTriggerExtraOutput was triggered`); + context.extraOutputs.set(queueOutput, `${blob.toString()}-extraOutput`); + }, +}); diff --git a/azure-pipelines/templates/test-node-version.yml b/azure-pipelines/templates/test-node-version.yml index fcbeca96..380696db 100644 --- a/azure-pipelines/templates/test-node-version.yml +++ b/azure-pipelines/templates/test-node-version.yml @@ -15,6 +15,9 @@ steps: docker compose -f src/utils/eventhub/docker-compose.yml pull docker compose -f src/utils/eventhub/docker-compose.yml up -d displayName: 'Install Azurite and Start EventHub Emulator' + - bash: | + docker logs azurite + displayName: 'Show Azurite Logs' - bash: | npm run ${{ parameters.testCommand }} displayName: 'Run tests Node ${{ parameters.nodeVersion }}' diff --git a/azure-pipelines/templates/test.yml b/azure-pipelines/templates/test.yml index 99aafeed..19f6efe0 100644 --- a/azure-pipelines/templates/test.yml +++ b/azure-pipelines/templates/test.yml @@ -16,13 +16,13 @@ jobs: - template: /azure-pipelines/templates/build-apps.yml@self - - template: /azure-pipelines/templates/test-node-version.yml@self - parameters: - nodeVersion: 18.x + # - template: /azure-pipelines/templates/test-node-version.yml@self + # parameters: + # nodeVersion: 18.x - - template: /azure-pipelines/templates/test-node-version.yml@self - parameters: - nodeVersion: 20.x + # - template: /azure-pipelines/templates/test-node-version.yml@self + # parameters: + # nodeVersion: 20.x - template: /azure-pipelines/templates/test-node-version.yml@self parameters: diff --git a/src/index.ts b/src/index.ts index 0c52d1c2..69118ba6 100644 --- a/src/index.ts +++ b/src/index.ts @@ -6,9 +6,16 @@ import Mocha from 'mocha'; import path from 'path'; import { defaultTimeout } from './constants'; import { getModelArg, getOldConfigArg } from './getModelArg'; +import yargs from 'yargs'; export async function run(): Promise { try { + const argv = yargs(process.argv.slice(2)).option('exclude', { + type: 'string', + description: 'Glob pattern of tests to exclude', + }).parseSync(); + const excludePattern = argv.exclude ? [argv.exclude] : []; + const oldConfigSuffix = getOldConfigArg() ? '_oldConfig' : ''; const fileName = `${process.platform}_model-${getModelArg()}_Node-${process.version}${oldConfigSuffix}.xml`; const options: Mocha.MochaOptions = { @@ -27,7 +34,7 @@ export async function run(): Promise { const mocha = new Mocha(options); - const files: string[] = await globby('**/**.test.js', { cwd: __dirname }); + const files: string[] = await globby(['**/**.test.js', ...excludePattern.map(p => `!${p}`)], { cwd: __dirname }); files.forEach((f) => mocha.addFile(path.resolve(__dirname, f))); diff --git a/src/storage.test.ts b/src/storage.test.ts index fe2efc09..b6624ea1 100644 --- a/src/storage.test.ts +++ b/src/storage.test.ts @@ -1,14 +1,14 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT License. -// import { ContainerClient } from '@azure/storage-blob'; +import { ContainerClient } from '@azure/storage-blob'; // import { QueueClient } from '@azure/storage-queue'; // import { expect } from 'chai'; // import { default as fetch } from 'node-fetch'; // import { getFuncUrl } from './constants'; -// import { waitForOutput } from './global.test'; -// import { getRandomTestData } from './utils/getRandomTestData'; -// import { storageConnectionString } from './utils/connectionStrings'; +import { waitForOutput } from './global.test'; +import { getRandomTestData } from './utils/getRandomTestData'; +import { storageConnectionString } from './utils/connectionStrings'; // describe('storage', () => { // it('queue trigger and output', async () => { @@ -22,86 +22,86 @@ // await waitForOutput(`storageQueueTrigger was triggered by "${message}"`); // }); -// it('queue extra output', async () => { -// const url = getFuncUrl('httpTriggerStorageQueueOutput'); + // it('queue extra output', async () => { + // const url = getFuncUrl('httpTriggerStorageQueueOutput'); -// // single -// const message = getRandomTestData(); -// await fetch(url, { method: 'POST', body: JSON.stringify({ output: message }) }); -// await waitForOutput(`storageQueueTrigger was triggered by "${message}"`); + // // single + // const message = getRandomTestData(); + // await fetch(url, { method: 'POST', body: JSON.stringify({ output: message }) }); + // await waitForOutput(`storageQueueTrigger was triggered by "${message}"`); + + // // bulk + // const bulkMsgs: string[] = []; + // for (let i = 0; i < 5; i++) { + // bulkMsgs.push(getRandomTestData()); + // } + // await fetch(url, { method: 'POST', body: JSON.stringify({ output: bulkMsgs }) }); + // for (const msg of bulkMsgs) { + // await waitForOutput(`storageQueueTrigger was triggered by "${msg}"`); + // } + // }); -// // bulk -// const bulkMsgs: string[] = []; -// for (let i = 0; i < 5; i++) { -// bulkMsgs.push(getRandomTestData()); -// } -// await fetch(url, { method: 'POST', body: JSON.stringify({ output: bulkMsgs }) }); -// for (const msg of bulkMsgs) { -// await waitForOutput(`storageQueueTrigger was triggered by "${msg}"`); -// } -// }); + it('blob trigger and output', async () => { + const containerName = 'e2e-test-container'; + const client = new ContainerClient(storageConnectionString, containerName); + await client.createIfNotExists(); + + const message = getRandomTestData(); + const messageBuffer = Buffer.from(message); + const blobName = 'e2e-test-blob-trigger-and-output'; + await client.uploadBlockBlob(blobName, messageBuffer, messageBuffer.byteLength); + + await waitForOutput( + `storageBlobTriggerAndOutput was triggered by blob "${containerName}/${blobName}" with content "${message}"` + ); + await waitForOutput( + `storageBlobTrigger was triggered by blob "${containerName}/e2e-test-blob-trigger" with content "${message}"` + ); + }); + + // type TableItem = { PartitionKey: string; RowKey: string; Name: string }; + + // it('table input and output', async () => { + // const rowKey = getRandomTestData(); + // const items: TableItem[] = [ + // { + // PartitionKey: 'e2eTestPartKey', + // RowKey: rowKey, + // Name: 'e2eTestName', + // }, + // ]; + // const responseOut = await fetch(getFuncUrl('httpTriggerTableOutput'), { + // method: 'POST', + // body: JSON.stringify(items), + // }); + // expect(responseOut.status).to.equal(201); + // await waitForOutput(`httpTriggerTableOutput was triggered`); + + // const responseIn = await fetch(getFuncUrl(`httpTriggerTableInput/${rowKey}`), { method: 'GET' }); + // expect(responseIn.status).to.equal(200); + // const result = await responseIn.json(); + // expect(result).to.deep.equal(items); + // await waitForOutput(`httpTriggerTableInput was triggered`); + // }); + + // Test for bug https://github.com/Azure/azure-functions-nodejs-library/issues/179 + // it('Shared output bug', async function (this: Mocha.Context) { + // if (model === 'v3') { + // this.skip(); + // } - // it('blob trigger and output', async () => { // const containerName = 'e2e-test-container'; // const client = new ContainerClient(storageConnectionString, containerName); // await client.createIfNotExists(); // const message = getRandomTestData(); // const messageBuffer = Buffer.from(message); - // const blobName = 'e2e-test-blob-trigger-and-output'; + // const blobName = 'e2e-test-blob-trigger-shared-output-bug'; // await client.uploadBlockBlob(blobName, messageBuffer, messageBuffer.byteLength); - // await waitForOutput( - // `storageBlobTriggerAndOutput was triggered by blob "${containerName}/${blobName}" with content "${message}"` - // ); - // await waitForOutput( - // `storageBlobTrigger was triggered by blob "${containerName}/e2e-test-blob-trigger" with content "${message}"` - // ); + // await waitForOutput(`storageBlobTriggerReturnOutput was triggered`); + // await waitForOutput(`storageBlobTriggerExtraOutput was triggered`); + // await waitForOutput(`storageQueueTrigger was triggered by "${message}-returnOutput"`); + // await waitForOutput(`storageQueueTrigger was triggered by "${message}-extraOutput"`); // }); - -// type TableItem = { PartitionKey: string; RowKey: string; Name: string }; - -// it('table input and output', async () => { -// const rowKey = getRandomTestData(); -// const items: TableItem[] = [ -// { -// PartitionKey: 'e2eTestPartKey', -// RowKey: rowKey, -// Name: 'e2eTestName', -// }, -// ]; -// const responseOut = await fetch(getFuncUrl('httpTriggerTableOutput'), { -// method: 'POST', -// body: JSON.stringify(items), -// }); -// expect(responseOut.status).to.equal(201); -// await waitForOutput(`httpTriggerTableOutput was triggered`); - -// const responseIn = await fetch(getFuncUrl(`httpTriggerTableInput/${rowKey}`), { method: 'GET' }); -// expect(responseIn.status).to.equal(200); -// const result = await responseIn.json(); -// expect(result).to.deep.equal(items); -// await waitForOutput(`httpTriggerTableInput was triggered`); -// }); - -// // Test for bug https://github.com/Azure/azure-functions-nodejs-library/issues/179 -// it('Shared output bug', async function (this: Mocha.Context) { -// if (model === 'v3') { -// this.skip(); -// } - -// const containerName = 'e2e-test-container'; -// const client = new ContainerClient(storageConnectionString, containerName); -// await client.createIfNotExists(); - -// const message = getRandomTestData(); -// const messageBuffer = Buffer.from(message); -// const blobName = 'e2e-test-blob-trigger-shared-output-bug'; -// await client.uploadBlockBlob(blobName, messageBuffer, messageBuffer.byteLength); - -// await waitForOutput(`storageBlobTriggerReturnOutput was triggered`); -// await waitForOutput(`storageBlobTriggerExtraOutput was triggered`); -// await waitForOutput(`storageQueueTrigger was triggered by "${message}-returnOutput"`); -// await waitForOutput(`storageQueueTrigger was triggered by "${message}-extraOutput"`); -// }); -// }); +}); diff --git a/src/utils/servicebus/config.json b/src/utils/servicebus/config.json new file mode 100644 index 00000000..20cf8344 --- /dev/null +++ b/src/utils/servicebus/config.json @@ -0,0 +1,28 @@ +{ + "UserConfig": { + "Namespaces": [ + { + "Name": "sbemulatorns", + "Queues": [ + { + "Name": "testqueue", + "Properties": { + "DeadLetteringOnMessageExpiration": false, + "DefaultMessageTimeToLive": "PT1H", + "DuplicateDetectionHistoryTimeWindow": "PT20S", + "ForwardDeadLetteredMessagesTo": "", + "ForwardTo": "", + "LockDuration": "PT1M", + "MaxDeliveryCount": 10, + "RequiresDuplicateDetection": false, + "RequiresSession": false + } + } + ] + } + ], + "Logging": { + "Type": "File" + } + } +} \ No newline at end of file diff --git a/src/utils/servicebus/docker-compose.yml b/src/utils/servicebus/docker-compose.yml new file mode 100644 index 00000000..e69de29b From 603bd9606a1188fb24e2480d00d3364d734fa5a7 Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Mon, 21 Jul 2025 13:27:10 -0500 Subject: [PATCH 002/142] test --- __azurite_db_blob__.json | 1 + __azurite_db_blob_extent__.json | 1 + src/storage.test.ts | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 __azurite_db_blob__.json create mode 100644 __azurite_db_blob_extent__.json diff --git a/__azurite_db_blob__.json b/__azurite_db_blob__.json new file mode 100644 index 00000000..4d82d705 --- /dev/null +++ b/__azurite_db_blob__.json @@ -0,0 +1 @@ +{"filename":"c:\\Users\\evanroman\\source\\repos\\azure-functions-nodejs-e2e-tests\\__azurite_db_blob__.json","collections":[{"name":"$SERVICES_COLLECTION$","data":[],"idIndex":null,"binaryIndices":{},"constraints":null,"uniqueNames":["accountName"],"transforms":{},"objType":"$SERVICES_COLLECTION$","dirty":false,"cachedIndex":null,"cachedBinaryIndex":null,"cachedData":null,"adaptiveBinaryIndices":true,"transactional":false,"cloneObjects":false,"cloneMethod":"parse-stringify","asyncListeners":false,"disableMeta":false,"disableChangesApi":true,"disableDeltaChangesApi":true,"autoupdate":false,"serializableIndices":true,"disableFreeze":true,"ttl":null,"maxId":0,"DynamicViews":[],"events":{"insert":[],"update":[],"pre-insert":[],"pre-update":[],"close":[],"flushbuffer":[],"error":[],"delete":[null],"warning":[null]},"changes":[],"dirtyIds":[]},{"name":"$CONTAINERS_COLLECTION$","data":[],"idIndex":null,"binaryIndices":{"accountName":{"name":"accountName","dirty":false,"values":[]},"name":{"name":"name","dirty":false,"values":[]}},"constraints":null,"uniqueNames":[],"transforms":{},"objType":"$CONTAINERS_COLLECTION$","dirty":false,"cachedIndex":null,"cachedBinaryIndex":null,"cachedData":null,"adaptiveBinaryIndices":true,"transactional":false,"cloneObjects":false,"cloneMethod":"parse-stringify","asyncListeners":false,"disableMeta":false,"disableChangesApi":true,"disableDeltaChangesApi":true,"autoupdate":false,"serializableIndices":true,"disableFreeze":true,"ttl":null,"maxId":0,"DynamicViews":[],"events":{"insert":[],"update":[],"pre-insert":[],"pre-update":[],"close":[],"flushbuffer":[],"error":[],"delete":[null],"warning":[null]},"changes":[],"dirtyIds":[]},{"name":"$BLOBS_COLLECTION$","data":[],"idIndex":null,"binaryIndices":{"accountName":{"name":"accountName","dirty":false,"values":[]},"containerName":{"name":"containerName","dirty":false,"values":[]},"name":{"name":"name","dirty":false,"values":[]},"snapshot":{"name":"snapshot","dirty":false,"values":[]}},"constraints":null,"uniqueNames":[],"transforms":{},"objType":"$BLOBS_COLLECTION$","dirty":false,"cachedIndex":null,"cachedBinaryIndex":null,"cachedData":null,"adaptiveBinaryIndices":true,"transactional":false,"cloneObjects":false,"cloneMethod":"parse-stringify","asyncListeners":false,"disableMeta":false,"disableChangesApi":true,"disableDeltaChangesApi":true,"autoupdate":false,"serializableIndices":true,"disableFreeze":true,"ttl":null,"maxId":0,"DynamicViews":[],"events":{"insert":[],"update":[],"pre-insert":[],"pre-update":[],"close":[],"flushbuffer":[],"error":[],"delete":[null],"warning":[null]},"changes":[],"dirtyIds":[]},{"name":"$BLOCKS_COLLECTION$","data":[],"idIndex":null,"binaryIndices":{"accountName":{"name":"accountName","dirty":false,"values":[]},"containerName":{"name":"containerName","dirty":false,"values":[]},"blobName":{"name":"blobName","dirty":false,"values":[]},"name":{"name":"name","dirty":false,"values":[]}},"constraints":null,"uniqueNames":[],"transforms":{},"objType":"$BLOCKS_COLLECTION$","dirty":false,"cachedIndex":null,"cachedBinaryIndex":null,"cachedData":null,"adaptiveBinaryIndices":true,"transactional":false,"cloneObjects":false,"cloneMethod":"parse-stringify","asyncListeners":false,"disableMeta":false,"disableChangesApi":true,"disableDeltaChangesApi":true,"autoupdate":false,"serializableIndices":true,"disableFreeze":true,"ttl":null,"maxId":0,"DynamicViews":[],"events":{"insert":[],"update":[],"pre-insert":[],"pre-update":[],"close":[],"flushbuffer":[],"error":[],"delete":[null],"warning":[null]},"changes":[],"dirtyIds":[]}],"databaseVersion":1.5,"engineVersion":1.5,"autosave":true,"autosaveInterval":5000,"autosaveHandle":null,"throttledSaves":true,"options":{"persistenceMethod":"fs","autosave":true,"autosaveInterval":5000,"serializationMethod":"normal","destructureDelimiter":"$<\n"},"persistenceMethod":"fs","persistenceAdapter":null,"verbose":false,"events":{"init":[null],"loaded":[],"flushChanges":[],"close":[],"changes":[],"warning":[]},"ENV":"NODEJS"} \ No newline at end of file diff --git a/__azurite_db_blob_extent__.json b/__azurite_db_blob_extent__.json new file mode 100644 index 00000000..06515548 --- /dev/null +++ b/__azurite_db_blob_extent__.json @@ -0,0 +1 @@ +{"filename":"c:\\Users\\evanroman\\source\\repos\\azure-functions-nodejs-e2e-tests\\__azurite_db_blob_extent__.json","collections":[{"name":"$EXTENTS_COLLECTION$","data":[],"idIndex":null,"binaryIndices":{"id":{"name":"id","dirty":false,"values":[]}},"constraints":null,"uniqueNames":[],"transforms":{},"objType":"$EXTENTS_COLLECTION$","dirty":false,"cachedIndex":null,"cachedBinaryIndex":null,"cachedData":null,"adaptiveBinaryIndices":true,"transactional":false,"cloneObjects":false,"cloneMethod":"parse-stringify","asyncListeners":false,"disableMeta":false,"disableChangesApi":true,"disableDeltaChangesApi":true,"autoupdate":false,"serializableIndices":true,"disableFreeze":true,"ttl":null,"maxId":0,"DynamicViews":[],"events":{"insert":[],"update":[],"pre-insert":[],"pre-update":[],"close":[],"flushbuffer":[],"error":[],"delete":[null],"warning":[null]},"changes":[],"dirtyIds":[]}],"databaseVersion":1.5,"engineVersion":1.5,"autosave":true,"autosaveInterval":5000,"autosaveHandle":null,"throttledSaves":true,"options":{"persistenceMethod":"fs","autosave":true,"autosaveInterval":5000,"serializationMethod":"normal","destructureDelimiter":"$<\n"},"persistenceMethod":"fs","persistenceAdapter":null,"verbose":false,"events":{"init":[null],"loaded":[],"flushChanges":[],"close":[],"changes":[],"warning":[]},"ENV":"NODEJS"} \ No newline at end of file diff --git a/src/storage.test.ts b/src/storage.test.ts index b6624ea1..ae659dad 100644 --- a/src/storage.test.ts +++ b/src/storage.test.ts @@ -10,7 +10,7 @@ import { waitForOutput } from './global.test'; import { getRandomTestData } from './utils/getRandomTestData'; import { storageConnectionString } from './utils/connectionStrings'; -// describe('storage', () => { +describe('storage', () => { // it('queue trigger and output', async () => { // const client = new QueueClient(storageConnectionString, 'e2e-test-queue-trigger-and-output'); // await client.createIfNotExists(); From 5f2cc67ee5d1ddcb739ce19392edf9df8ac0ad2d Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Mon, 21 Jul 2025 14:18:12 -0500 Subject: [PATCH 003/142] test --- src/index.ts | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/index.ts b/src/index.ts index 69118ba6..0c52d1c2 100644 --- a/src/index.ts +++ b/src/index.ts @@ -6,16 +6,9 @@ import Mocha from 'mocha'; import path from 'path'; import { defaultTimeout } from './constants'; import { getModelArg, getOldConfigArg } from './getModelArg'; -import yargs from 'yargs'; export async function run(): Promise { try { - const argv = yargs(process.argv.slice(2)).option('exclude', { - type: 'string', - description: 'Glob pattern of tests to exclude', - }).parseSync(); - const excludePattern = argv.exclude ? [argv.exclude] : []; - const oldConfigSuffix = getOldConfigArg() ? '_oldConfig' : ''; const fileName = `${process.platform}_model-${getModelArg()}_Node-${process.version}${oldConfigSuffix}.xml`; const options: Mocha.MochaOptions = { @@ -34,7 +27,7 @@ export async function run(): Promise { const mocha = new Mocha(options); - const files: string[] = await globby(['**/**.test.js', ...excludePattern.map(p => `!${p}`)], { cwd: __dirname }); + const files: string[] = await globby('**/**.test.js', { cwd: __dirname }); files.forEach((f) => mocha.addFile(path.resolve(__dirname, f))); From bae5c5114a0f5749fefa3daf8379e305c8e3b720 Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Mon, 21 Jul 2025 14:49:17 -0500 Subject: [PATCH 004/142] test --- app/v3/storageBlobTrigger/index.ts | 16 +++--- app/v3/storageBlobTriggerAndOutput/index.ts | 18 +++---- .../storageBlobTriggerSharedOutputBug.ts | 52 +++++++++---------- 3 files changed, 43 insertions(+), 43 deletions(-) diff --git a/app/v3/storageBlobTrigger/index.ts b/app/v3/storageBlobTrigger/index.ts index 5f2003e3..2bd017fe 100644 --- a/app/v3/storageBlobTrigger/index.ts +++ b/app/v3/storageBlobTrigger/index.ts @@ -1,11 +1,11 @@ -// // Copyright (c) .NET Foundation. All rights reserved. -// // Licensed under the MIT License. +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT License. -// import { AzureFunction, Context } from '@azure/functions'; +import { AzureFunction, Context } from '@azure/functions'; -// const blobTrigger: AzureFunction = async function (context: Context, myBlob: any): Promise { -// const blobPath = context.bindingData.blobTrigger; -// context.log(`storageBlobTrigger was triggered by blob "${blobPath}" with content "${myBlob.toString()}"`); -// }; +const blobTrigger: AzureFunction = async function (context: Context, myBlob: any): Promise { + const blobPath = context.bindingData.blobTrigger; + context.log(`storageBlobTrigger was triggered by blob "${blobPath}" with content "${myBlob.toString()}"`); +}; -// export default blobTrigger; +export default blobTrigger; diff --git a/app/v3/storageBlobTriggerAndOutput/index.ts b/app/v3/storageBlobTriggerAndOutput/index.ts index b195e84f..67d5c723 100644 --- a/app/v3/storageBlobTriggerAndOutput/index.ts +++ b/app/v3/storageBlobTriggerAndOutput/index.ts @@ -1,12 +1,12 @@ -// // Copyright (c) .NET Foundation. All rights reserved. -// // Licensed under the MIT License. +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT License. -// import { AzureFunction, Context } from '@azure/functions'; +import { AzureFunction, Context } from '@azure/functions'; -// const blobTrigger: AzureFunction = async function (context: Context, myBlob: any): Promise { -// const blobPath = context.bindingData.blobTrigger; -// context.log(`storageBlobTriggerAndOutput was triggered by blob "${blobPath}" with content "${myBlob.toString()}"`); -// return myBlob; -// }; +const blobTrigger: AzureFunction = async function (context: Context, myBlob: any): Promise { + const blobPath = context.bindingData.blobTrigger; + context.log(`storageBlobTriggerAndOutput was triggered by blob "${blobPath}" with content "${myBlob.toString()}"`); + return myBlob; +}; -// export default blobTrigger; +export default blobTrigger; diff --git a/app/v4/src/functions/storageBlobTriggerSharedOutputBug.ts b/app/v4/src/functions/storageBlobTriggerSharedOutputBug.ts index 99d1eb1c..8c4d824e 100644 --- a/app/v4/src/functions/storageBlobTriggerSharedOutputBug.ts +++ b/app/v4/src/functions/storageBlobTriggerSharedOutputBug.ts @@ -1,31 +1,31 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the MIT License. +// // Copyright (c) .NET Foundation. All rights reserved. +// // Licensed under the MIT License. -import { app, InvocationContext, output } from '@azure/functions'; +// import { app, InvocationContext, output } from '@azure/functions'; -// Test for bug https://github.com/Azure/azure-functions-nodejs-library/issues/179 +// // Test for bug https://github.com/Azure/azure-functions-nodejs-library/issues/179 -const queueOutput = output.storageQueue({ - queueName: 'e2e-test-queue-trigger', - connection: 'AzureWebJobsStorage', -}); +// const queueOutput = output.storageQueue({ +// queueName: 'e2e-test-queue-trigger', +// connection: 'AzureWebJobsStorage', +// }); -app.storageBlob('storageBlobTriggerReturnOutput', { - path: 'e2e-test-container/e2e-test-blob-trigger-shared-output-bug', - connection: 'AzureWebJobsStorage', - return: queueOutput, - handler: (blob: Buffer, context: InvocationContext) => { - context.log(`storageBlobTriggerReturnOutput was triggered`); - return `${blob.toString()}-returnOutput`; - }, -}); +// app.storageBlob('storageBlobTriggerReturnOutput', { +// path: 'e2e-test-container/e2e-test-blob-trigger-shared-output-bug', +// connection: 'AzureWebJobsStorage', +// return: queueOutput, +// handler: (blob: Buffer, context: InvocationContext) => { +// context.log(`storageBlobTriggerReturnOutput was triggered`); +// return `${blob.toString()}-returnOutput`; +// }, +// }); -app.storageBlob('storageBlobTriggerExtraOutput', { - path: 'e2e-test-container/e2e-test-blob-trigger-shared-output-bug', - connection: 'AzureWebJobsStorage', - extraOutputs: [queueOutput], - handler: (blob: Buffer, context: InvocationContext) => { - context.log(`storageBlobTriggerExtraOutput was triggered`); - context.extraOutputs.set(queueOutput, `${blob.toString()}-extraOutput`); - }, -}); +// app.storageBlob('storageBlobTriggerExtraOutput', { +// path: 'e2e-test-container/e2e-test-blob-trigger-shared-output-bug', +// connection: 'AzureWebJobsStorage', +// extraOutputs: [queueOutput], +// handler: (blob: Buffer, context: InvocationContext) => { +// context.log(`storageBlobTriggerExtraOutput was triggered`); +// context.extraOutputs.set(queueOutput, `${blob.toString()}-extraOutput`); +// }, +// }); From 655b7a3bbe59fc3d349fe74254a7d7e11eb3d376 Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Mon, 21 Jul 2025 15:12:12 -0500 Subject: [PATCH 005/142] test --- .../storageBlobTriggerSharedOutputBug.ts | 52 +++++++++---------- src/storage.test.ts | 36 ++++++------- 2 files changed, 44 insertions(+), 44 deletions(-) diff --git a/app/v4/src/functions/storageBlobTriggerSharedOutputBug.ts b/app/v4/src/functions/storageBlobTriggerSharedOutputBug.ts index 8c4d824e..99d1eb1c 100644 --- a/app/v4/src/functions/storageBlobTriggerSharedOutputBug.ts +++ b/app/v4/src/functions/storageBlobTriggerSharedOutputBug.ts @@ -1,31 +1,31 @@ -// // Copyright (c) .NET Foundation. All rights reserved. -// // Licensed under the MIT License. +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT License. -// import { app, InvocationContext, output } from '@azure/functions'; +import { app, InvocationContext, output } from '@azure/functions'; -// // Test for bug https://github.com/Azure/azure-functions-nodejs-library/issues/179 +// Test for bug https://github.com/Azure/azure-functions-nodejs-library/issues/179 -// const queueOutput = output.storageQueue({ -// queueName: 'e2e-test-queue-trigger', -// connection: 'AzureWebJobsStorage', -// }); +const queueOutput = output.storageQueue({ + queueName: 'e2e-test-queue-trigger', + connection: 'AzureWebJobsStorage', +}); -// app.storageBlob('storageBlobTriggerReturnOutput', { -// path: 'e2e-test-container/e2e-test-blob-trigger-shared-output-bug', -// connection: 'AzureWebJobsStorage', -// return: queueOutput, -// handler: (blob: Buffer, context: InvocationContext) => { -// context.log(`storageBlobTriggerReturnOutput was triggered`); -// return `${blob.toString()}-returnOutput`; -// }, -// }); +app.storageBlob('storageBlobTriggerReturnOutput', { + path: 'e2e-test-container/e2e-test-blob-trigger-shared-output-bug', + connection: 'AzureWebJobsStorage', + return: queueOutput, + handler: (blob: Buffer, context: InvocationContext) => { + context.log(`storageBlobTriggerReturnOutput was triggered`); + return `${blob.toString()}-returnOutput`; + }, +}); -// app.storageBlob('storageBlobTriggerExtraOutput', { -// path: 'e2e-test-container/e2e-test-blob-trigger-shared-output-bug', -// connection: 'AzureWebJobsStorage', -// extraOutputs: [queueOutput], -// handler: (blob: Buffer, context: InvocationContext) => { -// context.log(`storageBlobTriggerExtraOutput was triggered`); -// context.extraOutputs.set(queueOutput, `${blob.toString()}-extraOutput`); -// }, -// }); +app.storageBlob('storageBlobTriggerExtraOutput', { + path: 'e2e-test-container/e2e-test-blob-trigger-shared-output-bug', + connection: 'AzureWebJobsStorage', + extraOutputs: [queueOutput], + handler: (blob: Buffer, context: InvocationContext) => { + context.log(`storageBlobTriggerExtraOutput was triggered`); + context.extraOutputs.set(queueOutput, `${blob.toString()}-extraOutput`); + }, +}); diff --git a/src/storage.test.ts b/src/storage.test.ts index ae659dad..c3ece231 100644 --- a/src/storage.test.ts +++ b/src/storage.test.ts @@ -6,7 +6,7 @@ import { ContainerClient } from '@azure/storage-blob'; // import { expect } from 'chai'; // import { default as fetch } from 'node-fetch'; // import { getFuncUrl } from './constants'; -import { waitForOutput } from './global.test'; +import { model, waitForOutput } from './global.test'; import { getRandomTestData } from './utils/getRandomTestData'; import { storageConnectionString } from './utils/connectionStrings'; @@ -85,23 +85,23 @@ describe('storage', () => { // }); // Test for bug https://github.com/Azure/azure-functions-nodejs-library/issues/179 - // it('Shared output bug', async function (this: Mocha.Context) { - // if (model === 'v3') { - // this.skip(); - // } + it('Shared output bug', async function (this: Mocha.Context) { + if (model === 'v3') { + this.skip(); + } - // const containerName = 'e2e-test-container'; - // const client = new ContainerClient(storageConnectionString, containerName); - // await client.createIfNotExists(); + const containerName = 'e2e-test-container'; + const client = new ContainerClient(storageConnectionString, containerName); + await client.createIfNotExists(); - // const message = getRandomTestData(); - // const messageBuffer = Buffer.from(message); - // const blobName = 'e2e-test-blob-trigger-shared-output-bug'; - // await client.uploadBlockBlob(blobName, messageBuffer, messageBuffer.byteLength); - - // await waitForOutput(`storageBlobTriggerReturnOutput was triggered`); - // await waitForOutput(`storageBlobTriggerExtraOutput was triggered`); - // await waitForOutput(`storageQueueTrigger was triggered by "${message}-returnOutput"`); - // await waitForOutput(`storageQueueTrigger was triggered by "${message}-extraOutput"`); - // }); + const message = getRandomTestData(); + const messageBuffer = Buffer.from(message); + const blobName = 'e2e-test-blob-trigger-shared-output-bug'; + await client.uploadBlockBlob(blobName, messageBuffer, messageBuffer.byteLength); + + await waitForOutput(`storageBlobTriggerReturnOutput was triggered`); + await waitForOutput(`storageBlobTriggerExtraOutput was triggered`); + await waitForOutput(`storageQueueTrigger was triggered by "${message}-returnOutput"`); + await waitForOutput(`storageQueueTrigger was triggered by "${message}-extraOutput"`); + }); }); From 655abcd3bfe7d5cb54cfba2505e68c7e038ce2f1 Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Mon, 21 Jul 2025 15:30:02 -0500 Subject: [PATCH 006/142] test --- __azurite_db_blob__.json | 1 - __azurite_db_blob_extent__.json | 1 - app/v3/httpTriggerStorageQueueOutput/index.ts | 22 +++---- app/v3/storageQueueTrigger/index.ts | 14 ++-- app/v3/storageQueueTriggerAndOutput/index.ts | 16 ++--- .../httpTriggerStorageQueueOutput.ts | 42 ++++++------ app/v4/src/functions/storageQueueTrigger.ts | 22 +++---- .../functions/storageQueueTriggerAndOutput.ts | 32 +++++----- src/storage.test.ts | 64 +++++++++---------- 9 files changed, 106 insertions(+), 108 deletions(-) delete mode 100644 __azurite_db_blob__.json delete mode 100644 __azurite_db_blob_extent__.json diff --git a/__azurite_db_blob__.json b/__azurite_db_blob__.json deleted file mode 100644 index 4d82d705..00000000 --- a/__azurite_db_blob__.json +++ /dev/null @@ -1 +0,0 @@ -{"filename":"c:\\Users\\evanroman\\source\\repos\\azure-functions-nodejs-e2e-tests\\__azurite_db_blob__.json","collections":[{"name":"$SERVICES_COLLECTION$","data":[],"idIndex":null,"binaryIndices":{},"constraints":null,"uniqueNames":["accountName"],"transforms":{},"objType":"$SERVICES_COLLECTION$","dirty":false,"cachedIndex":null,"cachedBinaryIndex":null,"cachedData":null,"adaptiveBinaryIndices":true,"transactional":false,"cloneObjects":false,"cloneMethod":"parse-stringify","asyncListeners":false,"disableMeta":false,"disableChangesApi":true,"disableDeltaChangesApi":true,"autoupdate":false,"serializableIndices":true,"disableFreeze":true,"ttl":null,"maxId":0,"DynamicViews":[],"events":{"insert":[],"update":[],"pre-insert":[],"pre-update":[],"close":[],"flushbuffer":[],"error":[],"delete":[null],"warning":[null]},"changes":[],"dirtyIds":[]},{"name":"$CONTAINERS_COLLECTION$","data":[],"idIndex":null,"binaryIndices":{"accountName":{"name":"accountName","dirty":false,"values":[]},"name":{"name":"name","dirty":false,"values":[]}},"constraints":null,"uniqueNames":[],"transforms":{},"objType":"$CONTAINERS_COLLECTION$","dirty":false,"cachedIndex":null,"cachedBinaryIndex":null,"cachedData":null,"adaptiveBinaryIndices":true,"transactional":false,"cloneObjects":false,"cloneMethod":"parse-stringify","asyncListeners":false,"disableMeta":false,"disableChangesApi":true,"disableDeltaChangesApi":true,"autoupdate":false,"serializableIndices":true,"disableFreeze":true,"ttl":null,"maxId":0,"DynamicViews":[],"events":{"insert":[],"update":[],"pre-insert":[],"pre-update":[],"close":[],"flushbuffer":[],"error":[],"delete":[null],"warning":[null]},"changes":[],"dirtyIds":[]},{"name":"$BLOBS_COLLECTION$","data":[],"idIndex":null,"binaryIndices":{"accountName":{"name":"accountName","dirty":false,"values":[]},"containerName":{"name":"containerName","dirty":false,"values":[]},"name":{"name":"name","dirty":false,"values":[]},"snapshot":{"name":"snapshot","dirty":false,"values":[]}},"constraints":null,"uniqueNames":[],"transforms":{},"objType":"$BLOBS_COLLECTION$","dirty":false,"cachedIndex":null,"cachedBinaryIndex":null,"cachedData":null,"adaptiveBinaryIndices":true,"transactional":false,"cloneObjects":false,"cloneMethod":"parse-stringify","asyncListeners":false,"disableMeta":false,"disableChangesApi":true,"disableDeltaChangesApi":true,"autoupdate":false,"serializableIndices":true,"disableFreeze":true,"ttl":null,"maxId":0,"DynamicViews":[],"events":{"insert":[],"update":[],"pre-insert":[],"pre-update":[],"close":[],"flushbuffer":[],"error":[],"delete":[null],"warning":[null]},"changes":[],"dirtyIds":[]},{"name":"$BLOCKS_COLLECTION$","data":[],"idIndex":null,"binaryIndices":{"accountName":{"name":"accountName","dirty":false,"values":[]},"containerName":{"name":"containerName","dirty":false,"values":[]},"blobName":{"name":"blobName","dirty":false,"values":[]},"name":{"name":"name","dirty":false,"values":[]}},"constraints":null,"uniqueNames":[],"transforms":{},"objType":"$BLOCKS_COLLECTION$","dirty":false,"cachedIndex":null,"cachedBinaryIndex":null,"cachedData":null,"adaptiveBinaryIndices":true,"transactional":false,"cloneObjects":false,"cloneMethod":"parse-stringify","asyncListeners":false,"disableMeta":false,"disableChangesApi":true,"disableDeltaChangesApi":true,"autoupdate":false,"serializableIndices":true,"disableFreeze":true,"ttl":null,"maxId":0,"DynamicViews":[],"events":{"insert":[],"update":[],"pre-insert":[],"pre-update":[],"close":[],"flushbuffer":[],"error":[],"delete":[null],"warning":[null]},"changes":[],"dirtyIds":[]}],"databaseVersion":1.5,"engineVersion":1.5,"autosave":true,"autosaveInterval":5000,"autosaveHandle":null,"throttledSaves":true,"options":{"persistenceMethod":"fs","autosave":true,"autosaveInterval":5000,"serializationMethod":"normal","destructureDelimiter":"$<\n"},"persistenceMethod":"fs","persistenceAdapter":null,"verbose":false,"events":{"init":[null],"loaded":[],"flushChanges":[],"close":[],"changes":[],"warning":[]},"ENV":"NODEJS"} \ No newline at end of file diff --git a/__azurite_db_blob_extent__.json b/__azurite_db_blob_extent__.json deleted file mode 100644 index 06515548..00000000 --- a/__azurite_db_blob_extent__.json +++ /dev/null @@ -1 +0,0 @@ -{"filename":"c:\\Users\\evanroman\\source\\repos\\azure-functions-nodejs-e2e-tests\\__azurite_db_blob_extent__.json","collections":[{"name":"$EXTENTS_COLLECTION$","data":[],"idIndex":null,"binaryIndices":{"id":{"name":"id","dirty":false,"values":[]}},"constraints":null,"uniqueNames":[],"transforms":{},"objType":"$EXTENTS_COLLECTION$","dirty":false,"cachedIndex":null,"cachedBinaryIndex":null,"cachedData":null,"adaptiveBinaryIndices":true,"transactional":false,"cloneObjects":false,"cloneMethod":"parse-stringify","asyncListeners":false,"disableMeta":false,"disableChangesApi":true,"disableDeltaChangesApi":true,"autoupdate":false,"serializableIndices":true,"disableFreeze":true,"ttl":null,"maxId":0,"DynamicViews":[],"events":{"insert":[],"update":[],"pre-insert":[],"pre-update":[],"close":[],"flushbuffer":[],"error":[],"delete":[null],"warning":[null]},"changes":[],"dirtyIds":[]}],"databaseVersion":1.5,"engineVersion":1.5,"autosave":true,"autosaveInterval":5000,"autosaveHandle":null,"throttledSaves":true,"options":{"persistenceMethod":"fs","autosave":true,"autosaveInterval":5000,"serializationMethod":"normal","destructureDelimiter":"$<\n"},"persistenceMethod":"fs","persistenceAdapter":null,"verbose":false,"events":{"init":[null],"loaded":[],"flushChanges":[],"close":[],"changes":[],"warning":[]},"ENV":"NODEJS"} \ No newline at end of file diff --git a/app/v3/httpTriggerStorageQueueOutput/index.ts b/app/v3/httpTriggerStorageQueueOutput/index.ts index 8a663ae4..3f3252c0 100644 --- a/app/v3/httpTriggerStorageQueueOutput/index.ts +++ b/app/v3/httpTriggerStorageQueueOutput/index.ts @@ -1,14 +1,14 @@ -// // Copyright (c) .NET Foundation. All rights reserved. -// // Licensed under the MIT License. +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT License. -// import { AzureFunction, Context, HttpRequest } from '@azure/functions'; +import { AzureFunction, Context, HttpRequest } from '@azure/functions'; -// const httpTriggerStorageQueueOutput: AzureFunction = async function ( -// context: Context, -// request: HttpRequest -// ): Promise { -// context.bindings.outputMsg = request.body.output; -// context.res = { body: 'done' }; -// }; +const httpTriggerStorageQueueOutput: AzureFunction = async function ( + context: Context, + request: HttpRequest +): Promise { + context.bindings.outputMsg = request.body.output; + context.res = { body: 'done' }; +}; -// export default httpTriggerStorageQueueOutput; +export default httpTriggerStorageQueueOutput; diff --git a/app/v3/storageQueueTrigger/index.ts b/app/v3/storageQueueTrigger/index.ts index bd4359bb..8986179e 100644 --- a/app/v3/storageQueueTrigger/index.ts +++ b/app/v3/storageQueueTrigger/index.ts @@ -1,10 +1,10 @@ -// // Copyright (c) .NET Foundation. All rights reserved. -// // Licensed under the MIT License. +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT License. -// import { AzureFunction, Context } from '@azure/functions'; +import { AzureFunction, Context } from '@azure/functions'; -// const queueTrigger: AzureFunction = async function (context: Context, myQueueItem: string): Promise { -// context.log(`storageQueueTrigger was triggered by "${myQueueItem}"`); -// }; +const queueTrigger: AzureFunction = async function (context: Context, myQueueItem: string): Promise { + context.log(`storageQueueTrigger was triggered by "${myQueueItem}"`); +}; -// export default queueTrigger; +export default queueTrigger; diff --git a/app/v3/storageQueueTriggerAndOutput/index.ts b/app/v3/storageQueueTriggerAndOutput/index.ts index 458f91ef..79ee5283 100644 --- a/app/v3/storageQueueTriggerAndOutput/index.ts +++ b/app/v3/storageQueueTriggerAndOutput/index.ts @@ -1,11 +1,11 @@ -// // Copyright (c) .NET Foundation. All rights reserved. -// // Licensed under the MIT License. +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT License. -// import { AzureFunction, Context } from '@azure/functions'; +import { AzureFunction, Context } from '@azure/functions'; -// const queueTrigger: AzureFunction = async function (context: Context, myQueueItem: string): Promise { -// context.log(`storageQueueTriggerAndOutput was triggered by "${myQueueItem}"`); -// return myQueueItem; -// }; +const queueTrigger: AzureFunction = async function (context: Context, myQueueItem: string): Promise { + context.log(`storageQueueTriggerAndOutput was triggered by "${myQueueItem}"`); + return myQueueItem; +}; -// export default queueTrigger; +export default queueTrigger; diff --git a/app/v4/src/functions/httpTriggerStorageQueueOutput.ts b/app/v4/src/functions/httpTriggerStorageQueueOutput.ts index 53d9b2a2..5b853fd8 100644 --- a/app/v4/src/functions/httpTriggerStorageQueueOutput.ts +++ b/app/v4/src/functions/httpTriggerStorageQueueOutput.ts @@ -1,25 +1,25 @@ -// // Copyright (c) .NET Foundation. All rights reserved. -// // Licensed under the MIT License. +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT License. -// import { app, HttpRequest, HttpResponseInit, InvocationContext, output } from '@azure/functions'; +import { app, HttpRequest, HttpResponseInit, InvocationContext, output } from '@azure/functions'; -// const storageOutput = output.storageQueue({ -// queueName: 'e2e-test-queue-trigger', -// connection: 'e2eTest_storage', -// }); +const storageOutput = output.storageQueue({ + queueName: 'e2e-test-queue-trigger', + connection: 'AzureWebJobsStorage', +}); -// export async function httpTriggerStorageQueueOutput( -// request: HttpRequest, -// context: InvocationContext -// ): Promise { -// const body = <{ output: any }>await request.json(); -// context.extraOutputs.set(storageOutput, body.output); -// return { body: 'done' }; -// } +export async function httpTriggerStorageQueueOutput( + request: HttpRequest, + context: InvocationContext +): Promise { + const body = <{ output: any }>await request.json(); + context.extraOutputs.set(storageOutput, body.output); + return { body: 'done' }; +} -// app.http('httpTriggerStorageQueueOutput', { -// methods: ['POST'], -// authLevel: 'anonymous', -// extraOutputs: [storageOutput], -// handler: httpTriggerStorageQueueOutput, -// }); +app.http('httpTriggerStorageQueueOutput', { + methods: ['POST'], + authLevel: 'anonymous', + extraOutputs: [storageOutput], + handler: httpTriggerStorageQueueOutput, +}); diff --git a/app/v4/src/functions/storageQueueTrigger.ts b/app/v4/src/functions/storageQueueTrigger.ts index a11895e1..3cce0a19 100644 --- a/app/v4/src/functions/storageQueueTrigger.ts +++ b/app/v4/src/functions/storageQueueTrigger.ts @@ -1,14 +1,14 @@ -// // Copyright (c) .NET Foundation. All rights reserved. -// // Licensed under the MIT License. +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT License. -// import { app, InvocationContext } from '@azure/functions'; +import { app, InvocationContext } from '@azure/functions'; -// export async function storageQueueTrigger(queueItem: string, context: InvocationContext): Promise { -// context.log(`storageQueueTrigger was triggered by "${queueItem}"`); -// } +export async function storageQueueTrigger(queueItem: string, context: InvocationContext): Promise { + context.log(`storageQueueTrigger was triggered by "${queueItem}"`); +} -// app.storageQueue('storageQueueTrigger', { -// queueName: 'e2e-test-queue-trigger', -// connection: 'e2eTest_storage', -// handler: storageQueueTrigger, -// }); +app.storageQueue('storageQueueTrigger', { + queueName: 'e2e-test-queue-trigger', + connection: 'AzureWebJobsStorage', + handler: storageQueueTrigger, +}); diff --git a/app/v4/src/functions/storageQueueTriggerAndOutput.ts b/app/v4/src/functions/storageQueueTriggerAndOutput.ts index faa110b2..2c5efc4e 100644 --- a/app/v4/src/functions/storageQueueTriggerAndOutput.ts +++ b/app/v4/src/functions/storageQueueTriggerAndOutput.ts @@ -1,19 +1,19 @@ -// // Copyright (c) .NET Foundation. All rights reserved. -// // Licensed under the MIT License. +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT License. -// import { app, InvocationContext, output } from '@azure/functions'; +import { app, InvocationContext, output } from '@azure/functions'; -// export async function storageQueueTriggerAndOutput(queueItem: string, context: InvocationContext): Promise { -// context.log(`storageQueueTriggerAndOutput was triggered by "${queueItem}"`); -// return queueItem; -// } +export async function storageQueueTriggerAndOutput(queueItem: string, context: InvocationContext): Promise { + context.log(`storageQueueTriggerAndOutput was triggered by "${queueItem}"`); + return queueItem; +} -// app.storageQueue('storageQueueTriggerAndOutput', { -// queueName: 'e2e-test-queue-trigger-and-output', -// connection: 'e2eTest_storage', -// return: output.storageQueue({ -// queueName: 'e2e-test-queue-trigger', -// connection: 'e2eTest_storage', -// }), -// handler: storageQueueTriggerAndOutput, -// }); +app.storageQueue('storageQueueTriggerAndOutput', { + queueName: 'e2e-test-queue-trigger-and-output', + connection: 'AzureWebJobsStorage', + return: output.storageQueue({ + queueName: 'e2e-test-queue-trigger', + connection: 'AzureWebJobsStorage', + }), + handler: storageQueueTriggerAndOutput, +}); diff --git a/src/storage.test.ts b/src/storage.test.ts index c3ece231..ff8a2ccb 100644 --- a/src/storage.test.ts +++ b/src/storage.test.ts @@ -2,44 +2,44 @@ // Licensed under the MIT License. import { ContainerClient } from '@azure/storage-blob'; -// import { QueueClient } from '@azure/storage-queue'; +import { QueueClient } from '@azure/storage-queue'; // import { expect } from 'chai'; -// import { default as fetch } from 'node-fetch'; -// import { getFuncUrl } from './constants'; +import { default as fetch } from 'node-fetch'; +import { getFuncUrl } from './constants'; import { model, waitForOutput } from './global.test'; import { getRandomTestData } from './utils/getRandomTestData'; import { storageConnectionString } from './utils/connectionStrings'; describe('storage', () => { -// it('queue trigger and output', async () => { -// const client = new QueueClient(storageConnectionString, 'e2e-test-queue-trigger-and-output'); -// await client.createIfNotExists(); - -// const message = getRandomTestData(); -// await client.sendMessage(Buffer.from(message).toString('base64')); - -// await waitForOutput(`storageQueueTriggerAndOutput was triggered by "${message}"`); -// await waitForOutput(`storageQueueTrigger was triggered by "${message}"`); -// }); - - // it('queue extra output', async () => { - // const url = getFuncUrl('httpTriggerStorageQueueOutput'); - - // // single - // const message = getRandomTestData(); - // await fetch(url, { method: 'POST', body: JSON.stringify({ output: message }) }); - // await waitForOutput(`storageQueueTrigger was triggered by "${message}"`); - - // // bulk - // const bulkMsgs: string[] = []; - // for (let i = 0; i < 5; i++) { - // bulkMsgs.push(getRandomTestData()); - // } - // await fetch(url, { method: 'POST', body: JSON.stringify({ output: bulkMsgs }) }); - // for (const msg of bulkMsgs) { - // await waitForOutput(`storageQueueTrigger was triggered by "${msg}"`); - // } - // }); + it('queue trigger and output', async () => { + const client = new QueueClient(storageConnectionString, 'e2e-test-queue-trigger-and-output'); + await client.createIfNotExists(); + + const message = getRandomTestData(); + await client.sendMessage(Buffer.from(message).toString('base64')); + + await waitForOutput(`storageQueueTriggerAndOutput was triggered by "${message}"`); + await waitForOutput(`storageQueueTrigger was triggered by "${message}"`); + }); + + it('queue extra output', async () => { + const url = getFuncUrl('httpTriggerStorageQueueOutput'); + + // single + const message = getRandomTestData(); + await fetch(url, { method: 'POST', body: JSON.stringify({ output: message }) }); + await waitForOutput(`storageQueueTrigger was triggered by "${message}"`); + + // bulk + const bulkMsgs: string[] = []; + for (let i = 0; i < 5; i++) { + bulkMsgs.push(getRandomTestData()); + } + await fetch(url, { method: 'POST', body: JSON.stringify({ output: bulkMsgs }) }); + for (const msg of bulkMsgs) { + await waitForOutput(`storageQueueTrigger was triggered by "${msg}"`); + } + }); it('blob trigger and output', async () => { const containerName = 'e2e-test-container'; From 3da7543ce4a132140738287ae494915c95de9585 Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Mon, 21 Jul 2025 17:38:57 -0500 Subject: [PATCH 007/142] retry --- .../templates/test-node-version.yml | 5 ++++ src/constants.ts | 7 +++++ src/global.test.ts | 4 ++- src/utils/connectionStrings.ts | 2 ++ src/utils/servicebus/config.json | 28 ------------------- src/utils/servicebus/docker-compose.yml | 0 6 files changed, 17 insertions(+), 29 deletions(-) delete mode 100644 src/utils/servicebus/config.json delete mode 100644 src/utils/servicebus/docker-compose.yml diff --git a/azure-pipelines/templates/test-node-version.yml b/azure-pipelines/templates/test-node-version.yml index 380696db..788736b2 100644 --- a/azure-pipelines/templates/test-node-version.yml +++ b/azure-pipelines/templates/test-node-version.yml @@ -11,6 +11,11 @@ steps: versionSpec: ${{ parameters.nodeVersion }} displayName: 'Install Node ${{ parameters.nodeVersion }}' retryCountOnTaskFailure: 10 + - bash: | + docker pull mcr.microsoft.com/cosmosdb/linux/azure-cosmos-emulator:vnext-preview + docker run --detach --publish 8081:8081 --publish 1234:1234 mcr.microsoft.com/cosmosdb/linux/azure-cosmos-emulator:vnext-preview + docker ps + displayName: "Start CosmosDB Emulator" - bash: | docker compose -f src/utils/eventhub/docker-compose.yml pull docker compose -f src/utils/eventhub/docker-compose.yml up -d diff --git a/src/constants.ts b/src/constants.ts index 894caf79..1716da19 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -3,9 +3,16 @@ export namespace EnvVarNames { export const storage = 'AzureWebJobsStorage'; + export const cosmosDB = 'CosmosDBConnection'; export const eventHub = 'EventHubConnection'; } +export namespace CosmosDB { + export const dbName = 'e2eTestDB'; + export const triggerAndOutputContainerName = 'e2eTestContainerTriggerAndOutput'; + export const triggerContainerName = 'e2eTestContainerTrigger'; +} + export namespace EventHub { export const eventHubOneTriggerAndOutput = 'e2e-test-hub-one-trigger-and-output'; export const eventHubManyTriggerAndOutput = 'e2e-test-hub-many-trigger-and-output'; diff --git a/src/global.test.ts b/src/global.test.ts index f07a6118..cb3cbd5e 100644 --- a/src/global.test.ts +++ b/src/global.test.ts @@ -8,6 +8,7 @@ import semver from 'semver'; import { combinedFolder, defaultTimeout, EnvVarNames, oldConfigSuffix } from './constants'; import { getModelArg, getOldConfigArg, Model } from './getModelArg'; import { + cosmosDBConnectionString, eventHubConnectionString, initializeConnectionStrings, storageConnectionString @@ -107,9 +108,10 @@ async function startFuncProcess(appPath: string): Promise { { IsEncrypted: false, Values: { - [EnvVarNames.storage]: storageConnectionString, FUNCTIONS_WORKER_RUNTIME: 'node', logging__logLevel__Worker: 'debug', + [EnvVarNames.storage]: storageConnectionString, + [EnvVarNames.cosmosDB]: cosmosDBConnectionString, [EnvVarNames.eventHub]: eventHubConnectionString, FUNCTIONS_REQUEST_BODY_SIZE_LIMIT: '4294967296', }, diff --git a/src/utils/connectionStrings.ts b/src/utils/connectionStrings.ts index ed8cecc3..e65db531 100644 --- a/src/utils/connectionStrings.ts +++ b/src/utils/connectionStrings.ts @@ -2,9 +2,11 @@ // Licensed under the MIT License. export let storageConnectionString: string; +export let cosmosDBConnectionString: string; export let eventHubConnectionString: string; export async function initializeConnectionStrings(): Promise { storageConnectionString = "UseDevelopmentStorage=true"; + cosmosDBConnectionString = "AccountEndpoint=http://localhost:8081/;AccountKey=C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw=="; eventHubConnectionString = "Endpoint=sb://localhost;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=SAS_KEY_VALUE;UseDevelopmentEmulator=true;"; } diff --git a/src/utils/servicebus/config.json b/src/utils/servicebus/config.json deleted file mode 100644 index 20cf8344..00000000 --- a/src/utils/servicebus/config.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "UserConfig": { - "Namespaces": [ - { - "Name": "sbemulatorns", - "Queues": [ - { - "Name": "testqueue", - "Properties": { - "DeadLetteringOnMessageExpiration": false, - "DefaultMessageTimeToLive": "PT1H", - "DuplicateDetectionHistoryTimeWindow": "PT20S", - "ForwardDeadLetteredMessagesTo": "", - "ForwardTo": "", - "LockDuration": "PT1M", - "MaxDeliveryCount": 10, - "RequiresDuplicateDetection": false, - "RequiresSession": false - } - } - ] - } - ], - "Logging": { - "Type": "File" - } - } -} \ No newline at end of file diff --git a/src/utils/servicebus/docker-compose.yml b/src/utils/servicebus/docker-compose.yml deleted file mode 100644 index e69de29b..00000000 From 2314cce8ff5bbd18ed0475e2c949b12fd850a3f1 Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Mon, 21 Jul 2025 17:49:15 -0500 Subject: [PATCH 008/142] retry --- app/v3-oldConfig/cosmosDBTrigger/function.json | 2 +- app/v3-oldConfig/cosmosDBTriggerAndOutput/function.json | 4 ++-- app/v3-oldConfig/httpTriggerCosmosDBInput/function.json | 2 +- app/v3-oldConfig/httpTriggerCosmosDBOutput/function.json | 2 +- app/v3/cosmosDBTrigger/function.json | 2 +- app/v3/cosmosDBTriggerAndOutput/function.json | 4 ++-- app/v3/httpTriggerCosmosDBInput/function.json | 2 +- app/v3/httpTriggerCosmosDBOutput/function.json | 2 +- app/v4-oldConfig/src/functions/cosmosDBTrigger.ts | 2 +- app/v4-oldConfig/src/functions/cosmosDBTriggerAndOutput.ts | 4 ++-- app/v4-oldConfig/src/functions/httpTriggerCosmosDBInput.ts | 2 +- app/v4-oldConfig/src/functions/httpTriggerCosmosDBOutput.ts | 2 +- app/v4/src/functions/cosmosDBTrigger.ts | 2 +- app/v4/src/functions/cosmosDBTriggerAndOutput.ts | 4 ++-- app/v4/src/functions/httpTriggerCosmosDBInput.ts | 2 +- app/v4/src/functions/httpTriggerCosmosDBOutput.ts | 2 +- 16 files changed, 20 insertions(+), 20 deletions(-) diff --git a/app/v3-oldConfig/cosmosDBTrigger/function.json b/app/v3-oldConfig/cosmosDBTrigger/function.json index 900e5d06..702e4a80 100644 --- a/app/v3-oldConfig/cosmosDBTrigger/function.json +++ b/app/v3-oldConfig/cosmosDBTrigger/function.json @@ -5,7 +5,7 @@ "name": "documents", "direction": "in", "leaseCollectionName": "leases", - "connectionStringSetting": "e2eTest_cosmosDB", + "connectionStringSetting": "CosmosDBConnection", "databaseName": "e2eTestDB", "collectionName": "e2eTestContainerTrigger", "createLeaseCollectionIfNotExists": true, diff --git a/app/v3-oldConfig/cosmosDBTriggerAndOutput/function.json b/app/v3-oldConfig/cosmosDBTriggerAndOutput/function.json index 154511d4..19be81df 100644 --- a/app/v3-oldConfig/cosmosDBTriggerAndOutput/function.json +++ b/app/v3-oldConfig/cosmosDBTriggerAndOutput/function.json @@ -5,7 +5,7 @@ "name": "documents", "direction": "in", "leaseCollectionName": "leases", - "connectionStringSetting": "e2eTest_cosmosDB", + "connectionStringSetting": "CosmosDBConnection", "databaseName": "e2eTestDB", "collectionName": "e2eTestContainerTriggerAndOutput", "createLeaseCollectionIfNotExists": true, @@ -15,7 +15,7 @@ "type": "cosmosDB", "name": "$return", "direction": "out", - "connectionStringSetting": "e2eTest_cosmosDB", + "connectionStringSetting": "CosmosDBConnection", "databaseName": "e2eTestDB", "collectionName": "e2eTestContainerTrigger" } diff --git a/app/v3-oldConfig/httpTriggerCosmosDBInput/function.json b/app/v3-oldConfig/httpTriggerCosmosDBInput/function.json index f454fcaf..5f0426c3 100644 --- a/app/v3-oldConfig/httpTriggerCosmosDBInput/function.json +++ b/app/v3-oldConfig/httpTriggerCosmosDBInput/function.json @@ -16,7 +16,7 @@ "type": "cosmosDB", "name": "inputDoc", "direction": "in", - "connectionStringSetting": "e2eTest_cosmosDB", + "connectionStringSetting": "CosmosDBConnection", "databaseName": "e2eTestDB", "collectionName": "e2eTestContainerTriggerAndOutput", "partitionKey": "testPartKey", diff --git a/app/v3-oldConfig/httpTriggerCosmosDBOutput/function.json b/app/v3-oldConfig/httpTriggerCosmosDBOutput/function.json index 6d99f5b7..9e9aeee4 100644 --- a/app/v3-oldConfig/httpTriggerCosmosDBOutput/function.json +++ b/app/v3-oldConfig/httpTriggerCosmosDBOutput/function.json @@ -16,7 +16,7 @@ "type": "cosmosDB", "name": "outputDoc", "direction": "out", - "connectionStringSetting": "e2eTest_cosmosDB", + "connectionStringSetting": "CosmosDBConnection", "databaseName": "e2eTestDB", "collectionName": "e2eTestContainerTriggerAndOutput" } diff --git a/app/v3/cosmosDBTrigger/function.json b/app/v3/cosmosDBTrigger/function.json index 7f560a63..02e9d917 100644 --- a/app/v3/cosmosDBTrigger/function.json +++ b/app/v3/cosmosDBTrigger/function.json @@ -5,7 +5,7 @@ "name": "documents", "direction": "in", "leaseContainerName": "leases", - "connection": "e2eTest_cosmosDB", + "connection": "CosmosDBConnection", "databaseName": "e2eTestDB", "containerName": "e2eTestContainerTrigger", "createLeaseContainerIfNotExists": true, diff --git a/app/v3/cosmosDBTriggerAndOutput/function.json b/app/v3/cosmosDBTriggerAndOutput/function.json index 96881bdf..7c9d7487 100644 --- a/app/v3/cosmosDBTriggerAndOutput/function.json +++ b/app/v3/cosmosDBTriggerAndOutput/function.json @@ -5,7 +5,7 @@ "name": "documents", "direction": "in", "leaseContainerName": "leases", - "connection": "e2eTest_cosmosDB", + "connection": "CosmosDBConnection", "databaseName": "e2eTestDB", "containerName": "e2eTestContainerTriggerAndOutput", "createLeaseContainerIfNotExists": true, @@ -15,7 +15,7 @@ "type": "cosmosDB", "name": "$return", "direction": "out", - "connection": "e2eTest_cosmosDB", + "connection": "CosmosDBConnection", "databaseName": "e2eTestDB", "containerName": "e2eTestContainerTrigger" } diff --git a/app/v3/httpTriggerCosmosDBInput/function.json b/app/v3/httpTriggerCosmosDBInput/function.json index d3ddeb95..fb8d4232 100644 --- a/app/v3/httpTriggerCosmosDBInput/function.json +++ b/app/v3/httpTriggerCosmosDBInput/function.json @@ -16,7 +16,7 @@ "type": "cosmosDB", "name": "inputDoc", "direction": "in", - "connection": "e2eTest_cosmosDB", + "connection": "CosmosDBConnection", "databaseName": "e2eTestDB", "containerName": "e2eTestContainerTriggerAndOutput", "partitionKey": "testPartKey", diff --git a/app/v3/httpTriggerCosmosDBOutput/function.json b/app/v3/httpTriggerCosmosDBOutput/function.json index cfc7a368..fc540372 100644 --- a/app/v3/httpTriggerCosmosDBOutput/function.json +++ b/app/v3/httpTriggerCosmosDBOutput/function.json @@ -16,7 +16,7 @@ "type": "cosmosDB", "name": "outputDoc", "direction": "out", - "connection": "e2eTest_cosmosDB", + "connection": "CosmosDBConnection", "databaseName": "e2eTestDB", "containerName": "e2eTestContainerTriggerAndOutput" } diff --git a/app/v4-oldConfig/src/functions/cosmosDBTrigger.ts b/app/v4-oldConfig/src/functions/cosmosDBTrigger.ts index a04a233c..bdec0a40 100644 --- a/app/v4-oldConfig/src/functions/cosmosDBTrigger.ts +++ b/app/v4-oldConfig/src/functions/cosmosDBTrigger.ts @@ -11,7 +11,7 @@ // } // app.cosmosDB('cosmosDBTrigger', { -// connectionStringSetting: 'e2eTest_cosmosDB', +// connectionStringSetting: 'CosmosDBConnection', // databaseName: 'e2eTestDB', // collectionName: 'e2eTestContainerTrigger', // createLeaseCollectionIfNotExists: true, diff --git a/app/v4-oldConfig/src/functions/cosmosDBTriggerAndOutput.ts b/app/v4-oldConfig/src/functions/cosmosDBTriggerAndOutput.ts index fbc87c7f..89eda8f4 100644 --- a/app/v4-oldConfig/src/functions/cosmosDBTriggerAndOutput.ts +++ b/app/v4-oldConfig/src/functions/cosmosDBTriggerAndOutput.ts @@ -12,13 +12,13 @@ // } // app.cosmosDB('cosmosDBTriggerAndOutput', { -// connectionStringSetting: 'e2eTest_cosmosDB', +// connectionStringSetting: 'CosmosDBConnection', // databaseName: 'e2eTestDB', // collectionName: 'e2eTestContainerTriggerAndOutput', // createLeaseCollectionIfNotExists: true, // leaseCollectionPrefix: '1', // return: output.cosmosDB({ -// connectionStringSetting: 'e2eTest_cosmosDB', +// connectionStringSetting: 'CosmosDBConnection', // databaseName: 'e2eTestDB', // collectionName: 'e2eTestContainerTrigger', // }), diff --git a/app/v4-oldConfig/src/functions/httpTriggerCosmosDBInput.ts b/app/v4-oldConfig/src/functions/httpTriggerCosmosDBInput.ts index 96bb41a7..7c65e72e 100644 --- a/app/v4-oldConfig/src/functions/httpTriggerCosmosDBInput.ts +++ b/app/v4-oldConfig/src/functions/httpTriggerCosmosDBInput.ts @@ -8,7 +8,7 @@ // collectionName: 'e2eTestContainerTriggerAndOutput', // id: '{Query.id}', // partitionKey: 'testPartKey', -// connectionStringSetting: 'e2eTest_cosmosDB', +// connectionStringSetting: 'CosmosDBConnection', // }); // export async function httpTriggerCosmosDBInput( diff --git a/app/v4-oldConfig/src/functions/httpTriggerCosmosDBOutput.ts b/app/v4-oldConfig/src/functions/httpTriggerCosmosDBOutput.ts index 9383420c..35740acb 100644 --- a/app/v4-oldConfig/src/functions/httpTriggerCosmosDBOutput.ts +++ b/app/v4-oldConfig/src/functions/httpTriggerCosmosDBOutput.ts @@ -6,7 +6,7 @@ // const cosmosOutput = output.cosmosDB({ // databaseName: 'e2eTestDB', // collectionName: 'e2eTestContainerTrigger', -// connectionStringSetting: 'e2eTest_cosmosDB', +// connectionStringSetting: 'CosmosDBConnection', // }); // export async function httpTriggerCosmosDBOutput( diff --git a/app/v4/src/functions/cosmosDBTrigger.ts b/app/v4/src/functions/cosmosDBTrigger.ts index 832f7d91..b32e3c03 100644 --- a/app/v4/src/functions/cosmosDBTrigger.ts +++ b/app/v4/src/functions/cosmosDBTrigger.ts @@ -11,7 +11,7 @@ // } // app.cosmosDB('cosmosDBTrigger', { -// connection: 'e2eTest_cosmosDB', +// connection: 'CosmosDBConnection', // databaseName: 'e2eTestDB', // containerName: 'e2eTestContainerTrigger', // createLeaseContainerIfNotExists: true, diff --git a/app/v4/src/functions/cosmosDBTriggerAndOutput.ts b/app/v4/src/functions/cosmosDBTriggerAndOutput.ts index d96785cb..37099504 100644 --- a/app/v4/src/functions/cosmosDBTriggerAndOutput.ts +++ b/app/v4/src/functions/cosmosDBTriggerAndOutput.ts @@ -12,13 +12,13 @@ // } // app.cosmosDB('cosmosDBTriggerAndOutput', { -// connection: 'e2eTest_cosmosDB', +// connection: 'CosmosDBConnection', // databaseName: 'e2eTestDB', // containerName: 'e2eTestContainerTriggerAndOutput', // createLeaseContainerIfNotExists: true, // leaseContainerPrefix: '1', // return: output.cosmosDB({ -// connection: 'e2eTest_cosmosDB', +// connection: 'CosmosDBConnection', // databaseName: 'e2eTestDB', // containerName: 'e2eTestContainerTrigger', // }), diff --git a/app/v4/src/functions/httpTriggerCosmosDBInput.ts b/app/v4/src/functions/httpTriggerCosmosDBInput.ts index 0ff46291..25e0f4fd 100644 --- a/app/v4/src/functions/httpTriggerCosmosDBInput.ts +++ b/app/v4/src/functions/httpTriggerCosmosDBInput.ts @@ -8,7 +8,7 @@ // containerName: 'e2eTestContainerTriggerAndOutput', // id: '{Query.id}', // partitionKey: 'testPartKey', -// connection: 'e2eTest_cosmosDB', +// connection: 'CosmosDBConnection', // }); // export async function httpTriggerCosmosDBInput( diff --git a/app/v4/src/functions/httpTriggerCosmosDBOutput.ts b/app/v4/src/functions/httpTriggerCosmosDBOutput.ts index 1f56ab29..12eeb42b 100644 --- a/app/v4/src/functions/httpTriggerCosmosDBOutput.ts +++ b/app/v4/src/functions/httpTriggerCosmosDBOutput.ts @@ -6,7 +6,7 @@ // const cosmosOutput = output.cosmosDB({ // databaseName: 'e2eTestDB', // containerName: 'e2eTestContainerTrigger', -// connection: 'e2eTest_cosmosDB', +// connection: 'CosmosDBConnection', // }); // export async function httpTriggerCosmosDBOutput( From 288f20cc3b93c75000c9afe61bed1618ed964520 Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Mon, 21 Jul 2025 19:18:38 -0500 Subject: [PATCH 009/142] add --- app/v4/src/functions/cosmosDBTrigger.ts | 34 ++++++------ .../src/functions/cosmosDBTriggerAndOutput.ts | 46 ++++++++-------- src/cosmosDB.test.ts | 53 +++++++++++++++++++ 3 files changed, 93 insertions(+), 40 deletions(-) create mode 100644 src/cosmosDB.test.ts diff --git a/app/v4/src/functions/cosmosDBTrigger.ts b/app/v4/src/functions/cosmosDBTrigger.ts index b32e3c03..1f5a5041 100644 --- a/app/v4/src/functions/cosmosDBTrigger.ts +++ b/app/v4/src/functions/cosmosDBTrigger.ts @@ -1,20 +1,20 @@ -// // Copyright (c) .NET Foundation. All rights reserved. -// // Licensed under the MIT License. +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT License. -// import { app, InvocationContext } from '@azure/functions'; +import { app, InvocationContext } from '@azure/functions'; -// export async function cosmosDBTrigger(documents: unknown[], context: InvocationContext): Promise { -// context.log(`cosmosDBTrigger processed ${documents.length} documents`); -// for (const document of documents) { -// context.log(`cosmosDBTrigger was triggered by "${(document).testData}"`); -// } -// } +export async function cosmosDBTrigger(documents: unknown[], context: InvocationContext): Promise { + context.log(`cosmosDBTrigger processed ${documents.length} documents`); + for (const document of documents) { + context.log(`cosmosDBTrigger was triggered by "${(document).testData}"`); + } +} -// app.cosmosDB('cosmosDBTrigger', { -// connection: 'CosmosDBConnection', -// databaseName: 'e2eTestDB', -// containerName: 'e2eTestContainerTrigger', -// createLeaseContainerIfNotExists: true, -// leaseContainerPrefix: '2', -// handler: cosmosDBTrigger, -// }); +app.cosmosDB('cosmosDBTrigger', { + connection: 'CosmosDBConnection', + databaseName: 'e2eTestDB', + containerName: 'e2eTestContainerTrigger', + createLeaseContainerIfNotExists: true, + leaseContainerPrefix: '2', + handler: cosmosDBTrigger, +}); diff --git a/app/v4/src/functions/cosmosDBTriggerAndOutput.ts b/app/v4/src/functions/cosmosDBTriggerAndOutput.ts index 37099504..f658b801 100644 --- a/app/v4/src/functions/cosmosDBTriggerAndOutput.ts +++ b/app/v4/src/functions/cosmosDBTriggerAndOutput.ts @@ -1,26 +1,26 @@ -// // Copyright (c) .NET Foundation. All rights reserved. -// // Licensed under the MIT License. +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT License. -// import { app, InvocationContext, output } from '@azure/functions'; +import { app, InvocationContext, output } from '@azure/functions'; -// export async function cosmosDBTriggerAndOutput(documents: unknown[], context: InvocationContext): Promise { -// context.log(`cosmosDBTriggerAndOutput processed ${documents.length} documents`); -// for (const document of documents) { -// context.log(`cosmosDBTriggerAndOutput was triggered by "${(document).testData}"`); -// } -// return documents; -// } +export async function cosmosDBTriggerAndOutput(documents: unknown[], context: InvocationContext): Promise { + context.log(`cosmosDBTriggerAndOutput processed ${documents.length} documents`); + for (const document of documents) { + context.log(`cosmosDBTriggerAndOutput was triggered by "${(document).testData}"`); + } + return documents; +} -// app.cosmosDB('cosmosDBTriggerAndOutput', { -// connection: 'CosmosDBConnection', -// databaseName: 'e2eTestDB', -// containerName: 'e2eTestContainerTriggerAndOutput', -// createLeaseContainerIfNotExists: true, -// leaseContainerPrefix: '1', -// return: output.cosmosDB({ -// connection: 'CosmosDBConnection', -// databaseName: 'e2eTestDB', -// containerName: 'e2eTestContainerTrigger', -// }), -// handler: cosmosDBTriggerAndOutput, -// }); +app.cosmosDB('cosmosDBTriggerAndOutput', { + connection: 'CosmosDBConnection', + databaseName: 'e2eTestDB', + containerName: 'e2eTestContainerTriggerAndOutput', + createLeaseContainerIfNotExists: true, + leaseContainerPrefix: '1', + return: output.cosmosDB({ + connection: 'CosmosDBConnection', + databaseName: 'e2eTestDB', + containerName: 'e2eTestContainerTrigger', + }), + handler: cosmosDBTriggerAndOutput, +}); diff --git a/src/cosmosDB.test.ts b/src/cosmosDB.test.ts new file mode 100644 index 00000000..b134a953 --- /dev/null +++ b/src/cosmosDB.test.ts @@ -0,0 +1,53 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT License. + +import { CosmosClient } from '@azure/cosmos'; +import { expect } from 'chai'; +import { default as fetch } from 'node-fetch'; +import { getFuncUrl, CosmosDB } from './constants'; +import { waitForOutput } from './global.test'; +import { cosmosDBConnectionString } from './utils/connectionStrings'; +import { getRandomTestData } from './utils/getRandomTestData'; + +describe('cosmosDB', () => { + it('trigger, output, input', async () => { + const client = new CosmosClient(cosmosDBConnectionString); + const container = client.database(CosmosDB.dbName).container(CosmosDB.triggerAndOutputContainerName); + const testData = getRandomTestData(); + const createdItem = await container.items.create({ testData, _partitionKey: 'testPartKey' }); + + await waitForOutput(`cosmosDBTriggerAndOutput processed 1 documents`); + await waitForOutput(`cosmosDBTriggerAndOutput was triggered by "${testData}"`); + await waitForOutput(`cosmosDBTrigger processed 1 documents`); + await waitForOutput(`cosmosDBTrigger was triggered by "${testData}"`); + + const url = `${getFuncUrl('httpTriggerCosmosDBInput')}?id=${createdItem.item.id}`; + const response = await fetch(url); + const body = await response.text(); + expect(body).to.equal(testData); + }); + + it('extra output', async () => { + type Doc = { id: string; testData: string }; + function getDoc(): Doc { + const data = getRandomTestData(); + return { id: data, testData: data }; + } + const url = getFuncUrl('httpTriggerCosmosDBOutput'); + + // single doc + const singleDoc = getDoc(); + await fetch(url, { method: 'POST', body: JSON.stringify(singleDoc) }); + await waitForOutput(`cosmosDBTrigger was triggered by "${singleDoc.testData}"`); + + // bulk docs + const bulkDocs: Doc[] = []; + for (let i = 0; i < 5; i++) { + bulkDocs.push(getDoc()); + } + await fetch(url, { method: 'POST', body: JSON.stringify(bulkDocs) }); + for (const doc of bulkDocs) { + await waitForOutput(`cosmosDBTrigger was triggered by "${doc.testData}"`); + } + }); +}); \ No newline at end of file From 1879fcbb7ddda70b910871b9ad4f30a22b206233 Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Tue, 22 Jul 2025 02:40:22 -0500 Subject: [PATCH 010/142] make explicit --- src/constants.ts | 1 + src/global.test.ts | 3 +++ src/utils/azureCli.ts | 50 -------------------------------------- src/utils/setupCosmosDB.ts | 16 ++++++++++++ 4 files changed, 20 insertions(+), 50 deletions(-) delete mode 100644 src/utils/azureCli.ts create mode 100644 src/utils/setupCosmosDB.ts diff --git a/src/constants.ts b/src/constants.ts index 1716da19..63ca0ff9 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -11,6 +11,7 @@ export namespace CosmosDB { export const dbName = 'e2eTestDB'; export const triggerAndOutputContainerName = 'e2eTestContainerTriggerAndOutput'; export const triggerContainerName = 'e2eTestContainerTrigger'; + export const triggerDatabaseName = 'e2eTestDB'; } export namespace EventHub { diff --git a/src/global.test.ts b/src/global.test.ts index cb3cbd5e..f0472763 100644 --- a/src/global.test.ts +++ b/src/global.test.ts @@ -13,6 +13,7 @@ import { initializeConnectionStrings, storageConnectionString } from './utils/connectionStrings'; +import { setupCosmosDB } from './utils/setupCosmosDB'; import { delay } from './utils/delay'; import findProcess = require('find-process'); @@ -39,6 +40,8 @@ before(async function (this: Mocha.Context): Promise { await initializeConnectionStrings(); + await setupCosmosDB(); + isOldConfig = getOldConfigArg(); const appPath = isOldConfig ? path.join(__dirname, '..', 'app', combinedFolder, model + oldConfigSuffix) diff --git a/src/utils/azureCli.ts b/src/utils/azureCli.ts deleted file mode 100644 index cc7e6f8a..00000000 --- a/src/utils/azureCli.ts +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the MIT License. - -import * as cp from 'child_process'; - -export async function getSubscriptionId(): Promise { - return executeCommand('az account show --query id -o tsv'); -} - -export async function getTenantId(): Promise { - return executeCommand('az account show --query tenantId -o tsv'); -} - -export async function getUserName(): Promise { - return executeCommand('az account show --query user.name -o tsv'); -} - -export async function getUserType(): Promise { - return executeCommand('az account show --query user.type -o tsv'); -} - -export async function getObjectId(userName: string): Promise { - const adCmd = (await getUserType()) === 'user' ? 'user' : 'sp'; - return executeCommand(`az ad ${adCmd} show --id ${userName} --query id -o tsv`); -} - -async function executeCommand(command: string): Promise { - return new Promise((resolve, reject) => { - let stdout = ''; - - const childProc = cp.spawn(command, { shell: true }); - - childProc.stdout?.on('data', (data) => { - stdout += data.toString(); - }); - - childProc.stderr?.on('data', (data) => { - console.error(data.toString()); - }); - - childProc.on('error', reject); - childProc.on('close', (code: number) => { - if (code === 0) { - resolve(stdout.trim()); - } else { - reject(new Error(`Command "${command}" failed with exit code ${code}`)); - } - }); - }); -} diff --git a/src/utils/setupCosmosDB.ts b/src/utils/setupCosmosDB.ts new file mode 100644 index 00000000..7767e750 --- /dev/null +++ b/src/utils/setupCosmosDB.ts @@ -0,0 +1,16 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT License. + +// The CosmosDB emulator requires a container and database to be created before running tests but after the emulator starts +// Otherwise the following error will occur: +// Microsoft.Azure.Cosmos.Client: This builder instance has already been used to build a processor. Create a new instance to build another. + +import { CosmosClient } from '@azure/cosmos'; +import { cosmosDBConnectionString } from './connectionStrings'; +import { CosmosDB } from '../constants'; + +export async function setupCosmosDB() { + const client = new CosmosClient(cosmosDBConnectionString); + await client.databases.createIfNotExists({ id: CosmosDB.triggerDatabaseName }); + await client.database(CosmosDB.triggerDatabaseName).containers.createIfNotExists({ id: CosmosDB.triggerAndOutputContainerName }); +} \ No newline at end of file From 3cbab29ceff4e0c122e579c555510bb743c2b92f Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Tue, 22 Jul 2025 10:11:46 -0500 Subject: [PATCH 011/142] update --- package-lock.json | 325 +++++++++++++++++++++++++++------------------- package.json | 2 +- 2 files changed, 194 insertions(+), 133 deletions(-) diff --git a/package-lock.json b/package-lock.json index 0b84cf79..74e081dd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,7 +16,7 @@ "@azure/arm-servicebus": "^6.1.0", "@azure/arm-sql": "^10.0.0", "@azure/arm-storage": "^18.1.0", - "@azure/cosmos": "^3.17.3", + "@azure/cosmos": "^4.5.0", "@azure/data-tables": "^13.2.2", "@azure/event-hubs": "^5.10.0", "@azure/identity": "^3.4.2", @@ -71,6 +71,46 @@ "node": ">=0.10.0" } }, + "node_modules/@azure-rest/core-client": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@azure-rest/core-client/-/core-client-2.5.0.tgz", + "integrity": "sha512-KMVIPxG6ygcQ1M2hKHahF7eddKejYsWTjoLIfTWiqnaj42dBkYzj4+S8rK9xxmlOaEHKZHcMrRbm0NfN4kgwHw==", + "dependencies": { + "@azure/abort-controller": "^2.0.0", + "@azure/core-auth": "^1.9.0", + "@azure/core-rest-pipeline": "^1.5.0", + "@azure/core-tracing": "^1.0.1", + "@typespec/ts-http-runtime": "^0.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@azure-rest/core-client/node_modules/@azure/abort-controller": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-2.1.2.tgz", + "integrity": "sha512-nBrLsEWm4J2u5LpAPjxADTlq3trDgVZZXHNKabeXZtpq3d3AbN/KGO82R87rdDz5/lYB024rtEf10/q0urNgsA==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@azure-rest/core-client/node_modules/@typespec/ts-http-runtime": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@typespec/ts-http-runtime/-/ts-http-runtime-0.3.0.tgz", + "integrity": "sha512-sOx1PKSuFwnIl7z4RN0Ls7N9AQawmR9r66eI5rFCzLDIs8HTIYrIpH9QjYWoX0lkgGrkLxXhi4QnK7MizPRrIg==", + "dependencies": { + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, "node_modules/@azure/abort-controller": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-1.1.0.tgz", @@ -298,13 +338,13 @@ } }, "node_modules/@azure/core-http-compat": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@azure/core-http-compat/-/core-http-compat-2.1.2.tgz", - "integrity": "sha512-5MnV1yqzZwgNLLjlizsU3QqOeQChkIXw781Fwh1xdAqJR5AA32IUaq6xv1BICJvfbHoa+JYcaij2HFkhLbNTJQ==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@azure/core-http-compat/-/core-http-compat-2.3.0.tgz", + "integrity": "sha512-qLQujmUypBBG0gxHd0j6/Jdmul6ttl24c8WGiLXIk7IHXdBlfoBqW27hyz3Xn6xbfdyVSarl1Ttbk0AwnZBYCw==", "dependencies": { "@azure/abort-controller": "^2.0.0", "@azure/core-client": "^1.3.0", - "@azure/core-rest-pipeline": "^1.3.0" + "@azure/core-rest-pipeline": "^1.20.0" }, "engines": { "node": ">=18.0.0" @@ -342,47 +382,80 @@ } }, "node_modules/@azure/core-lro": { - "version": "2.5.4", - "resolved": "https://registry.npmjs.org/@azure/core-lro/-/core-lro-2.5.4.tgz", - "integrity": "sha512-3GJiMVH7/10bulzOKGrrLeG/uCBH/9VtxqaMcB9lIqAeamI/xYQSHJL/KcsLDuH+yTjYpro/u6D/MuRe4dN70Q==", + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/@azure/core-lro/-/core-lro-2.7.2.tgz", + "integrity": "sha512-0YIpccoX8m/k00O7mDDMdJpbr6mf1yWo2dfmxt5A8XVZVVMz2SSKaEbMCeJRvgQ0IaSlqhjT47p4hVIRRy90xw==", "dependencies": { - "@azure/abort-controller": "^1.0.0", + "@azure/abort-controller": "^2.0.0", "@azure/core-util": "^1.2.0", "@azure/logger": "^1.0.0", - "tslib": "^2.2.0" + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=18.0.0" + } + }, + "node_modules/@azure/core-lro/node_modules/@azure/abort-controller": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-2.1.2.tgz", + "integrity": "sha512-nBrLsEWm4J2u5LpAPjxADTlq3trDgVZZXHNKabeXZtpq3d3AbN/KGO82R87rdDz5/lYB024rtEf10/q0urNgsA==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" } }, "node_modules/@azure/core-paging": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@azure/core-paging/-/core-paging-1.5.0.tgz", - "integrity": "sha512-zqWdVIt+2Z+3wqxEOGzR5hXFZ8MGKK52x4vFLw8n58pR6ZfKRx3EXYTxTaYxYHc/PexPUTyimcTWFJbji9Z6Iw==", + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/@azure/core-paging/-/core-paging-1.6.2.tgz", + "integrity": "sha512-YKWi9YuCU04B55h25cnOYZHxXYtEvQEbKST5vqRga7hWY9ydd3FZHdeQF8pyh+acWZvppw13M/LMGx0LABUVMA==", "dependencies": { - "tslib": "^2.2.0" + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=18.0.0" } }, "node_modules/@azure/core-rest-pipeline": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@azure/core-rest-pipeline/-/core-rest-pipeline-1.12.1.tgz", - "integrity": "sha512-SsyWQ+T5MFQRX+M8H/66AlaI6HyCbQStGfFngx2fuiW+vKI2DkhtOvbYodPyf9fOe/ARLWWc3ohX54lQ5Kmaog==", + "version": "1.22.0", + "resolved": "https://registry.npmjs.org/@azure/core-rest-pipeline/-/core-rest-pipeline-1.22.0.tgz", + "integrity": "sha512-OKHmb3/Kpm06HypvB3g6Q3zJuvyXcpxDpCS1PnU8OV6AJgSFaee/covXBcPbWc6XDDxtEPlbi3EMQ6nUiPaQtw==", "dependencies": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-auth": "^1.4.0", + "@azure/abort-controller": "^2.0.0", + "@azure/core-auth": "^1.8.0", "@azure/core-tracing": "^1.0.1", - "@azure/core-util": "^1.3.0", + "@azure/core-util": "^1.11.0", "@azure/logger": "^1.0.0", - "form-data": "^4.0.0", - "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.0", - "tslib": "^2.2.0" + "@typespec/ts-http-runtime": "^0.3.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=20.0.0" + } + }, + "node_modules/@azure/core-rest-pipeline/node_modules/@azure/abort-controller": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-2.1.2.tgz", + "integrity": "sha512-nBrLsEWm4J2u5LpAPjxADTlq3trDgVZZXHNKabeXZtpq3d3AbN/KGO82R87rdDz5/lYB024rtEf10/q0urNgsA==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@azure/core-rest-pipeline/node_modules/@typespec/ts-http-runtime": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@typespec/ts-http-runtime/-/ts-http-runtime-0.3.0.tgz", + "integrity": "sha512-sOx1PKSuFwnIl7z4RN0Ls7N9AQawmR9r66eI5rFCzLDIs8HTIYrIpH9QjYWoX0lkgGrkLxXhi4QnK7MizPRrIg==", + "dependencies": { + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" } }, "node_modules/@azure/core-tracing": { @@ -433,34 +506,35 @@ } }, "node_modules/@azure/cosmos": { - "version": "3.17.3", - "resolved": "https://registry.npmjs.org/@azure/cosmos/-/cosmos-3.17.3.tgz", - "integrity": "sha512-wBglkQ6Irjv5Vo2iw8fd6eYj60WYRSSg4/0DBkeOP6BwQ4RA91znsOHd6s3qG6UAbNgYuzC9Nnq07vlFFZkHEw==", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/@azure/cosmos/-/cosmos-4.5.0.tgz", + "integrity": "sha512-JsTh4twb6FcwP7rJwxQiNZQ/LGtuF6gmciaxY9Rnp6/A325Lhsw/SH4R2ArpT0yCvozbZpweIwdPfUkXVBtp5w==", "dependencies": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-auth": "^1.3.0", - "@azure/core-rest-pipeline": "^1.2.0", - "@azure/core-tracing": "^1.0.0", - "debug": "^4.1.1", + "@azure/abort-controller": "^2.1.2", + "@azure/core-auth": "^1.9.0", + "@azure/core-rest-pipeline": "^1.19.1", + "@azure/core-tracing": "^1.2.0", + "@azure/core-util": "^1.11.0", + "@azure/keyvault-keys": "^4.9.0", + "@azure/logger": "^1.1.4", "fast-json-stable-stringify": "^2.1.0", - "jsbi": "^3.1.3", - "node-abort-controller": "^3.0.0", - "priorityqueuejs": "^1.0.0", - "semaphore": "^1.0.5", - "tslib": "^2.2.0", - "universal-user-agent": "^6.0.0", - "uuid": "^8.3.0" + "priorityqueuejs": "^2.0.0", + "semaphore": "^1.1.0", + "tslib": "^2.8.1" }, "engines": { - "node": ">=14.0.0" + "node": ">=20.0.0" } }, - "node_modules/@azure/cosmos/node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "bin": { - "uuid": "dist/bin/uuid" + "node_modules/@azure/cosmos/node_modules/@azure/abort-controller": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-2.1.2.tgz", + "integrity": "sha512-nBrLsEWm4J2u5LpAPjxADTlq3trDgVZZXHNKabeXZtpq3d3AbN/KGO82R87rdDz5/lYB024rtEf10/q0urNgsA==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" } }, "node_modules/@azure/data-tables": { @@ -546,27 +620,68 @@ "node": ">=14.0.0" } }, - "node_modules/@azure/keyvault-keys": { - "version": "4.8.0", - "resolved": "https://registry.npmjs.org/@azure/keyvault-keys/-/keyvault-keys-4.8.0.tgz", - "integrity": "sha512-jkuYxgkw0aaRfk40OQhFqDIupqblIOIlYESWB6DKCVDxQet1pyv86Tfk9M+5uFM0+mCs6+MUHU+Hxh3joiUn4Q==", + "node_modules/@azure/keyvault-common": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@azure/keyvault-common/-/keyvault-common-2.0.0.tgz", + "integrity": "sha512-wRLVaroQtOqfg60cxkzUkGKrKMsCP6uYXAOomOIysSMyt1/YM0eUn9LqieAWM8DLcU4+07Fio2YGpPeqUbpP9w==", "dependencies": { - "@azure/abort-controller": "^1.0.0", + "@azure/abort-controller": "^2.0.0", "@azure/core-auth": "^1.3.0", "@azure/core-client": "^1.5.0", - "@azure/core-http-compat": "^2.0.1", - "@azure/core-lro": "^2.2.0", - "@azure/core-paging": "^1.1.1", - "@azure/core-rest-pipeline": "^1.8.1", + "@azure/core-rest-pipeline": "^1.8.0", "@azure/core-tracing": "^1.0.0", - "@azure/core-util": "^1.0.0", - "@azure/logger": "^1.0.0", + "@azure/core-util": "^1.10.0", + "@azure/logger": "^1.1.4", "tslib": "^2.2.0" }, "engines": { "node": ">=18.0.0" } }, + "node_modules/@azure/keyvault-common/node_modules/@azure/abort-controller": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-2.1.2.tgz", + "integrity": "sha512-nBrLsEWm4J2u5LpAPjxADTlq3trDgVZZXHNKabeXZtpq3d3AbN/KGO82R87rdDz5/lYB024rtEf10/q0urNgsA==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@azure/keyvault-keys": { + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/@azure/keyvault-keys/-/keyvault-keys-4.10.0.tgz", + "integrity": "sha512-eDT7iXoBTRZ2n3fLiftuGJFD+yjkiB1GNqzU2KbY1TLYeXeSPVTVgn2eJ5vmRTZ11978jy2Kg2wI7xa9Tyr8ag==", + "dependencies": { + "@azure-rest/core-client": "^2.3.3", + "@azure/abort-controller": "^2.1.2", + "@azure/core-auth": "^1.9.0", + "@azure/core-http-compat": "^2.2.0", + "@azure/core-lro": "^2.7.2", + "@azure/core-paging": "^1.6.2", + "@azure/core-rest-pipeline": "^1.19.0", + "@azure/core-tracing": "^1.2.0", + "@azure/core-util": "^1.11.0", + "@azure/keyvault-common": "^2.0.0", + "@azure/logger": "^1.1.4", + "tslib": "^2.8.1" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@azure/keyvault-keys/node_modules/@azure/abort-controller": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-2.1.2.tgz", + "integrity": "sha512-nBrLsEWm4J2u5LpAPjxADTlq3trDgVZZXHNKabeXZtpq3d3AbN/KGO82R87rdDz5/lYB024rtEf10/q0urNgsA==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, "node_modules/@azure/logger": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@azure/logger/-/logger-1.2.0.tgz", @@ -1071,14 +1186,6 @@ "resolved": "https://registry.npmjs.org/@tediousjs/connection-string/-/connection-string-0.5.0.tgz", "integrity": "sha512-7qSgZbincDDDFyRweCIEvZULFAw5iz/DeunhvuxpL31nfntX3P4Yd4HkHBRg9H8CdqY1e5WFN1PZIz/REL9MVQ==" }, - "node_modules/@tootallnate/once": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", - "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", - "engines": { - "node": ">= 10" - } - }, "node_modules/@types/chai": { "version": "4.3.8", "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.8.tgz", @@ -1388,38 +1495,6 @@ "node": ">=18.0.0" } }, - "node_modules/@typespec/ts-http-runtime/node_modules/agent-base": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", - "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", - "engines": { - "node": ">= 14" - } - }, - "node_modules/@typespec/ts-http-runtime/node_modules/http-proxy-agent": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", - "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", - "dependencies": { - "agent-base": "^7.1.0", - "debug": "^4.3.4" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/@typespec/ts-http-runtime/node_modules/https-proxy-agent": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", - "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", - "dependencies": { - "agent-base": "^7.1.2", - "debug": "4" - }, - "engines": { - "node": ">= 14" - } - }, "node_modules/@webassemblyjs/ast": { "version": "1.12.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.12.1.tgz", @@ -1609,14 +1684,11 @@ } }, "node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dependencies": { - "debug": "4" - }, + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", + "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", "engines": { - "node": ">= 6.0.0" + "node": ">= 14" } }, "node_modules/agentkeepalive": { @@ -3485,28 +3557,27 @@ } }, "node_modules/http-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", - "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", "dependencies": { - "@tootallnate/once": "2", - "agent-base": "6", - "debug": "4" + "agent-base": "^7.1.0", + "debug": "^4.3.4" }, "engines": { - "node": ">= 6" + "node": ">= 14" } }, "node_modules/https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", "dependencies": { - "agent-base": "6", + "agent-base": "^7.1.2", "debug": "4" }, "engines": { - "node": ">= 6" + "node": ">= 14" } }, "node_modules/humanize-ms": { @@ -3993,11 +4064,6 @@ "js-yaml": "bin/js-yaml.js" } }, - "node_modules/jsbi": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/jsbi/-/jsbi-3.2.5.tgz", - "integrity": "sha512-aBE4n43IPvjaddScbvWRA2YlTzKEynHzu7MqOyTipdHucf/VxS63ViCjxYRg86M8Rxwbt/GfzHl1kKERkt45fQ==" - }, "node_modules/json-buffer": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", @@ -4865,9 +4931,9 @@ } }, "node_modules/priorityqueuejs": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/priorityqueuejs/-/priorityqueuejs-1.0.0.tgz", - "integrity": "sha512-lg++21mreCEOuGWTbO5DnJKAdxfjrdN0S9ysoW9SzdSJvbkWpkaDdpG/cdsPCsEnoLUwmd9m3WcZhngW7yKA2g==" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/priorityqueuejs/-/priorityqueuejs-2.0.0.tgz", + "integrity": "sha512-19BMarhgpq3x4ccvVi8k2QpJZcymo/iFUcrhPd4V96kYGovOdTsWwy7fxChYi4QY+m2EnGBWSX9Buakz+tWNQQ==" }, "node_modules/process": { "version": "0.11.10", @@ -6047,11 +6113,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/universal-user-agent": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz", - "integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==" - }, "node_modules/update-browserslist-db": { "version": "1.0.13", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", diff --git a/package.json b/package.json index 2132f6d1..7b679fae 100644 --- a/package.json +++ b/package.json @@ -42,7 +42,7 @@ "@azure/arm-servicebus": "^6.1.0", "@azure/arm-sql": "^10.0.0", "@azure/arm-storage": "^18.1.0", - "@azure/cosmos": "^3.17.3", + "@azure/cosmos": "^4.5.0", "@azure/data-tables": "^13.2.2", "@azure/event-hubs": "^5.10.0", "@azure/identity": "^3.4.2", From 6c2e04e40c1bda8318f2254dbee8773944e2dda6 Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Tue, 22 Jul 2025 10:33:27 -0500 Subject: [PATCH 012/142] add key --- src/utils/setupCosmosDB.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/utils/setupCosmosDB.ts b/src/utils/setupCosmosDB.ts index 7767e750..ac1415be 100644 --- a/src/utils/setupCosmosDB.ts +++ b/src/utils/setupCosmosDB.ts @@ -12,5 +12,8 @@ import { CosmosDB } from '../constants'; export async function setupCosmosDB() { const client = new CosmosClient(cosmosDBConnectionString); await client.databases.createIfNotExists({ id: CosmosDB.triggerDatabaseName }); - await client.database(CosmosDB.triggerDatabaseName).containers.createIfNotExists({ id: CosmosDB.triggerAndOutputContainerName }); + await client.database(CosmosDB.triggerDatabaseName).containers.createIfNotExists({ + id: CosmosDB.triggerAndOutputContainerName, + partitionKey: { paths: ['/testPartKey'] }, + }); } \ No newline at end of file From b3845f976a9230dae71faa7e036f17fb377485c4 Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Tue, 22 Jul 2025 10:48:56 -0500 Subject: [PATCH 013/142] add --- src/utils/setupCosmosDB.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/utils/setupCosmosDB.ts b/src/utils/setupCosmosDB.ts index ac1415be..12ee507d 100644 --- a/src/utils/setupCosmosDB.ts +++ b/src/utils/setupCosmosDB.ts @@ -5,7 +5,7 @@ // Otherwise the following error will occur: // Microsoft.Azure.Cosmos.Client: This builder instance has already been used to build a processor. Create a new instance to build another. -import { CosmosClient } from '@azure/cosmos'; +import { CosmosClient, PartitionKeyKind } from '@azure/cosmos'; import { cosmosDBConnectionString } from './connectionStrings'; import { CosmosDB } from '../constants'; @@ -14,6 +14,6 @@ export async function setupCosmosDB() { await client.databases.createIfNotExists({ id: CosmosDB.triggerDatabaseName }); await client.database(CosmosDB.triggerDatabaseName).containers.createIfNotExists({ id: CosmosDB.triggerAndOutputContainerName, - partitionKey: { paths: ['/testPartKey'] }, + partitionKey: { paths: ['/testPartKey'], kind: PartitionKeyKind.Hash } }); } \ No newline at end of file From 29e29306de335da9bfabfa64ca64b9d29fc1f6bc Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Tue, 22 Jul 2025 11:00:45 -0500 Subject: [PATCH 014/142] add --- app/v3/cosmosDBTrigger/index.ts | 20 ++++---- app/v3/cosmosDBTriggerAndOutput/index.ts | 22 ++++----- app/v3/httpTriggerCosmosDBInput/index.ts | 24 +++++----- .../src/functions/httpTriggerCosmosDBInput.ts | 46 +++++++++---------- 4 files changed, 56 insertions(+), 56 deletions(-) diff --git a/app/v3/cosmosDBTrigger/index.ts b/app/v3/cosmosDBTrigger/index.ts index 78aea6fb..fe205aad 100644 --- a/app/v3/cosmosDBTrigger/index.ts +++ b/app/v3/cosmosDBTrigger/index.ts @@ -1,13 +1,13 @@ -// // Copyright (c) .NET Foundation. All rights reserved. -// // Licensed under the MIT License. +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT License. -// import { AzureFunction, Context } from '@azure/functions'; +import { AzureFunction, Context } from '@azure/functions'; -// const cosmosDBTrigger: AzureFunction = async function (context: Context, documents: any[]): Promise { -// context.log(`cosmosDBTrigger processed ${documents.length} documents`); -// for (const document of documents) { -// context.log(`cosmosDBTrigger was triggered by "${document.testData}"`); -// } -// }; +const cosmosDBTrigger: AzureFunction = async function (context: Context, documents: any[]): Promise { + context.log(`cosmosDBTrigger processed ${documents.length} documents`); + for (const document of documents) { + context.log(`cosmosDBTrigger was triggered by "${document.testData}"`); + } +}; -// export default cosmosDBTrigger; +export default cosmosDBTrigger; diff --git a/app/v3/cosmosDBTriggerAndOutput/index.ts b/app/v3/cosmosDBTriggerAndOutput/index.ts index 43f42cd3..1eb41f1f 100644 --- a/app/v3/cosmosDBTriggerAndOutput/index.ts +++ b/app/v3/cosmosDBTriggerAndOutput/index.ts @@ -1,14 +1,14 @@ -// // Copyright (c) .NET Foundation. All rights reserved. -// // Licensed under the MIT License. +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT License. -// import { AzureFunction, Context } from '@azure/functions'; +import { AzureFunction, Context } from '@azure/functions'; -// const cosmosDBTrigger: AzureFunction = async function (context: Context, documents: any[]): Promise { -// context.log(`cosmosDBTriggerAndOutput processed ${documents.length} documents`); -// for (const document of documents) { -// context.log(`cosmosDBTriggerAndOutput was triggered by "${document.testData}"`); -// } -// return documents; -// }; +const cosmosDBTrigger: AzureFunction = async function (context: Context, documents: any[]): Promise { + context.log(`cosmosDBTriggerAndOutput processed ${documents.length} documents`); + for (const document of documents) { + context.log(`cosmosDBTriggerAndOutput was triggered by "${document.testData}"`); + } + return documents; +}; -// export default cosmosDBTrigger; +export default cosmosDBTrigger; diff --git a/app/v3/httpTriggerCosmosDBInput/index.ts b/app/v3/httpTriggerCosmosDBInput/index.ts index 28550488..d99e123a 100644 --- a/app/v3/httpTriggerCosmosDBInput/index.ts +++ b/app/v3/httpTriggerCosmosDBInput/index.ts @@ -1,15 +1,15 @@ -// // Copyright (c) .NET Foundation. All rights reserved. -// // Licensed under the MIT License. +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT License. -// import { AzureFunction, Context, HttpRequest } from '@azure/functions'; +import { AzureFunction, Context, HttpRequest } from '@azure/functions'; -// const httpTriggerCosmosDBInput: AzureFunction = async function ( -// context: Context, -// _request: HttpRequest -// ): Promise { -// context.res = { -// body: context.bindings.inputDoc.testData, -// }; -// }; +const httpTriggerCosmosDBInput: AzureFunction = async function ( + context: Context, + _request: HttpRequest +): Promise { + context.res = { + body: context.bindings.inputDoc.testData, + }; +}; -// export default httpTriggerCosmosDBInput; +export default httpTriggerCosmosDBInput; diff --git a/app/v4/src/functions/httpTriggerCosmosDBInput.ts b/app/v4/src/functions/httpTriggerCosmosDBInput.ts index 25e0f4fd..acadf06e 100644 --- a/app/v4/src/functions/httpTriggerCosmosDBInput.ts +++ b/app/v4/src/functions/httpTriggerCosmosDBInput.ts @@ -1,27 +1,27 @@ -// // Copyright (c) .NET Foundation. All rights reserved. -// // Licensed under the MIT License. +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT License. -// import { app, HttpRequest, HttpResponseInit, input, InvocationContext } from '@azure/functions'; +import { app, HttpRequest, HttpResponseInit, input, InvocationContext } from '@azure/functions'; -// const cosmosInput = input.cosmosDB({ -// databaseName: 'e2eTestDB', -// containerName: 'e2eTestContainerTriggerAndOutput', -// id: '{Query.id}', -// partitionKey: 'testPartKey', -// connection: 'CosmosDBConnection', -// }); +const cosmosInput = input.cosmosDB({ + databaseName: 'e2eTestDB', + containerName: 'e2eTestContainerTriggerAndOutput', + id: '{Query.id}', + partitionKey: 'testPartKey', + connection: 'CosmosDBConnection', +}); -// export async function httpTriggerCosmosDBInput( -// _request: HttpRequest, -// context: InvocationContext -// ): Promise { -// const doc = context.extraInputs.get(cosmosInput); -// return { body: (doc).testData }; -// } +export async function httpTriggerCosmosDBInput( + _request: HttpRequest, + context: InvocationContext +): Promise { + const doc = context.extraInputs.get(cosmosInput); + return { body: (doc).testData }; +} -// app.http('httpTriggerCosmosDBInput', { -// methods: ['GET', 'POST'], -// authLevel: 'anonymous', -// extraInputs: [cosmosInput], -// handler: httpTriggerCosmosDBInput, -// }); +app.http('httpTriggerCosmosDBInput', { + methods: ['GET', 'POST'], + authLevel: 'anonymous', + extraInputs: [cosmosInput], + handler: httpTriggerCosmosDBInput, +}); From e722da540a6567aaa276c5710f3ffd4e65910b2b Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Tue, 22 Jul 2025 11:25:17 -0500 Subject: [PATCH 015/142] add --- src/utils/setupCosmosDB.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/utils/setupCosmosDB.ts b/src/utils/setupCosmosDB.ts index 12ee507d..a6c75b5f 100644 --- a/src/utils/setupCosmosDB.ts +++ b/src/utils/setupCosmosDB.ts @@ -12,6 +12,10 @@ import { CosmosDB } from '../constants'; export async function setupCosmosDB() { const client = new CosmosClient(cosmosDBConnectionString); await client.databases.createIfNotExists({ id: CosmosDB.triggerDatabaseName }); + await client.database(CosmosDB.triggerDatabaseName).containers.createIfNotExists({ + id: CosmosDB.triggerContainerName, + partitionKey: { paths: ['/testPartKey'], kind: PartitionKeyKind.Hash } + }); await client.database(CosmosDB.triggerDatabaseName).containers.createIfNotExists({ id: CosmosDB.triggerAndOutputContainerName, partitionKey: { paths: ['/testPartKey'], kind: PartitionKeyKind.Hash } From dcebe469ef4ab8f2c95fd4b6821a953baf5b4ff3 Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Tue, 22 Jul 2025 11:38:05 -0500 Subject: [PATCH 016/142] add --- app/v3/httpTriggerCosmosDBOutput/index.ts | 22 +++++----- .../functions/httpTriggerCosmosDBOutput.ts | 44 +++++++++---------- 2 files changed, 33 insertions(+), 33 deletions(-) diff --git a/app/v3/httpTriggerCosmosDBOutput/index.ts b/app/v3/httpTriggerCosmosDBOutput/index.ts index d2c0236a..9745ee1c 100644 --- a/app/v3/httpTriggerCosmosDBOutput/index.ts +++ b/app/v3/httpTriggerCosmosDBOutput/index.ts @@ -1,14 +1,14 @@ -// // Copyright (c) .NET Foundation. All rights reserved. -// // Licensed under the MIT License. +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT License. -// import { AzureFunction, Context, HttpRequest } from '@azure/functions'; +import { AzureFunction, Context, HttpRequest } from '@azure/functions'; -// const httpTriggerCosmosDBOutput: AzureFunction = async function ( -// context: Context, -// request: HttpRequest -// ): Promise { -// context.bindings.outputDoc = request.body; -// context.res = { body: 'done' }; -// }; +const httpTriggerCosmosDBOutput: AzureFunction = async function ( + context: Context, + request: HttpRequest +): Promise { + context.bindings.outputDoc = request.body; + context.res = { body: 'done' }; +}; -// export default httpTriggerCosmosDBOutput; +export default httpTriggerCosmosDBOutput; diff --git a/app/v4/src/functions/httpTriggerCosmosDBOutput.ts b/app/v4/src/functions/httpTriggerCosmosDBOutput.ts index 12eeb42b..a4580a97 100644 --- a/app/v4/src/functions/httpTriggerCosmosDBOutput.ts +++ b/app/v4/src/functions/httpTriggerCosmosDBOutput.ts @@ -1,26 +1,26 @@ -// // Copyright (c) .NET Foundation. All rights reserved. -// // Licensed under the MIT License. +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT License. -// import { app, HttpRequest, HttpResponseInit, InvocationContext, output } from '@azure/functions'; +import { app, HttpRequest, HttpResponseInit, InvocationContext, output } from '@azure/functions'; -// const cosmosOutput = output.cosmosDB({ -// databaseName: 'e2eTestDB', -// containerName: 'e2eTestContainerTrigger', -// connection: 'CosmosDBConnection', -// }); +const cosmosOutput = output.cosmosDB({ + databaseName: 'e2eTestDB', + containerName: 'e2eTestContainerTrigger', + connection: 'CosmosDBConnection', +}); -// export async function httpTriggerCosmosDBOutput( -// request: HttpRequest, -// context: InvocationContext -// ): Promise { -// const body = await request.json(); -// context.extraOutputs.set(cosmosOutput, body); -// return { body: 'done' }; -// } +export async function httpTriggerCosmosDBOutput( + request: HttpRequest, + context: InvocationContext +): Promise { + const body = await request.json(); + context.extraOutputs.set(cosmosOutput, body); + return { body: 'done' }; +} -// app.http('httpTriggerCosmosDBOutput', { -// methods: ['GET', 'POST'], -// authLevel: 'anonymous', -// extraOutputs: [cosmosOutput], -// handler: httpTriggerCosmosDBOutput, -// }); +app.http('httpTriggerCosmosDBOutput', { + methods: ['GET', 'POST'], + authLevel: 'anonymous', + extraOutputs: [cosmosOutput], + handler: httpTriggerCosmosDBOutput, +}); From 2a92719aa872f389b9853307a47a4b33ae32d7d4 Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Tue, 22 Jul 2025 11:55:57 -0500 Subject: [PATCH 017/142] add --- .../src/functions/httpTriggerCosmosDBInput.ts | 46 +++++++++---------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/app/v4-oldConfig/src/functions/httpTriggerCosmosDBInput.ts b/app/v4-oldConfig/src/functions/httpTriggerCosmosDBInput.ts index 7c65e72e..88288768 100644 --- a/app/v4-oldConfig/src/functions/httpTriggerCosmosDBInput.ts +++ b/app/v4-oldConfig/src/functions/httpTriggerCosmosDBInput.ts @@ -1,27 +1,27 @@ -// // Copyright (c) .NET Foundation. All rights reserved. -// // Licensed under the MIT License. +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT License. -// import { app, HttpRequest, HttpResponseInit, input, InvocationContext } from '@azure/functions'; +import { app, HttpRequest, HttpResponseInit, input, InvocationContext } from '@azure/functions'; -// const cosmosInput = input.cosmosDB({ -// databaseName: 'e2eTestDB', -// collectionName: 'e2eTestContainerTriggerAndOutput', -// id: '{Query.id}', -// partitionKey: 'testPartKey', -// connectionStringSetting: 'CosmosDBConnection', -// }); +const cosmosInput = input.cosmosDB({ + databaseName: 'e2eTestDB', + collectionName: 'e2eTestContainerTriggerAndOutput', + id: '{Query.id}', + partitionKey: 'testPartKey', + connectionStringSetting: 'CosmosDBConnection', +}); -// export async function httpTriggerCosmosDBInput( -// _request: HttpRequest, -// context: InvocationContext -// ): Promise { -// const doc = context.extraInputs.get(cosmosInput); -// return { body: (doc).testData }; -// } +export async function httpTriggerCosmosDBInput( + _request: HttpRequest, + context: InvocationContext +): Promise { + const doc = context.extraInputs.get(cosmosInput); + return { body: (doc).testData }; +} -// app.http('httpTriggerCosmosDBInput', { -// methods: ['GET', 'POST'], -// authLevel: 'anonymous', -// extraInputs: [cosmosInput], -// handler: httpTriggerCosmosDBInput, -// }); +app.http('httpTriggerCosmosDBInput', { + methods: ['GET', 'POST'], + authLevel: 'anonymous', + extraInputs: [cosmosInput], + handler: httpTriggerCosmosDBInput, +}); From 880fa874ce6273114f0532a9b52ece2979a0ceaf Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Tue, 22 Jul 2025 12:24:48 -0500 Subject: [PATCH 018/142] add --- .../src/functions/cosmosDBTrigger.ts | 34 +++++++------- .../src/functions/cosmosDBTriggerAndOutput.ts | 46 +++++++++---------- src/cosmosDB.test.ts | 2 +- 3 files changed, 41 insertions(+), 41 deletions(-) diff --git a/app/v4-oldConfig/src/functions/cosmosDBTrigger.ts b/app/v4-oldConfig/src/functions/cosmosDBTrigger.ts index bdec0a40..3b02a056 100644 --- a/app/v4-oldConfig/src/functions/cosmosDBTrigger.ts +++ b/app/v4-oldConfig/src/functions/cosmosDBTrigger.ts @@ -1,20 +1,20 @@ -// // Copyright (c) .NET Foundation. All rights reserved. -// // Licensed under the MIT License. +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT License. -// import { app, InvocationContext } from '@azure/functions'; +import { app, InvocationContext } from '@azure/functions'; -// export async function cosmosDBTrigger(documents: unknown[], context: InvocationContext): Promise { -// context.log(`cosmosDBTrigger processed ${documents.length} documents`); -// for (const document of documents) { -// context.log(`cosmosDBTrigger was triggered by "${(document).testData}"`); -// } -// } +export async function cosmosDBTrigger(documents: unknown[], context: InvocationContext): Promise { + context.log(`cosmosDBTrigger processed ${documents.length} documents`); + for (const document of documents) { + context.log(`cosmosDBTrigger was triggered by "${(document).testData}"`); + } +} -// app.cosmosDB('cosmosDBTrigger', { -// connectionStringSetting: 'CosmosDBConnection', -// databaseName: 'e2eTestDB', -// collectionName: 'e2eTestContainerTrigger', -// createLeaseCollectionIfNotExists: true, -// leaseCollectionPrefix: '2', -// handler: cosmosDBTrigger, -// }); +app.cosmosDB('cosmosDBTrigger', { + connectionStringSetting: 'CosmosDBConnection', + databaseName: 'e2eTestDB', + collectionName: 'e2eTestContainerTrigger', + createLeaseCollectionIfNotExists: true, + leaseCollectionPrefix: '2', + handler: cosmosDBTrigger, +}); diff --git a/app/v4-oldConfig/src/functions/cosmosDBTriggerAndOutput.ts b/app/v4-oldConfig/src/functions/cosmosDBTriggerAndOutput.ts index 89eda8f4..ab00a27a 100644 --- a/app/v4-oldConfig/src/functions/cosmosDBTriggerAndOutput.ts +++ b/app/v4-oldConfig/src/functions/cosmosDBTriggerAndOutput.ts @@ -1,26 +1,26 @@ -// // Copyright (c) .NET Foundation. All rights reserved. -// // Licensed under the MIT License. +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT License. -// import { app, InvocationContext, output } from '@azure/functions'; +import { app, InvocationContext, output } from '@azure/functions'; -// export async function cosmosDBTriggerAndOutput(documents: unknown[], context: InvocationContext): Promise { -// context.log(`cosmosDBTriggerAndOutput processed ${documents.length} documents`); -// for (const document of documents) { -// context.log(`cosmosDBTriggerAndOutput was triggered by "${(document).testData}"`); -// } -// return documents; -// } +export async function cosmosDBTriggerAndOutput(documents: unknown[], context: InvocationContext): Promise { + context.log(`cosmosDBTriggerAndOutput processed ${documents.length} documents`); + for (const document of documents) { + context.log(`cosmosDBTriggerAndOutput was triggered by "${(document).testData}"`); + } + return documents; +} -// app.cosmosDB('cosmosDBTriggerAndOutput', { -// connectionStringSetting: 'CosmosDBConnection', -// databaseName: 'e2eTestDB', -// collectionName: 'e2eTestContainerTriggerAndOutput', -// createLeaseCollectionIfNotExists: true, -// leaseCollectionPrefix: '1', -// return: output.cosmosDB({ -// connectionStringSetting: 'CosmosDBConnection', -// databaseName: 'e2eTestDB', -// collectionName: 'e2eTestContainerTrigger', -// }), -// handler: cosmosDBTriggerAndOutput, -// }); +app.cosmosDB('cosmosDBTriggerAndOutput', { + connectionStringSetting: 'CosmosDBConnection', + databaseName: 'e2eTestDB', + collectionName: 'e2eTestContainerTriggerAndOutput', + createLeaseCollectionIfNotExists: true, + leaseCollectionPrefix: '1', + return: output.cosmosDB({ + connectionStringSetting: 'CosmosDBConnection', + databaseName: 'e2eTestDB', + collectionName: 'e2eTestContainerTrigger', + }), + handler: cosmosDBTriggerAndOutput, +}); diff --git a/src/cosmosDB.test.ts b/src/cosmosDB.test.ts index b134a953..ebf6a786 100644 --- a/src/cosmosDB.test.ts +++ b/src/cosmosDB.test.ts @@ -14,7 +14,7 @@ describe('cosmosDB', () => { const client = new CosmosClient(cosmosDBConnectionString); const container = client.database(CosmosDB.dbName).container(CosmosDB.triggerAndOutputContainerName); const testData = getRandomTestData(); - const createdItem = await container.items.create({ testData, _partitionKey: 'testPartKey' }); + const createdItem = await container.items.create({ testData, testPartKey: 'testPartKey' }); await waitForOutput(`cosmosDBTriggerAndOutput processed 1 documents`); await waitForOutput(`cosmosDBTriggerAndOutput was triggered by "${testData}"`); From 5025dc20f008e0ef903f9ee8b3728e939a9cad50 Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Tue, 22 Jul 2025 12:37:34 -0500 Subject: [PATCH 019/142] add all --- .../functions/httpTriggerCosmosDBOutput.ts | 44 +++++++++---------- .../templates/test-node-version.yml | 3 -- azure-pipelines/templates/test.yml | 21 +++++---- 3 files changed, 32 insertions(+), 36 deletions(-) diff --git a/app/v4-oldConfig/src/functions/httpTriggerCosmosDBOutput.ts b/app/v4-oldConfig/src/functions/httpTriggerCosmosDBOutput.ts index 35740acb..2cdfc272 100644 --- a/app/v4-oldConfig/src/functions/httpTriggerCosmosDBOutput.ts +++ b/app/v4-oldConfig/src/functions/httpTriggerCosmosDBOutput.ts @@ -1,26 +1,26 @@ -// // Copyright (c) .NET Foundation. All rights reserved. -// // Licensed under the MIT License. +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT License. -// import { HttpRequest, HttpResponseInit, InvocationContext, app, output } from '@azure/functions'; +import { HttpRequest, HttpResponseInit, InvocationContext, app, output } from '@azure/functions'; -// const cosmosOutput = output.cosmosDB({ -// databaseName: 'e2eTestDB', -// collectionName: 'e2eTestContainerTrigger', -// connectionStringSetting: 'CosmosDBConnection', -// }); +const cosmosOutput = output.cosmosDB({ + databaseName: 'e2eTestDB', + collectionName: 'e2eTestContainerTrigger', + connectionStringSetting: 'CosmosDBConnection', +}); -// export async function httpTriggerCosmosDBOutput( -// request: HttpRequest, -// context: InvocationContext -// ): Promise { -// const body = await request.json(); -// context.extraOutputs.set(cosmosOutput, body); -// return { body: 'done' }; -// } +export async function httpTriggerCosmosDBOutput( + request: HttpRequest, + context: InvocationContext +): Promise { + const body = await request.json(); + context.extraOutputs.set(cosmosOutput, body); + return { body: 'done' }; +} -// app.http('httpTriggerCosmosDBOutput', { -// methods: ['GET', 'POST'], -// authLevel: 'anonymous', -// extraOutputs: [cosmosOutput], -// handler: httpTriggerCosmosDBOutput, -// }); +app.http('httpTriggerCosmosDBOutput', { + methods: ['GET', 'POST'], + authLevel: 'anonymous', + extraOutputs: [cosmosOutput], + handler: httpTriggerCosmosDBOutput, +}); diff --git a/azure-pipelines/templates/test-node-version.yml b/azure-pipelines/templates/test-node-version.yml index 788736b2..1064596b 100644 --- a/azure-pipelines/templates/test-node-version.yml +++ b/azure-pipelines/templates/test-node-version.yml @@ -20,9 +20,6 @@ steps: docker compose -f src/utils/eventhub/docker-compose.yml pull docker compose -f src/utils/eventhub/docker-compose.yml up -d displayName: 'Install Azurite and Start EventHub Emulator' - - bash: | - docker logs azurite - displayName: 'Show Azurite Logs' - bash: | npm run ${{ parameters.testCommand }} displayName: 'Run tests Node ${{ parameters.nodeVersion }}' diff --git a/azure-pipelines/templates/test.yml b/azure-pipelines/templates/test.yml index 19f6efe0..98ebca05 100644 --- a/azure-pipelines/templates/test.yml +++ b/azure-pipelines/templates/test.yml @@ -16,24 +16,23 @@ jobs: - template: /azure-pipelines/templates/build-apps.yml@self - # - template: /azure-pipelines/templates/test-node-version.yml@self - # parameters: - # nodeVersion: 18.x + - template: /azure-pipelines/templates/test-node-version.yml@self + parameters: + nodeVersion: 18.x - # - template: /azure-pipelines/templates/test-node-version.yml@self - # parameters: - # nodeVersion: 20.x + - template: /azure-pipelines/templates/test-node-version.yml@self + parameters: + nodeVersion: 20.x - template: /azure-pipelines/templates/test-node-version.yml@self parameters: nodeVersion: 22.x - # These all use Cosmos - so we will come back and emulate this # Run tests for old config (just one Node.js version is enough) - # - template: /azure-pipelines/templates/test-node-version.yml@self - # parameters: - # nodeVersion: 18.x - # testCommand: testOldConfig + - template: /azure-pipelines/templates/test-node-version.yml@self + parameters: + nodeVersion: 18.x + testCommand: testOldConfig - task: PublishTestResults@2 displayName: 'Publish Unit Test Results' From 2428155a37f2651dd43733d1463680f1b499ea27 Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Tue, 22 Jul 2025 12:47:31 -0500 Subject: [PATCH 020/142] add --- src/constants.ts | 1 + src/cosmosDB.test.ts | 2 +- src/utils/setupCosmosDB.ts | 5 +++-- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/constants.ts b/src/constants.ts index 63ca0ff9..24cebd74 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -12,6 +12,7 @@ export namespace CosmosDB { export const triggerAndOutputContainerName = 'e2eTestContainerTriggerAndOutput'; export const triggerContainerName = 'e2eTestContainerTrigger'; export const triggerDatabaseName = 'e2eTestDB'; + export const partitionKey = 'testPartKey'; } export namespace EventHub { diff --git a/src/cosmosDB.test.ts b/src/cosmosDB.test.ts index ebf6a786..33572a25 100644 --- a/src/cosmosDB.test.ts +++ b/src/cosmosDB.test.ts @@ -14,7 +14,7 @@ describe('cosmosDB', () => { const client = new CosmosClient(cosmosDBConnectionString); const container = client.database(CosmosDB.dbName).container(CosmosDB.triggerAndOutputContainerName); const testData = getRandomTestData(); - const createdItem = await container.items.create({ testData, testPartKey: 'testPartKey' }); + const createdItem = await container.items.create({ testData, testPartKey: CosmosDB.partitionKey }); await waitForOutput(`cosmosDBTriggerAndOutput processed 1 documents`); await waitForOutput(`cosmosDBTriggerAndOutput was triggered by "${testData}"`); diff --git a/src/utils/setupCosmosDB.ts b/src/utils/setupCosmosDB.ts index a6c75b5f..b7a68bc0 100644 --- a/src/utils/setupCosmosDB.ts +++ b/src/utils/setupCosmosDB.ts @@ -10,14 +10,15 @@ import { cosmosDBConnectionString } from './connectionStrings'; import { CosmosDB } from '../constants'; export async function setupCosmosDB() { + const partitionKeyPath = `/${CosmosDB.partitionKey}`; const client = new CosmosClient(cosmosDBConnectionString); await client.databases.createIfNotExists({ id: CosmosDB.triggerDatabaseName }); await client.database(CosmosDB.triggerDatabaseName).containers.createIfNotExists({ id: CosmosDB.triggerContainerName, - partitionKey: { paths: ['/testPartKey'], kind: PartitionKeyKind.Hash } + partitionKey: { paths: [partitionKeyPath], kind: PartitionKeyKind.Hash } }); await client.database(CosmosDB.triggerDatabaseName).containers.createIfNotExists({ id: CosmosDB.triggerAndOutputContainerName, - partitionKey: { paths: ['/testPartKey'], kind: PartitionKeyKind.Hash } + partitionKey: { paths: [partitionKeyPath], kind: PartitionKeyKind.Hash } }); } \ No newline at end of file From 10fd04258ce32935dbeb9b89d970ac7b4481244f Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Tue, 22 Jul 2025 13:20:22 -0500 Subject: [PATCH 021/142] add --- app/v3/httpTriggerTableOutput/index.ts | 22 ++++----- app/v4/src/functions/httpTriggerTableInput.ts | 48 +++++++++---------- .../src/functions/httpTriggerTableOutput.ts | 44 ++++++++--------- azure-pipelines/templates/test.yml | 8 ++-- 4 files changed, 61 insertions(+), 61 deletions(-) diff --git a/app/v3/httpTriggerTableOutput/index.ts b/app/v3/httpTriggerTableOutput/index.ts index 0d6688b9..022d757c 100644 --- a/app/v3/httpTriggerTableOutput/index.ts +++ b/app/v3/httpTriggerTableOutput/index.ts @@ -1,14 +1,14 @@ -// // Copyright (c) .NET Foundation. All rights reserved. -// // Licensed under the MIT License. +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT License. -// import { AzureFunction, Context, HttpRequest } from '@azure/functions'; +import { AzureFunction, Context, HttpRequest } from '@azure/functions'; -// const httpTriggerTableOutput: AzureFunction = async function (context: Context, request: HttpRequest): Promise { -// context.log(`httpTriggerTableOutput was triggered`); -// context.bindings.outputItem = request.body; -// context.res = { -// status: 201, -// }; -// }; +const httpTriggerTableOutput: AzureFunction = async function (context: Context, request: HttpRequest): Promise { + context.log(`httpTriggerTableOutput was triggered`); + context.bindings.outputItem = request.body; + context.res = { + status: 201, + }; +}; -// export default httpTriggerTableOutput; +export default httpTriggerTableOutput; diff --git a/app/v4/src/functions/httpTriggerTableInput.ts b/app/v4/src/functions/httpTriggerTableInput.ts index 2674fd5c..50d28b1e 100644 --- a/app/v4/src/functions/httpTriggerTableInput.ts +++ b/app/v4/src/functions/httpTriggerTableInput.ts @@ -1,28 +1,28 @@ -// // Copyright (c) .NET Foundation. All rights reserved. -// // Licensed under the MIT License. +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT License. -// import { app, HttpRequest, HttpResponseInit, input, InvocationContext } from '@azure/functions'; +import { app, HttpRequest, HttpResponseInit, input, InvocationContext } from '@azure/functions'; -// const tableInput = input.table({ -// tableName: 'e2etesttable', -// partitionKey: 'e2eTestPartKey', -// filter: "RowKey eq '{rowKey}'", -// connection: 'e2eTest_storage', -// }); +const tableInput = input.table({ + tableName: 'e2etesttable', + partitionKey: 'e2eTestPartKey', + filter: "RowKey eq '{rowKey}'", + connection: 'AzureWebJobsStorage', +}); -// export async function httpTriggerTableInput( -// request: HttpRequest, -// context: InvocationContext -// ): Promise { -// context.log(`httpTriggerTableInput was triggered`); -// const items = context.extraInputs.get(tableInput); -// return { jsonBody: items }; -// } +export async function httpTriggerTableInput( + request: HttpRequest, + context: InvocationContext +): Promise { + context.log(`httpTriggerTableInput was triggered`); + const items = context.extraInputs.get(tableInput); + return { jsonBody: items }; +} -// app.http('httpTriggerTableInput', { -// methods: ['GET', 'POST'], -// authLevel: 'anonymous', -// route: 'httpTriggerTableInput/{rowKey}', -// extraInputs: [tableInput], -// handler: httpTriggerTableInput, -// }); +app.http('httpTriggerTableInput', { + methods: ['GET', 'POST'], + authLevel: 'anonymous', + route: 'httpTriggerTableInput/{rowKey}', + extraInputs: [tableInput], + handler: httpTriggerTableInput, +}); diff --git a/app/v4/src/functions/httpTriggerTableOutput.ts b/app/v4/src/functions/httpTriggerTableOutput.ts index 645228b4..bf9bb2a3 100644 --- a/app/v4/src/functions/httpTriggerTableOutput.ts +++ b/app/v4/src/functions/httpTriggerTableOutput.ts @@ -1,26 +1,26 @@ -// // Copyright (c) .NET Foundation. All rights reserved. -// // Licensed under the MIT License. +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT License. -// import { app, HttpRequest, HttpResponseInit, InvocationContext, output } from '@azure/functions'; +import { app, HttpRequest, HttpResponseInit, InvocationContext, output } from '@azure/functions'; -// const tableOutput = output.table({ -// tableName: 'e2etesttable', -// connection: 'e2eTest_storage', -// }); +const tableOutput = output.table({ + tableName: 'e2etesttable', + connection: 'AzureWebJobsStorage', +}); -// export async function httpTriggerTableOutput( -// request: HttpRequest, -// context: InvocationContext -// ): Promise { -// context.log(`httpTriggerTableOutput was triggered`); -// const body = await request.json(); -// context.extraOutputs.set(tableOutput, body); -// return { status: 201 }; -// } +export async function httpTriggerTableOutput( + request: HttpRequest, + context: InvocationContext +): Promise { + context.log(`httpTriggerTableOutput was triggered`); + const body = await request.json(); + context.extraOutputs.set(tableOutput, body); + return { status: 201 }; +} -// app.http('httpTriggerTableOutput', { -// methods: ['GET', 'POST'], -// authLevel: 'anonymous', -// extraOutputs: [tableOutput], -// handler: httpTriggerTableOutput, -// }); +app.http('httpTriggerTableOutput', { + methods: ['GET', 'POST'], + authLevel: 'anonymous', + extraOutputs: [tableOutput], + handler: httpTriggerTableOutput, +}); diff --git a/azure-pipelines/templates/test.yml b/azure-pipelines/templates/test.yml index 98ebca05..e1d1489d 100644 --- a/azure-pipelines/templates/test.yml +++ b/azure-pipelines/templates/test.yml @@ -29,10 +29,10 @@ jobs: nodeVersion: 22.x # Run tests for old config (just one Node.js version is enough) - - template: /azure-pipelines/templates/test-node-version.yml@self - parameters: - nodeVersion: 18.x - testCommand: testOldConfig + # - template: /azure-pipelines/templates/test-node-version.yml@self + # parameters: + # nodeVersion: 18.x + # testCommand: testOldConfig - task: PublishTestResults@2 displayName: 'Publish Unit Test Results' From 433955ea760df779f704f0328d2dbd7f85274394 Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Tue, 22 Jul 2025 14:13:00 -0500 Subject: [PATCH 022/142] adjust --- .../templates/test-node-version.yml | 1 + azure-pipelines/templates/test.yml | 8 +-- src/eventHub.test.ts | 10 +++- src/storage.test.ts | 50 +++++++++---------- 4 files changed, 38 insertions(+), 31 deletions(-) diff --git a/azure-pipelines/templates/test-node-version.yml b/azure-pipelines/templates/test-node-version.yml index 1064596b..029551be 100644 --- a/azure-pipelines/templates/test-node-version.yml +++ b/azure-pipelines/templates/test-node-version.yml @@ -20,6 +20,7 @@ steps: docker compose -f src/utils/eventhub/docker-compose.yml pull docker compose -f src/utils/eventhub/docker-compose.yml up -d displayName: 'Install Azurite and Start EventHub Emulator' + condition: and(succeeded(), ne('${{ parameters.testCommand }}', 'testOldConfig')) - bash: | npm run ${{ parameters.testCommand }} displayName: 'Run tests Node ${{ parameters.nodeVersion }}' diff --git a/azure-pipelines/templates/test.yml b/azure-pipelines/templates/test.yml index e1d1489d..98ebca05 100644 --- a/azure-pipelines/templates/test.yml +++ b/azure-pipelines/templates/test.yml @@ -29,10 +29,10 @@ jobs: nodeVersion: 22.x # Run tests for old config (just one Node.js version is enough) - # - template: /azure-pipelines/templates/test-node-version.yml@self - # parameters: - # nodeVersion: 18.x - # testCommand: testOldConfig + - template: /azure-pipelines/templates/test-node-version.yml@self + parameters: + nodeVersion: 18.x + testCommand: testOldConfig - task: PublishTestResults@2 displayName: 'Publish Unit Test Results' diff --git a/src/eventHub.test.ts b/src/eventHub.test.ts index ed770fc3..9980f455 100644 --- a/src/eventHub.test.ts +++ b/src/eventHub.test.ts @@ -2,7 +2,7 @@ // Licensed under the MIT License. import { EventHubProducerClient } from '@azure/event-hubs'; -import { waitForOutput } from './global.test'; +import { isOldConfig, waitForOutput } from './global.test'; import { eventHubConnectionString } from './utils/connectionStrings'; import { getRandomTestData } from './utils/getRandomTestData'; import { EventHub } from './constants'; @@ -14,7 +14,13 @@ describe('eventHub', () => { let clientManyTrigger: EventHubProducerClient; - before(() => { + before(function (this: Mocha.Context) { + // Old config (Exts bundles < 4.0.0) cannot use EventHub emulator + // Microsoft.Azure.Functions.Worker.Extensions.EventHubs bundle must be >= 6.3.0 + // https://github.com/Azure/azure-event-hubs-emulator-installer/issues/15 + if (isOldConfig) { + this.skip(); + } clientOneTriggerAndOutput = new EventHubProducerClient(eventHubConnectionString, EventHub.eventHubOneTriggerAndOutput); clientOneTrigger = new EventHubProducerClient(eventHubConnectionString, EventHub.eventHubOneTrigger); clientManyTriggerAndOutput = new EventHubProducerClient(eventHubConnectionString, EventHub.eventHubManyTriggerAndOutput); diff --git a/src/storage.test.ts b/src/storage.test.ts index ff8a2ccb..562f0e8f 100644 --- a/src/storage.test.ts +++ b/src/storage.test.ts @@ -3,7 +3,7 @@ import { ContainerClient } from '@azure/storage-blob'; import { QueueClient } from '@azure/storage-queue'; -// import { expect } from 'chai'; +import { expect } from 'chai'; import { default as fetch } from 'node-fetch'; import { getFuncUrl } from './constants'; import { model, waitForOutput } from './global.test'; @@ -59,30 +59,30 @@ describe('storage', () => { ); }); - // type TableItem = { PartitionKey: string; RowKey: string; Name: string }; - - // it('table input and output', async () => { - // const rowKey = getRandomTestData(); - // const items: TableItem[] = [ - // { - // PartitionKey: 'e2eTestPartKey', - // RowKey: rowKey, - // Name: 'e2eTestName', - // }, - // ]; - // const responseOut = await fetch(getFuncUrl('httpTriggerTableOutput'), { - // method: 'POST', - // body: JSON.stringify(items), - // }); - // expect(responseOut.status).to.equal(201); - // await waitForOutput(`httpTriggerTableOutput was triggered`); - - // const responseIn = await fetch(getFuncUrl(`httpTriggerTableInput/${rowKey}`), { method: 'GET' }); - // expect(responseIn.status).to.equal(200); - // const result = await responseIn.json(); - // expect(result).to.deep.equal(items); - // await waitForOutput(`httpTriggerTableInput was triggered`); - // }); + type TableItem = { PartitionKey: string; RowKey: string; Name: string }; + + it('table input and output', async () => { + const rowKey = getRandomTestData(); + const items: TableItem[] = [ + { + PartitionKey: 'e2eTestPartKey', + RowKey: rowKey, + Name: 'e2eTestName', + }, + ]; + const responseOut = await fetch(getFuncUrl('httpTriggerTableOutput'), { + method: 'POST', + body: JSON.stringify(items), + }); + expect(responseOut.status).to.equal(201); + await waitForOutput(`httpTriggerTableOutput was triggered`); + + const responseIn = await fetch(getFuncUrl(`httpTriggerTableInput/${rowKey}`), { method: 'GET' }); + expect(responseIn.status).to.equal(200); + const result = await responseIn.json(); + expect(result).to.deep.equal(items); + await waitForOutput(`httpTriggerTableInput was triggered`); + }); // Test for bug https://github.com/Azure/azure-functions-nodejs-library/issues/179 it('Shared output bug', async function (this: Mocha.Context) { From 40662b7bf23fa1d82df5ba12e694120f58881bad Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Tue, 22 Jul 2025 14:33:20 -0500 Subject: [PATCH 023/142] adjust --- app/v3/httpTriggerTableInput/index.ts | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/app/v3/httpTriggerTableInput/index.ts b/app/v3/httpTriggerTableInput/index.ts index 34d8c02e..8e01167c 100644 --- a/app/v3/httpTriggerTableInput/index.ts +++ b/app/v3/httpTriggerTableInput/index.ts @@ -1,13 +1,13 @@ -// // Copyright (c) .NET Foundation. All rights reserved. -// // Licensed under the MIT License. +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT License. -// import { AzureFunction, Context, HttpRequest } from '@azure/functions'; +import { AzureFunction, Context, HttpRequest } from '@azure/functions'; -// const httpTriggerTableInput: AzureFunction = async function (context: Context, request: HttpRequest): Promise { -// context.log(`httpTriggerTableInput was triggered`); -// context.res = { -// body: context.bindings.inputItem, -// }; -// }; +const httpTriggerTableInput: AzureFunction = async function (context: Context, request: HttpRequest): Promise { + context.log(`httpTriggerTableInput was triggered`); + context.res = { + body: context.bindings.inputItem, + }; +}; -// export default httpTriggerTableInput; +export default httpTriggerTableInput; From 8758b64af1836607ca8e27cc635d432e27c4f735 Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Tue, 22 Jul 2025 15:03:30 -0500 Subject: [PATCH 024/142] adjust --- src/eventHub.test.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/eventHub.test.ts b/src/eventHub.test.ts index 9980f455..c68ea8e6 100644 --- a/src/eventHub.test.ts +++ b/src/eventHub.test.ts @@ -28,10 +28,10 @@ describe('eventHub', () => { }); after(async () => { - void clientOneTriggerAndOutput.close(); - void clientOneTrigger.close(); - void clientManyTriggerAndOutput.close(); - void clientManyTrigger.close(); + void clientOneTriggerAndOutput?.close(); + void clientOneTrigger?.close(); + void clientManyTriggerAndOutput?.close(); + void clientManyTrigger?.close(); }); describe('cardinality one', () => { From 2182c04eaa5c75dfc3c2787e3084de3d89a1751a Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Mon, 28 Jul 2025 12:12:35 -0500 Subject: [PATCH 025/142] adjust --- .../serviceBusQueueManyTrigger/function.json | 4 +- app/v3/serviceBusQueueManyTrigger/index.ts | 18 ++--- .../function.json | 8 +- .../index.ts | 24 +++--- app/v3/serviceBusQueueTrigger/function.json | 4 +- app/v3/serviceBusQueueTrigger/index.ts | 14 ++-- .../function.json | 8 +- .../serviceBusQueueTriggerAndOutput/index.ts | 16 ++-- app/v3/serviceBusTopicTrigger/function.json | 4 +- app/v3/serviceBusTopicTrigger/index.ts | 14 ++-- .../function.json | 8 +- .../serviceBusTopicTriggerAndOutput/index.ts | 16 ++-- .../functions/serviceBusQueueManyTrigger.ts | 28 +++---- .../serviceBusQueueManyTriggerAndOutput.ts | 48 ++++++------ .../src/functions/serviceBusQueueTrigger.ts | 22 +++--- .../serviceBusQueueTriggerAndOutput.ts | 32 ++++---- .../src/functions/serviceBusTopicTrigger.ts | 24 +++--- .../serviceBusTopicTriggerAndOutput.ts | 34 ++++---- src/constants.ts | 10 +++ src/global.test.ts | 2 + src/serviceBus.test.ts | 78 +++++++++++++++++++ src/utils/connectionStrings.ts | 3 +- src/utils/servicebus/config.json | 70 +++++++++++++++++ src/utils/servicebus/docker-compose.yml | 39 ++++++++++ 24 files changed, 364 insertions(+), 164 deletions(-) create mode 100644 src/serviceBus.test.ts create mode 100644 src/utils/servicebus/config.json create mode 100644 src/utils/servicebus/docker-compose.yml diff --git a/app/v3/serviceBusQueueManyTrigger/function.json b/app/v3/serviceBusQueueManyTrigger/function.json index f5e9f878..65e5addf 100644 --- a/app/v3/serviceBusQueueManyTrigger/function.json +++ b/app/v3/serviceBusQueueManyTrigger/function.json @@ -4,8 +4,8 @@ "name": "mySbMsg", "type": "serviceBusTrigger", "direction": "in", - "queueName": "e2eTestQueueManyTrigger", - "connection": "e2eTest_serviceBus", + "queueName": "e2e-test-queue-many-trigger", + "connection": "ServiceBusConnection", "cardinality": "many" } ], diff --git a/app/v3/serviceBusQueueManyTrigger/index.ts b/app/v3/serviceBusQueueManyTrigger/index.ts index aed2e7d5..a2215ef9 100644 --- a/app/v3/serviceBusQueueManyTrigger/index.ts +++ b/app/v3/serviceBusQueueManyTrigger/index.ts @@ -1,12 +1,12 @@ -// // Copyright (c) .NET Foundation. All rights reserved. -// // Licensed under the MIT License. +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT License. -// import { AzureFunction, Context } from '@azure/functions'; +import { AzureFunction, Context } from '@azure/functions'; -// const serviceBusQueueTrigger: AzureFunction = async function (context: Context, messages: any): Promise { -// for (const message of messages) { -// context.log(`serviceBusQueueManyTrigger was triggered by "${message}"`); -// } -// }; +const serviceBusQueueTrigger: AzureFunction = async function (context: Context, messages: any): Promise { + for (const message of messages) { + context.log(`serviceBusQueueManyTrigger was triggered by "${message}"`); + } +}; -// export default serviceBusQueueTrigger; +export default serviceBusQueueTrigger; diff --git a/app/v3/serviceBusQueueManyTriggerAndOutput/function.json b/app/v3/serviceBusQueueManyTriggerAndOutput/function.json index 73885d79..e5d44e97 100644 --- a/app/v3/serviceBusQueueManyTriggerAndOutput/function.json +++ b/app/v3/serviceBusQueueManyTriggerAndOutput/function.json @@ -4,16 +4,16 @@ "name": "mySbMsg", "type": "serviceBusTrigger", "direction": "in", - "queueName": "e2eTestQueueManyTriggerAndOutput", - "connection": "e2eTest_serviceBus", + "queueName": "e2e-test-queue-many-trigger-and-output", + "connection": "ServiceBusConnection", "cardinality": "many" }, { "name": "$return", "type": "serviceBus", "direction": "out", - "topicName": "e2eTestQueueManyTrigger", - "connection": "e2eTest_serviceBus" + "topicName": "e2e-test-queue-many-trigger", + "connection": "ServiceBusConnection" } ], "scriptFile": "../dist/serviceBusQueueManyTriggerAndOutput/index.js" diff --git a/app/v3/serviceBusQueueManyTriggerAndOutput/index.ts b/app/v3/serviceBusQueueManyTriggerAndOutput/index.ts index 2ee5ce3c..d649e246 100644 --- a/app/v3/serviceBusQueueManyTriggerAndOutput/index.ts +++ b/app/v3/serviceBusQueueManyTriggerAndOutput/index.ts @@ -1,16 +1,16 @@ -// // Copyright (c) .NET Foundation. All rights reserved. -// // Licensed under the MIT License. +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT License. -// import { AzureFunction, Context } from '@azure/functions'; +import { AzureFunction, Context } from '@azure/functions'; -// const serviceBusQueueTrigger: AzureFunction = async function (context: Context, messages: any): Promise { -// for (const message of messages) { -// context.log(`serviceBusQueueManyTriggerAndOutput was triggered by "${message}"`); -// } +const serviceBusQueueTrigger: AzureFunction = async function (context: Context, messages: any): Promise { + for (const message of messages) { + context.log(`serviceBusQueueManyTriggerAndOutput was triggered by "${message}"`); + } -// // do an extra stringify to make sure the values are JSON-parse-able otherwise it'll hit this bug: -// // https://github.com/Azure/azure-functions-eventhubs-extension/issues/118 -// return messages.map((m) => JSON.stringify(m)); -// }; + // do an extra stringify to make sure the values are JSON-parse-able otherwise it'll hit this bug: + // https://github.com/Azure/azure-functions-eventhubs-extension/issues/118 + return messages.map((m) => JSON.stringify(m)); +}; -// export default serviceBusQueueTrigger; +export default serviceBusQueueTrigger; diff --git a/app/v3/serviceBusQueueTrigger/function.json b/app/v3/serviceBusQueueTrigger/function.json index c0d50073..f569ab9a 100644 --- a/app/v3/serviceBusQueueTrigger/function.json +++ b/app/v3/serviceBusQueueTrigger/function.json @@ -4,8 +4,8 @@ "name": "mySbMsg", "type": "serviceBusTrigger", "direction": "in", - "queueName": "e2eTestQueueOneTrigger", - "connection": "e2eTest_serviceBus" + "queueName": "e2e-test-queue-one-trigger", + "connection": "ServiceBusConnection" } ], "scriptFile": "../dist/serviceBusQueueTrigger/index.js" diff --git a/app/v3/serviceBusQueueTrigger/index.ts b/app/v3/serviceBusQueueTrigger/index.ts index e5e29d7b..0f274f64 100644 --- a/app/v3/serviceBusQueueTrigger/index.ts +++ b/app/v3/serviceBusQueueTrigger/index.ts @@ -1,10 +1,10 @@ -// // Copyright (c) .NET Foundation. All rights reserved. -// // Licensed under the MIT License. +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT License. -// import { AzureFunction, Context } from '@azure/functions'; +import { AzureFunction, Context } from '@azure/functions'; -// const serviceBusQueueTrigger: AzureFunction = async function (context: Context, mySbMsg: any): Promise { -// context.log(`serviceBusQueueTrigger was triggered by "${mySbMsg}"`); -// }; +const serviceBusQueueTrigger: AzureFunction = async function (context: Context, mySbMsg: any): Promise { + context.log(`serviceBusQueueTrigger was triggered by "${mySbMsg}"`); +}; -// export default serviceBusQueueTrigger; +export default serviceBusQueueTrigger; diff --git a/app/v3/serviceBusQueueTriggerAndOutput/function.json b/app/v3/serviceBusQueueTriggerAndOutput/function.json index 7e4f18f4..3edce73d 100644 --- a/app/v3/serviceBusQueueTriggerAndOutput/function.json +++ b/app/v3/serviceBusQueueTriggerAndOutput/function.json @@ -4,15 +4,15 @@ "name": "mySbMsg", "type": "serviceBusTrigger", "direction": "in", - "queueName": "e2eTestQueueOneTriggerAndOutput", - "connection": "e2eTest_serviceBus" + "queueName": "e2e-test-queue-one-trigger-and-output", + "connection": "ServiceBusConnection" }, { "name": "$return", "type": "serviceBus", "direction": "out", - "topicName": "e2eTestQueueOneTrigger", - "connection": "e2eTest_serviceBus" + "topicName": "e2e-test-queue-one-trigger", + "connection": "ServiceBusConnection" } ], "scriptFile": "../dist/serviceBusQueueTriggerAndOutput/index.js" diff --git a/app/v3/serviceBusQueueTriggerAndOutput/index.ts b/app/v3/serviceBusQueueTriggerAndOutput/index.ts index ce3db961..f6086a03 100644 --- a/app/v3/serviceBusQueueTriggerAndOutput/index.ts +++ b/app/v3/serviceBusQueueTriggerAndOutput/index.ts @@ -1,11 +1,11 @@ -// // Copyright (c) .NET Foundation. All rights reserved. -// // Licensed under the MIT License. +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT License. -// import { AzureFunction, Context } from '@azure/functions'; +import { AzureFunction, Context } from '@azure/functions'; -// const serviceBusQueueTrigger: AzureFunction = async function (context: Context, mySbMsg: any): Promise { -// context.log(`serviceBusQueueTriggerAndOutput was triggered by "${mySbMsg}"`); -// return mySbMsg; -// }; +const serviceBusQueueTrigger: AzureFunction = async function (context: Context, mySbMsg: any): Promise { + context.log(`serviceBusQueueTriggerAndOutput was triggered by "${mySbMsg}"`); + return mySbMsg; +}; -// export default serviceBusQueueTrigger; +export default serviceBusQueueTrigger; diff --git a/app/v3/serviceBusTopicTrigger/function.json b/app/v3/serviceBusTopicTrigger/function.json index 3d6749f5..aca59931 100644 --- a/app/v3/serviceBusTopicTrigger/function.json +++ b/app/v3/serviceBusTopicTrigger/function.json @@ -4,9 +4,9 @@ "name": "mySbMsg", "type": "serviceBusTrigger", "direction": "in", - "topicName": "e2eTestTopicTrigger", + "topicName": "e2e-test-topic-trigger", "subscriptionName": "e2etestsub", - "connection": "e2eTest_serviceBus" + "connection": "ServiceBusConnection" } ], "scriptFile": "../dist/serviceBusTopicTrigger/index.js" diff --git a/app/v3/serviceBusTopicTrigger/index.ts b/app/v3/serviceBusTopicTrigger/index.ts index 8bbee113..8c4bb147 100644 --- a/app/v3/serviceBusTopicTrigger/index.ts +++ b/app/v3/serviceBusTopicTrigger/index.ts @@ -1,10 +1,10 @@ -// // Copyright (c) .NET Foundation. All rights reserved. -// // Licensed under the MIT License. +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT License. -// import { AzureFunction, Context } from '@azure/functions'; +import { AzureFunction, Context } from '@azure/functions'; -// const serviceBusTopicTrigger: AzureFunction = async function (context: Context, mySbMsg: any): Promise { -// context.log(`serviceBusTopicTrigger was triggered by "${mySbMsg}"`); -// }; +const serviceBusTopicTrigger: AzureFunction = async function (context: Context, mySbMsg: any): Promise { + context.log(`serviceBusTopicTrigger was triggered by "${mySbMsg}"`); +}; -// export default serviceBusTopicTrigger; +export default serviceBusTopicTrigger; diff --git a/app/v3/serviceBusTopicTriggerAndOutput/function.json b/app/v3/serviceBusTopicTriggerAndOutput/function.json index 4240bdb4..39b2b141 100644 --- a/app/v3/serviceBusTopicTriggerAndOutput/function.json +++ b/app/v3/serviceBusTopicTriggerAndOutput/function.json @@ -4,16 +4,16 @@ "name": "mySbMsg", "type": "serviceBusTrigger", "direction": "in", - "topicName": "e2eTestTopicTriggerAndOutput", + "topicName": "e2e-test-topic-trigger-and-output", "subscriptionName": "e2etestsub", - "connection": "e2eTest_serviceBus" + "connection": "ServiceBusConnection" }, { "name": "$return", "type": "serviceBus", "direction": "out", - "topicName": "e2eTestTopicTrigger", - "connection": "e2eTest_serviceBus" + "topicName": "e2e-test-topic-trigger", + "connection": "ServiceBusConnection" } ], "scriptFile": "../dist/serviceBusTopicTriggerAndOutput/index.js" diff --git a/app/v3/serviceBusTopicTriggerAndOutput/index.ts b/app/v3/serviceBusTopicTriggerAndOutput/index.ts index abf91677..a7125402 100644 --- a/app/v3/serviceBusTopicTriggerAndOutput/index.ts +++ b/app/v3/serviceBusTopicTriggerAndOutput/index.ts @@ -1,11 +1,11 @@ -// // Copyright (c) .NET Foundation. All rights reserved. -// // Licensed under the MIT License. +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT License. -// import { AzureFunction, Context } from '@azure/functions'; +import { AzureFunction, Context } from '@azure/functions'; -// const serviceBusTopicTrigger: AzureFunction = async function (context: Context, mySbMsg: any): Promise { -// context.log(`serviceBusTopicTriggerAndOutput was triggered by "${mySbMsg}"`); -// return mySbMsg; -// }; +const serviceBusTopicTrigger: AzureFunction = async function (context: Context, mySbMsg: any): Promise { + context.log(`serviceBusTopicTriggerAndOutput was triggered by "${mySbMsg}"`); + return mySbMsg; +}; -// export default serviceBusTopicTrigger; +export default serviceBusTopicTrigger; diff --git a/app/v4/src/functions/serviceBusQueueManyTrigger.ts b/app/v4/src/functions/serviceBusQueueManyTrigger.ts index 8484a6e1..0ba7b852 100644 --- a/app/v4/src/functions/serviceBusQueueManyTrigger.ts +++ b/app/v4/src/functions/serviceBusQueueManyTrigger.ts @@ -1,17 +1,17 @@ -// // Copyright (c) .NET Foundation. All rights reserved. -// // Licensed under the MIT License. +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT License. -// import { app, InvocationContext } from '@azure/functions'; +import { app, InvocationContext } from '@azure/functions'; -// export async function serviceBusQueueManyTrigger(messages: unknown[], context: InvocationContext): Promise { -// for (const message of messages) { -// context.log(`serviceBusQueueManyTrigger was triggered by "${message}"`); -// } -// } +export async function serviceBusQueueManyTrigger(messages: unknown[], context: InvocationContext): Promise { + for (const message of messages) { + context.log(`serviceBusQueueManyTrigger was triggered by "${message}"`); + } +} -// app.serviceBusQueue('serviceBusQueueManyTrigger', { -// connection: 'e2eTest_serviceBus', -// queueName: 'e2eTestQueueManyTrigger', -// cardinality: 'many', -// handler: serviceBusQueueManyTrigger, -// }); +app.serviceBusQueue('serviceBusQueueManyTrigger', { + connection: 'ServiceBusConnection', + queueName: 'e2e-test-queue-many-trigger', + cardinality: 'many', + handler: serviceBusQueueManyTrigger, +}); diff --git a/app/v4/src/functions/serviceBusQueueManyTriggerAndOutput.ts b/app/v4/src/functions/serviceBusQueueManyTriggerAndOutput.ts index 6e6a40bb..c70d8449 100644 --- a/app/v4/src/functions/serviceBusQueueManyTriggerAndOutput.ts +++ b/app/v4/src/functions/serviceBusQueueManyTriggerAndOutput.ts @@ -1,28 +1,28 @@ -// // Copyright (c) .NET Foundation. All rights reserved. -// // Licensed under the MIT License. +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT License. -// import { app, InvocationContext, output } from '@azure/functions'; +import { app, InvocationContext, output } from '@azure/functions'; -// export async function serviceBusQueueManyTriggerAndOutput( -// messages: unknown[], -// context: InvocationContext -// ): Promise { -// for (const message of messages) { -// context.log(`serviceBusQueueManyTriggerAndOutput was triggered by "${message}"`); -// } +export async function serviceBusQueueManyTriggerAndOutput( + messages: unknown[], + context: InvocationContext +): Promise { + for (const message of messages) { + context.log(`serviceBusQueueManyTriggerAndOutput was triggered by "${message}"`); + } -// // do an extra stringify to make sure the values are JSON-parse-able otherwise it'll hit this bug: -// // https://github.com/Azure/azure-functions-eventhubs-extension/issues/118 -// return messages.map((m) => JSON.stringify(m)); -// } + // do an extra stringify to make sure the values are JSON-parse-able otherwise it'll hit this bug: + // https://github.com/Azure/azure-functions-eventhubs-extension/issues/118 + return messages.map((m) => JSON.stringify(m)); +} -// app.serviceBusQueue('serviceBusQueueManyTriggerAndOutput', { -// connection: 'e2eTest_serviceBus', -// queueName: 'e2eTestQueueManyTriggerAndOutput', -// cardinality: 'many', -// return: output.serviceBusQueue({ -// connection: 'e2eTest_serviceBus', -// queueName: 'e2eTestQueueManyTrigger', -// }), -// handler: serviceBusQueueManyTriggerAndOutput, -// }); +app.serviceBusQueue('serviceBusQueueManyTriggerAndOutput', { + connection: 'ServiceBusConnection', + queueName: 'e2e-test-queue-many-trigger-and-output', + cardinality: 'many', + return: output.serviceBusQueue({ + connection: 'ServiceBusConnection', + queueName: 'e2e-test-queue-many-trigger', + }), + handler: serviceBusQueueManyTriggerAndOutput, +}); diff --git a/app/v4/src/functions/serviceBusQueueTrigger.ts b/app/v4/src/functions/serviceBusQueueTrigger.ts index 34b0e1dc..961e5c80 100644 --- a/app/v4/src/functions/serviceBusQueueTrigger.ts +++ b/app/v4/src/functions/serviceBusQueueTrigger.ts @@ -1,14 +1,14 @@ -// // Copyright (c) .NET Foundation. All rights reserved. -// // Licensed under the MIT License. +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT License. -// import { app, InvocationContext } from '@azure/functions'; +import { app, InvocationContext } from '@azure/functions'; -// export async function serviceBusQueueTrigger(message: unknown, context: InvocationContext): Promise { -// context.log(`serviceBusQueueTrigger was triggered by "${message}"`); -// } +export async function serviceBusQueueTrigger(message: unknown, context: InvocationContext): Promise { + context.log(`serviceBusQueueTrigger was triggered by "${message}"`); +} -// app.serviceBusQueue('serviceBusQueueTrigger', { -// connection: 'EventHubConnection', -// queueName: 'e2e_test_queue_one_trigger', -// handler: serviceBusQueueTrigger, -// }); +app.serviceBusQueue('serviceBusQueueTrigger', { + connection: 'ServiceBusConnection', + queueName: 'e2e-test-queue-one-trigger', + handler: serviceBusQueueTrigger, +}); diff --git a/app/v4/src/functions/serviceBusQueueTriggerAndOutput.ts b/app/v4/src/functions/serviceBusQueueTriggerAndOutput.ts index 52ddb09f..b73e56c5 100644 --- a/app/v4/src/functions/serviceBusQueueTriggerAndOutput.ts +++ b/app/v4/src/functions/serviceBusQueueTriggerAndOutput.ts @@ -1,19 +1,19 @@ -// // Copyright (c) .NET Foundation. All rights reserved. -// // Licensed under the MIT License. +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT License. -// import { app, InvocationContext, output } from '@azure/functions'; +import { app, InvocationContext, output } from '@azure/functions'; -// export async function serviceBusQueueTriggerAndOutput(message: unknown, context: InvocationContext): Promise { -// context.log(`serviceBusQueueTriggerAndOutput was triggered by "${message}"`); -// return message; -// } +export async function serviceBusQueueTriggerAndOutput(message: unknown, context: InvocationContext): Promise { + context.log(`serviceBusQueueTriggerAndOutput was triggered by "${message}"`); + return message; +} -// app.serviceBusQueue('serviceBusQueueTriggerAndOutput', { -// connection: 'EventHubConnection', -// queueName: 'e2e-test-queue-one-trigger-and-output', -// return: output.serviceBusQueue({ -// connection: 'EventHubConnection', -// queueName: 'e2e_test_queue_one_trigger', -// }), -// handler: serviceBusQueueTriggerAndOutput, -// }); +app.serviceBusQueue('serviceBusQueueTriggerAndOutput', { + connection: 'ServiceBusConnection', + queueName: 'e2e-test-queue-one-trigger-and-output', + return: output.serviceBusQueue({ + connection: 'ServiceBusConnection', + queueName: 'e2e-test-queue-one-trigger', + }), + handler: serviceBusQueueTriggerAndOutput, +}); diff --git a/app/v4/src/functions/serviceBusTopicTrigger.ts b/app/v4/src/functions/serviceBusTopicTrigger.ts index c2899518..deaeb1cc 100644 --- a/app/v4/src/functions/serviceBusTopicTrigger.ts +++ b/app/v4/src/functions/serviceBusTopicTrigger.ts @@ -1,15 +1,15 @@ -// // Copyright (c) .NET Foundation. All rights reserved. -// // Licensed under the MIT License. +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT License. -// import { app, InvocationContext } from '@azure/functions'; +import { app, InvocationContext } from '@azure/functions'; -// export async function serviceBusTopicTrigger(message: unknown, context: InvocationContext): Promise { -// context.log(`serviceBusTopicTrigger was triggered by "${message}"`); -// } +export async function serviceBusTopicTrigger(message: unknown, context: InvocationContext): Promise { + context.log(`serviceBusTopicTrigger was triggered by "${message}"`); +} -// app.serviceBusTopic('serviceBusTopicTrigger', { -// connection: 'e2eTest_serviceBus', -// topicName: 'e2eTestTopicTrigger', -// subscriptionName: 'e2etestsub', -// handler: serviceBusTopicTrigger, -// }); +app.serviceBusTopic('serviceBusTopicTrigger', { + connection: 'ServiceBusConnection', + topicName: 'e2e-test-topic-trigger', + subscriptionName: 'e2etestsub', + handler: serviceBusTopicTrigger, +}); diff --git a/app/v4/src/functions/serviceBusTopicTriggerAndOutput.ts b/app/v4/src/functions/serviceBusTopicTriggerAndOutput.ts index bcb59f2f..5d4ab8a9 100644 --- a/app/v4/src/functions/serviceBusTopicTriggerAndOutput.ts +++ b/app/v4/src/functions/serviceBusTopicTriggerAndOutput.ts @@ -1,20 +1,20 @@ -// // Copyright (c) .NET Foundation. All rights reserved. -// // Licensed under the MIT License. +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT License. -// import { app, InvocationContext, output } from '@azure/functions'; +import { app, InvocationContext, output } from '@azure/functions'; -// export async function serviceBusTopicTriggerAndOutput(message: unknown, context: InvocationContext): Promise { -// context.log(`serviceBusTopicTriggerAndOutput was triggered by "${message}"`); -// return message; -// } +export async function serviceBusTopicTriggerAndOutput(message: unknown, context: InvocationContext): Promise { + context.log(`serviceBusTopicTriggerAndOutput was triggered by "${message}"`); + return message; +} -// app.serviceBusTopic('serviceBusTopicTriggerAndOutput', { -// connection: 'e2eTest_serviceBus', -// topicName: 'e2eTestTopicTriggerAndOutput', -// subscriptionName: 'e2etestsub', -// return: output.serviceBusTopic({ -// connection: 'e2eTest_serviceBus', -// topicName: 'e2eTestTopicTrigger', -// }), -// handler: serviceBusTopicTriggerAndOutput, -// }); +app.serviceBusTopic('serviceBusTopicTriggerAndOutput', { + connection: 'ServiceBusConnection', + topicName: 'e2e-test-topic-trigger-and-output', + subscriptionName: 'e2etestsub', + return: output.serviceBusTopic({ + connection: 'ServiceBusConnection', + topicName: 'e2e-test-topic-trigger', + }), + handler: serviceBusTopicTriggerAndOutput, +}); diff --git a/src/constants.ts b/src/constants.ts index 24cebd74..43e5d77f 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -5,6 +5,7 @@ export namespace EnvVarNames { export const storage = 'AzureWebJobsStorage'; export const cosmosDB = 'CosmosDBConnection'; export const eventHub = 'EventHubConnection'; + export const serviceBus = 'ServiceBusConnection'; } export namespace CosmosDB { @@ -22,6 +23,15 @@ export namespace EventHub { export const eventHubManyTrigger = 'e2e-test-hub-many-trigger'; } +export namespace ServiceBus { + export const serviceBusQueueOneTriggerAndOutput = 'e2e-test-queue-one-trigger-and-output'; + export const serviceBusQueueOneTrigger = 'e2e-test-queue-one-trigger'; + export const serviceBusQueueManyTriggerAndOutput = 'e2e-test-queue-many-trigger-and-output'; + export const serviceBusQueueManyTrigger = 'e2e-test-queue-many-trigger'; + export const serviceBusTopicTriggerAndOutput = 'e2e-test-topic-trigger-and-output'; + export const serviceBusTopicTrigger = 'e2e-test-topic-trigger'; +} + export const defaultTimeout = 3 * 60 * 1000; export const combinedFolder = 'combined'; diff --git a/src/global.test.ts b/src/global.test.ts index f0472763..aa45b17a 100644 --- a/src/global.test.ts +++ b/src/global.test.ts @@ -11,6 +11,7 @@ import { cosmosDBConnectionString, eventHubConnectionString, initializeConnectionStrings, + serviceBusConnectionString, storageConnectionString } from './utils/connectionStrings'; import { setupCosmosDB } from './utils/setupCosmosDB'; @@ -116,6 +117,7 @@ async function startFuncProcess(appPath: string): Promise { [EnvVarNames.storage]: storageConnectionString, [EnvVarNames.cosmosDB]: cosmosDBConnectionString, [EnvVarNames.eventHub]: eventHubConnectionString, + [EnvVarNames.serviceBus]: serviceBusConnectionString, FUNCTIONS_REQUEST_BODY_SIZE_LIMIT: '4294967296', }, }, diff --git a/src/serviceBus.test.ts b/src/serviceBus.test.ts new file mode 100644 index 00000000..b65989ec --- /dev/null +++ b/src/serviceBus.test.ts @@ -0,0 +1,78 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT License. + +import { ServiceBusClient } from '@azure/service-bus'; +import { default as fetch } from 'node-fetch'; +import { getFuncUrl } from './constants'; +import { waitForOutput } from './global.test'; +import { getRandomTestData } from './utils/getRandomTestData'; +import { serviceBusConnectionString } from './utils/connectionStrings'; +import { ServiceBus } from './constants'; + +describe('serviceBus', () => { + let client: ServiceBusClient; + + before(() => { + client = new ServiceBusClient(serviceBusConnectionString); + }); + + after(async () => { + void client.close(); + }); + + it('queue trigger and output', async () => { + const message = getRandomTestData(); + const sender = client.createSender(ServiceBus.serviceBusQueueOneTriggerAndOutput); + const batch = await sender.createMessageBatch(); + batch.tryAddMessage({ body: message }); + await sender.sendMessages(batch); + + await waitForOutput(`serviceBusQueueTriggerAndOutput was triggered by "${message}"`); + await waitForOutput(`serviceBusQueueTrigger was triggered by "${message}"`); + }); + + it('topic trigger and output', async () => { + const message = getRandomTestData(); + const sender = client.createSender(ServiceBus.serviceBusTopicTriggerAndOutput); + const batch = await sender.createMessageBatch(); + batch.tryAddMessage({ body: message }); + await sender.sendMessages(batch); + + await waitForOutput(`serviceBusTopicTriggerAndOutput was triggered by "${message}"`); + await waitForOutput(`serviceBusTopicTrigger was triggered by "${message}"`); + }); + + it('trigger and output, cardinality many', async () => { + const message1 = getRandomTestData(); + const message2 = getRandomTestData(); + const sender = client.createSender(ServiceBus.serviceBusQueueManyTriggerAndOutput); + const batch = await sender.createMessageBatch(); + batch.tryAddMessage({ body: message1 }); + batch.tryAddMessage({ body: message2 }); + await sender.sendMessages(batch); + + await waitForOutput(`serviceBusQueueManyTriggerAndOutput was triggered by "${message1}"`); + await waitForOutput(`serviceBusQueueManyTriggerAndOutput was triggered by "${message2}"`); + await waitForOutput(`serviceBusQueueManyTrigger was triggered by "${message1}"`); + await waitForOutput(`serviceBusQueueManyTrigger was triggered by "${message2}"`); + }); + + it('extra output', async () => { + const url = getFuncUrl('httpTriggerServiceBusOutput'); + + // single + const message = getRandomTestData(); + await fetch(url, { method: 'POST', body: JSON.stringify({ output: message }) }); + await waitForOutput(`serviceBusQueueTrigger was triggered by "${message}"`); + + // bulk + const bulkMsgs: string[] = []; + for (let i = 0; i < 5; i++) { + bulkMsgs.push(getRandomTestData()); + } + await fetch(url, { method: 'POST', body: JSON.stringify({ output: bulkMsgs }) }); + for (const msg of bulkMsgs) { + await waitForOutput(`serviceBusQueueTrigger was triggered by "${msg}"`); + } + }); +}); \ No newline at end of file diff --git a/src/utils/connectionStrings.ts b/src/utils/connectionStrings.ts index e65db531..9e9f501e 100644 --- a/src/utils/connectionStrings.ts +++ b/src/utils/connectionStrings.ts @@ -4,9 +4,10 @@ export let storageConnectionString: string; export let cosmosDBConnectionString: string; export let eventHubConnectionString: string; +export let serviceBusConnectionString: string; export async function initializeConnectionStrings(): Promise { storageConnectionString = "UseDevelopmentStorage=true"; cosmosDBConnectionString = "AccountEndpoint=http://localhost:8081/;AccountKey=C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw=="; - eventHubConnectionString = "Endpoint=sb://localhost;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=SAS_KEY_VALUE;UseDevelopmentEmulator=true;"; + serviceBusConnectionString = eventHubConnectionString = "Endpoint=sb://localhost;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=SAS_KEY_VALUE;UseDevelopmentEmulator=true;"; } diff --git a/src/utils/servicebus/config.json b/src/utils/servicebus/config.json new file mode 100644 index 00000000..4196dd9d --- /dev/null +++ b/src/utils/servicebus/config.json @@ -0,0 +1,70 @@ +{ + "UserConfig": { + "Namespaces": [ + { + "Name": "sbemulatorns", + "Queues": [ + { + "Name": "e2e-test-queue-one-trigger", + "Properties": { + "DeadLetteringOnMessageExpiration": false, + "DefaultMessageTimeToLive": "PT1H", + "DuplicateDetectionHistoryTimeWindow": "PT20S", + "ForwardDeadLetteredMessagesTo": "", + "ForwardTo": "", + "LockDuration": "PT1M", + "MaxDeliveryCount": 10, + "RequiresDuplicateDetection": false, + "RequiresSession": false + } + }, + { + "Name": "e2e-test-queue-many-trigger", + "Properties": { + "DeadLetteringOnMessageExpiration": false, + "DefaultMessageTimeToLive": "PT1H", + "DuplicateDetectionHistoryTimeWindow": "PT20S", + "ForwardDeadLetteredMessagesTo": "", + "ForwardTo": "", + "LockDuration": "PT1M", + "MaxDeliveryCount": 10, + "RequiresDuplicateDetection": false, + "RequiresSession": false + } + }, + { + "Name": "e2e-test-queue-one-trigger-and-output", + "Properties": { + "DeadLetteringOnMessageExpiration": false, + "DefaultMessageTimeToLive": "PT1H", + "DuplicateDetectionHistoryTimeWindow": "PT20S", + "ForwardDeadLetteredMessagesTo": "", + "ForwardTo": "", + "LockDuration": "PT1M", + "MaxDeliveryCount": 10, + "RequiresDuplicateDetection": false, + "RequiresSession": false + } + }, + { + "Name": "e2e-test-queue-many-trigger-and-output", + "Properties": { + "DeadLetteringOnMessageExpiration": false, + "DefaultMessageTimeToLive": "PT1H", + "DuplicateDetectionHistoryTimeWindow": "PT20S", + "ForwardDeadLetteredMessagesTo": "", + "ForwardTo": "", + "LockDuration": "PT1M", + "MaxDeliveryCount": 10, + "RequiresDuplicateDetection": false, + "RequiresSession": false + } + } + ] + } + ], + "Logging": { + "Type": "File" + } + } +} \ No newline at end of file diff --git a/src/utils/servicebus/docker-compose.yml b/src/utils/servicebus/docker-compose.yml new file mode 100644 index 00000000..5fd7a7c0 --- /dev/null +++ b/src/utils/servicebus/docker-compose.yml @@ -0,0 +1,39 @@ +name: microsoft-azure-servicebus +services: + sbemulator: + container_name: "servicebus-emulator" + image: mcr.microsoft.com/azure-messaging/servicebus-emulator:latest + volumes: + - "./config.json:/ServiceBus_Emulator/ConfigFiles/Config.json" + ports: + - "5672:5672" + environment: + SQL_SERVER: sqledge + MSSQL_SA_PASSWORD: notarealpassword385! + ACCEPT_EULA: Y + depends_on: + - sqledge + networks: + sb-emulator: + aliases: + - "sb-emulator" + sqledge: + container_name: "sqledge" + image: "mcr.microsoft.com/azure-sql-edge:latest" + networks: + sb-emulator: + aliases: + - "sqledge" + environment: + ACCEPT_EULA: Y + MSSQL_SA_PASSWORD: notarealpassword123! + # Service for the Azurite Storage Emulator + azurite: + container_name: "azurite-sb" + image: "mcr.microsoft.com/azure-storage/azurite:latest" + ports: + - "10003:10003" + - "10004:10004" + - "10005:10005" +networks: + sb-emulator: \ No newline at end of file From 62c1b41a15eab041ba85c6602053408873b19399 Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Mon, 28 Jul 2025 15:11:15 -0500 Subject: [PATCH 026/142] adjust --- azure-pipelines/templates/test-node-version.yml | 7 ++++++- src/utils/servicebus/docker-compose.yml | 12 ++++++------ 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/azure-pipelines/templates/test-node-version.yml b/azure-pipelines/templates/test-node-version.yml index 029551be..bba81373 100644 --- a/azure-pipelines/templates/test-node-version.yml +++ b/azure-pipelines/templates/test-node-version.yml @@ -19,7 +19,12 @@ steps: - bash: | docker compose -f src/utils/eventhub/docker-compose.yml pull docker compose -f src/utils/eventhub/docker-compose.yml up -d - displayName: 'Install Azurite and Start EventHub Emulator' + displayName: 'Start Azurite and EventHub Emulator' + condition: and(succeeded(), ne('${{ parameters.testCommand }}', 'testOldConfig')) + - bash: | + docker compose -f src/utils/servicebus/docker-compose.yml pull + docker compose -f src/utils/servicebus/docker-compose.yml up -d + displayName: 'Start Azurite ServiceBus Emulator' condition: and(succeeded(), ne('${{ parameters.testCommand }}', 'testOldConfig')) - bash: | npm run ${{ parameters.testCommand }} diff --git a/src/utils/servicebus/docker-compose.yml b/src/utils/servicebus/docker-compose.yml index 5fd7a7c0..d9adf8da 100644 --- a/src/utils/servicebus/docker-compose.yml +++ b/src/utils/servicebus/docker-compose.yml @@ -6,10 +6,10 @@ services: volumes: - "./config.json:/ServiceBus_Emulator/ConfigFiles/Config.json" ports: - - "5672:5672" + - "5673:5672" environment: SQL_SERVER: sqledge - MSSQL_SA_PASSWORD: notarealpassword385! + MSSQL_SA_PASSWORD: thisdoesnotmatter37456! ACCEPT_EULA: Y depends_on: - sqledge @@ -26,14 +26,14 @@ services: - "sqledge" environment: ACCEPT_EULA: Y - MSSQL_SA_PASSWORD: notarealpassword123! + MSSQL_SA_PASSWORD: thisdoesnotmatter37456! # Service for the Azurite Storage Emulator azurite: container_name: "azurite-sb" image: "mcr.microsoft.com/azure-storage/azurite:latest" ports: - - "10003:10003" - - "10004:10004" - - "10005:10005" + - "10003:10000" + - "10004:10001" + - "10005:10002" networks: sb-emulator: \ No newline at end of file From 732c47d9a2ff146eaf28b16ee1e04af35c709caa Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Mon, 28 Jul 2025 15:32:30 -0500 Subject: [PATCH 027/142] adjust --- azure-pipelines/templates/test-node-version.yml | 14 ++++++++------ src/utils/servicebus/docker-compose.yml | 14 +++++++------- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/azure-pipelines/templates/test-node-version.yml b/azure-pipelines/templates/test-node-version.yml index bba81373..2e7c1a9c 100644 --- a/azure-pipelines/templates/test-node-version.yml +++ b/azure-pipelines/templates/test-node-version.yml @@ -16,15 +16,17 @@ steps: docker run --detach --publish 8081:8081 --publish 1234:1234 mcr.microsoft.com/cosmosdb/linux/azure-cosmos-emulator:vnext-preview docker ps displayName: "Start CosmosDB Emulator" - - bash: | - docker compose -f src/utils/eventhub/docker-compose.yml pull - docker compose -f src/utils/eventhub/docker-compose.yml up -d - displayName: 'Start Azurite and EventHub Emulator' - condition: and(succeeded(), ne('${{ parameters.testCommand }}', 'testOldConfig')) + # - bash: | + # docker compose -f src/utils/eventhub/docker-compose.yml pull + # docker compose -f src/utils/eventhub/docker-compose.yml up -d + # displayName: 'Start Azurite and EventHub Emulator' + # condition: and(succeeded(), ne('${{ parameters.testCommand }}', 'testOldConfig')) - bash: | docker compose -f src/utils/servicebus/docker-compose.yml pull docker compose -f src/utils/servicebus/docker-compose.yml up -d - displayName: 'Start Azurite ServiceBus Emulator' + env: + AzureWebJobsSQLPassword: $(AzureWebJobsSQLPassword) + displayName: 'Start Azurite and ServiceBus Emulator' condition: and(succeeded(), ne('${{ parameters.testCommand }}', 'testOldConfig')) - bash: | npm run ${{ parameters.testCommand }} diff --git a/src/utils/servicebus/docker-compose.yml b/src/utils/servicebus/docker-compose.yml index d9adf8da..048f121f 100644 --- a/src/utils/servicebus/docker-compose.yml +++ b/src/utils/servicebus/docker-compose.yml @@ -6,10 +6,10 @@ services: volumes: - "./config.json:/ServiceBus_Emulator/ConfigFiles/Config.json" ports: - - "5673:5672" + - "5672:5672" environment: SQL_SERVER: sqledge - MSSQL_SA_PASSWORD: thisdoesnotmatter37456! + MSSQL_SA_PASSWORD: $(AzureWebJobsSQLPassword) ACCEPT_EULA: Y depends_on: - sqledge @@ -26,14 +26,14 @@ services: - "sqledge" environment: ACCEPT_EULA: Y - MSSQL_SA_PASSWORD: thisdoesnotmatter37456! + MSSQL_SA_PASSWORD: $(AzureWebJobsSQLPassword) # Service for the Azurite Storage Emulator azurite: - container_name: "azurite-sb" + container_name: "azurite" image: "mcr.microsoft.com/azure-storage/azurite:latest" ports: - - "10003:10000" - - "10004:10001" - - "10005:10002" + - "10000:10000" + - "10001:10001" + - "10002:10002" networks: sb-emulator: \ No newline at end of file From 738b3027108bae43713d1247f39305f68048275d Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Mon, 28 Jul 2025 16:29:54 -0500 Subject: [PATCH 028/142] adjust --- .../function.json | 2 +- .../src/functions/serviceBusTopicTrigger.ts | 2 +- .../serviceBusTopicTriggerAndOutput.ts | 2 +- src/utils/servicebus/config.json | 84 ++++++++++++++++++- 4 files changed, 86 insertions(+), 4 deletions(-) diff --git a/app/v3/serviceBusTopicTriggerAndOutput/function.json b/app/v3/serviceBusTopicTriggerAndOutput/function.json index 39b2b141..48f1fbe5 100644 --- a/app/v3/serviceBusTopicTriggerAndOutput/function.json +++ b/app/v3/serviceBusTopicTriggerAndOutput/function.json @@ -5,7 +5,7 @@ "type": "serviceBusTrigger", "direction": "in", "topicName": "e2e-test-topic-trigger-and-output", - "subscriptionName": "e2etestsub", + "subscriptionName": "e2e-test-sub", "connection": "ServiceBusConnection" }, { diff --git a/app/v4/src/functions/serviceBusTopicTrigger.ts b/app/v4/src/functions/serviceBusTopicTrigger.ts index deaeb1cc..fc8b7972 100644 --- a/app/v4/src/functions/serviceBusTopicTrigger.ts +++ b/app/v4/src/functions/serviceBusTopicTrigger.ts @@ -10,6 +10,6 @@ export async function serviceBusTopicTrigger(message: unknown, context: Invocati app.serviceBusTopic('serviceBusTopicTrigger', { connection: 'ServiceBusConnection', topicName: 'e2e-test-topic-trigger', - subscriptionName: 'e2etestsub', + subscriptionName: 'e2e-test-sub', handler: serviceBusTopicTrigger, }); diff --git a/app/v4/src/functions/serviceBusTopicTriggerAndOutput.ts b/app/v4/src/functions/serviceBusTopicTriggerAndOutput.ts index 5d4ab8a9..a1b45ae4 100644 --- a/app/v4/src/functions/serviceBusTopicTriggerAndOutput.ts +++ b/app/v4/src/functions/serviceBusTopicTriggerAndOutput.ts @@ -11,7 +11,7 @@ export async function serviceBusTopicTriggerAndOutput(message: unknown, context: app.serviceBusTopic('serviceBusTopicTriggerAndOutput', { connection: 'ServiceBusConnection', topicName: 'e2e-test-topic-trigger-and-output', - subscriptionName: 'e2etestsub', + subscriptionName: 'e2e-test-sub', return: output.serviceBusTopic({ connection: 'ServiceBusConnection', topicName: 'e2e-test-topic-trigger', diff --git a/src/utils/servicebus/config.json b/src/utils/servicebus/config.json index 4196dd9d..aa5c5f42 100644 --- a/src/utils/servicebus/config.json +++ b/src/utils/servicebus/config.json @@ -60,7 +60,89 @@ "RequiresSession": false } } - ] + ], + "Topics": [ + { + "Name": "e2e-test-topic-trigger", + "Properties": { + "DefaultMessageTimeToLive": "PT1H", + "DuplicateDetectionHistoryTimeWindow": "PT20S", + "RequiresDuplicateDetection": false + }, + "Subscriptions": [ + { + "Name": "e2e-test-sub", + "Properties": { + "DeadLetteringOnMessageExpiration": false, + "DefaultMessageTimeToLive": "PT1H", + "LockDuration": "PT1M", + "MaxDeliveryCount": 3, + "ForwardDeadLetteredMessagesTo": "", + "ForwardTo": "", + "RequiresSession": false + }, + "Rules": [ + { + "Name": "app-prop-filter-1", + "Properties": { + "FilterType": "Correlation", + "CorrelationFilter": { + "ContentType": "application/text", + "CorrelationId": "id1", + "Label": "subject1", + "MessageId": "msgid1", + "ReplyTo": "someQueue", + "ReplyToSessionId": "sessionId", + "SessionId": "session1", + "To": "xyz" + } + } + } + ] + } + ] + }, + { + "Name": "e2e-test-topic-trigger-and-output", + "Properties": { + "DefaultMessageTimeToLive": "PT1H", + "DuplicateDetectionHistoryTimeWindow": "PT20S", + "RequiresDuplicateDetection": false + }, + "Subscriptions": [ + { + "Name": "e2e-test-sub", + "Properties": { + "DeadLetteringOnMessageExpiration": false, + "DefaultMessageTimeToLive": "PT1H", + "LockDuration": "PT1M", + "MaxDeliveryCount": 3, + "ForwardDeadLetteredMessagesTo": "", + "ForwardTo": "", + "RequiresSession": false + }, + "Rules": [ + { + "Name": "app-prop-filter-1", + "Properties": { + "FilterType": "Correlation", + "CorrelationFilter": { + "ContentType": "application/text", + "CorrelationId": "id1", + "Label": "subject1", + "MessageId": "msgid1", + "ReplyTo": "someQueue", + "ReplyToSessionId": "sessionId", + "SessionId": "session1", + "To": "xyz" + } + } + } + ] + } + ] + } + ] } ], "Logging": { From 5c048d52775ceab784880ee42c27b1292583c810 Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Mon, 28 Jul 2025 16:51:49 -0500 Subject: [PATCH 029/142] adjust --- app/v3/serviceBusTopicTrigger/function.json | 2 +- src/utils/servicebus/config.json | 40 ++------------------- 2 files changed, 3 insertions(+), 39 deletions(-) diff --git a/app/v3/serviceBusTopicTrigger/function.json b/app/v3/serviceBusTopicTrigger/function.json index aca59931..93c6c8ab 100644 --- a/app/v3/serviceBusTopicTrigger/function.json +++ b/app/v3/serviceBusTopicTrigger/function.json @@ -5,7 +5,7 @@ "type": "serviceBusTrigger", "direction": "in", "topicName": "e2e-test-topic-trigger", - "subscriptionName": "e2etestsub", + "subscriptionName": "e2e-test-sub", "connection": "ServiceBusConnection" } ], diff --git a/src/utils/servicebus/config.json b/src/utils/servicebus/config.json index aa5c5f42..796e0d23 100644 --- a/src/utils/servicebus/config.json +++ b/src/utils/servicebus/config.json @@ -80,25 +80,7 @@ "ForwardDeadLetteredMessagesTo": "", "ForwardTo": "", "RequiresSession": false - }, - "Rules": [ - { - "Name": "app-prop-filter-1", - "Properties": { - "FilterType": "Correlation", - "CorrelationFilter": { - "ContentType": "application/text", - "CorrelationId": "id1", - "Label": "subject1", - "MessageId": "msgid1", - "ReplyTo": "someQueue", - "ReplyToSessionId": "sessionId", - "SessionId": "session1", - "To": "xyz" - } - } - } - ] + } } ] }, @@ -120,25 +102,7 @@ "ForwardDeadLetteredMessagesTo": "", "ForwardTo": "", "RequiresSession": false - }, - "Rules": [ - { - "Name": "app-prop-filter-1", - "Properties": { - "FilterType": "Correlation", - "CorrelationFilter": { - "ContentType": "application/text", - "CorrelationId": "id1", - "Label": "subject1", - "MessageId": "msgid1", - "ReplyTo": "someQueue", - "ReplyToSessionId": "sessionId", - "SessionId": "session1", - "To": "xyz" - } - } - } - ] + } } ] } From 284287de82cf3d8694d61c63b3d3740d016e5e10 Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Mon, 28 Jul 2025 17:09:31 -0500 Subject: [PATCH 030/142] adjust --- .../httpTriggerServiceBusOutput/function.json | 4 +- app/v3/httpTriggerServiceBusOutput/index.ts | 22 +++++----- .../functions/httpTriggerServiceBusOutput.ts | 42 +++++++++---------- 3 files changed, 34 insertions(+), 34 deletions(-) diff --git a/app/v3/httpTriggerServiceBusOutput/function.json b/app/v3/httpTriggerServiceBusOutput/function.json index 628f9df7..c14d1fb2 100644 --- a/app/v3/httpTriggerServiceBusOutput/function.json +++ b/app/v3/httpTriggerServiceBusOutput/function.json @@ -16,8 +16,8 @@ "type": "serviceBus", "name": "outputMsg", "direction": "out", - "connection": "e2eTest_serviceBus", - "queueName": "e2eTestQueueOneTrigger" + "connection": "ServiceBusConnection", + "queueName": "e2e-test-queue-one-trigger" } ], "scriptFile": "../dist/httpTriggerServiceBusOutput/index.js" diff --git a/app/v3/httpTriggerServiceBusOutput/index.ts b/app/v3/httpTriggerServiceBusOutput/index.ts index 670c3093..1dee7499 100644 --- a/app/v3/httpTriggerServiceBusOutput/index.ts +++ b/app/v3/httpTriggerServiceBusOutput/index.ts @@ -1,14 +1,14 @@ -// // Copyright (c) .NET Foundation. All rights reserved. -// // Licensed under the MIT License. +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT License. -// import { AzureFunction, Context, HttpRequest } from '@azure/functions'; +import { AzureFunction, Context, HttpRequest } from '@azure/functions'; -// const httpTriggerServiceBusOutput: AzureFunction = async function ( -// context: Context, -// request: HttpRequest -// ): Promise { -// context.bindings.outputMsg = request.body.output; -// context.res = { body: 'done' }; -// }; +const httpTriggerServiceBusOutput: AzureFunction = async function ( + context: Context, + request: HttpRequest +): Promise { + context.bindings.outputMsg = request.body.output; + context.res = { body: 'done' }; +}; -// export default httpTriggerServiceBusOutput; +export default httpTriggerServiceBusOutput; diff --git a/app/v4/src/functions/httpTriggerServiceBusOutput.ts b/app/v4/src/functions/httpTriggerServiceBusOutput.ts index e3685ca1..9505a930 100644 --- a/app/v4/src/functions/httpTriggerServiceBusOutput.ts +++ b/app/v4/src/functions/httpTriggerServiceBusOutput.ts @@ -1,25 +1,25 @@ -// // Copyright (c) .NET Foundation. All rights reserved. -// // Licensed under the MIT License. +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT License. -// import { app, HttpRequest, HttpResponseInit, InvocationContext, output } from '@azure/functions'; +import { app, HttpRequest, HttpResponseInit, InvocationContext, output } from '@azure/functions'; -// const serviceBusOutput = output.serviceBusQueue({ -// connection: 'e2eTest_serviceBus', -// queueName: 'e2eTestQueueOneTrigger', -// }); +const serviceBusOutput = output.serviceBusQueue({ + connection: 'ServiceBusConnection', + queueName: 'e2e-test-queue-one-trigger', +}); -// export async function httpTriggerServiceBusOutput( -// request: HttpRequest, -// context: InvocationContext -// ): Promise { -// const body = <{ output: any }>await request.json(); -// context.extraOutputs.set(serviceBusOutput, body.output); -// return { body: 'done' }; -// } +export async function httpTriggerServiceBusOutput( + request: HttpRequest, + context: InvocationContext +): Promise { + const body = <{ output: any }>await request.json(); + context.extraOutputs.set(serviceBusOutput, body.output); + return { body: 'done' }; +} -// app.http('httpTriggerServiceBusOutput', { -// methods: ['GET', 'POST'], -// authLevel: 'anonymous', -// extraOutputs: [serviceBusOutput], -// handler: httpTriggerServiceBusOutput, -// }); +app.http('httpTriggerServiceBusOutput', { + methods: ['GET', 'POST'], + authLevel: 'anonymous', + extraOutputs: [serviceBusOutput], + handler: httpTriggerServiceBusOutput, +}); From 686910b356bac08c268d1dac3027033f30257b77 Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Mon, 28 Jul 2025 17:32:44 -0500 Subject: [PATCH 031/142] adjust --- azure-pipelines/templates/test-node-version.yml | 17 +++++++++++++---- src/utils/servicebus/docker-compose.yml | 10 +++++----- 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/azure-pipelines/templates/test-node-version.yml b/azure-pipelines/templates/test-node-version.yml index 2e7c1a9c..bb38edbd 100644 --- a/azure-pipelines/templates/test-node-version.yml +++ b/azure-pipelines/templates/test-node-version.yml @@ -17,16 +17,25 @@ steps: docker ps displayName: "Start CosmosDB Emulator" # - bash: | - # docker compose -f src/utils/eventhub/docker-compose.yml pull - # docker compose -f src/utils/eventhub/docker-compose.yml up -d - # displayName: 'Start Azurite and EventHub Emulator' + # docker run -d \ + # --name shared-azurite \ + # -p 10000:10000 \ + # -p 10001:10001 \ + # -p 10002:10002 \ + # mcr.microsoft.com/azure-storage/azurite:latest + # displayName: 'Start Shared Azurite Emulator' # condition: and(succeeded(), ne('${{ parameters.testCommand }}', 'testOldConfig')) + - bash: | + docker compose -f src/utils/eventhub/docker-compose.yml pull + docker compose -f src/utils/eventhub/docker-compose.yml up -d + displayName: 'Start EventHub Emulator' + condition: and(succeeded(), ne('${{ parameters.testCommand }}', 'testOldConfig')) - bash: | docker compose -f src/utils/servicebus/docker-compose.yml pull docker compose -f src/utils/servicebus/docker-compose.yml up -d env: AzureWebJobsSQLPassword: $(AzureWebJobsSQLPassword) - displayName: 'Start Azurite and ServiceBus Emulator' + displayName: 'Start ServiceBus Emulator' condition: and(succeeded(), ne('${{ parameters.testCommand }}', 'testOldConfig')) - bash: | npm run ${{ parameters.testCommand }} diff --git a/src/utils/servicebus/docker-compose.yml b/src/utils/servicebus/docker-compose.yml index 048f121f..56bb5db8 100644 --- a/src/utils/servicebus/docker-compose.yml +++ b/src/utils/servicebus/docker-compose.yml @@ -6,7 +6,7 @@ services: volumes: - "./config.json:/ServiceBus_Emulator/ConfigFiles/Config.json" ports: - - "5672:5672" + - "5673:5672" environment: SQL_SERVER: sqledge MSSQL_SA_PASSWORD: $(AzureWebJobsSQLPassword) @@ -29,11 +29,11 @@ services: MSSQL_SA_PASSWORD: $(AzureWebJobsSQLPassword) # Service for the Azurite Storage Emulator azurite: - container_name: "azurite" + container_name: "azurite-sb" image: "mcr.microsoft.com/azure-storage/azurite:latest" ports: - - "10000:10000" - - "10001:10001" - - "10002:10002" + - "10003:10003" + - "10004:10004" + - "10005:10005" networks: sb-emulator: \ No newline at end of file From 8a8232c612039924bed95ae473fc76dcb1a6dc13 Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Mon, 28 Jul 2025 17:41:52 -0500 Subject: [PATCH 032/142] adjust --- azure-pipelines/templates/test-node-version.yml | 10 +++++----- src/utils/servicebus/docker-compose.yml | 8 ++++---- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/azure-pipelines/templates/test-node-version.yml b/azure-pipelines/templates/test-node-version.yml index bb38edbd..d7ac9fa6 100644 --- a/azure-pipelines/templates/test-node-version.yml +++ b/azure-pipelines/templates/test-node-version.yml @@ -25,11 +25,11 @@ steps: # mcr.microsoft.com/azure-storage/azurite:latest # displayName: 'Start Shared Azurite Emulator' # condition: and(succeeded(), ne('${{ parameters.testCommand }}', 'testOldConfig')) - - bash: | - docker compose -f src/utils/eventhub/docker-compose.yml pull - docker compose -f src/utils/eventhub/docker-compose.yml up -d - displayName: 'Start EventHub Emulator' - condition: and(succeeded(), ne('${{ parameters.testCommand }}', 'testOldConfig')) + # - bash: | + # docker compose -f src/utils/eventhub/docker-compose.yml pull + # docker compose -f src/utils/eventhub/docker-compose.yml up -d + # displayName: 'Start EventHub Emulator' + # condition: and(succeeded(), ne('${{ parameters.testCommand }}', 'testOldConfig')) - bash: | docker compose -f src/utils/servicebus/docker-compose.yml pull docker compose -f src/utils/servicebus/docker-compose.yml up -d diff --git a/src/utils/servicebus/docker-compose.yml b/src/utils/servicebus/docker-compose.yml index 56bb5db8..fe7c3a1a 100644 --- a/src/utils/servicebus/docker-compose.yml +++ b/src/utils/servicebus/docker-compose.yml @@ -29,11 +29,11 @@ services: MSSQL_SA_PASSWORD: $(AzureWebJobsSQLPassword) # Service for the Azurite Storage Emulator azurite: - container_name: "azurite-sb" + container_name: "azurite" image: "mcr.microsoft.com/azure-storage/azurite:latest" ports: - - "10003:10003" - - "10004:10004" - - "10005:10005" + - "10000:10000" + - "10001:10001" + - "10002:10002" networks: sb-emulator: \ No newline at end of file From 3f6b4b0f86506c6e652aa55fab4b2f35bd6b612f Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Tue, 29 Jul 2025 13:32:17 -0500 Subject: [PATCH 033/142] adjust --- src/utils/connectionStrings.ts | 3 ++- src/utils/servicebus/docker-compose.yml | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/utils/connectionStrings.ts b/src/utils/connectionStrings.ts index 9e9f501e..1fd27bd1 100644 --- a/src/utils/connectionStrings.ts +++ b/src/utils/connectionStrings.ts @@ -9,5 +9,6 @@ export let serviceBusConnectionString: string; export async function initializeConnectionStrings(): Promise { storageConnectionString = "UseDevelopmentStorage=true"; cosmosDBConnectionString = "AccountEndpoint=http://localhost:8081/;AccountKey=C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw=="; - serviceBusConnectionString = eventHubConnectionString = "Endpoint=sb://localhost;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=SAS_KEY_VALUE;UseDevelopmentEmulator=true;"; + eventHubConnectionString = "Endpoint=sb://localhost;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=SAS_KEY_VALUE;UseDevelopmentEmulator=true;"; + serviceBusConnectionString = "Endpoint=sb://localhost:5673;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=SAS_KEY_VALUE;UseDevelopmentEmulator=true;"; } diff --git a/src/utils/servicebus/docker-compose.yml b/src/utils/servicebus/docker-compose.yml index fe7c3a1a..724bdc23 100644 --- a/src/utils/servicebus/docker-compose.yml +++ b/src/utils/servicebus/docker-compose.yml @@ -6,7 +6,7 @@ services: volumes: - "./config.json:/ServiceBus_Emulator/ConfigFiles/Config.json" ports: - - "5673:5672" + - "5673:5673" environment: SQL_SERVER: sqledge MSSQL_SA_PASSWORD: $(AzureWebJobsSQLPassword) From b6bb9df67a897ab79332388d0faf0de8cccff1c0 Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Wed, 30 Jul 2025 01:27:16 -0500 Subject: [PATCH 034/142] fix --- .../templates/test-node-version.yml | 24 ++-- src/global.test.ts | 2 +- src/sql.test.ts | 132 +++++++++--------- src/utils/connectionStrings.ts | 6 +- src/utils/{ => cosmosdb}/setupCosmosDB.ts | 4 +- src/utils/eventhub/docker-compose.yml | 2 +- src/utils/servicebus/docker-compose.yml | 2 +- src/utils/sql/docker-compose.yml | 17 +++ src/utils/sql/setupSql.ts | 113 +++++++++++++++ 9 files changed, 219 insertions(+), 83 deletions(-) rename src/utils/{ => cosmosdb}/setupCosmosDB.ts (91%) create mode 100644 src/utils/sql/docker-compose.yml create mode 100644 src/utils/sql/setupSql.ts diff --git a/azure-pipelines/templates/test-node-version.yml b/azure-pipelines/templates/test-node-version.yml index d7ac9fa6..c4357b04 100644 --- a/azure-pipelines/templates/test-node-version.yml +++ b/azure-pipelines/templates/test-node-version.yml @@ -16,6 +16,10 @@ steps: docker run --detach --publish 8081:8081 --publish 1234:1234 mcr.microsoft.com/cosmosdb/linux/azure-cosmos-emulator:vnext-preview docker ps displayName: "Start CosmosDB Emulator" + - bash: | + docker compose -f src/utils/sql/docker-compose.yml pull + docker compose -f src/utils/sql/docker-compose.yml up -d + displayName: "Start MySQL Service" # - bash: | # docker run -d \ # --name shared-azurite \ @@ -25,18 +29,18 @@ steps: # mcr.microsoft.com/azure-storage/azurite:latest # displayName: 'Start Shared Azurite Emulator' # condition: and(succeeded(), ne('${{ parameters.testCommand }}', 'testOldConfig')) - # - bash: | - # docker compose -f src/utils/eventhub/docker-compose.yml pull - # docker compose -f src/utils/eventhub/docker-compose.yml up -d - # displayName: 'Start EventHub Emulator' - # condition: and(succeeded(), ne('${{ parameters.testCommand }}', 'testOldConfig')) - bash: | - docker compose -f src/utils/servicebus/docker-compose.yml pull - docker compose -f src/utils/servicebus/docker-compose.yml up -d - env: - AzureWebJobsSQLPassword: $(AzureWebJobsSQLPassword) - displayName: 'Start ServiceBus Emulator' + docker compose -f src/utils/eventhub/docker-compose.yml pull + docker compose -f src/utils/eventhub/docker-compose.yml up -d + displayName: 'Start EventHub Emulator' condition: and(succeeded(), ne('${{ parameters.testCommand }}', 'testOldConfig')) + # - bash: | + # docker compose -f src/utils/servicebus/docker-compose.yml pull + # docker compose -f src/utils/servicebus/docker-compose.yml up -d + # env: + # AzureWebJobsSQLPassword: $(AzureWebJobsSQLPassword) + # displayName: 'Start ServiceBus Emulator' + # condition: and(succeeded(), ne('${{ parameters.testCommand }}', 'testOldConfig')) - bash: | npm run ${{ parameters.testCommand }} displayName: 'Run tests Node ${{ parameters.nodeVersion }}' diff --git a/src/global.test.ts b/src/global.test.ts index aa45b17a..b2d3b43c 100644 --- a/src/global.test.ts +++ b/src/global.test.ts @@ -14,7 +14,7 @@ import { serviceBusConnectionString, storageConnectionString } from './utils/connectionStrings'; -import { setupCosmosDB } from './utils/setupCosmosDB'; +import { setupCosmosDB } from './utils/cosmosdb/setupCosmosDB'; import { delay } from './utils/delay'; import findProcess = require('find-process'); diff --git a/src/sql.test.ts b/src/sql.test.ts index e2b1f3a0..6d01fb8f 100644 --- a/src/sql.test.ts +++ b/src/sql.test.ts @@ -1,78 +1,78 @@ -// // Copyright (c) .NET Foundation. All rights reserved. -// // Licensed under the MIT License. +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT License. -// import { expect } from 'chai'; -// import { ConnectionPool } from 'mssql'; -// import { default as fetch } from 'node-fetch'; -// import { v4 as uuid } from 'uuid'; -// import { getFuncUrl } from './constants'; -// import { isOldConfig, waitForOutput } from './global.test'; -// import { sqlConnectionString } from './resources/connectionStrings'; -// import { createPoolConnnection, sqlTriggerTable } from './resources/sql'; -// import { getRandomTestData } from './utils/getRandomTestData'; +import { expect } from 'chai'; +import { ConnectionPool } from 'mssql'; +import { default as fetch } from 'node-fetch'; +import { v4 as uuid } from 'uuid'; +import { getFuncUrl } from './constants'; +import { isOldConfig, waitForOutput } from './global.test'; +import { sqlConnectionString } from './utils/connectionStrings'; +import { createPoolConnnection, sqlTriggerTable } from './utils/sql'; +import { getRandomTestData } from './utils/getRandomTestData'; -// describe('sql', () => { -// let poolConnection: ConnectionPool | undefined; -// before(async function (this: Mocha.Context) { -// if (isOldConfig) { -// this.skip(); -// } +describe('sql', () => { + let poolConnection: ConnectionPool | undefined; + before(async function (this: Mocha.Context) { + if (isOldConfig) { + this.skip(); + } -// poolConnection = await createPoolConnnection(sqlConnectionString); -// }); + poolConnection = await createPoolConnnection(sqlConnectionString); + }); -// after(async () => { -// await poolConnection?.close(); -// }); + after(async () => { + await poolConnection?.close(); + }); -// type SqlItem = { id: string; testData: string }; + type SqlItem = { id: string; testData: string }; -// it('trigger', async () => { -// const id = uuid(); -// const testData = getRandomTestData(); + it('trigger', async () => { + const id = uuid(); + const testData = getRandomTestData(); -// // trigger by insert -// await poolConnection!.request().query(`INSERT INTO ${sqlTriggerTable} VALUES ('${id}', '${testData}');`); -// await waitForOutput(`sqlTrigger processed 1 changes`); -// await waitForOutput(`sqlTrigger was triggered by operation "insert" for "${JSON.stringify({ id, testData })}"`); + // trigger by insert + await poolConnection!.request().query(`INSERT INTO ${sqlTriggerTable} VALUES ('${id}', '${testData}');`); + await waitForOutput(`sqlTrigger processed 1 changes`); + await waitForOutput(`sqlTrigger was triggered by operation "insert" for "${JSON.stringify({ id, testData })}"`); -// // trigger by update -// await poolConnection! -// .request() -// .query(`UPDATE ${sqlTriggerTable} SET testData='${testData}-updated' WHERE id='${id}';`); -// await waitForOutput(`sqlTrigger processed 1 changes`); -// await waitForOutput( -// `sqlTrigger was triggered by operation "update" for "${JSON.stringify({ -// id, -// testData: `${testData}-updated`, -// })}"` -// ); + // trigger by update + await poolConnection! + .request() + .query(`UPDATE ${sqlTriggerTable} SET testData='${testData}-updated' WHERE id='${id}';`); + await waitForOutput(`sqlTrigger processed 1 changes`); + await waitForOutput( + `sqlTrigger was triggered by operation "update" for "${JSON.stringify({ + id, + testData: `${testData}-updated`, + })}"` + ); -// // trigger by delete -// await poolConnection!.request().query(`DELETE FROM ${sqlTriggerTable} WHERE id='${id}';`); -// await waitForOutput(`sqlTrigger processed 1 changes`); -// await waitForOutput(`sqlTrigger was triggered by operation "delete" for "${JSON.stringify({ id })}"`); -// }); + // trigger by delete + await poolConnection!.request().query(`DELETE FROM ${sqlTriggerTable} WHERE id='${id}';`); + await waitForOutput(`sqlTrigger processed 1 changes`); + await waitForOutput(`sqlTrigger was triggered by operation "delete" for "${JSON.stringify({ id })}"`); + }); -// it('input and output', async () => { -// const outputUrl = getFuncUrl('httpTriggerSqlOutput'); + it('input and output', async () => { + const outputUrl = getFuncUrl('httpTriggerSqlOutput'); -// const id = uuid(); -// const items: SqlItem[] = [ -// { -// id, -// testData: getRandomTestData(), -// }, -// ]; -// const responseOut = await fetch(outputUrl, { method: 'POST', body: JSON.stringify(items) }); -// expect(responseOut.status).to.equal(201); -// await waitForOutput(`httpTriggerSqlOutput was triggered`); + const id = uuid(); + const items: SqlItem[] = [ + { + id, + testData: getRandomTestData(), + }, + ]; + const responseOut = await fetch(outputUrl, { method: 'POST', body: JSON.stringify(items) }); + expect(responseOut.status).to.equal(201); + await waitForOutput(`httpTriggerSqlOutput was triggered`); -// const inputUrl = getFuncUrl('httpTriggerSqlInput'); -// const responseIn = await fetch(`${inputUrl}?id=${id}`, { method: 'GET' }); -// expect(responseIn.status).to.equal(200); -// const result = await responseIn.json(); -// expect(result).to.deep.equal(items); -// await waitForOutput(`httpTriggerSqlInput was triggered`); -// }); -// }); + const inputUrl = getFuncUrl('httpTriggerSqlInput'); + const responseIn = await fetch(`${inputUrl}?id=${id}`, { method: 'GET' }); + expect(responseIn.status).to.equal(200); + const result = await responseIn.json(); + expect(result).to.deep.equal(items); + await waitForOutput(`httpTriggerSqlInput was triggered`); + }); +}); diff --git a/src/utils/connectionStrings.ts b/src/utils/connectionStrings.ts index 1fd27bd1..5d8f81cf 100644 --- a/src/utils/connectionStrings.ts +++ b/src/utils/connectionStrings.ts @@ -5,10 +5,12 @@ export let storageConnectionString: string; export let cosmosDBConnectionString: string; export let eventHubConnectionString: string; export let serviceBusConnectionString: string; +export let sqlConnectionString: string; export async function initializeConnectionStrings(): Promise { storageConnectionString = "UseDevelopmentStorage=true"; cosmosDBConnectionString = "AccountEndpoint=http://localhost:8081/;AccountKey=C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw=="; - eventHubConnectionString = "Endpoint=sb://localhost;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=SAS_KEY_VALUE;UseDevelopmentEmulator=true;"; - serviceBusConnectionString = "Endpoint=sb://localhost:5673;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=SAS_KEY_VALUE;UseDevelopmentEmulator=true;"; + eventHubConnectionString = "Endpoint=sb://127.0.0.1:6672;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=SAS_KEY_VALUE;UseDevelopmentEmulator=true;"; + serviceBusConnectionString = "Endpoint=sb://localhost;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=SAS_KEY_VALUE;UseDevelopmentEmulator=true;"; + sqlConnectionString = "Server=localhost;UserID=root;Password=password;Database=testdb;Port=3307" } diff --git a/src/utils/setupCosmosDB.ts b/src/utils/cosmosdb/setupCosmosDB.ts similarity index 91% rename from src/utils/setupCosmosDB.ts rename to src/utils/cosmosdb/setupCosmosDB.ts index b7a68bc0..b8851b7c 100644 --- a/src/utils/setupCosmosDB.ts +++ b/src/utils/cosmosdb/setupCosmosDB.ts @@ -6,8 +6,8 @@ // Microsoft.Azure.Cosmos.Client: This builder instance has already been used to build a processor. Create a new instance to build another. import { CosmosClient, PartitionKeyKind } from '@azure/cosmos'; -import { cosmosDBConnectionString } from './connectionStrings'; -import { CosmosDB } from '../constants'; +import { cosmosDBConnectionString } from '../connectionStrings'; +import { CosmosDB } from '../../constants'; export async function setupCosmosDB() { const partitionKeyPath = `/${CosmosDB.partitionKey}`; diff --git a/src/utils/eventhub/docker-compose.yml b/src/utils/eventhub/docker-compose.yml index 642ac61a..13ff52d3 100644 --- a/src/utils/eventhub/docker-compose.yml +++ b/src/utils/eventhub/docker-compose.yml @@ -6,7 +6,7 @@ services: volumes: - "./config.json:/Eventhubs_Emulator/ConfigFiles/Config.json" ports: - - "5672:5672" + - "6672:5672" - "9092:9092" - "5300:5300" environment: diff --git a/src/utils/servicebus/docker-compose.yml b/src/utils/servicebus/docker-compose.yml index 724bdc23..048f121f 100644 --- a/src/utils/servicebus/docker-compose.yml +++ b/src/utils/servicebus/docker-compose.yml @@ -6,7 +6,7 @@ services: volumes: - "./config.json:/ServiceBus_Emulator/ConfigFiles/Config.json" ports: - - "5673:5673" + - "5672:5672" environment: SQL_SERVER: sqledge MSSQL_SA_PASSWORD: $(AzureWebJobsSQLPassword) diff --git a/src/utils/sql/docker-compose.yml b/src/utils/sql/docker-compose.yml new file mode 100644 index 00000000..a4e8754a --- /dev/null +++ b/src/utils/sql/docker-compose.yml @@ -0,0 +1,17 @@ +name: mysql-database +services: + mysql: + container_name: "mysql" + image: "mysql:8.0" + ports: + - "3307:3306" + environment: + MYSQL_ROOT_PASSWORD: password + MYSQL_DATABASE: testdb + MYSQL_USER: user + MYSQL_PASSWORD: password + networks: + - mysql-network +networks: + mysql-network: + driver: bridge \ No newline at end of file diff --git a/src/utils/sql/setupSql.ts b/src/utils/sql/setupSql.ts new file mode 100644 index 00000000..4cb6f8a5 --- /dev/null +++ b/src/utils/sql/setupSql.ts @@ -0,0 +1,113 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT License. + +import { SqlManagementClient } from '@azure/arm-sql'; +import * as sql from 'mssql'; +import { default as fetch } from 'node-fetch'; +import retry from 'p-retry'; +import { createSecret, getSecret } from './keyVault'; +import { ResourceInfo } from './ResourceInfo'; + +/** + * Various helpful sql docs: + * https://github.com/Azure/azure-functions-sql-extension/blob/main/docs/GeneralSetup.md + * https://github.com/Azure/azure-functions-sql-extension/blob/main/docs/SetupGuide_Javascript.md + * https://learn.microsoft.com/en-us/azure/azure-sql/database/connect-query-nodejs + * https://learn.microsoft.com/en-us/azure/azure-sql/database/azure-sql-javascript-mssql-quickstart + */ + +function getSqlAccountName(info: ResourceInfo): string { + return info.resourcePrefix + 'sql'; +} + +export const dbName = 'e2eTestDB'; +export const sqlTriggerTable = 'e2eSqlTriggerTable'; +export const sqlNonTriggerTable = 'e2eSqlNonTriggerTable'; +export const sqlSecretName = 'e2eSqlSecret'; + +export async function createSql(info: ResourceInfo): Promise { + const serverName = getSqlAccountName(info); + const armClient = new SqlManagementClient(info.creds, info.subscriptionId); + const password = await createSecret(info, sqlSecretName); + await armClient.servers.beginCreateOrUpdateAndWait(info.resourceGroupName, serverName, { + location: info.location, + administratorLogin: info.userName, + administratorLoginPassword: password, + }); + + const [startIpAddress, endIpAddress] = await getPublicIpAddress(); + console.log(`Adding ip address "${startIpAddress}"-"${endIpAddress}" to sql firewall rule.`); + await armClient.firewallRules.createOrUpdate(info.resourceGroupName, serverName, 'e2eTestFirewall', { + startIpAddress, + endIpAddress, + }); + await armClient.databases.beginCreateOrUpdateAndWait(info.resourceGroupName, serverName, dbName, { + location: info.location, + sku: { + name: 'GP_S_Gen5_1', + tier: 'GeneralPurpose', + }, + }); + + await runSetupQueries(info); +} + +async function getPublicIpAddress(): Promise<[string, string]> { + const response = await fetch('https://api.ipify.org/'); + const ip = await response.text(); + // Use a range because the host ID part of the address can change mid-run in hosted agents + const hostIdRegex = /\.[0-9]+$/; + const start = ip.replace(hostIdRegex, '.0'); + const end = ip.replace(hostIdRegex, '.255'); + return [start, end]; +} + +/** + * create tables and enable change tracking for trigger + */ +async function runSetupQueries(info: ResourceInfo) { + const connectionString = await getSqlConnectionString(info); + const poolConnection = await createPoolConnnection(connectionString); + + try { + await poolConnection + .request() + .query(`ALTER DATABASE ${dbName} SET CHANGE_TRACKING = ON (CHANGE_RETENTION = 2 DAYS, AUTO_CLEANUP = ON);`); + + for (const table of [sqlTriggerTable, sqlNonTriggerTable]) { + await poolConnection + .request() + .query( + `CREATE TABLE dbo.${table} ([id] UNIQUEIDENTIFIER PRIMARY KEY, [testData] NVARCHAR(200) NOT NULL);` + ); + await poolConnection.request().query(`ALTER TABLE dbo.${table} ENABLE CHANGE_TRACKING;`); + } + } finally { + await poolConnection.close(); + } +} + +export async function createPoolConnnection(connectionString: string): Promise { + const retries = 5; + return retry( + async (currentAttempt: number) => { + if (currentAttempt > 1) { + console.log( + `${new Date().toISOString()}: Retrying sql connect. Attempt ${currentAttempt}/${retries + 1}` + ); + } + return sql.connect(connectionString); + }, + { + retries: retries, + minTimeout: 5 * 1000, + onFailedAttempt: (error) => { + if (!/ip address/i.test(error?.message || '')) { + throw error; // abort for an unrecognized error + } else if (error.retriesLeft > 0) { + console.log(`Warning: Failed to sql connect with error "${error.message}"`); + } + }, + } + ); +} \ No newline at end of file From 991cb13ccfaf5b1761951916b685683681ffcadc Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Wed, 30 Jul 2025 01:27:39 -0500 Subject: [PATCH 035/142] fix --- src/sql.test.ts | 132 ++++++++++++++++++++++++------------------------ 1 file changed, 66 insertions(+), 66 deletions(-) diff --git a/src/sql.test.ts b/src/sql.test.ts index 6d01fb8f..8c113a11 100644 --- a/src/sql.test.ts +++ b/src/sql.test.ts @@ -1,78 +1,78 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the MIT License. +// // Copyright (c) .NET Foundation. All rights reserved. +// // Licensed under the MIT License. -import { expect } from 'chai'; -import { ConnectionPool } from 'mssql'; -import { default as fetch } from 'node-fetch'; -import { v4 as uuid } from 'uuid'; -import { getFuncUrl } from './constants'; -import { isOldConfig, waitForOutput } from './global.test'; -import { sqlConnectionString } from './utils/connectionStrings'; -import { createPoolConnnection, sqlTriggerTable } from './utils/sql'; -import { getRandomTestData } from './utils/getRandomTestData'; +// import { expect } from 'chai'; +// import { ConnectionPool } from 'mssql'; +// import { default as fetch } from 'node-fetch'; +// import { v4 as uuid } from 'uuid'; +// import { getFuncUrl } from './constants'; +// import { isOldConfig, waitForOutput } from './global.test'; +// import { sqlConnectionString } from './utils/connectionStrings'; +// import { createPoolConnnection, sqlTriggerTable } from './utils/sql'; +// import { getRandomTestData } from './utils/getRandomTestData'; -describe('sql', () => { - let poolConnection: ConnectionPool | undefined; - before(async function (this: Mocha.Context) { - if (isOldConfig) { - this.skip(); - } +// describe('sql', () => { +// let poolConnection: ConnectionPool | undefined; +// before(async function (this: Mocha.Context) { +// if (isOldConfig) { +// this.skip(); +// } - poolConnection = await createPoolConnnection(sqlConnectionString); - }); +// poolConnection = await createPoolConnnection(sqlConnectionString); +// }); - after(async () => { - await poolConnection?.close(); - }); +// after(async () => { +// await poolConnection?.close(); +// }); - type SqlItem = { id: string; testData: string }; +// type SqlItem = { id: string; testData: string }; - it('trigger', async () => { - const id = uuid(); - const testData = getRandomTestData(); +// it('trigger', async () => { +// const id = uuid(); +// const testData = getRandomTestData(); - // trigger by insert - await poolConnection!.request().query(`INSERT INTO ${sqlTriggerTable} VALUES ('${id}', '${testData}');`); - await waitForOutput(`sqlTrigger processed 1 changes`); - await waitForOutput(`sqlTrigger was triggered by operation "insert" for "${JSON.stringify({ id, testData })}"`); +// // trigger by insert +// await poolConnection!.request().query(`INSERT INTO ${sqlTriggerTable} VALUES ('${id}', '${testData}');`); +// await waitForOutput(`sqlTrigger processed 1 changes`); +// await waitForOutput(`sqlTrigger was triggered by operation "insert" for "${JSON.stringify({ id, testData })}"`); - // trigger by update - await poolConnection! - .request() - .query(`UPDATE ${sqlTriggerTable} SET testData='${testData}-updated' WHERE id='${id}';`); - await waitForOutput(`sqlTrigger processed 1 changes`); - await waitForOutput( - `sqlTrigger was triggered by operation "update" for "${JSON.stringify({ - id, - testData: `${testData}-updated`, - })}"` - ); +// // trigger by update +// await poolConnection! +// .request() +// .query(`UPDATE ${sqlTriggerTable} SET testData='${testData}-updated' WHERE id='${id}';`); +// await waitForOutput(`sqlTrigger processed 1 changes`); +// await waitForOutput( +// `sqlTrigger was triggered by operation "update" for "${JSON.stringify({ +// id, +// testData: `${testData}-updated`, +// })}"` +// ); - // trigger by delete - await poolConnection!.request().query(`DELETE FROM ${sqlTriggerTable} WHERE id='${id}';`); - await waitForOutput(`sqlTrigger processed 1 changes`); - await waitForOutput(`sqlTrigger was triggered by operation "delete" for "${JSON.stringify({ id })}"`); - }); +// // trigger by delete +// await poolConnection!.request().query(`DELETE FROM ${sqlTriggerTable} WHERE id='${id}';`); +// await waitForOutput(`sqlTrigger processed 1 changes`); +// await waitForOutput(`sqlTrigger was triggered by operation "delete" for "${JSON.stringify({ id })}"`); +// }); - it('input and output', async () => { - const outputUrl = getFuncUrl('httpTriggerSqlOutput'); +// it('input and output', async () => { +// const outputUrl = getFuncUrl('httpTriggerSqlOutput'); - const id = uuid(); - const items: SqlItem[] = [ - { - id, - testData: getRandomTestData(), - }, - ]; - const responseOut = await fetch(outputUrl, { method: 'POST', body: JSON.stringify(items) }); - expect(responseOut.status).to.equal(201); - await waitForOutput(`httpTriggerSqlOutput was triggered`); +// const id = uuid(); +// const items: SqlItem[] = [ +// { +// id, +// testData: getRandomTestData(), +// }, +// ]; +// const responseOut = await fetch(outputUrl, { method: 'POST', body: JSON.stringify(items) }); +// expect(responseOut.status).to.equal(201); +// await waitForOutput(`httpTriggerSqlOutput was triggered`); - const inputUrl = getFuncUrl('httpTriggerSqlInput'); - const responseIn = await fetch(`${inputUrl}?id=${id}`, { method: 'GET' }); - expect(responseIn.status).to.equal(200); - const result = await responseIn.json(); - expect(result).to.deep.equal(items); - await waitForOutput(`httpTriggerSqlInput was triggered`); - }); -}); +// const inputUrl = getFuncUrl('httpTriggerSqlInput'); +// const responseIn = await fetch(`${inputUrl}?id=${id}`, { method: 'GET' }); +// expect(responseIn.status).to.equal(200); +// const result = await responseIn.json(); +// expect(result).to.deep.equal(items); +// await waitForOutput(`httpTriggerSqlInput was triggered`); +// }); +// }); From c3c01c28f689e3580cfabb38c8d1ef70fe8dab15 Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Wed, 30 Jul 2025 01:45:37 -0500 Subject: [PATCH 036/142] add --- src/sql.test.ts | 132 +++++++++++++++++++------------------- src/utils/sql/setupSql.ts | 2 - 2 files changed, 66 insertions(+), 68 deletions(-) diff --git a/src/sql.test.ts b/src/sql.test.ts index 8c113a11..0db37d76 100644 --- a/src/sql.test.ts +++ b/src/sql.test.ts @@ -1,78 +1,78 @@ -// // Copyright (c) .NET Foundation. All rights reserved. -// // Licensed under the MIT License. +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT License. -// import { expect } from 'chai'; -// import { ConnectionPool } from 'mssql'; -// import { default as fetch } from 'node-fetch'; -// import { v4 as uuid } from 'uuid'; -// import { getFuncUrl } from './constants'; -// import { isOldConfig, waitForOutput } from './global.test'; -// import { sqlConnectionString } from './utils/connectionStrings'; -// import { createPoolConnnection, sqlTriggerTable } from './utils/sql'; -// import { getRandomTestData } from './utils/getRandomTestData'; +import { expect } from 'chai'; +import { ConnectionPool } from 'mssql'; +import { default as fetch } from 'node-fetch'; +import { v4 as uuid } from 'uuid'; +import { getFuncUrl } from './constants'; +import { isOldConfig, waitForOutput } from './global.test'; +import { sqlConnectionString } from './utils/connectionStrings'; +import { getRandomTestData } from './utils/getRandomTestData'; +import { createPoolConnnection } from './utils/sql/setupSql'; -// describe('sql', () => { -// let poolConnection: ConnectionPool | undefined; -// before(async function (this: Mocha.Context) { -// if (isOldConfig) { -// this.skip(); -// } +describe('sql', () => { + let poolConnection: ConnectionPool | undefined; + before(async function (this: Mocha.Context) { + if (isOldConfig) { + this.skip(); + } -// poolConnection = await createPoolConnnection(sqlConnectionString); -// }); + poolConnection = await createPoolConnnection(sqlConnectionString); + }); -// after(async () => { -// await poolConnection?.close(); -// }); + after(async () => { + await poolConnection?.close(); + }); -// type SqlItem = { id: string; testData: string }; + type SqlItem = { id: string; testData: string }; -// it('trigger', async () => { -// const id = uuid(); -// const testData = getRandomTestData(); + it('trigger', async () => { + const id = uuid(); + const testData = getRandomTestData(); -// // trigger by insert -// await poolConnection!.request().query(`INSERT INTO ${sqlTriggerTable} VALUES ('${id}', '${testData}');`); -// await waitForOutput(`sqlTrigger processed 1 changes`); -// await waitForOutput(`sqlTrigger was triggered by operation "insert" for "${JSON.stringify({ id, testData })}"`); + // trigger by insert + await poolConnection!.request().query(`INSERT INTO ${sqlTriggerTable} VALUES ('${id}', '${testData}');`); + await waitForOutput(`sqlTrigger processed 1 changes`); + await waitForOutput(`sqlTrigger was triggered by operation "insert" for "${JSON.stringify({ id, testData })}"`); -// // trigger by update -// await poolConnection! -// .request() -// .query(`UPDATE ${sqlTriggerTable} SET testData='${testData}-updated' WHERE id='${id}';`); -// await waitForOutput(`sqlTrigger processed 1 changes`); -// await waitForOutput( -// `sqlTrigger was triggered by operation "update" for "${JSON.stringify({ -// id, -// testData: `${testData}-updated`, -// })}"` -// ); + // trigger by update + await poolConnection! + .request() + .query(`UPDATE ${sqlTriggerTable} SET testData='${testData}-updated' WHERE id='${id}';`); + await waitForOutput(`sqlTrigger processed 1 changes`); + await waitForOutput( + `sqlTrigger was triggered by operation "update" for "${JSON.stringify({ + id, + testData: `${testData}-updated`, + })}"` + ); -// // trigger by delete -// await poolConnection!.request().query(`DELETE FROM ${sqlTriggerTable} WHERE id='${id}';`); -// await waitForOutput(`sqlTrigger processed 1 changes`); -// await waitForOutput(`sqlTrigger was triggered by operation "delete" for "${JSON.stringify({ id })}"`); -// }); + // trigger by delete + await poolConnection!.request().query(`DELETE FROM ${sqlTriggerTable} WHERE id='${id}';`); + await waitForOutput(`sqlTrigger processed 1 changes`); + await waitForOutput(`sqlTrigger was triggered by operation "delete" for "${JSON.stringify({ id })}"`); + }); -// it('input and output', async () => { -// const outputUrl = getFuncUrl('httpTriggerSqlOutput'); + it('input and output', async () => { + const outputUrl = getFuncUrl('httpTriggerSqlOutput'); -// const id = uuid(); -// const items: SqlItem[] = [ -// { -// id, -// testData: getRandomTestData(), -// }, -// ]; -// const responseOut = await fetch(outputUrl, { method: 'POST', body: JSON.stringify(items) }); -// expect(responseOut.status).to.equal(201); -// await waitForOutput(`httpTriggerSqlOutput was triggered`); + const id = uuid(); + const items: SqlItem[] = [ + { + id, + testData: getRandomTestData(), + }, + ]; + const responseOut = await fetch(outputUrl, { method: 'POST', body: JSON.stringify(items) }); + expect(responseOut.status).to.equal(201); + await waitForOutput(`httpTriggerSqlOutput was triggered`); -// const inputUrl = getFuncUrl('httpTriggerSqlInput'); -// const responseIn = await fetch(`${inputUrl}?id=${id}`, { method: 'GET' }); -// expect(responseIn.status).to.equal(200); -// const result = await responseIn.json(); -// expect(result).to.deep.equal(items); -// await waitForOutput(`httpTriggerSqlInput was triggered`); -// }); -// }); + const inputUrl = getFuncUrl('httpTriggerSqlInput'); + const responseIn = await fetch(`${inputUrl}?id=${id}`, { method: 'GET' }); + expect(responseIn.status).to.equal(200); + const result = await responseIn.json(); + expect(result).to.deep.equal(items); + await waitForOutput(`httpTriggerSqlInput was triggered`); + }); +}); diff --git a/src/utils/sql/setupSql.ts b/src/utils/sql/setupSql.ts index 4cb6f8a5..7ac6a302 100644 --- a/src/utils/sql/setupSql.ts +++ b/src/utils/sql/setupSql.ts @@ -5,8 +5,6 @@ import { SqlManagementClient } from '@azure/arm-sql'; import * as sql from 'mssql'; import { default as fetch } from 'node-fetch'; import retry from 'p-retry'; -import { createSecret, getSecret } from './keyVault'; -import { ResourceInfo } from './ResourceInfo'; /** * Various helpful sql docs: From aeb4edee770e4415bbc8c18ebf5ca7df8e61fe29 Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Wed, 30 Jul 2025 02:15:36 -0500 Subject: [PATCH 037/142] fix --- src/constants.ts | 9 +-- src/global.test.ts | 5 ++ src/sql.test.ts | 131 +++++++++++++++---------------- src/utils/connectionStrings.ts | 2 +- src/utils/sql/docker-compose.yml | 45 ++++++++--- src/utils/sql/setupSql.ts | 53 ++----------- 6 files changed, 109 insertions(+), 136 deletions(-) diff --git a/src/constants.ts b/src/constants.ts index 790c240a..b71b2d76 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -6,14 +6,7 @@ export namespace EnvVarNames { export const cosmosDB = 'CosmosDBConnection'; export const eventHub = 'EventHubConnection'; export const serviceBus = 'ServiceBusConnection'; -} - -export namespace CosmosDB { - export const dbName = 'e2eTestDB'; - export const triggerAndOutputContainerName = 'e2eTestContainerTriggerAndOutput'; - export const triggerContainerName = 'e2eTestContainerTrigger'; - export const triggerDatabaseName = 'e2eTestDB'; - export const partitionKey = 'testPartKey'; + export const sql = 'SqlConnection'; } export namespace CosmosDB { diff --git a/src/global.test.ts b/src/global.test.ts index b2d3b43c..69b1de89 100644 --- a/src/global.test.ts +++ b/src/global.test.ts @@ -12,9 +12,11 @@ import { eventHubConnectionString, initializeConnectionStrings, serviceBusConnectionString, + sqlConnectionString, storageConnectionString } from './utils/connectionStrings'; import { setupCosmosDB } from './utils/cosmosdb/setupCosmosDB'; +import { runSqlSetupQueries } from './utils/sql/setupSql'; import { delay } from './utils/delay'; import findProcess = require('find-process'); @@ -43,6 +45,8 @@ before(async function (this: Mocha.Context): Promise { await setupCosmosDB(); + await runSqlSetupQueries(); + isOldConfig = getOldConfigArg(); const appPath = isOldConfig ? path.join(__dirname, '..', 'app', combinedFolder, model + oldConfigSuffix) @@ -118,6 +122,7 @@ async function startFuncProcess(appPath: string): Promise { [EnvVarNames.cosmosDB]: cosmosDBConnectionString, [EnvVarNames.eventHub]: eventHubConnectionString, [EnvVarNames.serviceBus]: serviceBusConnectionString, + [EnvVarNames.sql]: sqlConnectionString, FUNCTIONS_REQUEST_BODY_SIZE_LIMIT: '4294967296', }, }, diff --git a/src/sql.test.ts b/src/sql.test.ts index 0db37d76..05c3a40d 100644 --- a/src/sql.test.ts +++ b/src/sql.test.ts @@ -1,78 +1,77 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the MIT License. +// // Copyright (c) .NET Foundation. All rights reserved. +// // Licensed under the MIT License. -import { expect } from 'chai'; -import { ConnectionPool } from 'mssql'; -import { default as fetch } from 'node-fetch'; -import { v4 as uuid } from 'uuid'; -import { getFuncUrl } from './constants'; -import { isOldConfig, waitForOutput } from './global.test'; -import { sqlConnectionString } from './utils/connectionStrings'; -import { getRandomTestData } from './utils/getRandomTestData'; -import { createPoolConnnection } from './utils/sql/setupSql'; +// import { expect } from 'chai'; +// import { ConnectionPool } from 'mssql'; +// import { default as fetch } from 'node-fetch'; +// import { v4 as uuid } from 'uuid'; +// import { getFuncUrl } from './constants'; +// import { isOldConfig, waitForOutput } from './global.test'; +// import { getRandomTestData } from './utils/getRandomTestData'; +// import { createPoolConnnection } from './utils/sql/setupSql'; -describe('sql', () => { - let poolConnection: ConnectionPool | undefined; - before(async function (this: Mocha.Context) { - if (isOldConfig) { - this.skip(); - } +// describe('sql', () => { +// let poolConnection: ConnectionPool | undefined; +// before(async function (this: Mocha.Context) { +// if (isOldConfig) { +// this.skip(); +// } - poolConnection = await createPoolConnnection(sqlConnectionString); - }); +// poolConnection = await createPoolConnnection(); +// }); - after(async () => { - await poolConnection?.close(); - }); +// after(async () => { +// await poolConnection?.close(); +// }); - type SqlItem = { id: string; testData: string }; +// type SqlItem = { id: string; testData: string }; - it('trigger', async () => { - const id = uuid(); - const testData = getRandomTestData(); +// it('trigger', async () => { +// const id = uuid(); +// const testData = getRandomTestData(); - // trigger by insert - await poolConnection!.request().query(`INSERT INTO ${sqlTriggerTable} VALUES ('${id}', '${testData}');`); - await waitForOutput(`sqlTrigger processed 1 changes`); - await waitForOutput(`sqlTrigger was triggered by operation "insert" for "${JSON.stringify({ id, testData })}"`); +// // trigger by insert +// await poolConnection!.request().query(`INSERT INTO ${sqlTriggerTable} VALUES ('${id}', '${testData}');`); +// await waitForOutput(`sqlTrigger processed 1 changes`); +// await waitForOutput(`sqlTrigger was triggered by operation "insert" for "${JSON.stringify({ id, testData })}"`); - // trigger by update - await poolConnection! - .request() - .query(`UPDATE ${sqlTriggerTable} SET testData='${testData}-updated' WHERE id='${id}';`); - await waitForOutput(`sqlTrigger processed 1 changes`); - await waitForOutput( - `sqlTrigger was triggered by operation "update" for "${JSON.stringify({ - id, - testData: `${testData}-updated`, - })}"` - ); +// // trigger by update +// await poolConnection! +// .request() +// .query(`UPDATE ${sqlTriggerTable} SET testData='${testData}-updated' WHERE id='${id}';`); +// await waitForOutput(`sqlTrigger processed 1 changes`); +// await waitForOutput( +// `sqlTrigger was triggered by operation "update" for "${JSON.stringify({ +// id, +// testData: `${testData}-updated`, +// })}"` +// ); - // trigger by delete - await poolConnection!.request().query(`DELETE FROM ${sqlTriggerTable} WHERE id='${id}';`); - await waitForOutput(`sqlTrigger processed 1 changes`); - await waitForOutput(`sqlTrigger was triggered by operation "delete" for "${JSON.stringify({ id })}"`); - }); +// // trigger by delete +// await poolConnection!.request().query(`DELETE FROM ${sqlTriggerTable} WHERE id='${id}';`); +// await waitForOutput(`sqlTrigger processed 1 changes`); +// await waitForOutput(`sqlTrigger was triggered by operation "delete" for "${JSON.stringify({ id })}"`); +// }); - it('input and output', async () => { - const outputUrl = getFuncUrl('httpTriggerSqlOutput'); +// it('input and output', async () => { +// const outputUrl = getFuncUrl('httpTriggerSqlOutput'); - const id = uuid(); - const items: SqlItem[] = [ - { - id, - testData: getRandomTestData(), - }, - ]; - const responseOut = await fetch(outputUrl, { method: 'POST', body: JSON.stringify(items) }); - expect(responseOut.status).to.equal(201); - await waitForOutput(`httpTriggerSqlOutput was triggered`); +// const id = uuid(); +// const items: SqlItem[] = [ +// { +// id, +// testData: getRandomTestData(), +// }, +// ]; +// const responseOut = await fetch(outputUrl, { method: 'POST', body: JSON.stringify(items) }); +// expect(responseOut.status).to.equal(201); +// await waitForOutput(`httpTriggerSqlOutput was triggered`); - const inputUrl = getFuncUrl('httpTriggerSqlInput'); - const responseIn = await fetch(`${inputUrl}?id=${id}`, { method: 'GET' }); - expect(responseIn.status).to.equal(200); - const result = await responseIn.json(); - expect(result).to.deep.equal(items); - await waitForOutput(`httpTriggerSqlInput was triggered`); - }); -}); +// const inputUrl = getFuncUrl('httpTriggerSqlInput'); +// const responseIn = await fetch(`${inputUrl}?id=${id}`, { method: 'GET' }); +// expect(responseIn.status).to.equal(200); +// const result = await responseIn.json(); +// expect(result).to.deep.equal(items); +// await waitForOutput(`httpTriggerSqlInput was triggered`); +// }); +// }); diff --git a/src/utils/connectionStrings.ts b/src/utils/connectionStrings.ts index 5d8f81cf..d2893ee8 100644 --- a/src/utils/connectionStrings.ts +++ b/src/utils/connectionStrings.ts @@ -12,5 +12,5 @@ export async function initializeConnectionStrings(): Promise { cosmosDBConnectionString = "AccountEndpoint=http://localhost:8081/;AccountKey=C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw=="; eventHubConnectionString = "Endpoint=sb://127.0.0.1:6672;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=SAS_KEY_VALUE;UseDevelopmentEmulator=true;"; serviceBusConnectionString = "Endpoint=sb://localhost;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=SAS_KEY_VALUE;UseDevelopmentEmulator=true;"; - sqlConnectionString = "Server=localhost;UserID=root;Password=password;Database=testdb;Port=3307" + sqlConnectionString = "Server=localhost,1433;Database=master;User Id=sa;Password=YourStrong!Passw0rd;Encrypt=true;TrustServerCertificate=true;" } diff --git a/src/utils/sql/docker-compose.yml b/src/utils/sql/docker-compose.yml index a4e8754a..e2df175f 100644 --- a/src/utils/sql/docker-compose.yml +++ b/src/utils/sql/docker-compose.yml @@ -1,17 +1,36 @@ -name: mysql-database +# name: mysql-database +# services: +# mysql: +# container_name: "mysql" +# image: "mysql:8.0" +# ports: +# - "3307:3306" +# environment: +# MYSQL_ROOT_PASSWORD: password +# MYSQL_DATABASE: testdb +# MYSQL_USER: user +# MYSQL_PASSWORD: password +# networks: +# - mysql-network +# networks: +# mysql-network: +# driver: bridge + +version: '3.8' + services: - mysql: - container_name: "mysql" - image: "mysql:8.0" - ports: - - "3307:3306" + mssql: + image: mcr.microsoft.com/mssql/server:2022-latest + container_name: mssql environment: - MYSQL_ROOT_PASSWORD: password - MYSQL_DATABASE: testdb - MYSQL_USER: user - MYSQL_PASSWORD: password + SA_PASSWORD: "YourStrong!Passw0rd" + ACCEPT_EULA: "Y" + ports: + - "1433:1433" networks: - - mysql-network + - mssql-network + restart: unless-stopped + networks: - mysql-network: - driver: bridge \ No newline at end of file + mssql-network: + driver: bridge diff --git a/src/utils/sql/setupSql.ts b/src/utils/sql/setupSql.ts index 7ac6a302..60f66b22 100644 --- a/src/utils/sql/setupSql.ts +++ b/src/utils/sql/setupSql.ts @@ -1,10 +1,9 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT License. -import { SqlManagementClient } from '@azure/arm-sql'; import * as sql from 'mssql'; -import { default as fetch } from 'node-fetch'; import retry from 'p-retry'; +import { sqlConnectionString } from '../connectionStrings'; /** * Various helpful sql docs: @@ -14,58 +13,16 @@ import retry from 'p-retry'; * https://learn.microsoft.com/en-us/azure/azure-sql/database/azure-sql-javascript-mssql-quickstart */ -function getSqlAccountName(info: ResourceInfo): string { - return info.resourcePrefix + 'sql'; -} - export const dbName = 'e2eTestDB'; export const sqlTriggerTable = 'e2eSqlTriggerTable'; export const sqlNonTriggerTable = 'e2eSqlNonTriggerTable'; export const sqlSecretName = 'e2eSqlSecret'; -export async function createSql(info: ResourceInfo): Promise { - const serverName = getSqlAccountName(info); - const armClient = new SqlManagementClient(info.creds, info.subscriptionId); - const password = await createSecret(info, sqlSecretName); - await armClient.servers.beginCreateOrUpdateAndWait(info.resourceGroupName, serverName, { - location: info.location, - administratorLogin: info.userName, - administratorLoginPassword: password, - }); - - const [startIpAddress, endIpAddress] = await getPublicIpAddress(); - console.log(`Adding ip address "${startIpAddress}"-"${endIpAddress}" to sql firewall rule.`); - await armClient.firewallRules.createOrUpdate(info.resourceGroupName, serverName, 'e2eTestFirewall', { - startIpAddress, - endIpAddress, - }); - await armClient.databases.beginCreateOrUpdateAndWait(info.resourceGroupName, serverName, dbName, { - location: info.location, - sku: { - name: 'GP_S_Gen5_1', - tier: 'GeneralPurpose', - }, - }); - - await runSetupQueries(info); -} - -async function getPublicIpAddress(): Promise<[string, string]> { - const response = await fetch('https://api.ipify.org/'); - const ip = await response.text(); - // Use a range because the host ID part of the address can change mid-run in hosted agents - const hostIdRegex = /\.[0-9]+$/; - const start = ip.replace(hostIdRegex, '.0'); - const end = ip.replace(hostIdRegex, '.255'); - return [start, end]; -} - /** * create tables and enable change tracking for trigger */ -async function runSetupQueries(info: ResourceInfo) { - const connectionString = await getSqlConnectionString(info); - const poolConnection = await createPoolConnnection(connectionString); +export async function runSqlSetupQueries() { + const poolConnection = await createPoolConnnection(); try { await poolConnection @@ -85,7 +42,7 @@ async function runSetupQueries(info: ResourceInfo) { } } -export async function createPoolConnnection(connectionString: string): Promise { +export async function createPoolConnnection(): Promise { const retries = 5; return retry( async (currentAttempt: number) => { @@ -94,7 +51,7 @@ export async function createPoolConnnection(connectionString: string): Promise Date: Wed, 30 Jul 2025 14:00:50 -0500 Subject: [PATCH 038/142] fix --- package-lock.json | 95 ++++++++++++++++++++++++++++++++ package.json | 1 + src/utils/connectionStrings.ts | 2 +- src/utils/sql/docker-compose.yml | 45 +++++---------- src/utils/sql/setupSql.ts | 22 ++++---- 5 files changed, 122 insertions(+), 43 deletions(-) diff --git a/package-lock.json b/package-lock.json index 74e081dd..fa724198 100644 --- a/package-lock.json +++ b/package-lock.json @@ -52,6 +52,7 @@ "mocha-junit-reporter": "^2.0.2", "mocha-multi-reporters": "^1.5.1", "mssql": "^10.0.2", + "mysql2": "^3.14.3", "node-fetch": "2.6.7", "p-retry": "^4.0.0", "prettier": "^2.4.1", @@ -1933,6 +1934,14 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/aws-ssl-profiles": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/aws-ssl-profiles/-/aws-ssl-profiles-1.1.2.tgz", + "integrity": "sha512-NZKeq9AfyQvEeNlN0zSYAaWrmBffJh3IELMZfRpJVWgrpEbtEpnjvzqBPf+mxoI287JohRDoa+/nsfqqiZmF6g==", + "engines": { + "node": ">= 6.0.0" + } + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -2432,6 +2441,14 @@ "node": ">=0.4.0" } }, + "node_modules/denque": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", + "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==", + "engines": { + "node": ">=0.10" + } + }, "node_modules/diff": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", @@ -3309,6 +3326,14 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/generate-function": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz", + "integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==", + "dependencies": { + "is-property": "^1.0.2" + } + }, "node_modules/get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", @@ -3882,6 +3907,11 @@ "node": ">=8" } }, + "node_modules/is-property": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", + "integrity": "sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g==" + }, "node_modules/is-regex": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", @@ -4295,6 +4325,20 @@ "node": ">=10" } }, + "node_modules/lru.min": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/lru.min/-/lru.min-1.1.2.tgz", + "integrity": "sha512-Nv9KddBcQSlQopmBHXSsZVY5xsdlZkdH/Iey0BlcBYggMd4two7cZnKOK9vmy3nY0O5RGH99z1PCeTpPqszUYg==", + "engines": { + "bun": ">=1.0.0", + "deno": ">=1.30.0", + "node": ">=8.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wellwelwel" + } + }, "node_modules/make-error": { "version": "1.3.6", "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", @@ -4570,6 +4614,44 @@ "node": ">=16" } }, + "node_modules/mysql2": { + "version": "3.14.3", + "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-3.14.3.tgz", + "integrity": "sha512-fD6MLV8XJ1KiNFIF0bS7Msl8eZyhlTDCDl75ajU5SJtpdx9ZPEACulJcqJWr1Y8OYyxsFc4j3+nflpmhxCU5aQ==", + "dependencies": { + "aws-ssl-profiles": "^1.1.1", + "denque": "^2.1.0", + "generate-function": "^2.3.1", + "iconv-lite": "^0.6.3", + "long": "^5.2.1", + "lru.min": "^1.0.0", + "named-placeholders": "^1.1.3", + "seq-queue": "^0.0.5", + "sqlstring": "^2.3.2" + }, + "engines": { + "node": ">= 8.0" + } + }, + "node_modules/named-placeholders": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/named-placeholders/-/named-placeholders-1.1.3.tgz", + "integrity": "sha512-eLoBxg6wE/rZkJPhU/xRX1WTpkFEwDJEN96oxFrTsqBdbT5ec295Q+CoHrL9IT0DipqKhmGcaZmwOt8OON5x1w==", + "dependencies": { + "lru-cache": "^7.14.1" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/named-placeholders/node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "engines": { + "node": ">=12" + } + }, "node_modules/native-duplexpair": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/native-duplexpair/-/native-duplexpair-1.0.0.tgz", @@ -5312,6 +5394,11 @@ "node": ">=10" } }, + "node_modules/seq-queue": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/seq-queue/-/seq-queue-0.0.5.tgz", + "integrity": "sha512-hr3Wtp/GZIc/6DAGPDcV4/9WoZhjrkXsi5B/07QgX8tsdc6ilr7BFM6PM6rbdAX1kFSDYeZGLipIZZKyQP0O5Q==" + }, "node_modules/serialize-javascript": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", @@ -5451,6 +5538,14 @@ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" }, + "node_modules/sqlstring": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.3.tgz", + "integrity": "sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg==", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/stoppable": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/stoppable/-/stoppable-1.1.0.tgz", diff --git a/package.json b/package.json index 7b679fae..e79384d1 100644 --- a/package.json +++ b/package.json @@ -78,6 +78,7 @@ "mocha-junit-reporter": "^2.0.2", "mocha-multi-reporters": "^1.5.1", "mssql": "^10.0.2", + "mysql2": "^3.14.3", "node-fetch": "2.6.7", "p-retry": "^4.0.0", "prettier": "^2.4.1", diff --git a/src/utils/connectionStrings.ts b/src/utils/connectionStrings.ts index d2893ee8..5d8f81cf 100644 --- a/src/utils/connectionStrings.ts +++ b/src/utils/connectionStrings.ts @@ -12,5 +12,5 @@ export async function initializeConnectionStrings(): Promise { cosmosDBConnectionString = "AccountEndpoint=http://localhost:8081/;AccountKey=C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw=="; eventHubConnectionString = "Endpoint=sb://127.0.0.1:6672;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=SAS_KEY_VALUE;UseDevelopmentEmulator=true;"; serviceBusConnectionString = "Endpoint=sb://localhost;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=SAS_KEY_VALUE;UseDevelopmentEmulator=true;"; - sqlConnectionString = "Server=localhost,1433;Database=master;User Id=sa;Password=YourStrong!Passw0rd;Encrypt=true;TrustServerCertificate=true;" + sqlConnectionString = "Server=localhost;UserID=root;Password=password;Database=testdb;Port=3307" } diff --git a/src/utils/sql/docker-compose.yml b/src/utils/sql/docker-compose.yml index e2df175f..a4e8754a 100644 --- a/src/utils/sql/docker-compose.yml +++ b/src/utils/sql/docker-compose.yml @@ -1,36 +1,17 @@ -# name: mysql-database -# services: -# mysql: -# container_name: "mysql" -# image: "mysql:8.0" -# ports: -# - "3307:3306" -# environment: -# MYSQL_ROOT_PASSWORD: password -# MYSQL_DATABASE: testdb -# MYSQL_USER: user -# MYSQL_PASSWORD: password -# networks: -# - mysql-network -# networks: -# mysql-network: -# driver: bridge - -version: '3.8' - +name: mysql-database services: - mssql: - image: mcr.microsoft.com/mssql/server:2022-latest - container_name: mssql - environment: - SA_PASSWORD: "YourStrong!Passw0rd" - ACCEPT_EULA: "Y" + mysql: + container_name: "mysql" + image: "mysql:8.0" ports: - - "1433:1433" + - "3307:3306" + environment: + MYSQL_ROOT_PASSWORD: password + MYSQL_DATABASE: testdb + MYSQL_USER: user + MYSQL_PASSWORD: password networks: - - mssql-network - restart: unless-stopped - + - mysql-network networks: - mssql-network: - driver: bridge + mysql-network: + driver: bridge \ No newline at end of file diff --git a/src/utils/sql/setupSql.ts b/src/utils/sql/setupSql.ts index 60f66b22..779e05da 100644 --- a/src/utils/sql/setupSql.ts +++ b/src/utils/sql/setupSql.ts @@ -1,9 +1,8 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT License. -import * as sql from 'mssql'; +import mysql from 'mysql2/promise'; import retry from 'p-retry'; -import { sqlConnectionString } from '../connectionStrings'; /** * Various helpful sql docs: @@ -25,24 +24,21 @@ export async function runSqlSetupQueries() { const poolConnection = await createPoolConnnection(); try { - await poolConnection - .request() - .query(`ALTER DATABASE ${dbName} SET CHANGE_TRACKING = ON (CHANGE_RETENTION = 2 DAYS, AUTO_CLEANUP = ON);`); + await poolConnection.query(`ALTER DATABASE ${dbName} SET CHANGE_TRACKING = ON (CHANGE_RETENTION = 2 DAYS, AUTO_CLEANUP = ON);`); for (const table of [sqlTriggerTable, sqlNonTriggerTable]) { await poolConnection - .request() .query( `CREATE TABLE dbo.${table} ([id] UNIQUEIDENTIFIER PRIMARY KEY, [testData] NVARCHAR(200) NOT NULL);` ); - await poolConnection.request().query(`ALTER TABLE dbo.${table} ENABLE CHANGE_TRACKING;`); + await poolConnection.query(`ALTER TABLE dbo.${table} ENABLE CHANGE_TRACKING;`); } } finally { - await poolConnection.close(); + await poolConnection.end(); } } -export async function createPoolConnnection(): Promise { +export async function createPoolConnnection(): Promise { const retries = 5; return retry( async (currentAttempt: number) => { @@ -51,7 +47,13 @@ export async function createPoolConnnection(): Promise { `${new Date().toISOString()}: Retrying sql connect. Attempt ${currentAttempt}/${retries + 1}` ); } - return sql.connect(sqlConnectionString); + return mysql.createConnection({ + host: 'localhost', + user: 'user', + password: 'password', + database: 'testdb', + port: 3307 + }); }, { retries: retries, From 488c31269c56e426d1609d5e3b2c80d34d9e6140 Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Wed, 30 Jul 2025 14:02:28 -0500 Subject: [PATCH 039/142] fix --- src/utils/connectionStrings.ts | 2 +- src/utils/sql/setupSql.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/utils/connectionStrings.ts b/src/utils/connectionStrings.ts index 5d8f81cf..e52a44cb 100644 --- a/src/utils/connectionStrings.ts +++ b/src/utils/connectionStrings.ts @@ -12,5 +12,5 @@ export async function initializeConnectionStrings(): Promise { cosmosDBConnectionString = "AccountEndpoint=http://localhost:8081/;AccountKey=C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw=="; eventHubConnectionString = "Endpoint=sb://127.0.0.1:6672;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=SAS_KEY_VALUE;UseDevelopmentEmulator=true;"; serviceBusConnectionString = "Endpoint=sb://localhost;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=SAS_KEY_VALUE;UseDevelopmentEmulator=true;"; - sqlConnectionString = "Server=localhost;UserID=root;Password=password;Database=testdb;Port=3307" + sqlConnectionString = "Server=localhost;UserID=root;Password=password;Database=e2eTestDB;Port=3307" } diff --git a/src/utils/sql/setupSql.ts b/src/utils/sql/setupSql.ts index 779e05da..dc211a56 100644 --- a/src/utils/sql/setupSql.ts +++ b/src/utils/sql/setupSql.ts @@ -51,7 +51,7 @@ export async function createPoolConnnection(): Promise { host: 'localhost', user: 'user', password: 'password', - database: 'testdb', + database: 'e2eTestDB', port: 3307 }); }, From 76dc81b6209495c47753784f2ddf5aab4037cbc2 Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Wed, 30 Jul 2025 16:10:04 -0500 Subject: [PATCH 040/142] fix --- src/utils/sql/setupSql.ts | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/src/utils/sql/setupSql.ts b/src/utils/sql/setupSql.ts index dc211a56..582a9c37 100644 --- a/src/utils/sql/setupSql.ts +++ b/src/utils/sql/setupSql.ts @@ -24,14 +24,24 @@ export async function runSqlSetupQueries() { const poolConnection = await createPoolConnnection(); try { - await poolConnection.query(`ALTER DATABASE ${dbName} SET CHANGE_TRACKING = ON (CHANGE_RETENTION = 2 DAYS, AUTO_CLEANUP = ON);`); + await poolConnection.query(`CREATE DATABASE IF NOT EXISTS \`${dbName}\`;`); + await poolConnection.changeUser({ database: dbName }); for (const table of [sqlTriggerTable, sqlNonTriggerTable]) { - await poolConnection - .query( - `CREATE TABLE dbo.${table} ([id] UNIQUEIDENTIFIER PRIMARY KEY, [testData] NVARCHAR(200) NOT NULL);` - ); - await poolConnection.query(`ALTER TABLE dbo.${table} ENABLE CHANGE_TRACKING;`); + await poolConnection.query(` + CREATE TABLE IF NOT EXISTS \`${table}_changes\` ( + id CHAR(36), + action ENUM('INSERT', 'UPDATE', 'DELETE'), + changed_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP + ); + `); + + await poolConnection.query(` + CREATE TRIGGER IF NOT EXISTS ${table}_after_insert + AFTER INSERT ON \`${table}\` + FOR EACH ROW + INSERT INTO \`${table}_changes\` (id, action) VALUES (NEW.id, 'INSERT'); + `); } } finally { await poolConnection.end(); From 6a89357480f67bbac69cddb6242ecc0ea9813c1a Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Wed, 30 Jul 2025 16:25:51 -0500 Subject: [PATCH 041/142] fix --- src/utils/sql/setupSql.ts | 67 ++++++++++++++------------------------- 1 file changed, 23 insertions(+), 44 deletions(-) diff --git a/src/utils/sql/setupSql.ts b/src/utils/sql/setupSql.ts index 582a9c37..122d0382 100644 --- a/src/utils/sql/setupSql.ts +++ b/src/utils/sql/setupSql.ts @@ -27,54 +27,33 @@ export async function runSqlSetupQueries() { await poolConnection.query(`CREATE DATABASE IF NOT EXISTS \`${dbName}\`;`); await poolConnection.changeUser({ database: dbName }); - for (const table of [sqlTriggerTable, sqlNonTriggerTable]) { - await poolConnection.query(` - CREATE TABLE IF NOT EXISTS \`${table}_changes\` ( - id CHAR(36), - action ENUM('INSERT', 'UPDATE', 'DELETE'), - changed_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP - ); - `); - - await poolConnection.query(` - CREATE TRIGGER IF NOT EXISTS ${table}_after_insert - AFTER INSERT ON \`${table}\` - FOR EACH ROW - INSERT INTO \`${table}_changes\` (id, action) VALUES (NEW.id, 'INSERT'); - `); - } + // for (const table of [sqlTriggerTable, sqlNonTriggerTable]) { + // await poolConnection.query(` + // CREATE TABLE IF NOT EXISTS \`${table}_changes\` ( + // id CHAR(36), + // action ENUM('INSERT', 'UPDATE', 'DELETE'), + // changed_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP + // ); + // `); + + // await poolConnection.query(` + // CREATE TRIGGER IF NOT EXISTS ${table}_after_insert + // AFTER INSERT ON \`${table}\` + // FOR EACH ROW + // INSERT INTO \`${table}_changes\` (id, action) VALUES (NEW.id, 'INSERT'); + // `); + // } } finally { await poolConnection.end(); } } export async function createPoolConnnection(): Promise { - const retries = 5; - return retry( - async (currentAttempt: number) => { - if (currentAttempt > 1) { - console.log( - `${new Date().toISOString()}: Retrying sql connect. Attempt ${currentAttempt}/${retries + 1}` - ); - } - return mysql.createConnection({ - host: 'localhost', - user: 'user', - password: 'password', - database: 'e2eTestDB', - port: 3307 - }); - }, - { - retries: retries, - minTimeout: 5 * 1000, - onFailedAttempt: (error) => { - if (!/ip address/i.test(error?.message || '')) { - throw error; // abort for an unrecognized error - } else if (error.retriesLeft > 0) { - console.log(`Warning: Failed to sql connect with error "${error.message}"`); - } - }, - } - ); + return mysql.createConnection({ + host: 'localhost', + user: 'user', + password: 'password', + database: 'testdb', + port: 3307 + }); } \ No newline at end of file From 27707c88ae1e12327c185a8d2678e0480b3be5d7 Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Wed, 30 Jul 2025 16:39:48 -0500 Subject: [PATCH 042/142] fix --- src/utils/sql/setupSql.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/utils/sql/setupSql.ts b/src/utils/sql/setupSql.ts index 122d0382..d046a841 100644 --- a/src/utils/sql/setupSql.ts +++ b/src/utils/sql/setupSql.ts @@ -2,7 +2,6 @@ // Licensed under the MIT License. import mysql from 'mysql2/promise'; -import retry from 'p-retry'; /** * Various helpful sql docs: From 76e52b9d45e529f427b75356821be1d8b2851202 Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Thu, 31 Jul 2025 14:34:00 -0500 Subject: [PATCH 043/142] fix --- src/global.test.ts | 2 +- src/utils/sql/setupSql.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/global.test.ts b/src/global.test.ts index 69b1de89..75972b11 100644 --- a/src/global.test.ts +++ b/src/global.test.ts @@ -45,7 +45,7 @@ before(async function (this: Mocha.Context): Promise { await setupCosmosDB(); - await runSqlSetupQueries(); + // await runSqlSetupQueries(); isOldConfig = getOldConfigArg(); const appPath = isOldConfig diff --git a/src/utils/sql/setupSql.ts b/src/utils/sql/setupSql.ts index d046a841..be1ddeee 100644 --- a/src/utils/sql/setupSql.ts +++ b/src/utils/sql/setupSql.ts @@ -53,6 +53,6 @@ export async function createPoolConnnection(): Promise { user: 'user', password: 'password', database: 'testdb', - port: 3307 + port: 3307, }); } \ No newline at end of file From a838120b9639d7815e7ca9de47ea662f6635dfda Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Thu, 31 Jul 2025 14:39:44 -0500 Subject: [PATCH 044/142] fix --- src/global.test.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/global.test.ts b/src/global.test.ts index 75972b11..d679fab1 100644 --- a/src/global.test.ts +++ b/src/global.test.ts @@ -16,7 +16,6 @@ import { storageConnectionString } from './utils/connectionStrings'; import { setupCosmosDB } from './utils/cosmosdb/setupCosmosDB'; -import { runSqlSetupQueries } from './utils/sql/setupSql'; import { delay } from './utils/delay'; import findProcess = require('find-process'); From 0ecc3e5b373ecf5b203a242e4389bd488b29d58f Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Thu, 31 Jul 2025 16:53:35 -0500 Subject: [PATCH 045/142] fix --- .../templates/test-node-version-oldconfig.yml | 19 +++++++ .../templates/test-node-version.yml | 52 ++++++++----------- azure-pipelines/templates/test.yml | 15 +++--- package.json | 11 ++-- src/index.ts | 10 +++- src/utils/connectionStrings.ts | 3 +- src/utils/eventhub/docker-compose.yml | 8 +-- src/utils/servicebus/docker-compose.yml | 2 +- 8 files changed, 69 insertions(+), 51 deletions(-) create mode 100644 azure-pipelines/templates/test-node-version-oldconfig.yml diff --git a/azure-pipelines/templates/test-node-version-oldconfig.yml b/azure-pipelines/templates/test-node-version-oldconfig.yml new file mode 100644 index 00000000..2cb98909 --- /dev/null +++ b/azure-pipelines/templates/test-node-version-oldconfig.yml @@ -0,0 +1,19 @@ +parameters: + - name: nodeVersion + type: string + +steps: + - task: NodeTool@0 + inputs: + versionSpec: ${{ parameters.nodeVersion }} + displayName: 'Install Node ${{ parameters.nodeVersion }}' + retryCountOnTaskFailure: 10 + - bash: | + docker pull mcr.microsoft.com/cosmosdb/linux/azure-cosmos-emulator:vnext-preview + docker run --detach --publish 8081:8081 --publish 1234:1234 mcr.microsoft.com/cosmosdb/linux/azure-cosmos-emulator:vnext-preview + docker ps + displayName: "Start CosmosDB Emulator" + - bash: | + npm run testOldConfig + displayName: 'Run tests Node ${{ parameters.nodeVersion }}' + continueOnError: true \ No newline at end of file diff --git a/azure-pipelines/templates/test-node-version.yml b/azure-pipelines/templates/test-node-version.yml index c4357b04..00856dfc 100644 --- a/azure-pipelines/templates/test-node-version.yml +++ b/azure-pipelines/templates/test-node-version.yml @@ -1,47 +1,37 @@ parameters: - name: nodeVersion type: string - - name: testCommand - type: string - default: test steps: - task: NodeTool@0 inputs: - versionSpec: ${{ parameters.nodeVersion }} + versionSpec: ${{ parameters.nodeVersion }} displayName: 'Install Node ${{ parameters.nodeVersion }}' retryCountOnTaskFailure: 10 + - bash: | + docker compose -f src/utils/servicebus/docker-compose.yml pull + docker compose -f src/utils/servicebus/docker-compose.yml up -d + env: + AzureWebJobsSQLPassword: $(AzureWebJobsSQLPassword) + displayName: 'Start ServiceBus Emulator' + - bash: npm run testServiceBus + displayName: 'Run ServiceBus tests Node ${{ parameters.nodeVersion }}' + continueOnError: true + - bash: | + docker stop servicebus-emulator + docker container rm --force servicebus-emulator + docker compose -f src/utils/eventhub/docker-compose.yml pull + docker compose -f src/utils/eventhub/docker-compose.yml up -d + displayName: 'Stop ServiceBus Emulator and Start EventHub Emulator' - bash: | docker pull mcr.microsoft.com/cosmosdb/linux/azure-cosmos-emulator:vnext-preview docker run --detach --publish 8081:8081 --publish 1234:1234 mcr.microsoft.com/cosmosdb/linux/azure-cosmos-emulator:vnext-preview docker ps displayName: "Start CosmosDB Emulator" - - bash: | - docker compose -f src/utils/sql/docker-compose.yml pull - docker compose -f src/utils/sql/docker-compose.yml up -d - displayName: "Start MySQL Service" # - bash: | - # docker run -d \ - # --name shared-azurite \ - # -p 10000:10000 \ - # -p 10001:10001 \ - # -p 10002:10002 \ - # mcr.microsoft.com/azure-storage/azurite:latest - # displayName: 'Start Shared Azurite Emulator' - # condition: and(succeeded(), ne('${{ parameters.testCommand }}', 'testOldConfig')) - - bash: | - docker compose -f src/utils/eventhub/docker-compose.yml pull - docker compose -f src/utils/eventhub/docker-compose.yml up -d - displayName: 'Start EventHub Emulator' - condition: and(succeeded(), ne('${{ parameters.testCommand }}', 'testOldConfig')) - # - bash: | - # docker compose -f src/utils/servicebus/docker-compose.yml pull - # docker compose -f src/utils/servicebus/docker-compose.yml up -d - # env: - # AzureWebJobsSQLPassword: $(AzureWebJobsSQLPassword) - # displayName: 'Start ServiceBus Emulator' - # condition: and(succeeded(), ne('${{ parameters.testCommand }}', 'testOldConfig')) - - bash: | - npm run ${{ parameters.testCommand }} - displayName: 'Run tests Node ${{ parameters.nodeVersion }}' + # docker compose -f src/utils/sql/docker-compose.yml pull + # docker compose -f src/utils/sql/docker-compose.yml up -d + # displayName: "Start MySQL Service" + - bash: npm run testAllExceptServiceBus + displayName: 'Run remaining tests Node ${{ parameters.nodeVersion }}' continueOnError: true \ No newline at end of file diff --git a/azure-pipelines/templates/test.yml b/azure-pipelines/templates/test.yml index 98ebca05..c5a7add4 100644 --- a/azure-pipelines/templates/test.yml +++ b/azure-pipelines/templates/test.yml @@ -20,19 +20,18 @@ jobs: parameters: nodeVersion: 18.x - - template: /azure-pipelines/templates/test-node-version.yml@self - parameters: - nodeVersion: 20.x + # - template: /azure-pipelines/templates/test-node-version.yml@self + # parameters: + # nodeVersion: 20.x - - template: /azure-pipelines/templates/test-node-version.yml@self - parameters: - nodeVersion: 22.x + # - template: /azure-pipelines/templates/test-node-version.yml@self + # parameters: + # nodeVersion: 22.x # Run tests for old config (just one Node.js version is enough) - - template: /azure-pipelines/templates/test-node-version.yml@self + - template: /azure-pipelines/templates/test-node-version-oldconfig.yml@self parameters: nodeVersion: 18.x - testCommand: testOldConfig - task: PublishTestResults@2 displayName: 'Publish Unit Test Results' diff --git a/package.json b/package.json index e79384d1..1ddffa5f 100644 --- a/package.json +++ b/package.json @@ -27,12 +27,15 @@ "lint": "eslint . --fix", "watch": "tsc -w", "createCombinedApps": "node out/createCombinedApps.js", - "test": "npm run testV3 && npm run testV4", "testOldConfig": "npm run testV3OldConfig && npm run testV4OldConfig", - "testV3": "node out/index.js --model v3", "testV3OldConfig": "node out/index.js --model v3 --oldConfig", - "testV4": "node out/index.js --model v4", - "testV4OldConfig": "node out/index.js --model v4 --oldConfig" + "testV4OldConfig": "node out/index.js --model v4 --oldConfig", + "testServiceBus": "npm run testV3ServiceBus && npm run testV4ServiceBus", + "testV3ServiceBus": "ONLY_TEST=serviceBus.test.js node out/index.js --model v3", + "testV4ServiceBus": "ONLY_TEST=serviceBus.test.js node out/index.js --model v4", + "testAllExceptServiceBus": "npm run testV3AllExceptServiceBus && npm run testV4AllExceptServiceBus", + "testV3AllExceptServiceBus": "EXCLUDE_TEST=serviceBus.test.js node out/index.js --model v3", + "testV4AllExceptServiceBus": "EXCLUDE_TEST=serviceBus.test.js node out/index.js --model v4" }, "dependencies": { "@azure/arm-cosmosdb": "^15.4.0", diff --git a/src/index.ts b/src/index.ts index 0c52d1c2..acb151e6 100644 --- a/src/index.ts +++ b/src/index.ts @@ -27,7 +27,15 @@ export async function run(): Promise { const mocha = new Mocha(options); - const files: string[] = await globby('**/**.test.js', { cwd: __dirname }); + let files: string[] = await globby('**/*.test.js', { cwd: __dirname }); + const onlyTest = process.env.ONLY_TEST; + const excludeTest = process.env.EXCLUDE_TEST; + + if (onlyTest) { + files = files.filter((f) => f.endsWith(onlyTest)); + } else if (excludeTest) { + files = files.filter((f) => !f.endsWith(excludeTest)); + } files.forEach((f) => mocha.addFile(path.resolve(__dirname, f))); diff --git a/src/utils/connectionStrings.ts b/src/utils/connectionStrings.ts index e52a44cb..814bba18 100644 --- a/src/utils/connectionStrings.ts +++ b/src/utils/connectionStrings.ts @@ -10,7 +10,6 @@ export let sqlConnectionString: string; export async function initializeConnectionStrings(): Promise { storageConnectionString = "UseDevelopmentStorage=true"; cosmosDBConnectionString = "AccountEndpoint=http://localhost:8081/;AccountKey=C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw=="; - eventHubConnectionString = "Endpoint=sb://127.0.0.1:6672;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=SAS_KEY_VALUE;UseDevelopmentEmulator=true;"; - serviceBusConnectionString = "Endpoint=sb://localhost;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=SAS_KEY_VALUE;UseDevelopmentEmulator=true;"; + serviceBusConnectionString = eventHubConnectionString = "Endpoint=sb://localhost;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=SAS_KEY_VALUE;UseDevelopmentEmulator=true;"; sqlConnectionString = "Server=localhost;UserID=root;Password=password;Database=e2eTestDB;Port=3307" } diff --git a/src/utils/eventhub/docker-compose.yml b/src/utils/eventhub/docker-compose.yml index 13ff52d3..93fc3066 100644 --- a/src/utils/eventhub/docker-compose.yml +++ b/src/utils/eventhub/docker-compose.yml @@ -6,7 +6,7 @@ services: volumes: - "./config.json:/Eventhubs_Emulator/ConfigFiles/Config.json" ports: - - "6672:5672" + - "5672:5672" - "9092:9092" - "5300:5300" environment: @@ -23,9 +23,9 @@ services: container_name: "azurite" image: "mcr.microsoft.com/azure-storage/azurite:latest" ports: - - "10000:10000" - - "10001:10001" - - "10002:10002" + - "10003:10003" + - "10004:10004" + - "10005:10005" networks: eh-emulator: aliases: diff --git a/src/utils/servicebus/docker-compose.yml b/src/utils/servicebus/docker-compose.yml index 048f121f..214e4e32 100644 --- a/src/utils/servicebus/docker-compose.yml +++ b/src/utils/servicebus/docker-compose.yml @@ -16,7 +16,7 @@ services: networks: sb-emulator: aliases: - - "sb-emulator" + - "servicebus-emulator" sqledge: container_name: "sqledge" image: "mcr.microsoft.com/azure-sql-edge:latest" From 3645e485bd41466d07be712e64f8711e675c77ee Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Thu, 31 Jul 2025 17:19:10 -0500 Subject: [PATCH 046/142] fix --- package.json | 8 ++++---- src/getModelArg.ts | 7 +++++++ src/index.ts | 14 ++++++-------- 3 files changed, 17 insertions(+), 12 deletions(-) diff --git a/package.json b/package.json index 1ddffa5f..6a4f43ef 100644 --- a/package.json +++ b/package.json @@ -31,11 +31,11 @@ "testV3OldConfig": "node out/index.js --model v3 --oldConfig", "testV4OldConfig": "node out/index.js --model v4 --oldConfig", "testServiceBus": "npm run testV3ServiceBus && npm run testV4ServiceBus", - "testV3ServiceBus": "ONLY_TEST=serviceBus.test.js node out/index.js --model v3", - "testV4ServiceBus": "ONLY_TEST=serviceBus.test.js node out/index.js --model v4", + "testV3ServiceBus": "node out/index.js --model v3 --only serviceBus.test.js", + "testV4ServiceBus": "node out/index.js --model v4 --only serviceBus.test.js", "testAllExceptServiceBus": "npm run testV3AllExceptServiceBus && npm run testV4AllExceptServiceBus", - "testV3AllExceptServiceBus": "EXCLUDE_TEST=serviceBus.test.js node out/index.js --model v3", - "testV4AllExceptServiceBus": "EXCLUDE_TEST=serviceBus.test.js node out/index.js --model v4" + "testV3AllExceptServiceBus": "node out/index.js --model v3 --exclude serviceBus.test.js", + "testV4AllExceptServiceBus": "node out/index.js --model v4 --exclude serviceBus.test.js" }, "dependencies": { "@azure/arm-cosmosdb": "^15.4.0", diff --git a/src/getModelArg.ts b/src/getModelArg.ts index 9f85b941..7c496e31 100644 --- a/src/getModelArg.ts +++ b/src/getModelArg.ts @@ -20,3 +20,10 @@ export function getOldConfigArg(): boolean { const args = parseArgs(process.argv.slice(2), { boolean: flag }); return args[flag]; } + +export function getTestFileFilter(): { only?: string; exclude?: string } { + const args = parseArgs(process.argv.slice(2)); + const only = typeof args.only === 'string' ? args.only : undefined; + const exclude = typeof args.exclude === 'string' ? args.exclude : undefined; + return { only, exclude }; +} \ No newline at end of file diff --git a/src/index.ts b/src/index.ts index acb151e6..e8fde1de 100644 --- a/src/index.ts +++ b/src/index.ts @@ -5,7 +5,7 @@ import globby from 'globby'; import Mocha from 'mocha'; import path from 'path'; import { defaultTimeout } from './constants'; -import { getModelArg, getOldConfigArg } from './getModelArg'; +import { getModelArg, getOldConfigArg, getTestFileFilter } from './getModelArg'; export async function run(): Promise { try { @@ -28,13 +28,11 @@ export async function run(): Promise { const mocha = new Mocha(options); let files: string[] = await globby('**/*.test.js', { cwd: __dirname }); - const onlyTest = process.env.ONLY_TEST; - const excludeTest = process.env.EXCLUDE_TEST; - - if (onlyTest) { - files = files.filter((f) => f.endsWith(onlyTest)); - } else if (excludeTest) { - files = files.filter((f) => !f.endsWith(excludeTest)); + const { only, exclude } = getTestFileFilter(); + if (only) { + files = files.filter(f => f.endsWith(only)); + } else if (exclude) { + files = files.filter(f => !f.endsWith(exclude)); } files.forEach((f) => mocha.addFile(path.resolve(__dirname, f))); From 4522697ac8918cbf3fbdcc2e1ad7a205399efb7f Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Thu, 31 Jul 2025 17:33:07 -0500 Subject: [PATCH 047/142] fix --- azure-pipelines/templates/test-node-version.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/azure-pipelines/templates/test-node-version.yml b/azure-pipelines/templates/test-node-version.yml index 00856dfc..87aa4893 100644 --- a/azure-pipelines/templates/test-node-version.yml +++ b/azure-pipelines/templates/test-node-version.yml @@ -8,6 +8,11 @@ steps: versionSpec: ${{ parameters.nodeVersion }} displayName: 'Install Node ${{ parameters.nodeVersion }}' retryCountOnTaskFailure: 10 + - bash: | + docker pull mcr.microsoft.com/cosmosdb/linux/azure-cosmos-emulator:vnext-preview + docker run --detach --publish 8081:8081 --publish 1234:1234 mcr.microsoft.com/cosmosdb/linux/azure-cosmos-emulator:vnext-preview + docker ps + displayName: "Start CosmosDB Emulator" - bash: | docker compose -f src/utils/servicebus/docker-compose.yml pull docker compose -f src/utils/servicebus/docker-compose.yml up -d @@ -23,11 +28,6 @@ steps: docker compose -f src/utils/eventhub/docker-compose.yml pull docker compose -f src/utils/eventhub/docker-compose.yml up -d displayName: 'Stop ServiceBus Emulator and Start EventHub Emulator' - - bash: | - docker pull mcr.microsoft.com/cosmosdb/linux/azure-cosmos-emulator:vnext-preview - docker run --detach --publish 8081:8081 --publish 1234:1234 mcr.microsoft.com/cosmosdb/linux/azure-cosmos-emulator:vnext-preview - docker ps - displayName: "Start CosmosDB Emulator" # - bash: | # docker compose -f src/utils/sql/docker-compose.yml pull # docker compose -f src/utils/sql/docker-compose.yml up -d From d1f402eb6e67b95f6d57994b3829230ae4f02287 Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Thu, 31 Jul 2025 17:50:48 -0500 Subject: [PATCH 048/142] fix --- src/utils/eventhub/docker-compose.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/utils/eventhub/docker-compose.yml b/src/utils/eventhub/docker-compose.yml index 93fc3066..2a396a95 100644 --- a/src/utils/eventhub/docker-compose.yml +++ b/src/utils/eventhub/docker-compose.yml @@ -20,7 +20,7 @@ services: aliases: - "eventhubs-emulator" azurite: - container_name: "azurite" + container_name: "azurite-eh" image: "mcr.microsoft.com/azure-storage/azurite:latest" ports: - "10003:10003" @@ -29,6 +29,6 @@ services: networks: eh-emulator: aliases: - - "azurite" + - "azurite-eh" networks: eh-emulator: \ No newline at end of file From 56b423e33c9dc61cb95aa96c393ab5cb516d5330 Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Fri, 1 Aug 2025 02:07:11 -0500 Subject: [PATCH 049/142] fix --- src/serviceBus.test.ts | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/serviceBus.test.ts b/src/serviceBus.test.ts index b65989ec..74d2f5ee 100644 --- a/src/serviceBus.test.ts +++ b/src/serviceBus.test.ts @@ -4,7 +4,7 @@ import { ServiceBusClient } from '@azure/service-bus'; import { default as fetch } from 'node-fetch'; import { getFuncUrl } from './constants'; -import { waitForOutput } from './global.test'; +import { isOldConfig, waitForOutput } from './global.test'; import { getRandomTestData } from './utils/getRandomTestData'; import { serviceBusConnectionString } from './utils/connectionStrings'; import { ServiceBus } from './constants'; @@ -12,12 +12,15 @@ import { ServiceBus } from './constants'; describe('serviceBus', () => { let client: ServiceBusClient; - before(() => { + before(function (this: Mocha.Context) { + if (isOldConfig) { + this.skip(); + } client = new ServiceBusClient(serviceBusConnectionString); }); after(async () => { - void client.close(); + void client?.close(); }); it('queue trigger and output', async () => { From 75e4ee6b96dc6fe89b8420e80c23367ddd8761af Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Fri, 1 Aug 2025 02:34:40 -0500 Subject: [PATCH 050/142] fix --- .../templates/test-node-version-oldconfig.yml | 19 ------------------- .../templates/test-node-version.yml | 15 +++++++++++---- azure-pipelines/templates/test.yml | 15 ++++++++------- 3 files changed, 19 insertions(+), 30 deletions(-) delete mode 100644 azure-pipelines/templates/test-node-version-oldconfig.yml diff --git a/azure-pipelines/templates/test-node-version-oldconfig.yml b/azure-pipelines/templates/test-node-version-oldconfig.yml deleted file mode 100644 index 2cb98909..00000000 --- a/azure-pipelines/templates/test-node-version-oldconfig.yml +++ /dev/null @@ -1,19 +0,0 @@ -parameters: - - name: nodeVersion - type: string - -steps: - - task: NodeTool@0 - inputs: - versionSpec: ${{ parameters.nodeVersion }} - displayName: 'Install Node ${{ parameters.nodeVersion }}' - retryCountOnTaskFailure: 10 - - bash: | - docker pull mcr.microsoft.com/cosmosdb/linux/azure-cosmos-emulator:vnext-preview - docker run --detach --publish 8081:8081 --publish 1234:1234 mcr.microsoft.com/cosmosdb/linux/azure-cosmos-emulator:vnext-preview - docker ps - displayName: "Start CosmosDB Emulator" - - bash: | - npm run testOldConfig - displayName: 'Run tests Node ${{ parameters.nodeVersion }}' - continueOnError: true \ No newline at end of file diff --git a/azure-pipelines/templates/test-node-version.yml b/azure-pipelines/templates/test-node-version.yml index 87aa4893..d0706190 100644 --- a/azure-pipelines/templates/test-node-version.yml +++ b/azure-pipelines/templates/test-node-version.yml @@ -1,6 +1,9 @@ parameters: - name: nodeVersion type: string + - name: runOldConfig + type: boolean + default: false steps: - task: NodeTool@0 @@ -13,6 +16,10 @@ steps: docker run --detach --publish 8081:8081 --publish 1234:1234 mcr.microsoft.com/cosmosdb/linux/azure-cosmos-emulator:vnext-preview docker ps displayName: "Start CosmosDB Emulator" + # - bash: | + # docker compose -f src/utils/sql/docker-compose.yml pull + # docker compose -f src/utils/sql/docker-compose.yml up -d + # displayName: "Start MySQL Service" - bash: | docker compose -f src/utils/servicebus/docker-compose.yml pull docker compose -f src/utils/servicebus/docker-compose.yml up -d @@ -28,10 +35,10 @@ steps: docker compose -f src/utils/eventhub/docker-compose.yml pull docker compose -f src/utils/eventhub/docker-compose.yml up -d displayName: 'Stop ServiceBus Emulator and Start EventHub Emulator' - # - bash: | - # docker compose -f src/utils/sql/docker-compose.yml pull - # docker compose -f src/utils/sql/docker-compose.yml up -d - # displayName: "Start MySQL Service" - bash: npm run testAllExceptServiceBus displayName: 'Run remaining tests Node ${{ parameters.nodeVersion }}' + continueOnError: true + - bash: npm run testOldConfig + displayName: 'Run oldConfig tests Node ${{ parameters.nodeVersion }}' + condition: and(succeeded(), eq('${{ parameters.runOldConfig }}', 'true')) continueOnError: true \ No newline at end of file diff --git a/azure-pipelines/templates/test.yml b/azure-pipelines/templates/test.yml index c5a7add4..3ee4fb4b 100644 --- a/azure-pipelines/templates/test.yml +++ b/azure-pipelines/templates/test.yml @@ -20,18 +20,19 @@ jobs: parameters: nodeVersion: 18.x - # - template: /azure-pipelines/templates/test-node-version.yml@self - # parameters: - # nodeVersion: 20.x + - template: /azure-pipelines/templates/test-node-version.yml@self + parameters: + nodeVersion: 20.x - # - template: /azure-pipelines/templates/test-node-version.yml@self - # parameters: - # nodeVersion: 22.x + - template: /azure-pipelines/templates/test-node-version.yml@self + parameters: + nodeVersion: 22.x # Run tests for old config (just one Node.js version is enough) - - template: /azure-pipelines/templates/test-node-version-oldconfig.yml@self + - template: /azure-pipelines/templates/test-node-version.yml@self parameters: nodeVersion: 18.x + runOldConfig: true - task: PublishTestResults@2 displayName: 'Publish Unit Test Results' From dd331119d7386cdc74a193ea84088676d21ab336 Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Fri, 1 Aug 2025 02:56:36 -0500 Subject: [PATCH 051/142] fix --- azure-pipelines/templates/test-node-version.yml | 12 +++--------- azure-pipelines/templates/test.yml | 11 +++++------ 2 files changed, 8 insertions(+), 15 deletions(-) diff --git a/azure-pipelines/templates/test-node-version.yml b/azure-pipelines/templates/test-node-version.yml index d0706190..328e98d8 100644 --- a/azure-pipelines/templates/test-node-version.yml +++ b/azure-pipelines/templates/test-node-version.yml @@ -1,9 +1,6 @@ parameters: - name: nodeVersion type: string - - name: runOldConfig - type: boolean - default: false steps: - task: NodeTool@0 @@ -31,14 +28,11 @@ steps: continueOnError: true - bash: | docker stop servicebus-emulator - docker container rm --force servicebus-emulator docker compose -f src/utils/eventhub/docker-compose.yml pull docker compose -f src/utils/eventhub/docker-compose.yml up -d displayName: 'Stop ServiceBus Emulator and Start EventHub Emulator' - bash: npm run testAllExceptServiceBus displayName: 'Run remaining tests Node ${{ parameters.nodeVersion }}' - continueOnError: true - - bash: npm run testOldConfig - displayName: 'Run oldConfig tests Node ${{ parameters.nodeVersion }}' - condition: and(succeeded(), eq('${{ parameters.runOldConfig }}', 'true')) - continueOnError: true \ No newline at end of file + continueOnError: + - bash: docker stop eventhubs-emulator + displayName: 'Stop EventHub Emulator' \ No newline at end of file diff --git a/azure-pipelines/templates/test.yml b/azure-pipelines/templates/test.yml index 3ee4fb4b..12921ad4 100644 --- a/azure-pipelines/templates/test.yml +++ b/azure-pipelines/templates/test.yml @@ -20,6 +20,11 @@ jobs: parameters: nodeVersion: 18.x + # Run tests for old config (just one Node.js version (18) is enough) + - bash: npm run testOldConfig + displayName: 'Run oldConfig tests Node 18.x' + continueOnError: true + - template: /azure-pipelines/templates/test-node-version.yml@self parameters: nodeVersion: 20.x @@ -28,12 +33,6 @@ jobs: parameters: nodeVersion: 22.x - # Run tests for old config (just one Node.js version is enough) - - template: /azure-pipelines/templates/test-node-version.yml@self - parameters: - nodeVersion: 18.x - runOldConfig: true - - task: PublishTestResults@2 displayName: 'Publish Unit Test Results' inputs: From db31754fe2c628a2978e754c85b6342cd3fa8393 Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Fri, 1 Aug 2025 03:08:03 -0500 Subject: [PATCH 052/142] fix --- azure-pipelines/templates/test-node-version.yml | 9 ++++++++- azure-pipelines/templates/test.yml | 1 + 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/azure-pipelines/templates/test-node-version.yml b/azure-pipelines/templates/test-node-version.yml index 328e98d8..698bd9b6 100644 --- a/azure-pipelines/templates/test-node-version.yml +++ b/azure-pipelines/templates/test-node-version.yml @@ -1,6 +1,9 @@ parameters: - name: nodeVersion type: string + - name: runOldConfig + type: boolean + default: false steps: - task: NodeTool@0 @@ -35,4 +38,8 @@ steps: displayName: 'Run remaining tests Node ${{ parameters.nodeVersion }}' continueOnError: - bash: docker stop eventhubs-emulator - displayName: 'Stop EventHub Emulator' \ No newline at end of file + displayName: 'Stop EventHub Emulator' + - bash: npm run testOldConfig + displayName: 'Run oldConfig tests Node ${{ parameters.nodeVersion }}' + condition: and(succeeded(), eq('${{ parameters.runOldConfig }}', 'true')) + continueOnError: true \ No newline at end of file diff --git a/azure-pipelines/templates/test.yml b/azure-pipelines/templates/test.yml index 12921ad4..4b18997e 100644 --- a/azure-pipelines/templates/test.yml +++ b/azure-pipelines/templates/test.yml @@ -19,6 +19,7 @@ jobs: - template: /azure-pipelines/templates/test-node-version.yml@self parameters: nodeVersion: 18.x + runOldConfig: true # Run tests for old config (just one Node.js version (18) is enough) - bash: npm run testOldConfig From 8e6746bf2846591158b304679b3ed5369342262e Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Fri, 1 Aug 2025 03:08:41 -0500 Subject: [PATCH 053/142] fix --- azure-pipelines/templates/test.yml | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/azure-pipelines/templates/test.yml b/azure-pipelines/templates/test.yml index 4b18997e..13871bf4 100644 --- a/azure-pipelines/templates/test.yml +++ b/azure-pipelines/templates/test.yml @@ -19,12 +19,7 @@ jobs: - template: /azure-pipelines/templates/test-node-version.yml@self parameters: nodeVersion: 18.x - runOldConfig: true - - # Run tests for old config (just one Node.js version (18) is enough) - - bash: npm run testOldConfig - displayName: 'Run oldConfig tests Node 18.x' - continueOnError: true + runOldConfig: true # Run tests for old config (just one Node.js version (18) is enough) - template: /azure-pipelines/templates/test-node-version.yml@self parameters: From bbc65dfe4f2534fc90cf5ebf926d18917f956a8c Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Fri, 1 Aug 2025 10:54:27 -0500 Subject: [PATCH 054/142] fix --- azure-pipelines/templates/test-node-version.yml | 2 +- azure-pipelines/templates/test.yml | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/azure-pipelines/templates/test-node-version.yml b/azure-pipelines/templates/test-node-version.yml index 698bd9b6..bf6b58ea 100644 --- a/azure-pipelines/templates/test-node-version.yml +++ b/azure-pipelines/templates/test-node-version.yml @@ -36,7 +36,7 @@ steps: displayName: 'Stop ServiceBus Emulator and Start EventHub Emulator' - bash: npm run testAllExceptServiceBus displayName: 'Run remaining tests Node ${{ parameters.nodeVersion }}' - continueOnError: + continueOnError: true - bash: docker stop eventhubs-emulator displayName: 'Stop EventHub Emulator' - bash: npm run testOldConfig diff --git a/azure-pipelines/templates/test.yml b/azure-pipelines/templates/test.yml index 13871bf4..14cb21c1 100644 --- a/azure-pipelines/templates/test.yml +++ b/azure-pipelines/templates/test.yml @@ -16,10 +16,11 @@ jobs: - template: /azure-pipelines/templates/build-apps.yml@self + # Run tests for old config (just one Node.js version (18) is enough) - template: /azure-pipelines/templates/test-node-version.yml@self parameters: nodeVersion: 18.x - runOldConfig: true # Run tests for old config (just one Node.js version (18) is enough) + runOldConfig: true - template: /azure-pipelines/templates/test-node-version.yml@self parameters: From aa7487d11143296181bcbe55d04548232fd23407 Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Fri, 1 Aug 2025 13:48:23 -0500 Subject: [PATCH 055/142] fix --- azure-pipelines/templates/test-node-version.yml | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/azure-pipelines/templates/test-node-version.yml b/azure-pipelines/templates/test-node-version.yml index bf6b58ea..cc7120b5 100644 --- a/azure-pipelines/templates/test-node-version.yml +++ b/azure-pipelines/templates/test-node-version.yml @@ -13,7 +13,8 @@ steps: retryCountOnTaskFailure: 10 - bash: | docker pull mcr.microsoft.com/cosmosdb/linux/azure-cosmos-emulator:vnext-preview - docker run --detach --publish 8081:8081 --publish 1234:1234 mcr.microsoft.com/cosmosdb/linux/azure-cosmos-emulator:vnext-preview + docker run --detach --publish 8081:8081 --publish 1234:1234 mcr.microsoft.com/cosmosdb/linux/azure-cosmos-emulator:vnext- + sleep 60 docker ps displayName: "Start CosmosDB Emulator" # - bash: | @@ -23,6 +24,7 @@ steps: - bash: | docker compose -f src/utils/servicebus/docker-compose.yml pull docker compose -f src/utils/servicebus/docker-compose.yml up -d + sleep 30 env: AzureWebJobsSQLPassword: $(AzureWebJobsSQLPassword) displayName: 'Start ServiceBus Emulator' @@ -30,15 +32,21 @@ steps: displayName: 'Run ServiceBus tests Node ${{ parameters.nodeVersion }}' continueOnError: true - bash: | - docker stop servicebus-emulator + docker stop servicebus-emulator || true + docker rm -f servicebus-emulator || true docker compose -f src/utils/eventhub/docker-compose.yml pull docker compose -f src/utils/eventhub/docker-compose.yml up -d + sleep 30 displayName: 'Stop ServiceBus Emulator and Start EventHub Emulator' - bash: npm run testAllExceptServiceBus displayName: 'Run remaining tests Node ${{ parameters.nodeVersion }}' continueOnError: true - - bash: docker stop eventhubs-emulator - displayName: 'Stop EventHub Emulator' + - bash: | + docker stop cosmosdb-emulator || true + docker rm -f cosmosdb-emulator || true + docker compose -f src/utils/eventhub/docker-compose.yml down -v + docker compose -f src/utils/servicebus/docker-compose.yml down -v + displayName: 'Stop all emulators' - bash: npm run testOldConfig displayName: 'Run oldConfig tests Node ${{ parameters.nodeVersion }}' condition: and(succeeded(), eq('${{ parameters.runOldConfig }}', 'true')) From 50259fe89ae869339aea897b64d008b41179cbc0 Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Fri, 1 Aug 2025 13:50:13 -0500 Subject: [PATCH 056/142] fix --- azure-pipelines/templates/test-node-version.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azure-pipelines/templates/test-node-version.yml b/azure-pipelines/templates/test-node-version.yml index cc7120b5..88d5bffb 100644 --- a/azure-pipelines/templates/test-node-version.yml +++ b/azure-pipelines/templates/test-node-version.yml @@ -13,7 +13,7 @@ steps: retryCountOnTaskFailure: 10 - bash: | docker pull mcr.microsoft.com/cosmosdb/linux/azure-cosmos-emulator:vnext-preview - docker run --detach --publish 8081:8081 --publish 1234:1234 mcr.microsoft.com/cosmosdb/linux/azure-cosmos-emulator:vnext- + docker run --detach --publish 8081:8081 --publish 1234:1234 --name cosmosdb-emulator mcr.microsoft.com/cosmosdb/linux/azure-cosmos-emulator:vnext- sleep 60 docker ps displayName: "Start CosmosDB Emulator" From d0b2b8f9ddd16e5b6aaf4fd8f567d156c55a2c92 Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Fri, 1 Aug 2025 14:01:19 -0500 Subject: [PATCH 057/142] fix --- azure-pipelines/templates/test-node-version.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azure-pipelines/templates/test-node-version.yml b/azure-pipelines/templates/test-node-version.yml index 88d5bffb..49613aa9 100644 --- a/azure-pipelines/templates/test-node-version.yml +++ b/azure-pipelines/templates/test-node-version.yml @@ -13,7 +13,7 @@ steps: retryCountOnTaskFailure: 10 - bash: | docker pull mcr.microsoft.com/cosmosdb/linux/azure-cosmos-emulator:vnext-preview - docker run --detach --publish 8081:8081 --publish 1234:1234 --name cosmosdb-emulator mcr.microsoft.com/cosmosdb/linux/azure-cosmos-emulator:vnext- + docker run --detach --publish 8081:8081 --publish 1234:1234 --name cosmosdb-emulator mcr.microsoft.com/cosmosdb/linux/azure-cosmos-emulator:vnext-preview sleep 60 docker ps displayName: "Start CosmosDB Emulator" From f50cc4e2c90cb2f50b3fef4a12506a338f1b9d88 Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Fri, 1 Aug 2025 14:18:28 -0500 Subject: [PATCH 058/142] fix --- azure-pipelines/templates/test-node-version.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/azure-pipelines/templates/test-node-version.yml b/azure-pipelines/templates/test-node-version.yml index 49613aa9..3f31fb1b 100644 --- a/azure-pipelines/templates/test-node-version.yml +++ b/azure-pipelines/templates/test-node-version.yml @@ -41,13 +41,13 @@ steps: - bash: npm run testAllExceptServiceBus displayName: 'Run remaining tests Node ${{ parameters.nodeVersion }}' continueOnError: true + - bash: npm run testOldConfig + displayName: 'Run oldConfig tests Node ${{ parameters.nodeVersion }}' + condition: and(succeeded(), eq('${{ parameters.runOldConfig }}', 'true')) + continueOnError: true - bash: | docker stop cosmosdb-emulator || true docker rm -f cosmosdb-emulator || true docker compose -f src/utils/eventhub/docker-compose.yml down -v docker compose -f src/utils/servicebus/docker-compose.yml down -v - displayName: 'Stop all emulators' - - bash: npm run testOldConfig - displayName: 'Run oldConfig tests Node ${{ parameters.nodeVersion }}' - condition: and(succeeded(), eq('${{ parameters.runOldConfig }}', 'true')) - continueOnError: true \ No newline at end of file + displayName: 'Stop all emulators' \ No newline at end of file From a155b6d7180f8509e1a8eb652fb9ff2d58bde9fc Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Fri, 1 Aug 2025 16:00:55 -0500 Subject: [PATCH 059/142] fix --- .../templates/test-node-version.yml | 15 +-- package-lock.json | 101 +----------------- package.json | 1 - src/global.test.ts | 3 +- src/sql.test.ts | 7 +- src/utils/sql/docker-compose.yml | 23 ++-- src/utils/sql/setupSql.ts | 82 ++++++++------ 7 files changed, 79 insertions(+), 153 deletions(-) diff --git a/azure-pipelines/templates/test-node-version.yml b/azure-pipelines/templates/test-node-version.yml index 3f31fb1b..416c5e43 100644 --- a/azure-pipelines/templates/test-node-version.yml +++ b/azure-pipelines/templates/test-node-version.yml @@ -17,14 +17,15 @@ steps: sleep 60 docker ps displayName: "Start CosmosDB Emulator" - # - bash: | - # docker compose -f src/utils/sql/docker-compose.yml pull - # docker compose -f src/utils/sql/docker-compose.yml up -d - # displayName: "Start MySQL Service" + - bash: | + docker compose -f src/utils/sql/docker-compose.yml pull + docker compose -f src/utils/sql/docker-compose.yml up -d + env: + AzureWebJobsSQLPassword: $(AzureWebJobsSQLPassword) + displayName: "Start MSSQL Service" - bash: | docker compose -f src/utils/servicebus/docker-compose.yml pull docker compose -f src/utils/servicebus/docker-compose.yml up -d - sleep 30 env: AzureWebJobsSQLPassword: $(AzureWebJobsSQLPassword) displayName: 'Start ServiceBus Emulator' @@ -36,7 +37,6 @@ steps: docker rm -f servicebus-emulator || true docker compose -f src/utils/eventhub/docker-compose.yml pull docker compose -f src/utils/eventhub/docker-compose.yml up -d - sleep 30 displayName: 'Stop ServiceBus Emulator and Start EventHub Emulator' - bash: npm run testAllExceptServiceBus displayName: 'Run remaining tests Node ${{ parameters.nodeVersion }}' @@ -50,4 +50,5 @@ steps: docker rm -f cosmosdb-emulator || true docker compose -f src/utils/eventhub/docker-compose.yml down -v docker compose -f src/utils/servicebus/docker-compose.yml down -v - displayName: 'Stop all emulators' \ No newline at end of file + docker compose -f src/utils/sql/docker-compose.yml down -v + displayName: 'Stop all resources' \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index fa724198..93838b4e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -52,7 +52,6 @@ "mocha-junit-reporter": "^2.0.2", "mocha-multi-reporters": "^1.5.1", "mssql": "^10.0.2", - "mysql2": "^3.14.3", "node-fetch": "2.6.7", "p-retry": "^4.0.0", "prettier": "^2.4.1", @@ -1934,14 +1933,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/aws-ssl-profiles": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/aws-ssl-profiles/-/aws-ssl-profiles-1.1.2.tgz", - "integrity": "sha512-NZKeq9AfyQvEeNlN0zSYAaWrmBffJh3IELMZfRpJVWgrpEbtEpnjvzqBPf+mxoI287JohRDoa+/nsfqqiZmF6g==", - "engines": { - "node": ">= 6.0.0" - } - }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -2441,14 +2432,6 @@ "node": ">=0.4.0" } }, - "node_modules/denque": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", - "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==", - "engines": { - "node": ">=0.10" - } - }, "node_modules/diff": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", @@ -3326,14 +3309,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/generate-function": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz", - "integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==", - "dependencies": { - "is-property": "^1.0.2" - } - }, "node_modules/get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", @@ -3907,11 +3882,6 @@ "node": ">=8" } }, - "node_modules/is-property": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", - "integrity": "sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g==" - }, "node_modules/is-regex": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", @@ -4325,20 +4295,6 @@ "node": ">=10" } }, - "node_modules/lru.min": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/lru.min/-/lru.min-1.1.2.tgz", - "integrity": "sha512-Nv9KddBcQSlQopmBHXSsZVY5xsdlZkdH/Iey0BlcBYggMd4two7cZnKOK9vmy3nY0O5RGH99z1PCeTpPqszUYg==", - "engines": { - "bun": ">=1.0.0", - "deno": ">=1.30.0", - "node": ">=8.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wellwelwel" - } - }, "node_modules/make-error": { "version": "1.3.6", "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", @@ -4588,9 +4544,9 @@ "license": "MIT" }, "node_modules/mssql": { - "version": "10.0.2", - "resolved": "https://registry.npmjs.org/mssql/-/mssql-10.0.2.tgz", - "integrity": "sha512-GrQ6gzv2xA7ndOvONyZ++4RZsNkr8qDiIpvuFn2pR3TPiSk/cKdmvOrDU3jWgon7EPj7CPgmDiMh7Hgtft2xLg==", + "version": "10.0.4", + "resolved": "https://registry.npmjs.org/mssql/-/mssql-10.0.4.tgz", + "integrity": "sha512-MhX5IcJ75/q+dUiOe+1ajpqjEe96ZKqMchYYPUIDU+Btqhwt4gbFeZhcGUZaRCEMV9uF+G8kLvaNSFaEzL9OXQ==", "dependencies": { "@tediousjs/connection-string": "^0.5.0", "commander": "^11.0.0", @@ -4614,44 +4570,6 @@ "node": ">=16" } }, - "node_modules/mysql2": { - "version": "3.14.3", - "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-3.14.3.tgz", - "integrity": "sha512-fD6MLV8XJ1KiNFIF0bS7Msl8eZyhlTDCDl75ajU5SJtpdx9ZPEACulJcqJWr1Y8OYyxsFc4j3+nflpmhxCU5aQ==", - "dependencies": { - "aws-ssl-profiles": "^1.1.1", - "denque": "^2.1.0", - "generate-function": "^2.3.1", - "iconv-lite": "^0.6.3", - "long": "^5.2.1", - "lru.min": "^1.0.0", - "named-placeholders": "^1.1.3", - "seq-queue": "^0.0.5", - "sqlstring": "^2.3.2" - }, - "engines": { - "node": ">= 8.0" - } - }, - "node_modules/named-placeholders": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/named-placeholders/-/named-placeholders-1.1.3.tgz", - "integrity": "sha512-eLoBxg6wE/rZkJPhU/xRX1WTpkFEwDJEN96oxFrTsqBdbT5ec295Q+CoHrL9IT0DipqKhmGcaZmwOt8OON5x1w==", - "dependencies": { - "lru-cache": "^7.14.1" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/named-placeholders/node_modules/lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", - "engines": { - "node": ">=12" - } - }, "node_modules/native-duplexpair": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/native-duplexpair/-/native-duplexpair-1.0.0.tgz", @@ -5394,11 +5312,6 @@ "node": ">=10" } }, - "node_modules/seq-queue": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/seq-queue/-/seq-queue-0.0.5.tgz", - "integrity": "sha512-hr3Wtp/GZIc/6DAGPDcV4/9WoZhjrkXsi5B/07QgX8tsdc6ilr7BFM6PM6rbdAX1kFSDYeZGLipIZZKyQP0O5Q==" - }, "node_modules/serialize-javascript": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", @@ -5538,14 +5451,6 @@ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" }, - "node_modules/sqlstring": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.3.tgz", - "integrity": "sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg==", - "engines": { - "node": ">= 0.6" - } - }, "node_modules/stoppable": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/stoppable/-/stoppable-1.1.0.tgz", diff --git a/package.json b/package.json index 6a4f43ef..35f54926 100644 --- a/package.json +++ b/package.json @@ -81,7 +81,6 @@ "mocha-junit-reporter": "^2.0.2", "mocha-multi-reporters": "^1.5.1", "mssql": "^10.0.2", - "mysql2": "^3.14.3", "node-fetch": "2.6.7", "p-retry": "^4.0.0", "prettier": "^2.4.1", diff --git a/src/global.test.ts b/src/global.test.ts index d679fab1..ac00f64c 100644 --- a/src/global.test.ts +++ b/src/global.test.ts @@ -18,6 +18,7 @@ import { import { setupCosmosDB } from './utils/cosmosdb/setupCosmosDB'; import { delay } from './utils/delay'; import findProcess = require('find-process'); +import { runSqlSetupQueries } from './utils/sql/setupSql'; let perTestFuncOutput = ''; let fullFuncOutput = ''; @@ -44,7 +45,7 @@ before(async function (this: Mocha.Context): Promise { await setupCosmosDB(); - // await runSqlSetupQueries(); + await runSqlSetupQueries(); isOldConfig = getOldConfigArg(); const appPath = isOldConfig diff --git a/src/sql.test.ts b/src/sql.test.ts index 05c3a40d..2f7bc488 100644 --- a/src/sql.test.ts +++ b/src/sql.test.ts @@ -7,8 +7,9 @@ // import { v4 as uuid } from 'uuid'; // import { getFuncUrl } from './constants'; // import { isOldConfig, waitForOutput } from './global.test'; +// import { sqlConnectionString } from './resources/connectionStrings'; +// import { createPoolConnnection, sqlTriggerTable } from './resources/sql'; // import { getRandomTestData } from './utils/getRandomTestData'; -// import { createPoolConnnection } from './utils/sql/setupSql'; // describe('sql', () => { // let poolConnection: ConnectionPool | undefined; @@ -17,7 +18,7 @@ // this.skip(); // } -// poolConnection = await createPoolConnnection(); +// poolConnection = await createPoolConnnection(sqlConnectionString); // }); // after(async () => { @@ -74,4 +75,4 @@ // expect(result).to.deep.equal(items); // await waitForOutput(`httpTriggerSqlInput was triggered`); // }); -// }); +// }); \ No newline at end of file diff --git a/src/utils/sql/docker-compose.yml b/src/utils/sql/docker-compose.yml index a4e8754a..9c31144d 100644 --- a/src/utils/sql/docker-compose.yml +++ b/src/utils/sql/docker-compose.yml @@ -1,17 +1,16 @@ -name: mysql-database +name: mssql-database services: - mysql: - container_name: "mysql" - image: "mysql:8.0" - ports: - - "3307:3306" + sqlserver: + image: mcr.microsoft.com/mssql/server:2025-latest + container_name: sqlserver environment: - MYSQL_ROOT_PASSWORD: password - MYSQL_DATABASE: testdb - MYSQL_USER: user - MYSQL_PASSWORD: password + MSSQL_SA_PASSWORD: $(AzureWebJobsSQLPassword) + ACCEPT_EULA: "Y" + ports: + - "1433:1433" networks: - - mysql-network + - sqlnetwork + networks: - mysql-network: + sqlnetwork: driver: bridge \ No newline at end of file diff --git a/src/utils/sql/setupSql.ts b/src/utils/sql/setupSql.ts index be1ddeee..dd839be0 100644 --- a/src/utils/sql/setupSql.ts +++ b/src/utils/sql/setupSql.ts @@ -1,7 +1,8 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT License. -import mysql from 'mysql2/promise'; +import * as sql from 'mssql'; +import retry from 'p-retry'; /** * Various helpful sql docs: @@ -20,39 +21,58 @@ export const sqlSecretName = 'e2eSqlSecret'; * create tables and enable change tracking for trigger */ export async function runSqlSetupQueries() { - const poolConnection = await createPoolConnnection(); + const connectionString = await getSqlConnectionString(); + const poolConnection = await createPoolConnnection(connectionString); try { - await poolConnection.query(`CREATE DATABASE IF NOT EXISTS \`${dbName}\`;`); - await poolConnection.changeUser({ database: dbName }); - - // for (const table of [sqlTriggerTable, sqlNonTriggerTable]) { - // await poolConnection.query(` - // CREATE TABLE IF NOT EXISTS \`${table}_changes\` ( - // id CHAR(36), - // action ENUM('INSERT', 'UPDATE', 'DELETE'), - // changed_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP - // ); - // `); - - // await poolConnection.query(` - // CREATE TRIGGER IF NOT EXISTS ${table}_after_insert - // AFTER INSERT ON \`${table}\` - // FOR EACH ROW - // INSERT INTO \`${table}_changes\` (id, action) VALUES (NEW.id, 'INSERT'); - // `); - // } + await poolConnection + .request() + .query(`ALTER DATABASE ${dbName} SET CHANGE_TRACKING = ON (CHANGE_RETENTION = 2 DAYS, AUTO_CLEANUP = ON);`); + + for (const table of [sqlTriggerTable, sqlNonTriggerTable]) { + await poolConnection + .request() + .query( + `CREATE TABLE dbo.${table} ([id] UNIQUEIDENTIFIER PRIMARY KEY, [testData] NVARCHAR(200) NOT NULL);` + ); + await poolConnection.request().query(`ALTER TABLE dbo.${table} ENABLE CHANGE_TRACKING;`); + } } finally { - await poolConnection.end(); + await poolConnection.close(); } } -export async function createPoolConnnection(): Promise { - return mysql.createConnection({ - host: 'localhost', - user: 'user', - password: 'password', - database: 'testdb', - port: 3307, - }); -} \ No newline at end of file +export async function createPoolConnnection(connectionString: string): Promise { + const retries = 5; + return retry( + async (currentAttempt: number) => { + if (currentAttempt > 1) { + console.log( + `${new Date().toISOString()}: Retrying sql connect. Attempt ${currentAttempt}/${retries + 1}` + ); + } + return sql.connect(connectionString); + }, + { + retries: retries, + minTimeout: 5 * 1000, + onFailedAttempt: (error) => { + if (!/ip address/i.test(error?.message || '')) { + throw error; // abort for an unrecognized error + } else if (error.retriesLeft > 0) { + console.log(`Warning: Failed to sql connect with error "${error.message}"`); + } + }, + } + ); +} + +export async function getSqlConnectionString(): Promise { + const server = 'localhost'; // or 'sqlserver' if running in another container + const port = 1433; + const user = 'sa'; + const password = process.env.AzureWebJobsSQLPassword || 'yourStrong(!)Password'; // use your actual password + const database = dbName; + + return `Server=${server},${port};Database=${database};User Id=${user};Password=${password};Encrypt=false;TrustServerCertificate=true;`; +} From 7825fbb6dcd9c827c04516999616a04ad3670d03 Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Fri, 1 Aug 2025 16:17:32 -0500 Subject: [PATCH 060/142] fix --- src/utils/sql/setupSql.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/sql/setupSql.ts b/src/utils/sql/setupSql.ts index dd839be0..aa48fa8d 100644 --- a/src/utils/sql/setupSql.ts +++ b/src/utils/sql/setupSql.ts @@ -71,7 +71,7 @@ export async function getSqlConnectionString(): Promise { const server = 'localhost'; // or 'sqlserver' if running in another container const port = 1433; const user = 'sa'; - const password = process.env.AzureWebJobsSQLPassword || 'yourStrong(!)Password'; // use your actual password + const password = process.env.AzureWebJobsSQLPassword || 'thispassworddoesntmatter457!'; // use your actual password const database = dbName; return `Server=${server},${port};Database=${database};User Id=${user};Password=${password};Encrypt=false;TrustServerCertificate=true;`; From 2cc749b817035ab81173daacde142ac0089249d6 Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Fri, 1 Aug 2025 16:35:12 -0500 Subject: [PATCH 061/142] fix --- src/utils/sql/setupSql.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/sql/setupSql.ts b/src/utils/sql/setupSql.ts index aa48fa8d..08083c3f 100644 --- a/src/utils/sql/setupSql.ts +++ b/src/utils/sql/setupSql.ts @@ -71,7 +71,7 @@ export async function getSqlConnectionString(): Promise { const server = 'localhost'; // or 'sqlserver' if running in another container const port = 1433; const user = 'sa'; - const password = process.env.AzureWebJobsSQLPassword || 'thispassworddoesntmatter457!'; // use your actual password + const password = 'thisPasswordDoesntMatter@1475'; // use your actual password const database = dbName; return `Server=${server},${port};Database=${database};User Id=${user};Password=${password};Encrypt=false;TrustServerCertificate=true;`; From d85cf19e8cd7ca595893effb6bbe5366c77a9fdb Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Fri, 1 Aug 2025 16:37:06 -0500 Subject: [PATCH 062/142] fix --- azure-pipelines/templates/test-node-version.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/azure-pipelines/templates/test-node-version.yml b/azure-pipelines/templates/test-node-version.yml index 416c5e43..a02b9986 100644 --- a/azure-pipelines/templates/test-node-version.yml +++ b/azure-pipelines/templates/test-node-version.yml @@ -32,6 +32,11 @@ steps: - bash: npm run testServiceBus displayName: 'Run ServiceBus tests Node ${{ parameters.nodeVersion }}' continueOnError: true + - bash: | + docker logs sqlserver + env: + AzureWebJobsSQLPassword: $(AzureWebJobsSQLPassword) + displayName: 'Start ServiceBus Emulator' - bash: | docker stop servicebus-emulator || true docker rm -f servicebus-emulator || true From ff48ddfe00810bc218949dc7d9cfe881cf159f00 Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Fri, 1 Aug 2025 16:56:16 -0500 Subject: [PATCH 063/142] fix --- .../templates/test-node-version.yml | 4 +- src/utils/sql/setupSql.ts | 80 +++++++++++-------- 2 files changed, 47 insertions(+), 37 deletions(-) diff --git a/azure-pipelines/templates/test-node-version.yml b/azure-pipelines/templates/test-node-version.yml index a02b9986..55bff178 100644 --- a/azure-pipelines/templates/test-node-version.yml +++ b/azure-pipelines/templates/test-node-version.yml @@ -34,9 +34,7 @@ steps: continueOnError: true - bash: | docker logs sqlserver - env: - AzureWebJobsSQLPassword: $(AzureWebJobsSQLPassword) - displayName: 'Start ServiceBus Emulator' + displayName: 'SQL server logs' - bash: | docker stop servicebus-emulator || true docker rm -f servicebus-emulator || true diff --git a/src/utils/sql/setupSql.ts b/src/utils/sql/setupSql.ts index 08083c3f..be43c8da 100644 --- a/src/utils/sql/setupSql.ts +++ b/src/utils/sql/setupSql.ts @@ -21,8 +21,20 @@ export const sqlSecretName = 'e2eSqlSecret'; * create tables and enable change tracking for trigger */ export async function runSqlSetupQueries() { - const connectionString = await getSqlConnectionString(); - const poolConnection = await createPoolConnnection(connectionString); + // const connectionString = await getSqlConnectionString(); + const config: sql.config = { + user: 'sa', + password: 'placeholderForContainer@1475', + server: 'localhost', // or 'sqlserver' if running from another container + database: dbName, // or create your own + port: 1433, + options: { + encrypt: false, // set to true if using Azure or SSL + trustServerCertificate: true, + } + }; + const poolConnection = await sql.connect(config) + // const poolConnection = await createPoolConnnection(); try { await poolConnection @@ -42,37 +54,37 @@ export async function runSqlSetupQueries() { } } -export async function createPoolConnnection(connectionString: string): Promise { - const retries = 5; - return retry( - async (currentAttempt: number) => { - if (currentAttempt > 1) { - console.log( - `${new Date().toISOString()}: Retrying sql connect. Attempt ${currentAttempt}/${retries + 1}` - ); - } - return sql.connect(connectionString); - }, - { - retries: retries, - minTimeout: 5 * 1000, - onFailedAttempt: (error) => { - if (!/ip address/i.test(error?.message || '')) { - throw error; // abort for an unrecognized error - } else if (error.retriesLeft > 0) { - console.log(`Warning: Failed to sql connect with error "${error.message}"`); - } - }, - } - ); -} +// export async function createPoolConnnection(connectionString: string): Promise { +// const retries = 5; +// return retry( +// async (currentAttempt: number) => { +// if (currentAttempt > 1) { +// console.log( +// `${new Date().toISOString()}: Retrying sql connect. Attempt ${currentAttempt}/${retries + 1}` +// ); +// } +// return sql.connect(connectionString); +// }, +// { +// retries: retries, +// minTimeout: 5 * 1000, +// onFailedAttempt: (error) => { +// if (!/ip address/i.test(error?.message || '')) { +// throw error; // abort for an unrecognized error +// } else if (error.retriesLeft > 0) { +// console.log(`Warning: Failed to sql connect with error "${error.message}"`); +// } +// }, +// } +// ); +// } -export async function getSqlConnectionString(): Promise { - const server = 'localhost'; // or 'sqlserver' if running in another container - const port = 1433; - const user = 'sa'; - const password = 'thisPasswordDoesntMatter@1475'; // use your actual password - const database = dbName; +// export async function getSqlConnectionString(): Promise { +// const server = 'localhost'; // or 'sqlserver' if running in another container +// const port = 1433; +// const user = 'sa'; +// const password = 'thisPasswordDoesntMatter@1475'; +// const database = dbName; - return `Server=${server},${port};Database=${database};User Id=${user};Password=${password};Encrypt=false;TrustServerCertificate=true;`; -} +// return `Server=${server},${port};Database=${database};User Id=${user};Password=${password};Encrypt=false;TrustServerCertificate=true;`; +// } From 56a12a97add521b49e1a7dff20c574151dfbace1 Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Fri, 1 Aug 2025 17:09:04 -0500 Subject: [PATCH 064/142] fix --- src/utils/sql/setupSql.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/sql/setupSql.ts b/src/utils/sql/setupSql.ts index be43c8da..a76dd5b9 100644 --- a/src/utils/sql/setupSql.ts +++ b/src/utils/sql/setupSql.ts @@ -2,7 +2,7 @@ // Licensed under the MIT License. import * as sql from 'mssql'; -import retry from 'p-retry'; +// import retry from 'p-retry'; /** * Various helpful sql docs: From 909a68e81faf0b55e345d1a8c62d615488680b16 Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Fri, 1 Aug 2025 17:21:46 -0500 Subject: [PATCH 065/142] fix --- azure-pipelines/templates/test-node-version.yml | 3 ++- src/utils/sql/docker-compose.yml | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/azure-pipelines/templates/test-node-version.yml b/azure-pipelines/templates/test-node-version.yml index 55bff178..7007e3a6 100644 --- a/azure-pipelines/templates/test-node-version.yml +++ b/azure-pipelines/templates/test-node-version.yml @@ -21,7 +21,8 @@ steps: docker compose -f src/utils/sql/docker-compose.yml pull docker compose -f src/utils/sql/docker-compose.yml up -d env: - AzureWebJobsSQLPassword: $(AzureWebJobsSQLPassword) + MSSQL_SA_PASSWORD: "placeholderForContainer@1475" + SA_PASSWORD: "placeholderForContainer@1475" displayName: "Start MSSQL Service" - bash: | docker compose -f src/utils/servicebus/docker-compose.yml pull diff --git a/src/utils/sql/docker-compose.yml b/src/utils/sql/docker-compose.yml index 9c31144d..58f6440c 100644 --- a/src/utils/sql/docker-compose.yml +++ b/src/utils/sql/docker-compose.yml @@ -4,7 +4,8 @@ services: image: mcr.microsoft.com/mssql/server:2025-latest container_name: sqlserver environment: - MSSQL_SA_PASSWORD: $(AzureWebJobsSQLPassword) + MSSQL_SA_PASSWORD: "placeholderForContainer@1475" + SA_PASSWORD: "placeholderForContainer@1475" ACCEPT_EULA: "Y" ports: - "1433:1433" From 09889efe7009f7515648ff12ab6876e30c6c5450 Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Mon, 4 Aug 2025 00:33:01 -0500 Subject: [PATCH 066/142] fix --- azure-pipelines/templates/test-node-version.yml | 4 ++-- src/utils/sql/setupSql.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/azure-pipelines/templates/test-node-version.yml b/azure-pipelines/templates/test-node-version.yml index 7007e3a6..561d3af5 100644 --- a/azure-pipelines/templates/test-node-version.yml +++ b/azure-pipelines/templates/test-node-version.yml @@ -21,8 +21,8 @@ steps: docker compose -f src/utils/sql/docker-compose.yml pull docker compose -f src/utils/sql/docker-compose.yml up -d env: - MSSQL_SA_PASSWORD: "placeholderForContainer@1475" - SA_PASSWORD: "placeholderForContainer@1475" + MSSQL_SA_PASSWORD: "placeholderForContainer1475" + SA_PASSWORD: "placeholderForContainer1475" displayName: "Start MSSQL Service" - bash: | docker compose -f src/utils/servicebus/docker-compose.yml pull diff --git a/src/utils/sql/setupSql.ts b/src/utils/sql/setupSql.ts index a76dd5b9..6bf70955 100644 --- a/src/utils/sql/setupSql.ts +++ b/src/utils/sql/setupSql.ts @@ -24,7 +24,7 @@ export async function runSqlSetupQueries() { // const connectionString = await getSqlConnectionString(); const config: sql.config = { user: 'sa', - password: 'placeholderForContainer@1475', + password: 'placeholderForContainer1475', server: 'localhost', // or 'sqlserver' if running from another container database: dbName, // or create your own port: 1433, From 753677d50f122e48ed9914954f4c4c63e3fd7d81 Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Mon, 4 Aug 2025 00:38:41 -0500 Subject: [PATCH 067/142] fix --- src/utils/sql/docker-compose.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/utils/sql/docker-compose.yml b/src/utils/sql/docker-compose.yml index 58f6440c..c082b47f 100644 --- a/src/utils/sql/docker-compose.yml +++ b/src/utils/sql/docker-compose.yml @@ -4,8 +4,8 @@ services: image: mcr.microsoft.com/mssql/server:2025-latest container_name: sqlserver environment: - MSSQL_SA_PASSWORD: "placeholderForContainer@1475" - SA_PASSWORD: "placeholderForContainer@1475" + MSSQL_SA_PASSWORD: "placeholderForContainer1475" + SA_PASSWORD: "placeholderForContainer1475" ACCEPT_EULA: "Y" ports: - "1433:1433" From 80dd8a8dd8851925fac4b36c4a9f6821254f97de Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Mon, 4 Aug 2025 01:15:51 -0500 Subject: [PATCH 068/142] fix --- .../templates/test-node-version.yml | 20 ++++++------ src/utils/servicebus/docker-compose.yml | 4 +-- src/utils/sql/docker-compose.yml | 32 +++++++++---------- 3 files changed, 28 insertions(+), 28 deletions(-) diff --git a/azure-pipelines/templates/test-node-version.yml b/azure-pipelines/templates/test-node-version.yml index 561d3af5..d6e0a1dd 100644 --- a/azure-pipelines/templates/test-node-version.yml +++ b/azure-pipelines/templates/test-node-version.yml @@ -17,25 +17,25 @@ steps: sleep 60 docker ps displayName: "Start CosmosDB Emulator" - - bash: | - docker compose -f src/utils/sql/docker-compose.yml pull - docker compose -f src/utils/sql/docker-compose.yml up -d - env: - MSSQL_SA_PASSWORD: "placeholderForContainer1475" - SA_PASSWORD: "placeholderForContainer1475" - displayName: "Start MSSQL Service" + # - bash: | + # docker compose -f src/utils/sql/docker-compose.yml pull + # docker compose -f src/utils/sql/docker-compose.yml up -d + # env: + # MSSQL_SA_PASSWORD: "placeholderForContainer1475" + # SA_PASSWORD: "placeholderForContainer1475" + # displayName: "Start MSSQL Service" - bash: | docker compose -f src/utils/servicebus/docker-compose.yml pull docker compose -f src/utils/servicebus/docker-compose.yml up -d env: - AzureWebJobsSQLPassword: $(AzureWebJobsSQLPassword) + AzureWebJobsSQLPassword: ${AzureWebJobsSQLPassword} displayName: 'Start ServiceBus Emulator' - bash: npm run testServiceBus displayName: 'Run ServiceBus tests Node ${{ parameters.nodeVersion }}' continueOnError: true - bash: | - docker logs sqlserver - displayName: 'SQL server logs' + docker logs sqledge + displayName: 'SQL edge logs' - bash: | docker stop servicebus-emulator || true docker rm -f servicebus-emulator || true diff --git a/src/utils/servicebus/docker-compose.yml b/src/utils/servicebus/docker-compose.yml index 214e4e32..b1a2c58e 100644 --- a/src/utils/servicebus/docker-compose.yml +++ b/src/utils/servicebus/docker-compose.yml @@ -9,7 +9,7 @@ services: - "5672:5672" environment: SQL_SERVER: sqledge - MSSQL_SA_PASSWORD: $(AzureWebJobsSQLPassword) + MSSQL_SA_PASSWORD: ${AzureWebJobsSQLPassword} ACCEPT_EULA: Y depends_on: - sqledge @@ -26,7 +26,7 @@ services: - "sqledge" environment: ACCEPT_EULA: Y - MSSQL_SA_PASSWORD: $(AzureWebJobsSQLPassword) + MSSQL_SA_PASSWORD: ${AzureWebJobsSQLPassword} # Service for the Azurite Storage Emulator azurite: container_name: "azurite" diff --git a/src/utils/sql/docker-compose.yml b/src/utils/sql/docker-compose.yml index c082b47f..86c72f94 100644 --- a/src/utils/sql/docker-compose.yml +++ b/src/utils/sql/docker-compose.yml @@ -1,17 +1,17 @@ -name: mssql-database -services: - sqlserver: - image: mcr.microsoft.com/mssql/server:2025-latest - container_name: sqlserver - environment: - MSSQL_SA_PASSWORD: "placeholderForContainer1475" - SA_PASSWORD: "placeholderForContainer1475" - ACCEPT_EULA: "Y" - ports: - - "1433:1433" - networks: - - sqlnetwork +# name: mssql-database +# services: +# sqlserver: +# image: mcr.microsoft.com/mssql/server:2025-latest +# container_name: sqlserver +# environment: +# MSSQL_SA_PASSWORD: "placeholderForContainer1475" +# SA_PASSWORD: "placeholderForContainer1475" +# ACCEPT_EULA: "Y" +# ports: +# - "1433:1433" +# networks: +# - sqlnetwork -networks: - sqlnetwork: - driver: bridge \ No newline at end of file +# networks: +# sqlnetwork: +# driver: bridge \ No newline at end of file From 7caaf2d6d86a8cf42e9c411e0180ac0a9ee8551f Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Mon, 4 Aug 2025 01:30:22 -0500 Subject: [PATCH 069/142] fix --- src/utils/servicebus/docker-compose.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/utils/servicebus/docker-compose.yml b/src/utils/servicebus/docker-compose.yml index b1a2c58e..a1160710 100644 --- a/src/utils/servicebus/docker-compose.yml +++ b/src/utils/servicebus/docker-compose.yml @@ -20,6 +20,9 @@ services: sqledge: container_name: "sqledge" image: "mcr.microsoft.com/azure-sql-edge:latest" + ports: + - "1431:1431" + - "1433:1433" networks: sb-emulator: aliases: From 76b7eb21cdc7310ce2229d37230e12d26343705f Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Mon, 4 Aug 2025 02:05:06 -0500 Subject: [PATCH 070/142] fix --- .../templates/test-node-version.yml | 17 ++-- package-lock.json | 95 +++++++++++++++++++ package.json | 1 + src/utils/connectionStrings.ts | 2 +- src/utils/sql/docker-compose.yml | 34 +++---- src/utils/sql/setupSql.ts | 62 ++++++------ 6 files changed, 156 insertions(+), 55 deletions(-) diff --git a/azure-pipelines/templates/test-node-version.yml b/azure-pipelines/templates/test-node-version.yml index d6e0a1dd..4b3744f0 100644 --- a/azure-pipelines/templates/test-node-version.yml +++ b/azure-pipelines/templates/test-node-version.yml @@ -17,13 +17,12 @@ steps: sleep 60 docker ps displayName: "Start CosmosDB Emulator" - # - bash: | - # docker compose -f src/utils/sql/docker-compose.yml pull - # docker compose -f src/utils/sql/docker-compose.yml up -d - # env: - # MSSQL_SA_PASSWORD: "placeholderForContainer1475" - # SA_PASSWORD: "placeholderForContainer1475" - # displayName: "Start MSSQL Service" + - bash: | + docker compose -f src/utils/sql/docker-compose.yml pull + docker compose -f src/utils/sql/docker-compose.yml up -d + env: + MySqlConnectionString: "Server=localhost;UserID =root;Password=password;Database=testdb;Port=3307" + displayName: "Start SQL Service" - bash: | docker compose -f src/utils/servicebus/docker-compose.yml pull docker compose -f src/utils/servicebus/docker-compose.yml up -d @@ -34,8 +33,8 @@ steps: displayName: 'Run ServiceBus tests Node ${{ parameters.nodeVersion }}' continueOnError: true - bash: | - docker logs sqledge - displayName: 'SQL edge logs' + docker logs mysql + displayName: 'SQL logs' - bash: | docker stop servicebus-emulator || true docker rm -f servicebus-emulator || true diff --git a/package-lock.json b/package-lock.json index 93838b4e..99527545 100644 --- a/package-lock.json +++ b/package-lock.json @@ -52,6 +52,7 @@ "mocha-junit-reporter": "^2.0.2", "mocha-multi-reporters": "^1.5.1", "mssql": "^10.0.2", + "mysql2": "^3.14.3", "node-fetch": "2.6.7", "p-retry": "^4.0.0", "prettier": "^2.4.1", @@ -1933,6 +1934,14 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/aws-ssl-profiles": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/aws-ssl-profiles/-/aws-ssl-profiles-1.1.2.tgz", + "integrity": "sha512-NZKeq9AfyQvEeNlN0zSYAaWrmBffJh3IELMZfRpJVWgrpEbtEpnjvzqBPf+mxoI287JohRDoa+/nsfqqiZmF6g==", + "engines": { + "node": ">= 6.0.0" + } + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -2432,6 +2441,14 @@ "node": ">=0.4.0" } }, + "node_modules/denque": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", + "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==", + "engines": { + "node": ">=0.10" + } + }, "node_modules/diff": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", @@ -3309,6 +3326,14 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/generate-function": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz", + "integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==", + "dependencies": { + "is-property": "^1.0.2" + } + }, "node_modules/get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", @@ -3882,6 +3907,11 @@ "node": ">=8" } }, + "node_modules/is-property": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", + "integrity": "sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g==" + }, "node_modules/is-regex": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", @@ -4295,6 +4325,20 @@ "node": ">=10" } }, + "node_modules/lru.min": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/lru.min/-/lru.min-1.1.2.tgz", + "integrity": "sha512-Nv9KddBcQSlQopmBHXSsZVY5xsdlZkdH/Iey0BlcBYggMd4two7cZnKOK9vmy3nY0O5RGH99z1PCeTpPqszUYg==", + "engines": { + "bun": ">=1.0.0", + "deno": ">=1.30.0", + "node": ">=8.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wellwelwel" + } + }, "node_modules/make-error": { "version": "1.3.6", "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", @@ -4570,6 +4614,44 @@ "node": ">=16" } }, + "node_modules/mysql2": { + "version": "3.14.3", + "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-3.14.3.tgz", + "integrity": "sha512-fD6MLV8XJ1KiNFIF0bS7Msl8eZyhlTDCDl75ajU5SJtpdx9ZPEACulJcqJWr1Y8OYyxsFc4j3+nflpmhxCU5aQ==", + "dependencies": { + "aws-ssl-profiles": "^1.1.1", + "denque": "^2.1.0", + "generate-function": "^2.3.1", + "iconv-lite": "^0.6.3", + "long": "^5.2.1", + "lru.min": "^1.0.0", + "named-placeholders": "^1.1.3", + "seq-queue": "^0.0.5", + "sqlstring": "^2.3.2" + }, + "engines": { + "node": ">= 8.0" + } + }, + "node_modules/named-placeholders": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/named-placeholders/-/named-placeholders-1.1.3.tgz", + "integrity": "sha512-eLoBxg6wE/rZkJPhU/xRX1WTpkFEwDJEN96oxFrTsqBdbT5ec295Q+CoHrL9IT0DipqKhmGcaZmwOt8OON5x1w==", + "dependencies": { + "lru-cache": "^7.14.1" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/named-placeholders/node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "engines": { + "node": ">=12" + } + }, "node_modules/native-duplexpair": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/native-duplexpair/-/native-duplexpair-1.0.0.tgz", @@ -5312,6 +5394,11 @@ "node": ">=10" } }, + "node_modules/seq-queue": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/seq-queue/-/seq-queue-0.0.5.tgz", + "integrity": "sha512-hr3Wtp/GZIc/6DAGPDcV4/9WoZhjrkXsi5B/07QgX8tsdc6ilr7BFM6PM6rbdAX1kFSDYeZGLipIZZKyQP0O5Q==" + }, "node_modules/serialize-javascript": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", @@ -5451,6 +5538,14 @@ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" }, + "node_modules/sqlstring": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.3.tgz", + "integrity": "sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg==", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/stoppable": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/stoppable/-/stoppable-1.1.0.tgz", diff --git a/package.json b/package.json index 35f54926..6a4f43ef 100644 --- a/package.json +++ b/package.json @@ -81,6 +81,7 @@ "mocha-junit-reporter": "^2.0.2", "mocha-multi-reporters": "^1.5.1", "mssql": "^10.0.2", + "mysql2": "^3.14.3", "node-fetch": "2.6.7", "p-retry": "^4.0.0", "prettier": "^2.4.1", diff --git a/src/utils/connectionStrings.ts b/src/utils/connectionStrings.ts index 814bba18..83d75de9 100644 --- a/src/utils/connectionStrings.ts +++ b/src/utils/connectionStrings.ts @@ -11,5 +11,5 @@ export async function initializeConnectionStrings(): Promise { storageConnectionString = "UseDevelopmentStorage=true"; cosmosDBConnectionString = "AccountEndpoint=http://localhost:8081/;AccountKey=C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw=="; serviceBusConnectionString = eventHubConnectionString = "Endpoint=sb://localhost;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=SAS_KEY_VALUE;UseDevelopmentEmulator=true;"; - sqlConnectionString = "Server=localhost;UserID=root;Password=password;Database=e2eTestDB;Port=3307" + sqlConnectionString = "Server=localhost;UserID =root;Password=password;Database=testdb;Port=3307" } diff --git a/src/utils/sql/docker-compose.yml b/src/utils/sql/docker-compose.yml index 86c72f94..a4e8754a 100644 --- a/src/utils/sql/docker-compose.yml +++ b/src/utils/sql/docker-compose.yml @@ -1,17 +1,17 @@ -# name: mssql-database -# services: -# sqlserver: -# image: mcr.microsoft.com/mssql/server:2025-latest -# container_name: sqlserver -# environment: -# MSSQL_SA_PASSWORD: "placeholderForContainer1475" -# SA_PASSWORD: "placeholderForContainer1475" -# ACCEPT_EULA: "Y" -# ports: -# - "1433:1433" -# networks: -# - sqlnetwork - -# networks: -# sqlnetwork: -# driver: bridge \ No newline at end of file +name: mysql-database +services: + mysql: + container_name: "mysql" + image: "mysql:8.0" + ports: + - "3307:3306" + environment: + MYSQL_ROOT_PASSWORD: password + MYSQL_DATABASE: testdb + MYSQL_USER: user + MYSQL_PASSWORD: password + networks: + - mysql-network +networks: + mysql-network: + driver: bridge \ No newline at end of file diff --git a/src/utils/sql/setupSql.ts b/src/utils/sql/setupSql.ts index 6bf70955..fe4d10ed 100644 --- a/src/utils/sql/setupSql.ts +++ b/src/utils/sql/setupSql.ts @@ -1,7 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT License. -import * as sql from 'mssql'; +import mysql from 'mysql2/promise'; // import retry from 'p-retry'; /** @@ -22,36 +22,42 @@ export const sqlSecretName = 'e2eSqlSecret'; */ export async function runSqlSetupQueries() { // const connectionString = await getSqlConnectionString(); - const config: sql.config = { - user: 'sa', - password: 'placeholderForContainer1475', - server: 'localhost', // or 'sqlserver' if running from another container - database: dbName, // or create your own - port: 1433, - options: { - encrypt: false, // set to true if using Azure or SSL - trustServerCertificate: true, - } - }; - const poolConnection = await sql.connect(config) + const pool = mysql.createPool({ + host: 'localhost', + port: 3307, + user: 'root', + password: 'password', + database: 'testdb', + }); + + const createTableQuery = ` + CREATE TABLE IF NOT EXISTS person ( + id INT NOT NULL AUTO_INCREMENT, + name VARCHAR(100) NOT NULL, + address VARCHAR(255) NOT NULL, + PRIMARY KEY (id) + ) ENGINE=InnoDB; + `; + await pool.query(createTableQuery) + // const poolConnection = await createPoolConnnection(); - try { - await poolConnection - .request() - .query(`ALTER DATABASE ${dbName} SET CHANGE_TRACKING = ON (CHANGE_RETENTION = 2 DAYS, AUTO_CLEANUP = ON);`); + // try { + // await poolConnection + // .request() + // .query(`ALTER DATABASE ${dbName} SET CHANGE_TRACKING = ON (CHANGE_RETENTION = 2 DAYS, AUTO_CLEANUP = ON);`); - for (const table of [sqlTriggerTable, sqlNonTriggerTable]) { - await poolConnection - .request() - .query( - `CREATE TABLE dbo.${table} ([id] UNIQUEIDENTIFIER PRIMARY KEY, [testData] NVARCHAR(200) NOT NULL);` - ); - await poolConnection.request().query(`ALTER TABLE dbo.${table} ENABLE CHANGE_TRACKING;`); - } - } finally { - await poolConnection.close(); - } + // for (const table of [sqlTriggerTable, sqlNonTriggerTable]) { + // await poolConnection + // .request() + // .query( + // `CREATE TABLE dbo.${table} ([id] UNIQUEIDENTIFIER PRIMARY KEY, [testData] NVARCHAR(200) NOT NULL);` + // ); + // await poolConnection.request().query(`ALTER TABLE dbo.${table} ENABLE CHANGE_TRACKING;`); + // } + // } finally { + // await poolConnection.close(); + // } } // export async function createPoolConnnection(connectionString: string): Promise { From a66e536b875394cc114d8e4bb378c9ee5e05308a Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Mon, 4 Aug 2025 10:34:44 -0500 Subject: [PATCH 071/142] fix --- azure-pipelines/templates/test-node-version.yml | 2 -- src/utils/sql/setupSql.ts | 2 ++ 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/azure-pipelines/templates/test-node-version.yml b/azure-pipelines/templates/test-node-version.yml index 4b3744f0..799e288d 100644 --- a/azure-pipelines/templates/test-node-version.yml +++ b/azure-pipelines/templates/test-node-version.yml @@ -20,8 +20,6 @@ steps: - bash: | docker compose -f src/utils/sql/docker-compose.yml pull docker compose -f src/utils/sql/docker-compose.yml up -d - env: - MySqlConnectionString: "Server=localhost;UserID =root;Password=password;Database=testdb;Port=3307" displayName: "Start SQL Service" - bash: | docker compose -f src/utils/servicebus/docker-compose.yml pull diff --git a/src/utils/sql/setupSql.ts b/src/utils/sql/setupSql.ts index fe4d10ed..c91b4697 100644 --- a/src/utils/sql/setupSql.ts +++ b/src/utils/sql/setupSql.ts @@ -39,6 +39,8 @@ export async function runSqlSetupQueries() { ) ENGINE=InnoDB; `; await pool.query(createTableQuery) + console.log('Table "person" created or already exists.'); + pool.end(); // const poolConnection = await createPoolConnnection(); From 5d3fd8bfd25b89aa2729b1a79d1b211c97faef4a Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Mon, 4 Aug 2025 10:55:33 -0500 Subject: [PATCH 072/142] fix --- src/utils/sql/setupSql.ts | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/src/utils/sql/setupSql.ts b/src/utils/sql/setupSql.ts index c91b4697..5819a07e 100644 --- a/src/utils/sql/setupSql.ts +++ b/src/utils/sql/setupSql.ts @@ -40,7 +40,7 @@ export async function runSqlSetupQueries() { `; await pool.query(createTableQuery) console.log('Table "person" created or already exists.'); - pool.end(); + await pool.end(); // const poolConnection = await createPoolConnnection(); @@ -86,13 +86,3 @@ export async function runSqlSetupQueries() { // } // ); // } - -// export async function getSqlConnectionString(): Promise { -// const server = 'localhost'; // or 'sqlserver' if running in another container -// const port = 1433; -// const user = 'sa'; -// const password = 'thisPasswordDoesntMatter@1475'; -// const database = dbName; - -// return `Server=${server},${port};Database=${database};User Id=${user};Password=${password};Encrypt=false;TrustServerCertificate=true;`; -// } From 9c78ae0760513c09e4df4c15e4057905aaff5f86 Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Mon, 4 Aug 2025 11:23:55 -0500 Subject: [PATCH 073/142] fix --- azure-pipelines/templates/test-node-version.yml | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/azure-pipelines/templates/test-node-version.yml b/azure-pipelines/templates/test-node-version.yml index 799e288d..ea2ae098 100644 --- a/azure-pipelines/templates/test-node-version.yml +++ b/azure-pipelines/templates/test-node-version.yml @@ -17,10 +17,6 @@ steps: sleep 60 docker ps displayName: "Start CosmosDB Emulator" - - bash: | - docker compose -f src/utils/sql/docker-compose.yml pull - docker compose -f src/utils/sql/docker-compose.yml up -d - displayName: "Start SQL Service" - bash: | docker compose -f src/utils/servicebus/docker-compose.yml pull docker compose -f src/utils/servicebus/docker-compose.yml up -d @@ -30,18 +26,23 @@ steps: - bash: npm run testServiceBus displayName: 'Run ServiceBus tests Node ${{ parameters.nodeVersion }}' continueOnError: true - - bash: | - docker logs mysql - displayName: 'SQL logs' - bash: | docker stop servicebus-emulator || true docker rm -f servicebus-emulator || true docker compose -f src/utils/eventhub/docker-compose.yml pull docker compose -f src/utils/eventhub/docker-compose.yml up -d displayName: 'Stop ServiceBus Emulator and Start EventHub Emulator' + - bash: | + docker compose -f src/utils/sql/docker-compose.yml pull + docker compose -f src/utils/sql/docker-compose.yml up -d + sleep 60 + displayName: "Start SQL Service" - bash: npm run testAllExceptServiceBus displayName: 'Run remaining tests Node ${{ parameters.nodeVersion }}' continueOnError: true + - bash: | + docker logs mysql + displayName: 'SQL logs' - bash: npm run testOldConfig displayName: 'Run oldConfig tests Node ${{ parameters.nodeVersion }}' condition: and(succeeded(), eq('${{ parameters.runOldConfig }}', 'true')) From 811252318a4acd3d1727e5ac8de5e62c42060793 Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Mon, 4 Aug 2025 12:03:56 -0500 Subject: [PATCH 074/142] fix --- azure-pipelines/templates/test-node-version.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/azure-pipelines/templates/test-node-version.yml b/azure-pipelines/templates/test-node-version.yml index ea2ae098..a305f00b 100644 --- a/azure-pipelines/templates/test-node-version.yml +++ b/azure-pipelines/templates/test-node-version.yml @@ -17,6 +17,11 @@ steps: sleep 60 docker ps displayName: "Start CosmosDB Emulator" + - bash: | + docker compose -f src/utils/sql/docker-compose.yml pull + docker compose -f src/utils/sql/docker-compose.yml up -d + sleep 60 + displayName: "Start SQL Service" - bash: | docker compose -f src/utils/servicebus/docker-compose.yml pull docker compose -f src/utils/servicebus/docker-compose.yml up -d @@ -32,11 +37,6 @@ steps: docker compose -f src/utils/eventhub/docker-compose.yml pull docker compose -f src/utils/eventhub/docker-compose.yml up -d displayName: 'Stop ServiceBus Emulator and Start EventHub Emulator' - - bash: | - docker compose -f src/utils/sql/docker-compose.yml pull - docker compose -f src/utils/sql/docker-compose.yml up -d - sleep 60 - displayName: "Start SQL Service" - bash: npm run testAllExceptServiceBus displayName: 'Run remaining tests Node ${{ parameters.nodeVersion }}' continueOnError: true From e0d9f38c534e8df4e53b665a8293f57fa7bc5c76 Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Mon, 4 Aug 2025 16:02:29 -0500 Subject: [PATCH 075/142] fix --- app/v3/httpTriggerSqlInput/function.json | 6 +- app/v3/httpTriggerSqlInput/index.ts | 20 +-- app/v3/httpTriggerSqlOutput/function.json | 4 +- app/v3/httpTriggerSqlOutput/index.ts | 22 +-- app/v3/sqlTrigger/function.json | 2 +- app/v3/sqlTrigger/index.ts | 48 +++---- app/v4/src/functions/httpTriggerSqlInput.ts | 40 +++--- app/v4/src/functions/httpTriggerSqlOutput.ts | 44 +++--- app/v4/src/functions/sqlTrigger.ts | 56 ++++---- .../templates/test-node-version.yml | 4 +- src/constants.ts | 7 + src/cosmosDB.test.ts | 5 + src/sql.test.ts | 132 +++++++++--------- src/utils/connectionStrings.ts | 2 +- src/utils/sql/setupSql.ts | 46 ++---- 15 files changed, 216 insertions(+), 222 deletions(-) diff --git a/app/v3/httpTriggerSqlInput/function.json b/app/v3/httpTriggerSqlInput/function.json index 088d52f3..090e8074 100644 --- a/app/v3/httpTriggerSqlInput/function.json +++ b/app/v3/httpTriggerSqlInput/function.json @@ -16,10 +16,10 @@ "type": "sql", "name": "inputItem", "direction": "in", - "connectionStringSetting": "e2eTest_sql", - "commandText": "select * from dbo.e2eSqlNonTriggerTable where id = @id", + "connectionStringSetting": "SqlConnection", + "commandText": "SELECT * FROM e2eSqlNonTriggerTable WHERE id = ?", "commandType": "Text", - "parameters": "@id={Query.id}" + "parameters": "?={Query.id}" } ], "scriptFile": "../dist/httpTriggerSqlInput/index.js" diff --git a/app/v3/httpTriggerSqlInput/index.ts b/app/v3/httpTriggerSqlInput/index.ts index 31a1c423..f6c6c113 100644 --- a/app/v3/httpTriggerSqlInput/index.ts +++ b/app/v3/httpTriggerSqlInput/index.ts @@ -1,13 +1,13 @@ -// // Copyright (c) .NET Foundation. All rights reserved. -// // Licensed under the MIT License. +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT License. -// import { AzureFunction, Context, HttpRequest } from '@azure/functions'; +import { AzureFunction, Context, HttpRequest } from '@azure/functions'; -// const httpTriggerSqlInput: AzureFunction = async function (context: Context, _request: HttpRequest): Promise { -// context.log(`httpTriggerSqlInput was triggered`); -// context.res = { -// body: context.bindings.inputItem, -// }; -// }; +const httpTriggerSqlInput: AzureFunction = async function (context: Context, _request: HttpRequest): Promise { + context.log(`httpTriggerSqlInput was triggered`); + context.res = { + body: context.bindings.inputItem, + }; +}; -// export default httpTriggerSqlInput; +export default httpTriggerSqlInput; diff --git a/app/v3/httpTriggerSqlOutput/function.json b/app/v3/httpTriggerSqlOutput/function.json index edc518e4..4d390b83 100644 --- a/app/v3/httpTriggerSqlOutput/function.json +++ b/app/v3/httpTriggerSqlOutput/function.json @@ -16,8 +16,8 @@ "type": "sql", "name": "outputItem", "direction": "out", - "connectionStringSetting": "e2eTest_sql", - "commandText": "dbo.e2eSqlNonTriggerTable" + "connectionStringSetting": "SqlConnection", + "commandText": "e2eSqlNonTriggerTable" } ], "scriptFile": "../dist/httpTriggerSqlOutput/index.js" diff --git a/app/v3/httpTriggerSqlOutput/index.ts b/app/v3/httpTriggerSqlOutput/index.ts index 7b70adf4..8a27d059 100644 --- a/app/v3/httpTriggerSqlOutput/index.ts +++ b/app/v3/httpTriggerSqlOutput/index.ts @@ -1,14 +1,14 @@ -// // Copyright (c) .NET Foundation. All rights reserved. -// // Licensed under the MIT License. +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT License. -// import { AzureFunction, Context, HttpRequest } from '@azure/functions'; +import { AzureFunction, Context, HttpRequest } from '@azure/functions'; -// const httpTriggerSqlOutput: AzureFunction = async function (context: Context, request: HttpRequest): Promise { -// context.log(`httpTriggerSqlOutput was triggered`); -// context.bindings.outputItem = request.body; -// context.res = { -// status: 201, -// }; -// }; +const httpTriggerSqlOutput: AzureFunction = async function (context: Context, request: HttpRequest): Promise { + context.log(`httpTriggerSqlOutput was triggered`); + context.bindings.outputItem = request.body; + context.res = { + status: 201, + }; +}; -// export default httpTriggerSqlOutput; +export default httpTriggerSqlOutput; diff --git a/app/v3/sqlTrigger/function.json b/app/v3/sqlTrigger/function.json index dce04990..b91b1013 100644 --- a/app/v3/sqlTrigger/function.json +++ b/app/v3/sqlTrigger/function.json @@ -5,7 +5,7 @@ "name": "changes", "direction": "in", "tableName": "dbo.e2eSqlTriggerTable", - "connectionStringSetting": "e2eTest_sql" + "connectionStringSetting": "SqlConnection" } ], "scriptFile": "../dist/sqlTrigger/index.js" diff --git a/app/v3/sqlTrigger/index.ts b/app/v3/sqlTrigger/index.ts index ec3112e1..d6aeca95 100644 --- a/app/v3/sqlTrigger/index.ts +++ b/app/v3/sqlTrigger/index.ts @@ -1,27 +1,27 @@ -// // Copyright (c) .NET Foundation. All rights reserved. -// // Licensed under the MIT License. +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT License. -// import { AzureFunction, Context } from '@azure/functions'; +import { AzureFunction, Context } from '@azure/functions'; -// const sqlTrigger: AzureFunction = async function (context: Context, changes: any[]): Promise { -// context.log(`sqlTrigger processed ${changes.length} changes`); -// for (const change of changes) { -// let operation: string; -// switch (change.Operation) { -// case 0: -// operation = 'insert'; -// break; -// case 1: -// operation = 'update'; -// break; -// case 2: -// operation = 'delete'; -// break; -// default: -// throw RangeError(`Unrecognized operation "${change.Operation}"`); -// } -// context.log(`sqlTrigger was triggered by operation "${operation}" for "${JSON.stringify(change.Item)}"`); -// } -// }; +const sqlTrigger: AzureFunction = async function (context: Context, changes: any[]): Promise { + context.log(`sqlTrigger processed ${changes.length} changes`); + for (const change of changes) { + let operation: string; + switch (change.Operation) { + case 0: + operation = 'insert'; + break; + case 1: + operation = 'update'; + break; + case 2: + operation = 'delete'; + break; + default: + throw RangeError(`Unrecognized operation "${change.Operation}"`); + } + context.log(`sqlTrigger was triggered by operation "${operation}" for "${JSON.stringify(change.Item)}"`); + } +}; -// export default sqlTrigger; +export default sqlTrigger; diff --git a/app/v4/src/functions/httpTriggerSqlInput.ts b/app/v4/src/functions/httpTriggerSqlInput.ts index e9b072f7..0a98c94a 100644 --- a/app/v4/src/functions/httpTriggerSqlInput.ts +++ b/app/v4/src/functions/httpTriggerSqlInput.ts @@ -1,24 +1,24 @@ -// // Copyright (c) .NET Foundation. All rights reserved. -// // Licensed under the MIT License. +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT License. -// import { app, HttpRequest, HttpResponseInit, input, InvocationContext } from '@azure/functions'; +import { app, HttpRequest, HttpResponseInit, input, InvocationContext } from '@azure/functions'; -// const sqlInput = input.sql({ -// connectionStringSetting: 'e2eTest_sql', -// commandText: 'select * from dbo.e2eSqlNonTriggerTable where id = @id', -// commandType: 'Text', -// parameters: '@id={Query.id}', -// }); +const sqlInput = input.sql({ + connectionStringSetting: 'SqlConnection', + commandText: 'select * from dbo.e2eSqlNonTriggerTable where id = @id', + commandType: 'Text', + parameters: '@id={Query.id}', +}); -// export async function httpTriggerSqlInput(request: HttpRequest, context: InvocationContext): Promise { -// context.log(`httpTriggerSqlInput was triggered`); -// const items = context.extraInputs.get(sqlInput); -// return { jsonBody: items }; -// } +export async function httpTriggerSqlInput(request: HttpRequest, context: InvocationContext): Promise { + context.log(`httpTriggerSqlInput was triggered`); + const items = context.extraInputs.get(sqlInput); + return { jsonBody: items }; +} -// app.http('httpTriggerSqlInput', { -// methods: ['GET', 'POST'], -// authLevel: 'anonymous', -// extraInputs: [sqlInput], -// handler: httpTriggerSqlInput, -// }); +app.http('httpTriggerSqlInput', { + methods: ['GET', 'POST'], + authLevel: 'anonymous', + extraInputs: [sqlInput], + handler: httpTriggerSqlInput, +}); diff --git a/app/v4/src/functions/httpTriggerSqlOutput.ts b/app/v4/src/functions/httpTriggerSqlOutput.ts index c1170fe9..1fa61fee 100644 --- a/app/v4/src/functions/httpTriggerSqlOutput.ts +++ b/app/v4/src/functions/httpTriggerSqlOutput.ts @@ -1,26 +1,26 @@ -// // Copyright (c) .NET Foundation. All rights reserved. -// // Licensed under the MIT License. +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT License. -// import { app, HttpRequest, HttpResponseInit, InvocationContext, output } from '@azure/functions'; +import { app, HttpRequest, HttpResponseInit, InvocationContext, output } from '@azure/functions'; -// const sqlOutput = output.sql({ -// connectionStringSetting: 'e2eTest_sql', -// commandText: 'dbo.e2eSqlNonTriggerTable', -// }); +const sqlOutput = output.sql({ + connectionStringSetting: 'SqlConnection', + commandText: 'e2eSqlNonTriggerTable', +}); -// export async function httpTriggerSqlOutput( -// request: HttpRequest, -// context: InvocationContext -// ): Promise { -// context.log(`httpTriggerSqlOutput was triggered`); -// const body = await request.json(); -// context.extraOutputs.set(sqlOutput, body); -// return { status: 201 }; -// } +export async function httpTriggerSqlOutput( + request: HttpRequest, + context: InvocationContext +): Promise { + context.log(`httpTriggerSqlOutput was triggered`); + const body = await request.json(); + context.extraOutputs.set(sqlOutput, body); + return { status: 201 }; +} -// app.http('httpTriggerSqlOutput', { -// methods: ['GET', 'POST'], -// authLevel: 'anonymous', -// extraOutputs: [sqlOutput], -// handler: httpTriggerSqlOutput, -// }); +app.http('httpTriggerSqlOutput', { + methods: ['GET', 'POST'], + authLevel: 'anonymous', + extraOutputs: [sqlOutput], + handler: httpTriggerSqlOutput, +}); diff --git a/app/v4/src/functions/sqlTrigger.ts b/app/v4/src/functions/sqlTrigger.ts index 4cdab5b8..5bf07f02 100644 --- a/app/v4/src/functions/sqlTrigger.ts +++ b/app/v4/src/functions/sqlTrigger.ts @@ -1,31 +1,31 @@ -// // Copyright (c) .NET Foundation. All rights reserved. -// // Licensed under the MIT License. +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT License. -// import { app, InvocationContext, SqlChange, SqlChangeOperation } from '@azure/functions'; +import { app, InvocationContext, SqlChange, SqlChangeOperation } from '@azure/functions'; -// export async function sqlTrigger(changes: SqlChange[], context: InvocationContext): Promise { -// context.log(`sqlTrigger processed ${changes.length} changes`); -// for (const change of changes) { -// let operation: string; -// switch (change.Operation) { -// case SqlChangeOperation.Insert: -// operation = 'insert'; -// break; -// case SqlChangeOperation.Update: -// operation = 'update'; -// break; -// case SqlChangeOperation.Delete: -// operation = 'delete'; -// break; -// default: -// throw RangeError(`Unrecognized operation "${change.Operation}"`); -// } -// context.log(`sqlTrigger was triggered by operation "${operation}" for "${JSON.stringify(change.Item)}"`); -// } -// } +export async function sqlTrigger(changes: SqlChange[], context: InvocationContext): Promise { + context.log(`sqlTrigger processed ${changes.length} changes`); + for (const change of changes) { + let operation: string; + switch (change.Operation) { + case SqlChangeOperation.Insert: + operation = 'insert'; + break; + case SqlChangeOperation.Update: + operation = 'update'; + break; + case SqlChangeOperation.Delete: + operation = 'delete'; + break; + default: + throw RangeError(`Unrecognized operation "${change.Operation}"`); + } + context.log(`sqlTrigger was triggered by operation "${operation}" for "${JSON.stringify(change.Item)}"`); + } +} -// app.sql('sqlTrigger', { -// tableName: 'dbo.e2eSqlTriggerTable', -// connectionStringSetting: 'e2eTest_sql', -// handler: sqlTrigger, -// }); +app.sql('sqlTrigger', { + tableName: 'e2eSqlTriggerTable', + connectionStringSetting: 'SqlConnection', + handler: sqlTrigger, +}); diff --git a/azure-pipelines/templates/test-node-version.yml b/azure-pipelines/templates/test-node-version.yml index a305f00b..660d90eb 100644 --- a/azure-pipelines/templates/test-node-version.yml +++ b/azure-pipelines/templates/test-node-version.yml @@ -14,13 +14,13 @@ steps: - bash: | docker pull mcr.microsoft.com/cosmosdb/linux/azure-cosmos-emulator:vnext-preview docker run --detach --publish 8081:8081 --publish 1234:1234 --name cosmosdb-emulator mcr.microsoft.com/cosmosdb/linux/azure-cosmos-emulator:vnext-preview - sleep 60 + sleep 30 docker ps displayName: "Start CosmosDB Emulator" - bash: | docker compose -f src/utils/sql/docker-compose.yml pull docker compose -f src/utils/sql/docker-compose.yml up -d - sleep 60 + sleep 30 displayName: "Start SQL Service" - bash: | docker compose -f src/utils/servicebus/docker-compose.yml pull diff --git a/src/constants.ts b/src/constants.ts index b71b2d76..14682503 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -33,6 +33,13 @@ export namespace ServiceBus { export const serviceBusTopicTrigger = 'e2e-test-topic-trigger'; } +export namespace Sql { + export const dbName = 'e2eTestDB'; + export const sqlTriggerTable = 'e2eSqlTriggerTable'; + export const sqlNonTriggerTable = 'e2eSqlNonTriggerTable'; + export const sqlSecretName = 'e2eSqlSecret'; +} + export const defaultTimeout = 3 * 60 * 1000; export const combinedFolder = 'combined'; diff --git a/src/cosmosDB.test.ts b/src/cosmosDB.test.ts index 33572a25..519a5fef 100644 --- a/src/cosmosDB.test.ts +++ b/src/cosmosDB.test.ts @@ -8,8 +8,13 @@ import { getFuncUrl, CosmosDB } from './constants'; import { waitForOutput } from './global.test'; import { cosmosDBConnectionString } from './utils/connectionStrings'; import { getRandomTestData } from './utils/getRandomTestData'; +import { setupCosmosDB } from './utils/setupCosmosDB'; describe('cosmosDB', () => { + before(async () => { + await setupCosmosDB(); + }); + it('trigger, output, input', async () => { const client = new CosmosClient(cosmosDBConnectionString); const container = client.database(CosmosDB.dbName).container(CosmosDB.triggerAndOutputContainerName); diff --git a/src/sql.test.ts b/src/sql.test.ts index 2f7bc488..03d99d93 100644 --- a/src/sql.test.ts +++ b/src/sql.test.ts @@ -1,78 +1,76 @@ -// // Copyright (c) .NET Foundation. All rights reserved. -// // Licensed under the MIT License. +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT License. -// import { expect } from 'chai'; -// import { ConnectionPool } from 'mssql'; -// import { default as fetch } from 'node-fetch'; -// import { v4 as uuid } from 'uuid'; -// import { getFuncUrl } from './constants'; -// import { isOldConfig, waitForOutput } from './global.test'; -// import { sqlConnectionString } from './resources/connectionStrings'; -// import { createPoolConnnection, sqlTriggerTable } from './resources/sql'; -// import { getRandomTestData } from './utils/getRandomTestData'; +import mysql from 'mysql2/promise'; +import { expect } from 'chai'; +import { default as fetch } from 'node-fetch'; +import { v4 as uuid } from 'uuid'; +import { getFuncUrl } from './constants'; +import { isOldConfig, waitForOutput } from './global.test'; +import { getRandomTestData } from './utils/getRandomTestData'; +import { runSqlSetupQueries } from './utils/sql/setupSql'; +import { Sql } from './constants'; -// describe('sql', () => { -// let poolConnection: ConnectionPool | undefined; -// before(async function (this: Mocha.Context) { -// if (isOldConfig) { -// this.skip(); -// } +describe('sql', () => { + let poolConnection: mysql.Pool | undefined; + before(async function (this: Mocha.Context) { + if (isOldConfig) { + this.skip(); + } + + poolConnection = await runSqlSetupQueries(); + }); -// poolConnection = await createPoolConnnection(sqlConnectionString); -// }); + after(async () => { + await poolConnection?.end(); + }); -// after(async () => { -// await poolConnection?.close(); -// }); + type SqlItem = { id: string; testData: string }; -// type SqlItem = { id: string; testData: string }; + it('trigger', async () => { + const id = uuid(); + const testData = getRandomTestData(); -// it('trigger', async () => { -// const id = uuid(); -// const testData = getRandomTestData(); + // trigger by insert + await poolConnection!.query(`INSERT INTO ${Sql.sqlTriggerTable} (id, testData) VALUES (?, ?)`, [id, testData]); + await waitForOutput(`sqlTrigger processed 1 changes`); + await waitForOutput(`sqlTrigger was triggered by operation "insert" for "${JSON.stringify({ id, testData })}"`); -// // trigger by insert -// await poolConnection!.request().query(`INSERT INTO ${sqlTriggerTable} VALUES ('${id}', '${testData}');`); -// await waitForOutput(`sqlTrigger processed 1 changes`); -// await waitForOutput(`sqlTrigger was triggered by operation "insert" for "${JSON.stringify({ id, testData })}"`); + // trigger by update + await poolConnection!.query(`UPDATE ${Sql.sqlTriggerTable} SET testData=? WHERE id=?`,[`${testData}-updated`, id]); + await waitForOutput(`sqlTrigger processed 1 changes`); + await waitForOutput( + `sqlTrigger was triggered by operation "update" for "${JSON.stringify({ + id, + testData: `${testData}-updated`, + })}"` + ); -// // trigger by update -// await poolConnection! -// .request() -// .query(`UPDATE ${sqlTriggerTable} SET testData='${testData}-updated' WHERE id='${id}';`); -// await waitForOutput(`sqlTrigger processed 1 changes`); -// await waitForOutput( -// `sqlTrigger was triggered by operation "update" for "${JSON.stringify({ -// id, -// testData: `${testData}-updated`, -// })}"` -// ); + // trigger by delete + await poolConnection!.query(`DELETE FROM ${Sql.sqlTriggerTable} WHERE id=?`, [id]); + await waitForOutput(`sqlTrigger processed 1 changes`); + await waitForOutput(`sqlTrigger was triggered by operation "delete" for "${JSON.stringify({ id })}"`); + }); -// // trigger by delete -// await poolConnection!.request().query(`DELETE FROM ${sqlTriggerTable} WHERE id='${id}';`); -// await waitForOutput(`sqlTrigger processed 1 changes`); -// await waitForOutput(`sqlTrigger was triggered by operation "delete" for "${JSON.stringify({ id })}"`); -// }); + it('input and output', async () => { + const outputUrl = getFuncUrl('httpTriggerSqlOutput'); -// it('input and output', async () => { -// const outputUrl = getFuncUrl('httpTriggerSqlOutput'); + const id = uuid(); + const items: SqlItem[] = [ + { + id, + testData: getRandomTestData(), + }, + ]; + const responseOut = await fetch(outputUrl, { method: 'POST', body: JSON.stringify(items) }); + expect(responseOut.status).to.equal(201); + await waitForOutput(`httpTriggerSqlOutput was triggered`); -// const id = uuid(); -// const items: SqlItem[] = [ -// { -// id, -// testData: getRandomTestData(), -// }, -// ]; -// const responseOut = await fetch(outputUrl, { method: 'POST', body: JSON.stringify(items) }); -// expect(responseOut.status).to.equal(201); -// await waitForOutput(`httpTriggerSqlOutput was triggered`); - -// const inputUrl = getFuncUrl('httpTriggerSqlInput'); -// const responseIn = await fetch(`${inputUrl}?id=${id}`, { method: 'GET' }); -// expect(responseIn.status).to.equal(200); -// const result = await responseIn.json(); -// expect(result).to.deep.equal(items); -// await waitForOutput(`httpTriggerSqlInput was triggered`); -// }); -// }); \ No newline at end of file + const inputUrl = getFuncUrl('httpTriggerSqlInput'); + const responseIn = await fetch(`${inputUrl}?id=${id}`, { method: 'GET' }); + expect(responseIn.status).to.equal(200); + const result = await responseIn.json(); + expect(result).to.deep.equal(items); + await waitForOutput(`httpTriggerSqlInput was triggered`); + }); +}); \ No newline at end of file diff --git a/src/utils/connectionStrings.ts b/src/utils/connectionStrings.ts index 83d75de9..942564c8 100644 --- a/src/utils/connectionStrings.ts +++ b/src/utils/connectionStrings.ts @@ -11,5 +11,5 @@ export async function initializeConnectionStrings(): Promise { storageConnectionString = "UseDevelopmentStorage=true"; cosmosDBConnectionString = "AccountEndpoint=http://localhost:8081/;AccountKey=C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw=="; serviceBusConnectionString = eventHubConnectionString = "Endpoint=sb://localhost;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=SAS_KEY_VALUE;UseDevelopmentEmulator=true;"; - sqlConnectionString = "Server=localhost;UserID =root;Password=password;Database=testdb;Port=3307" + sqlConnectionString = "Server=localhost;UserID=root;Password=password;Database=testdb;Port=3307" } diff --git a/src/utils/sql/setupSql.ts b/src/utils/sql/setupSql.ts index 5819a07e..89cf648f 100644 --- a/src/utils/sql/setupSql.ts +++ b/src/utils/sql/setupSql.ts @@ -2,45 +2,29 @@ // Licensed under the MIT License. import mysql from 'mysql2/promise'; -// import retry from 'p-retry'; +import { Sql } from '../../constants'; -/** - * Various helpful sql docs: - * https://github.com/Azure/azure-functions-sql-extension/blob/main/docs/GeneralSetup.md - * https://github.com/Azure/azure-functions-sql-extension/blob/main/docs/SetupGuide_Javascript.md - * https://learn.microsoft.com/en-us/azure/azure-sql/database/connect-query-nodejs - * https://learn.microsoft.com/en-us/azure/azure-sql/database/azure-sql-javascript-mssql-quickstart - */ - -export const dbName = 'e2eTestDB'; -export const sqlTriggerTable = 'e2eSqlTriggerTable'; -export const sqlNonTriggerTable = 'e2eSqlNonTriggerTable'; -export const sqlSecretName = 'e2eSqlSecret'; - -/** - * create tables and enable change tracking for trigger - */ -export async function runSqlSetupQueries() { +export async function runSqlSetupQueries(): Promise { // const connectionString = await getSqlConnectionString(); const pool = mysql.createPool({ host: 'localhost', port: 3307, user: 'root', password: 'password', - database: 'testdb', + database: Sql.dbName, }); - - const createTableQuery = ` - CREATE TABLE IF NOT EXISTS person ( - id INT NOT NULL AUTO_INCREMENT, - name VARCHAR(100) NOT NULL, - address VARCHAR(255) NOT NULL, - PRIMARY KEY (id) - ) ENGINE=InnoDB; - `; - await pool.query(createTableQuery) - console.log('Table "person" created or already exists.'); - await pool.end(); + + for (const table of [Sql.sqlTriggerTable, Sql.sqlNonTriggerTable]) { + await pool.query(` + CREATE TABLE IF NOT EXISTS ${table} ( + id CHAR(36) PRIMARY KEY, + testData VARCHAR(200) NOT NULL, + az_func_updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP + ) ENGINE=InnoDB; + `); + } + + return pool; // const poolConnection = await createPoolConnnection(); From f6791355b98e9499896e6b723d6f7cd86b061dd4 Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Mon, 4 Aug 2025 16:22:04 -0500 Subject: [PATCH 076/142] fix --- src/utils/connectionStrings.ts | 2 +- src/utils/sql/docker-compose.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/utils/connectionStrings.ts b/src/utils/connectionStrings.ts index 942564c8..814bba18 100644 --- a/src/utils/connectionStrings.ts +++ b/src/utils/connectionStrings.ts @@ -11,5 +11,5 @@ export async function initializeConnectionStrings(): Promise { storageConnectionString = "UseDevelopmentStorage=true"; cosmosDBConnectionString = "AccountEndpoint=http://localhost:8081/;AccountKey=C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw=="; serviceBusConnectionString = eventHubConnectionString = "Endpoint=sb://localhost;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=SAS_KEY_VALUE;UseDevelopmentEmulator=true;"; - sqlConnectionString = "Server=localhost;UserID=root;Password=password;Database=testdb;Port=3307" + sqlConnectionString = "Server=localhost;UserID=root;Password=password;Database=e2eTestDB;Port=3307" } diff --git a/src/utils/sql/docker-compose.yml b/src/utils/sql/docker-compose.yml index a4e8754a..aa43d920 100644 --- a/src/utils/sql/docker-compose.yml +++ b/src/utils/sql/docker-compose.yml @@ -7,7 +7,7 @@ services: - "3307:3306" environment: MYSQL_ROOT_PASSWORD: password - MYSQL_DATABASE: testdb + MYSQL_DATABASE: e2eTestDB MYSQL_USER: user MYSQL_PASSWORD: password networks: From d22fc537c6e7f22913a11fa83add28bbd5836306 Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Mon, 4 Aug 2025 17:14:21 -0500 Subject: [PATCH 077/142] fix --- src/global.test.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/global.test.ts b/src/global.test.ts index ac00f64c..18f4b9fe 100644 --- a/src/global.test.ts +++ b/src/global.test.ts @@ -123,6 +123,7 @@ async function startFuncProcess(appPath: string): Promise { [EnvVarNames.eventHub]: eventHubConnectionString, [EnvVarNames.serviceBus]: serviceBusConnectionString, [EnvVarNames.sql]: sqlConnectionString, + WEBSITE_SITE_NAME: 'azure-functions-nodejs-e2e-tests', FUNCTIONS_REQUEST_BODY_SIZE_LIMIT: '4294967296', }, }, From fc53c751d1032fa5da0f8adae3873794d43716e4 Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Tue, 5 Aug 2025 02:06:56 -0500 Subject: [PATCH 078/142] fix --- app/v3/sqlTrigger/function.json | 2 +- src/utils/connectionStrings.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/v3/sqlTrigger/function.json b/app/v3/sqlTrigger/function.json index b91b1013..108cfe8c 100644 --- a/app/v3/sqlTrigger/function.json +++ b/app/v3/sqlTrigger/function.json @@ -4,7 +4,7 @@ "type": "sqlTrigger", "name": "changes", "direction": "in", - "tableName": "dbo.e2eSqlTriggerTable", + "tableName": "e2eSqlTriggerTable", "connectionStringSetting": "SqlConnection" } ], diff --git a/src/utils/connectionStrings.ts b/src/utils/connectionStrings.ts index 814bba18..9c1805b2 100644 --- a/src/utils/connectionStrings.ts +++ b/src/utils/connectionStrings.ts @@ -11,5 +11,5 @@ export async function initializeConnectionStrings(): Promise { storageConnectionString = "UseDevelopmentStorage=true"; cosmosDBConnectionString = "AccountEndpoint=http://localhost:8081/;AccountKey=C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw=="; serviceBusConnectionString = eventHubConnectionString = "Endpoint=sb://localhost;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=SAS_KEY_VALUE;UseDevelopmentEmulator=true;"; - sqlConnectionString = "Server=localhost;UserID=root;Password=password;Database=e2eTestDB;Port=3307" + sqlConnectionString = "server=localhost;uid=root;pwd=password;database=e2eTestDB" } From 4670b59033e40bd46fcc44c97de128ca53ac0619 Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Tue, 5 Aug 2025 02:37:57 -0500 Subject: [PATCH 079/142] fix --- src/utils/connectionStrings.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/connectionStrings.ts b/src/utils/connectionStrings.ts index 9c1805b2..5aa6a0d1 100644 --- a/src/utils/connectionStrings.ts +++ b/src/utils/connectionStrings.ts @@ -11,5 +11,5 @@ export async function initializeConnectionStrings(): Promise { storageConnectionString = "UseDevelopmentStorage=true"; cosmosDBConnectionString = "AccountEndpoint=http://localhost:8081/;AccountKey=C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw=="; serviceBusConnectionString = eventHubConnectionString = "Endpoint=sb://localhost;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=SAS_KEY_VALUE;UseDevelopmentEmulator=true;"; - sqlConnectionString = "server=localhost;uid=root;pwd=password;database=e2eTestDB" + sqlConnectionString = "Server=localhost;User ID=root;Password=password;Database=e2eTestDB;Port=3307" } From 1a6c773b6f3ecbea62f2d15d244947510780ecea Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Tue, 5 Aug 2025 10:03:50 -0500 Subject: [PATCH 080/142] fix --- src/utils/connectionStrings.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/connectionStrings.ts b/src/utils/connectionStrings.ts index 5aa6a0d1..62bcdbbf 100644 --- a/src/utils/connectionStrings.ts +++ b/src/utils/connectionStrings.ts @@ -11,5 +11,5 @@ export async function initializeConnectionStrings(): Promise { storageConnectionString = "UseDevelopmentStorage=true"; cosmosDBConnectionString = "AccountEndpoint=http://localhost:8081/;AccountKey=C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw=="; serviceBusConnectionString = eventHubConnectionString = "Endpoint=sb://localhost;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=SAS_KEY_VALUE;UseDevelopmentEmulator=true;"; - sqlConnectionString = "Server=localhost;User ID=root;Password=password;Database=e2eTestDB;Port=3307" + sqlConnectionString = "Server=localhost;User ID=root;Password=password;Database=e2eTestDB" } From 1393675b92a0bf4f13a1fdef52c12c45194e35c2 Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Tue, 5 Aug 2025 16:31:44 -0500 Subject: [PATCH 081/142] fix --- src/utils/sql/docker-compose.yml | 35 ++++++++++++++++++------------- src/utils/sql/setupSql.ts | 36 +++++++++++++++----------------- 2 files changed, 38 insertions(+), 33 deletions(-) diff --git a/src/utils/sql/docker-compose.yml b/src/utils/sql/docker-compose.yml index aa43d920..fd905031 100644 --- a/src/utils/sql/docker-compose.yml +++ b/src/utils/sql/docker-compose.yml @@ -1,17 +1,24 @@ -name: mysql-database +name: scratch-mssql + services: - mysql: - container_name: "mysql" - image: "mysql:8.0" - ports: - - "3307:3306" + mssql: + image: mcr.microsoft.com/mssql/server:2022-CU12-ubuntu-22.04 + restart: no + hostname: scratch-mssql environment: - MYSQL_ROOT_PASSWORD: password - MYSQL_DATABASE: e2eTestDB - MYSQL_USER: user - MYSQL_PASSWORD: password - networks: - - mysql-network + - ACCEPT_EULA=Y + - MSSQL_SA_PASSWORD=${AzureWebJobsSQLPassword} + - MSSQL_PID=Developer + - MSSQL_BACKUP_DIR=/var/opt/mssql/backups + - MSSQL_LCID=1033 + - TZ=Etc/UTC + ports: + - 14330:1433 + volumes: + - ./data/mssql/backups:/var/opt/mssql/backups + - ./data/mssql/data:/var/opt/mssql/data + - ./data/mssql/log:/var/opt/mssql/log + networks: - mysql-network: - driver: bridge \ No newline at end of file + default: + name: scratch-mssql-net \ No newline at end of file diff --git a/src/utils/sql/setupSql.ts b/src/utils/sql/setupSql.ts index 89cf648f..432cb6f4 100644 --- a/src/utils/sql/setupSql.ts +++ b/src/utils/sql/setupSql.ts @@ -1,28 +1,26 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT License. -import mysql from 'mysql2/promise'; +// import mysql from 'mysql2/promise'; +import * as sql from 'mssql'; import { Sql } from '../../constants'; -export async function runSqlSetupQueries(): Promise { - // const connectionString = await getSqlConnectionString(); - const pool = mysql.createPool({ - host: 'localhost', - port: 3307, - user: 'root', - password: 'password', - database: Sql.dbName, - }); +export async function runSqlSetupQueries(): Promise { + const config = { + user: 'sa', + password: process.env.AzureWebJobsSQLPassword, + server: 'localhost', + port: 14330, + database: 'master', + options: { + encrypt: false, // true for Azure; false for local/dev + trustServerCertificate: true, // required for local development + }, + }; - for (const table of [Sql.sqlTriggerTable, Sql.sqlNonTriggerTable]) { - await pool.query(` - CREATE TABLE IF NOT EXISTS ${table} ( - id CHAR(36) PRIMARY KEY, - testData VARCHAR(200) NOT NULL, - az_func_updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP - ) ENGINE=InnoDB; - `); - } + const pool = await sql.connect(config); + await pool.request().query(`CREATE DATABASE ${Sql.dbName}`); + console.log('Database created'); return pool; From 3150695c6acf84c1dd07a47588c1559ac0cf53b1 Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Tue, 5 Aug 2025 18:31:57 -0500 Subject: [PATCH 082/142] fix --- src/sql.test.ts | 50 ++++++++++++++++++++++++------------------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/src/sql.test.ts b/src/sql.test.ts index 03d99d93..058d7655 100644 --- a/src/sql.test.ts +++ b/src/sql.test.ts @@ -1,7 +1,6 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT License. -import mysql from 'mysql2/promise'; import { expect } from 'chai'; import { default as fetch } from 'node-fetch'; import { v4 as uuid } from 'uuid'; @@ -9,10 +8,11 @@ import { getFuncUrl } from './constants'; import { isOldConfig, waitForOutput } from './global.test'; import { getRandomTestData } from './utils/getRandomTestData'; import { runSqlSetupQueries } from './utils/sql/setupSql'; -import { Sql } from './constants'; +// import { Sql } from './constants'; +import { ConnectionPool } from 'mssql'; describe('sql', () => { - let poolConnection: mysql.Pool | undefined; + let poolConnection: ConnectionPool | undefined; before(async function (this: Mocha.Context) { if (isOldConfig) { this.skip(); @@ -22,35 +22,35 @@ describe('sql', () => { }); after(async () => { - await poolConnection?.end(); + // await poolConnection?.end(); }); type SqlItem = { id: string; testData: string }; - it('trigger', async () => { - const id = uuid(); - const testData = getRandomTestData(); + // it('trigger', async () => { + // // const id = uuid(); + // // const testData = getRandomTestData(); - // trigger by insert - await poolConnection!.query(`INSERT INTO ${Sql.sqlTriggerTable} (id, testData) VALUES (?, ?)`, [id, testData]); - await waitForOutput(`sqlTrigger processed 1 changes`); - await waitForOutput(`sqlTrigger was triggered by operation "insert" for "${JSON.stringify({ id, testData })}"`); + // // // trigger by insert + // // await poolConnection!.query(`INSERT INTO ${Sql.sqlTriggerTable} (id, testData) VALUES (?, ?)`, [id, testData]); + // // await waitForOutput(`sqlTrigger processed 1 changes`); + // // await waitForOutput(`sqlTrigger was triggered by operation "insert" for "${JSON.stringify({ id, testData })}"`); - // trigger by update - await poolConnection!.query(`UPDATE ${Sql.sqlTriggerTable} SET testData=? WHERE id=?`,[`${testData}-updated`, id]); - await waitForOutput(`sqlTrigger processed 1 changes`); - await waitForOutput( - `sqlTrigger was triggered by operation "update" for "${JSON.stringify({ - id, - testData: `${testData}-updated`, - })}"` - ); + // // // trigger by update + // // await poolConnection!.query(`UPDATE ${Sql.sqlTriggerTable} SET testData=? WHERE id=?`,[`${testData}-updated`, id]); + // // await waitForOutput(`sqlTrigger processed 1 changes`); + // // await waitForOutput( + // // `sqlTrigger was triggered by operation "update" for "${JSON.stringify({ + // // id, + // // testData: `${testData}-updated`, + // // })}"` + // // ); - // trigger by delete - await poolConnection!.query(`DELETE FROM ${Sql.sqlTriggerTable} WHERE id=?`, [id]); - await waitForOutput(`sqlTrigger processed 1 changes`); - await waitForOutput(`sqlTrigger was triggered by operation "delete" for "${JSON.stringify({ id })}"`); - }); + // // // trigger by delete + // // await poolConnection!.query(`DELETE FROM ${Sql.sqlTriggerTable} WHERE id=?`, [id]); + // // await waitForOutput(`sqlTrigger processed 1 changes`); + // // await waitForOutput(`sqlTrigger was triggered by operation "delete" for "${JSON.stringify({ id })}"`); + // }); it('input and output', async () => { const outputUrl = getFuncUrl('httpTriggerSqlOutput'); From 2cb660112498ba1a172358d3e8abcd40a4ab856b Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Tue, 5 Aug 2025 18:50:56 -0500 Subject: [PATCH 083/142] fix --- src/sql.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sql.test.ts b/src/sql.test.ts index 058d7655..c2f54033 100644 --- a/src/sql.test.ts +++ b/src/sql.test.ts @@ -22,7 +22,7 @@ describe('sql', () => { }); after(async () => { - // await poolConnection?.end(); + await poolConnection?.close(); }); type SqlItem = { id: string; testData: string }; From 724dd9c588dee1dba22deb858d8e4479856ccfa2 Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Wed, 6 Aug 2025 01:53:53 -0500 Subject: [PATCH 084/142] fix --- .../templates/test-node-version.yml | 5 ++-- src/utils/connectionStrings.ts | 2 +- src/utils/sql/docker-compose.yml | 30 ++++++++----------- src/utils/sql/setupSql.ts | 22 +++++++------- 4 files changed, 26 insertions(+), 33 deletions(-) diff --git a/azure-pipelines/templates/test-node-version.yml b/azure-pipelines/templates/test-node-version.yml index 660d90eb..2ac9d898 100644 --- a/azure-pipelines/templates/test-node-version.yml +++ b/azure-pipelines/templates/test-node-version.yml @@ -18,9 +18,8 @@ steps: docker ps displayName: "Start CosmosDB Emulator" - bash: | - docker compose -f src/utils/sql/docker-compose.yml pull docker compose -f src/utils/sql/docker-compose.yml up -d - sleep 30 + sleep 60 displayName: "Start SQL Service" - bash: | docker compose -f src/utils/servicebus/docker-compose.yml pull @@ -41,7 +40,7 @@ steps: displayName: 'Run remaining tests Node ${{ parameters.nodeVersion }}' continueOnError: true - bash: | - docker logs mysql + docker logs mssql displayName: 'SQL logs' - bash: npm run testOldConfig displayName: 'Run oldConfig tests Node ${{ parameters.nodeVersion }}' diff --git a/src/utils/connectionStrings.ts b/src/utils/connectionStrings.ts index 62bcdbbf..2785dfe4 100644 --- a/src/utils/connectionStrings.ts +++ b/src/utils/connectionStrings.ts @@ -11,5 +11,5 @@ export async function initializeConnectionStrings(): Promise { storageConnectionString = "UseDevelopmentStorage=true"; cosmosDBConnectionString = "AccountEndpoint=http://localhost:8081/;AccountKey=C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw=="; serviceBusConnectionString = eventHubConnectionString = "Endpoint=sb://localhost;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=SAS_KEY_VALUE;UseDevelopmentEmulator=true;"; - sqlConnectionString = "Server=localhost;User ID=root;Password=password;Database=e2eTestDB" + sqlConnectionString = "Server=localhost,1433;Database=master;User Id=sa;Password=YourStrong!Passw0rd;" } diff --git a/src/utils/sql/docker-compose.yml b/src/utils/sql/docker-compose.yml index fd905031..2cb01870 100644 --- a/src/utils/sql/docker-compose.yml +++ b/src/utils/sql/docker-compose.yml @@ -1,24 +1,18 @@ -name: scratch-mssql +version: '3.9' services: mssql: - image: mcr.microsoft.com/mssql/server:2022-CU12-ubuntu-22.04 - restart: no - hostname: scratch-mssql - environment: - - ACCEPT_EULA=Y - - MSSQL_SA_PASSWORD=${AzureWebJobsSQLPassword} - - MSSQL_PID=Developer - - MSSQL_BACKUP_DIR=/var/opt/mssql/backups - - MSSQL_LCID=1033 - - TZ=Etc/UTC + image: mcr.microsoft.com/mssql/server:2022-latest + container_name: mssql ports: - - 14330:1433 + - "1433:1433" + environment: + SA_PASSWORD: ${AzureWebJobsSQLPassword} + MSSQL_SA_PASSWORD: ${AzureWebJobsSQLPassword} + ACCEPT_EULA: "Y" volumes: - - ./data/mssql/backups:/var/opt/mssql/backups - - ./data/mssql/data:/var/opt/mssql/data - - ./data/mssql/log:/var/opt/mssql/log + - mssql_data:/var/opt/mssql + restart: unless-stopped -networks: - default: - name: scratch-mssql-net \ No newline at end of file +volumes: + mssql_data: \ No newline at end of file diff --git a/src/utils/sql/setupSql.ts b/src/utils/sql/setupSql.ts index 432cb6f4..66e4ce0e 100644 --- a/src/utils/sql/setupSql.ts +++ b/src/utils/sql/setupSql.ts @@ -7,20 +7,20 @@ import { Sql } from '../../constants'; export async function runSqlSetupQueries(): Promise { const config = { - user: 'sa', - password: process.env.AzureWebJobsSQLPassword, - server: 'localhost', - port: 14330, - database: 'master', - options: { - encrypt: false, // true for Azure; false for local/dev - trustServerCertificate: true, // required for local development - }, + user: 'sa', + password: 'YourStrong!Passw0rd', + server: 'localhost', + port: 1433, + database: 'master', + options: { + encrypt: false, // set to true if connecting to Azure SQL + trustServerCertificate: true, + } }; const pool = await sql.connect(config); - await pool.request().query(`CREATE DATABASE ${Sql.dbName}`); - console.log('Database created'); + const result = await pool.request().query('SELECT name FROM sys.databases'); + console.log('Databases:', result.recordset); return pool; From 44c3bb4dbedff9e20e22c3e38552434a8145d723 Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Wed, 6 Aug 2025 02:10:35 -0500 Subject: [PATCH 085/142] fix --- src/utils/sql/setupSql.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/sql/setupSql.ts b/src/utils/sql/setupSql.ts index 66e4ce0e..78c99425 100644 --- a/src/utils/sql/setupSql.ts +++ b/src/utils/sql/setupSql.ts @@ -3,7 +3,7 @@ // import mysql from 'mysql2/promise'; import * as sql from 'mssql'; -import { Sql } from '../../constants'; +// import { Sql } from '../../constants'; export async function runSqlSetupQueries(): Promise { const config = { From 94646c68e2978898bcd8ec72d54943e834d3cdf0 Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Wed, 6 Aug 2025 02:40:07 -0500 Subject: [PATCH 086/142] fix --- src/utils/sql/docker-compose.yml | 2 +- src/utils/sql/setupSql.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/utils/sql/docker-compose.yml b/src/utils/sql/docker-compose.yml index 2cb01870..53779f8c 100644 --- a/src/utils/sql/docker-compose.yml +++ b/src/utils/sql/docker-compose.yml @@ -5,7 +5,7 @@ services: image: mcr.microsoft.com/mssql/server:2022-latest container_name: mssql ports: - - "1433:1433" + - "15433:1433" environment: SA_PASSWORD: ${AzureWebJobsSQLPassword} MSSQL_SA_PASSWORD: ${AzureWebJobsSQLPassword} diff --git a/src/utils/sql/setupSql.ts b/src/utils/sql/setupSql.ts index 78c99425..8bc5ade7 100644 --- a/src/utils/sql/setupSql.ts +++ b/src/utils/sql/setupSql.ts @@ -10,7 +10,7 @@ export async function runSqlSetupQueries(): Promise { user: 'sa', password: 'YourStrong!Passw0rd', server: 'localhost', - port: 1433, + port: 15433, database: 'master', options: { encrypt: false, // set to true if connecting to Azure SQL From ab4423995c113c0d7e94ec872dfc32bc13f86fd2 Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Wed, 6 Aug 2025 10:10:00 -0500 Subject: [PATCH 087/142] fix --- azure-pipelines/public-build.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/azure-pipelines/public-build.yml b/azure-pipelines/public-build.yml index 7fcc9281..63eeceed 100644 --- a/azure-pipelines/public-build.yml +++ b/azure-pipelines/public-build.yml @@ -42,11 +42,11 @@ extends: image: 1es-windows-2022 os: windows - sdl: - codeql: - compiled: - enabled: true - runSourceLanguagesInSourceAnalysis: true + # sdl: + # codeql: + # compiled: + # enabled: true + # runSourceLanguagesInSourceAnalysis: true settings: # PR's from forks do not have sufficient permissions to set tags. From f0298bd10d76e27aed0f28af250e9a0fa01f26b5 Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Wed, 6 Aug 2025 10:38:43 -0500 Subject: [PATCH 088/142] fix --- src/utils/connectionStrings.ts | 7 ++++++- src/utils/sql/docker-compose.yml | 1 + src/utils/sql/setupSql.ts | 7 ++++++- src/utils/validateEnvVar.ts | 12 ------------ 4 files changed, 13 insertions(+), 14 deletions(-) delete mode 100644 src/utils/validateEnvVar.ts diff --git a/src/utils/connectionStrings.ts b/src/utils/connectionStrings.ts index 2785dfe4..bdec9d36 100644 --- a/src/utils/connectionStrings.ts +++ b/src/utils/connectionStrings.ts @@ -8,8 +8,13 @@ export let serviceBusConnectionString: string; export let sqlConnectionString: string; export async function initializeConnectionStrings(): Promise { + const conn = process.env.SqlConnection; + if (!conn || conn.trim() === '') { + throw new Error('Missing required environment variable: SqlConnection'); + } + storageConnectionString = "UseDevelopmentStorage=true"; cosmosDBConnectionString = "AccountEndpoint=http://localhost:8081/;AccountKey=C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw=="; serviceBusConnectionString = eventHubConnectionString = "Endpoint=sb://localhost;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=SAS_KEY_VALUE;UseDevelopmentEmulator=true;"; - sqlConnectionString = "Server=localhost,1433;Database=master;User Id=sa;Password=YourStrong!Passw0rd;" + sqlConnectionString = conn; } diff --git a/src/utils/sql/docker-compose.yml b/src/utils/sql/docker-compose.yml index 53779f8c..9b55131a 100644 --- a/src/utils/sql/docker-compose.yml +++ b/src/utils/sql/docker-compose.yml @@ -10,6 +10,7 @@ services: SA_PASSWORD: ${AzureWebJobsSQLPassword} MSSQL_SA_PASSWORD: ${AzureWebJobsSQLPassword} ACCEPT_EULA: "Y" + SQLConnection: ${SqlConnection} volumes: - mssql_data:/var/opt/mssql restart: unless-stopped diff --git a/src/utils/sql/setupSql.ts b/src/utils/sql/setupSql.ts index 8bc5ade7..26e48420 100644 --- a/src/utils/sql/setupSql.ts +++ b/src/utils/sql/setupSql.ts @@ -6,9 +6,14 @@ import * as sql from 'mssql'; // import { Sql } from '../../constants'; export async function runSqlSetupQueries(): Promise { + const password = process.env.MSSQL_SA_PASSWORD; + if (!password || password.trim() === '') { + throw new Error('Missing required environment variable: MSSQL_SA_PASSWORD'); + } + const config = { user: 'sa', - password: 'YourStrong!Passw0rd', + password: password, server: 'localhost', port: 15433, database: 'master', diff --git a/src/utils/validateEnvVar.ts b/src/utils/validateEnvVar.ts deleted file mode 100644 index 7abf90d1..00000000 --- a/src/utils/validateEnvVar.ts +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the MIT License. - -import { isDefined } from './nonNull'; - -export function validateEnvVar(name: string): string { - const value = process.env[name]; - if (!isDefined(value)) { - throw new Error(`You must set the environment variable "${name}".`); - } - return value; -} From 33c90410271ec1a0bee74625846fdd4fd524d7d7 Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Wed, 6 Aug 2025 11:08:56 -0500 Subject: [PATCH 089/142] fix --- azure-pipelines/templates/test-node-version.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/azure-pipelines/templates/test-node-version.yml b/azure-pipelines/templates/test-node-version.yml index 2ac9d898..74c8e610 100644 --- a/azure-pipelines/templates/test-node-version.yml +++ b/azure-pipelines/templates/test-node-version.yml @@ -20,6 +20,8 @@ steps: - bash: | docker compose -f src/utils/sql/docker-compose.yml up -d sleep 60 + env: + SqlConnection: ${SqlConnection} displayName: "Start SQL Service" - bash: | docker compose -f src/utils/servicebus/docker-compose.yml pull @@ -28,6 +30,8 @@ steps: AzureWebJobsSQLPassword: ${AzureWebJobsSQLPassword} displayName: 'Start ServiceBus Emulator' - bash: npm run testServiceBus + env: + SqlConnection: ${SqlConnection} displayName: 'Run ServiceBus tests Node ${{ parameters.nodeVersion }}' continueOnError: true - bash: | From 5c0dbd6e45684d5e28b5394dfc17d8ded6830fe8 Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Wed, 6 Aug 2025 11:20:33 -0500 Subject: [PATCH 090/142] fix --- azure-pipelines/templates/test-node-version.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/azure-pipelines/templates/test-node-version.yml b/azure-pipelines/templates/test-node-version.yml index 74c8e610..4bd95717 100644 --- a/azure-pipelines/templates/test-node-version.yml +++ b/azure-pipelines/templates/test-node-version.yml @@ -21,6 +21,8 @@ steps: docker compose -f src/utils/sql/docker-compose.yml up -d sleep 60 env: + SA_PASSWORD: ${AzureWebJobsSQLPassword} + MSSQL_SA_PASSWORD: ${AzureWebJobsSQLPassword} SqlConnection: ${SqlConnection} displayName: "Start SQL Service" - bash: | From 3f926357f16f321eb12c9a37d0f22909842e511a Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Wed, 6 Aug 2025 11:47:14 -0500 Subject: [PATCH 091/142] fix --- azure-pipelines/templates/test-node-version.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/azure-pipelines/templates/test-node-version.yml b/azure-pipelines/templates/test-node-version.yml index 4bd95717..71de8847 100644 --- a/azure-pipelines/templates/test-node-version.yml +++ b/azure-pipelines/templates/test-node-version.yml @@ -34,6 +34,8 @@ steps: - bash: npm run testServiceBus env: SqlConnection: ${SqlConnection} + SA_PASSWORD: ${AzureWebJobsSQLPassword} + MSSQL_SA_PASSWORD: ${AzureWebJobsSQLPassword} displayName: 'Run ServiceBus tests Node ${{ parameters.nodeVersion }}' continueOnError: true - bash: | From d506cd771232068264805a40d322359f2b6aa020 Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Wed, 6 Aug 2025 12:15:17 -0500 Subject: [PATCH 092/142] fix --- azure-pipelines/templates/test-node-version.yml | 7 +++++-- src/utils/sql/docker-compose.yml | 1 - src/utils/sql/setupSql.ts | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/azure-pipelines/templates/test-node-version.yml b/azure-pipelines/templates/test-node-version.yml index 71de8847..2748542d 100644 --- a/azure-pipelines/templates/test-node-version.yml +++ b/azure-pipelines/templates/test-node-version.yml @@ -22,7 +22,6 @@ steps: sleep 60 env: SA_PASSWORD: ${AzureWebJobsSQLPassword} - MSSQL_SA_PASSWORD: ${AzureWebJobsSQLPassword} SqlConnection: ${SqlConnection} displayName: "Start SQL Service" - bash: | @@ -31,11 +30,15 @@ steps: env: AzureWebJobsSQLPassword: ${AzureWebJobsSQLPassword} displayName: 'Start ServiceBus Emulator' + - script: | + echo "== Debugging SA_PASSWORD ==" + echo "Length: ${#AzureWebJobsSQLPassword}" + echo "Value: ${AzureWebJobsSQLPassword}" + displayName: "Debug SQL Password in CI" - bash: npm run testServiceBus env: SqlConnection: ${SqlConnection} SA_PASSWORD: ${AzureWebJobsSQLPassword} - MSSQL_SA_PASSWORD: ${AzureWebJobsSQLPassword} displayName: 'Run ServiceBus tests Node ${{ parameters.nodeVersion }}' continueOnError: true - bash: | diff --git a/src/utils/sql/docker-compose.yml b/src/utils/sql/docker-compose.yml index 9b55131a..6d1c51eb 100644 --- a/src/utils/sql/docker-compose.yml +++ b/src/utils/sql/docker-compose.yml @@ -8,7 +8,6 @@ services: - "15433:1433" environment: SA_PASSWORD: ${AzureWebJobsSQLPassword} - MSSQL_SA_PASSWORD: ${AzureWebJobsSQLPassword} ACCEPT_EULA: "Y" SQLConnection: ${SqlConnection} volumes: diff --git a/src/utils/sql/setupSql.ts b/src/utils/sql/setupSql.ts index 26e48420..2316a345 100644 --- a/src/utils/sql/setupSql.ts +++ b/src/utils/sql/setupSql.ts @@ -6,7 +6,7 @@ import * as sql from 'mssql'; // import { Sql } from '../../constants'; export async function runSqlSetupQueries(): Promise { - const password = process.env.MSSQL_SA_PASSWORD; + const password = process.env.SA_PASSWORD; if (!password || password.trim() === '') { throw new Error('Missing required environment variable: MSSQL_SA_PASSWORD'); } From 34b490e98f5722ba72dc55b7fefc651a1e1c6ea1 Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Wed, 6 Aug 2025 12:42:38 -0500 Subject: [PATCH 093/142] fix --- azure-pipelines/templates/test-node-version.yml | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/azure-pipelines/templates/test-node-version.yml b/azure-pipelines/templates/test-node-version.yml index 2748542d..a2e8f975 100644 --- a/azure-pipelines/templates/test-node-version.yml +++ b/azure-pipelines/templates/test-node-version.yml @@ -21,19 +21,21 @@ steps: docker compose -f src/utils/sql/docker-compose.yml up -d sleep 60 env: - SA_PASSWORD: ${AzureWebJobsSQLPassword} - SqlConnection: ${SqlConnection} + SA_PASSWORD: $(AzureWebJobsSQLPassword) + SqlConnection: $(SqlConnection) displayName: "Start SQL Service" - bash: | docker compose -f src/utils/servicebus/docker-compose.yml pull docker compose -f src/utils/servicebus/docker-compose.yml up -d env: - AzureWebJobsSQLPassword: ${AzureWebJobsSQLPassword} + AzureWebJobsSQLPassword: $(AzureWebJobsSQLPassword) displayName: 'Start ServiceBus Emulator' - script: | echo "== Debugging SA_PASSWORD ==" echo "Length: ${#AzureWebJobsSQLPassword}" - echo "Value: ${AzureWebJobsSQLPassword}" + echo "Value: $AzureWebJobsSQLPassword" + env: + AzureWebJobsSQLPassword: $(AzureWebJobsSQLPassword) displayName: "Debug SQL Password in CI" - bash: npm run testServiceBus env: From 5b380d984bdb324b87bc926b1bcd2d8d45d8cd98 Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Wed, 6 Aug 2025 12:54:07 -0500 Subject: [PATCH 094/142] fix --- azure-pipelines/templates/test-node-version.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/azure-pipelines/templates/test-node-version.yml b/azure-pipelines/templates/test-node-version.yml index a2e8f975..90ebd386 100644 --- a/azure-pipelines/templates/test-node-version.yml +++ b/azure-pipelines/templates/test-node-version.yml @@ -39,8 +39,8 @@ steps: displayName: "Debug SQL Password in CI" - bash: npm run testServiceBus env: - SqlConnection: ${SqlConnection} - SA_PASSWORD: ${AzureWebJobsSQLPassword} + SqlConnection: $(SqlConnection) + SA_PASSWORD: $(AzureWebJobsSQLPassword) displayName: 'Run ServiceBus tests Node ${{ parameters.nodeVersion }}' continueOnError: true - bash: | From 117d80c0bd07140ef60f609983aacf73e4237ac0 Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Wed, 6 Aug 2025 13:12:08 -0500 Subject: [PATCH 095/142] fix --- azure-pipelines/templates/test-node-version.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/azure-pipelines/templates/test-node-version.yml b/azure-pipelines/templates/test-node-version.yml index 90ebd386..95311317 100644 --- a/azure-pipelines/templates/test-node-version.yml +++ b/azure-pipelines/templates/test-node-version.yml @@ -22,6 +22,7 @@ steps: sleep 60 env: SA_PASSWORD: $(AzureWebJobsSQLPassword) + MSSQL_SA_PASSWORD: $(AzureWebJobsSQLPassword) SqlConnection: $(SqlConnection) displayName: "Start SQL Service" - bash: | @@ -35,12 +36,14 @@ steps: echo "Length: ${#AzureWebJobsSQLPassword}" echo "Value: $AzureWebJobsSQLPassword" env: - AzureWebJobsSQLPassword: $(AzureWebJobsSQLPassword) + SA_PASSWORD: $(AzureWebJobsSQLPassword) + MSSQL_SA_PASSWORD: $(AzureWebJobsSQLPassword) displayName: "Debug SQL Password in CI" - bash: npm run testServiceBus env: SqlConnection: $(SqlConnection) SA_PASSWORD: $(AzureWebJobsSQLPassword) + MSSQL_SA_PASSWORD: $(AzureWebJobsSQLPassword) displayName: 'Run ServiceBus tests Node ${{ parameters.nodeVersion }}' continueOnError: true - bash: | From 940d298ec0477f59a52d8d401974cea201c9eae6 Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Wed, 6 Aug 2025 14:26:51 -0500 Subject: [PATCH 096/142] fix --- .../templates/test-node-version.yml | 20 ++++++------------- src/utils/sql/docker-compose.yml | 3 +-- src/utils/sql/setupSql.ts | 2 +- 3 files changed, 8 insertions(+), 17 deletions(-) diff --git a/azure-pipelines/templates/test-node-version.yml b/azure-pipelines/templates/test-node-version.yml index 95311317..a1480aaa 100644 --- a/azure-pipelines/templates/test-node-version.yml +++ b/azure-pipelines/templates/test-node-version.yml @@ -20,30 +20,17 @@ steps: - bash: | docker compose -f src/utils/sql/docker-compose.yml up -d sleep 60 - env: - SA_PASSWORD: $(AzureWebJobsSQLPassword) - MSSQL_SA_PASSWORD: $(AzureWebJobsSQLPassword) - SqlConnection: $(SqlConnection) displayName: "Start SQL Service" - bash: | docker compose -f src/utils/servicebus/docker-compose.yml pull docker compose -f src/utils/servicebus/docker-compose.yml up -d - env: - AzureWebJobsSQLPassword: $(AzureWebJobsSQLPassword) displayName: 'Start ServiceBus Emulator' - script: | echo "== Debugging SA_PASSWORD ==" echo "Length: ${#AzureWebJobsSQLPassword}" echo "Value: $AzureWebJobsSQLPassword" - env: - SA_PASSWORD: $(AzureWebJobsSQLPassword) - MSSQL_SA_PASSWORD: $(AzureWebJobsSQLPassword) displayName: "Debug SQL Password in CI" - bash: npm run testServiceBus - env: - SqlConnection: $(SqlConnection) - SA_PASSWORD: $(AzureWebJobsSQLPassword) - MSSQL_SA_PASSWORD: $(AzureWebJobsSQLPassword) displayName: 'Run ServiceBus tests Node ${{ parameters.nodeVersion }}' continueOnError: true - bash: | @@ -68,4 +55,9 @@ steps: docker compose -f src/utils/eventhub/docker-compose.yml down -v docker compose -f src/utils/servicebus/docker-compose.yml down -v docker compose -f src/utils/sql/docker-compose.yml down -v - displayName: 'Stop all resources' \ No newline at end of file + displayName: 'Stop all resources' +env: + AzureWebJobsSQLPassword: $(AzureWebJobsSQLPassword) + SA_PASSWORD: $(AzureWebJobsSQLPassword) + MSSQL_SA_PASSWORD: $(AzureWebJobsSQLPassword) + SqlConnection: $(SqlConnection) \ No newline at end of file diff --git a/src/utils/sql/docker-compose.yml b/src/utils/sql/docker-compose.yml index 6d1c51eb..cc672e3a 100644 --- a/src/utils/sql/docker-compose.yml +++ b/src/utils/sql/docker-compose.yml @@ -7,9 +7,8 @@ services: ports: - "15433:1433" environment: - SA_PASSWORD: ${AzureWebJobsSQLPassword} + SA_PASSWORD: ${SA_PASSWORD} ACCEPT_EULA: "Y" - SQLConnection: ${SqlConnection} volumes: - mssql_data:/var/opt/mssql restart: unless-stopped diff --git a/src/utils/sql/setupSql.ts b/src/utils/sql/setupSql.ts index 2316a345..4f7659ca 100644 --- a/src/utils/sql/setupSql.ts +++ b/src/utils/sql/setupSql.ts @@ -8,7 +8,7 @@ import * as sql from 'mssql'; export async function runSqlSetupQueries(): Promise { const password = process.env.SA_PASSWORD; if (!password || password.trim() === '') { - throw new Error('Missing required environment variable: MSSQL_SA_PASSWORD'); + throw new Error('Missing required environment variable: SA_PASSWORD'); } const config = { From 767239e02c7362a7e0925af807414d9211a6dec9 Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Wed, 6 Aug 2025 14:42:40 -0500 Subject: [PATCH 097/142] fix --- .../templates/test-node-version.yml | 24 ++++++++++--------- src/utils/connectionStrings.ts | 2 +- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/azure-pipelines/templates/test-node-version.yml b/azure-pipelines/templates/test-node-version.yml index a1480aaa..48b579bd 100644 --- a/azure-pipelines/templates/test-node-version.yml +++ b/azure-pipelines/templates/test-node-version.yml @@ -20,17 +20,24 @@ steps: - bash: | docker compose -f src/utils/sql/docker-compose.yml up -d sleep 60 + env: + SA_PASSWORD: $(AzureWebJobsSQLPassword) displayName: "Start SQL Service" + - bash: | + echo "Debugging SA_PASSWORD" + echo "Length: ${#SA_PASSWORD}" + echo "Value: $SA_PASSWORD" + env: + SA_PASSWORD: $(AzureWebJobsSQLPassword) + displayName: "Debug SQL Password" - bash: | docker compose -f src/utils/servicebus/docker-compose.yml pull docker compose -f src/utils/servicebus/docker-compose.yml up -d displayName: 'Start ServiceBus Emulator' - - script: | - echo "== Debugging SA_PASSWORD ==" - echo "Length: ${#AzureWebJobsSQLPassword}" - echo "Value: $AzureWebJobsSQLPassword" - displayName: "Debug SQL Password in CI" - bash: npm run testServiceBus + env: + SA_PASSWORD: $(AzureWebJobsSQLPassword) + SqlConnection: $(SqlConnection) displayName: 'Run ServiceBus tests Node ${{ parameters.nodeVersion }}' continueOnError: true - bash: | @@ -55,9 +62,4 @@ steps: docker compose -f src/utils/eventhub/docker-compose.yml down -v docker compose -f src/utils/servicebus/docker-compose.yml down -v docker compose -f src/utils/sql/docker-compose.yml down -v - displayName: 'Stop all resources' -env: - AzureWebJobsSQLPassword: $(AzureWebJobsSQLPassword) - SA_PASSWORD: $(AzureWebJobsSQLPassword) - MSSQL_SA_PASSWORD: $(AzureWebJobsSQLPassword) - SqlConnection: $(SqlConnection) \ No newline at end of file + displayName: 'Stop all resources' \ No newline at end of file diff --git a/src/utils/connectionStrings.ts b/src/utils/connectionStrings.ts index bdec9d36..c9c3a687 100644 --- a/src/utils/connectionStrings.ts +++ b/src/utils/connectionStrings.ts @@ -16,5 +16,5 @@ export async function initializeConnectionStrings(): Promise { storageConnectionString = "UseDevelopmentStorage=true"; cosmosDBConnectionString = "AccountEndpoint=http://localhost:8081/;AccountKey=C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw=="; serviceBusConnectionString = eventHubConnectionString = "Endpoint=sb://localhost;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=SAS_KEY_VALUE;UseDevelopmentEmulator=true;"; - sqlConnectionString = conn; + sqlConnectionString = "abc"; } From 3942913f0a36dc3ab5cd1a323735dc0a17a97b9a Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Wed, 6 Aug 2025 14:49:06 -0500 Subject: [PATCH 098/142] fix --- app/v3/httpTriggerSqlInput/function.json | 52 +++++++++--------- app/v3/httpTriggerSqlOutput/function.json | 48 ++++++++--------- app/v3/sqlTrigger/function.json | 24 ++++----- app/v4/src/functions/httpTriggerSqlInput.ts | 40 +++++++------- app/v4/src/functions/httpTriggerSqlOutput.ts | 44 +++++++-------- app/v4/src/functions/sqlTrigger.ts | 56 ++++++++++---------- src/utils/connectionStrings.ts | 8 +-- 7 files changed, 136 insertions(+), 136 deletions(-) diff --git a/app/v3/httpTriggerSqlInput/function.json b/app/v3/httpTriggerSqlInput/function.json index 090e8074..109ccad1 100644 --- a/app/v3/httpTriggerSqlInput/function.json +++ b/app/v3/httpTriggerSqlInput/function.json @@ -1,26 +1,26 @@ -{ - "bindings": [ - { - "authLevel": "anonymous", - "type": "httpTrigger", - "direction": "in", - "name": "req", - "methods": ["get", "post"] - }, - { - "type": "http", - "direction": "out", - "name": "res" - }, - { - "type": "sql", - "name": "inputItem", - "direction": "in", - "connectionStringSetting": "SqlConnection", - "commandText": "SELECT * FROM e2eSqlNonTriggerTable WHERE id = ?", - "commandType": "Text", - "parameters": "?={Query.id}" - } - ], - "scriptFile": "../dist/httpTriggerSqlInput/index.js" -} +// { +// "bindings": [ +// { +// "authLevel": "anonymous", +// "type": "httpTrigger", +// "direction": "in", +// "name": "req", +// "methods": ["get", "post"] +// }, +// { +// "type": "http", +// "direction": "out", +// "name": "res" +// }, +// { +// "type": "sql", +// "name": "inputItem", +// "direction": "in", +// "connectionStringSetting": "SqlConnection", +// "commandText": "SELECT * FROM e2eSqlNonTriggerTable WHERE id = ?", +// "commandType": "Text", +// "parameters": "?={Query.id}" +// } +// ], +// "scriptFile": "../dist/httpTriggerSqlInput/index.js" +// } diff --git a/app/v3/httpTriggerSqlOutput/function.json b/app/v3/httpTriggerSqlOutput/function.json index 4d390b83..826d5b7a 100644 --- a/app/v3/httpTriggerSqlOutput/function.json +++ b/app/v3/httpTriggerSqlOutput/function.json @@ -1,24 +1,24 @@ -{ - "bindings": [ - { - "authLevel": "anonymous", - "type": "httpTrigger", - "direction": "in", - "name": "req", - "methods": ["get", "post"] - }, - { - "type": "http", - "direction": "out", - "name": "res" - }, - { - "type": "sql", - "name": "outputItem", - "direction": "out", - "connectionStringSetting": "SqlConnection", - "commandText": "e2eSqlNonTriggerTable" - } - ], - "scriptFile": "../dist/httpTriggerSqlOutput/index.js" -} +// { +// "bindings": [ +// { +// "authLevel": "anonymous", +// "type": "httpTrigger", +// "direction": "in", +// "name": "req", +// "methods": ["get", "post"] +// }, +// { +// "type": "http", +// "direction": "out", +// "name": "res" +// }, +// { +// "type": "sql", +// "name": "outputItem", +// "direction": "out", +// "connectionStringSetting": "SqlConnection", +// "commandText": "e2eSqlNonTriggerTable" +// } +// ], +// "scriptFile": "../dist/httpTriggerSqlOutput/index.js" +// } diff --git a/app/v3/sqlTrigger/function.json b/app/v3/sqlTrigger/function.json index 108cfe8c..bdb76bea 100644 --- a/app/v3/sqlTrigger/function.json +++ b/app/v3/sqlTrigger/function.json @@ -1,12 +1,12 @@ -{ - "bindings": [ - { - "type": "sqlTrigger", - "name": "changes", - "direction": "in", - "tableName": "e2eSqlTriggerTable", - "connectionStringSetting": "SqlConnection" - } - ], - "scriptFile": "../dist/sqlTrigger/index.js" -} +// { +// "bindings": [ +// { +// "type": "sqlTrigger", +// "name": "changes", +// "direction": "in", +// "tableName": "e2eSqlTriggerTable", +// "connectionStringSetting": "SqlConnection" +// } +// ], +// "scriptFile": "../dist/sqlTrigger/index.js" +// } diff --git a/app/v4/src/functions/httpTriggerSqlInput.ts b/app/v4/src/functions/httpTriggerSqlInput.ts index 0a98c94a..fb0a82f7 100644 --- a/app/v4/src/functions/httpTriggerSqlInput.ts +++ b/app/v4/src/functions/httpTriggerSqlInput.ts @@ -1,24 +1,24 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the MIT License. +// // Copyright (c) .NET Foundation. All rights reserved. +// // Licensed under the MIT License. -import { app, HttpRequest, HttpResponseInit, input, InvocationContext } from '@azure/functions'; +// import { app, HttpRequest, HttpResponseInit, input, InvocationContext } from '@azure/functions'; -const sqlInput = input.sql({ - connectionStringSetting: 'SqlConnection', - commandText: 'select * from dbo.e2eSqlNonTriggerTable where id = @id', - commandType: 'Text', - parameters: '@id={Query.id}', -}); +// const sqlInput = input.sql({ +// connectionStringSetting: 'SqlConnection', +// commandText: 'select * from dbo.e2eSqlNonTriggerTable where id = @id', +// commandType: 'Text', +// parameters: '@id={Query.id}', +// }); -export async function httpTriggerSqlInput(request: HttpRequest, context: InvocationContext): Promise { - context.log(`httpTriggerSqlInput was triggered`); - const items = context.extraInputs.get(sqlInput); - return { jsonBody: items }; -} +// export async function httpTriggerSqlInput(request: HttpRequest, context: InvocationContext): Promise { +// context.log(`httpTriggerSqlInput was triggered`); +// const items = context.extraInputs.get(sqlInput); +// return { jsonBody: items }; +// } -app.http('httpTriggerSqlInput', { - methods: ['GET', 'POST'], - authLevel: 'anonymous', - extraInputs: [sqlInput], - handler: httpTriggerSqlInput, -}); +// app.http('httpTriggerSqlInput', { +// methods: ['GET', 'POST'], +// authLevel: 'anonymous', +// extraInputs: [sqlInput], +// handler: httpTriggerSqlInput, +// }); diff --git a/app/v4/src/functions/httpTriggerSqlOutput.ts b/app/v4/src/functions/httpTriggerSqlOutput.ts index 1fa61fee..165cd268 100644 --- a/app/v4/src/functions/httpTriggerSqlOutput.ts +++ b/app/v4/src/functions/httpTriggerSqlOutput.ts @@ -1,26 +1,26 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the MIT License. +// // Copyright (c) .NET Foundation. All rights reserved. +// // Licensed under the MIT License. -import { app, HttpRequest, HttpResponseInit, InvocationContext, output } from '@azure/functions'; +// import { app, HttpRequest, HttpResponseInit, InvocationContext, output } from '@azure/functions'; -const sqlOutput = output.sql({ - connectionStringSetting: 'SqlConnection', - commandText: 'e2eSqlNonTriggerTable', -}); +// const sqlOutput = output.sql({ +// connectionStringSetting: 'SqlConnection', +// commandText: 'e2eSqlNonTriggerTable', +// }); -export async function httpTriggerSqlOutput( - request: HttpRequest, - context: InvocationContext -): Promise { - context.log(`httpTriggerSqlOutput was triggered`); - const body = await request.json(); - context.extraOutputs.set(sqlOutput, body); - return { status: 201 }; -} +// export async function httpTriggerSqlOutput( +// request: HttpRequest, +// context: InvocationContext +// ): Promise { +// context.log(`httpTriggerSqlOutput was triggered`); +// const body = await request.json(); +// context.extraOutputs.set(sqlOutput, body); +// return { status: 201 }; +// } -app.http('httpTriggerSqlOutput', { - methods: ['GET', 'POST'], - authLevel: 'anonymous', - extraOutputs: [sqlOutput], - handler: httpTriggerSqlOutput, -}); +// app.http('httpTriggerSqlOutput', { +// methods: ['GET', 'POST'], +// authLevel: 'anonymous', +// extraOutputs: [sqlOutput], +// handler: httpTriggerSqlOutput, +// }); diff --git a/app/v4/src/functions/sqlTrigger.ts b/app/v4/src/functions/sqlTrigger.ts index 5bf07f02..adaf61a3 100644 --- a/app/v4/src/functions/sqlTrigger.ts +++ b/app/v4/src/functions/sqlTrigger.ts @@ -1,31 +1,31 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the MIT License. +// // Copyright (c) .NET Foundation. All rights reserved. +// // Licensed under the MIT License. -import { app, InvocationContext, SqlChange, SqlChangeOperation } from '@azure/functions'; +// import { app, InvocationContext, SqlChange, SqlChangeOperation } from '@azure/functions'; -export async function sqlTrigger(changes: SqlChange[], context: InvocationContext): Promise { - context.log(`sqlTrigger processed ${changes.length} changes`); - for (const change of changes) { - let operation: string; - switch (change.Operation) { - case SqlChangeOperation.Insert: - operation = 'insert'; - break; - case SqlChangeOperation.Update: - operation = 'update'; - break; - case SqlChangeOperation.Delete: - operation = 'delete'; - break; - default: - throw RangeError(`Unrecognized operation "${change.Operation}"`); - } - context.log(`sqlTrigger was triggered by operation "${operation}" for "${JSON.stringify(change.Item)}"`); - } -} +// export async function sqlTrigger(changes: SqlChange[], context: InvocationContext): Promise { +// context.log(`sqlTrigger processed ${changes.length} changes`); +// for (const change of changes) { +// let operation: string; +// switch (change.Operation) { +// case SqlChangeOperation.Insert: +// operation = 'insert'; +// break; +// case SqlChangeOperation.Update: +// operation = 'update'; +// break; +// case SqlChangeOperation.Delete: +// operation = 'delete'; +// break; +// default: +// throw RangeError(`Unrecognized operation "${change.Operation}"`); +// } +// context.log(`sqlTrigger was triggered by operation "${operation}" for "${JSON.stringify(change.Item)}"`); +// } +// } -app.sql('sqlTrigger', { - tableName: 'e2eSqlTriggerTable', - connectionStringSetting: 'SqlConnection', - handler: sqlTrigger, -}); +// app.sql('sqlTrigger', { +// tableName: 'e2eSqlTriggerTable', +// connectionStringSetting: 'SqlConnection', +// handler: sqlTrigger, +// }); diff --git a/src/utils/connectionStrings.ts b/src/utils/connectionStrings.ts index c9c3a687..526a6d03 100644 --- a/src/utils/connectionStrings.ts +++ b/src/utils/connectionStrings.ts @@ -8,10 +8,10 @@ export let serviceBusConnectionString: string; export let sqlConnectionString: string; export async function initializeConnectionStrings(): Promise { - const conn = process.env.SqlConnection; - if (!conn || conn.trim() === '') { - throw new Error('Missing required environment variable: SqlConnection'); - } + // const conn = process.env.SqlConnection; + // if (!conn || conn.trim() === '') { + // throw new Error('Missing required environment variable: SqlConnection'); + // } storageConnectionString = "UseDevelopmentStorage=true"; cosmosDBConnectionString = "AccountEndpoint=http://localhost:8081/;AccountKey=C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw=="; From 28f4863c9064c1d81bf0ba897f604ed8928fdc73 Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Wed, 6 Aug 2025 15:39:52 -0500 Subject: [PATCH 099/142] fix --- azure-pipelines/templates/test-node-version.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/azure-pipelines/templates/test-node-version.yml b/azure-pipelines/templates/test-node-version.yml index 48b579bd..dd523c97 100644 --- a/azure-pipelines/templates/test-node-version.yml +++ b/azure-pipelines/templates/test-node-version.yml @@ -33,6 +33,8 @@ steps: - bash: | docker compose -f src/utils/servicebus/docker-compose.yml pull docker compose -f src/utils/servicebus/docker-compose.yml up -d + env: + AzureWebJobsSQLPassword: $(AzureWebJobsSQLPassword) displayName: 'Start ServiceBus Emulator' - bash: npm run testServiceBus env: From fedfe5833309e6eab0a0477dd085e80cfcb0ee50 Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Wed, 6 Aug 2025 16:23:40 -0500 Subject: [PATCH 100/142] fix --- app/v3/httpTriggerSqlInput/function.json | 52 ++++++++--------- app/v3/httpTriggerSqlInput/index.ts | 2 +- app/v3/httpTriggerSqlOutput/function.json | 48 ++++++++-------- app/v3/httpTriggerSqlOutput/index.ts | 2 +- app/v3/sqlTrigger/function.json | 24 ++++---- app/v4/src/functions/httpTriggerSqlInput.ts | 40 ++++++------- app/v4/src/functions/httpTriggerSqlOutput.ts | 44 +++++++-------- app/v4/src/functions/sqlTrigger.ts | 56 +++++++++---------- .../templates/test-node-version.yml | 3 +- src/global.test.ts | 4 +- src/sql.test.ts | 50 +++++++++-------- src/utils/connectionStrings.ts | 10 ++-- src/utils/sql/setupSql.ts | 39 ++++++------- 13 files changed, 187 insertions(+), 187 deletions(-) diff --git a/app/v3/httpTriggerSqlInput/function.json b/app/v3/httpTriggerSqlInput/function.json index 109ccad1..986c8027 100644 --- a/app/v3/httpTriggerSqlInput/function.json +++ b/app/v3/httpTriggerSqlInput/function.json @@ -1,26 +1,26 @@ -// { -// "bindings": [ -// { -// "authLevel": "anonymous", -// "type": "httpTrigger", -// "direction": "in", -// "name": "req", -// "methods": ["get", "post"] -// }, -// { -// "type": "http", -// "direction": "out", -// "name": "res" -// }, -// { -// "type": "sql", -// "name": "inputItem", -// "direction": "in", -// "connectionStringSetting": "SqlConnection", -// "commandText": "SELECT * FROM e2eSqlNonTriggerTable WHERE id = ?", -// "commandType": "Text", -// "parameters": "?={Query.id}" -// } -// ], -// "scriptFile": "../dist/httpTriggerSqlInput/index.js" -// } +{ + "bindings": [ + { + "authLevel": "anonymous", + "type": "httpTrigger", + "direction": "in", + "name": "req", + "methods": ["get", "post"] + }, + { + "type": "http", + "direction": "out", + "name": "res" + }, + { + "type": "sql", + "name": "inputItem", + "direction": "in", + "connectionStringSetting": "SqlConnection", + "commandText": "select * from dbo.e2eSqlNonTriggerTable where id = @id", + "commandType": "Text", + "parameters": "@id={Query.id}" + } + ], + "scriptFile": "../dist/httpTriggerSqlInput/index.js" +} \ No newline at end of file diff --git a/app/v3/httpTriggerSqlInput/index.ts b/app/v3/httpTriggerSqlInput/index.ts index f6c6c113..eb1de547 100644 --- a/app/v3/httpTriggerSqlInput/index.ts +++ b/app/v3/httpTriggerSqlInput/index.ts @@ -10,4 +10,4 @@ const httpTriggerSqlInput: AzureFunction = async function (context: Context, _re }; }; -export default httpTriggerSqlInput; +export default httpTriggerSqlInput; \ No newline at end of file diff --git a/app/v3/httpTriggerSqlOutput/function.json b/app/v3/httpTriggerSqlOutput/function.json index 826d5b7a..76edda65 100644 --- a/app/v3/httpTriggerSqlOutput/function.json +++ b/app/v3/httpTriggerSqlOutput/function.json @@ -1,24 +1,24 @@ -// { -// "bindings": [ -// { -// "authLevel": "anonymous", -// "type": "httpTrigger", -// "direction": "in", -// "name": "req", -// "methods": ["get", "post"] -// }, -// { -// "type": "http", -// "direction": "out", -// "name": "res" -// }, -// { -// "type": "sql", -// "name": "outputItem", -// "direction": "out", -// "connectionStringSetting": "SqlConnection", -// "commandText": "e2eSqlNonTriggerTable" -// } -// ], -// "scriptFile": "../dist/httpTriggerSqlOutput/index.js" -// } +{ + "bindings": [ + { + "authLevel": "anonymous", + "type": "httpTrigger", + "direction": "in", + "name": "req", + "methods": ["get", "post"] + }, + { + "type": "http", + "direction": "out", + "name": "res" + }, + { + "type": "sql", + "name": "outputItem", + "direction": "out", + "connectionStringSetting": "SqlConnection", + "commandText": "dbo.e2eSqlNonTriggerTable" + } + ], + "scriptFile": "../dist/httpTriggerSqlOutput/index.js" +} \ No newline at end of file diff --git a/app/v3/httpTriggerSqlOutput/index.ts b/app/v3/httpTriggerSqlOutput/index.ts index 8a27d059..f62e0c72 100644 --- a/app/v3/httpTriggerSqlOutput/index.ts +++ b/app/v3/httpTriggerSqlOutput/index.ts @@ -11,4 +11,4 @@ const httpTriggerSqlOutput: AzureFunction = async function (context: Context, re }; }; -export default httpTriggerSqlOutput; +export default httpTriggerSqlOutput; \ No newline at end of file diff --git a/app/v3/sqlTrigger/function.json b/app/v3/sqlTrigger/function.json index bdb76bea..c18873d9 100644 --- a/app/v3/sqlTrigger/function.json +++ b/app/v3/sqlTrigger/function.json @@ -1,12 +1,12 @@ -// { -// "bindings": [ -// { -// "type": "sqlTrigger", -// "name": "changes", -// "direction": "in", -// "tableName": "e2eSqlTriggerTable", -// "connectionStringSetting": "SqlConnection" -// } -// ], -// "scriptFile": "../dist/sqlTrigger/index.js" -// } +{ + "bindings": [ + { + "type": "sqlTrigger", + "name": "changes", + "direction": "in", + "tableName": "dbo.e2eSqlTriggerTable", + "connectionStringSetting": "SqlConnection" + } + ], + "scriptFile": "../dist/sqlTrigger/index.js" +} \ No newline at end of file diff --git a/app/v4/src/functions/httpTriggerSqlInput.ts b/app/v4/src/functions/httpTriggerSqlInput.ts index fb0a82f7..1f68f86f 100644 --- a/app/v4/src/functions/httpTriggerSqlInput.ts +++ b/app/v4/src/functions/httpTriggerSqlInput.ts @@ -1,24 +1,24 @@ -// // Copyright (c) .NET Foundation. All rights reserved. -// // Licensed under the MIT License. +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT License. -// import { app, HttpRequest, HttpResponseInit, input, InvocationContext } from '@azure/functions'; +import { app, HttpRequest, HttpResponseInit, input, InvocationContext } from '@azure/functions'; -// const sqlInput = input.sql({ -// connectionStringSetting: 'SqlConnection', -// commandText: 'select * from dbo.e2eSqlNonTriggerTable where id = @id', -// commandType: 'Text', -// parameters: '@id={Query.id}', -// }); +const sqlInput = input.sql({ + connectionStringSetting: 'SqlConnection', + commandText: 'select * from dbo.e2eSqlNonTriggerTable where id = @id', + commandType: 'Text', + parameters: '@id={Query.id}', +}); -// export async function httpTriggerSqlInput(request: HttpRequest, context: InvocationContext): Promise { -// context.log(`httpTriggerSqlInput was triggered`); -// const items = context.extraInputs.get(sqlInput); -// return { jsonBody: items }; -// } +export async function httpTriggerSqlInput(request: HttpRequest, context: InvocationContext): Promise { + context.log(`httpTriggerSqlInput was triggered`); + const items = context.extraInputs.get(sqlInput); + return { jsonBody: items }; +} -// app.http('httpTriggerSqlInput', { -// methods: ['GET', 'POST'], -// authLevel: 'anonymous', -// extraInputs: [sqlInput], -// handler: httpTriggerSqlInput, -// }); +app.http('httpTriggerSqlInput', { + methods: ['GET', 'POST'], + authLevel: 'anonymous', + extraInputs: [sqlInput], + handler: httpTriggerSqlInput, +}); \ No newline at end of file diff --git a/app/v4/src/functions/httpTriggerSqlOutput.ts b/app/v4/src/functions/httpTriggerSqlOutput.ts index 165cd268..60cd1306 100644 --- a/app/v4/src/functions/httpTriggerSqlOutput.ts +++ b/app/v4/src/functions/httpTriggerSqlOutput.ts @@ -1,26 +1,26 @@ -// // Copyright (c) .NET Foundation. All rights reserved. -// // Licensed under the MIT License. +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT License. -// import { app, HttpRequest, HttpResponseInit, InvocationContext, output } from '@azure/functions'; +import { app, HttpRequest, HttpResponseInit, InvocationContext, output } from '@azure/functions'; -// const sqlOutput = output.sql({ -// connectionStringSetting: 'SqlConnection', -// commandText: 'e2eSqlNonTriggerTable', -// }); +const sqlOutput = output.sql({ + connectionStringSetting: 'SqlConnection', + commandText: 'dbo.e2eSqlNonTriggerTable', +}); -// export async function httpTriggerSqlOutput( -// request: HttpRequest, -// context: InvocationContext -// ): Promise { -// context.log(`httpTriggerSqlOutput was triggered`); -// const body = await request.json(); -// context.extraOutputs.set(sqlOutput, body); -// return { status: 201 }; -// } +export async function httpTriggerSqlOutput( + request: HttpRequest, + context: InvocationContext +): Promise { + context.log(`httpTriggerSqlOutput was triggered`); + const body = await request.json(); + context.extraOutputs.set(sqlOutput, body); + return { status: 201 }; +} -// app.http('httpTriggerSqlOutput', { -// methods: ['GET', 'POST'], -// authLevel: 'anonymous', -// extraOutputs: [sqlOutput], -// handler: httpTriggerSqlOutput, -// }); +app.http('httpTriggerSqlOutput', { + methods: ['GET', 'POST'], + authLevel: 'anonymous', + extraOutputs: [sqlOutput], + handler: httpTriggerSqlOutput, +}); \ No newline at end of file diff --git a/app/v4/src/functions/sqlTrigger.ts b/app/v4/src/functions/sqlTrigger.ts index adaf61a3..8998cf3d 100644 --- a/app/v4/src/functions/sqlTrigger.ts +++ b/app/v4/src/functions/sqlTrigger.ts @@ -1,31 +1,31 @@ -// // Copyright (c) .NET Foundation. All rights reserved. -// // Licensed under the MIT License. +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT License. -// import { app, InvocationContext, SqlChange, SqlChangeOperation } from '@azure/functions'; +import { app, InvocationContext, SqlChange, SqlChangeOperation } from '@azure/functions'; -// export async function sqlTrigger(changes: SqlChange[], context: InvocationContext): Promise { -// context.log(`sqlTrigger processed ${changes.length} changes`); -// for (const change of changes) { -// let operation: string; -// switch (change.Operation) { -// case SqlChangeOperation.Insert: -// operation = 'insert'; -// break; -// case SqlChangeOperation.Update: -// operation = 'update'; -// break; -// case SqlChangeOperation.Delete: -// operation = 'delete'; -// break; -// default: -// throw RangeError(`Unrecognized operation "${change.Operation}"`); -// } -// context.log(`sqlTrigger was triggered by operation "${operation}" for "${JSON.stringify(change.Item)}"`); -// } -// } +export async function sqlTrigger(changes: SqlChange[], context: InvocationContext): Promise { + context.log(`sqlTrigger processed ${changes.length} changes`); + for (const change of changes) { + let operation: string; + switch (change.Operation) { + case SqlChangeOperation.Insert: + operation = 'insert'; + break; + case SqlChangeOperation.Update: + operation = 'update'; + break; + case SqlChangeOperation.Delete: + operation = 'delete'; + break; + default: + throw RangeError(`Unrecognized operation "${change.Operation}"`); + } + context.log(`sqlTrigger was triggered by operation "${operation}" for "${JSON.stringify(change.Item)}"`); + } +} -// app.sql('sqlTrigger', { -// tableName: 'e2eSqlTriggerTable', -// connectionStringSetting: 'SqlConnection', -// handler: sqlTrigger, -// }); +app.sql('sqlTrigger', { + tableName: 'dbo.e2eSqlTriggerTable', + connectionStringSetting: 'SqlConnection', + handler: sqlTrigger, +}); \ No newline at end of file diff --git a/azure-pipelines/templates/test-node-version.yml b/azure-pipelines/templates/test-node-version.yml index dd523c97..3d809020 100644 --- a/azure-pipelines/templates/test-node-version.yml +++ b/azure-pipelines/templates/test-node-version.yml @@ -39,7 +39,6 @@ steps: - bash: npm run testServiceBus env: SA_PASSWORD: $(AzureWebJobsSQLPassword) - SqlConnection: $(SqlConnection) displayName: 'Run ServiceBus tests Node ${{ parameters.nodeVersion }}' continueOnError: true - bash: | @@ -49,6 +48,8 @@ steps: docker compose -f src/utils/eventhub/docker-compose.yml up -d displayName: 'Stop ServiceBus Emulator and Start EventHub Emulator' - bash: npm run testAllExceptServiceBus + env: + SA_PASSWORD: $(AzureWebJobsSQLPassword) displayName: 'Run remaining tests Node ${{ parameters.nodeVersion }}' continueOnError: true - bash: | diff --git a/src/global.test.ts b/src/global.test.ts index 18f4b9fe..b1da4ad2 100644 --- a/src/global.test.ts +++ b/src/global.test.ts @@ -18,7 +18,7 @@ import { import { setupCosmosDB } from './utils/cosmosdb/setupCosmosDB'; import { delay } from './utils/delay'; import findProcess = require('find-process'); -import { runSqlSetupQueries } from './utils/sql/setupSql'; +// import { runSqlSetupQueries } from './utils/sql/setupSql'; let perTestFuncOutput = ''; let fullFuncOutput = ''; @@ -45,7 +45,7 @@ before(async function (this: Mocha.Context): Promise { await setupCosmosDB(); - await runSqlSetupQueries(); + // await runSqlSetupQueries(); isOldConfig = getOldConfigArg(); const appPath = isOldConfig diff --git a/src/sql.test.ts b/src/sql.test.ts index c2f54033..ce05b318 100644 --- a/src/sql.test.ts +++ b/src/sql.test.ts @@ -7,8 +7,8 @@ import { v4 as uuid } from 'uuid'; import { getFuncUrl } from './constants'; import { isOldConfig, waitForOutput } from './global.test'; import { getRandomTestData } from './utils/getRandomTestData'; -import { runSqlSetupQueries } from './utils/sql/setupSql'; -// import { Sql } from './constants'; +import { createPoolConnnection } from './utils/sql/setupSql'; +import { Sql } from './constants'; import { ConnectionPool } from 'mssql'; describe('sql', () => { @@ -18,7 +18,7 @@ describe('sql', () => { this.skip(); } - poolConnection = await runSqlSetupQueries(); + poolConnection = await createPoolConnnection(); }); after(async () => { @@ -27,30 +27,32 @@ describe('sql', () => { type SqlItem = { id: string; testData: string }; - // it('trigger', async () => { - // // const id = uuid(); - // // const testData = getRandomTestData(); + it('trigger', async () => { + const id = uuid(); + const testData = getRandomTestData(); - // // // trigger by insert - // // await poolConnection!.query(`INSERT INTO ${Sql.sqlTriggerTable} (id, testData) VALUES (?, ?)`, [id, testData]); - // // await waitForOutput(`sqlTrigger processed 1 changes`); - // // await waitForOutput(`sqlTrigger was triggered by operation "insert" for "${JSON.stringify({ id, testData })}"`); + // trigger by insert + await poolConnection!.request().query(`INSERT INTO ${Sql.sqlTriggerTable} VALUES ('${id}', '${testData}');`); + await waitForOutput(`sqlTrigger processed 1 changes`); + await waitForOutput(`sqlTrigger was triggered by operation "insert" for "${JSON.stringify({ id, testData })}"`); - // // // trigger by update - // // await poolConnection!.query(`UPDATE ${Sql.sqlTriggerTable} SET testData=? WHERE id=?`,[`${testData}-updated`, id]); - // // await waitForOutput(`sqlTrigger processed 1 changes`); - // // await waitForOutput( - // // `sqlTrigger was triggered by operation "update" for "${JSON.stringify({ - // // id, - // // testData: `${testData}-updated`, - // // })}"` - // // ); + // trigger by update + await poolConnection! + .request() + .query(`UPDATE ${Sql.sqlTriggerTable} SET testData='${testData}-updated' WHERE id='${id}';`); + await waitForOutput(`sqlTrigger processed 1 changes`); + await waitForOutput( + `sqlTrigger was triggered by operation "update" for "${JSON.stringify({ + id, + testData: `${testData}-updated`, + })}"` + ); - // // // trigger by delete - // // await poolConnection!.query(`DELETE FROM ${Sql.sqlTriggerTable} WHERE id=?`, [id]); - // // await waitForOutput(`sqlTrigger processed 1 changes`); - // // await waitForOutput(`sqlTrigger was triggered by operation "delete" for "${JSON.stringify({ id })}"`); - // }); + // trigger by delete + await poolConnection!.request().query(`DELETE FROM ${Sql.sqlTriggerTable} WHERE id='${id}';`); + await waitForOutput(`sqlTrigger processed 1 changes`); + await waitForOutput(`sqlTrigger was triggered by operation "delete" for "${JSON.stringify({ id })}"`); + }); it('input and output', async () => { const outputUrl = getFuncUrl('httpTriggerSqlOutput'); diff --git a/src/utils/connectionStrings.ts b/src/utils/connectionStrings.ts index 526a6d03..23a46e25 100644 --- a/src/utils/connectionStrings.ts +++ b/src/utils/connectionStrings.ts @@ -8,13 +8,13 @@ export let serviceBusConnectionString: string; export let sqlConnectionString: string; export async function initializeConnectionStrings(): Promise { - // const conn = process.env.SqlConnection; - // if (!conn || conn.trim() === '') { - // throw new Error('Missing required environment variable: SqlConnection'); - // } + const password = process.env.SA_PASSWORD; + if (!password || password.trim() === '') { + throw new Error('Missing required environment variable: SA_PASSWORD'); + } storageConnectionString = "UseDevelopmentStorage=true"; cosmosDBConnectionString = "AccountEndpoint=http://localhost:8081/;AccountKey=C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw=="; serviceBusConnectionString = eventHubConnectionString = "Endpoint=sb://localhost;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=SAS_KEY_VALUE;UseDevelopmentEmulator=true;"; - sqlConnectionString = "abc"; + sqlConnectionString = `Server=localhost,15433;Database=master;User Id=sa;Password=${password};Encrypt=false;TrustServerCertificate=true;`; } diff --git a/src/utils/sql/setupSql.ts b/src/utils/sql/setupSql.ts index 4f7659ca..7154c132 100644 --- a/src/utils/sql/setupSql.ts +++ b/src/utils/sql/setupSql.ts @@ -3,31 +3,28 @@ // import mysql from 'mysql2/promise'; import * as sql from 'mssql'; +import { sqlConnectionString } from '../connectionStrings'; // import { Sql } from '../../constants'; -export async function runSqlSetupQueries(): Promise { - const password = process.env.SA_PASSWORD; - if (!password || password.trim() === '') { - throw new Error('Missing required environment variable: SA_PASSWORD'); - } - - const config = { - user: 'sa', - password: password, - server: 'localhost', - port: 15433, - database: 'master', - options: { - encrypt: false, // set to true if connecting to Azure SQL - trustServerCertificate: true, - } - }; +export async function createPoolConnnection(): Promise { + // const password = process.env.SA_PASSWORD; + // if (!password || password.trim() === '') { + // throw new Error('Missing required environment variable: SA_PASSWORD'); + // } - const pool = await sql.connect(config); - const result = await pool.request().query('SELECT name FROM sys.databases'); - console.log('Databases:', result.recordset); + // const config = { + // user: 'sa', + // password: password, + // server: 'localhost', + // port: 15433, + // database: 'master', + // options: { + // encrypt: false, // set to true if connecting to Azure SQL + // trustServerCertificate: true, + // } + // }; - return pool; + return await sql.connect(sqlConnectionString); // const poolConnection = await createPoolConnnection(); From a1c5c1264e897112570e6bd249b9c8b7996c8f96 Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Wed, 6 Aug 2025 16:48:48 -0500 Subject: [PATCH 101/142] fix --- src/sql.test.ts | 4 ++++ src/utils/sql/setupSql.ts | 37 ++++++++++++++++++------------------- 2 files changed, 22 insertions(+), 19 deletions(-) diff --git a/src/sql.test.ts b/src/sql.test.ts index ce05b318..e5f1183c 100644 --- a/src/sql.test.ts +++ b/src/sql.test.ts @@ -31,6 +31,10 @@ describe('sql', () => { const id = uuid(); const testData = getRandomTestData(); + if (!poolConnection) { + throw new Error('SQL connection pool is not initialized'); + } + // trigger by insert await poolConnection!.request().query(`INSERT INTO ${Sql.sqlTriggerTable} VALUES ('${id}', '${testData}');`); await waitForOutput(`sqlTrigger processed 1 changes`); diff --git a/src/utils/sql/setupSql.ts b/src/utils/sql/setupSql.ts index 7154c132..0a39b9c6 100644 --- a/src/utils/sql/setupSql.ts +++ b/src/utils/sql/setupSql.ts @@ -4,7 +4,7 @@ // import mysql from 'mysql2/promise'; import * as sql from 'mssql'; import { sqlConnectionString } from '../connectionStrings'; -// import { Sql } from '../../constants'; +import { Sql } from '../../constants'; export async function createPoolConnnection(): Promise { // const password = process.env.SA_PASSWORD; @@ -24,26 +24,25 @@ export async function createPoolConnnection(): Promise { // } // }; - return await sql.connect(sqlConnectionString); + if (!sqlConnectionString || sqlConnectionString.trim() === '') { + throw new Error('Missing required environment variable: SqlConnection'); + } + + const poolConnection = await sql.connect(sqlConnectionString); + await poolConnection + .request() + .query(`ALTER DATABASE ${Sql.dbName} SET CHANGE_TRACKING = ON (CHANGE_RETENTION = 2 DAYS, AUTO_CLEANUP = ON);`); - // const poolConnection = await createPoolConnnection(); + for (const table of [Sql.sqlTriggerTable, Sql.sqlNonTriggerTable]) { + await poolConnection + .request() + .query( + `CREATE TABLE dbo.${table} ([id] UNIQUEIDENTIFIER PRIMARY KEY, [testData] NVARCHAR(200) NOT NULL);` + ); + await poolConnection.request().query(`ALTER TABLE dbo.${table} ENABLE CHANGE_TRACKING;`); + } - // try { - // await poolConnection - // .request() - // .query(`ALTER DATABASE ${dbName} SET CHANGE_TRACKING = ON (CHANGE_RETENTION = 2 DAYS, AUTO_CLEANUP = ON);`); - - // for (const table of [sqlTriggerTable, sqlNonTriggerTable]) { - // await poolConnection - // .request() - // .query( - // `CREATE TABLE dbo.${table} ([id] UNIQUEIDENTIFIER PRIMARY KEY, [testData] NVARCHAR(200) NOT NULL);` - // ); - // await poolConnection.request().query(`ALTER TABLE dbo.${table} ENABLE CHANGE_TRACKING;`); - // } - // } finally { - // await poolConnection.close(); - // } + return poolConnection; } // export async function createPoolConnnection(connectionString: string): Promise { From b919ad8d5fa0d283dd34d9708de6852f937551da Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Wed, 6 Aug 2025 17:13:54 -0500 Subject: [PATCH 102/142] fix --- src/global.test.ts | 4 +-- src/utils/sql/setupSql.ts | 72 +++++++++------------------------------ 2 files changed, 18 insertions(+), 58 deletions(-) diff --git a/src/global.test.ts b/src/global.test.ts index b1da4ad2..18f4b9fe 100644 --- a/src/global.test.ts +++ b/src/global.test.ts @@ -18,7 +18,7 @@ import { import { setupCosmosDB } from './utils/cosmosdb/setupCosmosDB'; import { delay } from './utils/delay'; import findProcess = require('find-process'); -// import { runSqlSetupQueries } from './utils/sql/setupSql'; +import { runSqlSetupQueries } from './utils/sql/setupSql'; let perTestFuncOutput = ''; let fullFuncOutput = ''; @@ -45,7 +45,7 @@ before(async function (this: Mocha.Context): Promise { await setupCosmosDB(); - // await runSqlSetupQueries(); + await runSqlSetupQueries(); isOldConfig = getOldConfigArg(); const appPath = isOldConfig diff --git a/src/utils/sql/setupSql.ts b/src/utils/sql/setupSql.ts index 0a39b9c6..6871babe 100644 --- a/src/utils/sql/setupSql.ts +++ b/src/utils/sql/setupSql.ts @@ -6,66 +6,26 @@ import * as sql from 'mssql'; import { sqlConnectionString } from '../connectionStrings'; import { Sql } from '../../constants'; -export async function createPoolConnnection(): Promise { - // const password = process.env.SA_PASSWORD; - // if (!password || password.trim() === '') { - // throw new Error('Missing required environment variable: SA_PASSWORD'); - // } - - // const config = { - // user: 'sa', - // password: password, - // server: 'localhost', - // port: 15433, - // database: 'master', - // options: { - // encrypt: false, // set to true if connecting to Azure SQL - // trustServerCertificate: true, - // } - // }; - - if (!sqlConnectionString || sqlConnectionString.trim() === '') { - throw new Error('Missing required environment variable: SqlConnection'); - } - +export async function runSqlSetupQueries() { const poolConnection = await sql.connect(sqlConnectionString); - await poolConnection + try { + await poolConnection .request() .query(`ALTER DATABASE ${Sql.dbName} SET CHANGE_TRACKING = ON (CHANGE_RETENTION = 2 DAYS, AUTO_CLEANUP = ON);`); - for (const table of [Sql.sqlTriggerTable, Sql.sqlNonTriggerTable]) { - await poolConnection - .request() - .query( - `CREATE TABLE dbo.${table} ([id] UNIQUEIDENTIFIER PRIMARY KEY, [testData] NVARCHAR(200) NOT NULL);` - ); - await poolConnection.request().query(`ALTER TABLE dbo.${table} ENABLE CHANGE_TRACKING;`); + for (const table of [Sql.sqlTriggerTable, Sql.sqlNonTriggerTable]) { + await poolConnection + .request() + .query( + `CREATE TABLE dbo.${table} ([id] UNIQUEIDENTIFIER PRIMARY KEY, [testData] NVARCHAR(200) NOT NULL);` + ); + await poolConnection.request().query(`ALTER TABLE dbo.${table} ENABLE CHANGE_TRACKING;`); + } + } finally { + await poolConnection.close(); } - - return poolConnection; } -// export async function createPoolConnnection(connectionString: string): Promise { -// const retries = 5; -// return retry( -// async (currentAttempt: number) => { -// if (currentAttempt > 1) { -// console.log( -// `${new Date().toISOString()}: Retrying sql connect. Attempt ${currentAttempt}/${retries + 1}` -// ); -// } -// return sql.connect(connectionString); -// }, -// { -// retries: retries, -// minTimeout: 5 * 1000, -// onFailedAttempt: (error) => { -// if (!/ip address/i.test(error?.message || '')) { -// throw error; // abort for an unrecognized error -// } else if (error.retriesLeft > 0) { -// console.log(`Warning: Failed to sql connect with error "${error.message}"`); -// } -// }, -// } -// ); -// } +export async function createPoolConnnection() { + return await sql.connect(sqlConnectionString); +} From 38e235c9e80a0c3169514cd17b09ce97600a3c88 Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Wed, 6 Aug 2025 17:38:20 -0500 Subject: [PATCH 103/142] fix --- src/constants.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/constants.ts b/src/constants.ts index 14682503..5cb77749 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -34,10 +34,9 @@ export namespace ServiceBus { } export namespace Sql { - export const dbName = 'e2eTestDB'; + export const dbName = 'master'; export const sqlTriggerTable = 'e2eSqlTriggerTable'; export const sqlNonTriggerTable = 'e2eSqlNonTriggerTable'; - export const sqlSecretName = 'e2eSqlSecret'; } export const defaultTimeout = 3 * 60 * 1000; From 0c04a4859af8320f5fd5fc11885071a491a2815d Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Wed, 6 Aug 2025 21:51:14 -0500 Subject: [PATCH 104/142] fix --- src/global.test.ts | 4 ++-- src/utils/connectionStrings.ts | 2 ++ src/utils/sql/setupSql.ts | 27 ++++++++++++++++++++------- 3 files changed, 24 insertions(+), 9 deletions(-) diff --git a/src/global.test.ts b/src/global.test.ts index 18f4b9fe..136caf00 100644 --- a/src/global.test.ts +++ b/src/global.test.ts @@ -12,7 +12,7 @@ import { eventHubConnectionString, initializeConnectionStrings, serviceBusConnectionString, - sqlConnectionString, + sqlTestConnectionString, storageConnectionString } from './utils/connectionStrings'; import { setupCosmosDB } from './utils/cosmosdb/setupCosmosDB'; @@ -122,7 +122,7 @@ async function startFuncProcess(appPath: string): Promise { [EnvVarNames.cosmosDB]: cosmosDBConnectionString, [EnvVarNames.eventHub]: eventHubConnectionString, [EnvVarNames.serviceBus]: serviceBusConnectionString, - [EnvVarNames.sql]: sqlConnectionString, + [EnvVarNames.sql]: sqlTestConnectionString, WEBSITE_SITE_NAME: 'azure-functions-nodejs-e2e-tests', FUNCTIONS_REQUEST_BODY_SIZE_LIMIT: '4294967296', }, diff --git a/src/utils/connectionStrings.ts b/src/utils/connectionStrings.ts index 23a46e25..1db44455 100644 --- a/src/utils/connectionStrings.ts +++ b/src/utils/connectionStrings.ts @@ -6,6 +6,7 @@ export let cosmosDBConnectionString: string; export let eventHubConnectionString: string; export let serviceBusConnectionString: string; export let sqlConnectionString: string; +export let sqlTestConnectionString: string; export async function initializeConnectionStrings(): Promise { const password = process.env.SA_PASSWORD; @@ -17,4 +18,5 @@ export async function initializeConnectionStrings(): Promise { cosmosDBConnectionString = "AccountEndpoint=http://localhost:8081/;AccountKey=C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw=="; serviceBusConnectionString = eventHubConnectionString = "Endpoint=sb://localhost;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=SAS_KEY_VALUE;UseDevelopmentEmulator=true;"; sqlConnectionString = `Server=localhost,15433;Database=master;User Id=sa;Password=${password};Encrypt=false;TrustServerCertificate=true;`; + sqlTestConnectionString = `Server=localhost,15433;Database=DB;User Id=sa;Password=${password};Encrypt=false;TrustServerCertificate=true;`; } diff --git a/src/utils/sql/setupSql.ts b/src/utils/sql/setupSql.ts index 6871babe..7d0f35fe 100644 --- a/src/utils/sql/setupSql.ts +++ b/src/utils/sql/setupSql.ts @@ -3,29 +3,42 @@ // import mysql from 'mysql2/promise'; import * as sql from 'mssql'; -import { sqlConnectionString } from '../connectionStrings'; +import { sqlConnectionString, sqlTestConnectionString } from '../connectionStrings'; import { Sql } from '../../constants'; export async function runSqlSetupQueries() { - const poolConnection = await sql.connect(sqlConnectionString); + let pool = await sql.connect(sqlConnectionString); try { - await poolConnection + await pool + .request() + .query(`IF NOT EXISTS (SELECT name FROM sys.databases WHERE name = '${Sql.dbName}') + BEGIN + CREATE DATABASE [${Sql.dbName}]; + END`); + } finally { + await pool.close(); + } + + pool = await sql.connect(sqlTestConnectionString); + + try { + await pool .request() .query(`ALTER DATABASE ${Sql.dbName} SET CHANGE_TRACKING = ON (CHANGE_RETENTION = 2 DAYS, AUTO_CLEANUP = ON);`); for (const table of [Sql.sqlTriggerTable, Sql.sqlNonTriggerTable]) { - await poolConnection + await pool .request() .query( `CREATE TABLE dbo.${table} ([id] UNIQUEIDENTIFIER PRIMARY KEY, [testData] NVARCHAR(200) NOT NULL);` ); - await poolConnection.request().query(`ALTER TABLE dbo.${table} ENABLE CHANGE_TRACKING;`); + await pool.request().query(`ALTER TABLE dbo.${table} ENABLE CHANGE_TRACKING;`); } } finally { - await poolConnection.close(); + await pool.close(); } } export async function createPoolConnnection() { - return await sql.connect(sqlConnectionString); + return await sql.connect(sqlTestConnectionString); } From 952e26e04f1beeab1f5aa8109db88d81984f49b5 Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Wed, 6 Aug 2025 23:19:49 -0500 Subject: [PATCH 105/142] fix --- src/constants.ts | 2 +- src/utils/connectionStrings.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/constants.ts b/src/constants.ts index 5cb77749..88fe114d 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -34,7 +34,7 @@ export namespace ServiceBus { } export namespace Sql { - export const dbName = 'master'; + export const dbName = 'e2eTestDB'; export const sqlTriggerTable = 'e2eSqlTriggerTable'; export const sqlNonTriggerTable = 'e2eSqlNonTriggerTable'; } diff --git a/src/utils/connectionStrings.ts b/src/utils/connectionStrings.ts index 1db44455..466ab42e 100644 --- a/src/utils/connectionStrings.ts +++ b/src/utils/connectionStrings.ts @@ -18,5 +18,5 @@ export async function initializeConnectionStrings(): Promise { cosmosDBConnectionString = "AccountEndpoint=http://localhost:8081/;AccountKey=C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw=="; serviceBusConnectionString = eventHubConnectionString = "Endpoint=sb://localhost;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=SAS_KEY_VALUE;UseDevelopmentEmulator=true;"; sqlConnectionString = `Server=localhost,15433;Database=master;User Id=sa;Password=${password};Encrypt=false;TrustServerCertificate=true;`; - sqlTestConnectionString = `Server=localhost,15433;Database=DB;User Id=sa;Password=${password};Encrypt=false;TrustServerCertificate=true;`; + sqlTestConnectionString = `Server=localhost,15433;Database=e2eTestDB;User Id=sa;Password=${password};Encrypt=false;TrustServerCertificate=true;`; } From d9eb43734dd4a006b996480d875469dd62bcd885 Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Wed, 6 Aug 2025 23:38:49 -0500 Subject: [PATCH 106/142] fix --- src/utils/sql/setupSql.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/utils/sql/setupSql.ts b/src/utils/sql/setupSql.ts index 7d0f35fe..4ce5ee9b 100644 --- a/src/utils/sql/setupSql.ts +++ b/src/utils/sql/setupSql.ts @@ -15,6 +15,9 @@ export async function runSqlSetupQueries() { BEGIN CREATE DATABASE [${Sql.dbName}]; END`); + await pool + .request() + .query(`ALTER DATABASE ${Sql.dbName} SET CHANGE_TRACKING = ON (CHANGE_RETENTION = 2 DAYS, AUTO_CLEANUP = ON);`); } finally { await pool.close(); } @@ -22,10 +25,6 @@ export async function runSqlSetupQueries() { pool = await sql.connect(sqlTestConnectionString); try { - await pool - .request() - .query(`ALTER DATABASE ${Sql.dbName} SET CHANGE_TRACKING = ON (CHANGE_RETENTION = 2 DAYS, AUTO_CLEANUP = ON);`); - for (const table of [Sql.sqlTriggerTable, Sql.sqlNonTriggerTable]) { await pool .request() From 58020868f15517f6e552291f459a0c5e73b4d5cf Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Wed, 6 Aug 2025 23:55:23 -0500 Subject: [PATCH 107/142] fix --- src/utils/sql/setupSql.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/utils/sql/setupSql.ts b/src/utils/sql/setupSql.ts index 4ce5ee9b..7e3cf80c 100644 --- a/src/utils/sql/setupSql.ts +++ b/src/utils/sql/setupSql.ts @@ -15,9 +15,9 @@ export async function runSqlSetupQueries() { BEGIN CREATE DATABASE [${Sql.dbName}]; END`); - await pool - .request() - .query(`ALTER DATABASE ${Sql.dbName} SET CHANGE_TRACKING = ON (CHANGE_RETENTION = 2 DAYS, AUTO_CLEANUP = ON);`); + // await pool + // .request() + // .query(`ALTER DATABASE ${Sql.dbName} SET CHANGE_TRACKING = ON (CHANGE_RETENTION = 2 DAYS, AUTO_CLEANUP = ON);`); } finally { await pool.close(); } @@ -31,7 +31,7 @@ export async function runSqlSetupQueries() { .query( `CREATE TABLE dbo.${table} ([id] UNIQUEIDENTIFIER PRIMARY KEY, [testData] NVARCHAR(200) NOT NULL);` ); - await pool.request().query(`ALTER TABLE dbo.${table} ENABLE CHANGE_TRACKING;`); + // await pool.request().query(`ALTER TABLE dbo.${table} ENABLE CHANGE_TRACKING;`); } } finally { await pool.close(); From da770d71249362a2bc99c8c9d3c470bd798104aa Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Thu, 7 Aug 2025 00:14:06 -0500 Subject: [PATCH 108/142] fix --- .../templates/test-node-version.yml | 34 +++++++++---------- src/global.test.ts | 4 --- src/sql.test.ts | 3 +- 3 files changed, 19 insertions(+), 22 deletions(-) diff --git a/azure-pipelines/templates/test-node-version.yml b/azure-pipelines/templates/test-node-version.yml index 3d809020..ec1fb952 100644 --- a/azure-pipelines/templates/test-node-version.yml +++ b/azure-pipelines/templates/test-node-version.yml @@ -30,23 +30,23 @@ steps: env: SA_PASSWORD: $(AzureWebJobsSQLPassword) displayName: "Debug SQL Password" - - bash: | - docker compose -f src/utils/servicebus/docker-compose.yml pull - docker compose -f src/utils/servicebus/docker-compose.yml up -d - env: - AzureWebJobsSQLPassword: $(AzureWebJobsSQLPassword) - displayName: 'Start ServiceBus Emulator' - - bash: npm run testServiceBus - env: - SA_PASSWORD: $(AzureWebJobsSQLPassword) - displayName: 'Run ServiceBus tests Node ${{ parameters.nodeVersion }}' - continueOnError: true - - bash: | - docker stop servicebus-emulator || true - docker rm -f servicebus-emulator || true - docker compose -f src/utils/eventhub/docker-compose.yml pull - docker compose -f src/utils/eventhub/docker-compose.yml up -d - displayName: 'Stop ServiceBus Emulator and Start EventHub Emulator' + # - bash: | + # docker compose -f src/utils/servicebus/docker-compose.yml pull + # docker compose -f src/utils/servicebus/docker-compose.yml up -d + # env: + # AzureWebJobsSQLPassword: $(AzureWebJobsSQLPassword) + # displayName: 'Start ServiceBus Emulator' + # - bash: npm run testServiceBus + # env: + # SA_PASSWORD: $(AzureWebJobsSQLPassword) + # displayName: 'Run ServiceBus tests Node ${{ parameters.nodeVersion }}' + # continueOnError: true + # - bash: | + # docker stop servicebus-emulator || true + # docker rm -f servicebus-emulator || true + # docker compose -f src/utils/eventhub/docker-compose.yml pull + # docker compose -f src/utils/eventhub/docker-compose.yml up -d + # displayName: 'Stop ServiceBus Emulator and Start EventHub Emulator' - bash: npm run testAllExceptServiceBus env: SA_PASSWORD: $(AzureWebJobsSQLPassword) diff --git a/src/global.test.ts b/src/global.test.ts index 136caf00..351d1bdf 100644 --- a/src/global.test.ts +++ b/src/global.test.ts @@ -43,10 +43,6 @@ before(async function (this: Mocha.Context): Promise { await initializeConnectionStrings(); - await setupCosmosDB(); - - await runSqlSetupQueries(); - isOldConfig = getOldConfigArg(); const appPath = isOldConfig ? path.join(__dirname, '..', 'app', combinedFolder, model + oldConfigSuffix) diff --git a/src/sql.test.ts b/src/sql.test.ts index e5f1183c..d498a461 100644 --- a/src/sql.test.ts +++ b/src/sql.test.ts @@ -7,7 +7,7 @@ import { v4 as uuid } from 'uuid'; import { getFuncUrl } from './constants'; import { isOldConfig, waitForOutput } from './global.test'; import { getRandomTestData } from './utils/getRandomTestData'; -import { createPoolConnnection } from './utils/sql/setupSql'; +import { createPoolConnnection, runSqlSetupQueries } from './utils/sql/setupSql'; import { Sql } from './constants'; import { ConnectionPool } from 'mssql'; @@ -18,6 +18,7 @@ describe('sql', () => { this.skip(); } + await runSqlSetupQueries(); poolConnection = await createPoolConnnection(); }); From 63ba4a9182a7ee3ea449b5238d7d5b9dd23c69f0 Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Thu, 7 Aug 2025 00:22:20 -0500 Subject: [PATCH 109/142] fix --- AzuriteConfig | 1 + azure-pipelines/public-build.yml | 10 +++++----- src/global.test.ts | 4 ++-- src/utils/sql/setupSql.ts | 8 ++++---- 4 files changed, 12 insertions(+), 11 deletions(-) create mode 100644 AzuriteConfig diff --git a/AzuriteConfig b/AzuriteConfig new file mode 100644 index 00000000..cd07be9c --- /dev/null +++ b/AzuriteConfig @@ -0,0 +1 @@ +{"instaceID":"996986a5-e616-422f-aaeb-2ca54ea6342a"} \ No newline at end of file diff --git a/azure-pipelines/public-build.yml b/azure-pipelines/public-build.yml index 63eeceed..7fcc9281 100644 --- a/azure-pipelines/public-build.yml +++ b/azure-pipelines/public-build.yml @@ -42,11 +42,11 @@ extends: image: 1es-windows-2022 os: windows - # sdl: - # codeql: - # compiled: - # enabled: true - # runSourceLanguagesInSourceAnalysis: true + sdl: + codeql: + compiled: + enabled: true + runSourceLanguagesInSourceAnalysis: true settings: # PR's from forks do not have sufficient permissions to set tags. diff --git a/src/global.test.ts b/src/global.test.ts index 351d1bdf..401c0e82 100644 --- a/src/global.test.ts +++ b/src/global.test.ts @@ -15,10 +15,10 @@ import { sqlTestConnectionString, storageConnectionString } from './utils/connectionStrings'; -import { setupCosmosDB } from './utils/cosmosdb/setupCosmosDB'; +// import { setupCosmosDB } from './utils/cosmosdb/setupCosmosDB'; import { delay } from './utils/delay'; import findProcess = require('find-process'); -import { runSqlSetupQueries } from './utils/sql/setupSql'; +// import { runSqlSetupQueries } from './utils/sql/setupSql'; let perTestFuncOutput = ''; let fullFuncOutput = ''; diff --git a/src/utils/sql/setupSql.ts b/src/utils/sql/setupSql.ts index 7e3cf80c..4ce5ee9b 100644 --- a/src/utils/sql/setupSql.ts +++ b/src/utils/sql/setupSql.ts @@ -15,9 +15,9 @@ export async function runSqlSetupQueries() { BEGIN CREATE DATABASE [${Sql.dbName}]; END`); - // await pool - // .request() - // .query(`ALTER DATABASE ${Sql.dbName} SET CHANGE_TRACKING = ON (CHANGE_RETENTION = 2 DAYS, AUTO_CLEANUP = ON);`); + await pool + .request() + .query(`ALTER DATABASE ${Sql.dbName} SET CHANGE_TRACKING = ON (CHANGE_RETENTION = 2 DAYS, AUTO_CLEANUP = ON);`); } finally { await pool.close(); } @@ -31,7 +31,7 @@ export async function runSqlSetupQueries() { .query( `CREATE TABLE dbo.${table} ([id] UNIQUEIDENTIFIER PRIMARY KEY, [testData] NVARCHAR(200) NOT NULL);` ); - // await pool.request().query(`ALTER TABLE dbo.${table} ENABLE CHANGE_TRACKING;`); + await pool.request().query(`ALTER TABLE dbo.${table} ENABLE CHANGE_TRACKING;`); } } finally { await pool.close(); From 2465c6de65082ca3669965b8250974d5486119a3 Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Thu, 7 Aug 2025 00:45:25 -0500 Subject: [PATCH 110/142] fix --- .../templates/test-node-version.yml | 54 +++++++++---------- azure-pipelines/templates/test.yml | 12 ++--- src/sql.test.ts | 2 +- src/utils/sql/setupSql.ts | 26 ++++----- 4 files changed, 47 insertions(+), 47 deletions(-) diff --git a/azure-pipelines/templates/test-node-version.yml b/azure-pipelines/templates/test-node-version.yml index ec1fb952..173f5c4e 100644 --- a/azure-pipelines/templates/test-node-version.yml +++ b/azure-pipelines/templates/test-node-version.yml @@ -30,39 +30,39 @@ steps: env: SA_PASSWORD: $(AzureWebJobsSQLPassword) displayName: "Debug SQL Password" - # - bash: | - # docker compose -f src/utils/servicebus/docker-compose.yml pull - # docker compose -f src/utils/servicebus/docker-compose.yml up -d - # env: - # AzureWebJobsSQLPassword: $(AzureWebJobsSQLPassword) - # displayName: 'Start ServiceBus Emulator' - # - bash: npm run testServiceBus - # env: - # SA_PASSWORD: $(AzureWebJobsSQLPassword) - # displayName: 'Run ServiceBus tests Node ${{ parameters.nodeVersion }}' - # continueOnError: true + - bash: | + docker compose -f src/utils/servicebus/docker-compose.yml pull + docker compose -f src/utils/servicebus/docker-compose.yml up -d + env: + AzureWebJobsSQLPassword: $(AzureWebJobsSQLPassword) + displayName: 'Start ServiceBus Emulator' + - bash: npm run testServiceBus + env: + SA_PASSWORD: $(AzureWebJobsSQLPassword) + displayName: 'Run ServiceBus tests Node ${{ parameters.nodeVersion }}' + continueOnError: true # - bash: | # docker stop servicebus-emulator || true # docker rm -f servicebus-emulator || true # docker compose -f src/utils/eventhub/docker-compose.yml pull # docker compose -f src/utils/eventhub/docker-compose.yml up -d # displayName: 'Stop ServiceBus Emulator and Start EventHub Emulator' - - bash: npm run testAllExceptServiceBus - env: - SA_PASSWORD: $(AzureWebJobsSQLPassword) - displayName: 'Run remaining tests Node ${{ parameters.nodeVersion }}' - continueOnError: true + # - bash: npm run testAllExceptServiceBus + # env: + # SA_PASSWORD: $(AzureWebJobsSQLPassword) + # displayName: 'Run remaining tests Node ${{ parameters.nodeVersion }}' + # continueOnError: true - bash: | docker logs mssql displayName: 'SQL logs' - - bash: npm run testOldConfig - displayName: 'Run oldConfig tests Node ${{ parameters.nodeVersion }}' - condition: and(succeeded(), eq('${{ parameters.runOldConfig }}', 'true')) - continueOnError: true - - bash: | - docker stop cosmosdb-emulator || true - docker rm -f cosmosdb-emulator || true - docker compose -f src/utils/eventhub/docker-compose.yml down -v - docker compose -f src/utils/servicebus/docker-compose.yml down -v - docker compose -f src/utils/sql/docker-compose.yml down -v - displayName: 'Stop all resources' \ No newline at end of file + # - bash: npm run testOldConfig + # displayName: 'Run oldConfig tests Node ${{ parameters.nodeVersion }}' + # condition: and(succeeded(), eq('${{ parameters.runOldConfig }}', 'true')) + # continueOnError: true + # - bash: | + # docker stop cosmosdb-emulator || true + # docker rm -f cosmosdb-emulator || true + # docker compose -f src/utils/eventhub/docker-compose.yml down -v + # docker compose -f src/utils/servicebus/docker-compose.yml down -v + # docker compose -f src/utils/sql/docker-compose.yml down -v + # displayName: 'Stop all resources' \ No newline at end of file diff --git a/azure-pipelines/templates/test.yml b/azure-pipelines/templates/test.yml index 14cb21c1..9eed1b4c 100644 --- a/azure-pipelines/templates/test.yml +++ b/azure-pipelines/templates/test.yml @@ -22,13 +22,13 @@ jobs: nodeVersion: 18.x runOldConfig: true - - template: /azure-pipelines/templates/test-node-version.yml@self - parameters: - nodeVersion: 20.x + # - template: /azure-pipelines/templates/test-node-version.yml@self + # parameters: + # nodeVersion: 20.x - - template: /azure-pipelines/templates/test-node-version.yml@self - parameters: - nodeVersion: 22.x + # - template: /azure-pipelines/templates/test-node-version.yml@self + # parameters: + # nodeVersion: 22.x - task: PublishTestResults@2 displayName: 'Publish Unit Test Results' diff --git a/src/sql.test.ts b/src/sql.test.ts index d498a461..06ba8830 100644 --- a/src/sql.test.ts +++ b/src/sql.test.ts @@ -19,7 +19,7 @@ describe('sql', () => { } await runSqlSetupQueries(); - poolConnection = await createPoolConnnection(); + throw new Error("Did it reach"); }); after(async () => { diff --git a/src/utils/sql/setupSql.ts b/src/utils/sql/setupSql.ts index 4ce5ee9b..b31b82a8 100644 --- a/src/utils/sql/setupSql.ts +++ b/src/utils/sql/setupSql.ts @@ -22,20 +22,20 @@ export async function runSqlSetupQueries() { await pool.close(); } - pool = await sql.connect(sqlTestConnectionString); + // pool = await sql.connect(sqlTestConnectionString); - try { - for (const table of [Sql.sqlTriggerTable, Sql.sqlNonTriggerTable]) { - await pool - .request() - .query( - `CREATE TABLE dbo.${table} ([id] UNIQUEIDENTIFIER PRIMARY KEY, [testData] NVARCHAR(200) NOT NULL);` - ); - await pool.request().query(`ALTER TABLE dbo.${table} ENABLE CHANGE_TRACKING;`); - } - } finally { - await pool.close(); - } + // try { + // for (const table of [Sql.sqlTriggerTable, Sql.sqlNonTriggerTable]) { + // await pool + // .request() + // .query( + // `CREATE TABLE dbo.${table} ([id] UNIQUEIDENTIFIER PRIMARY KEY, [testData] NVARCHAR(200) NOT NULL);` + // ); + // await pool.request().query(`ALTER TABLE dbo.${table} ENABLE CHANGE_TRACKING;`); + // } + // } finally { + // await pool.close(); + // } } export async function createPoolConnnection() { From a8f29f2589081757b61402889f2b90ea432218d0 Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Thu, 7 Aug 2025 00:52:28 -0500 Subject: [PATCH 111/142] fix --- src/sql.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sql.test.ts b/src/sql.test.ts index 06ba8830..02b09f1b 100644 --- a/src/sql.test.ts +++ b/src/sql.test.ts @@ -7,7 +7,7 @@ import { v4 as uuid } from 'uuid'; import { getFuncUrl } from './constants'; import { isOldConfig, waitForOutput } from './global.test'; import { getRandomTestData } from './utils/getRandomTestData'; -import { createPoolConnnection, runSqlSetupQueries } from './utils/sql/setupSql'; +import { runSqlSetupQueries } from './utils/sql/setupSql'; import { Sql } from './constants'; import { ConnectionPool } from 'mssql'; From 6543a620dacdf8baf693b413a72fb0aee1bfb771 Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Thu, 7 Aug 2025 01:14:02 -0500 Subject: [PATCH 112/142] fix --- src/global.test.ts | 4 +++- src/sql.test.ts | 3 --- src/utils/sql/docker-compose.yml | 2 -- src/utils/sql/setupSql.ts | 33 ++++++++++++++++++++++++++------ 4 files changed, 30 insertions(+), 12 deletions(-) diff --git a/src/global.test.ts b/src/global.test.ts index 401c0e82..0987f1aa 100644 --- a/src/global.test.ts +++ b/src/global.test.ts @@ -18,7 +18,7 @@ import { // import { setupCosmosDB } from './utils/cosmosdb/setupCosmosDB'; import { delay } from './utils/delay'; import findProcess = require('find-process'); -// import { runSqlSetupQueries } from './utils/sql/setupSql'; +import { runSqlSetupQueries } from './utils/sql/setupSql'; let perTestFuncOutput = ''; let fullFuncOutput = ''; @@ -43,6 +43,8 @@ before(async function (this: Mocha.Context): Promise { await initializeConnectionStrings(); + await runSqlSetupQueries(); + isOldConfig = getOldConfigArg(); const appPath = isOldConfig ? path.join(__dirname, '..', 'app', combinedFolder, model + oldConfigSuffix) diff --git a/src/sql.test.ts b/src/sql.test.ts index 02b09f1b..85e2fb57 100644 --- a/src/sql.test.ts +++ b/src/sql.test.ts @@ -17,9 +17,6 @@ describe('sql', () => { if (isOldConfig) { this.skip(); } - - await runSqlSetupQueries(); - throw new Error("Did it reach"); }); after(async () => { diff --git a/src/utils/sql/docker-compose.yml b/src/utils/sql/docker-compose.yml index cc672e3a..5d12463d 100644 --- a/src/utils/sql/docker-compose.yml +++ b/src/utils/sql/docker-compose.yml @@ -1,5 +1,3 @@ -version: '3.9' - services: mssql: image: mcr.microsoft.com/mssql/server:2022-latest diff --git a/src/utils/sql/setupSql.ts b/src/utils/sql/setupSql.ts index b31b82a8..bc54e074 100644 --- a/src/utils/sql/setupSql.ts +++ b/src/utils/sql/setupSql.ts @@ -1,13 +1,13 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT License. -// import mysql from 'mysql2/promise'; import * as sql from 'mssql'; -import { sqlConnectionString, sqlTestConnectionString } from '../connectionStrings'; +import retry from 'p-retry'; +import { sqlConnectionString } from '../connectionStrings'; import { Sql } from '../../constants'; export async function runSqlSetupQueries() { - let pool = await sql.connect(sqlConnectionString); + let pool = await createPoolConnnection(sqlConnectionString); try { await pool .request() @@ -38,6 +38,27 @@ export async function runSqlSetupQueries() { // } } -export async function createPoolConnnection() { - return await sql.connect(sqlTestConnectionString); -} +async function createPoolConnnection(connectionString: string): Promise { + const retries = 5; + return retry( + async (currentAttempt: number) => { + if (currentAttempt > 1) { + console.log( + `${new Date().toISOString()}: Retrying sql connect. Attempt ${currentAttempt}/${retries + 1}` + ); + } + return sql.connect(connectionString); + }, + { + retries: retries, + minTimeout: 5 * 1000, + onFailedAttempt: (error) => { + if (!/ip address/i.test(error?.message || '')) { + throw error; // abort for an unrecognized error + } else if (error.retriesLeft > 0) { + console.log(`Warning: Failed to sql connect with error "${error.message}"`); + } + }, + } + ); +} \ No newline at end of file From 08f5796f8c4c89f3eb123b57c9d8c5a15e8f2505 Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Thu, 7 Aug 2025 01:25:21 -0500 Subject: [PATCH 113/142] fix --- src/sql.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sql.test.ts b/src/sql.test.ts index 85e2fb57..7054ce6f 100644 --- a/src/sql.test.ts +++ b/src/sql.test.ts @@ -7,7 +7,7 @@ import { v4 as uuid } from 'uuid'; import { getFuncUrl } from './constants'; import { isOldConfig, waitForOutput } from './global.test'; import { getRandomTestData } from './utils/getRandomTestData'; -import { runSqlSetupQueries } from './utils/sql/setupSql'; +// import { runSqlSetupQueries } from './utils/sql/setupSql'; import { Sql } from './constants'; import { ConnectionPool } from 'mssql'; From c23fba9661e075fdd0bc42c52edd7ce5394963ca Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Thu, 7 Aug 2025 01:36:24 -0500 Subject: [PATCH 114/142] fix --- src/sql.test.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/sql.test.ts b/src/sql.test.ts index 7054ce6f..395595be 100644 --- a/src/sql.test.ts +++ b/src/sql.test.ts @@ -4,11 +4,9 @@ import { expect } from 'chai'; import { default as fetch } from 'node-fetch'; import { v4 as uuid } from 'uuid'; -import { getFuncUrl } from './constants'; +import { Sql, getFuncUrl } from './constants'; import { isOldConfig, waitForOutput } from './global.test'; import { getRandomTestData } from './utils/getRandomTestData'; -// import { runSqlSetupQueries } from './utils/sql/setupSql'; -import { Sql } from './constants'; import { ConnectionPool } from 'mssql'; describe('sql', () => { From a3570e50e25449e3914c131114e1aeebe18bfb0b Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Thu, 7 Aug 2025 02:18:14 -0500 Subject: [PATCH 115/142] fix --- src/utils/sql/setupSql.ts | 61 ++++++++++++++++++++++++++++++++------- 1 file changed, 51 insertions(+), 10 deletions(-) diff --git a/src/utils/sql/setupSql.ts b/src/utils/sql/setupSql.ts index bc54e074..d1d4364d 100644 --- a/src/utils/sql/setupSql.ts +++ b/src/utils/sql/setupSql.ts @@ -3,21 +3,62 @@ import * as sql from 'mssql'; import retry from 'p-retry'; -import { sqlConnectionString } from '../connectionStrings'; +import { sqlConnectionString, sqlTestConnectionString } from '../connectionStrings'; import { Sql } from '../../constants'; export async function runSqlSetupQueries() { + // STEP 1: Create DB if not exists let pool = await createPoolConnnection(sqlConnectionString); try { - await pool - .request() - .query(`IF NOT EXISTS (SELECT name FROM sys.databases WHERE name = '${Sql.dbName}') - BEGIN - CREATE DATABASE [${Sql.dbName}]; - END`); - await pool - .request() - .query(`ALTER DATABASE ${Sql.dbName} SET CHANGE_TRACKING = ON (CHANGE_RETENTION = 2 DAYS, AUTO_CLEANUP = ON);`); + await pool.request().query(` + IF NOT EXISTS (SELECT name FROM sys.databases WHERE name = '${Sql.dbName}') + BEGIN + CREATE DATABASE [${Sql.dbName}]; + END + `); + } finally { + await pool.close(); + } + + // STEP 2: Retry ALTER DATABASE (change_tracking) + pool = await createPoolConnnection(sqlConnectionString); + try { + await retry(async (currentAttempt) => { + if (currentAttempt > 1) { + console.log( + `${new Date().toISOString()}: Retrying ALTER DATABASE. Attempt ${currentAttempt}` + ); + } + await pool.request().query(` + ALTER DATABASE [${Sql.dbName}] + SET CHANGE_TRACKING = ON (CHANGE_RETENTION = 2 DAYS, AUTO_CLEANUP = ON); + `); + }, { + retries: 5, + minTimeout: 5000 + }); + } catch (err) { + console.error("ALTER DATABASE failed:", err); + throw err; + } finally { + await pool.close(); + } + + // STEP 3: Create tables and enable tracking + pool = await createPoolConnnection(sqlTestConnectionString); + try { + for (const table of [Sql.sqlTriggerTable, Sql.sqlNonTriggerTable]) { + await pool.request().query(` + IF OBJECT_ID('dbo.${table}', 'U') IS NULL + BEGIN + CREATE TABLE dbo.${table} ( + id UNIQUEIDENTIFIER PRIMARY KEY, + testData NVARCHAR(200) NOT NULL + ); + ALTER TABLE dbo.${table} ENABLE CHANGE_TRACKING; + END + `); + } } finally { await pool.close(); } From d773c152ec030a1917aca27e23769dee71f597fe Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Thu, 7 Aug 2025 02:46:55 -0500 Subject: [PATCH 116/142] fix --- .../templates/test-node-version.yml | 42 ++++++++++--------- src/global.test.ts | 3 -- src/sql.test.ts | 3 ++ 3 files changed, 26 insertions(+), 22 deletions(-) diff --git a/azure-pipelines/templates/test-node-version.yml b/azure-pipelines/templates/test-node-version.yml index 173f5c4e..1d6e22d7 100644 --- a/azure-pipelines/templates/test-node-version.yml +++ b/azure-pipelines/templates/test-node-version.yml @@ -11,18 +11,36 @@ steps: versionSpec: ${{ parameters.nodeVersion }} displayName: 'Install Node ${{ parameters.nodeVersion }}' retryCountOnTaskFailure: 10 + + - bash: docker compose -f src/utils/servicebus/docker-compose.yml up -d + env: + AzureWebJobsSQLPassword: $(AzureWebJobsSQLPassword) + displayName: 'Start ServiceBus Emulator' + + - bash: npm run testServiceBus + displayName: 'Run ServiceBus tests Node ${{ parameters.nodeVersion }}' + continueOnError: true + + - bash: | + docker stop servicebus-emulator || true + docker rm -f servicebus-emulator || true + docker compose -f src/utils/eventhub/docker-compose.yml up -d + displayName: 'Stop ServiceBus Emulator and Start EventHub Emulator' + - bash: | docker pull mcr.microsoft.com/cosmosdb/linux/azure-cosmos-emulator:vnext-preview docker run --detach --publish 8081:8081 --publish 1234:1234 --name cosmosdb-emulator mcr.microsoft.com/cosmosdb/linux/azure-cosmos-emulator:vnext-preview sleep 30 docker ps displayName: "Start CosmosDB Emulator" + - bash: | docker compose -f src/utils/sql/docker-compose.yml up -d sleep 60 env: SA_PASSWORD: $(AzureWebJobsSQLPassword) displayName: "Start SQL Service" + - bash: | echo "Debugging SA_PASSWORD" echo "Length: ${#SA_PASSWORD}" @@ -30,31 +48,17 @@ steps: env: SA_PASSWORD: $(AzureWebJobsSQLPassword) displayName: "Debug SQL Password" - - bash: | - docker compose -f src/utils/servicebus/docker-compose.yml pull - docker compose -f src/utils/servicebus/docker-compose.yml up -d - env: - AzureWebJobsSQLPassword: $(AzureWebJobsSQLPassword) - displayName: 'Start ServiceBus Emulator' - - bash: npm run testServiceBus + + - bash: npm run testAllExceptServiceBus env: SA_PASSWORD: $(AzureWebJobsSQLPassword) - displayName: 'Run ServiceBus tests Node ${{ parameters.nodeVersion }}' + displayName: 'Run remaining tests Node ${{ parameters.nodeVersion }}' continueOnError: true - # - bash: | - # docker stop servicebus-emulator || true - # docker rm -f servicebus-emulator || true - # docker compose -f src/utils/eventhub/docker-compose.yml pull - # docker compose -f src/utils/eventhub/docker-compose.yml up -d - # displayName: 'Stop ServiceBus Emulator and Start EventHub Emulator' - # - bash: npm run testAllExceptServiceBus - # env: - # SA_PASSWORD: $(AzureWebJobsSQLPassword) - # displayName: 'Run remaining tests Node ${{ parameters.nodeVersion }}' - # continueOnError: true + - bash: | docker logs mssql displayName: 'SQL logs' + # - bash: npm run testOldConfig # displayName: 'Run oldConfig tests Node ${{ parameters.nodeVersion }}' # condition: and(succeeded(), eq('${{ parameters.runOldConfig }}', 'true')) diff --git a/src/global.test.ts b/src/global.test.ts index 0987f1aa..fbd560a0 100644 --- a/src/global.test.ts +++ b/src/global.test.ts @@ -18,7 +18,6 @@ import { // import { setupCosmosDB } from './utils/cosmosdb/setupCosmosDB'; import { delay } from './utils/delay'; import findProcess = require('find-process'); -import { runSqlSetupQueries } from './utils/sql/setupSql'; let perTestFuncOutput = ''; let fullFuncOutput = ''; @@ -43,8 +42,6 @@ before(async function (this: Mocha.Context): Promise { await initializeConnectionStrings(); - await runSqlSetupQueries(); - isOldConfig = getOldConfigArg(); const appPath = isOldConfig ? path.join(__dirname, '..', 'app', combinedFolder, model + oldConfigSuffix) diff --git a/src/sql.test.ts b/src/sql.test.ts index 395595be..fb63636d 100644 --- a/src/sql.test.ts +++ b/src/sql.test.ts @@ -8,6 +8,7 @@ import { Sql, getFuncUrl } from './constants'; import { isOldConfig, waitForOutput } from './global.test'; import { getRandomTestData } from './utils/getRandomTestData'; import { ConnectionPool } from 'mssql'; +import { runSqlSetupQueries } from './utils/sql/setupSql'; describe('sql', () => { let poolConnection: ConnectionPool | undefined; @@ -15,6 +16,8 @@ describe('sql', () => { if (isOldConfig) { this.skip(); } + + await runSqlSetupQueries(); }); after(async () => { From 0f5e30c7b3edb213d580f020cdf13f8fb8cff372 Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Thu, 7 Aug 2025 02:55:05 -0500 Subject: [PATCH 117/142] fix --- AzuriteConfig | 1 - src/utils/connectionStrings.ts | 9 ++------- 2 files changed, 2 insertions(+), 8 deletions(-) delete mode 100644 AzuriteConfig diff --git a/AzuriteConfig b/AzuriteConfig deleted file mode 100644 index cd07be9c..00000000 --- a/AzuriteConfig +++ /dev/null @@ -1 +0,0 @@ -{"instaceID":"996986a5-e616-422f-aaeb-2ca54ea6342a"} \ No newline at end of file diff --git a/src/utils/connectionStrings.ts b/src/utils/connectionStrings.ts index 466ab42e..31b65015 100644 --- a/src/utils/connectionStrings.ts +++ b/src/utils/connectionStrings.ts @@ -9,14 +9,9 @@ export let sqlConnectionString: string; export let sqlTestConnectionString: string; export async function initializeConnectionStrings(): Promise { - const password = process.env.SA_PASSWORD; - if (!password || password.trim() === '') { - throw new Error('Missing required environment variable: SA_PASSWORD'); - } - storageConnectionString = "UseDevelopmentStorage=true"; cosmosDBConnectionString = "AccountEndpoint=http://localhost:8081/;AccountKey=C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw=="; serviceBusConnectionString = eventHubConnectionString = "Endpoint=sb://localhost;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=SAS_KEY_VALUE;UseDevelopmentEmulator=true;"; - sqlConnectionString = `Server=localhost,15433;Database=master;User Id=sa;Password=${password};Encrypt=false;TrustServerCertificate=true;`; - sqlTestConnectionString = `Server=localhost,15433;Database=e2eTestDB;User Id=sa;Password=${password};Encrypt=false;TrustServerCertificate=true;`; + sqlConnectionString = `Server=localhost,15433;Database=master;User Id=sa;Password=${process.env.SA_PASSWORD};Encrypt=false;TrustServerCertificate=true;`; + sqlTestConnectionString = `Server=localhost,15433;Database=e2eTestDB;User Id=sa;Password=${process.env.SA_PASSWORD};Encrypt=false;TrustServerCertificate=true;`; } From 3d33c6c7e2c473c96abb5d37098fa3fedb9e7ffb Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Thu, 7 Aug 2025 03:24:43 -0500 Subject: [PATCH 118/142] fix --- src/getModelArg.ts | 7 +++++++ src/global.test.ts | 3 +++ src/sql.test.ts | 4 +++- src/utils/sql/setupSql.ts | 2 +- 4 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/getModelArg.ts b/src/getModelArg.ts index 7c496e31..5a9f54b1 100644 --- a/src/getModelArg.ts +++ b/src/getModelArg.ts @@ -26,4 +26,11 @@ export function getTestFileFilter(): { only?: string; exclude?: string } { const only = typeof args.only === 'string' ? args.only : undefined; const exclude = typeof args.exclude === 'string' ? args.exclude : undefined; return { only, exclude }; +} + +export function isOnlyRunningServiceBusTests(): boolean { + const args = parseArgs(process.argv.slice(2)); + const only = typeof args.only === 'string' ? args.only : undefined; + + return only === 'serviceBus.test.js'; } \ No newline at end of file diff --git a/src/global.test.ts b/src/global.test.ts index fbd560a0..028c7401 100644 --- a/src/global.test.ts +++ b/src/global.test.ts @@ -18,6 +18,7 @@ import { // import { setupCosmosDB } from './utils/cosmosdb/setupCosmosDB'; import { delay } from './utils/delay'; import findProcess = require('find-process'); +import { setupCosmosDB } from './utils/setupCosmosDB'; let perTestFuncOutput = ''; let fullFuncOutput = ''; @@ -42,6 +43,8 @@ before(async function (this: Mocha.Context): Promise { await initializeConnectionStrings(); + await setupCosmosDB(); + isOldConfig = getOldConfigArg(); const appPath = isOldConfig ? path.join(__dirname, '..', 'app', combinedFolder, model + oldConfigSuffix) diff --git a/src/sql.test.ts b/src/sql.test.ts index fb63636d..c82afe68 100644 --- a/src/sql.test.ts +++ b/src/sql.test.ts @@ -8,7 +8,8 @@ import { Sql, getFuncUrl } from './constants'; import { isOldConfig, waitForOutput } from './global.test'; import { getRandomTestData } from './utils/getRandomTestData'; import { ConnectionPool } from 'mssql'; -import { runSqlSetupQueries } from './utils/sql/setupSql'; +import { createPoolConnnection, runSqlSetupQueries } from './utils/sql/setupSql'; +import { sqlTestConnectionString } from './utils/connectionStrings'; describe('sql', () => { let poolConnection: ConnectionPool | undefined; @@ -18,6 +19,7 @@ describe('sql', () => { } await runSqlSetupQueries(); + poolConnection = await createPoolConnnection(sqlTestConnectionString); }); after(async () => { diff --git a/src/utils/sql/setupSql.ts b/src/utils/sql/setupSql.ts index d1d4364d..6cbca0a6 100644 --- a/src/utils/sql/setupSql.ts +++ b/src/utils/sql/setupSql.ts @@ -79,7 +79,7 @@ export async function runSqlSetupQueries() { // } } -async function createPoolConnnection(connectionString: string): Promise { +export async function createPoolConnnection(connectionString: string): Promise { const retries = 5; return retry( async (currentAttempt: number) => { From 6392604dd6b8538d931a2d26f0c594bf1ff89351 Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Thu, 7 Aug 2025 10:41:44 -0500 Subject: [PATCH 119/142] fix --- azure-pipelines/templates/test-node-version.yml | 14 +++++++------- src/getModelArg.ts | 10 +++++----- src/global.test.ts | 3 +-- src/index.ts | 1 + 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/azure-pipelines/templates/test-node-version.yml b/azure-pipelines/templates/test-node-version.yml index 1d6e22d7..3f9eed90 100644 --- a/azure-pipelines/templates/test-node-version.yml +++ b/azure-pipelines/templates/test-node-version.yml @@ -12,6 +12,13 @@ steps: displayName: 'Install Node ${{ parameters.nodeVersion }}' retryCountOnTaskFailure: 10 + - bash: | + docker pull mcr.microsoft.com/cosmosdb/linux/azure-cosmos-emulator:vnext-preview + docker run --detach --publish 8081:8081 --publish 1234:1234 --name cosmosdb-emulator mcr.microsoft.com/cosmosdb/linux/azure-cosmos-emulator:vnext-preview + sleep 30 + docker ps + displayName: "Start CosmosDB Emulator" + - bash: docker compose -f src/utils/servicebus/docker-compose.yml up -d env: AzureWebJobsSQLPassword: $(AzureWebJobsSQLPassword) @@ -27,13 +34,6 @@ steps: docker compose -f src/utils/eventhub/docker-compose.yml up -d displayName: 'Stop ServiceBus Emulator and Start EventHub Emulator' - - bash: | - docker pull mcr.microsoft.com/cosmosdb/linux/azure-cosmos-emulator:vnext-preview - docker run --detach --publish 8081:8081 --publish 1234:1234 --name cosmosdb-emulator mcr.microsoft.com/cosmosdb/linux/azure-cosmos-emulator:vnext-preview - sleep 30 - docker ps - displayName: "Start CosmosDB Emulator" - - bash: | docker compose -f src/utils/sql/docker-compose.yml up -d sleep 60 diff --git a/src/getModelArg.ts b/src/getModelArg.ts index 5a9f54b1..da5632f4 100644 --- a/src/getModelArg.ts +++ b/src/getModelArg.ts @@ -28,9 +28,9 @@ export function getTestFileFilter(): { only?: string; exclude?: string } { return { only, exclude }; } -export function isOnlyRunningServiceBusTests(): boolean { - const args = parseArgs(process.argv.slice(2)); - const only = typeof args.only === 'string' ? args.only : undefined; +// export function isOnlyRunningServiceBusTests(): boolean { +// const args = parseArgs(process.argv.slice(2)); +// const only = typeof args.only === 'string' ? args.only : undefined; - return only === 'serviceBus.test.js'; -} \ No newline at end of file +// return only === 'serviceBus.test.js'; +// } \ No newline at end of file diff --git a/src/global.test.ts b/src/global.test.ts index 028c7401..6e087cb9 100644 --- a/src/global.test.ts +++ b/src/global.test.ts @@ -6,7 +6,7 @@ import * as fs from 'fs/promises'; import path from 'path'; import semver from 'semver'; import { combinedFolder, defaultTimeout, EnvVarNames, oldConfigSuffix } from './constants'; -import { getModelArg, getOldConfigArg, Model } from './getModelArg'; +import { getModelArg, getOldConfigArg, isOnlyRunningServiceBusTests, Model } from './getModelArg'; import { cosmosDBConnectionString, eventHubConnectionString, @@ -15,7 +15,6 @@ import { sqlTestConnectionString, storageConnectionString } from './utils/connectionStrings'; -// import { setupCosmosDB } from './utils/cosmosdb/setupCosmosDB'; import { delay } from './utils/delay'; import findProcess = require('find-process'); import { setupCosmosDB } from './utils/setupCosmosDB'; diff --git a/src/index.ts b/src/index.ts index e8fde1de..6f721f41 100644 --- a/src/index.ts +++ b/src/index.ts @@ -36,6 +36,7 @@ export async function run(): Promise { } files.forEach((f) => mocha.addFile(path.resolve(__dirname, f))); + mocha.addFile(path.resolve(__dirname, 'global.test.js')); const failures = await new Promise((resolve) => mocha.run(resolve)); if (failures > 0) { From 6c364eb0129c9b09090b386c1b9be15d20984e24 Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Thu, 7 Aug 2025 10:41:58 -0500 Subject: [PATCH 120/142] fix --- src/global.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/global.test.ts b/src/global.test.ts index 6e087cb9..4f975192 100644 --- a/src/global.test.ts +++ b/src/global.test.ts @@ -6,7 +6,7 @@ import * as fs from 'fs/promises'; import path from 'path'; import semver from 'semver'; import { combinedFolder, defaultTimeout, EnvVarNames, oldConfigSuffix } from './constants'; -import { getModelArg, getOldConfigArg, isOnlyRunningServiceBusTests, Model } from './getModelArg'; +import { getModelArg, getOldConfigArg, Model } from './getModelArg'; import { cosmosDBConnectionString, eventHubConnectionString, From da566e765b31503d6c753bb092f0fc8a68fd6241 Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Thu, 7 Aug 2025 14:11:39 -0500 Subject: [PATCH 121/142] fix --- src/cosmosDB.test.ts | 2 +- src/global.test.ts | 2 -- src/index.ts | 5 ++++- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/cosmosDB.test.ts b/src/cosmosDB.test.ts index 519a5fef..8fad9551 100644 --- a/src/cosmosDB.test.ts +++ b/src/cosmosDB.test.ts @@ -11,7 +11,7 @@ import { getRandomTestData } from './utils/getRandomTestData'; import { setupCosmosDB } from './utils/setupCosmosDB'; describe('cosmosDB', () => { - before(async () => { + before(async function (this: Mocha.Context) { await setupCosmosDB(); }); diff --git a/src/global.test.ts b/src/global.test.ts index 4f975192..a8c38a3a 100644 --- a/src/global.test.ts +++ b/src/global.test.ts @@ -42,8 +42,6 @@ before(async function (this: Mocha.Context): Promise { await initializeConnectionStrings(); - await setupCosmosDB(); - isOldConfig = getOldConfigArg(); const appPath = isOldConfig ? path.join(__dirname, '..', 'app', combinedFolder, model + oldConfigSuffix) diff --git a/src/index.ts b/src/index.ts index 6f721f41..487923aa 100644 --- a/src/index.ts +++ b/src/index.ts @@ -27,6 +27,9 @@ export async function run(): Promise { const mocha = new Mocha(options); + const globalTestPath = path.resolve(__dirname, 'global.test.js'); + mocha.addFile(globalTestPath); + let files: string[] = await globby('**/*.test.js', { cwd: __dirname }); const { only, exclude } = getTestFileFilter(); if (only) { @@ -35,8 +38,8 @@ export async function run(): Promise { files = files.filter(f => !f.endsWith(exclude)); } + files = files.filter(f => path.resolve(__dirname, f) !== globalTestPath); files.forEach((f) => mocha.addFile(path.resolve(__dirname, f))); - mocha.addFile(path.resolve(__dirname, 'global.test.js')); const failures = await new Promise((resolve) => mocha.run(resolve)); if (failures > 0) { From 3f97cd29ada7efa6c6e5a9a100eccdf9456ebc45 Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Thu, 7 Aug 2025 14:20:42 -0500 Subject: [PATCH 122/142] fix --- src/global.test.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/global.test.ts b/src/global.test.ts index a8c38a3a..93f6e773 100644 --- a/src/global.test.ts +++ b/src/global.test.ts @@ -17,7 +17,6 @@ import { } from './utils/connectionStrings'; import { delay } from './utils/delay'; import findProcess = require('find-process'); -import { setupCosmosDB } from './utils/setupCosmosDB'; let perTestFuncOutput = ''; let fullFuncOutput = ''; From 997bb8200172bd444b04eeee635ee3e1bae342f4 Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Thu, 7 Aug 2025 15:04:00 -0500 Subject: [PATCH 123/142] fix --- src/cosmosDB.test.ts | 5 ----- src/global.test.ts | 3 +++ 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/cosmosDB.test.ts b/src/cosmosDB.test.ts index 8fad9551..33572a25 100644 --- a/src/cosmosDB.test.ts +++ b/src/cosmosDB.test.ts @@ -8,13 +8,8 @@ import { getFuncUrl, CosmosDB } from './constants'; import { waitForOutput } from './global.test'; import { cosmosDBConnectionString } from './utils/connectionStrings'; import { getRandomTestData } from './utils/getRandomTestData'; -import { setupCosmosDB } from './utils/setupCosmosDB'; describe('cosmosDB', () => { - before(async function (this: Mocha.Context) { - await setupCosmosDB(); - }); - it('trigger, output, input', async () => { const client = new CosmosClient(cosmosDBConnectionString); const container = client.database(CosmosDB.dbName).container(CosmosDB.triggerAndOutputContainerName); diff --git a/src/global.test.ts b/src/global.test.ts index 93f6e773..4f975192 100644 --- a/src/global.test.ts +++ b/src/global.test.ts @@ -17,6 +17,7 @@ import { } from './utils/connectionStrings'; import { delay } from './utils/delay'; import findProcess = require('find-process'); +import { setupCosmosDB } from './utils/setupCosmosDB'; let perTestFuncOutput = ''; let fullFuncOutput = ''; @@ -41,6 +42,8 @@ before(async function (this: Mocha.Context): Promise { await initializeConnectionStrings(); + await setupCosmosDB(); + isOldConfig = getOldConfigArg(); const appPath = isOldConfig ? path.join(__dirname, '..', 'app', combinedFolder, model + oldConfigSuffix) From ebebdce75104067ccc17af29d353ee7752280458 Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Thu, 7 Aug 2025 15:25:58 -0500 Subject: [PATCH 124/142] fix --- azure-pipelines/templates/test-node-version.yml | 14 +++++++------- src/cosmosDB.test.ts | 5 +++++ src/global.test.ts | 3 --- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/azure-pipelines/templates/test-node-version.yml b/azure-pipelines/templates/test-node-version.yml index 3f9eed90..72caa934 100644 --- a/azure-pipelines/templates/test-node-version.yml +++ b/azure-pipelines/templates/test-node-version.yml @@ -12,13 +12,6 @@ steps: displayName: 'Install Node ${{ parameters.nodeVersion }}' retryCountOnTaskFailure: 10 - - bash: | - docker pull mcr.microsoft.com/cosmosdb/linux/azure-cosmos-emulator:vnext-preview - docker run --detach --publish 8081:8081 --publish 1234:1234 --name cosmosdb-emulator mcr.microsoft.com/cosmosdb/linux/azure-cosmos-emulator:vnext-preview - sleep 30 - docker ps - displayName: "Start CosmosDB Emulator" - - bash: docker compose -f src/utils/servicebus/docker-compose.yml up -d env: AzureWebJobsSQLPassword: $(AzureWebJobsSQLPassword) @@ -49,6 +42,13 @@ steps: SA_PASSWORD: $(AzureWebJobsSQLPassword) displayName: "Debug SQL Password" + - bash: | + docker pull mcr.microsoft.com/cosmosdb/linux/azure-cosmos-emulator:vnext-preview + docker run --detach --publish 8081:8081 --publish 1234:1234 --name cosmosdb-emulator mcr.microsoft.com/cosmosdb/linux/azure-cosmos-emulator:vnext-preview + sleep 30 + docker ps + displayName: "Start CosmosDB Emulator" + - bash: npm run testAllExceptServiceBus env: SA_PASSWORD: $(AzureWebJobsSQLPassword) diff --git a/src/cosmosDB.test.ts b/src/cosmosDB.test.ts index 33572a25..8fad9551 100644 --- a/src/cosmosDB.test.ts +++ b/src/cosmosDB.test.ts @@ -8,8 +8,13 @@ import { getFuncUrl, CosmosDB } from './constants'; import { waitForOutput } from './global.test'; import { cosmosDBConnectionString } from './utils/connectionStrings'; import { getRandomTestData } from './utils/getRandomTestData'; +import { setupCosmosDB } from './utils/setupCosmosDB'; describe('cosmosDB', () => { + before(async function (this: Mocha.Context) { + await setupCosmosDB(); + }); + it('trigger, output, input', async () => { const client = new CosmosClient(cosmosDBConnectionString); const container = client.database(CosmosDB.dbName).container(CosmosDB.triggerAndOutputContainerName); diff --git a/src/global.test.ts b/src/global.test.ts index 4f975192..93f6e773 100644 --- a/src/global.test.ts +++ b/src/global.test.ts @@ -17,7 +17,6 @@ import { } from './utils/connectionStrings'; import { delay } from './utils/delay'; import findProcess = require('find-process'); -import { setupCosmosDB } from './utils/setupCosmosDB'; let perTestFuncOutput = ''; let fullFuncOutput = ''; @@ -42,8 +41,6 @@ before(async function (this: Mocha.Context): Promise { await initializeConnectionStrings(); - await setupCosmosDB(); - isOldConfig = getOldConfigArg(); const appPath = isOldConfig ? path.join(__dirname, '..', 'app', combinedFolder, model + oldConfigSuffix) From e40f0a8de973e4c082da9ba244420c40290c6fcd Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Thu, 7 Aug 2025 17:34:30 -0500 Subject: [PATCH 125/142] fix --- .../cosmosDBTrigger/function.json | 2 +- .../cosmosDBTriggerAndOutput/function.json | 4 ++-- .../httpTriggerCosmosDBInput/function.json | 2 +- .../httpTriggerCosmosDBOutput/function.json | 2 +- app/v3/cosmosDBTrigger/function.json | 2 +- app/v3/cosmosDBTriggerAndOutput/function.json | 4 ++-- app/v3/httpTriggerCosmosDBInput/function.json | 2 +- .../httpTriggerCosmosDBOutput/function.json | 2 +- .../src/functions/cosmosDBTrigger.ts | 2 +- .../src/functions/cosmosDBTriggerAndOutput.ts | 4 ++-- .../src/functions/httpTriggerCosmosDBInput.ts | 2 +- .../functions/httpTriggerCosmosDBOutput.ts | 2 +- app/v4/src/functions/cosmosDBTrigger.ts | 2 +- .../src/functions/cosmosDBTriggerAndOutput.ts | 4 ++-- .../src/functions/httpTriggerCosmosDBInput.ts | 2 +- .../functions/httpTriggerCosmosDBOutput.ts | 2 +- src/constants.ts | 4 ++-- src/cosmosDB.test.ts | 2 +- src/utils/setupCosmosDB.ts | 24 ------------------- 19 files changed, 23 insertions(+), 47 deletions(-) delete mode 100644 src/utils/setupCosmosDB.ts diff --git a/app/v3-oldConfig/cosmosDBTrigger/function.json b/app/v3-oldConfig/cosmosDBTrigger/function.json index 702e4a80..aa0933fd 100644 --- a/app/v3-oldConfig/cosmosDBTrigger/function.json +++ b/app/v3-oldConfig/cosmosDBTrigger/function.json @@ -6,7 +6,7 @@ "direction": "in", "leaseCollectionName": "leases", "connectionStringSetting": "CosmosDBConnection", - "databaseName": "e2eTestDB", + "databaseName": "e2eTestCosmosDB", "collectionName": "e2eTestContainerTrigger", "createLeaseCollectionIfNotExists": true, "leaseCollectionPrefix": "2" diff --git a/app/v3-oldConfig/cosmosDBTriggerAndOutput/function.json b/app/v3-oldConfig/cosmosDBTriggerAndOutput/function.json index 19be81df..e351d266 100644 --- a/app/v3-oldConfig/cosmosDBTriggerAndOutput/function.json +++ b/app/v3-oldConfig/cosmosDBTriggerAndOutput/function.json @@ -6,7 +6,7 @@ "direction": "in", "leaseCollectionName": "leases", "connectionStringSetting": "CosmosDBConnection", - "databaseName": "e2eTestDB", + "databaseName": "e2eTestCosmosDB", "collectionName": "e2eTestContainerTriggerAndOutput", "createLeaseCollectionIfNotExists": true, "leaseCollectionPrefix": "1" @@ -16,7 +16,7 @@ "name": "$return", "direction": "out", "connectionStringSetting": "CosmosDBConnection", - "databaseName": "e2eTestDB", + "databaseName": "e2eTestCosmosDB", "collectionName": "e2eTestContainerTrigger" } ], diff --git a/app/v3-oldConfig/httpTriggerCosmosDBInput/function.json b/app/v3-oldConfig/httpTriggerCosmosDBInput/function.json index 5f0426c3..58d66595 100644 --- a/app/v3-oldConfig/httpTriggerCosmosDBInput/function.json +++ b/app/v3-oldConfig/httpTriggerCosmosDBInput/function.json @@ -17,7 +17,7 @@ "name": "inputDoc", "direction": "in", "connectionStringSetting": "CosmosDBConnection", - "databaseName": "e2eTestDB", + "databaseName": "e2eTestCosmosDB", "collectionName": "e2eTestContainerTriggerAndOutput", "partitionKey": "testPartKey", "id": "{Query.id}" diff --git a/app/v3-oldConfig/httpTriggerCosmosDBOutput/function.json b/app/v3-oldConfig/httpTriggerCosmosDBOutput/function.json index 9e9aeee4..0d1d8bbd 100644 --- a/app/v3-oldConfig/httpTriggerCosmosDBOutput/function.json +++ b/app/v3-oldConfig/httpTriggerCosmosDBOutput/function.json @@ -17,7 +17,7 @@ "name": "outputDoc", "direction": "out", "connectionStringSetting": "CosmosDBConnection", - "databaseName": "e2eTestDB", + "databaseName": "e2eTestCosmosDB", "collectionName": "e2eTestContainerTriggerAndOutput" } ], diff --git a/app/v3/cosmosDBTrigger/function.json b/app/v3/cosmosDBTrigger/function.json index 02e9d917..97b53e77 100644 --- a/app/v3/cosmosDBTrigger/function.json +++ b/app/v3/cosmosDBTrigger/function.json @@ -6,7 +6,7 @@ "direction": "in", "leaseContainerName": "leases", "connection": "CosmosDBConnection", - "databaseName": "e2eTestDB", + "databaseName": "e2eTestCosmosDB", "containerName": "e2eTestContainerTrigger", "createLeaseContainerIfNotExists": true, "leaseContainerPrefix": "2" diff --git a/app/v3/cosmosDBTriggerAndOutput/function.json b/app/v3/cosmosDBTriggerAndOutput/function.json index 7c9d7487..4ca8ac95 100644 --- a/app/v3/cosmosDBTriggerAndOutput/function.json +++ b/app/v3/cosmosDBTriggerAndOutput/function.json @@ -6,7 +6,7 @@ "direction": "in", "leaseContainerName": "leases", "connection": "CosmosDBConnection", - "databaseName": "e2eTestDB", + "databaseName": "e2eTestCosmosDB", "containerName": "e2eTestContainerTriggerAndOutput", "createLeaseContainerIfNotExists": true, "leaseContainerPrefix": "1" @@ -16,7 +16,7 @@ "name": "$return", "direction": "out", "connection": "CosmosDBConnection", - "databaseName": "e2eTestDB", + "databaseName": "e2eTestCosmosDB", "containerName": "e2eTestContainerTrigger" } ], diff --git a/app/v3/httpTriggerCosmosDBInput/function.json b/app/v3/httpTriggerCosmosDBInput/function.json index fb8d4232..a34f360a 100644 --- a/app/v3/httpTriggerCosmosDBInput/function.json +++ b/app/v3/httpTriggerCosmosDBInput/function.json @@ -17,7 +17,7 @@ "name": "inputDoc", "direction": "in", "connection": "CosmosDBConnection", - "databaseName": "e2eTestDB", + "databaseName": "e2eTestCosmosDB", "containerName": "e2eTestContainerTriggerAndOutput", "partitionKey": "testPartKey", "id": "{Query.id}" diff --git a/app/v3/httpTriggerCosmosDBOutput/function.json b/app/v3/httpTriggerCosmosDBOutput/function.json index fc540372..b2c45cc4 100644 --- a/app/v3/httpTriggerCosmosDBOutput/function.json +++ b/app/v3/httpTriggerCosmosDBOutput/function.json @@ -17,7 +17,7 @@ "name": "outputDoc", "direction": "out", "connection": "CosmosDBConnection", - "databaseName": "e2eTestDB", + "databaseName": "e2eTestCosmosDB", "containerName": "e2eTestContainerTriggerAndOutput" } ], diff --git a/app/v4-oldConfig/src/functions/cosmosDBTrigger.ts b/app/v4-oldConfig/src/functions/cosmosDBTrigger.ts index 3b02a056..24fc610f 100644 --- a/app/v4-oldConfig/src/functions/cosmosDBTrigger.ts +++ b/app/v4-oldConfig/src/functions/cosmosDBTrigger.ts @@ -12,7 +12,7 @@ export async function cosmosDBTrigger(documents: unknown[], context: InvocationC app.cosmosDB('cosmosDBTrigger', { connectionStringSetting: 'CosmosDBConnection', - databaseName: 'e2eTestDB', + databaseName: 'e2eTestCosmosDB', collectionName: 'e2eTestContainerTrigger', createLeaseCollectionIfNotExists: true, leaseCollectionPrefix: '2', diff --git a/app/v4-oldConfig/src/functions/cosmosDBTriggerAndOutput.ts b/app/v4-oldConfig/src/functions/cosmosDBTriggerAndOutput.ts index ab00a27a..954f51cc 100644 --- a/app/v4-oldConfig/src/functions/cosmosDBTriggerAndOutput.ts +++ b/app/v4-oldConfig/src/functions/cosmosDBTriggerAndOutput.ts @@ -13,13 +13,13 @@ export async function cosmosDBTriggerAndOutput(documents: unknown[], context: In app.cosmosDB('cosmosDBTriggerAndOutput', { connectionStringSetting: 'CosmosDBConnection', - databaseName: 'e2eTestDB', + databaseName: 'e2eTestCosmosDB', collectionName: 'e2eTestContainerTriggerAndOutput', createLeaseCollectionIfNotExists: true, leaseCollectionPrefix: '1', return: output.cosmosDB({ connectionStringSetting: 'CosmosDBConnection', - databaseName: 'e2eTestDB', + databaseName: 'e2eTestCosmosDB', collectionName: 'e2eTestContainerTrigger', }), handler: cosmosDBTriggerAndOutput, diff --git a/app/v4-oldConfig/src/functions/httpTriggerCosmosDBInput.ts b/app/v4-oldConfig/src/functions/httpTriggerCosmosDBInput.ts index 88288768..ae50436c 100644 --- a/app/v4-oldConfig/src/functions/httpTriggerCosmosDBInput.ts +++ b/app/v4-oldConfig/src/functions/httpTriggerCosmosDBInput.ts @@ -4,7 +4,7 @@ import { app, HttpRequest, HttpResponseInit, input, InvocationContext } from '@azure/functions'; const cosmosInput = input.cosmosDB({ - databaseName: 'e2eTestDB', + databaseName: 'e2eTestCosmosDB', collectionName: 'e2eTestContainerTriggerAndOutput', id: '{Query.id}', partitionKey: 'testPartKey', diff --git a/app/v4-oldConfig/src/functions/httpTriggerCosmosDBOutput.ts b/app/v4-oldConfig/src/functions/httpTriggerCosmosDBOutput.ts index 2cdfc272..95b24fec 100644 --- a/app/v4-oldConfig/src/functions/httpTriggerCosmosDBOutput.ts +++ b/app/v4-oldConfig/src/functions/httpTriggerCosmosDBOutput.ts @@ -4,7 +4,7 @@ import { HttpRequest, HttpResponseInit, InvocationContext, app, output } from '@azure/functions'; const cosmosOutput = output.cosmosDB({ - databaseName: 'e2eTestDB', + databaseName: 'e2eTestCosmosDB', collectionName: 'e2eTestContainerTrigger', connectionStringSetting: 'CosmosDBConnection', }); diff --git a/app/v4/src/functions/cosmosDBTrigger.ts b/app/v4/src/functions/cosmosDBTrigger.ts index 1f5a5041..7b40a688 100644 --- a/app/v4/src/functions/cosmosDBTrigger.ts +++ b/app/v4/src/functions/cosmosDBTrigger.ts @@ -12,7 +12,7 @@ export async function cosmosDBTrigger(documents: unknown[], context: InvocationC app.cosmosDB('cosmosDBTrigger', { connection: 'CosmosDBConnection', - databaseName: 'e2eTestDB', + databaseName: 'e2eTestCosmosDB', containerName: 'e2eTestContainerTrigger', createLeaseContainerIfNotExists: true, leaseContainerPrefix: '2', diff --git a/app/v4/src/functions/cosmosDBTriggerAndOutput.ts b/app/v4/src/functions/cosmosDBTriggerAndOutput.ts index f658b801..d1d128f6 100644 --- a/app/v4/src/functions/cosmosDBTriggerAndOutput.ts +++ b/app/v4/src/functions/cosmosDBTriggerAndOutput.ts @@ -13,13 +13,13 @@ export async function cosmosDBTriggerAndOutput(documents: unknown[], context: In app.cosmosDB('cosmosDBTriggerAndOutput', { connection: 'CosmosDBConnection', - databaseName: 'e2eTestDB', + databaseName: 'e2eTestCosmosDB', containerName: 'e2eTestContainerTriggerAndOutput', createLeaseContainerIfNotExists: true, leaseContainerPrefix: '1', return: output.cosmosDB({ connection: 'CosmosDBConnection', - databaseName: 'e2eTestDB', + databaseName: 'e2eTestCosmosDB', containerName: 'e2eTestContainerTrigger', }), handler: cosmosDBTriggerAndOutput, diff --git a/app/v4/src/functions/httpTriggerCosmosDBInput.ts b/app/v4/src/functions/httpTriggerCosmosDBInput.ts index acadf06e..255e6553 100644 --- a/app/v4/src/functions/httpTriggerCosmosDBInput.ts +++ b/app/v4/src/functions/httpTriggerCosmosDBInput.ts @@ -4,7 +4,7 @@ import { app, HttpRequest, HttpResponseInit, input, InvocationContext } from '@azure/functions'; const cosmosInput = input.cosmosDB({ - databaseName: 'e2eTestDB', + databaseName: 'e2eTestCosmosDB', containerName: 'e2eTestContainerTriggerAndOutput', id: '{Query.id}', partitionKey: 'testPartKey', diff --git a/app/v4/src/functions/httpTriggerCosmosDBOutput.ts b/app/v4/src/functions/httpTriggerCosmosDBOutput.ts index a4580a97..4d9fc06c 100644 --- a/app/v4/src/functions/httpTriggerCosmosDBOutput.ts +++ b/app/v4/src/functions/httpTriggerCosmosDBOutput.ts @@ -4,7 +4,7 @@ import { app, HttpRequest, HttpResponseInit, InvocationContext, output } from '@azure/functions'; const cosmosOutput = output.cosmosDB({ - databaseName: 'e2eTestDB', + databaseName: 'e2eTestCosmosDB', containerName: 'e2eTestContainerTrigger', connection: 'CosmosDBConnection', }); diff --git a/src/constants.ts b/src/constants.ts index 88fe114d..0d768a51 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -10,10 +10,10 @@ export namespace EnvVarNames { } export namespace CosmosDB { - export const dbName = 'e2eTestDB'; + export const dbName = 'e2eTestCosmosDB'; export const triggerAndOutputContainerName = 'e2eTestContainerTriggerAndOutput'; export const triggerContainerName = 'e2eTestContainerTrigger'; - export const triggerDatabaseName = 'e2eTestDB'; + export const triggerDatabaseName = 'e2eTestCosmosDB'; export const partitionKey = 'testPartKey'; } diff --git a/src/cosmosDB.test.ts b/src/cosmosDB.test.ts index 8fad9551..bf9fcdff 100644 --- a/src/cosmosDB.test.ts +++ b/src/cosmosDB.test.ts @@ -8,7 +8,7 @@ import { getFuncUrl, CosmosDB } from './constants'; import { waitForOutput } from './global.test'; import { cosmosDBConnectionString } from './utils/connectionStrings'; import { getRandomTestData } from './utils/getRandomTestData'; -import { setupCosmosDB } from './utils/setupCosmosDB'; +import { setupCosmosDB } from './utils/cosmosdb/setupCosmosDB'; describe('cosmosDB', () => { before(async function (this: Mocha.Context) { diff --git a/src/utils/setupCosmosDB.ts b/src/utils/setupCosmosDB.ts deleted file mode 100644 index b7a68bc0..00000000 --- a/src/utils/setupCosmosDB.ts +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the MIT License. - -// The CosmosDB emulator requires a container and database to be created before running tests but after the emulator starts -// Otherwise the following error will occur: -// Microsoft.Azure.Cosmos.Client: This builder instance has already been used to build a processor. Create a new instance to build another. - -import { CosmosClient, PartitionKeyKind } from '@azure/cosmos'; -import { cosmosDBConnectionString } from './connectionStrings'; -import { CosmosDB } from '../constants'; - -export async function setupCosmosDB() { - const partitionKeyPath = `/${CosmosDB.partitionKey}`; - const client = new CosmosClient(cosmosDBConnectionString); - await client.databases.createIfNotExists({ id: CosmosDB.triggerDatabaseName }); - await client.database(CosmosDB.triggerDatabaseName).containers.createIfNotExists({ - id: CosmosDB.triggerContainerName, - partitionKey: { paths: [partitionKeyPath], kind: PartitionKeyKind.Hash } - }); - await client.database(CosmosDB.triggerDatabaseName).containers.createIfNotExists({ - id: CosmosDB.triggerAndOutputContainerName, - partitionKey: { paths: [partitionKeyPath], kind: PartitionKeyKind.Hash } - }); -} \ No newline at end of file From e536e56f996987a412e44f03c7ee938d4e6f6fe0 Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Thu, 7 Aug 2025 17:35:50 -0500 Subject: [PATCH 126/142] fix --- azure-pipelines/templates/test-node-version.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/azure-pipelines/templates/test-node-version.yml b/azure-pipelines/templates/test-node-version.yml index 72caa934..ce14007a 100644 --- a/azure-pipelines/templates/test-node-version.yml +++ b/azure-pipelines/templates/test-node-version.yml @@ -58,6 +58,9 @@ steps: - bash: | docker logs mssql displayName: 'SQL logs' + - bash: | + docker logs cosmosdb-emulator + displayName: 'Cosmos logs' # - bash: npm run testOldConfig # displayName: 'Run oldConfig tests Node ${{ parameters.nodeVersion }}' From 02620522b956494163d3300470c3b9b5efc76ad1 Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Thu, 7 Aug 2025 18:00:40 -0500 Subject: [PATCH 127/142] fix --- src/global.test.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/global.test.ts b/src/global.test.ts index 93f6e773..1f712285 100644 --- a/src/global.test.ts +++ b/src/global.test.ts @@ -17,6 +17,7 @@ import { } from './utils/connectionStrings'; import { delay } from './utils/delay'; import findProcess = require('find-process'); +import { setupCosmosDB } from './utils/cosmosdb/setupCosmosDB'; let perTestFuncOutput = ''; let fullFuncOutput = ''; @@ -41,6 +42,8 @@ before(async function (this: Mocha.Context): Promise { await initializeConnectionStrings(); + await setupCosmosDB(); + isOldConfig = getOldConfigArg(); const appPath = isOldConfig ? path.join(__dirname, '..', 'app', combinedFolder, model + oldConfigSuffix) From 3cb08d6bdf0fbdefc32bc0f59c0f96b5084044dc Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Fri, 8 Aug 2025 00:20:16 -0500 Subject: [PATCH 128/142] fix --- src/global.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/global.test.ts b/src/global.test.ts index 1f712285..790bfebd 100644 --- a/src/global.test.ts +++ b/src/global.test.ts @@ -17,7 +17,7 @@ import { } from './utils/connectionStrings'; import { delay } from './utils/delay'; import findProcess = require('find-process'); -import { setupCosmosDB } from './utils/cosmosdb/setupCosmosDB'; +// import { setupCosmosDB } from './utils/cosmosdb/setupCosmosDB'; let perTestFuncOutput = ''; let fullFuncOutput = ''; @@ -42,7 +42,7 @@ before(async function (this: Mocha.Context): Promise { await initializeConnectionStrings(); - await setupCosmosDB(); + // await setupCosmosDB(); isOldConfig = getOldConfigArg(); const appPath = isOldConfig From c36fb5048bf91f436e6468721b30e14eae40e272 Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Fri, 8 Aug 2025 00:37:59 -0500 Subject: [PATCH 129/142] fix --- src/utils/cosmosdb/setupCosmosDB.ts | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/src/utils/cosmosdb/setupCosmosDB.ts b/src/utils/cosmosdb/setupCosmosDB.ts index b8851b7c..d8628042 100644 --- a/src/utils/cosmosdb/setupCosmosDB.ts +++ b/src/utils/cosmosdb/setupCosmosDB.ts @@ -5,20 +5,21 @@ // Otherwise the following error will occur: // Microsoft.Azure.Cosmos.Client: This builder instance has already been used to build a processor. Create a new instance to build another. -import { CosmosClient, PartitionKeyKind } from '@azure/cosmos'; -import { cosmosDBConnectionString } from '../connectionStrings'; -import { CosmosDB } from '../../constants'; +// import { CosmosClient, PartitionKeyKind } from '@azure/cosmos'; +// import { cosmosDBConnectionString } from '../connectionStrings'; +// import { CosmosDB } from '../../constants'; export async function setupCosmosDB() { - const partitionKeyPath = `/${CosmosDB.partitionKey}`; - const client = new CosmosClient(cosmosDBConnectionString); - await client.databases.createIfNotExists({ id: CosmosDB.triggerDatabaseName }); - await client.database(CosmosDB.triggerDatabaseName).containers.createIfNotExists({ - id: CosmosDB.triggerContainerName, - partitionKey: { paths: [partitionKeyPath], kind: PartitionKeyKind.Hash } - }); - await client.database(CosmosDB.triggerDatabaseName).containers.createIfNotExists({ - id: CosmosDB.triggerAndOutputContainerName, - partitionKey: { paths: [partitionKeyPath], kind: PartitionKeyKind.Hash } - }); + throw new Error('When do we throw?'); + // const partitionKeyPath = `/${CosmosDB.partitionKey}`; + // const client = new CosmosClient(cosmosDBConnectionString); + // await client.databases.createIfNotExists({ id: CosmosDB.triggerDatabaseName }); + // await client.database(CosmosDB.triggerDatabaseName).containers.createIfNotExists({ + // id: CosmosDB.triggerContainerName, + // partitionKey: { paths: [partitionKeyPath], kind: PartitionKeyKind.Hash } + // }); + // await client.database(CosmosDB.triggerDatabaseName).containers.createIfNotExists({ + // id: CosmosDB.triggerAndOutputContainerName, + // partitionKey: { paths: [partitionKeyPath], kind: PartitionKeyKind.Hash } + // }); } \ No newline at end of file From 4c41e9df873773d2956f9855ae4a201471300bbf Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Fri, 8 Aug 2025 01:00:23 -0500 Subject: [PATCH 130/142] fix --- .../templates/test-node-version.yml | 3 +- src/utils/cosmosdb/setupCosmosDB.ts | 39 ++++++++++++------- 2 files changed, 25 insertions(+), 17 deletions(-) diff --git a/azure-pipelines/templates/test-node-version.yml b/azure-pipelines/templates/test-node-version.yml index ce14007a..09944182 100644 --- a/azure-pipelines/templates/test-node-version.yml +++ b/azure-pipelines/templates/test-node-version.yml @@ -44,8 +44,7 @@ steps: - bash: | docker pull mcr.microsoft.com/cosmosdb/linux/azure-cosmos-emulator:vnext-preview - docker run --detach --publish 8081:8081 --publish 1234:1234 --name cosmosdb-emulator mcr.microsoft.com/cosmosdb/linux/azure-cosmos-emulator:vnext-preview - sleep 30 + docker run --detach --publish 8081:8081 --publish 1234:1234 mcr.microsoft.com/cosmosdb/linux/azure-cosmos-emulator:vnext-preview docker ps displayName: "Start CosmosDB Emulator" diff --git a/src/utils/cosmosdb/setupCosmosDB.ts b/src/utils/cosmosdb/setupCosmosDB.ts index d8628042..f6341512 100644 --- a/src/utils/cosmosdb/setupCosmosDB.ts +++ b/src/utils/cosmosdb/setupCosmosDB.ts @@ -5,21 +5,30 @@ // Otherwise the following error will occur: // Microsoft.Azure.Cosmos.Client: This builder instance has already been used to build a processor. Create a new instance to build another. -// import { CosmosClient, PartitionKeyKind } from '@azure/cosmos'; -// import { cosmosDBConnectionString } from '../connectionStrings'; -// import { CosmosDB } from '../../constants'; +import { CosmosClient, PartitionKeyKind } from '@azure/cosmos'; +import { cosmosDBConnectionString } from '../connectionStrings'; +import { CosmosDB } from '../../constants'; +import { delay } from '../delay'; export async function setupCosmosDB() { - throw new Error('When do we throw?'); - // const partitionKeyPath = `/${CosmosDB.partitionKey}`; - // const client = new CosmosClient(cosmosDBConnectionString); - // await client.databases.createIfNotExists({ id: CosmosDB.triggerDatabaseName }); - // await client.database(CosmosDB.triggerDatabaseName).containers.createIfNotExists({ - // id: CosmosDB.triggerContainerName, - // partitionKey: { paths: [partitionKeyPath], kind: PartitionKeyKind.Hash } - // }); - // await client.database(CosmosDB.triggerDatabaseName).containers.createIfNotExists({ - // id: CosmosDB.triggerAndOutputContainerName, - // partitionKey: { paths: [partitionKeyPath], kind: PartitionKeyKind.Hash } - // }); + try { + const partitionKeyPath = `/${CosmosDB.partitionKey}`; + if (!cosmosDBConnectionString) { + throw new Error('CosmosDB connection string is not set'); + } + const client = new CosmosClient(cosmosDBConnectionString); + await client.databases.createIfNotExists({ id: CosmosDB.triggerDatabaseName }); + await client.database(CosmosDB.triggerDatabaseName).containers.createIfNotExists({ + id: CosmosDB.triggerContainerName, + partitionKey: { paths: [partitionKeyPath], kind: PartitionKeyKind.Hash } + }); + await client.database(CosmosDB.triggerDatabaseName).containers.createIfNotExists({ + id: CosmosDB.triggerAndOutputContainerName, + partitionKey: { paths: [partitionKeyPath], kind: PartitionKeyKind.Hash } + }); +} catch (error) { + console.error('Error setting up CosmosDB:', error); + throw error; + } + await delay(30000); } \ No newline at end of file From 113dd3301dbcbedc26f67d4ec9dc80e9048a8b2b Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Fri, 8 Aug 2025 01:35:15 -0500 Subject: [PATCH 131/142] fix --- azure-pipelines/templates/test-node-version.yml | 16 ++++++++++------ src/cosmosDB.test.ts | 8 ++++---- src/global.test.ts | 8 ++++++-- 3 files changed, 20 insertions(+), 12 deletions(-) diff --git a/azure-pipelines/templates/test-node-version.yml b/azure-pipelines/templates/test-node-version.yml index 09944182..fbadff06 100644 --- a/azure-pipelines/templates/test-node-version.yml +++ b/azure-pipelines/templates/test-node-version.yml @@ -12,6 +12,12 @@ steps: displayName: 'Install Node ${{ parameters.nodeVersion }}' retryCountOnTaskFailure: 10 + - bash: | + docker pull mcr.microsoft.com/cosmosdb/linux/azure-cosmos-emulator:vnext-preview + docker run --detach --publish 8081:8081 --publish --name cosmosdb-emulator 1234:1234 mcr.microsoft.com/cosmosdb/linux/azure-cosmos-emulator:vnext-preview + docker ps + displayName: "Start CosmosDB Emulator" + - bash: docker compose -f src/utils/servicebus/docker-compose.yml up -d env: AzureWebJobsSQLPassword: $(AzureWebJobsSQLPassword) @@ -21,6 +27,10 @@ steps: displayName: 'Run ServiceBus tests Node ${{ parameters.nodeVersion }}' continueOnError: true + - bash: | + docker logs cosmosdb-emulator + displayName: 'Cosmos logs' + - bash: | docker stop servicebus-emulator || true docker rm -f servicebus-emulator || true @@ -42,12 +52,6 @@ steps: SA_PASSWORD: $(AzureWebJobsSQLPassword) displayName: "Debug SQL Password" - - bash: | - docker pull mcr.microsoft.com/cosmosdb/linux/azure-cosmos-emulator:vnext-preview - docker run --detach --publish 8081:8081 --publish 1234:1234 mcr.microsoft.com/cosmosdb/linux/azure-cosmos-emulator:vnext-preview - docker ps - displayName: "Start CosmosDB Emulator" - - bash: npm run testAllExceptServiceBus env: SA_PASSWORD: $(AzureWebJobsSQLPassword) diff --git a/src/cosmosDB.test.ts b/src/cosmosDB.test.ts index bf9fcdff..4731c689 100644 --- a/src/cosmosDB.test.ts +++ b/src/cosmosDB.test.ts @@ -8,12 +8,12 @@ import { getFuncUrl, CosmosDB } from './constants'; import { waitForOutput } from './global.test'; import { cosmosDBConnectionString } from './utils/connectionStrings'; import { getRandomTestData } from './utils/getRandomTestData'; -import { setupCosmosDB } from './utils/cosmosdb/setupCosmosDB'; +// import { setupCosmosDB } from './utils/cosmosdb/setupCosmosDB'; describe('cosmosDB', () => { - before(async function (this: Mocha.Context) { - await setupCosmosDB(); - }); + // before(async function (this: Mocha.Context) { + // await setupCosmosDB(); + // }); it('trigger, output, input', async () => { const client = new CosmosClient(cosmosDBConnectionString); diff --git a/src/global.test.ts b/src/global.test.ts index 790bfebd..b0ad5822 100644 --- a/src/global.test.ts +++ b/src/global.test.ts @@ -6,7 +6,7 @@ import * as fs from 'fs/promises'; import path from 'path'; import semver from 'semver'; import { combinedFolder, defaultTimeout, EnvVarNames, oldConfigSuffix } from './constants'; -import { getModelArg, getOldConfigArg, Model } from './getModelArg'; +import { getModelArg, getOldConfigArg, getTestFileFilter, Model } from './getModelArg'; import { cosmosDBConnectionString, eventHubConnectionString, @@ -17,6 +17,7 @@ import { } from './utils/connectionStrings'; import { delay } from './utils/delay'; import findProcess = require('find-process'); +import { setupCosmosDB } from './utils/cosmosdb/setupCosmosDB'; // import { setupCosmosDB } from './utils/cosmosdb/setupCosmosDB'; let perTestFuncOutput = ''; @@ -42,7 +43,10 @@ before(async function (this: Mocha.Context): Promise { await initializeConnectionStrings(); - // await setupCosmosDB(); + const { only } = getTestFileFilter(); + if (only) { + await setupCosmosDB(); + } isOldConfig = getOldConfigArg(); const appPath = isOldConfig From 0a79699ec4b4291007bf8035514d1acbc4f688c9 Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Fri, 8 Aug 2025 01:53:40 -0500 Subject: [PATCH 132/142] fix --- azure-pipelines/templates/test-node-version.yml | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/azure-pipelines/templates/test-node-version.yml b/azure-pipelines/templates/test-node-version.yml index fbadff06..b63f284c 100644 --- a/azure-pipelines/templates/test-node-version.yml +++ b/azure-pipelines/templates/test-node-version.yml @@ -14,7 +14,7 @@ steps: - bash: | docker pull mcr.microsoft.com/cosmosdb/linux/azure-cosmos-emulator:vnext-preview - docker run --detach --publish 8081:8081 --publish --name cosmosdb-emulator 1234:1234 mcr.microsoft.com/cosmosdb/linux/azure-cosmos-emulator:vnext-preview + docker run --detach --publish 8081:8081 --publish 1234:1234 mcr.microsoft.com/cosmosdb/linux/azure-cosmos-emulator:vnext-preview docker ps displayName: "Start CosmosDB Emulator" @@ -27,10 +27,6 @@ steps: displayName: 'Run ServiceBus tests Node ${{ parameters.nodeVersion }}' continueOnError: true - - bash: | - docker logs cosmosdb-emulator - displayName: 'Cosmos logs' - - bash: | docker stop servicebus-emulator || true docker rm -f servicebus-emulator || true @@ -61,9 +57,6 @@ steps: - bash: | docker logs mssql displayName: 'SQL logs' - - bash: | - docker logs cosmosdb-emulator - displayName: 'Cosmos logs' # - bash: npm run testOldConfig # displayName: 'Run oldConfig tests Node ${{ parameters.nodeVersion }}' From eb4e1880f3067d125b5e5c472b74d66ed155c190 Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Fri, 8 Aug 2025 02:18:59 -0500 Subject: [PATCH 133/142] fix --- src/global.test.ts | 1 - src/utils/sql/setupSql.ts | 112 +++++++++++++++++--------------------- 2 files changed, 49 insertions(+), 64 deletions(-) diff --git a/src/global.test.ts b/src/global.test.ts index b0ad5822..7a404979 100644 --- a/src/global.test.ts +++ b/src/global.test.ts @@ -18,7 +18,6 @@ import { import { delay } from './utils/delay'; import findProcess = require('find-process'); import { setupCosmosDB } from './utils/cosmosdb/setupCosmosDB'; -// import { setupCosmosDB } from './utils/cosmosdb/setupCosmosDB'; let perTestFuncOutput = ''; let fullFuncOutput = ''; diff --git a/src/utils/sql/setupSql.ts b/src/utils/sql/setupSql.ts index 6cbca0a6..34f2af73 100644 --- a/src/utils/sql/setupSql.ts +++ b/src/utils/sql/setupSql.ts @@ -4,75 +4,61 @@ import * as sql from 'mssql'; import retry from 'p-retry'; import { sqlConnectionString, sqlTestConnectionString } from '../connectionStrings'; -import { Sql } from '../../constants'; +// import { Sql } from '../../constants'; export async function runSqlSetupQueries() { - // STEP 1: Create DB if not exists - let pool = await createPoolConnnection(sqlConnectionString); - try { - await pool.request().query(` - IF NOT EXISTS (SELECT name FROM sys.databases WHERE name = '${Sql.dbName}') - BEGIN - CREATE DATABASE [${Sql.dbName}]; - END - `); - } finally { - await pool.close(); - } - - // STEP 2: Retry ALTER DATABASE (change_tracking) - pool = await createPoolConnnection(sqlConnectionString); - try { - await retry(async (currentAttempt) => { - if (currentAttempt > 1) { - console.log( - `${new Date().toISOString()}: Retrying ALTER DATABASE. Attempt ${currentAttempt}` - ); - } - await pool.request().query(` - ALTER DATABASE [${Sql.dbName}] - SET CHANGE_TRACKING = ON (CHANGE_RETENTION = 2 DAYS, AUTO_CLEANUP = ON); - `); - }, { - retries: 5, - minTimeout: 5000 - }); - } catch (err) { - console.error("ALTER DATABASE failed:", err); - throw err; - } finally { - await pool.close(); - } - - // STEP 3: Create tables and enable tracking - pool = await createPoolConnnection(sqlTestConnectionString); - try { - for (const table of [Sql.sqlTriggerTable, Sql.sqlNonTriggerTable]) { - await pool.request().query(` - IF OBJECT_ID('dbo.${table}', 'U') IS NULL - BEGIN - CREATE TABLE dbo.${table} ( - id UNIQUEIDENTIFIER PRIMARY KEY, - testData NVARCHAR(200) NOT NULL - ); - ALTER TABLE dbo.${table} ENABLE CHANGE_TRACKING; - END - `); - } - } finally { - await pool.close(); - } + throw new Error(`conn1: ${sqlConnectionString}, conn2: ${sqlTestConnectionString}`); + // // STEP 1: Create DB if not exists + // let pool = await createPoolConnnection(sqlConnectionString); + // try { + // await pool.request().query(` + // IF NOT EXISTS (SELECT name FROM sys.databases WHERE name = '${Sql.dbName}') + // BEGIN + // CREATE DATABASE [${Sql.dbName}]; + // END + // `); + // } finally { + // await pool.close(); + // } - // pool = await sql.connect(sqlTestConnectionString); + // // STEP 2: Retry ALTER DATABASE (change_tracking) + // pool = await createPoolConnnection(sqlConnectionString); + // try { + // await retry(async (currentAttempt) => { + // if (currentAttempt > 1) { + // console.log( + // `${new Date().toISOString()}: Retrying ALTER DATABASE. Attempt ${currentAttempt}` + // ); + // } + // await pool.request().query(` + // ALTER DATABASE [${Sql.dbName}] + // SET CHANGE_TRACKING = ON (CHANGE_RETENTION = 2 DAYS, AUTO_CLEANUP = ON); + // `); + // }, { + // retries: 5, + // minTimeout: 5000 + // }); + // } catch (err) { + // console.error("ALTER DATABASE failed:", err); + // throw err; + // } finally { + // await pool.close(); + // } + // // STEP 3: Create tables and enable tracking + // pool = await createPoolConnnection(sqlTestConnectionString); // try { // for (const table of [Sql.sqlTriggerTable, Sql.sqlNonTriggerTable]) { - // await pool - // .request() - // .query( - // `CREATE TABLE dbo.${table} ([id] UNIQUEIDENTIFIER PRIMARY KEY, [testData] NVARCHAR(200) NOT NULL);` - // ); - // await pool.request().query(`ALTER TABLE dbo.${table} ENABLE CHANGE_TRACKING;`); + // await pool.request().query(` + // IF OBJECT_ID('dbo.${table}', 'U') IS NULL + // BEGIN + // CREATE TABLE dbo.${table} ( + // id UNIQUEIDENTIFIER PRIMARY KEY, + // testData NVARCHAR(200) NOT NULL + // ); + // ALTER TABLE dbo.${table} ENABLE CHANGE_TRACKING; + // END + // `); // } // } finally { // await pool.close(); From f29562ed314dad356528d9c14228f58fac16c115 Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Fri, 8 Aug 2025 02:39:24 -0500 Subject: [PATCH 134/142] fix --- src/getModelArg.ts | 7 --- src/global.test.ts | 2 + src/sql.test.ts | 3 +- src/utils/sql/setupSql.ts | 109 +++++++++++++++++++------------------- 4 files changed, 57 insertions(+), 64 deletions(-) diff --git a/src/getModelArg.ts b/src/getModelArg.ts index da5632f4..912eb6e6 100644 --- a/src/getModelArg.ts +++ b/src/getModelArg.ts @@ -27,10 +27,3 @@ export function getTestFileFilter(): { only?: string; exclude?: string } { const exclude = typeof args.exclude === 'string' ? args.exclude : undefined; return { only, exclude }; } - -// export function isOnlyRunningServiceBusTests(): boolean { -// const args = parseArgs(process.argv.slice(2)); -// const only = typeof args.only === 'string' ? args.only : undefined; - -// return only === 'serviceBus.test.js'; -// } \ No newline at end of file diff --git a/src/global.test.ts b/src/global.test.ts index 7a404979..d39391dd 100644 --- a/src/global.test.ts +++ b/src/global.test.ts @@ -18,6 +18,7 @@ import { import { delay } from './utils/delay'; import findProcess = require('find-process'); import { setupCosmosDB } from './utils/cosmosdb/setupCosmosDB'; +import { runSqlSetupQueries } from './utils/sql/setupSql'; let perTestFuncOutput = ''; let fullFuncOutput = ''; @@ -44,6 +45,7 @@ before(async function (this: Mocha.Context): Promise { const { only } = getTestFileFilter(); if (only) { + await runSqlSetupQueries(); await setupCosmosDB(); } diff --git a/src/sql.test.ts b/src/sql.test.ts index c82afe68..833444f8 100644 --- a/src/sql.test.ts +++ b/src/sql.test.ts @@ -8,7 +8,7 @@ import { Sql, getFuncUrl } from './constants'; import { isOldConfig, waitForOutput } from './global.test'; import { getRandomTestData } from './utils/getRandomTestData'; import { ConnectionPool } from 'mssql'; -import { createPoolConnnection, runSqlSetupQueries } from './utils/sql/setupSql'; +import { createPoolConnnection } from './utils/sql/setupSql'; import { sqlTestConnectionString } from './utils/connectionStrings'; describe('sql', () => { @@ -18,7 +18,6 @@ describe('sql', () => { this.skip(); } - await runSqlSetupQueries(); poolConnection = await createPoolConnnection(sqlTestConnectionString); }); diff --git a/src/utils/sql/setupSql.ts b/src/utils/sql/setupSql.ts index 34f2af73..f014f03a 100644 --- a/src/utils/sql/setupSql.ts +++ b/src/utils/sql/setupSql.ts @@ -4,65 +4,64 @@ import * as sql from 'mssql'; import retry from 'p-retry'; import { sqlConnectionString, sqlTestConnectionString } from '../connectionStrings'; -// import { Sql } from '../../constants'; +import { Sql } from '../../constants'; export async function runSqlSetupQueries() { - throw new Error(`conn1: ${sqlConnectionString}, conn2: ${sqlTestConnectionString}`); - // // STEP 1: Create DB if not exists - // let pool = await createPoolConnnection(sqlConnectionString); - // try { - // await pool.request().query(` - // IF NOT EXISTS (SELECT name FROM sys.databases WHERE name = '${Sql.dbName}') - // BEGIN - // CREATE DATABASE [${Sql.dbName}]; - // END - // `); - // } finally { - // await pool.close(); - // } + // STEP 1: Create DB if not exists + let pool = await createPoolConnnection(sqlConnectionString); + try { + await pool.request().query(` + IF NOT EXISTS (SELECT name FROM sys.databases WHERE name = '${Sql.dbName}') + BEGIN + CREATE DATABASE [${Sql.dbName}]; + END + `); + } finally { + await pool.close(); + } - // // STEP 2: Retry ALTER DATABASE (change_tracking) - // pool = await createPoolConnnection(sqlConnectionString); - // try { - // await retry(async (currentAttempt) => { - // if (currentAttempt > 1) { - // console.log( - // `${new Date().toISOString()}: Retrying ALTER DATABASE. Attempt ${currentAttempt}` - // ); - // } - // await pool.request().query(` - // ALTER DATABASE [${Sql.dbName}] - // SET CHANGE_TRACKING = ON (CHANGE_RETENTION = 2 DAYS, AUTO_CLEANUP = ON); - // `); - // }, { - // retries: 5, - // minTimeout: 5000 - // }); - // } catch (err) { - // console.error("ALTER DATABASE failed:", err); - // throw err; - // } finally { - // await pool.close(); - // } + // STEP 2: Retry ALTER DATABASE (change_tracking) + pool = await createPoolConnnection(sqlConnectionString); + try { + await retry(async (currentAttempt) => { + if (currentAttempt > 1) { + console.log( + `${new Date().toISOString()}: Retrying ALTER DATABASE. Attempt ${currentAttempt}` + ); + } + await pool.request().query(` + ALTER DATABASE [${Sql.dbName}] + SET CHANGE_TRACKING = ON (CHANGE_RETENTION = 2 DAYS, AUTO_CLEANUP = ON); + `); + }, { + retries: 5, + minTimeout: 5000 + }); + } catch (err) { + console.error("ALTER DATABASE failed:", err); + throw err; + } finally { + await pool.close(); + } - // // STEP 3: Create tables and enable tracking - // pool = await createPoolConnnection(sqlTestConnectionString); - // try { - // for (const table of [Sql.sqlTriggerTable, Sql.sqlNonTriggerTable]) { - // await pool.request().query(` - // IF OBJECT_ID('dbo.${table}', 'U') IS NULL - // BEGIN - // CREATE TABLE dbo.${table} ( - // id UNIQUEIDENTIFIER PRIMARY KEY, - // testData NVARCHAR(200) NOT NULL - // ); - // ALTER TABLE dbo.${table} ENABLE CHANGE_TRACKING; - // END - // `); - // } - // } finally { - // await pool.close(); - // } + // STEP 3: Create tables and enable tracking + pool = await createPoolConnnection(sqlTestConnectionString); + try { + for (const table of [Sql.sqlTriggerTable, Sql.sqlNonTriggerTable]) { + await pool.request().query(` + IF OBJECT_ID('dbo.${table}', 'U') IS NULL + BEGIN + CREATE TABLE dbo.${table} ( + id UNIQUEIDENTIFIER PRIMARY KEY, + testData NVARCHAR(200) NOT NULL + ); + ALTER TABLE dbo.${table} ENABLE CHANGE_TRACKING; + END + `); + } + } finally { + await pool.close(); + } } export async function createPoolConnnection(connectionString: string): Promise { From 390822337b735c0440cb88275a23572705450858 Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Fri, 8 Aug 2025 02:56:56 -0500 Subject: [PATCH 135/142] fix --- azure-pipelines/templates/test-node-version.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/azure-pipelines/templates/test-node-version.yml b/azure-pipelines/templates/test-node-version.yml index b63f284c..19bc0a36 100644 --- a/azure-pipelines/templates/test-node-version.yml +++ b/azure-pipelines/templates/test-node-version.yml @@ -18,6 +18,13 @@ steps: docker ps displayName: "Start CosmosDB Emulator" + - bash: | + docker compose -f src/utils/sql/docker-compose.yml up -d + sleep 60 + env: + SA_PASSWORD: $(AzureWebJobsSQLPassword) + displayName: "Start SQL Service" + - bash: docker compose -f src/utils/servicebus/docker-compose.yml up -d env: AzureWebJobsSQLPassword: $(AzureWebJobsSQLPassword) @@ -33,13 +40,6 @@ steps: docker compose -f src/utils/eventhub/docker-compose.yml up -d displayName: 'Stop ServiceBus Emulator and Start EventHub Emulator' - - bash: | - docker compose -f src/utils/sql/docker-compose.yml up -d - sleep 60 - env: - SA_PASSWORD: $(AzureWebJobsSQLPassword) - displayName: "Start SQL Service" - - bash: | echo "Debugging SA_PASSWORD" echo "Length: ${#SA_PASSWORD}" From ee2f9492a30b962197776eccb1bd926995931190 Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Fri, 8 Aug 2025 10:39:40 -0500 Subject: [PATCH 136/142] fix --- azure-pipelines/templates/test-node-version.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/azure-pipelines/templates/test-node-version.yml b/azure-pipelines/templates/test-node-version.yml index 19bc0a36..61338222 100644 --- a/azure-pipelines/templates/test-node-version.yml +++ b/azure-pipelines/templates/test-node-version.yml @@ -31,6 +31,8 @@ steps: displayName: 'Start ServiceBus Emulator' - bash: npm run testServiceBus + env: + SA_PASSWORD: $(AzureWebJobsSQLPassword) displayName: 'Run ServiceBus tests Node ${{ parameters.nodeVersion }}' continueOnError: true From 59c876b9aed6ff4b7b75b7a196d03e276b3e66a6 Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Fri, 8 Aug 2025 14:35:22 -0500 Subject: [PATCH 137/142] fix --- src/cosmosDB.test.ts | 5 ----- src/utils/sql/setupSql.ts | 11 +++++++++-- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/cosmosDB.test.ts b/src/cosmosDB.test.ts index 4731c689..33572a25 100644 --- a/src/cosmosDB.test.ts +++ b/src/cosmosDB.test.ts @@ -8,13 +8,8 @@ import { getFuncUrl, CosmosDB } from './constants'; import { waitForOutput } from './global.test'; import { cosmosDBConnectionString } from './utils/connectionStrings'; import { getRandomTestData } from './utils/getRandomTestData'; -// import { setupCosmosDB } from './utils/cosmosdb/setupCosmosDB'; describe('cosmosDB', () => { - // before(async function (this: Mocha.Context) { - // await setupCosmosDB(); - // }); - it('trigger, output, input', async () => { const client = new CosmosClient(cosmosDBConnectionString); const container = client.database(CosmosDB.dbName).container(CosmosDB.triggerAndOutputContainerName); diff --git a/src/utils/sql/setupSql.ts b/src/utils/sql/setupSql.ts index f014f03a..4173d682 100644 --- a/src/utils/sql/setupSql.ts +++ b/src/utils/sql/setupSql.ts @@ -30,8 +30,15 @@ export async function runSqlSetupQueries() { ); } await pool.request().query(` - ALTER DATABASE [${Sql.dbName}] - SET CHANGE_TRACKING = ON (CHANGE_RETENTION = 2 DAYS, AUTO_CLEANUP = ON); + IF NOT EXISTS ( + SELECT 1 + FROM sys.change_tracking_databases + WHERE database_id = DB_ID('${Sql.dbName}') + ) + BEGIN + ALTER DATABASE [${Sql.dbName}] + SET CHANGE_TRACKING = ON (CHANGE_RETENTION = 2 DAYS, AUTO_CLEANUP = ON); + END `); }, { retries: 5, From 71d052d082f14d5da7655d99605d0f11318f3849 Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Fri, 8 Aug 2025 16:25:34 -0500 Subject: [PATCH 138/142] fix --- src/sql.test.ts | 4 ---- src/utils/cosmosdb/setupCosmosDB.ts | 7 ------- src/utils/sql/setupSql.ts | 20 ++++++-------------- 3 files changed, 6 insertions(+), 25 deletions(-) diff --git a/src/sql.test.ts b/src/sql.test.ts index 833444f8..6bbac192 100644 --- a/src/sql.test.ts +++ b/src/sql.test.ts @@ -31,10 +31,6 @@ describe('sql', () => { const id = uuid(); const testData = getRandomTestData(); - if (!poolConnection) { - throw new Error('SQL connection pool is not initialized'); - } - // trigger by insert await poolConnection!.request().query(`INSERT INTO ${Sql.sqlTriggerTable} VALUES ('${id}', '${testData}');`); await waitForOutput(`sqlTrigger processed 1 changes`); diff --git a/src/utils/cosmosdb/setupCosmosDB.ts b/src/utils/cosmosdb/setupCosmosDB.ts index f6341512..7f646a25 100644 --- a/src/utils/cosmosdb/setupCosmosDB.ts +++ b/src/utils/cosmosdb/setupCosmosDB.ts @@ -8,10 +8,8 @@ import { CosmosClient, PartitionKeyKind } from '@azure/cosmos'; import { cosmosDBConnectionString } from '../connectionStrings'; import { CosmosDB } from '../../constants'; -import { delay } from '../delay'; export async function setupCosmosDB() { - try { const partitionKeyPath = `/${CosmosDB.partitionKey}`; if (!cosmosDBConnectionString) { throw new Error('CosmosDB connection string is not set'); @@ -26,9 +24,4 @@ export async function setupCosmosDB() { id: CosmosDB.triggerAndOutputContainerName, partitionKey: { paths: [partitionKeyPath], kind: PartitionKeyKind.Hash } }); -} catch (error) { - console.error('Error setting up CosmosDB:', error); - throw error; - } - await delay(30000); } \ No newline at end of file diff --git a/src/utils/sql/setupSql.ts b/src/utils/sql/setupSql.ts index 4173d682..59b4c770 100644 --- a/src/utils/sql/setupSql.ts +++ b/src/utils/sql/setupSql.ts @@ -9,19 +9,14 @@ import { Sql } from '../../constants'; export async function runSqlSetupQueries() { // STEP 1: Create DB if not exists let pool = await createPoolConnnection(sqlConnectionString); - try { - await pool.request().query(` - IF NOT EXISTS (SELECT name FROM sys.databases WHERE name = '${Sql.dbName}') - BEGIN - CREATE DATABASE [${Sql.dbName}]; - END - `); - } finally { - await pool.close(); - } + await pool.request().query(` + IF NOT EXISTS (SELECT name FROM sys.databases WHERE name = '${Sql.dbName}') + BEGIN + CREATE DATABASE [${Sql.dbName}]; + END + `); // STEP 2: Retry ALTER DATABASE (change_tracking) - pool = await createPoolConnnection(sqlConnectionString); try { await retry(async (currentAttempt) => { if (currentAttempt > 1) { @@ -44,9 +39,6 @@ export async function runSqlSetupQueries() { retries: 5, minTimeout: 5000 }); - } catch (err) { - console.error("ALTER DATABASE failed:", err); - throw err; } finally { await pool.close(); } From a8874c08fa666d3552edf600db20195b1e20ec52 Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Mon, 11 Aug 2025 01:33:07 -0500 Subject: [PATCH 139/142] fix --- .../templates/test-node-version.yml | 33 +++++++------------ azure-pipelines/templates/test.yml | 12 +++---- 2 files changed, 17 insertions(+), 28 deletions(-) diff --git a/azure-pipelines/templates/test-node-version.yml b/azure-pipelines/templates/test-node-version.yml index 61338222..88497404 100644 --- a/azure-pipelines/templates/test-node-version.yml +++ b/azure-pipelines/templates/test-node-version.yml @@ -42,32 +42,21 @@ steps: docker compose -f src/utils/eventhub/docker-compose.yml up -d displayName: 'Stop ServiceBus Emulator and Start EventHub Emulator' - - bash: | - echo "Debugging SA_PASSWORD" - echo "Length: ${#SA_PASSWORD}" - echo "Value: $SA_PASSWORD" - env: - SA_PASSWORD: $(AzureWebJobsSQLPassword) - displayName: "Debug SQL Password" - - bash: npm run testAllExceptServiceBus env: SA_PASSWORD: $(AzureWebJobsSQLPassword) displayName: 'Run remaining tests Node ${{ parameters.nodeVersion }}' continueOnError: true - - bash: | - docker logs mssql - displayName: 'SQL logs' + - bash: npm run testOldConfig + displayName: 'Run oldConfig tests Node ${{ parameters.nodeVersion }}' + condition: and(succeeded(), eq('${{ parameters.runOldConfig }}', 'true')) + continueOnError: true - # - bash: npm run testOldConfig - # displayName: 'Run oldConfig tests Node ${{ parameters.nodeVersion }}' - # condition: and(succeeded(), eq('${{ parameters.runOldConfig }}', 'true')) - # continueOnError: true - # - bash: | - # docker stop cosmosdb-emulator || true - # docker rm -f cosmosdb-emulator || true - # docker compose -f src/utils/eventhub/docker-compose.yml down -v - # docker compose -f src/utils/servicebus/docker-compose.yml down -v - # docker compose -f src/utils/sql/docker-compose.yml down -v - # displayName: 'Stop all resources' \ No newline at end of file + - bash: | + docker stop cosmosdb-emulator || true + docker rm -f cosmosdb-emulator || true + docker compose -f src/utils/eventhub/docker-compose.yml down -v + docker compose -f src/utils/servicebus/docker-compose.yml down -v + docker compose -f src/utils/sql/docker-compose.yml down -v + displayName: 'Stop all resources' \ No newline at end of file diff --git a/azure-pipelines/templates/test.yml b/azure-pipelines/templates/test.yml index 9eed1b4c..14cb21c1 100644 --- a/azure-pipelines/templates/test.yml +++ b/azure-pipelines/templates/test.yml @@ -22,13 +22,13 @@ jobs: nodeVersion: 18.x runOldConfig: true - # - template: /azure-pipelines/templates/test-node-version.yml@self - # parameters: - # nodeVersion: 20.x + - template: /azure-pipelines/templates/test-node-version.yml@self + parameters: + nodeVersion: 20.x - # - template: /azure-pipelines/templates/test-node-version.yml@self - # parameters: - # nodeVersion: 22.x + - template: /azure-pipelines/templates/test-node-version.yml@self + parameters: + nodeVersion: 22.x - task: PublishTestResults@2 displayName: 'Publish Unit Test Results' From dda0450826b265c416be40ba97182bd4f61220ef Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Mon, 11 Aug 2025 02:25:30 -0500 Subject: [PATCH 140/142] fix --- .../templates/test-node-version.yml | 2 +- package-lock.json | 95 ------------------- package.json | 1 - src/constants.ts | 1 + src/global.test.ts | 3 +- 5 files changed, 4 insertions(+), 98 deletions(-) diff --git a/azure-pipelines/templates/test-node-version.yml b/azure-pipelines/templates/test-node-version.yml index 88497404..84732ae7 100644 --- a/azure-pipelines/templates/test-node-version.yml +++ b/azure-pipelines/templates/test-node-version.yml @@ -14,7 +14,7 @@ steps: - bash: | docker pull mcr.microsoft.com/cosmosdb/linux/azure-cosmos-emulator:vnext-preview - docker run --detach --publish 8081:8081 --publish 1234:1234 mcr.microsoft.com/cosmosdb/linux/azure-cosmos-emulator:vnext-preview + docker run --detach --publish 8081:8081 --publish 1234:1234 --name cosmosdb-emulator mcr.microsoft.com/cosmosdb/linux/azure-cosmos-emulator:vnext-preview docker ps displayName: "Start CosmosDB Emulator" diff --git a/package-lock.json b/package-lock.json index 99527545..93838b4e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -52,7 +52,6 @@ "mocha-junit-reporter": "^2.0.2", "mocha-multi-reporters": "^1.5.1", "mssql": "^10.0.2", - "mysql2": "^3.14.3", "node-fetch": "2.6.7", "p-retry": "^4.0.0", "prettier": "^2.4.1", @@ -1934,14 +1933,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/aws-ssl-profiles": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/aws-ssl-profiles/-/aws-ssl-profiles-1.1.2.tgz", - "integrity": "sha512-NZKeq9AfyQvEeNlN0zSYAaWrmBffJh3IELMZfRpJVWgrpEbtEpnjvzqBPf+mxoI287JohRDoa+/nsfqqiZmF6g==", - "engines": { - "node": ">= 6.0.0" - } - }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -2441,14 +2432,6 @@ "node": ">=0.4.0" } }, - "node_modules/denque": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", - "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==", - "engines": { - "node": ">=0.10" - } - }, "node_modules/diff": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", @@ -3326,14 +3309,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/generate-function": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz", - "integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==", - "dependencies": { - "is-property": "^1.0.2" - } - }, "node_modules/get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", @@ -3907,11 +3882,6 @@ "node": ">=8" } }, - "node_modules/is-property": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", - "integrity": "sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g==" - }, "node_modules/is-regex": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", @@ -4325,20 +4295,6 @@ "node": ">=10" } }, - "node_modules/lru.min": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/lru.min/-/lru.min-1.1.2.tgz", - "integrity": "sha512-Nv9KddBcQSlQopmBHXSsZVY5xsdlZkdH/Iey0BlcBYggMd4two7cZnKOK9vmy3nY0O5RGH99z1PCeTpPqszUYg==", - "engines": { - "bun": ">=1.0.0", - "deno": ">=1.30.0", - "node": ">=8.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wellwelwel" - } - }, "node_modules/make-error": { "version": "1.3.6", "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", @@ -4614,44 +4570,6 @@ "node": ">=16" } }, - "node_modules/mysql2": { - "version": "3.14.3", - "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-3.14.3.tgz", - "integrity": "sha512-fD6MLV8XJ1KiNFIF0bS7Msl8eZyhlTDCDl75ajU5SJtpdx9ZPEACulJcqJWr1Y8OYyxsFc4j3+nflpmhxCU5aQ==", - "dependencies": { - "aws-ssl-profiles": "^1.1.1", - "denque": "^2.1.0", - "generate-function": "^2.3.1", - "iconv-lite": "^0.6.3", - "long": "^5.2.1", - "lru.min": "^1.0.0", - "named-placeholders": "^1.1.3", - "seq-queue": "^0.0.5", - "sqlstring": "^2.3.2" - }, - "engines": { - "node": ">= 8.0" - } - }, - "node_modules/named-placeholders": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/named-placeholders/-/named-placeholders-1.1.3.tgz", - "integrity": "sha512-eLoBxg6wE/rZkJPhU/xRX1WTpkFEwDJEN96oxFrTsqBdbT5ec295Q+CoHrL9IT0DipqKhmGcaZmwOt8OON5x1w==", - "dependencies": { - "lru-cache": "^7.14.1" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/named-placeholders/node_modules/lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", - "engines": { - "node": ">=12" - } - }, "node_modules/native-duplexpair": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/native-duplexpair/-/native-duplexpair-1.0.0.tgz", @@ -5394,11 +5312,6 @@ "node": ">=10" } }, - "node_modules/seq-queue": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/seq-queue/-/seq-queue-0.0.5.tgz", - "integrity": "sha512-hr3Wtp/GZIc/6DAGPDcV4/9WoZhjrkXsi5B/07QgX8tsdc6ilr7BFM6PM6rbdAX1kFSDYeZGLipIZZKyQP0O5Q==" - }, "node_modules/serialize-javascript": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", @@ -5538,14 +5451,6 @@ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" }, - "node_modules/sqlstring": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.3.tgz", - "integrity": "sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg==", - "engines": { - "node": ">= 0.6" - } - }, "node_modules/stoppable": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/stoppable/-/stoppable-1.1.0.tgz", diff --git a/package.json b/package.json index 6a4f43ef..35f54926 100644 --- a/package.json +++ b/package.json @@ -81,7 +81,6 @@ "mocha-junit-reporter": "^2.0.2", "mocha-multi-reporters": "^1.5.1", "mssql": "^10.0.2", - "mysql2": "^3.14.3", "node-fetch": "2.6.7", "p-retry": "^4.0.0", "prettier": "^2.4.1", diff --git a/src/constants.ts b/src/constants.ts index 0d768a51..ddb5872c 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -31,6 +31,7 @@ export namespace ServiceBus { export const serviceBusQueueManyTrigger = 'e2e-test-queue-many-trigger'; export const serviceBusTopicTriggerAndOutput = 'e2e-test-topic-trigger-and-output'; export const serviceBusTopicTrigger = 'e2e-test-topic-trigger'; + export const serviceBusTestFileName = 'serviceBus.test'; } export namespace Sql { diff --git a/src/global.test.ts b/src/global.test.ts index d39391dd..52ccda8f 100644 --- a/src/global.test.ts +++ b/src/global.test.ts @@ -19,6 +19,7 @@ import { delay } from './utils/delay'; import findProcess = require('find-process'); import { setupCosmosDB } from './utils/cosmosdb/setupCosmosDB'; import { runSqlSetupQueries } from './utils/sql/setupSql'; +import { ServiceBus } from './constants'; let perTestFuncOutput = ''; let fullFuncOutput = ''; @@ -44,7 +45,7 @@ before(async function (this: Mocha.Context): Promise { await initializeConnectionStrings(); const { only } = getTestFileFilter(); - if (only) { + if (only?.startsWith(ServiceBus.serviceBusTestFileName)) { await runSqlSetupQueries(); await setupCosmosDB(); } From e7b1f5b0baea0fd03967bf80c911c0224aa03493 Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Mon, 11 Aug 2025 02:26:09 -0500 Subject: [PATCH 141/142] fix --- src/global.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/global.test.ts b/src/global.test.ts index 52ccda8f..3ffd8a24 100644 --- a/src/global.test.ts +++ b/src/global.test.ts @@ -45,7 +45,7 @@ before(async function (this: Mocha.Context): Promise { await initializeConnectionStrings(); const { only } = getTestFileFilter(); - if (only?.startsWith(ServiceBus.serviceBusTestFileName)) { + if (only === ServiceBus.serviceBusTestFileName) { await runSqlSetupQueries(); await setupCosmosDB(); } From 5f68465c1915a76b771e9a7dc06506a1389fa852 Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Mon, 11 Aug 2025 02:26:56 -0500 Subject: [PATCH 142/142] fix --- src/global.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/global.test.ts b/src/global.test.ts index 3ffd8a24..52ccda8f 100644 --- a/src/global.test.ts +++ b/src/global.test.ts @@ -45,7 +45,7 @@ before(async function (this: Mocha.Context): Promise { await initializeConnectionStrings(); const { only } = getTestFileFilter(); - if (only === ServiceBus.serviceBusTestFileName) { + if (only?.startsWith(ServiceBus.serviceBusTestFileName)) { await runSqlSetupQueries(); await setupCosmosDB(); }