iWhaleCloudGit

git 批量操作

  1. // ==UserScript==
  2. // @name iWhaleCloudGit
  3. // @namespace http://tampermonkey.net/
  4. // @version 0.1.3
  5. // @description git 批量操作
  6. // @author HolmesZhao
  7. // @match *://globaltech-code.alipay.com/*
  8. // @icon https://www.google.com/s2/favicons?sz=64&domain=alipay.com
  9. // @require https://cdn.jsdelivr.net/npm/jquery@3.7.1/dist/jquery.min.js
  10. // @require https://cdn.jsdelivr.net/npm/jquery-toast-plugin@1.3.2/dist/jquery.toast.min.js
  11. // @resource customCSS https://cdn.jsdelivr.net/npm/jquery-toast-plugin@1.3.2/dist/jquery.toast.min.css
  12. // @grant GM_getResourceText
  13. // @grant GM_addStyle
  14. // @license MIT
  15. // ==/UserScript==
  16.  
  17. (function () {
  18. "use strict";
  19.  
  20. // 吕廷元,4913
  21. // 林伟,4896
  22. // 赵五一,4940
  23.  
  24. const beProjectUrl =
  25. "https://globaltech-code.alipay.com/webapi/groups/Banco/overview?types=&page=1&per_page=15&events_page=1&_output_charset=utf-8&_input_charset=utf-8&ctoken=VXzCenNuvtS5YEzN";
  26. const beProjectReferrerUrl =
  27. "https://globaltech-code.alipay.com/groups/Banco";
  28. const qiProjectUrl =
  29. "https://globaltech-code.alipay.com/webapi/groups/qicard/overview?types=&page=1&per_page=15&events_page=1&_output_charset=utf-8&_input_charset=utf-8&ctoken=VXzCenNuvtS5YEzN";
  30. const qiProjectReferrerUrl =
  31. "https://globaltech-code.alipay.com/groups/qicard";
  32. // Your code here...
  33. async function getProjects(url, referrer) {
  34. const source = await fetch(url, {
  35. headers: {
  36. accept: "*/*",
  37. "accept-language": "zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7",
  38. "antcode-request-type": "ANTCODE_WEB_REQUEST",
  39. "linkc-request-type": "LINKC_WEB_REQUEST",
  40. priority: "u=1, i",
  41. "sec-ch-ua": '"Not-A.Brand";v="99", "Chromium";v="124"',
  42. "sec-ch-ua-mobile": "?0",
  43. "sec-ch-ua-platform": '"macOS"',
  44. "sec-fetch-dest": "empty",
  45. "sec-fetch-mode": "cors",
  46. "sec-fetch-site": "same-origin",
  47. "x-request-lib": "@alipay/bigfish/sdk/fetch",
  48. },
  49. referrer: referrer,
  50. referrerPolicy: "strict-origin-when-cross-origin",
  51. body: null,
  52. method: "GET",
  53. mode: "cors",
  54. credentials: "include",
  55. });
  56. return source.json();
  57. }
  58.  
  59. function createList(datas, top, left) {
  60. var myDiv = document.getElementById("myDiv");
  61. if (myDiv == null) {
  62. myDiv = document.createElement("div");
  63. myDiv.setAttribute("id", "myDiv");
  64. myDiv.setAttribute(
  65. "style",
  66. `position: fixed;top: ${top}px;left: ${left}px;background-color: #ddd;border: 1px solid #000;padding: 10px;z-index:1000`
  67. );
  68. document.body.appendChild(myDiv);
  69. } else {
  70. myDiv.innerHTML = "";
  71. }
  72.  
  73. var selectList = document.createElement("select");
  74. selectList.setAttribute("multiple", "");
  75. selectList.setAttribute(
  76. "style",
  77. "background-color: white; padding-right: 9px; height:" +
  78. datas.length * 22 +
  79. "px;" // 22 = 18(字号) + 4(间隙)
  80. );
  81.  
  82. const selectedValues = [];
  83. selectList.addEventListener("change", () => {
  84. selectedValues.length = 0;
  85. for (let i = 0; i < selectList.options.length; i++) {
  86. const option = selectList.options[i];
  87. if (option.selected) {
  88. selectedValues.push(option.value);
  89. }
  90. }
  91. });
  92.  
  93. const inputHTML = `
  94. <div style="padding: 10px;">
  95. <div style="display: flex;">
  96. <span style="width: 80px;">标题</span>
  97. <textarea id="iwc_title" placeholder="请输入标题" style="margin-left: 5px;"></textarea>
  98. </div>
  99. <div style="display: flex;margin-top: 10px;">
  100. <span style="width: 80px;">描述</span>
  101. <textarea id="iwc_desc" placeholder="请输入描述" style="margin-left: 5px;"></textarea>
  102. </div>
  103. <div style="display: flex;margin-top: 10px;">
  104. <span style="width: 80px;">源分支</span>
  105. <textarea id="iwc_source" placeholder="请输入源分支, eg: develop-4b-xxxxx" style="margin-left: 5px;"></textarea>
  106. </div>
  107. <div style="display: flex;margin-top: 10px;">
  108. <span style="width: 80px;">目标分支</span>
  109. <textarea id="iwc_target" placeholder="请输入目标分支, eg: develop-4b" style="margin-left: 5px;"></textarea>
  110. </div>
  111. <div style="display: flex;margin-top: 10px;">
  112. <span style="width: 80px;">合并后删除来源分支</span>
  113. <textarea
  114. id="iwc_delete"
  115. placeholder="默认不删除 0 也可以代码为默认删除 1"
  116. style="margin-left: 5px;"
  117. >0</textarea>
  118. </div>
  119. <div style="display: flex;margin-top: 10px;">
  120. <span style="width: 80px;">合并指派给</span>
  121. <textarea id="iwc_assignee" placeholder="请输入合并人" style="margin-left: 5px;"></textarea>
  122. </div>
  123. <div style="display: flex;margin-top: 10px;">
  124. <span style="width: 80px;">审核人</span>
  125. <textarea
  126. id="iwc_reviewer_ids"
  127. placeholder="请输入审核人, 用英文逗号链接"
  128. style="margin-left: 5px;"
  129. ></textarea>
  130. </div>
  131. <div style="display: flex;margin-top: 10px;">
  132. <span style="width: 80px;">审核票数</span>
  133. <textarea
  134. id="iwc_threshold"
  135. placeholder="请输入审核票数"
  136. style="margin-left: 5px;"
  137. ></textarea>
  138. </div>
  139. </div>
  140. `;
  141. const inputDiv = document.createElement("div");
  142. inputDiv.innerHTML = inputHTML;
  143.  
  144. var contentDiv = document.createElement("div");
  145. contentDiv.style.display = "flex";
  146. myDiv.appendChild(contentDiv);
  147. contentDiv.appendChild(selectList);
  148. contentDiv.appendChild(inputDiv);
  149.  
  150. var buttonDiv = document.createElement("div");
  151. myDiv.appendChild(buttonDiv);
  152.  
  153. var buttonClose = document.createElement("button");
  154. buttonClose.textContent = "关闭";
  155. buttonClose.style.marginLeft = "10px";
  156. buttonClose.style.marginTop = "10px";
  157. buttonClose.onclick = () => {
  158. myDiv.style.display = "none";
  159. };
  160. buttonDiv.appendChild(buttonClose);
  161.  
  162. var buttonRefresh = document.createElement("button");
  163. buttonRefresh.textContent = "刷新列表";
  164. buttonRefresh.style.marginLeft = "10px";
  165. buttonRefresh.style.marginTop = "10px";
  166. buttonRefresh.onclick = async () => {
  167. // selectList 移除所有子节点
  168. while (selectList.firstChild) {
  169. selectList.removeChild(selectList.firstChild);
  170. }
  171. const result = await getProjects(beProjectUrl, beProjectReferrerUrl);
  172. let options = result.projects;
  173.  
  174. for (var i = 0; i < options.length; i++) {
  175. var option = document.createElement("option");
  176. option.setAttribute("value", options[i].id);
  177. option.text = options[i].path_with_namespace;
  178. option.style.fontSize = "18px";
  179. selectList.appendChild(option);
  180. }
  181. };
  182. buttonDiv.appendChild(buttonRefresh);
  183.  
  184. var button = document.createElement("button");
  185. button.textContent = "批量 MR";
  186. button.style.marginTop = "10px";
  187. button.style.marginLeft = "10px";
  188. button.onclick = () => {
  189. var textArr = [];
  190. datas.forEach((e) => {
  191. if (selectedValues.indexOf(e.id + "") === -1) return;
  192.  
  193. const id = e.id;
  194. const title = e.path_with_namespace;
  195. const json = { id: id, title: title };
  196. textArr.push(json);
  197. });
  198.  
  199. console.log(textArr);
  200. batchMR(textArr);
  201. };
  202. buttonDiv.appendChild(button);
  203.  
  204. var options = datas;
  205.  
  206. for (var i = 0; i < options.length; i++) {
  207. var option = document.createElement("option");
  208. option.setAttribute("value", options[i].id);
  209. option.text = options[i].path_with_namespace;
  210. option.style.fontSize = "18px";
  211. selectList.appendChild(option);
  212. }
  213. }
  214.  
  215. function batchMR(datas) {
  216. if (datas.length === 0) {
  217. alert("请选择项目");
  218. return false;
  219. }
  220.  
  221. const iwc_title = document.getElementById("iwc_title");
  222. const iwc_desc = document.getElementById("iwc_desc");
  223. const iwc_source = document.getElementById("iwc_source");
  224. const iwc_target = document.getElementById("iwc_target");
  225. const iwc_delete = document.getElementById("iwc_delete");
  226. const iwc_assignee = document.getElementById("iwc_assignee");
  227. const iwc_reviewer_ids = document.getElementById("iwc_reviewer_ids");
  228. const iwc_threshold = document.getElementById("iwc_threshold");
  229. // 校验是否存在并且字符串长度是否满足要求
  230. if (!iwc_title || iwc_title.value.trim().length === 0) {
  231. alert("Title is required");
  232. return false;
  233. }
  234.  
  235. if (!iwc_desc || iwc_desc.value.trim().length === 0) {
  236. alert("Description is required");
  237. return false;
  238. }
  239.  
  240. if (!iwc_source || iwc_source.value.trim().length === 0) {
  241. alert("Source is required");
  242. return false;
  243. }
  244.  
  245. if (!iwc_target || iwc_target.value.trim().length === 0) {
  246. alert("Target is required");
  247. return false;
  248. }
  249.  
  250. if (!iwc_delete || iwc_delete.value.trim().length === 0) {
  251. alert("Delete is required");
  252. return false;
  253. }
  254.  
  255. if (!iwc_assignee || iwc_assignee.value.trim().length === 0) {
  256. alert("Assignee is required");
  257. return false;
  258. }
  259.  
  260. if (!iwc_reviewer_ids || iwc_reviewer_ids.value.trim().length === 0) {
  261. alert("Reviewer IDs is required");
  262. return false;
  263. }
  264.  
  265. if (!iwc_threshold || iwc_threshold.value.trim().length === 0) {
  266. alert("Threshold is required");
  267. return false;
  268. }
  269. const myHeaders = new Headers();
  270. myHeaders.append("accept", "application/json");
  271. myHeaders.append("accept-language", "zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7");
  272. myHeaders.append("antcode-request-type", "ANTCODE_WEB_REQUEST");
  273. myHeaders.append("content-type", "application/json");
  274. myHeaders.append("dnt", "1");
  275. myHeaders.append("linkc-request-type", "LINKC_WEB_REQUEST");
  276. myHeaders.append("origin", "https://globaltech-code.alipay.com");
  277. myHeaders.append("priority", "u=1, i");
  278. myHeaders.append("sec-ch-ua", "\"Not-A.Brand\";v=\"99\", \"Chromium\";v=\"124\"");
  279. myHeaders.append("sec-ch-ua-mobile", "?0");
  280. myHeaders.append("sec-ch-ua-platform", "\"macOS\"");
  281. myHeaders.append("sec-fetch-dest", "empty");
  282. myHeaders.append("sec-fetch-mode", "cors");
  283. myHeaders.append("sec-fetch-site", "same-origin");
  284. myHeaders.append("x-request-lib", "@alipay/bigfish/sdk/fetch");
  285.  
  286. const raw = JSON.stringify({
  287. "title": iwc_title.value,
  288. "source_branch": iwc_source.value,
  289. "target_branch": iwc_target.value,
  290. "description": iwc_desc.value,
  291. "labels": "",
  292. "should_remove_source_branch": iwc_delete.value === "1",
  293. "squash_merge": false,
  294. "assignee_id": iwc_assignee.value,
  295. "review_required": true,
  296. "reviewer_ids": iwc_reviewer_ids.value,
  297. "threshold": iwc_threshold.value
  298. });
  299.  
  300. const requestOptions = {
  301. method: "POST",
  302. headers: myHeaders,
  303. body: raw,
  304. redirect: "follow"
  305. };
  306.  
  307. datas.forEach((e) => {
  308. fetch(`https://globaltech-code.alipay.com/api/v3/projects/${e.id}/pull_requests?_output_charset=utf-8&_input_charset=utf-8`, requestOptions)
  309. .then((response) => response.text())
  310. .then((result) => console.log(result))
  311. .catch((error) => console.error(error));
  312. });
  313. }
  314.  
  315. async function startLoad(title) {
  316. const myDiv = document.getElementById("myDiv");
  317. if (myDiv) {
  318. myDiv.style.display = "block";
  319. return;
  320. }
  321. const buttons = document.getElementsByClassName("mmbutton");
  322. let button = null;
  323. for (let index = 0; index < buttons.length; index++) {
  324. const element = buttons[index];
  325. if (element.innerText == title) {
  326. button = element;
  327. }
  328. }
  329. if (button == null) {
  330. alert(`没有找到 ${title} 按钮`);
  331. return;
  332. }
  333. const result = await getProjects(beProjectUrl, beProjectReferrerUrl);
  334. createList(result.projects, button.offsetHeight, button.offsetLeft);
  335. }
  336.  
  337. function addButton(name, marginLeft, top, fun) {
  338. var txt = document.createTextNode(name);
  339. var btn = document.createElement("button");
  340. btn.className = "mmbutton";
  341. btn.style =
  342. "z-index: 9999; font-size: large; position: fixed; top: " +
  343. top +
  344. "px; left: " +
  345. marginLeft +
  346. "px;border:1px solid black; padding: 0 10px;";
  347. btn.onclick = () => {
  348. fun(name);
  349. };
  350. btn.appendChild(txt);
  351. document.body.appendChild(btn);
  352. return btn.offsetWidth + btn.offsetLeft;
  353. }
  354.  
  355. async function review() {
  356. try {
  357. const result = await getProjects(qiProjectUrl, qiProjectReferrerUrl);
  358. let options = result.projects;
  359. let project = ""
  360. options.forEach(e => {
  361. if (window.location.href.includes(e.path)) {
  362. project = e.id
  363. }
  364. })
  365. if (project == "") {
  366. console.log("project", project)
  367. return;
  368. }
  369. const pullId = parseInt(window.location.href.split('pull_requests/')[1])
  370. if (pullId == undefined || pullId == 0) {
  371. console.log("pullId", pullId)
  372. return;
  373. }
  374. const pullReqs = await fetch("https://globaltech-code.alipay.com/webapi/projects/"+project+"/get_pull_request_by_iid?iid="+pullId+"&_output_charset=utf-8&_input_charset=utf-8&ctoken=ElGV8J1MmfmUFbun", {
  375. "headers": {
  376. "accept": "*/*",
  377. "accept-language": "zh-CN,zh;q=0.9",
  378. "antcode-request-type": "ANTCODE_WEB_REQUEST",
  379. "linkc-request-type": "LINKC_WEB_REQUEST",
  380. "priority": "u=1, i",
  381. "sec-ch-ua": "\"Not/A)Brand\";v=\"8\", \"Chromium\";v=\"126\"",
  382. "sec-ch-ua-mobile": "?0",
  383. "sec-ch-ua-platform": "\"macOS\"",
  384. "sec-fetch-dest": "empty",
  385. "sec-fetch-mode": "cors",
  386. "sec-fetch-site": "same-origin",
  387. "x-request-lib": "@alipay/bigfish/sdk/fetch"
  388. },
  389. "referrer": "https://globaltech-code.alipay.com/qicard/standard-wallet-ios/pull_requests/551",
  390. "referrerPolicy": "strict-origin-when-cross-origin",
  391. "body": null,
  392. "method": "GET",
  393. "mode": "cors",
  394. "credentials": "include"
  395. });
  396. const pullReqsJson = await pullReqs.json()
  397. const noteId = pullReqsJson.id
  398. if (noteId == undefined) {
  399. console.log("noteId", pullReqsJson.json())
  400. return;
  401. }
  402. await fetch("https://globaltech-code.alipay.com/webapi/projects/"+project+"/pull_requests/"+noteId+"/comments?type=Comment&note=%23codeReviewResult%23success&_output_charset=utf-8&_input_charset=utf-8&ctoken=ElGV8J1MmfmUFbun", {
  403. "headers": {
  404. "accept": "*/*",
  405. "accept-language": "zh-CN,zh;q=0.9",
  406. "antcode-request-type": "ANTCODE_WEB_REQUEST",
  407. "linkc-request-type": "LINKC_WEB_REQUEST",
  408. "priority": "u=1, i",
  409. "sec-ch-ua": "\"Not/A)Brand\";v=\"8\", \"Chromium\";v=\"126\"",
  410. "sec-ch-ua-mobile": "?0",
  411. "sec-ch-ua-platform": "\"macOS\"",
  412. "sec-fetch-dest": "empty",
  413. "sec-fetch-mode": "cors",
  414. "sec-fetch-site": "same-origin",
  415. "x-request-lib": "@alipay/bigfish/sdk/fetch"
  416. },
  417. "referrer": "https://globaltech-code.alipay.com/qicard/",
  418. "referrerPolicy": "strict-origin-when-cross-origin",
  419. "body": null,
  420. "method": "POST",
  421. "mode": "cors",
  422. "credentials": "include"
  423. });
  424. $.toast({
  425. heading: 'Success',
  426. text: '请求成功',
  427. showHideTransition: 'slide',
  428. icon: 'success'
  429. })
  430. } catch(e) {
  431. $.toast({
  432. heading: 'Error',
  433. text: e,
  434. showHideTransition: 'fade',
  435. icon: 'error'
  436. })
  437. }
  438. }
  439.  
  440. // onload
  441. const isFunction = (variable) => {
  442. return typeof variable === "function";
  443. };
  444. const bakOnload = window.onload;
  445. window.onload = async () => {
  446. const css = GM_getResourceText("customCSS");
  447. GM_addStyle(css);
  448. if (isFunction(bakOnload)) {
  449. bakOnload();
  450. }
  451. };
  452.  
  453. console.log('执行了');
  454.  
  455. var btnLeft = screen.width / 8;
  456. var marginLeft = 30;
  457. btnLeft += marginLeft;
  458. btnLeft = addButton("批量 MR", btnLeft, 0, startLoad);
  459. btnLeft = addButton("通过Review(只有 Xone 合并才能用)", btnLeft, 0, review);
  460. // addButton('批量 MR', btnLeft, 40, copyImagesJSON2);
  461. })();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址