Skip to content

Commit 502cf2e

Browse files
committed
Fix content type handling: use correct media type and endpoint for YAML vs JSON changesets
1 parent 48f4d34 commit 502cf2e

3 files changed

Lines changed: 356 additions & 100 deletions

File tree

dist/index.js

Lines changed: 70 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -25712,6 +25712,29 @@ function buildUrl(baseUrl, endpoint, environment) {
2571225712
return `${baseUrl}${endpoint}${envParam}`;
2571325713
}
2571425714

25715+
function getFileFormat(filePath) {
25716+
const ext = path.extname(filePath).toLowerCase();
25717+
if (ext === '.json') return 'json';
25718+
return 'yaml'; // .yaml, .yml, or any other extension defaults to yaml
25719+
}
25720+
25721+
function buildYamlPayload(content, variables) {
25722+
// Indent each line of the changeset content for YAML block scalar
25723+
const indentedContent = content.split('\n').map(line => ' ' + line).join('\n');
25724+
let yaml = `changeset: |\n${indentedContent}`;
25725+
25726+
if (variables && Object.keys(variables).length > 0) {
25727+
yaml += '\nvariables:';
25728+
for (const [key, value] of Object.entries(variables)) {
25729+
// Quote values to safely handle special YAML characters
25730+
const escaped = value.replace(/\\/g, '\\\\').replace(/"/g, '\\"');
25731+
yaml += `\n ${key}: "${escaped}"`;
25732+
}
25733+
}
25734+
25735+
return yaml;
25736+
}
25737+
2571525738
function isGlobPattern(pattern) {
2571625739
return /[*?[\]{}]/.test(pattern);
2571725740
}
@@ -25747,15 +25770,27 @@ function resolveFiles(changesetFile) {
2574725770
async function validateFile(filePath, options) {
2574825771
const { apiKey, baseUrl, environment, pollingTimeoutSeconds, changesetVariables } = options;
2574925772
const content = fs.readFileSync(filePath, 'utf8');
25750-
const validateUrl = buildUrl(baseUrl, '/api/v1/change-set/change-set/validate_yaml/', environment);
25751-
25752-
core.debug(`Validate URL: ${validateUrl}`);
25753-
25754-
// Prepare request payload with changeset and variables
25755-
const requestPayload = {
25756-
changeset: content,
25757-
...(changesetVariables && { variables: changesetVariables })
25758-
};
25773+
const format = getFileFormat(filePath);
25774+
const endpoint = format === 'json'
25775+
? '/api/v1/change-set/change-set/validate_json/'
25776+
: '/api/v1/change-set/change-set/validate_yaml/';
25777+
const validateUrl = buildUrl(baseUrl, endpoint, environment);
25778+
25779+
core.debug(`Validate URL: ${validateUrl} (format: ${format})`);
25780+
25781+
// Build request body and content type based on file format
25782+
let body, contentType;
25783+
if (format === 'json') {
25784+
contentType = 'application/json';
25785+
const requestPayload = {
25786+
changeset: content,
25787+
...(changesetVariables && { variables: changesetVariables })
25788+
};
25789+
body = JSON.stringify(requestPayload);
25790+
} else {
25791+
contentType = 'text/yaml';
25792+
body = buildYamlPayload(content, changesetVariables);
25793+
}
2575925794

2576025795
core.debug(`Sending validation request to: ${validateUrl}`);
2576125796
let validateResponse;
@@ -25764,9 +25799,9 @@ async function validateFile(filePath, options) {
2576425799
method: 'POST',
2576525800
headers: {
2576625801
'Authorization': `Api-Key ${apiKey}`,
25767-
'Content-Type': 'application/json'
25802+
'Content-Type': contentType
2576825803
},
25769-
body: JSON.stringify(requestPayload)
25804+
body
2577025805
});
2577125806
core.debug(`API response status: ${validateResponse.status}`);
2577225807
} catch (error) {
@@ -25832,15 +25867,27 @@ async function validateFile(filePath, options) {
2583225867
async function executeFile(filePath, options) {
2583325868
const { apiKey, baseUrl, environment, pollingTimeoutSeconds, changesetVariables } = options;
2583425869
const content = fs.readFileSync(filePath, 'utf8');
25835-
const executeUrl = buildUrl(baseUrl, '/api/v1/change-set/change-set/execute_yaml/', environment);
25836-
25837-
core.debug(`Execute URL: ${executeUrl}`);
25838-
25839-
// Prepare request payload with changeset and variables
25840-
const requestPayload = {
25841-
changeset: content,
25842-
...(changesetVariables && { variables: changesetVariables })
25843-
};
25870+
const format = getFileFormat(filePath);
25871+
const endpoint = format === 'json'
25872+
? '/api/v1/change-set/change-set/execute_json/'
25873+
: '/api/v1/change-set/change-set/execute_yaml/';
25874+
const executeUrl = buildUrl(baseUrl, endpoint, environment);
25875+
25876+
core.debug(`Execute URL: ${executeUrl} (format: ${format})`);
25877+
25878+
// Build request body and content type based on file format
25879+
let body, contentType;
25880+
if (format === 'json') {
25881+
contentType = 'application/json';
25882+
const requestPayload = {
25883+
changeset: content,
25884+
...(changesetVariables && { variables: changesetVariables })
25885+
};
25886+
body = JSON.stringify(requestPayload);
25887+
} else {
25888+
contentType = 'text/yaml';
25889+
body = buildYamlPayload(content, changesetVariables);
25890+
}
2584425891

2584525892
core.debug(`Sending API request to: ${executeUrl}`);
2584625893
let executeResponse;
@@ -25849,9 +25896,9 @@ async function executeFile(filePath, options) {
2584925896
method: 'POST',
2585025897
headers: {
2585125898
'Authorization': `Api-Key ${apiKey}`,
25852-
'Content-Type': 'application/json'
25899+
'Content-Type': contentType
2585325900
},
25854-
body: JSON.stringify(requestPayload)
25901+
body
2585525902
});
2585625903
core.debug(`API response status: ${executeResponse.status}`);
2585725904
} catch (error) {
@@ -26150,7 +26197,7 @@ async function run() {
2615026197
}
2615126198
}
2615226199

26153-
module.exports = { run, pollTask, buildUrl, isGlobPattern, resolveFiles, worstStatus };
26200+
module.exports = { run, pollTask, buildUrl, isGlobPattern, resolveFiles, worstStatus, getFileFormat, buildYamlPayload };
2615426201

2615526202
/* istanbul ignore next */
2615626203
if (require.main === require.cache[eval('__filename')]) {

src/index.js

Lines changed: 70 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,29 @@ function buildUrl(baseUrl, endpoint, environment) {
6464
return `${baseUrl}${endpoint}${envParam}`;
6565
}
6666

67+
function getFileFormat(filePath) {
68+
const ext = path.extname(filePath).toLowerCase();
69+
if (ext === '.json') return 'json';
70+
return 'yaml'; // .yaml, .yml, or any other extension defaults to yaml
71+
}
72+
73+
function buildYamlPayload(content, variables) {
74+
// Indent each line of the changeset content for YAML block scalar
75+
const indentedContent = content.split('\n').map(line => ' ' + line).join('\n');
76+
let yaml = `changeset: |\n${indentedContent}`;
77+
78+
if (variables && Object.keys(variables).length > 0) {
79+
yaml += '\nvariables:';
80+
for (const [key, value] of Object.entries(variables)) {
81+
// Quote values to safely handle special YAML characters
82+
const escaped = value.replace(/\\/g, '\\\\').replace(/"/g, '\\"');
83+
yaml += `\n ${key}: "${escaped}"`;
84+
}
85+
}
86+
87+
return yaml;
88+
}
89+
6790
function isGlobPattern(pattern) {
6891
return /[*?[\]{}]/.test(pattern);
6992
}
@@ -99,15 +122,27 @@ function resolveFiles(changesetFile) {
99122
async function validateFile(filePath, options) {
100123
const { apiKey, baseUrl, environment, pollingTimeoutSeconds, changesetVariables } = options;
101124
const content = fs.readFileSync(filePath, 'utf8');
102-
const validateUrl = buildUrl(baseUrl, '/api/v1/change-set/change-set/validate_yaml/', environment);
103-
104-
core.debug(`Validate URL: ${validateUrl}`);
105-
106-
// Prepare request payload with changeset and variables
107-
const requestPayload = {
108-
changeset: content,
109-
...(changesetVariables && { variables: changesetVariables })
110-
};
125+
const format = getFileFormat(filePath);
126+
const endpoint = format === 'json'
127+
? '/api/v1/change-set/change-set/validate_json/'
128+
: '/api/v1/change-set/change-set/validate_yaml/';
129+
const validateUrl = buildUrl(baseUrl, endpoint, environment);
130+
131+
core.debug(`Validate URL: ${validateUrl} (format: ${format})`);
132+
133+
// Build request body and content type based on file format
134+
let body, contentType;
135+
if (format === 'json') {
136+
contentType = 'application/json';
137+
const requestPayload = {
138+
changeset: content,
139+
...(changesetVariables && { variables: changesetVariables })
140+
};
141+
body = JSON.stringify(requestPayload);
142+
} else {
143+
contentType = 'text/yaml';
144+
body = buildYamlPayload(content, changesetVariables);
145+
}
111146

112147
core.debug(`Sending validation request to: ${validateUrl}`);
113148
let validateResponse;
@@ -116,9 +151,9 @@ async function validateFile(filePath, options) {
116151
method: 'POST',
117152
headers: {
118153
'Authorization': `Api-Key ${apiKey}`,
119-
'Content-Type': 'application/json'
154+
'Content-Type': contentType
120155
},
121-
body: JSON.stringify(requestPayload)
156+
body
122157
});
123158
core.debug(`API response status: ${validateResponse.status}`);
124159
} catch (error) {
@@ -184,15 +219,27 @@ async function validateFile(filePath, options) {
184219
async function executeFile(filePath, options) {
185220
const { apiKey, baseUrl, environment, pollingTimeoutSeconds, changesetVariables } = options;
186221
const content = fs.readFileSync(filePath, 'utf8');
187-
const executeUrl = buildUrl(baseUrl, '/api/v1/change-set/change-set/execute_yaml/', environment);
188-
189-
core.debug(`Execute URL: ${executeUrl}`);
190-
191-
// Prepare request payload with changeset and variables
192-
const requestPayload = {
193-
changeset: content,
194-
...(changesetVariables && { variables: changesetVariables })
195-
};
222+
const format = getFileFormat(filePath);
223+
const endpoint = format === 'json'
224+
? '/api/v1/change-set/change-set/execute_json/'
225+
: '/api/v1/change-set/change-set/execute_yaml/';
226+
const executeUrl = buildUrl(baseUrl, endpoint, environment);
227+
228+
core.debug(`Execute URL: ${executeUrl} (format: ${format})`);
229+
230+
// Build request body and content type based on file format
231+
let body, contentType;
232+
if (format === 'json') {
233+
contentType = 'application/json';
234+
const requestPayload = {
235+
changeset: content,
236+
...(changesetVariables && { variables: changesetVariables })
237+
};
238+
body = JSON.stringify(requestPayload);
239+
} else {
240+
contentType = 'text/yaml';
241+
body = buildYamlPayload(content, changesetVariables);
242+
}
196243

197244
core.debug(`Sending API request to: ${executeUrl}`);
198245
let executeResponse;
@@ -201,9 +248,9 @@ async function executeFile(filePath, options) {
201248
method: 'POST',
202249
headers: {
203250
'Authorization': `Api-Key ${apiKey}`,
204-
'Content-Type': 'application/json'
251+
'Content-Type': contentType
205252
},
206-
body: JSON.stringify(requestPayload)
253+
body
207254
});
208255
core.debug(`API response status: ${executeResponse.status}`);
209256
} catch (error) {
@@ -502,7 +549,7 @@ async function run() {
502549
}
503550
}
504551

505-
module.exports = { run, pollTask, buildUrl, isGlobPattern, resolveFiles, worstStatus };
552+
module.exports = { run, pollTask, buildUrl, isGlobPattern, resolveFiles, worstStatus, getFileFormat, buildYamlPayload };
506553

507554
/* istanbul ignore next */
508555
if (require.main === module) {

0 commit comments

Comments
 (0)