Skip to content
This repository was archived by the owner on Jul 9, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Composer/packages/types/src/runtime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ type MakeDirectoryOptions = {
recursive?: boolean;
};

type IFileStorage = {
export type IFileStorage = {
stat(path: string): Promise<Stat>;
readFile(path: string): Promise<string>;
readDir(path: string): Promise<string[]>;
Expand Down
5 changes: 3 additions & 2 deletions extensions/azurePublish/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -95,9 +95,10 @@
"@botframework-composer/types": "file:../../Composer/packages/types",
"@types/archiver": "5.3.1",
"@types/fs-extra": "9.0.13",
"@types/jest": "ts3.9",
"@types/node": "18.0.3",
"@types/react": "^16.9.53",
"@types/react-dom": "18.0.6",
"@types/react": "^17.0.39",
"@types/react-dom": "^17.0.11",
"@types/request": "2.48.8",
"@types/request-promise": "4.1.48",
"html-webpack-plugin": "5.5.0",
Expand Down
9 changes: 4 additions & 5 deletions extensions/azurePublish/src/node/deploy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { TokenCredentials } from '@azure/ms-rest-js';
import { DialogSetting } from '@botframework-composer/types';

import { BotProjectDeployConfig, BotProjectDeployLoggerType } from './types';
import { build, publishLuisToPrediction } from './luisAndQnA';
import { build, BuildSettingType, publishLuisToPrediction } from './luisAndQnA';
import { AzurePublishErrors, createCustomizeError, stringifyError } from './utils/errorHandler';
import { copyDir } from './utils/copyDir';
import { KeyVaultApi } from './keyvaultHelper/keyvaultApi';
Expand Down Expand Up @@ -45,7 +45,7 @@ export class BotProjectDeploy {
*/
public async deploy(
project: any,
settings: DialogSetting,
settings: BuildSettingType<DialogSetting>,
profileName: string,
name: string,
environment: string,
Expand Down Expand Up @@ -100,8 +100,7 @@ export class BotProjectDeploy {
settings.luis,
luisResource,
this.projPath,
this.logger,
settings?.runtime
this.logger
);

const qnaConfig = await project.builder.getQnaConfig();
Expand Down Expand Up @@ -247,7 +246,7 @@ export class BotProjectDeploy {
const archive = archiver('zip', { zlib: { level: 9 } });
// eslint-disable-next-line security/detect-non-literal-fs-filename
const stream = fs.createWriteStream(out);
return new Promise((resolve, reject) => {
return new Promise<void>((resolve, reject) => {
archive
.glob('**/*', {
cwd: source,
Expand Down
23 changes: 12 additions & 11 deletions extensions/azurePublish/src/node/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
PublishResponse,
PublishResult,
SDKKinds,
PublishProfile,
} from '@botframework-composer/types';
import { parseRuntimeKey, applyPublishingProfileToSettings } from '@bfc/shared';
import { indexer } from '@bfc/indexers';
Expand Down Expand Up @@ -48,7 +49,7 @@ interface DeployResources {
abs?: any;
}

interface PublishConfig {
interface PublishConfig extends PublishProfile {
fullSettings: any;
profileName: string; //profile name
[key: string]: any;
Expand Down Expand Up @@ -631,7 +632,7 @@ export default async (composer: IExtensionRegistration): Promise<void> => {

private isProfileProvisioned = (profile: PublishConfig): boolean => {
//TODO: Post-migration we can check for profile?.tenantId
return profile?.resourceGroup && profile?.subscriptionId && profile?.region;
return !!(profile?.resourceGroup && profile?.subscriptionId && profile?.region);
};

// While the provisioning process may return more information for various resources than is checked here,
Expand All @@ -640,36 +641,36 @@ export default async (composer: IExtensionRegistration): Promise<void> => {
switch (resource.key) {
case AzureResourceTypes.APPINSIGHTS:
// InstrumentationKey is Pascal-cased for some unknown reason
return profile?.settings?.applicationInsights?.InstrumentationKey;
return !!profile?.settings?.applicationInsights?.InstrumentationKey;
case AzureResourceTypes.APP_REGISTRATION:
// MicrosoftAppId and MicrosoftAppPassword are Pascal-cased for some unknown reason
return profile?.settings?.MicrosoftAppId && profile?.settings?.MicrosoftAppPassword;
return !!(profile?.settings?.MicrosoftAppId && profile?.settings?.MicrosoftAppPassword);
case AzureResourceTypes.BLOBSTORAGE:
// name is not checked (not in schema.ts)
// container property is not checked (empty may be a valid value)
return profile?.settings?.blobStorage?.connectionString;
return !!profile?.settings?.blobStorage?.connectionString;
case AzureResourceTypes.BOT_REGISTRATION:
return profile?.botName;
return !!profile?.botName;
case AzureResourceTypes.COSMOSDB:
// collectionId is not checked (not in schema.ts)
// databaseId and containerId are not checked (empty may be a valid value)
return profile?.settings?.cosmosDB?.authKey && profile?.settings?.cosmosDB?.cosmosDBEndpoint;
return !!(profile?.settings?.cosmosDb?.authKey && profile?.settings?.cosmosDb?.cosmosDBEndpoint);
case AzureResourceTypes.LUIS_AUTHORING:
// region is not checked (empty may be a valid value)
return profile?.settings?.luis?.authoringKey && profile?.settings?.luis?.authoringEndpoint;
return !!(profile?.settings?.luis?.authoringKey && profile?.settings?.luis?.authoringEndpoint);
case AzureResourceTypes.LUIS_PREDICTION:
// region is not checked (empty may be a valid value)
return profile?.settings?.luis?.endpointKey && profile?.settings?.luis?.endpoint;
return !!(profile?.settings?.luis?.endpointKey && profile?.settings?.luis?.endpoint);
case AzureResourceTypes.QNA:
// endpoint is not checked (it is in schema.ts and provision() returns the value, but it is not set in the config)
// qnaRegion is not checked (empty may be a valid value)
return profile?.settings?.qna?.subscriptionKey;
return !!profile?.settings?.qna?.subscriptionKey;
case AzureResourceTypes.SERVICE_PLAN:
// no settings exist to verify the service plan was created
return true;
case AzureResourceTypes.AZUREFUNCTIONS:
case AzureResourceTypes.WEBAPP:
return profile?.hostname;
return !!profile?.hostname;
default:
throw new Error(
formatMessage('Azure resource type {resourceKey} is not handled.', { resourceKey: resource.key })
Expand Down
21 changes: 10 additions & 11 deletions extensions/azurePublish/src/node/luisAndQnA.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import axios, { AxiosRequestConfig } from 'axios';
import { AzurePublishErrors } from './utils/errorHandler';
import { BotProjectDeployLoggerType } from './types';

const botPath = (projPath: string, runtime?: DialogSetting['runtime']) => projPath;
const botPath = (projPath: string) => projPath;

type QnaConfigType = {
subscriptionKey: string;
Expand All @@ -24,13 +24,15 @@ type Resources = {
qnaResources: Resource[];
};

interface BuildSettingType {
export type BuildSettingType<T = {}> = {
[K in keyof T]: T[K];
} & {
luis: ILuisConfig;
qna: QnaConfigType;
luResources: Resource[];
qnaResources: Resource[];
luResources?: Resource[];
qnaResources?: Resource[];
runtime?: DialogSetting['runtime'];
}
};

function getAccount(accounts: any, filter: string) {
for (const account of accounts) {
Expand Down Expand Up @@ -85,8 +87,7 @@ export async function publishLuisToPrediction(
luisSettings: ILuisConfig,
luisResource: string,
path: string,
logger,
runtime?: RuntimeTemplate
logger
) {
let {
// eslint-disable-next-line prefer-const
Expand All @@ -105,9 +106,7 @@ export async function publishLuisToPrediction(
// Find any files that contain the name 'luis.settings' in them
// These are generated by the LuBuild process and placed in the generated folder
// These contain dialog-to-luis app id mapping
const luisConfigFiles = (await getFiles(botPath(path, runtime))).filter((filename) =>
filename.includes('luis.settings')
);
const luisConfigFiles = (await getFiles(botPath(path))).filter((filename) => filename.includes('luis.settings'));
const luisAppIds: any = {};

// Read in all the luis app id mappings
Expand Down Expand Up @@ -253,7 +252,7 @@ export async function build(project: IBotProject, path: string, settings: BuildS
}
});

builder.rootDir = botPath(path, settings?.runtime);
builder.rootDir = botPath(path);
builder.setBuildConfig({ ...luisConfig, ...qnaConfig }, project.settings.downsampling, project.settings.crossTrain);
await builder.build(luFiles, qnaFiles, Array.from(files.values()) as FileInfo[], emptyFiles);
await builder.copyModelPathToBot();
Expand Down
5 changes: 3 additions & 2 deletions extensions/azurePublish/src/node/provision.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

import { BotProjectProvision, ProvisionConfig } from './provision';

const mockConfig = {
const mockConfig = ({
logger: console.log,
accessToken: 'accessToken',
graphToken: 'graphToken',
Expand All @@ -18,7 +18,8 @@ const mockConfig = {
name: 'profileName',
type: 'azurepublish',
subscription: 'test',
} as ProvisionConfig;
} as unknown) as ProvisionConfig;

const azProvision = new BotProjectProvision(mockConfig);

const mockGet = jest.fn();
Expand Down
2 changes: 1 addition & 1 deletion extensions/azurePublish/src/node/utils/copyDir.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

import Path from 'path';

import { IFileStorage } from './interface';
import { IFileStorage } from '@botframework-composer/types';

export async function copyDir(
srcDir: string,
Expand Down
7 changes: 6 additions & 1 deletion extensions/azurePublish/tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
{
"compilerOptions": {
"esModuleInterop": true,
"jsx": "react"
"jsx": "react",
"skipLibCheck": true,
"typeRoots": [
"./node_modules/@types/",
],
"types": ["jest"]
},
"include": [
"src/**/*",
Expand Down
Loading