n8n-nodes-azuredevops-advanced 0.1.2 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/credentials/AzureDevOpsAdvancedApi.credentials.ts +2 -2
- package/dist/credentials/AzureDevOpsAdvancedApi.credentials.js +2 -2
- package/dist/nodes/AzureDevOpsAdvanced/AzureDevOpsAdvanced.node.js +41 -24
- package/dist/nodes/AzureDevOpsAdvanced/GenericFunctions.js +1 -1
- package/dist/nodes/AzureDevOpsAdvanced/descriptions/GitDescription.js +30 -0
- package/dist/nodes/AzureDevOpsAdvanced/descriptions/PipelineDescription.js +1 -1
- package/nodes/AzureDevOpsAdvanced/AzureDevOpsAdvanced.node.ts +41 -20
- package/nodes/AzureDevOpsAdvanced/GenericFunctions.ts +1 -1
- package/nodes/AzureDevOpsAdvanced/descriptions/GitDescription.ts +30 -0
- package/nodes/AzureDevOpsAdvanced/descriptions/PipelineDescription.ts +1 -1
- package/package.json +6 -2
|
@@ -3,7 +3,7 @@ import { ICredentialType, INodeProperties } from 'n8n-workflow';
|
|
|
3
3
|
export class AzureDevOpsAdvancedApi implements ICredentialType {
|
|
4
4
|
name = 'azureDevOpsAdvancedApi';
|
|
5
5
|
displayName = 'Azure DevOps Advanced API';
|
|
6
|
-
//
|
|
6
|
+
// Documentation link explaining how to obtain a Personal Access Token
|
|
7
7
|
documentationUrl = 'https://n8n.io/integrations/azure-devops';
|
|
8
8
|
properties: INodeProperties[] = [
|
|
9
9
|
{
|
|
@@ -21,7 +21,7 @@ export class AzureDevOpsAdvancedApi implements ICredentialType {
|
|
|
21
21
|
typeOptions: { password: true },
|
|
22
22
|
default: '',
|
|
23
23
|
required: true,
|
|
24
|
-
description: '
|
|
24
|
+
description: 'Your Azure DevOps Personal Access Token with Read/Write access to all required resources',
|
|
25
25
|
},
|
|
26
26
|
];
|
|
27
27
|
}
|
|
@@ -5,7 +5,7 @@ class AzureDevOpsAdvancedApi {
|
|
|
5
5
|
constructor() {
|
|
6
6
|
this.name = 'azureDevOpsAdvancedApi';
|
|
7
7
|
this.displayName = 'Azure DevOps Advanced API';
|
|
8
|
-
//
|
|
8
|
+
// Documentation link explaining how to obtain a Personal Access Token
|
|
9
9
|
this.documentationUrl = 'https://n8n.io/integrations/azure-devops';
|
|
10
10
|
this.properties = [
|
|
11
11
|
{
|
|
@@ -23,7 +23,7 @@ class AzureDevOpsAdvancedApi {
|
|
|
23
23
|
typeOptions: { password: true },
|
|
24
24
|
default: '',
|
|
25
25
|
required: true,
|
|
26
|
-
description: '
|
|
26
|
+
description: 'Your Azure DevOps Personal Access Token with Read/Write access to all required resources',
|
|
27
27
|
},
|
|
28
28
|
];
|
|
29
29
|
}
|
|
@@ -21,7 +21,7 @@ class AzureDevOpsAdvanced {
|
|
|
21
21
|
group: ['transform'],
|
|
22
22
|
version: 1,
|
|
23
23
|
subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}',
|
|
24
|
-
description: '
|
|
24
|
+
description: 'Comprehensive Azure DevOps integration node',
|
|
25
25
|
defaults: { name: 'Azure DevOps Advanced' },
|
|
26
26
|
inputs: ['main'],
|
|
27
27
|
outputs: ['main'],
|
|
@@ -70,7 +70,7 @@ class AzureDevOpsAdvanced {
|
|
|
70
70
|
};
|
|
71
71
|
}
|
|
72
72
|
async execute() {
|
|
73
|
-
var _a, _b, _c, _d;
|
|
73
|
+
var _a, _b, _c, _d, _e, _f;
|
|
74
74
|
const items = this.getInputData();
|
|
75
75
|
const returnData = [];
|
|
76
76
|
const resource = this.getNodeParameter('resource', 0);
|
|
@@ -95,25 +95,45 @@ class AzureDevOpsAdvanced {
|
|
|
95
95
|
else if (operation === 'createBranch') {
|
|
96
96
|
const repoId = this.getNodeParameter('repositoryId', i);
|
|
97
97
|
const branchName = this.getNodeParameter('branchName', i);
|
|
98
|
-
//
|
|
99
|
-
|
|
100
|
-
const
|
|
101
|
-
|
|
102
|
-
|
|
98
|
+
// Try main first, fall back to master
|
|
99
|
+
let oldObjectId = '0000000000000000000000000000000000000000';
|
|
100
|
+
for (const baseBranch of ['main', 'master']) {
|
|
101
|
+
const refResponse = await GenericFunctions_1.azureApiRequest.call(this, 'GET', `${project}/_apis/git/repositories/${repoId}/refs?filter=heads/${baseBranch}&api-version=7.1`);
|
|
102
|
+
if ((_b = (_a = refResponse === null || refResponse === void 0 ? void 0 : refResponse.value) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.objectId) {
|
|
103
|
+
oldObjectId = refResponse.value[0].objectId;
|
|
104
|
+
break;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
103
107
|
const createEndpoint = `${project}/_apis/git/repositories/${repoId}/refs?api-version=7.1`;
|
|
104
|
-
const body = [{ name: branchName, newObjectId: oldObjectId, oldObjectId:
|
|
108
|
+
const body = [{ name: branchName, newObjectId: oldObjectId, oldObjectId: '0000000000000000000000000000000000000000' }];
|
|
105
109
|
responseData = await GenericFunctions_1.azureApiRequest.call(this, 'POST', createEndpoint, body);
|
|
110
|
+
responseData = (responseData === null || responseData === void 0 ? void 0 : responseData.value) || responseData;
|
|
106
111
|
}
|
|
107
112
|
else if (operation === 'pushCommit') {
|
|
108
113
|
const repoId = this.getNodeParameter('repositoryId', i);
|
|
109
114
|
const branchName = this.getNodeParameter('branchName', i);
|
|
110
115
|
const commitMessage = this.getNodeParameter('commitMessage', i);
|
|
111
|
-
|
|
112
|
-
|
|
116
|
+
const pushFilePath = this.getNodeParameter('pushFilePath', i);
|
|
117
|
+
const fileContent = this.getNodeParameter('fileContent', i);
|
|
118
|
+
const changeType = this.getNodeParameter('changeType', i);
|
|
119
|
+
// Get current branch HEAD to use as oldObjectId
|
|
120
|
+
const branchFilter = branchName.replace('refs/heads/', '');
|
|
121
|
+
const refResponse = await GenericFunctions_1.azureApiRequest.call(this, 'GET', `${project}/_apis/git/repositories/${repoId}/refs?filter=heads/${branchFilter}&api-version=7.1`);
|
|
122
|
+
const oldObjectId = ((_d = (_c = refResponse === null || refResponse === void 0 ? void 0 : refResponse.value) === null || _c === void 0 ? void 0 : _c[0]) === null || _d === void 0 ? void 0 : _d.objectId) || '0000000000000000000000000000000000000000';
|
|
113
123
|
const endpoint = `${project}/_apis/git/repositories/${repoId}/pushes?api-version=7.1`;
|
|
114
124
|
const body = {
|
|
115
|
-
refUpdates: [{ name: branchName, oldObjectId
|
|
116
|
-
commits: [{
|
|
125
|
+
refUpdates: [{ name: branchName, oldObjectId }],
|
|
126
|
+
commits: [{
|
|
127
|
+
comment: commitMessage,
|
|
128
|
+
changes: [{
|
|
129
|
+
changeType,
|
|
130
|
+
item: { path: pushFilePath.startsWith('/') ? pushFilePath : `/${pushFilePath}` },
|
|
131
|
+
newContent: {
|
|
132
|
+
content: Buffer.from(fileContent).toString('base64'),
|
|
133
|
+
contentType: 'base64Encoded',
|
|
134
|
+
},
|
|
135
|
+
}],
|
|
136
|
+
}],
|
|
117
137
|
};
|
|
118
138
|
responseData = await GenericFunctions_1.azureApiRequest.call(this, 'POST', endpoint, body);
|
|
119
139
|
}
|
|
@@ -169,7 +189,7 @@ class AzureDevOpsAdvanced {
|
|
|
169
189
|
const endpoint = `${project}/_apis/wit/wiql?api-version=7.1`;
|
|
170
190
|
const wiqlQuery = { query: `Select [System.Id], [System.Title], [System.State] From WorkItems Where [System.TeamProject] = '${project}'` };
|
|
171
191
|
const idsResponse = await GenericFunctions_1.azureApiRequest.call(this, 'POST', endpoint, wiqlQuery);
|
|
172
|
-
const idsArray = (
|
|
192
|
+
const idsArray = (_e = idsResponse === null || idsResponse === void 0 ? void 0 : idsResponse.workItems) === null || _e === void 0 ? void 0 : _e.map((wi) => wi.id);
|
|
173
193
|
if (idsArray && idsArray.length > 0) {
|
|
174
194
|
const workItemIds = idsArray.join(',');
|
|
175
195
|
const bulkEndpoint = `${project}/_apis/wit/workitems?ids=${workItemIds}&api-version=7.1`;
|
|
@@ -195,14 +215,14 @@ class AzureDevOpsAdvanced {
|
|
|
195
215
|
if (!isUpdate) {
|
|
196
216
|
mapPropertyToPatch('System.Title', this.getNodeParameter('title', i));
|
|
197
217
|
}
|
|
198
|
-
const additionalFields = this.getNodeParameter('additionalFields', i);
|
|
199
|
-
if (Object.keys(additionalFields).length) {
|
|
218
|
+
const additionalFields = this.getNodeParameter('additionalFields', i, {});
|
|
219
|
+
if (additionalFields && Object.keys(additionalFields).length) {
|
|
200
220
|
mapPropertyToPatch('System.Description', additionalFields.description);
|
|
201
221
|
mapPropertyToPatch('System.AssignedTo', additionalFields.assignedTo);
|
|
202
222
|
mapPropertyToPatch('System.State', additionalFields.state);
|
|
203
223
|
mapPropertyToPatch('Microsoft.VSTS.Common.Priority', additionalFields.priority);
|
|
204
224
|
mapPropertyToPatch('System.Tags', additionalFields.tags);
|
|
205
|
-
if ((
|
|
225
|
+
if ((_f = additionalFields.customFieldsUi) === null || _f === void 0 ? void 0 : _f.customFieldsValues) {
|
|
206
226
|
for (const customField of additionalFields.customFieldsUi.customFieldsValues) {
|
|
207
227
|
mapPropertyToPatch(customField.fieldId, customField.fieldValue);
|
|
208
228
|
}
|
|
@@ -223,7 +243,7 @@ class AzureDevOpsAdvanced {
|
|
|
223
243
|
});
|
|
224
244
|
}
|
|
225
245
|
else if (operation === 'listUsers') {
|
|
226
|
-
//
|
|
246
|
+
// Users are fetched via the Azure Graph API (vssps endpoint)
|
|
227
247
|
const endpoint = `_apis/graph/users?api-version=7.1-preview.1`;
|
|
228
248
|
const credentials = await this.getCredentials('azureDevOpsAdvancedApi');
|
|
229
249
|
const baseUrl = `https://vssps.dev.azure.com/${credentials.organization}`;
|
|
@@ -240,7 +260,7 @@ class AzureDevOpsAdvanced {
|
|
|
240
260
|
responseData = (responseData === null || responseData === void 0 ? void 0 : responseData.value) || responseData;
|
|
241
261
|
}
|
|
242
262
|
else if (operation === 'listTags') {
|
|
243
|
-
//
|
|
263
|
+
// Retrieve all work item tags scoped to the project
|
|
244
264
|
const endpoint = `${project}/_apis/wit/tags?api-version=7.1-preview.1`;
|
|
245
265
|
responseData = await GenericFunctions_1.azureApiRequest.call(this, 'GET', endpoint);
|
|
246
266
|
responseData = (responseData === null || responseData === void 0 ? void 0 : responseData.value) || responseData;
|
|
@@ -256,7 +276,7 @@ class AzureDevOpsAdvanced {
|
|
|
256
276
|
}
|
|
257
277
|
else if (operation === 'getComments') {
|
|
258
278
|
const pullRequestId = this.getNodeParameter('pullRequestId', i);
|
|
259
|
-
const endpoint = `${project}/_apis/git/repositories/${repositoryId}/
|
|
279
|
+
const endpoint = `${project}/_apis/git/repositories/${repositoryId}/pullrequests/${pullRequestId}/threads?api-version=7.1`;
|
|
260
280
|
responseData = await GenericFunctions_1.azureApiRequest.call(this, 'GET', endpoint);
|
|
261
281
|
responseData = (responseData === null || responseData === void 0 ? void 0 : responseData.value) || responseData;
|
|
262
282
|
}
|
|
@@ -264,12 +284,9 @@ class AzureDevOpsAdvanced {
|
|
|
264
284
|
const listOptions = this.getNodeParameter('listOptions', i);
|
|
265
285
|
let endpoint = `${project}/_apis/git/repositories/${repositoryId}/pullrequests?api-version=7.1`;
|
|
266
286
|
if (listOptions) {
|
|
267
|
-
if (listOptions.status
|
|
287
|
+
if (listOptions.status) {
|
|
268
288
|
endpoint += `&searchCriteria.status=${listOptions.status}`;
|
|
269
289
|
}
|
|
270
|
-
else if (listOptions.status === 'all') {
|
|
271
|
-
endpoint += `&searchCriteria.status=all`;
|
|
272
|
-
}
|
|
273
290
|
if (listOptions.creatorId)
|
|
274
291
|
endpoint += `&searchCriteria.creatorId=${listOptions.creatorId}`;
|
|
275
292
|
if (listOptions.reviewerId)
|
|
@@ -505,7 +522,7 @@ class AzureDevOpsAdvanced {
|
|
|
505
522
|
});
|
|
506
523
|
}
|
|
507
524
|
}
|
|
508
|
-
//
|
|
525
|
+
// Process and return results
|
|
509
526
|
if (Array.isArray(responseData)) {
|
|
510
527
|
returnData.push.apply(returnData, responseData.map(item => ({ json: item })));
|
|
511
528
|
}
|
|
@@ -19,7 +19,7 @@ async function azureApiRequest(method, endpoint, body = {}, query = {}) {
|
|
|
19
19
|
},
|
|
20
20
|
json: true,
|
|
21
21
|
};
|
|
22
|
-
if (Object.keys(body).length === 0) {
|
|
22
|
+
if (!Array.isArray(body) && Object.keys(body).length === 0) {
|
|
23
23
|
delete options.body;
|
|
24
24
|
}
|
|
25
25
|
return this.helpers.request(options);
|
|
@@ -90,6 +90,36 @@ exports.gitFields = [
|
|
|
90
90
|
},
|
|
91
91
|
},
|
|
92
92
|
},
|
|
93
|
+
{
|
|
94
|
+
displayName: 'File Path',
|
|
95
|
+
name: 'pushFilePath',
|
|
96
|
+
type: 'string',
|
|
97
|
+
default: '',
|
|
98
|
+
required: true,
|
|
99
|
+
displayOptions: {
|
|
100
|
+
show: {
|
|
101
|
+
resource: ['git'],
|
|
102
|
+
operation: ['pushCommit'],
|
|
103
|
+
},
|
|
104
|
+
},
|
|
105
|
+
description: 'Path of the file to create or update (e.g. /src/app.ts)',
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
displayName: 'Change Type',
|
|
109
|
+
name: 'changeType',
|
|
110
|
+
type: 'options',
|
|
111
|
+
options: [
|
|
112
|
+
{ name: 'Edit (update existing file)', value: 'edit' },
|
|
113
|
+
{ name: 'Add (create new file)', value: 'add' },
|
|
114
|
+
],
|
|
115
|
+
default: 'edit',
|
|
116
|
+
displayOptions: {
|
|
117
|
+
show: {
|
|
118
|
+
resource: ['git'],
|
|
119
|
+
operation: ['pushCommit'],
|
|
120
|
+
},
|
|
121
|
+
},
|
|
122
|
+
},
|
|
93
123
|
{
|
|
94
124
|
displayName: 'File Content',
|
|
95
125
|
name: 'fileContent',
|
|
@@ -19,7 +19,7 @@ export class AzureDevOpsAdvanced implements INodeType {
|
|
|
19
19
|
group: ['transform'],
|
|
20
20
|
version: 1,
|
|
21
21
|
subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}',
|
|
22
|
-
description: '
|
|
22
|
+
description: 'Comprehensive Azure DevOps integration node',
|
|
23
23
|
defaults: { name: 'Azure DevOps Advanced' },
|
|
24
24
|
inputs: ['main'],
|
|
25
25
|
outputs: ['main'],
|
|
@@ -94,26 +94,49 @@ export class AzureDevOpsAdvanced implements INodeType {
|
|
|
94
94
|
else if (operation === 'createBranch') {
|
|
95
95
|
const repoId = this.getNodeParameter('repositoryId', i) as string;
|
|
96
96
|
const branchName = this.getNodeParameter('branchName', i) as string;
|
|
97
|
-
|
|
98
|
-
//
|
|
99
|
-
|
|
100
|
-
const
|
|
101
|
-
|
|
97
|
+
|
|
98
|
+
// Try main first, fall back to master
|
|
99
|
+
let oldObjectId = '0000000000000000000000000000000000000000';
|
|
100
|
+
for (const baseBranch of ['main', 'master']) {
|
|
101
|
+
const refResponse = await azureApiRequest.call(this, 'GET', `${project}/_apis/git/repositories/${repoId}/refs?filter=heads/${baseBranch}&api-version=7.1`);
|
|
102
|
+
if (refResponse?.value?.[0]?.objectId) {
|
|
103
|
+
oldObjectId = refResponse.value[0].objectId;
|
|
104
|
+
break;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
102
107
|
|
|
103
108
|
const createEndpoint = `${project}/_apis/git/repositories/${repoId}/refs?api-version=7.1`;
|
|
104
|
-
const body = [{ name: branchName, newObjectId: oldObjectId, oldObjectId:
|
|
109
|
+
const body = [{ name: branchName, newObjectId: oldObjectId, oldObjectId: '0000000000000000000000000000000000000000' }];
|
|
105
110
|
responseData = await azureApiRequest.call(this, 'POST', createEndpoint, body);
|
|
111
|
+
responseData = responseData?.value || responseData;
|
|
106
112
|
}
|
|
107
113
|
else if (operation === 'pushCommit') {
|
|
108
114
|
const repoId = this.getNodeParameter('repositoryId', i) as string;
|
|
109
115
|
const branchName = this.getNodeParameter('branchName', i) as string;
|
|
110
116
|
const commitMessage = this.getNodeParameter('commitMessage', i) as string;
|
|
111
|
-
|
|
112
|
-
|
|
117
|
+
const pushFilePath = this.getNodeParameter('pushFilePath', i) as string;
|
|
118
|
+
const fileContent = this.getNodeParameter('fileContent', i) as string;
|
|
119
|
+
const changeType = this.getNodeParameter('changeType', i) as string;
|
|
120
|
+
|
|
121
|
+
// Get current branch HEAD to use as oldObjectId
|
|
122
|
+
const branchFilter = branchName.replace('refs/heads/', '');
|
|
123
|
+
const refResponse = await azureApiRequest.call(this, 'GET', `${project}/_apis/git/repositories/${repoId}/refs?filter=heads/${branchFilter}&api-version=7.1`);
|
|
124
|
+
const oldObjectId = refResponse?.value?.[0]?.objectId || '0000000000000000000000000000000000000000';
|
|
125
|
+
|
|
113
126
|
const endpoint = `${project}/_apis/git/repositories/${repoId}/pushes?api-version=7.1`;
|
|
114
127
|
const body = {
|
|
115
|
-
refUpdates: [{ name: branchName, oldObjectId
|
|
116
|
-
commits: [{
|
|
128
|
+
refUpdates: [{ name: branchName, oldObjectId }],
|
|
129
|
+
commits: [{
|
|
130
|
+
comment: commitMessage,
|
|
131
|
+
changes: [{
|
|
132
|
+
changeType,
|
|
133
|
+
item: { path: pushFilePath.startsWith('/') ? pushFilePath : `/${pushFilePath}` },
|
|
134
|
+
newContent: {
|
|
135
|
+
content: Buffer.from(fileContent).toString('base64'),
|
|
136
|
+
contentType: 'base64Encoded',
|
|
137
|
+
},
|
|
138
|
+
}],
|
|
139
|
+
}],
|
|
117
140
|
};
|
|
118
141
|
responseData = await azureApiRequest.call(this, 'POST', endpoint, body);
|
|
119
142
|
}
|
|
@@ -203,8 +226,8 @@ export class AzureDevOpsAdvanced implements INodeType {
|
|
|
203
226
|
mapPropertyToPatch('System.Title', this.getNodeParameter('title', i));
|
|
204
227
|
}
|
|
205
228
|
|
|
206
|
-
const additionalFields = this.getNodeParameter('additionalFields', i) as any;
|
|
207
|
-
if (Object.keys(additionalFields).length) {
|
|
229
|
+
const additionalFields = this.getNodeParameter('additionalFields', i, {}) as any;
|
|
230
|
+
if (additionalFields && Object.keys(additionalFields).length) {
|
|
208
231
|
mapPropertyToPatch('System.Description', additionalFields.description);
|
|
209
232
|
mapPropertyToPatch('System.AssignedTo', additionalFields.assignedTo);
|
|
210
233
|
mapPropertyToPatch('System.State', additionalFields.state);
|
|
@@ -234,7 +257,7 @@ export class AzureDevOpsAdvanced implements INodeType {
|
|
|
234
257
|
});
|
|
235
258
|
}
|
|
236
259
|
else if (operation === 'listUsers') {
|
|
237
|
-
//
|
|
260
|
+
// Users are fetched via the Azure Graph API (vssps endpoint)
|
|
238
261
|
const endpoint = `_apis/graph/users?api-version=7.1-preview.1`;
|
|
239
262
|
const credentials = await this.getCredentials('azureDevOpsAdvancedApi');
|
|
240
263
|
const baseUrl = `https://vssps.dev.azure.com/${(credentials as any).organization}`;
|
|
@@ -252,7 +275,7 @@ export class AzureDevOpsAdvanced implements INodeType {
|
|
|
252
275
|
responseData = responseData?.value || responseData;
|
|
253
276
|
}
|
|
254
277
|
else if (operation === 'listTags') {
|
|
255
|
-
//
|
|
278
|
+
// Retrieve all work item tags scoped to the project
|
|
256
279
|
const endpoint = `${project}/_apis/wit/tags?api-version=7.1-preview.1`;
|
|
257
280
|
responseData = await azureApiRequest.call(this, 'GET', endpoint);
|
|
258
281
|
responseData = responseData?.value || responseData;
|
|
@@ -270,7 +293,7 @@ export class AzureDevOpsAdvanced implements INodeType {
|
|
|
270
293
|
}
|
|
271
294
|
else if (operation === 'getComments') {
|
|
272
295
|
const pullRequestId = this.getNodeParameter('pullRequestId', i) as number;
|
|
273
|
-
const endpoint = `${project}/_apis/git/repositories/${repositoryId}/
|
|
296
|
+
const endpoint = `${project}/_apis/git/repositories/${repositoryId}/pullrequests/${pullRequestId}/threads?api-version=7.1`;
|
|
274
297
|
responseData = await azureApiRequest.call(this, 'GET', endpoint);
|
|
275
298
|
responseData = responseData?.value || responseData;
|
|
276
299
|
}
|
|
@@ -279,10 +302,8 @@ export class AzureDevOpsAdvanced implements INodeType {
|
|
|
279
302
|
let endpoint = `${project}/_apis/git/repositories/${repositoryId}/pullrequests?api-version=7.1`;
|
|
280
303
|
|
|
281
304
|
if (listOptions) {
|
|
282
|
-
if (listOptions.status
|
|
305
|
+
if (listOptions.status) {
|
|
283
306
|
endpoint += `&searchCriteria.status=${listOptions.status}`;
|
|
284
|
-
} else if (listOptions.status === 'all') {
|
|
285
|
-
endpoint += `&searchCriteria.status=all`;
|
|
286
307
|
}
|
|
287
308
|
if (listOptions.creatorId) endpoint += `&searchCriteria.creatorId=${listOptions.creatorId}`;
|
|
288
309
|
if (listOptions.reviewerId) endpoint += `&searchCriteria.reviewerId=${listOptions.reviewerId}`;
|
|
@@ -519,7 +540,7 @@ export class AzureDevOpsAdvanced implements INodeType {
|
|
|
519
540
|
}
|
|
520
541
|
}
|
|
521
542
|
|
|
522
|
-
//
|
|
543
|
+
// Process and return results
|
|
523
544
|
if (Array.isArray(responseData)) {
|
|
524
545
|
returnData.push.apply(returnData, responseData.map(item => ({ json: item })));
|
|
525
546
|
} else {
|
|
@@ -91,6 +91,36 @@ export const gitFields: INodeProperties[] = [
|
|
|
91
91
|
},
|
|
92
92
|
},
|
|
93
93
|
},
|
|
94
|
+
{
|
|
95
|
+
displayName: 'File Path',
|
|
96
|
+
name: 'pushFilePath',
|
|
97
|
+
type: 'string',
|
|
98
|
+
default: '',
|
|
99
|
+
required: true,
|
|
100
|
+
displayOptions: {
|
|
101
|
+
show: {
|
|
102
|
+
resource: ['git'],
|
|
103
|
+
operation: ['pushCommit'],
|
|
104
|
+
},
|
|
105
|
+
},
|
|
106
|
+
description: 'Path of the file to create or update (e.g. /src/app.ts)',
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
displayName: 'Change Type',
|
|
110
|
+
name: 'changeType',
|
|
111
|
+
type: 'options',
|
|
112
|
+
options: [
|
|
113
|
+
{ name: 'Edit (update existing file)', value: 'edit' },
|
|
114
|
+
{ name: 'Add (create new file)', value: 'add' },
|
|
115
|
+
],
|
|
116
|
+
default: 'edit',
|
|
117
|
+
displayOptions: {
|
|
118
|
+
show: {
|
|
119
|
+
resource: ['git'],
|
|
120
|
+
operation: ['pushCommit'],
|
|
121
|
+
},
|
|
122
|
+
},
|
|
123
|
+
},
|
|
94
124
|
{
|
|
95
125
|
displayName: 'File Content',
|
|
96
126
|
name: 'fileContent',
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "n8n-nodes-azuredevops-advanced",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Comprehensive Azure DevOps custom node for n8n",
|
|
5
5
|
"main": "dist/nodes/AzureDevOpsAdvanced/AzureDevOpsAdvanced.node.js",
|
|
6
6
|
"license": "MIT",
|
|
@@ -38,14 +38,18 @@
|
|
|
38
38
|
},
|
|
39
39
|
"scripts": {
|
|
40
40
|
"build": "tsc",
|
|
41
|
-
"dev": "tsc --watch"
|
|
41
|
+
"dev": "tsc --watch",
|
|
42
|
+
"test": "jest --forceExit"
|
|
42
43
|
},
|
|
43
44
|
"dependencies": {
|
|
44
45
|
"n8n-core": "^1.x",
|
|
45
46
|
"n8n-workflow": "^1.x"
|
|
46
47
|
},
|
|
47
48
|
"devDependencies": {
|
|
49
|
+
"@types/jest": "^30.0.0",
|
|
48
50
|
"@types/node": "^18.x",
|
|
51
|
+
"jest": "^30.4.2",
|
|
52
|
+
"ts-jest": "^29.4.11",
|
|
49
53
|
"typescript": "^5.x"
|
|
50
54
|
},
|
|
51
55
|
"publishConfig": {
|