Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: ✨ add new command 'm365 pp pipeline list' to list Powe… #6434

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
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
102 changes: 102 additions & 0 deletions docs/docs/cmd/pp/pipeline/pipeline-list.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
import Global from '/docs/cmd/_global.mdx';
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';

# pp pipeline list

Lists the Power Platform pipelines for the specified environment.

## Usage

```sh
m365 pp pipeline list [options]
```
`-e, --environment <environment>`
: The name or id of the environment for which to list the pipelines.

`--asAdmin`
: Run the command as admin and retrieve pipelines from environments you do not have explicitly assigned permissions to.

<Global />

## Remarks

:::warning

This command is based on an API that is currently in preview and is subject to change once the API reaches general availability.

Register the CLI for Microsoft 365 or Microsoft Entra application as a management application for the Power Platform using

m365 pp managementapp add [options]

:::

## Examples

Retrieve the list of deployment pipelines in the specified Power Platform environment.

```sh
m365 pp pipeline list --environmentName Default-d87a7535-dd31-4437-bfe1-95340acd55c5
```

Retrieve the list of deployment pipelines as admin in the specified Power Platform environment.

```sh
m365 pp pipeline list --environmentName Default-d87a7535-dd31-4437-bfe1-95340acd55c5 --asAdmin
```

## Response

<Tabs>
<TabItem value="JSON">

```json
[
{
"name": "Sales Pipeline",
"deploymentpipelineid": "3ef59632-f087-ef11-8a69-7c1e521ba3ec",
"ownerid": "27f5bb85-6b7a-ef11-ac22-000d3a4e3cc8",
"statuscode": 1
}
]
```
</TabItem>

<TabItem value="Text">

```text
deploymentpipelineid: 3ef59632-f087-ef11-8a69-7c1e521ba3ec
name : Sales Pipeline
ownerid : 27f5bb85-6b7a-ef11-ac22-000d3a4e3cc8
statuscode : 1
```
</TabItem>

<TabItem value="CSV">

```csv
name,deploymentpipelineid,ownerid,statuscode
Sales Pipeline,3ef59632-f087-ef11-8a69-7c1e521ba3ec,27f5bb85-6b7a-ef11-ac22-000d3a4e3cc8,1
```
</TabItem>

<TabItem value="Markdown">

```md
# m365 pp pipeline list --environmentName Default-d87a7535-dd31-4437-bfe1-95340acd55c5

Date: 17/10/2024

## environmentName (default) (/providers/Microsoft.BusinessAppPlatform/environments/Default-e1dd4023-a656-480a-8a0e-c1b1eec51e1d)

Property | Value
---------|-------
name | Sales Pipeline
deploymentpipelineid | 3ef59632-f087-ef11-8a69-7c1e521ba3ec
ownerid | 27f5bb85-6b7a-ef11-ac22-000d3a4e3cc8
statuscode | 1
```

</TabItem>

</Tabs>
10 changes: 10 additions & 0 deletions docs/src/config/sidebars.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { SidebarsConfig } from '@docusaurus/plugin-content-docs';


