Create & copy release content for coding project.

Make your release real quick!

目前為 2020-07-07 提交的版本,檢視 最新版本

  1. // ==UserScript==
  2. // @name Create & copy release content for coding project.
  3. // @namespace https://greasyfork.org/zh-CN/scripts/395451
  4. // @version 1.5
  5. // @description Make your release real quick!
  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 = `0${t.getUTCDate()}`.slice(-2);
  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. http://e.coding.testing-1-corp.coding.io/signin?buffet=${target}
  71. http://e.staging-corp.coding.io/signin?buffet=${target}
  72. https://e.coding.net/signin?buffet=${target}
  73.  
  74.  
  75. `;
  76.  
  77. const getCompareResult = (source, target, depot, project, corp) =>
  78. fetch(`https://${corp}.coding.net/api/user/${corp}/project/${project}/depot/${depot}/git/compare_v2?source=${source}&target=${target}&w=&prefix=`);
  79.  
  80. const getMRId = url => {
  81. const match = url.match(/\d+(\/)?$/) || [];
  82. return match.shift() || 0;
  83. }
  84.  
  85. const matchFromPath = () => {
  86. const { pathname, host } = window.location;
  87. const match = pathname.match(/\/p\/(.*)[\/d\/(.*)]?\/git\/compare\/(.*)\.\.\.(.*)/) || [];
  88.  
  89. const len = match.length;
  90. if (len < 3 || !match[1]) {
  91. throw new Error(`failed to parse url.`);
  92. }
  93.  
  94. const corp = host.replace('.coding.net', '');
  95. const [project, depot] = match[1].split(`/d/`);
  96.  
  97. return [
  98. ...match.slice(-2),
  99. depot || project,
  100. project,
  101. corp,
  102. ];
  103. }
  104.  
  105. async function makeRelease() {
  106. const [source, target, depot, project, corp] = matchFromPath()
  107. const res = await getCompareResult(source, target, depot, project, corp);
  108. const { data: { commits = [] } } = await res.json()
  109. const mrs = commits.filter(c => c.rawMessage.startsWith(`Accept Merge Request #`))
  110.  
  111. const list = mrs.map(m => {
  112. const arr = m.rawMessage.split('\n');
  113. const title = arr.find(i => i.includes(`Merge Request:`)).replace(`Merge Request:`, '').trim();
  114. const creator = arr.find(i => i.includes(`Created By:`)).replace(`Created By:`, '').trim();
  115. const link = arr.find(i => i.includes(`URL:`)).replace(`URL:`, '').trim();
  116. const mrId = getMRId(link);
  117. const mrText = `<a href="${link}">#${mrId}</a>`;
  118. return `- ` + [title, creator, mrText].join(`, `);
  119. });
  120. const content = list.join(`\n`);
  121.  
  122. const [date, tag] = getDateStr();
  123. const text = getContent(source, target, content, date, tag, depot, project, corp);
  124. GM_setClipboard(text, `text`);
  125. GM_notification(`Copied to 📝`, `💯`);
  126. }
  127.  
  128. const style = `button#create-copy-release-btn {
  129. z-index: 100;
  130. position: absolute;
  131. right: 30px;
  132. top: 80px;
  133. display: inline-block;
  134. border: none;
  135. padding: 1rem 2rem;
  136. margin: 0;
  137. text-decoration: none;
  138. background: #0069ed;
  139. color: #ffffff;
  140. font-family: sans-serif;
  141. font-size: 1rem;
  142. cursor: pointer;
  143. text-align: center;
  144. transition: background 250ms ease-in-out,
  145. transform 150ms ease;
  146. -webkit-appearance: none;
  147. -moz-appearance: none;
  148. }
  149.  
  150. button#create-copy-release-btn:hover,
  151. button#create-copy-release-btn:focus {
  152. background: #0053ba;
  153. }
  154.  
  155. button#create-copy-release-btn:focus {
  156. outline: 1px solid #fff;
  157. outline-offset: -4px;
  158. }
  159.  
  160. button#create-copy-release-btn:active {
  161. transform: scale(0.99);
  162. }`;
  163. GM_addStyle(style);
  164.  
  165. const btn = document.createElement('button');
  166. btn.innerText = `Create & Copy Release`;
  167. btn.id = `create-copy-release-btn`;
  168. btn.onclick = makeRelease;
  169.  
  170. let timer = null;
  171. let inserted = false;
  172. timer = setInterval(() => {
  173. const isComparePage = PageRegExp.test(window.location.pathname);
  174.  
  175. if (inserted) {
  176. if (isComparePage) return;
  177. btn.parentNode.removeChild(btn);
  178. inserted = false;
  179. return;
  180. }
  181.  
  182. if (!isComparePage) {
  183. return;
  184. }
  185.  
  186. const s = document.querySelector(`[class*=ref-selector]`);
  187. if (!s) return;
  188.  
  189. if (!inserted) {
  190. s.parentNode.appendChild(btn);
  191. inserted = true;
  192. }
  193. // clearInterval(timer);
  194. }, 200);
  195. })()