- // ==UserScript==
- // @name Automated MCM Population
- // @namespace http://tampermonkey.net/
- // @version 1.0
- // @description Fetch package diff from pipeline heat-map and populate mcm.
- // @author adityamz@
- // @match https://code.amazon.com/version-sets/*/revisions/*
- // @match https://pipelines.amazon.com/pipelines/*/heat_map
- // @match https://pipelines.amazon.com/pipelines/*
- // @match https://mcm.amazon.com/cms/new*
- // @match https://mcm.amazon.com/cms/*/edit*
- // @require https://code.jquery.com/jquery-3.4.1.min.js
- // @grant GM.xmlHttpRequest
- // ==/UserScript==
-
- (function() {
-
- //========== This part is run in code.amazon.com ==========
- function addNewPackages(packageName, packageUrl) {
- unsafeWindow.packageDetails.push({
- "packageName": packageName,
- "type": "Added",
- "diffUrl": packageUrl,
- "owners": [],
- "commits": []
- });
- }
-
- function addRemovedPackages(packagename, packageUrl) {
- unsafeWindow.packageDetails.push({
- "packageName": packagename,
- "type": "Removed",
- "diffUrl": packageUrl,
- "owners": [],
- "commits": []
- });
- }
-
- function addBranchChangePackages(packageName, branchName, oldBranchName, startHash, endHash, diffUrl) {
- const asciURL = "https://pipelines.amazon.com/diff/pkg_changes?package_name=" + packageName
- + "&branch_name=" + branchName + "&old_commit_id=" + startHash + "&new_commit_id=" + endHash;
- GM.xmlHttpRequest({
- method: "GET",
- url: asciURL,
- onload: function() {
- if (this.readyState === 4 && this.status === 200) {
-
- const changes = [];
-
- let resElem = document.createElement("div");
- resElem.innerHTML = this.responseText;
- const commits = resElem.querySelectorAll('li');
- commits.forEach(function(commit){
- let author = commit.querySelector('.author>a').textContent;
- let description = commit.querySelector('.description').textContent;
- let repoChangeId = commit.querySelector('.change-link>a').href.split('/').reverse()[0];
- changes.push({author,description,repoChangeId});
- });
-
- let ownerList = [];
- const commitList = [];
- changes.forEach(function(change) {
- const author = change.author;
- const commit = author + '@: [' + change.description.split('\n')[0] + '](https://code.amazon.com/packages/'
- + packageName + '/commits/' + change.repoChangeId + ')';
- ownerList.push(author);
- commitList.push(commit);
- });
- ownerList = ownerList.filter((v, i, a) => a.indexOf(v) === i);
- const changeType = "Branch Changed (" + oldBranchName + " => " + branchName + ")";
- unsafeWindow.packageDetails.push({
- "packageName": packageName,
- "type": changeType,
- "diffUrl": diffUrl,
- "owners": ownerList,
- "commits": commitList
- });
- }
- }
- });
- }
-
- function addModifiedPackages(packageName, branchName, startHash, endHash, diffUrl) {
-
-
- const asciURL = "https://pipelines.amazon.com/diff/pkg_changes?package_name=" + packageName
- + "&branch_name=" + branchName + "&old_commit_id=" + startHash + "&new_commit_id=" + endHash;
-
-
- GM.xmlHttpRequest({
- method: "GET",
- url: asciURL,
- onload: function(response) {
- //console.log(this.responseText);
- if(this.status === 400){
- console.log(this.responseJSON);
- $("#toastDiff").text("Diff API Throttled.");
- $("#toastDiff").fadeIn("slow", function() { setTimeout(function() { $("#toastDiff").fadeOut("slow") }, 1500) });
- }
- if (this.readyState === 4 && this.status === 200) {
-
- const changes = [];
-
- let resElem = document.createElement("div");
- resElem.innerHTML = this.responseText;
- const commits = resElem.querySelectorAll('li');
- commits.forEach(function(commit){
- let author = commit.querySelector('.author>a').textContent;
- let description = commit.querySelector('.description').textContent;
- let repoChangeId = commit.querySelector('.change-link>a').href.split('/').reverse()[0];
- changes.push({author,description,repoChangeId});
- });
-
- console.log("fetched details for :"+ packageName);
- let ownerList = [];
- const commitList = [];
- changes.forEach(function(change) {
- const author = change.author;
- const commit = author + '@: [' + change.description.split('\n')[0] + '](https://code.amazon.com/packages/'
- + packageName + '/commits/' + change.repoChangeId + ')';
- ownerList.push(author);
- commitList.push(commit);
- });
- ownerList = ownerList.filter((v, i, a) => a.indexOf(v) === i);
- unsafeWindow.packageDetails.push({
- "packageName": packageName,
- "type": "Source Changed",
- "diffUrl": diffUrl,
- "owners": ownerList,
- "commits": commitList
- });
- }
- }
- });
- }
-
- function getPackageDiffOwners() {
- let allOwners = [];
- let diffOwnersString = "";
- let isPackageChecked = false;
- unsafeWindow.packageDetails.forEach(pkgDetail => {
- isPackageChecked = $("#" + pkgDetail.packageName + "Check").is(":checked");
- if (isPackageChecked) {
- diffOwnersString = diffOwnersString + "* [" + pkgDetail.packageName + "](https://code.amazon.com"
- + pkgDetail.diffUrl + ") [" + pkgDetail.type + "]\n";
- pkgDetail.owners.forEach(owner => {
- diffOwnersString = diffOwnersString + " * " + owner + "\n";
- allOwners.push(owner);
- })
- }
- })
- if (allOwners.length > 0) {
- allOwners = allOwners.filter((v, i, a) => a.indexOf(v) === i);
- diffOwnersString = diffOwnersString + "* All Owners\n";
- allOwners.forEach(owner => {
- diffOwnersString = diffOwnersString + " * " + owner + "\n";
- })
- }
- unsafeWindow.commitOwners=JSON.stringify(allOwners)
- return copyToClipboard(diffOwnersString);
- }
-
- function getPackageDiffCommits() {
- let diffCommitsString = "";
- let isPackageChecked = false;
- unsafeWindow.packageDetails.forEach(pkgDetail => {
- isPackageChecked = $("#" + pkgDetail.packageName + "Check").is(":checked");
- if (isPackageChecked) {
- diffCommitsString = diffCommitsString + "* [" + pkgDetail.packageName + "](https://code.amazon.com"
- + pkgDetail.diffUrl + ") [" + pkgDetail.type + "]\n";
- pkgDetail.commits.forEach(commit => {
- diffCommitsString = diffCommitsString + " * " + commit + "\n";
- })
- }
-
- })
-
- unsafeWindow.commitChanges = diffCommitsString;
-
- let pipelineDescription = getPipelineDescription(unsafeWindow.pipelineDetails, unsafeWindow.vsDetails)
- let commitDetailsDescription = getCommitDetailsDescription(diffCommitsString)
-
- return copyToClipboard(pipelineDescription + '\n'+commitDetailsDescription);
- }
-
- function copyToClipboard(text) {
- if (text !== "") {
- $("#toastDiff").text("Copied to clipboard!");
- $("#toastDiff").fadeIn("slow", function() { setTimeout(function() { $("#toastDiff").fadeOut("slow") }, 1500) });
- const textarea = document.createElement("textarea");
- textarea.textContent = text;
- textarea.style.position = "fixed";
- document.body.appendChild(textarea);
- textarea.select();
- try {
- document.execCommand("copy");
- } catch (ex) {
- console.warn("Copy to clipboard failed.", ex);
- } finally {
- document.body.removeChild(textarea);
- return true;
- }
- } else {
- $("#toastDiff").text("No diff found! Try again.");
- $("#toastDiff").fadeIn("slow", function() { setTimeout(function() { $("#toastDiff").fadeOut("slow") }, 1500) });
- return false;
- }
- }
-
- unsafeWindow.packageDetails = [];
- unsafeWindow.pipelineDetails = {pipelineName:'',packages:[]};
-
- $('#packages tr.added-pkg').each(function(i, el) {
- const $tds = $(this).find("td");
- const packageUrl = $tds.eq(0).find("a").attr("href");
- const packageName = $tds.eq(0).text();
- const checkbox = document.createElement("input");
- checkbox.setAttribute("type", "checkbox");
- checkbox.setAttribute("id", (packageName + "Check"));
- checkbox.setAttribute("style", "margin-right:5px");
- $tds.eq(0).prepend(checkbox);
- addNewPackages(packageName, packageUrl);
- })
-
- $('#packages tr.error').each(function(i, el) {
- const $tds = $(this).find('td');
- const packageUrl = $tds.eq(0).find('a').attr('href');
- const packageName = $tds.eq(0).text();
- const checkbox = document.createElement("input");
- checkbox.setAttribute("type", "checkbox");
- checkbox.setAttribute("id", (packageName + "Check"));
- checkbox.setAttribute("style", "margin-right:5px");
- $tds.eq(0).prepend(checkbox);
- addRemovedPackages(packageName, packageUrl);
- })
-
- $('#packages tr.branch-change').each(function(i, el) {
- const $tds = $(this).find('td');
- const diffUrl = $tds.eq(5).find('a').attr('href').trim();
- const startHash = $tds.eq(1).find('a').attr('href').split('/')[4].trim();
- const endHash = $tds.eq(3).find('a').attr('href').split('/')[4].trim();
- const packageName = $tds.eq(0).text().trim();
- const oldBranchName = $tds.eq(6).text().split("->")[0].trim();
- const branchName = $tds.eq(6).text().split("->")[1].trim();
- const checkbox = document.createElement("input");
- checkbox.setAttribute("type", "checkbox");
- checkbox.setAttribute("id", (packageName + "Check"));
- checkbox.setAttribute("style", "margin-right:5px");
- $tds.eq(0).prepend(checkbox);
-
- $(checkbox).change(function(){
- if(this.checked){
- addBranchChangePackages(packageName, branchName, oldBranchName, startHash, endHash, diffUrl);
- }
-
- })
-
-
- })
-
- $('#packages tr.source-change').each(function(i, el) {
- const $tds = $(this).find('td');
- const diffUrl = $tds.eq(5).find('a').attr('href').trim();
- const startHash = $tds.eq(1).find('a').attr('href').split('/')[4].trim();
- const endHash = $tds.eq(3).find('a').attr('href').split('/')[4].trim();
- const packageName = $tds.eq(0).text().trim();
- const branchName = $tds.eq(6).text().trim();
- const checkbox = document.createElement("input");
- checkbox.setAttribute("type", "checkbox");
- checkbox.setAttribute("id", (packageName + "Check"));
- checkbox.setAttribute("style", "margin-right:5px");
- $tds.eq(0).prepend(checkbox);
- $(checkbox).change(function(){
-
- if(this.checked){
- addModifiedPackages(packageName, branchName, startHash, endHash, diffUrl);
- }
-
-
- })
-
- })
-
-
- function createMCMWithTemplate(mcm_id){
- let diffcommit = getPackageDiffCommits();
- let diffpackage = getPackageDiffOwners();
-
- window.location.href = "https://mcm.amazon.com/cms/new?from_template="+mcm_id+"&commitChanges="+encodeURIComponent(unsafeWindow.commitChanges)+"&commitOwners="+unsafeWindow.commitOwners+
- "&vsDetails=" + encodeURIComponent(JSON.stringify(unsafeWindow.vsDetails)) + "&pipelineDetails=" + encodeURIComponent(JSON.stringify(unsafeWindow.pipelineDetails));
-
- }
-
- function updateMCMWithExistingDraft(mcm_id){
- let diffcommit = getPackageDiffCommits();
- let diffpackage = getPackageDiffOwners();
-
- window.location.href = "https://mcm.amazon.com/cms/"+mcm_id+"/edit?commitChanges="+encodeURIComponent(unsafeWindow.commitChanges)+"&commitOwners="+unsafeWindow.commitOwners+
- "&vsDetails=" + encodeURIComponent(JSON.stringify(unsafeWindow.vsDetails)) + "&pipelineDetails=" + encodeURIComponent(JSON.stringify(unsafeWindow.pipelineDetails));
- }
-
- const vsRangeDiff = document.getElementById('vs_range_diff');
- if (vsRangeDiff) {
- const mainDiv = document.createElement('div');
- mainDiv.innerHTML = '<div><div style="overflow: visible;"><div class="text-right top-buffer-small" style="background: aliceblue;padding: 8px;filter: drop-shadow(2px 2px 2px black);"><div> <button type="button" class="btn btn-default" id="diffCommits" style="width: 48%;float: left;">Copy Diff Commits</button> <button type="button" class="btn btn-default" id="diffOwners" style=" width: 48%;">Copy Diff Owners</button><input id="mcm_id" type="input" style="width: 100%;margin-top: 10px" placeholder="MCM template ID eg: MCM-78603254 or leave empty to use default template"/><button type="button" disabled class="btn btn-default" id="createMCM" style="width: 100%;margin-top: 10px">Loading ...</button></div></div><div id="toastDiff" style="width: 180px; background-color: rgba(0, 0, 0, 0.8); height: 30px; position: absolute; margin: 20px 20px 20px 6%; border-radius: 50px; color: rgba(255, 255, 255, 0.8);text-align: center;padding-top: 6px; display: none;"></div></div></div>';
- vsRangeDiff.appendChild(mainDiv);
-
- unsafeWindow.pipelineDetails = JSON.parse(new URLSearchParams(window.location.search).get('pipelineDetails'));
- unsafeWindow.vsDetails = JSON.parse(new URLSearchParams(window.location.search).get('vsDetails'));
-
- //mark all the packages autobuilt in the pipeline as checked for diff creation
- window.addEventListener("load", ()=>{
- unsafeWindow.pipelineDetails.packages.forEach((pkg)=>{
- let pkgElements = document.querySelectorAll('#'+pkg+'Check');
- pkgElements.forEach((pkgElem)=>{
- $(pkgElem).click();
- })
- });
-
- $('#createMCM').text('Create MCM');
- $('#createMCM').prop('disabled',false);
-
- });
-
-
- // adding click listener for diff commits
- $( "#diffCommits" ).click(function() {
- getPackageDiffCommits();
- });
-
- $( "#diffOwners" ).click(function() {
- getPackageDiffOwners();
- });
-
- $( "#createMCM" ).click(function() {
- const mcm_id = $('#mcm_id').val();
- if(mcm_id){
- updateMCMWithExistingDraft(mcm_id);
- }
- else {
- createMCMWithTemplate('7e9a85a5-bd0a-4560-8379-00a73ef82f1b');
- }
- });
-
-
- }
-
-
- //========== This part is run in pipelines.amazon.com ==========
- function getVSDiffLink(href) {
- const splittedHref = href.split("&");
- const currVS = splittedHref[0].split("=")[1];
- const currRev = splittedHref[1].split("=")[1];
- const prevVS = splittedHref[3].split("=")[1];
- const prevRev = splittedHref[4].split("=")[1];
- const vsDetails = {};
- vsDetails.cur = currRev;
- vsDetails.prev = prevRev;
- vsDetails.name = prevVS;
-
-
- return "https://code.amazon.com/version-sets/" + currVS + "/revisions/" + currRev + "?previous=" + prevRev + "&previous_vs=" + prevVS +
- "&pipelineDetails=" + sessionStorage.getItem('pipelineDetails') +
- "&vsDetails=" + JSON.stringify(vsDetails);
- }
-
- const pipelineName = document.querySelector('.pipeline-name-header');
-
- if(pipelineName){
- unsafeWindow.pipelineDetails.pipelineName = pipelineName.innerText;
- }
-
-
-
- const packages = document.querySelector('#stage-name-Packages > div > h3 > span');
- if(packages){
- document.querySelectorAll('.autobuild .target-details > div.name').forEach((pkg)=>{
- let pkg_name = pkg.getAttribute('data-targetname').split('/')[0]
- unsafeWindow.pipelineDetails.packages.push(pkg_name)
-
- })
-
- sessionStorage.setItem("pipelineDetails",JSON.stringify(unsafeWindow.pipelineDetails))
-
- }
-
- const diffLinkElements = document.getElementsByClassName("diff-link");
- if (diffLinkElements && !packages) {
- for(let i=0; i < diffLinkElements.length; i++) {
- const element = diffLinkElements[i];
- const href = element.getElementsByTagName("a")[0].getAttribute("href");
- const vsDiffLink = getVSDiffLink(href);
- const aTag = document.createElement("a");
- aTag.setAttribute("href", vsDiffLink);
- aTag.innerText = "VS";
- element.appendChild(aTag);
- }
- }
-
- //this code part will run in mcm
-
- const insideMcm = $('.mcm-logo').length
-
-
- function getPipelineDescription(pipelineDetails, vsDetails){
-
- let pipelineDescription = ""
-
- pipelineDescription+= `## ${pipelineDetails.pipelineName}\n`
- pipelineDescription+= `- Pipeline Link - https://pipelines.amazon.com/pipelines/${pipelineDetails.pipelineName}\n`
- pipelineDescription+= `- Pipeline Diff - [Link](https://pipelines.amazon.com/diff?new_name=${vsDetails.name}&new_revision=${vsDetails.cur}&new_type=VS&old_name=${vsDetails.name}&old_revision=${vsDetails.prev}&old_type=VS)\n`
- pipelineDescription+= `- Current VFI - ${vsDetails.name}@B${vsDetails.prev}\n`
- pipelineDescription+= `- VFI to be Deployed - ${vsDetails.name}@B${vsDetails.cur}\n`
-
- return pipelineDescription;
-
-
-
-
-
- }
-
- function getCommitDetailsDescription(commitDetails){
-
- let commitChanges = "";
- if(commitDetails){
- commitChanges+="#### Changes to be promoted in prod:\n"
- commitChanges+=commitDetails;
- }
-
- return commitChanges;
- }
-
- function updateDescription(commitDetails, vsDetails, pipelineDetails){
- const curr = $('#description').val()
- const rollbackId = "## Rollback Procedure";
-
- const pipelineDescription=getPipelineDescription(pipelineDetails, vsDetails);
- console.log(pipelineDescription);
-
- const pos = curr.indexOf('#### What is the purpose of this activity or change?')<0?curr.indexOf('Activity Details'):curr.indexOf('#### What is the purpose of this activity or change?');
-
- let commitChanges = getCommitDetailsDescription(commitDetails);
-
- let data = curr.substr(0, pos) + pipelineDescription+'\n'+ commitChanges+'\n' + curr.substr(pos);
-
-
-
- $('#description').val(data)
-
- }
-
- function updateMCMTitle(pipelineDetails){
- const title = $('#title')
- title.val(title.val()+pipelineDetails.pipelineName)
-
- }
-
- function addcommitOwners(commitOwners) {
-
- commitOwners.forEach((owner)=>{
- $('#add_approver_login').val(owner)
- $('#add_approver').click()
- })
-
- }
-
- if(insideMcm>0){
- const data = new URLSearchParams(window.location.search);
- const commitDetails = decodeURIComponent(data.get('commitChanges'));
- const versionSetDetails = JSON.parse(decodeURIComponent(data.get('vsDetails')));
- const pipelineDetails = JSON.parse(decodeURIComponent(data.get('pipelineDetails')));
- console.log(pipelineDetails);
- console.log(versionSetDetails);
- console.log(commitDetails);
- const commitOwners = JSON.parse(data.get('commitOwners'));
- updateMCMTitle(pipelineDetails);
-
- if(versionSetDetails){
- updateDescription(commitDetails, versionSetDetails, pipelineDetails)
- }
- if(commitOwners && commitOwners.length>0){
- addcommitOwners(commitOwners);
- }
- }
-
- })();