Skip to content

Commit e9f210e

Browse files
committed
Completes basic XML rewrite functionality
1 parent 47d1ddb commit e9f210e

File tree

8 files changed

+159
-31
lines changed

8 files changed

+159
-31
lines changed

.vscode/launch.json

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
{
2+
// Use IntelliSense to learn about possible attributes.
3+
// Hover to view descriptions of existing attributes.
4+
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
5+
"version": "0.2.0",
6+
"configurations": [
7+
{
8+
"type": "node",
9+
"request": "launch",
10+
"name": "Launch Program",
11+
"skipFiles": [
12+
"<node_internals>/**"
13+
],
14+
"preLaunchTask": "launch-build",
15+
"program": "${workspaceFolder}\\buildAndReleaseTask\\index.js",
16+
"env": {
17+
"INPUT_TARGETFILEPATH": "SampleServiceConfiguration.cscfg",
18+
"foo.blank": "blank-override",
19+
"FOO_BAR": "bar-override"
20+
},
21+
"outFiles": [
22+
"${workspaceFolder}/**/*.js"
23+
],
24+
}
25+
]
26+
}

.vscode/tasks.json

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
// See https://go.microsoft.com/fwlink/?LinkId=733558
3+
// for the documentation about the tasks.json format
4+
"version": "2.0.0",
5+
"tasks": [
6+
{
7+
"label": "launch-build",
8+
"type": "typescript",
9+
"tsconfig": "tsconfig.json",
10+
"problemMatcher": ["$tsc"],
11+
"group": {
12+
"kind": "build",
13+
"isDefault": true
14+
}
15+
}
16+
]
17+
}

SampleServiceConfiguration.cscfg

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<!--
3+
**********************************************************************************************
4+
5+
This file was generated by a tool from the project file: ServiceConfiguration.cscfg
6+
7+
Changes to this file may cause incorrect behavior and will be lost if the file is regenerated.
8+
9+
**********************************************************************************************
10+
-->
11+
<ServiceConfiguration serviceName="ServiceName" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceConfiguration" osFamily="6" osVersion="*" schemaVersion="2015-04.2.6">
12+
<Role name="RoleName">
13+
<Instances count="1" />
14+
<ConfigurationSettings>
15+
<Setting name="foo.blank" value="" />
16+
<Setting name="foo.bar" value="bar" />
17+
</ConfigurationSettings>
18+
</Role>
19+
</ServiceConfiguration>

buildAndReleaseTask/index.ts

Lines changed: 59 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,66 @@
1-
import tl = require('azure-pipelines-task-lib/task');
1+
import tl = require('azure-pipelines-task-lib');
2+
import { promises as fsPromises } from 'fs';
3+
import { DOMParser, XMLSerializer } from 'xmldom';
24

