Initial
This commit is contained in:
69
server/services/intunePromotionService.js
Normal file
69
server/services/intunePromotionService.js
Normal file
@@ -0,0 +1,69 @@
|
||||
// Pure helpers for the application promotion pipeline: producing the next
|
||||
// version's deployment plan and advancing assignment rings. No I/O, so both are
|
||||
// unit-tested; the controller persists/pushes the results.
|
||||
|
||||
// Bump the trailing numeric component of a version string (1.2.3 -> 1.2.4,
|
||||
// 126 -> 127). Falls back to appending ".1" when no number is present.
|
||||
export function bumpVersion(version = '') {
|
||||
const text = String(version).trim();
|
||||
if (!text) return '1.0.0';
|
||||
const match = text.match(/^(.*?)(\d+)(\D*)$/);
|
||||
if (!match) return `${text}.1`;
|
||||
const [, head, num, tail] = match;
|
||||
return `${head}${Number(num) + 1}${tail}`;
|
||||
}
|
||||
|
||||
// Build a fresh deployment payload for the next version, based on an existing
|
||||
// plan. The new plan is unpublished (no graphAppId), draft status, and keeps the
|
||||
// application link so the catalog groups both versions.
|
||||
export function cloneForNextVersion(deployment, { version, applicationId } = {}) {
|
||||
if (!deployment) throw new Error('A source deployment is required');
|
||||
const nextVersion = version || bumpVersion(extractVersion(deployment.name));
|
||||
const baseName = deployment.name.replace(/\s+\d[\d.]*$/, '').trim() || deployment.name;
|
||||
return {
|
||||
name: `${baseName} ${nextVersion}`.trim(),
|
||||
profileId: deployment.profileId || null,
|
||||
scriptId: deployment.scriptId || null,
|
||||
applicationId: applicationId || deployment.applicationId || null,
|
||||
sourceFolder: deployment.sourceFolder || '',
|
||||
intunewinFile: '',
|
||||
commandStyle: deployment.commandStyle,
|
||||
installBehavior: deployment.installBehavior,
|
||||
restartBehavior: deployment.restartBehavior,
|
||||
uiMode: deployment.uiMode,
|
||||
requirements: { ...(deployment.requirements || {}) },
|
||||
installCommand: deployment.installCommand,
|
||||
uninstallCommand: deployment.uninstallCommand,
|
||||
detectionType: deployment.detectionType,
|
||||
detectionRule: deployment.detectionRule,
|
||||
returnCodes: deployment.returnCodes || [],
|
||||
assignments: deployment.assignments || [],
|
||||
relationships: deployment.relationships || [],
|
||||
status: 'draft',
|
||||
graphAppId: '',
|
||||
graphConnectionId: deployment.graphConnectionId || null,
|
||||
notes: `Version ${nextVersion} created from ${deployment.name}.`,
|
||||
visibility: deployment.visibility,
|
||||
groupId: deployment.groupId || null
|
||||
};
|
||||
}
|
||||
|
||||
function extractVersion(name = '') {
|
||||
const match = String(name).match(/(\d[\d.]*)\s*$/);
|
||||
return match ? match[1] : '';
|
||||
}
|
||||
|
||||
// Advance a named assignment ring to a new intent (e.g. promote "Broad" from
|
||||
// available to required). Returns a new assignments array; unknown rings are a
|
||||
// no-op so callers can detect "nothing changed".
|
||||
export function setRingIntent(assignments = [], ring, intent) {
|
||||
let changed = false;
|
||||
const next = assignments.map((assignment) => {
|
||||
if (assignment.ring?.toLowerCase() === String(ring).toLowerCase() && assignment.intent !== intent) {
|
||||
changed = true;
|
||||
return { ...assignment, intent };
|
||||
}
|
||||
return assignment;
|
||||
});
|
||||
return { assignments: next, changed };
|
||||
}
|
||||
Reference in New Issue
Block a user