Skip to content

Commit

Permalink
M4 master merge (#695)
Browse files Browse the repository at this point in the history
* Emit Signal method and delegate to provide a hook into events

* Update Az.Accounts dependency to 1.8.4

* Adding target attribute to nuspec file elements

* Using backslash path separator in nuspec for cross platform compatability

* Remove Init method constructor call.

* Revert "Emit Signal method and delegate to provide a hook into events"

* Emit Signal method and delegate to provide hook into events for Non-Azure scenarios.

* Update ISendAsync.cs (#662)

* Update ISendAsync.cs

pass only Authorization to next header for long running operations.

* Update ISendAsync.cs

* Update ISendAsync.cs

fix potential null reference

* Update ISendAsync.cs

* Update ISendAsync.cs

* Update ISendAsync.cs

* update gitignore (#670)

* Add scan pipelines (#681)

* Update development.md - add how to debug (#683)

* Update development.md

* Update development.md

* Fix some merging issues

Co-authored-by: George Ndungu <[email protected]>
Co-authored-by: Tim Mullender <[email protected]>
Co-authored-by: Yabo Hu <[email protected]>
Co-authored-by: Yeming Liu <[email protected]>
Co-authored-by: Dingmeng Xue <[email protected]>
  • Loading branch information
6 people authored Oct 13, 2020
1 parent ac262b1 commit ce56adb
Show file tree
Hide file tree
Showing 92 changed files with 2,332 additions and 2,021 deletions.
Empty file.
50 changes: 50 additions & 0 deletions .azure-pipelines/daily-build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# Please don't use ADO UI defined scheduled triggers because it takes precedence over YAML scheduled triggers.
# https://docs.microsoft.com/en-us/azure/devops/pipelines/process/scheduled-triggers
schedules:
- cron: "0 0 * * *"
displayName: Daily Midnight Build
branches:
include:
- master

trigger: none
pr: none

pool:
name: Hosted VS2017
demands: npm

steps:
- task: NodeTool@0
displayName: 'Use Node 10.16.0'
inputs:
versionSpec: 10.16.0

- task: Npm@1
displayName: 'Install autorest@beta'
inputs:
command: custom
verbose: false
customCommand: 'install -g "@autorest/autorest"'

- task: Npm@1
displayName: 'Install @microsoft/rush'
inputs:
command: custom
verbose: false
customCommand: 'install -g @microsoft/[email protected]'

- task: CmdLine@2
displayName: 'Rush sync-versions'
inputs:
script: 'rush sync-versions'

- task: CmdLine@2
displayName: 'Rush Update'
inputs:
script: 'rush update'

- task: CmdLine@2
displayName: 'Rush Rebuild'
inputs:
script: 'rush rebuild'
15 changes: 15 additions & 0 deletions .azure-pipelines/security-scan.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
trigger:
branches:
include:
- '*'

pool:
vmImage: "windows-2019"

steps:
- task: ms-codeanalysis.vss-microsoft-security-code-analysis-devops.build-task-credscan.CredScan@2
displayName: 'Run CredScan'
continueOnError: true
inputs:
toolMajorVersion: "V2"
suppressionsFile: .azure-pipelines\credscan-suppressions.json
3 changes: 2 additions & 1 deletion docs/development.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,8 @@ To use the locally built version of the plugin, add `--use:<path>` to the comman

### Debugging

COMING SOON.
1. Start generating: `autorest-beta --use:C:\path\to\local\autorest.powershell --powershell.debugger`. It will wait for debugger to attach.
1. Start debugging: open autorest.powershell repo in vscode; press `F5`. You will see "Debugger attached." in your autorest console, then you can start debugging.

### Testing

Expand Down
8 changes: 8 additions & 0 deletions powershell/cmdlets/class.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1091,6 +1091,10 @@ export class CmdletClass extends Class {
// in azure mode, we signal the AzAccount module with every event that makes it here.
yield `await ${$this.state.project.serviceNamespace.moduleClass.declaration}.Instance.Signal(${id.value}, ${token.value}, ${messageData.value}, (i,t,m) => ((${ClientRuntime.IEventListener})this).Signal(i,t,()=> ${ClientRuntime.EventDataConverter}.ConvertFrom( m() ) as ${ClientRuntime.EventData} ), ${$this.invocationInfo.value}, this.ParameterSetName, ${$this.correlationId.value}, ${$this.processRecordId.value}, null );`;
yield If(`${token.value}.IsCancellationRequested`, Return());
} else {
// In Non-Azure Modes, emit the Signal method without coorelation and processrecordid
yield `await ${$this.state.project.serviceNamespace.moduleClass.declaration}.Instance.Signal(${id.value}, ${token.value}, ${messageData.value}, (i,t,m) => ((${ClientRuntime.IEventListener})this).Signal(i,t,()=> ${ClientRuntime.EventDataConverter}.ConvertFrom( m() ) as ${ClientRuntime.EventData} ), ${$this.invocationInfo.value}, this.ParameterSetName, null );`;
yield If(`${token.value}.IsCancellationRequested`, Return());
}
yield `WriteDebug($"{id}: {(messageData().Message ?? ${System.String.Empty})}");`;
// any handling of the signal on our side...
Expand Down Expand Up @@ -2310,6 +2314,10 @@ export class NewCmdletClass extends Class {
// in azure mode, we signal the AzAccount module with every event that makes it here.
yield `await ${$this.state.project.serviceNamespace.moduleClass.declaration}.Instance.Signal(${id.value}, ${token.value}, ${messageData.value}, (i,t,m) => ((${ClientRuntime.IEventListener})this).Signal(i,t,()=> ${ClientRuntime.EventDataConverter}.ConvertFrom( m() ) as ${ClientRuntime.EventData} ), ${$this.invocationInfo.value}, this.ParameterSetName, ${$this.correlationId.value}, ${$this.processRecordId.value}, null );`;
yield If(`${token.value}.IsCancellationRequested`, Return());
} else {
// In Non-Azure Modes, emit the Signal method without coorelation and processrecordid
yield `await ${$this.state.project.serviceNamespace.moduleClass.declaration}.Instance.Signal(${id.value}, ${token.value}, ${messageData.value}, (i,t,m) => ((${ClientRuntime.IEventListener})this).Signal(i,t,()=> ${ClientRuntime.EventDataConverter}.ConvertFrom( m() ) as ${ClientRuntime.EventData} ), ${$this.invocationInfo.value}, this.ParameterSetName, null );`;
yield If(`${token.value}.IsCancellationRequested`, Return());
}
yield `WriteDebug($"{id}: {(messageData().Message ?? ${System.String.Empty})}");`;
// any handling of the signal on our side...
Expand Down
1 change: 1 addition & 0 deletions powershell/generators/gitignore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ obj
generated
internal
exports
tools
custom/*.psm1
test/*-TestResults.xml
/*.ps1
Expand Down
12 changes: 6 additions & 6 deletions powershell/generators/nuspec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,12 @@ export async function generateNuspec(project: Project | NewProject) {
<file src="${removeCd(project.psm1)}" />
<!-- https://github.com/NuGet/Home/issues/3584 -->
<file src="${removeCd(project.dll)}" target="${removeCd(project.binFolder)}" />
<file src="${removeCd(project.binFolder)}/${project.dllName}.deps.json" target="${removeCd(project.binFolder)}" />
<file src="${removeCd(project.internalFolder)}/**/*.*" exclude="${removeCd(project.internalFolder)}/readme.md" />
<file src="${removeCd(project.customFolder)}/**/*.*" exclude="${removeCd(project.customFolder)}/readme.md;${removeCd(project.customFolder)}/**/*.cs" />
<file src="${removeCd(project.docsFolder)}/**/*.md" exclude="${removeCd(project.docsFolder)}/readme.md" />
<file src="${removeCd(project.exportsFolder)}/**/ProxyCmdletDefinitions.ps1" />
<file src="${removeCd(project.utilsFolder)}/**/*.*" />
<file src="${removeCd(project.binFolder)}\\${project.dllName}.deps.json" target="${removeCd(project.binFolder)}" />
<file src="${removeCd(project.internalFolder)}\\**\\*.*" exclude="${removeCd(project.internalFolder)}\\readme.md" target="${removeCd(project.internalFolder)}" />
<file src="${removeCd(project.customFolder)}\\**\\*.*" exclude="${removeCd(project.customFolder)}\\readme.md;${removeCd(project.customFolder)}\\**\\*.cs" target="${removeCd(project.customFolder)}" />
<file src="${removeCd(project.docsFolder)}\\**\\*.md" exclude="${removeCd(project.docsFolder)}\\readme.md" target="${removeCd(project.docsFolder)}" />
<file src="${removeCd(project.exportsFolder)}\\**\\ProxyCmdletDefinitions.ps1" target="${removeCd(project.exportsFolder)}" />
<file src="${removeCd(project.utilsFolder)}\\**\\*.*" target="${removeCd(project.utilsFolder)}" />
</files>
</package>`, undefined, 'source-file-other');
}
Expand Down
4 changes: 2 additions & 2 deletions powershell/internal/project.ts
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ export class Project extends codeDomProject {
// Values
this.moduleVersion = await this.state.getValue('module-version');
this.profiles = this.model.info.extensions['x-ms-metadata'].profiles || [];
this.accountsVersionMinimum = '1.7.4';
this.accountsVersionMinimum = '1.8.1';
this.helpLinkPrefix = await this.state.getValue('help-link-prefix');
this.metadata = await this.state.getValue<Metadata>('metadata');
this.license = await this.state.getValue('header-text', '');
Expand Down Expand Up @@ -335,7 +335,7 @@ export class NewProject extends codeDomProject {
// skip-for-time-being
//this.profiles = this.model.info.extensions['x-ms-metadata'].profiles || [];
this.profiles = [];
this.accountsVersionMinimum = '1.7.4';
this.accountsVersionMinimum = '1.8.1';
this.helpLinkPrefix = await this.state.getValue('help-link-prefix');
this.metadata = await this.state.getValue<Metadata>('metadata');
this.license = await this.state.getValue('header-text', '');
Expand Down
61 changes: 61 additions & 0 deletions powershell/module/module-class.ts
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,21 @@ export class ModuleClass extends Class {

createInitAndPipeline(namespace: Namespace) {
const $this = this;
// Custom Event Listener without Azure Spefic concepts. (ProcessId and CorelationId)
const customEventListenerFunc = System.Func(
dotnet.String,
System.Threading.CancellationToken,
System.Func(System.EventArgs),
this.incomingSignalFunc,
InvocationInfo,
dotnet.String,
System.Exception,
/* returns */ System.Threading.Tasks.Task());

const incomingSignalDelegate = namespace.add(new Alias('SignalDelegate', this.incomingSignalFunc));
const eventListenerDelegate = namespace.add(new Alias('EventListenerDelegate', customEventListenerFunc));
const EventListener = this.add(new Property('EventListener', eventListenerDelegate, { description: 'A delegate that gets called for each signalled event' }));

// non-azure init method
this.initMethod.add(function* () {
yield '// called at module init time...';
Expand All @@ -152,6 +167,22 @@ export class ModuleClass extends Class {
});

this.add(new LambdaProperty('Name', dotnet.String, new StringExpression(this.state.project.moduleName), { description: 'The Name of this module ' }));

// Add Signal extensibility point
const pSignal = new Parameter('signal', incomingSignalDelegate, { description: 'The callback for the event dispatcher ' });
// Emit signal extensibility points that called EventListenerDelegate, allowing us to handle Signals emitted by the Pipeline in the Auth Module
const signalImpl = this.add(new Method('Signal', System.Threading.Tasks.Task(), {
parameters: [this.pId, this.pToken, this.pGetEventData, pSignal, this.pInvocationInfo, this.pParameterSetName, this.pException], async: Modifier.Async,
description: 'Called to dispatch events to the common module listener',
returnsDescription: `A <see cref="${System.Threading.Tasks.Task()}" /> that will be complete when handling of the event is completed.`
}));

signalImpl.push(Using('NoSynchronizationContext', ''));
signalImpl.add(function* () {
// Emit call to EventListener after explicit null check.
// Not using Null-Conditional operator causes Null Reference exception when Func<Task> is null, due to awaiting null Task.
yield If(`${EventListener.value} != null`, `await ${EventListener.value}.Invoke(${$this.pId.value},${$this.pToken.value},${$this.pGetEventData.value}, ${pSignal.value}, ${$this.pInvocationInfo}, ${$this.pParameterSetName},${$this.pException});`)
});
}

createAzureInitAndPipeline(namespace: Namespace) {
Expand Down Expand Up @@ -379,6 +410,20 @@ export class NewModuleClass extends Class {

createInitAndPipeline(namespace: Namespace) {
const $this = this;
// Custom Event Listener without Azure Spefic concepts. (ProcessId and CorelationId)
const customEventListenerFunc = System.Func(
dotnet.String,
System.Threading.CancellationToken,
System.Func(System.EventArgs),
this.incomingSignalFunc,
InvocationInfo,
dotnet.String,
System.Exception,
/* returns */ System.Threading.Tasks.Task());

const incomingSignalDelegate = namespace.add(new Alias('SignalDelegate', this.incomingSignalFunc));
const eventListenerDelegate = namespace.add(new Alias('EventListenerDelegate', customEventListenerFunc));
const EventListener = this.add(new Property('EventListener', eventListenerDelegate, { description: 'A delegate that gets called for each signalled event' }));

// non-azure init method
this.initMethod.add(function* () {
Expand All @@ -403,6 +448,22 @@ export class NewModuleClass extends Class {
});

this.add(new LambdaProperty('Name', dotnet.String, new StringExpression(this.state.project.moduleName), { description: 'The Name of this module ' }));

// Add Signal extensibility point
const pSignal = new Parameter('signal', incomingSignalDelegate, { description: 'The callback for the event dispatcher ' });
// Emit signal extensibility points that called EventListenerDelegate, allowing us to handle Signals emitted by the Pipeline in the Auth Module
const signalImpl = this.add(new Method('Signal', System.Threading.Tasks.Task(), {
parameters: [this.pId, this.pToken, this.pGetEventData, pSignal, this.pInvocationInfo, this.pParameterSetName, this.pException], async: Modifier.Async,
description: 'Called to dispatch events to the common module listener',
returnsDescription: `A <see cref="${System.Threading.Tasks.Task()}" /> that will be complete when handling of the event is completed.`
}));

signalImpl.push(Using('NoSynchronizationContext', ''));
signalImpl.add(function* () {
// Emit call to EventListener after explicit null check.
// Not using Null-Conditional operator causes Null Reference exception when Func<Task> is null, due to awaiting null Task.
yield If(`${EventListener.value} != null`, `await ${EventListener.value}.Invoke(${$this.pId.value},${$this.pToken.value},${$this.pGetEventData.value}, ${pSignal.value}, ${$this.pInvocationInfo}, ${$this.pParameterSetName},${$this.pException});`)
});
}

createAzureInitAndPipeline(namespace: Namespace) {
Expand Down
2 changes: 1 addition & 1 deletion powershell/resources/assets/tools/Resources/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ This directory contains the PowerShell module for the Resources service.
This module was primarily generated via [AutoRest](https://github.com/Azure/autorest) using the [PowerShell](https://github.com/Azure/autorest.powershell) extension.

## Module Requirements
- [Az.Accounts module](https://www.powershellgallery.com/packages/Az.Accounts/), version 1.7.4 or greater
- [Az.Accounts module](https://www.powershellgallery.com/packages/Az.Accounts/), version 1.8.1 or greater

## Authentication
AutoRest does not generate authentication code for the module. Authentication is handled via Az.Accounts by altering the HTTP payload before it is sent.
Expand Down
Loading

0 comments on commit ce56adb

Please sign in to comment.