Skip to content

Commit ad21de0

Browse files
Fix for deleted solution branch (microsoft#4606)
Co-authored-by: Michael Ochs <[email protected]>
1 parent 14e6f38 commit ad21de0

File tree

1 file changed

+67
-49
lines changed

1 file changed

+67
-49
lines changed

coe-cli/src/commands/devops.ts

+67-49
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import * as azdev from "azure-devops-node-api"
33
import { IHeaders, IRequestHandler } from "azure-devops-node-api/interfaces/common/VsoBaseInterfaces";
44
import util from "util"
55
import * as CoreInterfaces from 'azure-devops-node-api/interfaces/CoreInterfaces';
6-
import { GitVersionDescriptor, GitVersionType, GitRefUpdate, GitCommitRef, GitPush, GitChange, VersionControlChangeType, GitItem, ItemContentType, GitRef, GitImportRequest, GitRepositoryCreateOptions, GitImportRequestParameters, GitImportGitSource, GitAsyncOperationStatus } from 'azure-devops-node-api/interfaces/GitInterfaces';
6+
import { GitVersionDescriptor, GitVersionType, GitRefUpdate, GitCommitRef, GitPush, GitChange, VersionControlChangeType, GitItem, ItemContentType, GitRef, GitImportRequest, GitRepositoryCreateOptions, GitImportRequestParameters, GitImportGitSource, GitAsyncOperationStatus, VersionControlRecursionType } from 'azure-devops-node-api/interfaces/GitInterfaces';
77
import * as gitm from "azure-devops-node-api/GitApi"
88
import * as BuildInterfaces from 'azure-devops-node-api/interfaces/BuildInterfaces';
99
import { GitHubCommand } from './github';
@@ -940,28 +940,40 @@ class DevOpsCommand {
940940
let newGitCommit = <GitCommitRef>{}
941941
newGitCommit.comment = "Add DevOps Pipeline"
942942
if (typeof args.settings["environments"] === "string") {
943-
newGitCommit.changes = await this.getGitCommitChanges(args, gitApi, pipelineRepo, args.destinationBranch, this.withoutRefsPrefix(projectRepo.defaultBranch), args.settings["environments"].split('|').map(element => {
943+
newGitCommit.changes = await this.getGitCommitChanges(args, gitApi, projectRepo, pipelineRepo, sourceRef[0].name, args.destinationBranch, this.withoutRefsPrefix(projectRepo.defaultBranch), args.settings["environments"].split('|').map(element => {
944944
return element.toLowerCase();
945945
}))
946946
}
947947
else {
948-
newGitCommit.changes = await this.getGitCommitChanges(args, gitApi, pipelineRepo, args.destinationBranch, this.withoutRefsPrefix(projectRepo.defaultBranch), ['validation', 'test', 'prod'])
948+
newGitCommit.changes = await this.getGitCommitChanges(args, gitApi, projectRepo, pipelineRepo, sourceRef[0].name, args.destinationBranch, this.withoutRefsPrefix(projectRepo.defaultBranch), ['validation', 'test', 'prod'])
949949
}
950-
let gitPush = <GitPush>{}
951-
gitPush.refUpdates = [newRef]
952-
gitPush.commits = [newGitCommit]
953-
954-
this.logger?.info(util.format('Pushing new branch %s', args.destinationBranch))
955-
await gitApi.createPush(gitPush, projectRepo.id, project.name)
956-
957-
if (repositoryName?.length > 0) {
958-
this.logger?.info(util.format("Repo %s not found", repositoryName))
959-
this.logger?.info('Did you mean?')
960-
projectRepos.forEach(repo => {
961-
if (repo.name.startsWith(repositoryName[0])) {
962-
this.logger?.info(repo.name)
963-
}
964-
});
950+
if(newGitCommit.changes.length == 0) {
951+
//Create new branch without any changes
952+
let newRef = <GitRefUpdate>{};
953+
newRef.newObjectId = sourceRef[0].objectId
954+
newRef.oldObjectId = "0000000000000000000000000000000000000000"
955+
newRef.name = util.format("refs/heads/%s", args.destinationBranch)
956+
gitApi.updateRefs([newRef], projectRepo.id, project.name)
957+
this.logger?.info(`Created branch ${args.destinationBranch}`)
958+
}
959+
else {
960+
//Create new branch with updates to pipeline templates
961+
let gitPush = <GitPush>{}
962+
gitPush.refUpdates = [newRef]
963+
gitPush.commits = [newGitCommit]
964+
965+
this.logger?.info(util.format('Pushing new branch %s: %s', args.destinationBranch, JSON.stringify(gitPush)))
966+
await gitApi.createPush(gitPush, projectRepo.id, project.name)
967+
968+
if (repositoryName?.length > 0) {
969+
this.logger?.info(util.format("Repo %s not found", repositoryName))
970+
this.logger?.info('Did you mean?')
971+
projectRepos.forEach(repo => {
972+
if (repo.name.startsWith(repositoryName[0])) {
973+
this.logger?.info(repo.name)
974+
}
975+
});
976+
}
965977
}
966978
}
967979
return projectRepo;
@@ -1193,7 +1205,7 @@ class DevOpsCommand {
11931205
}
11941206
}
11951207

1196-
async getGitCommitChanges(args: DevOpsBranchArguments, gitApi: gitm.IGitApi, pipelineRepo: GitRepository, destinationBranch: string, defaultBranch: string, names: string[]): Promise<GitChange[]> {
1208+
async getGitCommitChanges(args: DevOpsBranchArguments, gitApi: gitm.IGitApi, projectRepo: GitRepository, pipelineRepo: GitRepository, sourceBranch: string, destinationBranch: string, defaultBranch: string, names: string[]): Promise<GitChange[]> {
11971209
let pipelineProject = args.pipelineProject?.length > 0 ? args.pipelineProject : args.projectName
11981210
let results: GitChange[] = []
11991211

@@ -1213,40 +1225,46 @@ class DevOpsCommand {
12131225

12141226
for (var i = 0; i < names.length; i++) {
12151227
this.logger?.info(util.format("Getting changes for %s", names[i]));
1216-
let version: GitVersionDescriptor = <GitVersionDescriptor>{};
1217-
version.versionType = GitVersionType.Branch;
1218-
let templatePath = util.format("/Pipelines/build-deploy-%s-SampleSolution.yml", names[i])
1219-
if (typeof args.settings[`${names[i]}-buildtemplate`] === "string") {
1220-
templatePath = args.settings[`${names[i]}-buildtemplate`]
1221-
}
12221228

1223-
let devOpsOrgUrl = Environment.getDevOpsOrgUrl(args);
1224-
let contentUrl = `${devOpsOrgUrl}${pipelineProject}/_apis/git/repositories/${args.pipelineRepository}/items?path=${templatePath}&includeContent=true&versionDescriptor.version=${this.withoutRefsPrefix(pipelineRepo.defaultBranch)}&versionDescriptor.versionType=branch&api-version=5.0`
1225-
this.logger?.info(util.format("Getting content from %s", contentUrl));
1226-
1227-
let response: any = await this.getUrl(contentUrl, config)
1228-
if (response?.content != null) {
1229-
let commit = <GitChange>{}
1230-
commit.changeType = VersionControlChangeType.Add
1231-
commit.item = <GitItem>{}
1232-
commit.item.path = util.format("/%s/deploy-%s-%s.yml", destinationBranch, names[i], destinationBranch)
1233-
commit.newContent = <ItemContent>{}
1234-
1235-
commit.newContent.content = response?.content.toString().replace(/BranchContainingTheBuildTemplates/g, defaultBranch)
1236-
commit.newContent.content = (commit.newContent.content)?.replace(/RepositoryContainingTheBuildTemplates/g, `${pipelineProject}/${pipelineRepo.name}`)
1237-
commit.newContent.content = (commit.newContent.content)?.replace(/SampleSolutionName/g, destinationBranch)
1238-
1239-
let variableGroup = args.settings[names[i] + "-variablegroup"]
1240-
if (typeof variableGroup !== "undefined" && variableGroup != '') {
1241-
commit.newContent.content = (commit.newContent.content)?.replace(/alm-accelerator-variable-group/g, variableGroup)
1229+
let repoTemplatePath = util.format("/%s/deploy-%s-%s.yml", destinationBranch, names[i], destinationBranch)
1230+
let existingItem = await gitApi.getItem(projectRepo.id, repoTemplatePath, args.projectName, null, VersionControlRecursionType.None, false, true, false, <GitVersionDescriptor>{ versionType: GitVersionType.Branch, version: this.withoutRefsPrefix(sourceBranch)})
1231+
1232+
this.logger?.info(util.format("Existing item %s", existingItem?.path));
1233+
if (typeof existingItem === "undefined" || existingItem == null) {
1234+
this.logger?.info(util.format("Pipeline template does not exist %s", repoTemplatePath));
1235+
let templatePath = util.format("/Pipelines/build-deploy-%s-SampleSolution.yml", names[i])
1236+
if (typeof args.settings[`${names[i]}-buildtemplate`] === "string") {
1237+
templatePath = args.settings[`${names[i]}-buildtemplate`]
12421238
}
12431239

1244-
commit.newContent.contentType = ItemContentType.RawText
1240+
let devOpsOrgUrl = Environment.getDevOpsOrgUrl(args);
1241+
let contentUrl = `${devOpsOrgUrl}${pipelineProject}/_apis/git/repositories/${args.pipelineRepository}/items?path=${templatePath}&includeContent=true&versionDescriptor.version=${this.withoutRefsPrefix(pipelineRepo.defaultBranch)}&versionDescriptor.versionType=branch&api-version=5.0`
1242+
this.logger?.info(util.format("Getting content from %s", contentUrl));
1243+
1244+
let response: any = await this.getUrl(contentUrl, config)
1245+
if (response?.content != null) {
1246+
let commit = <GitChange>{}
1247+
commit.changeType = VersionControlChangeType.Add
1248+
commit.item = <GitItem>{}
1249+
commit.item.path = util.format("/%s/deploy-%s-%s.yml", destinationBranch, names[i], destinationBranch)
1250+
commit.newContent = <ItemContent>{}
1251+
1252+
commit.newContent.content = response?.content.toString().replace(/BranchContainingTheBuildTemplates/g, defaultBranch)
1253+
commit.newContent.content = (commit.newContent.content)?.replace(/RepositoryContainingTheBuildTemplates/g, `${pipelineProject}/${pipelineRepo.name}`)
1254+
commit.newContent.content = (commit.newContent.content)?.replace(/SampleSolutionName/g, destinationBranch)
1255+
1256+
let variableGroup = args.settings[names[i] + "-variablegroup"]
1257+
if (typeof variableGroup !== "undefined" && variableGroup != '') {
1258+
commit.newContent.content = (commit.newContent.content)?.replace(/alm-accelerator-variable-group/g, variableGroup)
1259+
}
12451260

1246-
results.push(commit)
1247-
} else {
1248-
this.logger?.info(`Error creating new pipeline definition for ${names[i]}: ${JSON.stringify(response)}`);
1249-
throw response
1261+
commit.newContent.contentType = ItemContentType.RawText
1262+
1263+
results.push(commit)
1264+
} else {
1265+
this.logger?.info(`Error creating new pipeline definition for ${names[i]}: ${JSON.stringify(response)}`);
1266+
throw response
1267+
}
12501268
}
12511269
}
12521270
return results;

0 commit comments

Comments
 (0)