diff --git a/Composer/packages/client/src/components/CreationFlow/CreateOptions/index.tsx b/Composer/packages/client/src/components/CreationFlow/CreateOptions/index.tsx index 987e837ef9..87c9811717 100644 --- a/Composer/packages/client/src/components/CreationFlow/CreateOptions/index.tsx +++ b/Composer/packages/client/src/components/CreationFlow/CreateOptions/index.tsx @@ -80,11 +80,16 @@ export function CreateOptions(props) { }; const handleJumpToNext = () => { + let routeToTemplate = emptyBotKey; if (option === optionKeys.createFromTemplate) { - onNext(currentTemplate); - } else { - onNext(emptyBotKey); + routeToTemplate = currentTemplate; + } + + if (props.location && props.location.search) { + routeToTemplate += props.location.search; } + + onNext(routeToTemplate); }; const tableColums = [ diff --git a/Composer/packages/client/src/router.tsx b/Composer/packages/client/src/router.tsx index 2cc72d19a0..d0c1edb01a 100644 --- a/Composer/packages/client/src/router.tsx +++ b/Composer/packages/client/src/router.tsx @@ -51,6 +51,7 @@ const Routes = (props) => { + diff --git a/Composer/packages/server/src/models/bot/botProject.ts b/Composer/packages/server/src/models/bot/botProject.ts index 95d33ba96f..ec318d5207 100644 --- a/Composer/packages/server/src/models/bot/botProject.ts +++ b/Composer/packages/server/src/models/bot/botProject.ts @@ -150,7 +150,7 @@ export class BotProject { try { this.fileStorage.zip(this.dataDir, cb); } catch (e) { - console.log('error zipping assets', e); + debug('error zipping assets', e); } }; @@ -187,10 +187,26 @@ export class BotProject { url: schemaUrl, responseType: 'stream', }); - const pathToSchema = `${pathToSave}/Schemas`; - await mkDirAsync(pathToSchema); - response.data.pipe(fs.createWriteStream(`${pathToSchema}/sdk.schema`)); + const dirToSchema = `${pathToSave}/schemas`; + await mkDirAsync(dirToSchema); + const writer = fs.createWriteStream(`${dirToSchema}/sdk.schema`); + + await new Promise((resolve, reject) => { + response.data.pipe(writer); + let error; + writer.on('error', (err) => { + error = err; + writer.close(); + reject(err); + }); + writer.on('close', () => { + if (!error) { + resolve(); + } + }); + }); } catch (ex) { + debug(`Custom Schema download error: ${ex}`); throw new Error('Schema file could not be downloaded. Please check the url to the schema.'); } } diff --git a/Composer/plugins/localPublish/src/copyDir.ts b/Composer/plugins/localPublish/src/copyDir.ts index e6da618d99..a41ad5e44d 100644 --- a/Composer/plugins/localPublish/src/copyDir.ts +++ b/Composer/plugins/localPublish/src/copyDir.ts @@ -3,14 +3,13 @@ import { IFileStorage } from './interface'; -/** - * Copy a dir from one storage to another storage - * @param srcDir path of the src dir - * @param srcStorage src storage - * @param dstDir path of the dst dir - * @param dstStorage dst storage - */ -export async function copyDir(srcDir: string, srcStorage: IFileStorage, dstDir: string, dstStorage: IFileStorage) { +export async function copyDir( + srcDir: string, + srcStorage: IFileStorage, + dstDir: string, + dstStorage: IFileStorage, + pathsToExclude?: Set +) { if (!(await srcStorage.exists(srcDir)) || !(await srcStorage.stat(srcDir)).isDir) { throw new Error(`No such dir ${srcDir}}`); } @@ -20,8 +19,12 @@ export async function copyDir(srcDir: string, srcStorage: IFileStorage, dstDir: } const paths = await srcStorage.readDir(srcDir); + for (const path of paths) { const srcPath = `${srcDir}/${path}`; + if (pathsToExclude && pathsToExclude.has(srcPath)) { + continue; + } const dstPath = `${dstDir}/${path}`; if ((await srcStorage.stat(srcPath)).isFile) { @@ -30,7 +33,7 @@ export async function copyDir(srcDir: string, srcStorage: IFileStorage, dstDir: await dstStorage.writeFile(dstPath, content); } else { // recursively copy dirs - await copyDir(srcPath, srcStorage, dstPath, dstStorage); + await copyDir(srcPath, srcStorage, dstPath, dstStorage, pathsToExclude); } } } diff --git a/Composer/plugins/localPublish/src/index.ts b/Composer/plugins/localPublish/src/index.ts index 5ebd4b8cb9..be606379d3 100644 --- a/Composer/plugins/localPublish/src/index.ts +++ b/Composer/plugins/localPublish/src/index.ts @@ -20,7 +20,7 @@ const stat = promisify(fs.stat); const readDir = promisify(fs.readdir); const removeFile = promisify(fs.unlink); const mkDir = promisify(fs.mkdir); -const rmDir = promisify(rimraf); +const removeDirAndFiles = promisify(rimraf); const copyFile = promisify(fs.copyFile); interface RunningBot { @@ -124,7 +124,7 @@ class LocalPublisher implements PublishPlugin { return { msg: `runtime path ${targetDir} does not exist` }; } try { - await rmDir(targetDir); + await removeDirAndFiles(targetDir); return { msg: `successfully removed runtime data in ${targetDir}` }; } catch (e) { throw new Error(`Failed to remove ${targetDir}`); @@ -189,7 +189,7 @@ class LocalPublisher implements PublishPlugin { execSync('dotnet build', { cwd: runtimeDir, stdio: 'inherit' }); } catch (error) { // delete the folder to make sure build again. - rmDir(botDir); + await removeDirAndFiles(botDir); throw new Error(error.toString()); } } @@ -206,7 +206,7 @@ class LocalPublisher implements PublishPlugin { const manifestDstDir = this.getManifestDstDir(dstPath); if (await this.dirExist(manifestDstDir)) { - await rmDir(manifestDstDir); + await removeDirAndFiles(manifestDstDir); } if (await this.dirExist(manifestSrcDir)) { @@ -430,25 +430,34 @@ export default async (composer: ComposerPluginRegistration): Promise => { key: 'azurewebapp', name: 'C#', startCommand: 'dotnet run --project azurewebapp', - eject: async (project: any, localDisk: IFileStorage) => { + eject: async (project, localDisk: IFileStorage) => { const sourcePath = path.resolve(__dirname, '../../../../runtime/dotnet'); const destPath = path.join(project.dir, 'runtime'); - const schemaSrcPath = path.join(sourcePath, 'azurewebapp/Schemas'); - const schemaDstPath = path.join(project.dir, 'schemas'); if (!(await project.fileStorage.exists(destPath))) { // used to read bot project template from source (bundled in plugin) await copyDir(sourcePath, localDisk, destPath, project.fileStorage); - await copyDir(schemaSrcPath, localDisk, schemaDstPath, project.fileStorage); + const schemaDstPath = path.join(project.dir, 'schemas'); + const schemaSrcPath = path.join(sourcePath, 'azurewebapp/schemas'); + const customSchemaExists = fs.existsSync(schemaDstPath); + const pathsToExclude: Set = new Set(); + if (customSchemaExists) { + const sdkExcludePath = await localDisk.glob('sdk.schema', schemaSrcPath); + if (sdkExcludePath.length > 0) { + pathsToExclude.add(path.join(schemaSrcPath, sdkExcludePath[0])); + } + } + await copyDir(schemaSrcPath, localDisk, schemaDstPath, project.fileStorage, pathsToExclude); + const schemaFolderInRuntime = path.join(destPath, 'azurewebapp/schemas'); + await removeDirAndFiles(schemaFolderInRuntime); return destPath; - } else { - throw new Error(`Runtime already exists at ${destPath}`); } + throw new Error(`Runtime already exists at ${destPath}`); }, }); }; // stop all the runningBot when process exit -const cleanup = (signal: NodeJS.Signals) => { +const cleanup = () => { LocalPublisher.stopAll(); process.exit(0); }; diff --git a/azure-pipelines.yml b/azure-pipelines.yml index d311ff6f3e..d5faf63304 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -83,7 +83,7 @@ jobs: scanType: 'Register' verbosity: 'Verbose' alertWarningLevel: 'High' - failOnAlert: false + failOnAlert: true diff --git a/runtime/dotnet/azurewebapp/Schemas/readme.md b/runtime/dotnet/azurewebapp/Schemas/readme.md index bbbe520a40..89934816da 100644 --- a/runtime/dotnet/azurewebapp/Schemas/readme.md +++ b/runtime/dotnet/azurewebapp/Schemas/readme.md @@ -49,10 +49,8 @@ ComponentRegistration.Add(new CustomActionComponentRegistration()); - Run the command `dotnet build` on the azurewebapp project to verify if it passes build after adding custom actions to it. -- Navigate to to the `Schemas (bot/runtime/azurewebapp/Schemas)` folder and then run the command `sh update.sh`. +- Navigate to to the `schemas (bot/schemas)` folder. This folder contains a Powershell script and a bash script. Run either of these scripts `./update-schema.ps1 -runtime azurewebapp` or `sh ./update-schema.sh -runtime azurewebapp`. The runtime `azurewebapp` is chosen by default if no argument is passed. - Validate that the partial schema (MultiplyDialog.schema inside customaction/Schema) has been appended to the default sdk.schema file to generate one single consolidated sdk.schema file. -- Copy the newly generated sdk.schema into the `schemas (bot/schemas)` folder at the root of the ejected runtime. - The above steps should have generated a new sdk.schema file inside `schemas` folder for Composer to use. Reload the bot and you should be able to include your new custom action! diff --git a/runtime/dotnet/azurewebapp/Schemas/update-schema.ps1 b/runtime/dotnet/azurewebapp/Schemas/update-schema.ps1 new file mode 100644 index 0000000000..a8b22ef230 --- /dev/null +++ b/runtime/dotnet/azurewebapp/Schemas/update-schema.ps1 @@ -0,0 +1,21 @@ +param ( + [string]$runtime = "azurewebapp" +) +$SCHEMA_FILE="sdk.schema" +$BACKUP_SCHEMA_FILE="sdk-backup.schema" + +Write-Host "Running schema merge on $runtime runtime." + +Move-Item -Force -Path $SCHEMA_FILE -Destination $BACKUP_SCHEMA_FILE + +bf dialog:merge "*.schema" "../runtime/$runtime/*.csproj" -o $SCHEMA_FILE -v + +if (Test-Path $SCHEMA_FILE -PathType leaf) +{ + Remove-Item -Force -Path $BACKUP_SCHEMA_FILE + Write-Host "Schema merged succesfully." +} +else +{ + Move-Item -Force -Path $BACKUP_SCHEMA_FILE -Destination $SCHEMA_FILE +} diff --git a/runtime/dotnet/azurewebapp/Schemas/update-schema.sh b/runtime/dotnet/azurewebapp/Schemas/update-schema.sh new file mode 100644 index 0000000000..1763e3ba74 --- /dev/null +++ b/runtime/dotnet/azurewebapp/Schemas/update-schema.sh @@ -0,0 +1,24 @@ +#!/bin/bash +runtime=${runtime:-azurewebapp} +SCHEMA_FILE=sdk.schema +BACKUP_SCHEMA_FILE=sdk-backup.schema + +while [ $# -gt 0 ]; do + if [[ $1 == *"-"* ]]; then + param="${1/-/}" + declare $param="$2" + fi + shift +done + +echo "Running schema merge on $runtime runtime." +mv "./$SCHEMA_FILE" "./$BACKUP_SCHEMA_FILE" + +bf dialog:merge "*.schema" "../runtime/$runtime/*.csproj" -o $SCHEMA_FILE -v + +if [ -f "$SCHEMA_FILE" ]; then + echo "Schema merged succesfully." + rm -rf "./$BACKUP_SCHEMA_FILE" +else + mv "./$BACKUP_SCHEMA_FILE" "./$SCHEMA_FILE" +fi diff --git a/runtime/dotnet/azurewebapp/Schemas/update.sh b/runtime/dotnet/azurewebapp/Schemas/update.sh deleted file mode 100644 index c9f8544cdb..0000000000 --- a/runtime/dotnet/azurewebapp/Schemas/update.sh +++ /dev/null @@ -1,2 +0,0 @@ -cd .. -bf dialog:merge *.csproj -o ./schemas/sdk.schema -v