Last active
December 4, 2020 22:42
-
-
Save marcosborges/6621081f4096c6f2d491f11b3dc395b2 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Copyright 2020 Spotify AB | |
* | |
* Licensed under the Apache License, Version 2.0 (the "License"); | |
* you may not use this file except in compliance with the License. | |
* You may obtain a copy of the License at | |
* | |
* http://www.apache.org/licenses/LICENSE-2.0 | |
* | |
* Unless required by applicable law or agreed to in writing, software | |
* distributed under the License is distributed on an "AS IS" BASIS, | |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
* See the License for the specific language governing permissions and | |
* limitations under the License. | |
*/ | |
import axios from "axios" | |
import { PublisherBase, PublisherOptions, PublisherResult } from './types'; | |
import { GitApi } from 'azure-devops-node-api/GitApi'; | |
import { GitRepositoryCreateOptions } from 'azure-devops-node-api/interfaces/GitInterfaces'; | |
import { pushToRemoteUserPass } from './helpers'; | |
import { JsonValue } from '@backstage/config'; | |
import { RequiredTemplateValues } from '../templater'; | |
export class AzurePublisher implements PublisherBase { | |
private readonly client: GitApi; | |
private readonly token: string; | |
constructor(client: GitApi, token: string) { | |
this.client = client; | |
this.token = token; | |
} | |
async publish({ | |
values, | |
directory, | |
}: PublisherOptions): Promise<PublisherResult> { | |
const repo = await this.createRemote(values); | |
const remoteUrl = repo.remoteUrl || '' | |
await pushToRemoteUserPass(directory, remoteUrl, 'notempty', this.token); | |
const catalogInfoUrl = `${remoteUrl}?path=%2F.azuredevops%2Fcatalog-info.yaml`; | |
await this.setupPipeline(values, repo); | |
await this.setupLibrary(values, repo); | |
await this.protectBranch(values, repo); | |
return { remoteUrl, catalogInfoUrl }; | |
} | |
private async createRemote( | |
values: RequiredTemplateValues & Record<string, JsonValue>, | |
) { | |
const [project, name] = values.storePath.split('/'); | |
const createOptions: GitRepositoryCreateOptions = { name }; | |
const repo = await this.client.createRepository(createOptions, project); | |
return repo || ''; | |
} | |
private async setupPipeline( | |
values: RequiredTemplateValues & Record<string, JsonValue>, | |
repo: any | |
) { | |
console.log('ScaffolderSetupPipeline') | |
const [project, name] = values.storePath.split('/'); | |
const setup = await this.setupPipelineApi(project, repo.id, name) | |
return setup; | |
} | |
private async setupLibrary( | |
values: RequiredTemplateValues & Record<string, JsonValue>, | |
repo: any | |
) { | |
console.log('setupLibrary') | |
const [project] = values.storePath.split('/'); | |
await this.setupLibraryApi(project, repo) | |
} | |
private async protectBranch( | |
values: RequiredTemplateValues & Record<string, JsonValue>, | |
repo: any | |
) { | |
console.log('ScaffolderProtectBranch') | |
const [project] = values.storePath.split('/'); | |
await this.protectBranchApi(project, "dev_integracao" , repo) | |
await this.protectBranchApi(project, "release" , repo) | |
await this.protectBranchApi(project, "master" , repo) | |
} | |
private async setupPipelineApi(projectId: string, repositoryId: any, name: string) { | |
console.log('projectId:' + projectId) | |
console.log('repositoryId:' + repositoryId) | |
console.log('name' + name) | |
const serviceName = name | |
const project = await this.getProjectApi(projectId) | |
console.log(project) | |
const body = { | |
variables: "", | |
triggers: [ | |
{ | |
branchFilters : [], | |
pathFilters : [], | |
settingsSourceType : 2, | |
batchChanges : true, | |
maxConcurrentBuildsPerBranch : 1, | |
triggerType : "continuousIntegration" | |
} | |
], | |
retentionRules: [ | |
{ | |
branches: [ | |
"+refs/heads/*", | |
], | |
daysToKeep: 10, | |
minimumToKeep: 1, | |
deleteBuildRecord: true, | |
deleteTestResults: true, | |
}, | |
], | |
buildNumberFormat: "$(date:yyyyMMdd)$(rev:.r)", | |
jobAuthorizationScope: 1, | |
jobTimeoutInMinutes: 60, | |
jobCancelTimeoutInMinutes: 5, | |
process: { | |
yamlFilename: ".azuredevops/pipeline-azure.yml", | |
type: 2, | |
}, | |
repository: { | |
properties: { | |
labelSources: 6, | |
labelSourcesFormat: 0, | |
reportBuildStatus: true, | |
fetchDepth: 0, | |
cleanOptions: 3, | |
gitLfsSupport: false, | |
skipSyncSource: false, | |
checkoutNestedSubmodules: false, | |
}, | |
id: repositoryId, | |
type: "TfsGit", | |
name: repositoryId, | |
defaultBranch: "refs/heads/dev_integracao", | |
clean: true, | |
checkoutSubmodules: false, | |
}, | |
name: serviceName, | |
path: "\\hefesto\\", | |
type: 2, | |
project: { | |
id: project.id, | |
}, | |
} | |
try { | |
console.log(`${this.client.baseUrl}/${projectId}/_apis/build/definitions?api-version=5.0`) | |
const response: any = await axios.post( | |
`${this.client.baseUrl}${projectId}/_apis/build/definitions?api-version=5.0`, | |
JSON.stringify(body), | |
this.getRequestOptions() | |
) | |
return response.status === 200 ? response.data : {} | |
} catch (error) { | |
console.log(error) | |
throw new Error("Error on setup the pipeline.") | |
} | |
} | |
private async protectBranchApi(projectId: string, branch: string, repository: any) { | |
const policyTypeId = "fa4e907d-c16b-4a4c-9dfa-4916e5d171ab" | |
const body = { | |
"isEnabled": true, | |
"isBlocking": true, | |
"type": { | |
"id": policyTypeId | |
}, | |
"settings": { | |
"useSquashMerge": true, | |
"allowNoFastForward": true, | |
"allowSquash": true, | |
"allowRebase": true, | |
"allowRebaseMerge": true, | |
"scope": [{ | |
"repositoryId": repository.id, | |
"refName": `refs/heads/${branch}`, | |
"matchKind": "exact" | |
}] | |
} | |
} | |
try { | |
await axios.post( | |
`${this.client.baseUrl}/${projectId}/_apis/policy/configurations?api-version=5.1-preview`, | |
JSON.stringify(body), | |
this.getRequestOptions() | |
) | |
} catch (error) { | |
throw new Error("Error on setup the pipeline.") | |
} | |
const policyTypeId2 = "fa4e907d-c16b-4a4c-9dfa-4906e5d171dd" | |
const body2 = { | |
"isEnabled": true, | |
"isBlocking": true, | |
"isDeleted":false, | |
"type": { | |
"id": policyTypeId2 | |
}, | |
"settings": { | |
"allowDownvotes":false, | |
"blockLastPusherVote":false, | |
"creatorVoteCounts":true, | |
"requireVoteOnLastIteration":false, | |
"resetOnSourcePush":false, | |
"resetRejectionsOnSourcePush":false, | |
"minimumApproverCount": (branch == "dev_integracao" ? 1 : 2), | |
"scope": [ | |
{ | |
"repositoryId": repository.id, | |
"refName": `refs/heads/${branch}`, | |
"matchKind": "exact" | |
} | |
] | |
} | |
} | |
try { | |
await axios.post( | |
`${this.client.baseUrl}/${projectId}/_apis/policy/configurations?api-version=5.1-preview`, | |
JSON.stringify(body2), | |
this.getRequestOptions() | |
) | |
} catch (error) { | |
throw new Error("Error on setup the pipeline.") | |
} | |
return true | |
} | |
private async setupLibraryApi(projectId: string, repository: any ) { | |
const body = { | |
"variables": { | |
"auto_created": { | |
"value": true | |
}, | |
"name" : { | |
"value" : repository.name | |
}, | |
"private_agent_pool" : { | |
"value" : "OnPrem-Pool" | |
}, | |
"skip_sonarqube" : { | |
"value" : "false" | |
}, | |
"skip_rdm" : { | |
"value" : "false" | |
} | |
}, | |
"type": "Vsts", | |
"name": repository.name, | |
"description": `grupo de vars de configuração da esteira para o repositório: ${repository.name}` | |
} | |
try { | |
const response: any = await axios.post( | |
`${this.client.baseUrl}/${projectId}/_apis/distributedtask/variablegroups?api-version=5.0-preview.1`, | |
JSON.stringify(body), | |
this.getRequestOptions() | |
) | |
return response.status === 200 ? response.data : {} | |
} catch (error) { | |
throw new Error("Error on setup the pipeline.") | |
} | |
} | |
private async getProjectApi(name: string): Promise<any> { | |
console.log(`${this.client.baseUrl}_apis/projects/${name}`) | |
try { | |
const response: any = await axios.get( | |
`${this.client.baseUrl}/_apis/projects/${name}`, | |
this.getRequestOptions() | |
) | |
console.log(response) | |
return response.status === 200 ? response.data : {} | |
} catch (error) { | |
console.log(error) | |
return {} | |
} | |
} | |
private getRequestOptions() { | |
const token = Buffer.from(`:${this.token}`).toString("base64") | |
return { | |
headers: { | |
Authorization: `Basic ${token}`, | |
"Content-Type": "application/json", | |
}, | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment