azdev-automation
Version:
Azure DevOps automation framework enables access control automation of projects, pipelines and repositories configuration in Azure DevOps Services
144 lines (143 loc) • 8.49 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.ReleaseUpdater = void 0;
class ReleaseUpdater {
constructor(releaseHelper, taskAgentHelper, securityHelper, commonHelper, logger) {
this.logger = logger;
this.debugLogger = logger.extend(this.constructor.name);
this.releaseHelper = releaseHelper;
this.taskAgentHelper = taskAgentHelper;
this.securityHelper = securityHelper;
this.commonHelper = commonHelper;
}
async initialize(projectName) {
this.logger.log("Initializing project classic release pipelines feature");
// Simply getting all release definitions initializes
// Required classic release pipelines capabilities
const result = this.releaseHelper.getDefinitions(projectName);
}
async removeDefinitionsArtifact(projectName, artifactName, artifactType, mock) {
const debug = this.debugLogger.extend(this.removeDefinitionsArtifact.name);
this.logger.log(`Updating <${projectName}> project release definition(s)`);
const filteredDefinitions = await this.releaseHelper.findDefinitionsWithArtifact(projectName, artifactName, artifactType);
if (filteredDefinitions.length === 0) {
this.logger.log(`No definitions with <${artifactName}> artifact <${artifactType}> found`);
return;
}
this.logger.log(`Found <${filteredDefinitions.length}> definition(s) with matching <${artifactName}> artifact`);
await Promise.all(filteredDefinitions.map(async (definition) => {
this.logger.log(`Updating <${definition.name}> definition artifact(s)`);
const targetArtifacts = definition.artifacts.filter((a) => a.alias === artifactName);
for (const artifact of targetArtifacts) {
let version = "latest";
if (artifact.definitionReference.defaultVersionType.id === "specificVersionType") {
version = artifact.definitionReference.defaultVersionSpecific.name;
}
this.logger.log(`Removing <${artifact.alias}> artifact <${artifact.definitionReference.branches.id}> branch <${version}> version`);
const updatedDefinition = await this.releaseHelper.removeDefinitionArtifact(definition, artifact.alias, artifact.type);
if (mock) {
debug(`Definition <${definition.name}> (${definition.id}) will not be updated (MOCK)`);
continue;
}
debug(`Updating <${definition.name}> definition <${artifact.alias}> artifact(s)`);
await this.releaseHelper.updateDefinition(updatedDefinition, projectName);
}
}));
}
async removeDefinitionsTasks(name, projectName, task, mock) {
const debug = this.debugLogger.extend(this.removeDefinitionsTasks.name);
this.logger.log(`Updating <${projectName}> project <${name}> release definition(s)`);
const tasks = await this.taskAgentHelper.findTasks(task.name);
if (tasks.length < 0) {
this.logger.log(`No tasks mathing <${task.name}> filter found`);
return;
}
const filteredDefinitions = await this.releaseHelper.findDefinitionsWithTasks(name, projectName, tasks);
if (filteredDefinitions.length === 0) {
debug(`No project <${projectName}> definitions with <${task.name}> task(s) found`);
return;
}
debug(`Found <${projectName}> project <${filteredDefinitions.length}> definitions`);
for (const definition of filteredDefinitions) {
const updatedDefinition = await this.releaseHelper.removeDefinitionTasks(definition, tasks);
this.logger.log(`${projectName} | ${definition.name} | ${task.name}`);
if (mock) {
debug(`Definition <${definition.name}> (${definition.id}) will not be updated (MOCK)`);
continue;
}
debug(`Removing <${definition.name}> definition task(s)`);
await this.releaseHelper.updateDefinition(updatedDefinition, projectName);
}
}
async updateDefinitionsTasks(name, projectName, task, releases, mock) {
const debug = this.debugLogger.extend(this.updateDefinitionsTasks.name);
this.logger.log(`Scanning <${projectName}> project <${name}> release definition(s)`);
const tasks = await this.taskAgentHelper.findTasks(task.name);
if (tasks.length <= 0) {
debug(`No tasks mathing <${task.name}> filter found`);
return;
}
debug(`Found <${tasks.length}> task(s) matching <${task.name}> filter`);
const filteredDefinitions = await this.releaseHelper.findDefinitionsWithTasks(name, projectName, tasks);
if (filteredDefinitions.length <= 0) {
debug(`No definitions mathing <${name}> filter found`);
return;
}
debug(`Found <${filteredDefinitions.length}> release definition(s) with matching task(s)`);
await Promise.all(filteredDefinitions.map(async (definition) => {
debug(`Updating <${definition.name}> (${definition.id}) definition task(s)`);
const updatedDefinition = await this.releaseHelper.updateDefinitionTasks(definition, tasks, task.parameters, task.filter);
// Push updated definition only
if (updatedDefinition.comment) {
if (mock) {
this.logger.log(`Definition <${updatedDefinition.name}> (${definition.id}) update required (MOCK)`);
}
else {
this.logger.log(`Updating <${updatedDefinition.name}> (${definition.id}) definition`);
await this.releaseHelper.updateDefinition(updatedDefinition, projectName);
}
}
else {
debug(`Definition <${updatedDefinition.name}> (${definition.id}) update not required`);
}
if (releases) {
const filteredReleases = await this.releaseHelper.findDefinitionReleasesWithTasks(definition.id, projectName, tasks);
for (const release of filteredReleases) {
debug(`Updating <${release.name}> (${release.id}) release task(s)`);
const updatedRelease = await this.releaseHelper.updateReleaseTasks(release, tasks, task.parameters, task.filter);
// Push updated release only
if (updatedRelease.comment) {
if (mock) {
this.logger.log(`Release <${updatedRelease.name}> (${updatedRelease.id}) update required (MOCK)`);
}
else {
this.logger.log(`Updating <${updatedRelease.name}> (${updatedRelease.id}) release`);
await this.releaseHelper.updateRelease(updatedRelease, projectName);
}
}
else {
debug(`Release <${updatedRelease.name}> (${updatedRelease.id}) update not required`);
}
}
}
}));
}
async updatePermissions(project, policy) {
const debug = this.debugLogger.extend(this.updatePermissions.name);
this.logger.log(`Applying <${policy.name}> release permissions policy`);
const namespace = await this.securityHelper.getNamespace("ReleaseManagement", "View release pipeline");
const permissionSetId = namespace.namespaceId;
const permissionSetToken = project.id;
const existingIdentities = await this.securityHelper.getExplicitIdentities(project.id, permissionSetId, permissionSetToken);
await Promise.all(policy.definition.map(async (group) => {
const groupName = `[${project.name}]\\${group.name}`;
this.logger.log(`Assigninig <${groupName}> group permissions`);
// Slow down parallel calls to address
// Intermittent API connectivity issues
await this.commonHelper.wait(500, 3000);
const targetIdentity = await this.securityHelper.getExistingIdentity(groupName, project.id, existingIdentities);
await this.securityHelper.updateIdentityPermissions(project.id, targetIdentity, group.permissions, permissionSetId, permissionSetToken);
}));
}
}
exports.ReleaseUpdater = ReleaseUpdater;