Skip to content

Commit

Permalink
Support escaped colon in variables (#336)
Browse files Browse the repository at this point in the history
  • Loading branch information
HuyPhanNguyen authored Jan 7, 2025
1 parent 248940a commit 0285590
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 7 deletions.
27 changes: 27 additions & 0 deletions source/tasks/Deploy/DeployV6/inputCommandBuilder.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,33 @@ describe("getInputCommand", () => {
expect(command.Variables).toStrictEqual({ var1: "value1", var2: "value2" });
});

test("handles escaped colons in variable names", () => {
task.addVariableString("Space", "Default");
task.addVariableString("Variables", "Test\\:Variable: Testing3");
task.addVariableString("Environments", "test");
task.addVariableString("Project", "Test project");
task.addVariableString("ReleaseNumber", "1.0.0");
task.addVariableString("DeployForTenants", "Tenant 1");

const command = createCommandFromInputs(logger, task);
expect(command.Variables).toStrictEqual({ "Test:Variable": "Testing3" });
});

test("handles multiple variables with escaped and unescaped colons", () => {
task.addVariableString("Space", "Default");
task.addVariableString("Variables", "Long\\:Variable\\:Name: Value123\nTest\\:Variable: Value: With: Colons");
task.addVariableString("Environments", "test");
task.addVariableString("Project", "Test project");
task.addVariableString("ReleaseNumber", "1.0.0");
task.addVariableString("DeployForTenants", "Tenant 1");

const command = createCommandFromInputs(logger, task);
expect(command.Variables).toStrictEqual({
"Long:Variable:Name": "Value123",
"Test:Variable": "Value: With: Colons"
});
});

test("multiline environments", () => {
task.addVariableString("Space", "Default");
task.addVariableString("Environments", "dev, test\nprod");
Expand Down
8 changes: 4 additions & 4 deletions source/tasks/Deploy/DeployV6/inputCommandBuilder.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import commandLineArgs from "command-line-args";
import shlex from "shlex";
import { getLineSeparatedItems } from "../../Utils/inputs";
import { getLineSeparatedItems, parseVariableString } from "../../Utils/inputs";
import { CreateDeploymentUntenantedCommandV1, Logger, PromptedVariableValues } from "@octopusdeploy/api-client";
import { TaskWrapper } from "tasks/Utils/taskInput";

Expand All @@ -22,13 +22,13 @@ export function createCommandFromInputs(logger: Logger, task: TaskWrapper): Crea
}

const variablesField = task.getInput("Variables");
logger.debug?.("Variables:" + variablesField);
logger.debug?.("Variables: " + variablesField);
if (variablesField) {
const variables = getLineSeparatedItems(variablesField).map((p) => p.trim()) || undefined;
if (variables) {
for (const variable of variables) {
const variableMap = variable.split(":").map((x) => x.trim());
variablesMap[variableMap[0]] = variableMap[1];
const [name, value] = parseVariableString(variable);
variablesMap[name] = value;
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,33 @@ describe("getInputCommand", () => {
expect(command.Variables).toStrictEqual({ var1: "value1", var2: "value2" });
});

test("handles escaped colons in variable names", () => {
task.addVariableString("Space", "Default");
task.addVariableString("Variables", "Test\\:Variable: Testing3");
task.addVariableString("Environment", "dev");
task.addVariableString("Project", "Test project");
task.addVariableString("ReleaseNumber", "1.0.0");
task.addVariableString("DeployForTenants", "Tenant 1");

const command = createCommandFromInputs(logger, task);
expect(command.Variables).toStrictEqual({ "Test:Variable": "Testing3" });
});

test("handles multiple variables with escaped and unescaped colons", () => {
task.addVariableString("Space", "Default");
task.addVariableString("Variables", "Long\\:Variable\\:Name: Value123\nTest\\:Variable: Value: With: Colons");
task.addVariableString("Environment", "dev");
task.addVariableString("Project", "Test project");
task.addVariableString("ReleaseNumber", "1.0.0");
task.addVariableString("DeployForTenants", "Tenant 1");

const command = createCommandFromInputs(logger, task);
expect(command.Variables).toStrictEqual({
"Long:Variable:Name": "Value123",
"Test:Variable": "Value: With: Colons"
});
});

test("validate tenants and tags", () => {
task.addVariableString("Space", "Default");
task.addVariableString("Project", "project 1");
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import commandLineArgs from "command-line-args";
import shlex from "shlex";
import { getLineSeparatedItems } from "../../Utils/inputs";
import { getLineSeparatedItems, parseVariableString } from "../../Utils/inputs";
import { CreateDeploymentTenantedCommandV1, Logger, PromptedVariableValues } from "@octopusdeploy/api-client";
import { TaskWrapper } from "tasks/Utils/taskInput";

Expand Down Expand Up @@ -32,8 +32,8 @@ export function createCommandFromInputs(logger: Logger, task: TaskWrapper): Crea
const variables = getLineSeparatedItems(variablesField).map((p) => p.trim()) || undefined;
if (variables) {
for (const variable of variables) {
const variableMap = variable.split(":").map((x) => x.trim());
variablesMap[variableMap[0]] = variableMap[1];
const [name, value] = parseVariableString(variable);
variablesMap[name] = value;
}
}
}
Expand Down
28 changes: 28 additions & 0 deletions source/tasks/Utils/inputs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,34 @@ export function getLineSeparatedItems(value: string): Array<string> {
return value ? value.split(/[\r\n]+/g).map((x) => x.trim()) : [];
}

export function parseVariableString(input: string): [string, string] {
let escapeNext = false;
let colonIndex = -1;

for (let i = 0; i < input.length; i++) {
if (input[i] === '\\' && !escapeNext) {
escapeNext = true;
continue;
}

if (input[i] === ':' && !escapeNext) {
colonIndex = i;
break;
}

escapeNext = false;
}

if (colonIndex === -1) {
throw new Error(`Invalid variable format. Expected 'name: value' but got '${input}'`);
}

const variableName = input.substring(0, colonIndex).replace(/\\:/g, ':').trim();
const variableValue = input.substring(colonIndex + 1).trim();

return [variableName, variableValue];
}

export function getOverwriteModeFromReplaceInput(replace: string): ReplaceOverwriteMode {
return ReplaceOverwriteMode[replace as keyof typeof ReplaceOverwriteMode] || ReplaceOverwriteMode.false;
}
Expand Down

0 comments on commit 0285590

Please sign in to comment.