const sidebars: SidebarsConfig = {
home: [
'index',
Expand Down Expand Up @@ -1786,6 +1787,15 @@ const sidebars: SidebarsConfig = {
}
]
},
{
pipeline: [
{
type: 'doc',
label: 'pipeline list',
id: 'cmd/pp/pipeline/pipeline-list'
}
]
},
{
tenant: [
{
Expand Down
3 changes: 2 additions & 1 deletion src/m365/pp/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,6 @@ export default {
SOLUTION_PUBLISHER_LIST: `${prefix} solution publisher list`,
SOLUTION_PUBLISHER_REMOVE: `${prefix} solution publisher remove`,
TENANT_SETTINGS_LIST: `${prefix} tenant settings list`,
TENANT_SETTINGS_SET: `${prefix} tenant settings set`
TENANT_SETTINGS_SET: `${prefix} tenant settings set`,
PIPELINE_LIST: `${prefix} pipeline list`
};
185 changes: 185 additions & 0 deletions src/m365/pp/commands/pipeline/pipeline-list.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
import assert from "assert";
import commands from "../../commands.js";
import command from './pipeline-list.js';
import sinon from 'sinon';
import request from '../../../../request.js';
import { telemetry } from '../../../../telemetry.js';
import auth from '../../../../Auth.js';
import { Logger } from '../../../../cli/Logger.js';
import { pid } from '../../../../utils/pid.js';
import { session } from "../../../../utils/session.js";
import { sinonUtil } from '../../../../utils/sinonUtil.js';
import { accessToken } from '../../../../utils/accessToken.js';
import { CommandError } from "../../../../Command.js";




describe(commands.PIPELINE_LIST, () => {
const environmentName = 'environmentName';
const mockPipelineListResponse: any = [
{
name: 'pipeline1',
deploymentpipelineid: 'deploymentpipelineid1',
ownerid: 'owner1',
statuscode: 'statuscode1'
}
];
const mockEnvironmentResponse = {
"id": `/providers/Microsoft.BusinessAppPlatform/environments/Default-Environment`,
"type": "Microsoft.BusinessAppPlatform/environments",
"location": "unitedstates",
"name": "Default-Environment",
"properties": {
"displayName": "contoso (default)",
"isDefault": true,
linkedEnvironmentMetadata: {
instanceApiUrl: 'https://contoso.crm.dynamics.com'
}
}
};

let log: string[];
let logger: Logger;

let loggerLogSpy: sinon.SinonSpy;

before(() => {
sinon.stub(auth, 'restoreAuth').resolves();
sinon.stub(telemetry, 'trackEvent').returns();
sinon.stub(pid, 'getProcessName').returns('');
sinon.stub(session, 'getId').returns('');
sinon.stub(accessToken, 'assertDelegatedAccessToken').returns();
auth.connection.active = true;
});

beforeEach(() => {
log = [];
logger = {
log: async (msg: string) => {
log.push(msg);
},
logRaw: async (msg: string) => {
log.push(msg);
},
logToStderr: async (msg: string) => {
log.push(msg);
}
};
loggerLogSpy = sinon.spy(logger, 'log');
});

afterEach(() => {
sinonUtil.restore([
request.get
]);
});

after(() => {
sinon.restore();
auth.connection.active = false;
});

it('has correct name', () => {
assert.strictEqual(commands.PIPELINE_LIST, command.name);
});

it('has a description', () => {
assert.notStrictEqual(command.description, null);
});

it('defines correct properties for the default output', () => {
assert.deepStrictEqual(command.defaultProperties(), ['name', 'deploymentpipelineid', 'ownerid', 'statuscode']);
});

it('should send a request to get environment details', async () => {
const getEnvironmentStub = sinon.stub(request, 'get').callsFake(async (opts) => {
if ((opts.url as string).indexOf(`/providers/Microsoft.BusinessAppPlatform/environments/${environmentName}`) > -1) {
return mockEnvironmentResponse;
}
throw 'Invalid request';
});
await command['getEnvironmentDetails'](environmentName, false);

assert(getEnvironmentStub.calledWith(sinon.match({
url: sinon.match(`https://api.bap.microsoft.com/providers/Microsoft.BusinessAppPlatform/environments/${environmentName}`),
headers: sinon.match({
accept: 'application/json;odata.metadata=none'
}),
responseType: 'json'
})));
});

it('should send a request to get environment details (as admin)', async () => {
const getEnvironmentStub = sinon.stub(request, 'get').callsFake(async (opts) => {
if ((opts.url as string).indexOf(`/providers/Microsoft.BusinessAppPlatform/scopes/admin/environments/${environmentName}`) > -1) {
return mockEnvironmentResponse;
}
throw 'Invalid request';
});
await command['getEnvironmentDetails'](environmentName, true);

assert(getEnvironmentStub.calledWith(sinon.match({
url: sinon.match(`https://api.bap.microsoft.com/providers/Microsoft.BusinessAppPlatform/scopes/admin/environments/${environmentName}`),
headers: sinon.match({
accept: 'application/json;odata.metadata=none'
}),
responseType: 'json'
})));
});

it('returns correct environment details', async () => {
sinon.stub(request, 'get').resolves(mockEnvironmentResponse);
const result = await command['getEnvironmentDetails'](environmentName, false);
assert.strictEqual(result.properties.linkedEnvironmentMetadata.instanceApiUrl, 'https://contoso.crm.dynamics.com');
});

it('retrieves pipelines in the specified Power Platform environment', async () => {
const getEnvironmentStub = await sinon.stub(command as any, 'getEnvironmentDetails').callsFake(() => Promise.resolve(mockEnvironmentResponse));
const getPipelineStub = sinon.stub(request, 'get').callsFake(async (opts) => {
if ((opts.url as string).indexOf('/api/data/v9.0/deploymentpipelines') > -1) {
return {
value: [
{
name: 'pipeline1',
deploymentpipelineid: 'deploymentpipelineid1',
'_ownerid_value': 'owner1',
statuscode: 'statuscode1'
}
]
};
}
throw new Error('Invalid request');
});

await command.action(logger, {
options: {
environmentName: environmentName,
asAdmin: false
}
});

assert(getEnvironmentStub.called);
assert(getPipelineStub.called);

assert(loggerLogSpy.calledWith(sinon.match(mockPipelineListResponse)));
});

it('correctly handles error when retrieving environment details or pipelines', async () => {
const errorMessage = 'An error has occurred';
sinon.stub(request, 'get').callsFake(async () => {
throw errorMessage;
});

await assert.rejects(command.action(logger, {
options: {
environmentName: environmentName,
asAdmin: false
}
}), new CommandError(errorMessage));
});

});



Loading