Get Branch Name

Uses ticket type and description to generate a branch name

  1. // ==UserScript==
  2. // @name Get Branch Name
  3. // @namespace http://tampermonkey.net/
  4. // @version 0.2
  5. // @description Uses ticket type and description to generate a branch name
  6. // @author https://github.com/cgriebel
  7. // @match https://roger-team.atlassian.net/*
  8. // @icon https://www.google.com/s2/favicons?sz=64&domain=atlassian.net
  9. // @grant none
  10. // ==/UserScript==
  11.  
  12. (function () {
  13. 'use strict';
  14.  
  15. const getTitle = () =>
  16. document
  17. .querySelector('[data-test-id="issue.views.issue-base.foundation.summary.heading"]')
  18. .textContent
  19. .trim()
  20. // Remove common branch prefixes
  21. .replaceAll(/\[US\]|(FE|BE) \- /g, '')
  22. // Replace invalid branch characters with '_'
  23. .replaceAll(/[ "'&:]+/g, '_')
  24. // Replace regex special characters separate so the other regexs are easier to grok
  25. .replaceAll(/[/\-\\^$*+?.()|[\]{}]+/g, '_')
  26. // Compress repeated '_'
  27. .replaceAll(/_+/g, '_')
  28. // Trim trailing '_'
  29. .replaceAll(/^_*([^_].*[^_])_*$/g, '$1')
  30. .toLowerCase();
  31.  
  32. function getPrefix() {
  33. const ticketType = document
  34. .querySelector('[data-testid="issue.views.issue-base.foundation.change-issue-type.button"] img')
  35. .getAttribute("alt")
  36.  
  37. console.log(ticketType);
  38. switch (ticketType) {
  39. case 'Bug':
  40. case 'Escalation':
  41. case 'QA Test Bugs':
  42. case 'QA Test Bug (Sub Task)': // this should probably match the parent ticket
  43. return 'fix';
  44. case 'Task':
  45. case 'Spike':
  46. return 'chore';
  47. case 'Story':
  48. case 'Sub-task':
  49. case 'New Feature':
  50. default:
  51. return 'feature';
  52. }
  53. }
  54.  
  55. const getIssueId = () =>
  56. document
  57. .querySelector('[data-testid="issue.views.issue-base.foundation.breadcrumbs.current-issue.item"]')
  58. .textContent;
  59.  
  60. const getBranch = () => `${getPrefix()}/${getIssueId()}_${getTitle()}`;
  61.  
  62. function init() {
  63. addStyles()
  64. if (document.getElementById('cg-copy-branch-name')) return;
  65.  
  66. window.getBranch = getBranch;
  67. window.init = init;
  68.  
  69. const createCommitElem = document
  70. .querySelector('[data-testid="development-summary-branch.ui.summary-item"]')
  71.  
  72. if (!createCommitElem) return;
  73.  
  74. const devContainer = createCommitElem.parentElement;
  75. const copyBranchNameBtn = document.createElement('div');
  76. copyBranchNameBtn.setAttribute('id', 'cg-copy-branch-name')
  77. copyBranchNameBtn.innerHTML = `<span>Copy branch name</span>`;
  78. copyBranchNameBtn.addEventListener("click", () => {
  79. const branchName = getBranch();
  80. console.log(branchName)
  81. navigator.clipboard.writeText(branchName);
  82. })
  83. devContainer.insertBefore(copyBranchNameBtn, createCommitElem)
  84. }
  85.  
  86. function addStyles() {
  87. const existing = document.querySelector('#cg-style-copy-branch');
  88. if (existing) return;
  89. console.log("adding custom styles");
  90. const styleElem = document.createElement('style');
  91. styleElem.setAttribute('id', 'cg-style-copy-branch')
  92. styleElem.innerHTML = `
  93. #cg-copy-branch-name {
  94. color: var(--ds-link, #0052CC) !important;
  95. font-weight: 500;
  96. height: 32px;
  97. display: flex;
  98. align-items: center;
  99. margin: 2px -8px 0px;
  100. width: 100%;
  101. max-width: 150px;
  102. cursor: pointer;
  103. padding-left: 32px;
  104. }
  105.  
  106. #cg-copy-branch-name:hover {
  107. background-color: var(--ds-background-neutral-subtle-hovered,#EBECF0);
  108. border-radius: 3px;
  109. }
  110. `
  111. const head = document.querySelector('head');
  112. head.append(styleElem);
  113. }
  114.  
  115. setInterval(() => {
  116. init();
  117. }, 250)
  118. })();