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
Original file line number Diff line number Diff line change
Expand Up @@ -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 = [
Expand Down
1 change: 1 addition & 0 deletions Composer/packages/client/src/router.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ const Routes = (props) => {
<Notifications path="notifications" />
<Publish path="publish/:targetName" />
<Skills path="skills/*" />
<DesignPage path="*" />
</ProjectRouter>
<BotCreationFlowRouter path="projects/*" />
<BotCreationFlowRouter path="home" />
Expand Down
24 changes: 20 additions & 4 deletions Composer/packages/server/src/models/bot/botProject.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
};

Expand Down Expand Up @@ -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.');
}
}
Expand Down
21 changes: 12 additions & 9 deletions Composer/plugins/localPublish/src/copyDir.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<string>
) {
if (!(await srcStorage.exists(srcDir)) || !(await srcStorage.stat(srcDir)).isDir) {
throw new Error(`No such dir ${srcDir}}`);
}
Expand All @@ -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) {
Expand All @@ -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);
}
}
}
31 changes: 20 additions & 11 deletions Composer/plugins/localPublish/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -124,7 +124,7 @@ class LocalPublisher implements PublishPlugin<PublishConfig> {
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}`);
Expand Down Expand Up @@ -189,7 +189,7 @@ class LocalPublisher implements PublishPlugin<PublishConfig> {
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());
}
}
Expand All @@ -206,7 +206,7 @@ class LocalPublisher implements PublishPlugin<PublishConfig> {
const manifestDstDir = this.getManifestDstDir(dstPath);

if (await this.dirExist(manifestDstDir)) {
await rmDir(manifestDstDir);
await removeDirAndFiles(manifestDstDir);
}

if (await this.dirExist(manifestSrcDir)) {
Expand Down Expand Up @@ -430,25 +430,34 @@ export default async (composer: ComposerPluginRegistration): Promise<void> => {
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<string> = 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);
};
Expand Down
2 changes: 1 addition & 1 deletion azure-pipelines.yml
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ jobs:
scanType: 'Register'
verbosity: 'Verbose'
alertWarningLevel: 'High'
failOnAlert: false
failOnAlert: true



4 changes: 1 addition & 3 deletions runtime/dotnet/azurewebapp/Schemas/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -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!
21 changes: 21 additions & 0 deletions runtime/dotnet/azurewebapp/Schemas/update-schema.ps1
Original file line number Diff line number Diff line change
@@ -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
}
24 changes: 24 additions & 0 deletions runtime/dotnet/azurewebapp/Schemas/update-schema.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#!/bin/bash
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We probably want a set -e for this script.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently bfdialog has two bugs

  1. On error it deletes the sdk.schema file and leaves the user with no schema file
  2. It returns the 0 code despite error in merging schemas
    Both these are in GH. To overcome this I take a backup of the file and revert to the backup if the bfdialog process does not generate a new sdk.schema file.

Unless they fix both these issues adding set -e might be risky for us. Let's say they fix just the error code bug. That still leaves our shell script in an unstable state since on error, the script exits immediately. This leaves the user with no .schema file as the portion of the script where I revert back to the original schema file will be skipped. Let me know if Im missing something here

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That makes sense. Are those issues with the CLI being tracked? Is that what you mean by "Both these are in GH"?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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
2 changes: 0 additions & 2 deletions runtime/dotnet/azurewebapp/Schemas/update.sh

This file was deleted.