Create & copy release content for coding project.

try to take over the world!

当前为 2020-01-20 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Create & copy release content for coding project.
  3. // @namespace https://gist.github.com/cangzhang/5655e7b44fca10439c41e9e952fc0213
  4. // @version 1.2
  5. // @description try to take over the world!
  6. // @author You
  7. // @match https://*.coding.net/p/*/d/*/git/compare/*
  8. // @grant GM_setClipboard
  9. // @grant GM_notification
  10. // @grant GM_addStyle
  11. // ==/UserScript==
  12.  
  13. (function () {
  14. const PageRegExp = /\/p\/(.*)[\/d\/(.*)]?\/git\/compare\/(.*)\.\.\.(.*)/;
  15.  
  16. const getDateStr = () => {
  17. const t = new Date()
  18. const y = t.getUTCFullYear();
  19. const m = `0${t.getUTCMonth() + 1}`.slice(-2);
  20. const d = t.getUTCDate();
  21. const dateStr = `${y}-${m}-${d}`;
  22. const tag = `${y}${m}${d}.1`;
  23. return [dateStr, tag];
  24. }
  25.  
  26. const getContent = (source, target, content, date, tag, depot, project, corp) => `# 更新日期
  27.  
  28. > 开始时间:${date} 10:00
  29. > 结束时间:
  30.  
  31.  
  32. # 发布类型
  33.  
  34. 常规发布
  35.  
  36.  
  37. # 负责人
  38.  
  39. @name
  40.  
  41.  
  42. # 改动说明
  43.  
  44. ${content}
  45.  
  46.  
  47. # ${depot} diff
  48.  
  49. https://${corp}.coding.net/p/${project}/d/${depot}/git/compare/${source}...${target}
  50.  
  51.  
  52. # 更新服务
  53.  
  54. 服务 | 标签 | 顺序
  55. :---------- | :----------: | ----------:
  56. e-${depot} | ${tag} | 1
  57.  
  58.  
  59. # 发布后 ${depot} master 指向
  60.  
  61. \`\`\`
  62. ${target}
  63. \`\`\`
  64.  
  65.  
  66. # Checklist
  67.  
  68. `;
  69.  
  70. const getCompareResult = (source, target, depot, project, corp) =>
  71. fetch(`https://${corp}.coding.net/api/user/${corp}/project/${project}/depot/${depot}/git/compare_v2?source=${source}&target=${target}&w=&prefix=`);
  72.  
  73. const getMRId = url => {
  74. const match = url.match(/\d+(\/)?$/) || [];
  75. return match.shift() || 0;
  76. }
  77.  
  78. const matchFromPath = () => {
  79. const { pathname, host } = window.location;
  80. const match = pathname.match(/\/p\/(.*)[\/d\/(.*)]?\/git\/compare\/(.*)\.\.\.(.*)/) || [];
  81.  
  82. const len = match.length;
  83. if (len < 3 || !match[1]) {
  84. throw new Error(`failed to parse url.`);
  85. }
  86.  
  87. const corp = host.replace('.coding.net', '');
  88. const [project, depot] = match[1].split(`/d/`);
  89.  
  90. return [
  91. ...match.slice(-2),
  92. depot || project,
  93. project,
  94. corp,
  95. ];
  96. }
  97.  
  98. async function makeRelease() {
  99. const [source, target, depot, project, corp] = matchFromPath()
  100. const res = await getCompareResult(source, target, depot, project, corp);
  101. const { data: { commits = [] } } = await res.json()
  102. const mrs = commits.filter(c => c.rawMessage.startsWith(`Accept Merge Request #`))
  103.  
  104. const list = mrs.map(m => {
  105. const arr = m.rawMessage.split('\n');
  106. const title = arr.find(i => i.includes(`Merge Request:`)).replace(`Merge Request:`, '').trim();
  107. const creator = arr.find(i => i.includes(`Created By:`)).replace(`Created By:`, '').trim();
  108. const link = arr.find(i => i.includes(`URL:`)).replace(`URL:`, '').trim();
  109. const mrId = getMRId(link);
  110. const mrText = `<a href="${link}">#${mrId}</a>`;
  111. return `- ` + [title, creator, mrText].join(`, `);
  112. });
  113. const content = list.join(`\n`);
  114.  
  115. const [date, tag] = getDateStr();
  116. const text = getContent(source, target, content, date, tag, depot, project, corp);
  117. GM_setClipboard(text, `text`);
  118. GM_notification(`Copied to 📝`, `💯`);
  119. }
  120.  
  121. const style = `button#create-copy-release-btn {
  122. z-index: 100;
  123. position: absolute;
  124. right: 30px;
  125. top: 80px;
  126. display: inline-block;
  127. border: none;
  128. padding: 1rem 2rem;
  129. margin: 0;
  130. text-decoration: none;
  131. background: #0069ed;
  132. color: #ffffff;
  133. font-family: sans-serif;
  134. font-size: 1rem;
  135. cursor: pointer;
  136. text-align: center;
  137. transition: background 250ms ease-in-out,
  138. transform 150ms ease;
  139. -webkit-appearance: none;
  140. -moz-appearance: none;
  141. }
  142.  
  143. button#create-copy-release-btn:hover,
  144. button#create-copy-release-btn:focus {
  145. background: #0053ba;
  146. }
  147.  
  148. button#create-copy-release-btn:focus {
  149. outline: 1px solid #fff;
  150. outline-offset: -4px;
  151. }
  152.  
  153. button#create-copy-release-btn:active {
  154. transform: scale(0.99);
  155. }`;
  156. GM_addStyle(style);
  157.  
  158. const btn = document.createElement('button');
  159. btn.innerText = `Create & Copy Release`;
  160. btn.id = `create-copy-release-btn`;
  161. btn.onclick = makeRelease;
  162.  
  163. let timer = null;
  164. let inserted = false;
  165. timer = setInterval(() => {
  166. const isComparePage = PageRegExp.test(window.location.pathname);
  167.  
  168. if (inserted) {
  169. if (isComparePage) return;
  170. btn.parentNode.removeChild(btn);
  171. inserted = false;
  172. return;
  173. }
  174.  
  175. if (!isComparePage) {
  176. return;
  177. }
  178.  
  179. const s = document.querySelector(`[class*=ref-selector]`);
  180. if (!s) return;
  181.  
  182. if (!inserted) {
  183. s.parentNode.appendChild(btn);
  184. inserted = true;
  185. }
  186. // clearInterval(timer);
  187. }, 200);
  188. })()