35
async function run() {
4-
try {
5-
const inputString: string | undefined = tl.getInput('samplestring', true);
6-
if (inputString == 'bad') {
7-
tl.setResult(tl.TaskResult.Failed, 'Bad input was given');
8-
return;
9-
}
10-
console.log('Hello', inputString);
6+
try {
7+
const targetFilePath: string | undefined = tl.getInput('targetFilePath', true);
8+
if (targetFilePath === '' || targetFilePath == null) {
9+
tl.setResult(tl.TaskResult.Failed, 'A file path to transform is required');
10+
return;
1111
}
12-
catch (err) {
13-
tl.setResult(tl.TaskResult.Failed, err.message);
12+
13+
let fileMutated = false;
14+
15+
const originalContents = await fsPromises.readFile(targetFilePath, 'utf8');
16+
const parser = new DOMParser();
17+
18+
let doc = parser.parseFromString(originalContents, 'text/xml');
19+
if (doc.documentElement.nodeName !== 'ServiceConfiguration') {
20+
tl.setResult(tl.TaskResult.Failed, 'Config file missing root ServiceConfiguration element');
21+
return;
22+
}
23+
24+
let roleNode = Array.from(doc.documentElement.childNodes).filter(n => n.nodeType === 1 && n.nodeName === 'Role')[0];
25+
if (!roleNode) {
26+
tl.setResult(tl.TaskResult.Failed, 'Config file missing Role element');
27+
return;
1428
}
29+
30+
let configSettingsNode = Array.from(roleNode.childNodes).filter(n => n.nodeType === 1 && n.nodeName === 'ConfigurationSettings')[0];
31+
if (!configSettingsNode) {
32+
tl.warning("Failed to find a ConfigurationSettings section to update");
33+
return;
34+
}
35+
36+
Array.from(configSettingsNode.childNodes).filter(n => n.nodeType === 1 && n.nodeName === 'Setting').forEach(settingsNode => {
37+
let settingsElement = <Element>settingsNode;
38+
const settingName = settingsElement.getAttribute('name');
39+
if (!settingName) {
40+
return;
41+
}
42+
43+
let overrideValue = tl.getVariable(settingName);
44+
45+
if (overrideValue != null) {
46+
tl.debug(`Override found for ${settingName}`);
47+
settingsElement.setAttribute('value', overrideValue);
48+
fileMutated = true;
49+
}
50+
});
51+
52+
if (fileMutated) {
53+
const newContents = new XMLSerializer().serializeToString(doc);
54+
fsPromises.writeFile(targetFilePath, newContents);
55+
}
56+
else {
57+
tl.warning("No variable updates were applied to the file.");
58+
}
59+
60+
}
61+
catch (err) {
62+
tl.setResult(tl.TaskResult.Failed, err.message);
63+
}
1564
}
1665

1766
run();

buildAndReleaseTask/task.json

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,30 +2,34 @@
22
"$schema": "https://raw.githubusercontent.com/Microsoft/azure-pipelines-task-lib/master/tasks.schema.json",
33
"id": "ed1c80dd-0444-415a-9a79-4cbd0251e8f2",
44
"name": "cscfg-transform",
5-
"friendlyName": "Azure Cloud Services Config Transform",
6-
"description": "Transforms Azure Cloud Service cscfg files.",
5+
"friendlyName": "Azure Cloud Services Config Variable Transform",
6+
"description": "Transforms Azure Cloud Service cscfg variables.",
77
"helpMarkDown": "",
88
"category": "Utility",
99
"author": "rezStream",
10+
"visibility": [
11+
"Build",
12+
"Release"
13+
],
1014
"version": {
11-
"Major": 0,
12-
"Minor": 1,
13-
"Patch": 0
15+
"Major": 0,
16+
"Minor": 1,
17+
"Patch": 0
1418
},
15-
"instanceNameFormat": "Echo $(samplestring)",
19+
"instanceNameFormat": "Transform cscfg $(targetFilePath)",
1620
"inputs": [
17-
{
18-
"name": "samplestring",
19-
"type": "string",
20-
"label": "Sample String",
21-
"defaultValue": "",
22-
"required": true,
23-
"helpMarkDown": "A sample string"
24-
}
21+
{
22+
"name": "targetFilePath",
23+
"type": "filePath",
24+
"label": "File path",
25+
"defaultValue": "",
26+
"required": true,
27+
"helpMarkDown": "The cscfg file to apply variable transforms to"
28+
}
2529
],
2630
"execution": {
27-
"Node10": {
28-
"target": "index.js"
29-
}
31+
"Node10": {
32+
"target": "index.js"
33+
}
3034
}
31-
}
35+
}

package-lock.json

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,14 @@
1313
"author": "rezStream",
1414
"license": "MIT",
1515
"dependencies": {
16-
"azure-pipelines-task-lib": "^2.9.3"
16+
"azure-pipelines-task-lib": "^2.9.3",
17+
"xmldom": "^0.2.1"
1718
},
1819
"devDependencies": {
1920
"@types/mocha": "^7.0.1",
2021
"@types/node": "^13.7.0",
2122
"@types/q": "^1.5.2",
23+
"@types/xmldom": "^0.1.29",
2224
"sync-request": "^6.1.0"
2325
}
2426
}

vss-extension.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
{
22
"manifestVersion": 1,
33
"id": "cscfg-transform",
4-
"name": "Azure Cloud Services Config Transform",
4+
"name": "Azure Cloud Services Config Variable Transform",
55
"version": "0.1.0",
66
"publisher": "rezStream",
77
"targets": [
88
{
99
"id": "Microsoft.VisualStudio.Services"
1010
}
1111
],
12-
"description": "Transforms Azure Cloud Service cscfg files.",
12+
"description": "Transforms Azure Cloud Service cscfg variables.",
1313
"categories": [
1414
"Azure Pipelines"
1515
],

0 commit comments

Comments
 (0)