From 8d6e8a2844e18c8b2f12b275c95aa4d75ca2ced3 Mon Sep 17 00:00:00 2001 From: zhaoyingbo Date: Thu, 8 Aug 2024 12:42:03 +0000 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=94=B9=E7=94=A8gitbeaker=E6=93=8D?= =?UTF-8?q?=E4=BD=9Cgitlab?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .vscode/settings.json | 2 + bun.lockb | Bin 105738 -> 113915 bytes controllers/managePipeLine/index.ts | 29 +-- controllers/managePipelineEvent/index.ts | 21 +-- controllers/manageProject/index.ts | 6 +- controllers/manageUser/index.ts | 6 +- package.json | 1 + schedule/monitorJob.ts | 13 +- script/badge/cloudml.ts | 50 +++--- script/badge/miai.ts | 113 ------------ service/gitlab/badge.ts | 60 ------- service/gitlab/commit.ts | 26 --- service/gitlab/index.ts | 15 +- service/gitlab/pipeline.ts | 66 ------- service/gitlab/project.ts | 26 --- service/gitlab/tools.ts | 34 ---- service/index.ts | 2 +- types/gitlab.ts | 215 ----------------------- 18 files changed, 82 insertions(+), 603 deletions(-) delete mode 100644 script/badge/miai.ts delete mode 100644 service/gitlab/badge.ts delete mode 100644 service/gitlab/commit.ts delete mode 100644 service/gitlab/pipeline.ts delete mode 100644 service/gitlab/project.ts delete mode 100644 service/gitlab/tools.ts diff --git a/.vscode/settings.json b/.vscode/settings.json index eef5140..113f533 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -11,10 +11,12 @@ "devcontainers", "eamodio", "esbenp", + "gitbeaker", "Gruntfuggly", "micr", "mioffice", "oxlint", + "sonarqube", "tseslint", "wlpbbgiky", "wujiali", diff --git a/bun.lockb b/bun.lockb index 2ea389c0e86726047df63730c4f6d2b7d03d2732..b9e1f44d2fe5d1baa03788b5299ba07dab086269 100755 GIT binary patch delta 24022 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

w8*99BuMx^urgO7Bozb__XoY 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%0D=1jry$OF5Fh*il1{R9+X-=KdH! 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 delta 19383 zcmeI4d019e_xI1a1>;7+IYB{%azF(^ML^^h%?XYJj%bd6s2C~%mY50J9 ztA2TAfFCH#8i2gvHk!{u8Vm#(9* z79_VQKW}oermgkYw5IU+$VSLXj`T;?fe%84B2$rdk*ysW;>a{VP4klfdVr?YKsJMj zQ6b1+cr#^q-f7w3-E zK6muSWfc|QN_k=K)S|p`C0Zn|iJ|9_;$>%C7ehXUNW1Sk^%`SM9j&!iHnAwWBx_Q> zmQ^^uAgiz_w+;nTF^yUxJ0T@}$7-l`o<^lxX+#{%%9&C)nSQe-TIOj>h++fsXCoyr zo9IXSom!X|JrQRMrcN%&nKCx_4JUssQUdZQQo1R3WCWG1fFY%yd&w8S@33WQSzb}} z`1~o^+CZWviUp3s?Gy5HCSXurQSP){8bw6otr!;RNT%JCoUG#9Kc}Da`ZX@~hS_dT z$SR6v=*C}eXxBPIzF5^H+;06$6-{dbKZKO|wSdWYBk~;OjgeE~7*MtcF5$u=%c{T5 zx1!uhx8)XUnuI93g!vU4VRzUZDeWgU^SK$;_EVqcGx6}ys7CH~grC7l~(^Mbsw#f7=K zT7F(pabYQz&u(cO@Yey~L%xJ^aVy)9xkzcy9iqZR%n}(i5?3dQIOo_G)`_|!K zz$IddF?RhalXHvnCgp0A*o8`SqQ^}>jiPjP3k}JbXCoydLy(gH*M>*niIg*sbFwfX zGS2qA9#ZOiky6i{(U)Rv?iz3&E(U)UO8}*zt1S|P21co^Rbxsc<86b-Bc;7iq^P_3 z+4L<-c`#D?WyGzySUW+}FuiOuQtFMJQXE}SIHiD?dX)tNc{`WtSX}| zYekl@)iC37w7wl}h0aJ>s_l@{pgS^dq}`FpEy~Ht&l;PXlb<&=kH*}QEs0CCmg@IO z_R^h{H<{QM6}L=LmDe>Yt(RiYpmBMV$3{;r(DwUmfBvTx{IS#AfmAzAn~@TaN02hb z7diRCUF~?!MvA|=NGZ=PESyppom)EX_M7Ym2004B-E2GakdY|*A!WeEAY}k@CS>K` zqG_6YllgBq5r5j3`V;etB|O?x3~VTC(A~>}df6TS+S8s>p}%KrZRU^ z|2ECmb2oLl*+jFWk3>(_>R~5B_Zhb5zau3=XOXg2k0EQ9k_hc%D|nI8;lyxmH%(&z=!GkupOjA|+D8Gi*XL zr@sBvXWl^-9|x`p(BD>b>vYy@sC|59C~w`)-i5lR5wtRos#Q0^b4ge8>iWF>J%pZ2 zO)~Xz<*nCQKcv$5)YV)*JE(p2I(zb~sPu+DPdz_1uc6QT7We-`>gcNc`UG!kRZU~n z*v#`#Rh1s*^LVaP^AH)=smd^)ciDBCh7)Ce>PX`R?^#$EtIKliXc?g9h5Nj7I2y1b z%BrYZ*C%+61gOA9K5r}o+{xCYqkI^XhK_25BzV?)RV6B)klC6{oI)j-c%@scyg`C@ zD2!Oy-Flu1RF#c=-V0<(n|@-vr+qb*-o)pfQjL2bnN_UJ=c=j7CO*%n)l^`F&l_J| z)7nvnx8Vt%3DwoS2%l#~bybP@qq+)=^m+OQsdU8RAT=-2=RL~)At9}zj?_u;whgw8 zz_Gds-i5FZR_~Pg?}jC+1=lBge#+6Lg_$1pok(s~0XSbNI+ z)sZF%-o7yQp|W5r&iBCB<;nuZ4$rQdYF<;Hr%5eUi5OT*1vc|}*RzC2pyIJqs@GQY zn)y5>^BjvWF(FzB}1!MJ9MBIjpKR$15C$ z`AnMc>Z|nDKJQR=1@;)4?q5H_e-$iNEohePJxofh)Fe2b>Y*w<+UMyNs^&%eyt6}X ze=J`;o5^H7edA;@h**`_!1l`?{M#H>RrT+X7yuE2ZN+b39W3)@CPcD@*ijTV1}0@5 zYe<$fRDrQR?*TF;GJe)tsUK#K+I33&9S)PG?Oqj38nXt-{}imNOjG}sZ1tVgf(FU{ z<46rreHteFM>ir2R%!#OQC6x3$GAaODu+}LE47wXs#;Jt+4EClmEO+hjca1h0qr?hu4#hzRahs>+Ww&lUQeW5 zX3x}4u=chl6KFb2H1U~!XzI4R^(oVNvxPR zVTp2flxlY15^uCaY)vr#i7-1zJ4t0&VW`>E35a(HDXD2KBG0O(sxr~%`J|}|O!E0} z<>1##1tlf>dzxdUmFht%!%8h7)!RyaLaMKoifzHxXQif->S3jJlIkicPu(b$p6v4! zM5%enKJTh1cdkhIzJbYH;T90fJZfn>9-#U&E#||-Mz0l=BQQIBGRJ~i*^H@qV`2bA zmb*2Z{MW!RH8RPnBkx~oC3A(Yt@ zf1Oiihx|uaH_B{wQ;gk16(w_F7ED~T$88f##?78X-@(LU+m<$M?47}0;kUL?fn9vw zXUP;5yXkLWVxVnA3oI9t?6R3KiIa8v@@|I7LJP1qk9dx-eXTNC-gm*e!t7S|z@!Iz zU-YNal|`5WlQMhjx)Ua$qd#K54JNkOJ^TW*dzT*K+SyLqfgBIJ(&kE7GWDukt-KGT zs?&RQ=DRSjbw2R5SC!p;-l=5fSru3@o>T2rdJmr`I$q5~6veAb#Kw3P*wg1Z6R*+{ z5gpV##KaD&vZv4c6wx0}^*XAY;pmj0X)|C<5*Fib*cJbRFjDNaBhj6tEI-@#5}3VG z#J>udOexx=mAagM_!ZcR=Up)Ik21{FI;!+^pLaBM)2+tv!GA4`jfT1T9Vt18)U$Sj zSnAn>Efc>0Cc|ql=+nf5?;f=S5iVVDdPGp!xOv!;`(?9F|U%oH-~ z$dva_BAKXyB9gtgl9C&fJ%2XA#9y{%I{zBR#9)+Un+jvt?M`Im`@(u!?MW;ig2@E8 zH?8Bat}x9S-3A1S3@0)}9cFL$OJL%LJxAVxNh`K3enbHSuozoB$5Pe244=0ify%H{ zxY>DgVc9Ty62A$Pj_ge$1Pkz)GOGJ4Sh_k`KiPYdl+>~J<<2+R2C(+of@Z^{1#X$q z37(xdsmcL9|3<9puIk``WdHf3#!1Ti11V{oYMh0lyW0V`?DmZBt^x;f*d$XdMTJnF zg;57<$}^}y#O=|O;N`-kSM~~eUEM>a5B7OKC)4iX2pfL{p_U=#9*@eno+@yN&ufx7 zkjy$(n8P^($h@&);Xe|_#@!;>`y?q@_V$83FZmV|!;{lAjqOK$G08x26#iu^r99 zFhcLJr7&3!wjC{LkY>gHCJFw+w4jB?nDl)UI>uM?GgxI>SC8Zqit@@0$)n0F>e~lrvE|Jm!Lt-fqaO)B& z`9#plA7JHb+SSra-f$;hq;xpK;Uc9zBWqnErF=BInRSi6h7`}UfhguUXR zC9)cL5Qv#eK>%0uM?OZUNHKc1P|)%5_B&G4X7_mHq!F18L)3r=4p_iNFV- z3OEJC@Q;rgqLzB)rHeh)%NA+`(G<-?YxR))tZsNzUJM?s`itm@=n z=WwsX1CerFEk(b&Qyzr84laKt6WP$wzapIxlMETKMvlU@q?AWEdN(?HB4q%h94=Dy zT08t&Qi`G-y;y6-k`e1v5GlzxN49ljJETm>6e;|Rlp9YM^2LxINa5*@-qljF3@2Zt zM5?q838~QEDY%vtj|MsAA|*N4;UXnD#F3d!{j~t#T1t5@EB9KG z{zc*cK5E!C{=c6z+#}2=$3l@}&}fHWON!^&j$V$VC-R?@hD2`GKPQcUP8!x4y81vN z%f#jXoHXp+@}HB&)h7&@A;M)3`RAnZzkkvQlED6X(x|vt@L3gAZ-${-Obt?#W*B;q z+AnQG~@ zAaxQ}UqzK=s$L~QYC)NyhpH2>3$T<~hTc%kot3H9Ob=4u!opS3>`XQEjv)2uY(sCX z&cXs_1gSoE8G3|Tc2}m_47&uoL8aZDsV3YRq@KIm(3`4@u#lNSYUDkJ-dwG{CsXZ( z1>I}tQEJ$|nQB^Tka`u?N_p?gR4vNz?>k1#^*iiBA@rF{!eA<_o=mf z&Qbc)nfhEcjL&&$1E2GicMX0$hF@z8eSz8nI}Qt9Yv>QCytVlCIDWy(Rp>hWT8&@p z3|*;xursjeXAJ!zRq_meJ%L{^Q$;lv@LjMsWYe^On9g{)(|HW>QTYV8Kb z3l{XEp|4fLUSzzUVZ30^C~pORJ&RuzhW?z|0y_>1-)QJBsJxB%^&Eb|HmJ~-@auW} zddbi$)IQi5SoF(={*o$r8NXh@FW4p(wTbas&v;f!hv!QQOb2l?y8yGLx zt14*=X3k#lPK#{*gKh3)qf-dkp=wTDAxOV3%N@sKo9hlW=gp6@g@v2uu- zvkMoYKWM7K{vj%HH$Lt+Jm)o42|WXiK45r$($w?=L)6kecnSSQQ!Nh;QN7;4&4Y&L zqNd)5UVx^&Wq5wm)V#Nbs5NimDD;x1IvyILhVI4FLx$%MO??Fo*oUi!4gP~@*JW=ZT&pP^_isGLsX?ll8 zWz=aQomU+Ha)KUQl4SS6zy8HcEUKvWZB?srPs@~wo4oI@_(IwKI@fdno=hi z90zi_&o66`e&5RB10{(-P4JqN=RUq1fhoeH|w+oU}wzjF||!J~eGrGAA#fNR0dIq&;2p3F>;`+l8{kc_ z7wiL-AQZ^7kZB-uP=>O;44I6xJc!K&Fd0k%6M*awL&43UH|PU;fiB=(Q2HJp$G~xL0=y5_gAHIi*a=<( zi@_W)7c2lFK#VU2Q-M6H&I1#{FmN*%4n_cZpx+J11AqCeLQBvJ{4V1!vpO8e-$P`N z7*E6ZfV;s=&>i#uw}JvN0t^TJKnCaw(m*;m2R;Fxf)~LuAdkFn2a~}RPylWPg&<3| z%p4N(1iuI933`Dv&<4l`buW#K0{wvjJ_fSxE5MWBX|M*Y1?zx3OP>Lz19@;DOJ5!& zY^3aE(3f-u_=EI*`qySb5`gS{gW;WlY_GDL{zh7s^GM`(;4||8jmU$#jZ&NBZj{~_tR676( z`e+ae*eSKs_K`$&8TsE%RJv%uS#x=nQ-y1tft^APPi+a1aLSO33Pv zs10g?8Xy=1fto-JlC47wkq)m1vIgpd2A~m$0F6Nt&=lMNZUikrGteA}Q?4^@NymX` z&`O3(8g2<%gEk-r#DaLx9*Cuq?g+$_M34ZIK^KtfK%&we$aIyp(G&CnvPNXR3`a^E0uyNU@{O7@_{tyD$6iPTBg_}AmN_@r1NQDI=B@S013H_ZwZjHLQo8f zz*KM>xE)A8cL3TgwJZ`Nq*L+0wM;sd`5<1ndGkom1#`fC;9hVKxEtIBD!_|C+It#2 z1s(um$U?9H+z(cR$H8OL<5ChPSOk^;1tGL% z2#BuS`{Wey5$U&q)RBn1366k6;4M(PpN~qg59|efz(H^TNSW}%KqjEekCS#Ae24T= za16W$-UTPXhu{P7J~#qi~JIN0X_$3z&GG4a1MOy@UM~o0^fu0zz^U&_)*4RED~>i1HXcc-~#v^Nd9Gz z1az#{z#j-XUdSQN4~UN3N9AZChd1F8YLV69a)*&)i`>@aUMu->M3DnvEjj1NDbNj_ zoCf6-D5t@lP9u{YDPy}ck^-(D(>8TY)SuPOfR1{5eVdumQEwUOv5NTEYu?&X57oPy z^AQaXQ>7YP#gr!!haVXo@Tx~2)jpg2c+onIUr zo%p#&Pl$<25alyfHu>?|j_yhGGc&sDA?Bb|y@6+dpIMNqhj>Q#nfb%?kg#!n_OFR5yRk8y&SLG(3jECNXm)Vlfn0I#wwu;m3VsTW4l(GkoT)2@wy6=2-MGBsE30l? zOncU&pIN;Nt-J5JPQI9Qq0htt4J}tXNZqx5W-1yT+&5-J_m+E4-n0H0G}^_)#kAuF zN$WLeyhh_G(At41!5%bX?ZCD6H*0pK^;CcBj#swuu@?tly7SOr zH0WL0a9@W$J?Des4Sg#Etdh7miYED+qol6;B6Y_&V^D)xA3ci(#W8XCO{-0@Y)FG% zM;iZ7vF}O=mOa~*S@C66>n2)O6kvYbRd4GKpXc=eGv+2nF2rk|>y2#YHM4J`{9K^9 zlSDC^XTpDE_plJyo`qD)9PmLZusuLC4Jv@Q7ihae(`C`hPW6O zP3Iu9tegI@r%tdL*8Qr!8wZ;cg?Fl9u3##Kxv$oJb0PcW=sE%Itq54LIab4b8_h8H zjp?O}Q+L0!d1we4@iFaWA6(X?A=3e;@RY9PL>gwUCWO5i8;+K`-ac)QX`h} zCT2@&nUD9N&5*j*Z_Z^|uSe|Zxis`At5=-lP*Kn;Is-c7xiMLRPUuX2#XJ~d)pcO<=UPVV}C#` zj+GJ5mKS1n?S(z=OViV~{FLC|F-_(!%QU6~o1WcJnEM)a;*#ja5xZ(L+B3x`EOsyL+4?y8FhQ4$Sr zn7KF&yWH2Tvv0jICAC_OM8_^7*(BWjL^RyjlXnk`{Uz}JmmfgGSzCL;&DeB$`Om9w zQx)^D4~qx+n=?hzefPP1)2>~4k#Tdb>_F$j&AtYjL5<7<=?ui7D*Sn(t!HW@bCpcs ze=iR4ENEnY+)r<7@~nA+%=$*6b7W84Y#zxrt*jt~yTCjBCPaj#DRz%(J512o8@rGC4 z-)EOtd*A2mj@0$s;b$K2gHsg|X7#?vixFmOU)prvEKfPVb3!_R9GV~2{*<52+!YJ8=FQBQ44iP^LXY?(a$rXO!#l2MxbLaA zC@o1)pR_o0rDR+)a|U(8+&9}Fe)5MFm#aMPy`r(WnYkVf&r{9J$_zp_Fv`4~!TKB# zW%llGhq6p$Zj`wZ*};8d{F~wy)05^m?Qiwg9<(T5rIwi6I+s10Qv^2v8 z(8sivW`_ZUbhe{8_~43SwE*kInTycyM8=ux z2J7R(+_&{t?_XN7a^l;0Y^aGb@iB3+T4cQ0dI)WeXM^T6Ugn+B>5Z@YKfDc%_?WgG zIF+C==D*Tl2U{`}m)uwWCv7oKpDBLtLB}QTVeXdze7=9i;z3y(KBPn@9^vpyG=Cq$ zWd2v8nV!iYIGuKI-_7p!V~v-d*|%dRHR6)EA;xO%>*PPbJ?4gmbG7DnNn37}A19dy zGI7a$!~dh7)-?78hir8<;xx<9hh^?A$KWvcs{~TUA09j7zKJ)AS?oDX+Rh!#!=mAS z`M_r<`@fm@ZTKkBu(u`WKkA^gy-yp?`P4mBUSqY% zTp&EGwpG&lHQTU8-2K9e@W|6Q?DR%%p>=02)=M$ZQP&=ww)_#q>~ypKa0mCRNQU&^ z-#4q~#y6>uU@trOs}6e3sPkC%sMB)JahA${pILqQwePkVA%=EIHN!^J*~nCL;cx;s zHPt?qX$yYd^>o+Yj?)(7Cl=e2#T=ExnPCxHaw6VQy7c$cU2YzYmb1+~l4{l*f#aLe z;22Z3>d4lDBf*mwq9J=bXNLcLRz8qwjvB!tbibmayv@xEn!S{gR8wbHv#v#{=Cf#c z{JWYT(~F$neia_v)r=X59Msj!Muz2fwVvjbCC_{O!?qC@U!(W7)+E$scQx0K#83BI z8-AX=WOm)ar*1$)eji}l^Xq2z9!1;1-OS6<)|hVgmT+dxyc+MlS5=Nt&RxpU40FHf z;fsvvRr(BGwh0YJrhQC;OoKAo3Uj~Xq5H0!oP*8J7os7jMB<<7Z*CmL=6{W|3@265 zXcBJ!=5l1{y2EKduH-i#ndm(Z=k`0A6ov-VNw&-T4C|>-*@}f1ODbb`{(Pmxwjs>=dI@IG zmW^NL*Vz5*y;l^@8s_&j9_D@_MM~i4kH2`|Urs(&{Tao4P2sja{LTKbYUm@iKB zkM=c#v+>yda*OY3o-p5;R<<2QXEC~8Z&9$M#+mB*cdw&_ag>90aX)iJHk;|re&)Jt zel_Z!VGsH64D%FihW+Pl*cq>uEJ}CmWPt{z%0p(ZvUGEHj^5SWo1@1zINR91W!#+@ he?XrWe0ja2RJh!%Jyt)x$&;%e@N8-^SwGtM{{W+puJix^ diff --git a/controllers/managePipeLine/index.ts b/controllers/managePipeLine/index.ts index 6b701bd..cfe831d 100644 --- a/controllers/managePipeLine/index.ts +++ b/controllers/managePipeLine/index.ts @@ -1,14 +1,15 @@ +import { ExpandedPipelineSchema, PipelineSchema } from "@gitbeaker/rest" import moment from "moment" +import pLimit from "p-limit" import db from "../../db" import service from "../../service" import { DB } from "../../types/db" -import { Gitlab } from "../../types/gitlab" /** * 获取全部的pipeline列表 * @param {DB.Project} project - 项目对象 - * @returns {Promise<(Gitlab.PipelineDetail & { created_at: string })[]>} - 返回包含详细信息的pipeline列表 + * @returns {Promise<(ExpandedPipelineSchema & { created_at: string })[]>} - 返回包含详细信息的pipeline列表 */ const getFullPipelineList = async (project: DB.Project) => { // 先获取最新的pipelineID @@ -18,14 +19,15 @@ const getFullPipelineList = async (project: DB.Project) => { latestOne?.created_at || "2024-01-01T00:00:00.000+08:00" ) // 获取pipeline列表并保存 - const fullPipelineList: Gitlab.Pipeline[] = [] + const fullPipelineList: PipelineSchema[] = [] let page = 1 let hasBeforeLatestTime = false while (!hasBeforeLatestTime) { - const pipelines = await service.gitlab.pipeline.getList( - project.project_id, - page++ - ) + const pipelines = await service.gitlab.Pipelines.all(project.project_id, { + page: page++, + perPage: 100, + scope: "finished", + }).catch(() => []) // 如果当前页没有数据,则直接跳出 if (pipelines.length === 0) break pipelines.forEach((pipeline) => { @@ -38,25 +40,30 @@ const getFullPipelineList = async (project: DB.Project) => { } }) } + const limit = pLimit(10) const fullPipelineDetailList = await Promise.all( fullPipelineList.map(({ project_id, id, created_at }) => - service.gitlab.pipeline.getDetail(project_id, id, created_at) + limit(() => + service.gitlab.Pipelines.show(project_id, id) + .catch(() => null) + .then((res) => (res ? { ...res, created_at } : null)) + ) ) ) - return fullPipelineDetailList.filter((v) => v) as (Gitlab.PipelineDetail & { + return fullPipelineDetailList.filter((v) => v) as (ExpandedPipelineSchema & { created_at: string })[] } /** * 插入全部的pipeline列表到数据库 - * @param {(Gitlab.PipelineDetail & { created_at: string })[][]} fullPipelineList - 包含详细信息的pipeline列表 + * @param {(ExpandedPipelineSchema & { created_at: string })[][]} fullPipelineList - 包含详细信息的pipeline列表 * @param {Record} fullUserMap - 用户映射表 * @param {Record} fullProjectMap - 项目映射表 * @returns {Promise} */ const insertFullPipelineList = async ( - fullPipelineList: (Gitlab.PipelineDetail & { created_at: string })[][], + fullPipelineList: (ExpandedPipelineSchema & { created_at: string })[][], fullUserMap: Record, fullProjectMap: Record ) => { diff --git a/controllers/managePipelineEvent/index.ts b/controllers/managePipelineEvent/index.ts index 9d8e1f1..0aa1387 100644 --- a/controllers/managePipelineEvent/index.ts +++ b/controllers/managePipelineEvent/index.ts @@ -1,3 +1,5 @@ +import type { MergeRequestSchema } from "@gitbeaker/rest" + import db from "../../db" import service from "../../service" import netTool from "../../service/netTool" @@ -54,10 +56,9 @@ const getNextAction = async ( } // 在流水线为`running`时,且该stage全部的job有非结束状态时即`created`、`pending`、`running`、`manual`、`scheduled`时,添加监控 if (pipeline.object_attributes.status === "running") { - const jobs = await service.gitlab.pipeline.getJobs( - pipeline.project.id, - pipeline.object_attributes.id - ) + const jobs = await service.gitlab.Jobs.all(pipeline.project.id, { + pipelineId: pipeline.object_attributes.id, + }).catch(() => []) if ( jobs.some( (job) => @@ -75,16 +76,16 @@ const getNextAction = async ( /** * 获取合并请求 * @param {Gitlab.PipelineEvent} pipeline - GitLab 流水线事件对象 - * @returns {Promise} - 返回合并请求对象或 null + * @returns {Promise} - 返回合并请求对象或 null */ const getMergeRequest = async ( pipeline: Gitlab.PipelineEvent -): Promise => { +): Promise => { if (!checkIsMergeCommit(pipeline)) return null - const res = await service.gitlab.commit.getMr( + const res = await service.gitlab.Commits.allMergeRequests( pipeline.project.id, pipeline.object_attributes.sha - ) + ).catch(() => []) if (res.length === 0) return null return res.find((mr) => mr.merge_commit_sha === pipeline.commit.id) || null } @@ -92,12 +93,12 @@ const getMergeRequest = async ( /** * 获取用户信息 * @param {Gitlab.PipelineEvent} pipeline - GitLab 流水线事件对象 - * @param {Gitlab.MergeRequest | null} mergeRequest - 合并请求对象或 null + * @param {MergeRequestSchema | null} mergeRequest - 合并请求对象或 null * @returns {{ participant: string, receiver: string[] }} - 返回包含参与者和接收者信息的对象 */ const getUserInfo = ( pipeline: Gitlab.PipelineEvent, - mergeRequest: Gitlab.MergeRequest | null + mergeRequest: MergeRequestSchema | null ): { participant: string; receiver: string[] } => { let participant = pipeline.user.name const receiver = [pipeline.user.username] diff --git a/controllers/manageProject/index.ts b/controllers/manageProject/index.ts index 7ece550..e6e5784 100644 --- a/controllers/manageProject/index.ts +++ b/controllers/manageProject/index.ts @@ -8,13 +8,15 @@ import { DB } from "../../types/db" * @returns {Promise} - 返回填充后的项目对象 */ const fillProj = async (project: DB.Project): Promise => { - const projDetail = await service.gitlab.project.getDetail(project.project_id) + const projDetail = await service.gitlab.Projects.show( + project.project_id + ).catch(() => null) if (!projDetail) { return project } const useFulParams: Partial = { ...project, - avatar_url: projDetail.avatar_url, + avatar_url: projDetail.avatar_url || "", description: projDetail.description, name: projDetail.name, path_with_namespace: projDetail.path_with_namespace, diff --git a/controllers/manageUser/index.ts b/controllers/manageUser/index.ts index 3406ccc..57f70ce 100644 --- a/controllers/manageUser/index.ts +++ b/controllers/manageUser/index.ts @@ -1,13 +1,15 @@ +import { ExpandedPipelineSchema } from "@gitbeaker/rest" + import db from "../../db" import { Gitlab } from "../../types/gitlab" /** * 获取完整的用户映射表 - * @param {Gitlab.PipelineDetail[][]} fullPipelineList - 完整的pipeline列表 + * @param {ExpandedPipelineSchema[][]} fullPipelineList - 完整的pipeline列表 * @returns {Promise>} - 返回用户映射表 */ const getFullUserMap = async ( - fullPipelineList: Gitlab.PipelineDetail[][] + fullPipelineList: ExpandedPipelineSchema[][] ): Promise> => { const userList: Gitlab.User[] = [] fullPipelineList.forEach((fullPipeline) => { diff --git a/package.json b/package.json index b727c31..2f442d8 100644 --- a/package.json +++ b/package.json @@ -35,6 +35,7 @@ "typescript": "^5.0.0" }, "dependencies": { + "@gitbeaker/rest": "^40.1.2", "lodash": "^4.17.21", "moment": "^2.30.1", "node-schedule": "^2.1.1", diff --git a/schedule/monitorJob.ts b/schedule/monitorJob.ts index 880dfef..e749c4e 100644 --- a/schedule/monitorJob.ts +++ b/schedule/monitorJob.ts @@ -15,10 +15,9 @@ const doMonitor = async (monitor: DB.Monitor): Promise => { const { project_id, pipeline_id, api_key, stage, receiver, variable } = monitor // 获取Job列表 - const jobList = await service.gitlab.pipeline.getJobs( - Number(project_id), - Number(pipeline_id) - ) + const jobList = await service.gitlab.Jobs.all(project_id, { + pipelineId: Number(pipeline_id), + }).catch(() => []) // 是否所有Stage关联的Job都成功了 const isAllSuccess = jobList.every( (job) => job.stage === stage && job.status === "success" @@ -28,10 +27,10 @@ const doMonitor = async (monitor: DB.Monitor): Promise => { // 先删除监控 await db.monitor.del(monitor.id) // 获取最新的执行时长 - const pipelineDetail = await service.gitlab.pipeline.getDetail( - Number(project_id), + const pipelineDetail = await service.gitlab.Pipelines.show( + project_id, Number(pipeline_id) - ) + ).catch(() => null) if (pipelineDetail) { variable["duration"] = sec2minStr(pipelineDetail.duration) } diff --git a/script/badge/cloudml.ts b/script/badge/cloudml.ts index 78ea223..6a59374 100644 --- a/script/badge/cloudml.ts +++ b/script/badge/cloudml.ts @@ -1,6 +1,7 @@ +import { ProjectSchema } from "@gitbeaker/rest" +import pLimit from "p-limit" + import service from "../../service" -import { BadgeSetParams } from "../../service/gitlab/badge" -import { Gitlab } from "../../types/gitlab" const projectList = [ // "cloud-ml/cloudml-maas", @@ -24,16 +25,23 @@ const projectList = [ "cloud-ml/lark_auth", ] +interface BadgeSetParams { + groupId: number + linkUrl: string + imageUrl: string + name: string +} + const getNewProjectBadge = async ( - projectDetail: Gitlab.ProjDetail + projectDetail: ProjectSchema ): Promise => { // 项目路径 cloud-ml/cloudml-dev const projectPath = projectDetail.path_with_namespace // 根据项目路径获取sonarqubeId 类似于 cloud-ml/cloudml-dev -> cloud-ml:cloudml-dev const sonarqubeId = projectPath.replace("/", ":") // 获取项目的badges - const badges: Gitlab.Badge[] = await service.gitlab.badge.get( - projectDetail.id + const badges = await service.gitlab.ProjectBadges.all(projectDetail.id).catch( + () => [] ) // 对badges进行补全,可能只有 name: "sonarqube_coverage" 的情况,把剩下的补全 const badgeNames = badges.map((badge) => badge.name) @@ -47,20 +55,18 @@ const getNewProjectBadge = async ( ] const diff = [...badgeNameList].filter((x) => !badgeNameSet.has(x)) const newBadges: BadgeSetParams[] = diff.map((name) => { - const link_url = encodeURI( + const linkUrl = encodeURI( `https://sonarqube.mioffice.cn/dashboard?id=${sonarqubeId}` ) const metric = name.replace("sonarqube_", "") - const image_url = + const imageUrl = name !== "sonarqube_quality_gate" ? `https://sonarqube.mioffice.cn/api/badges/measure?key=${sonarqubeId}&metric=${metric}` : `https://sonarqube.mioffice.cn/api/badges/gate?key=${sonarqubeId}` return { - id: projectDetail.id, - link_url, - image_url, - rendered_image_url: image_url, - rendered_link_url: link_url, + groupId: projectDetail.id, + linkUrl, + imageUrl, name, } }) @@ -68,21 +74,25 @@ const getNewProjectBadge = async ( } const addNewProjectBadge = async (badgeSetParamsList: BadgeSetParams[]) => { - const chunkSize = 5 // 每次并发请求的数量 - for (let i = 0; i < badgeSetParamsList.length; i += chunkSize) { - const chunk = badgeSetParamsList.slice(i, i + chunkSize) - const res = await Promise.all( - chunk.map((badgeSetParams) => service.gitlab.badge.add(badgeSetParams)) + const limit = pLimit(5) + await Promise.all( + badgeSetParamsList.map((b) => + limit(() => + service.gitlab.ProjectBadges.add(b.groupId, b.linkUrl, b.imageUrl, { + name: b.name, + }).catch(() => null) + ) ) - console.log(res) - } + ) } const main = async () => { const errorList: string[] = [] const badgeAddParamsList = await Promise.all( projectList.map(async (projectName) => { - const projectDetail = await service.gitlab.project.getDetail(projectName) + const projectDetail = await service.gitlab.Projects.show( + projectName + ).catch(() => null) if (!projectDetail) { errorList.push(projectName) return [] diff --git a/script/badge/miai.ts b/script/badge/miai.ts deleted file mode 100644 index 1098bc8..0000000 --- a/script/badge/miai.ts +++ /dev/null @@ -1,113 +0,0 @@ -import service from "../../service" -import { BadgeSetParams } from "../../service/gitlab/badge" -import { Gitlab } from "../../types/gitlab" - -const projectList = [ - "miai-fe/fe/ai-admin-fe", - "miai-fe/fe/ai-operation-fe", - "miai-fe/fe/ai-dripback-fe", - "miai-fe/fe/ai-open-admin-fe", - "miai-fe/fe/ai-model-deployment-fe", - "miai-fe/fe/ai-workbench", - "miai-fe/fe/ai-review-fe", - "miai-fe/fe/cms", - "miai-fe/fe/xiaoai-open-Platform", - "miai-fe/fe/ai-robot-fe", - "miai-fe/fe/ai-scene-review-fe", - "miai-fe/fe/houyi", - "miai-fe/fe/kms", - "miai-fe/fe/ai-productive-fe", - "miai-fe/fe/ai-sliding-label-fe", - "miai-fe/fe/ai-label-control-fe", - "miai-fe/fe/asr-fe", - "miai-fe/fe/feedback-platform-fe", - "miai-fe/fe/statisfaction-evaluation-platform-fe", - "miai-fe/fe/ai-quality-score-fe", - "miai-fe/fe/wakeup", - "miai-fe/fe/ai-badcase-label-fe", - "miai-fe/fe/func-manager", - "miai-fe/service/ado-server", - "miai-fe/fe/ado-fe", - "miai-fe/pwa/ai-rn-domain", - "miai-fe/pwa/ai-ak-fe", - "miai-fe/fe/ai-user-info-fe", - "miai-fe/fe-infra/xiaoai-jssdk", - "miai-fe/fe-infra/ai-ui", - "miai-fe/fe/ai-class-sheducle-fe", - "miai-fe/service/ai-schedule-service", - "miai-fe/fe/ai-schedule-devtool-v3", - "miai-fe/ai-scenes-fe", - "miai-fe/activity/om-music-tone", - "miai-fe/activity/ug-guide-test", - "miai-fe/activity/om-mood-blindbox", - "miai-fe/activity/om-love-poem", - "miai-fe/fe/ai-introduce", - "miai-fe/fe/ai-phonecall-guider-fe", - "miai-fe/activity/om-spring-couplets", - "miai-fe/activity/ug-play-assistant", - "miai-fe/fe/ai-iot-introduce-fe", - "miai-fe/fe/ai-rookie-play-fe", - "miai-fe/fe/ai-custom-tts-fe", - "miai-fe/fe-infra/split-rpk-sdk", - "miai-fe/fe/ai-full-animation-template-fe", - "miai-fe/fe/ai-schedule-manager-fe", - "miai-fe/fe/ai-voiceprint-fe", - "miai-fe/fe/ai-shortcut-fe", -] - -const getProjectId = async (projectName: string) => { - const res = await service.gitlab.project.getDetail(projectName) - return res?.id -} - -const getNewProjectBadge = async ( - projectId: number -): Promise => { - const badges: Gitlab.Badge[] = await service.gitlab.badge.get(projectId) - - const replacePath = (value: string) => - value.replace( - "https://sonarqube.mioffice.cn", - "http://scan.sonarqube.xiaomi.srv" - ) - - return badges.map((badge: Gitlab.Badge) => ({ - id: projectId, - badge_id: badge.id, - link_url: replacePath(badge.link_url), - image_url: badge.image_url, - rendered_image_url: badge.rendered_image_url, - rendered_link_url: replacePath(badge.rendered_link_url), - })) -} - -const setNewProjectBadge = async (badgeSetParamsList: BadgeSetParams[]) => { - const chunkSize = 5 // 每次并发请求的数量 - for (let i = 0; i < badgeSetParamsList.length; i += chunkSize) { - const chunk = badgeSetParamsList.slice(i, i + chunkSize) - const res = await Promise.all( - chunk.map((badgeSetParams) => service.gitlab.badge.set(badgeSetParams)) - ) - console.log(res) - } -} - -const main = async () => { - const errorList: string[] = [] - const badgeSetParamsList = await Promise.all( - projectList.map(async (projectName) => { - const projectId = await getProjectId(projectName) - if (!projectId) { - errorList.push(projectName) - return [] - } - return await getNewProjectBadge(projectId) - }) - ) - - await setNewProjectBadge(badgeSetParamsList.flat()) - - console.log("errorList", errorList) -} - -main() diff --git a/service/gitlab/badge.ts b/service/gitlab/badge.ts deleted file mode 100644 index 07e7423..0000000 --- a/service/gitlab/badge.ts +++ /dev/null @@ -1,60 +0,0 @@ -import { Gitlab } from "../../types/gitlab" -import netTool from "../netTool" -import { GITLAB_AUTH_HEADER, GITLAB_BASE_URL, gitlabReqWarp } from "./tools" - -/** - * 代表设置 GitLab 徽章的参数。 - */ -export type BadgeSetParams = Omit & { - badge_id?: number -} - -/** - * 为特定项目检索 GitLab 徽章。 - * @param {number} project_id - 项目的 ID。 - * @returns {Promise} 一个承诺,解析为 GitLab 徽章的数组。 - */ -const get = async (project_id: number): Promise => { - const URL = `${GITLAB_BASE_URL}/projects/${project_id}/badges` - return gitlabReqWarp( - () => netTool.get(URL, {}, GITLAB_AUTH_HEADER), - [] - ) -} - -/** - * 设置 GitLab 徽章。 - * @param {BadgeSetParams} badge - 徽章参数。 - * @returns {Promise} 一个承诺,解析为更新后的徽章。 - */ -const set = async (badge: BadgeSetParams): Promise => { - const URL = `${GITLAB_BASE_URL}/projects/${badge.id}/badges/${badge.badge_id}` - return gitlabReqWarp( - () => netTool.put(URL, badge, {}, GITLAB_AUTH_HEADER), - null - ) -} - -/** - * 添加 GitLab 徽章。 - * @param {BadgeSetParams} badge - 徽章参数。 - * @returns {Promise} 一个承诺,解析为添加的徽章。 - */ -const add = async (badge: BadgeSetParams): Promise => { - const URL = `${GITLAB_BASE_URL}/projects/${badge.id}/badges` - return gitlabReqWarp( - () => netTool.post(URL, badge, {}, GITLAB_AUTH_HEADER), - null - ) -} - -/** - * 代表一系列与徽章相关的函数。 - */ -const badge = { - get, - set, - add, -} - -export default badge diff --git a/service/gitlab/commit.ts b/service/gitlab/commit.ts deleted file mode 100644 index 4e14532..0000000 --- a/service/gitlab/commit.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { Gitlab } from "../../types/gitlab" -import netTool from "../netTool" -import { GITLAB_AUTH_HEADER, GITLAB_BASE_URL, gitlabReqWarp } from "./tools" - -/** - * 检索与特定提交关联的合并请求。 - * @param {number} project_id - 项目的ID。 - * @param {string} sha - 提交的SHA。 - * @returns {Promise} 一个解析为合并请求数组的promise。 - */ -const getMr = async ( - project_id: number, - sha: string -): Promise => { - const URL = `${GITLAB_BASE_URL}/projects/${project_id}/repository/commits/${sha}/merge_requests` - return gitlabReqWarp( - () => netTool.get(URL, {}, GITLAB_AUTH_HEADER), - [] - ) -} - -const commit = { - getMr, -} - -export default commit diff --git a/service/gitlab/index.ts b/service/gitlab/index.ts index c247995..6239caa 100644 --- a/service/gitlab/index.ts +++ b/service/gitlab/index.ts @@ -1,13 +1,8 @@ -import badge from "./badge" -import commit from "./commit" -import pipeline from "./pipeline" -import project from "./project" +import { Gitlab } from "@gitbeaker/rest" -const gitlab = { - project, - badge, - commit, - pipeline, -} +const gitlab = new Gitlab({ + token: "Zd1UASPcMwVox5tNS6ep", + host: "https://git.n.xiaomi.com", +}) export default gitlab diff --git a/service/gitlab/pipeline.ts b/service/gitlab/pipeline.ts deleted file mode 100644 index 273d6ae..0000000 --- a/service/gitlab/pipeline.ts +++ /dev/null @@ -1,66 +0,0 @@ -import { Gitlab } from "../../types/gitlab" -import netTool from "../netTool" -import { GITLAB_AUTH_HEADER, GITLAB_BASE_URL, gitlabReqWarp } from "./tools" - -/** - * 获取特定GitLab流水线的详细信息。 - * @param {number} project_id - 项目的ID。 - * @param {number} pipeline_id - 流水线的ID。 - * @param {string} created_at - 流水线的创建日期。 - */ -const getDetail = async ( - project_id: number, - pipeline_id: number, - created_at?: string -) => { - const URL = `${GITLAB_BASE_URL}/projects/${project_id}/pipelines/${pipeline_id}` - const res = await gitlabReqWarp( - () => netTool.get(URL, {}, GITLAB_AUTH_HEADER), - null - ) - if (res === null) return null - return { ...res, created_at } -} - -/** - * 获取特定项目的GitLab流水线列表。 - * @param {number} project_id - 项目的ID。 - * @param {number} [page=1] - 结果的页码(默认值:1)。 - * @returns {Promise} 一个解析为流水线数组的promise。 - */ -const getList = async ( - project_id: number, - page = 1 -): Promise => { - const URL = `${GITLAB_BASE_URL}/projects/${project_id}/pipelines` - const params = { scope: "finished", per_page: 100, page } - return gitlabReqWarp( - () => netTool.get(URL, params, GITLAB_AUTH_HEADER), - [] - ) -} - -/** - * 获取特定GitLab流水线的任务列表。 - * @param {number} project_id - 项目的ID。 - * @param {number} pipeline_id - 流水线的ID。 - * @returns {Promise} 一个解析为任务数组的promise。 - */ -const getJobs = async ( - project_id: number, - pipeline_id: number -): Promise => { - const URL = `${GITLAB_BASE_URL}/projects/${project_id}/pipelines/${pipeline_id}/jobs` - return gitlabReqWarp( - () => netTool.get(URL, {}, GITLAB_AUTH_HEADER), - [] - ) -} - -const pipeline = { - getDetail, - getList, - getJobs, -} - -export default pipeline diff --git a/service/gitlab/project.ts b/service/gitlab/project.ts deleted file mode 100644 index 7e61529..0000000 --- a/service/gitlab/project.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { Gitlab } from "../../types/gitlab" -import netTool from "../netTool" -import { GITLAB_AUTH_HEADER, GITLAB_BASE_URL, gitlabReqWarp } from "./tools" - -/** - * 获取 GitLab 项目的详细信息。 - * @param {number | string} project_id - 项目的 ID 或 URL-encoded 路径。 - * @returns {Promise} 一个解析为项目详细信息的 promise。 - */ -const getDetail = async ( - project_id: number | string -): Promise => { - if (typeof project_id === "string") - project_id = encodeURIComponent(project_id) - const URL = `${GITLAB_BASE_URL}/projects/${project_id}` - return gitlabReqWarp( - () => netTool.get(URL, {}, GITLAB_AUTH_HEADER), - null - ) -} - -const project = { - getDetail, -} - -export default project diff --git a/service/gitlab/tools.ts b/service/gitlab/tools.ts deleted file mode 100644 index 3424b95..0000000 --- a/service/gitlab/tools.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { Gitlab } from "../../types/gitlab" - -/** - * 包装一个 GitLab 请求函数,处理错误并返回默认值。 - * @template T - * @param {() => Promise} func - 要执行的请求函数。 - * @param {any} default_value - 请求失败时返回的默认值。 - * @returns {Promise} 一个解析为请求结果或默认值的 promise。 - */ -export const gitlabReqWarp = async ( - func: () => Promise, - default_value: any -): Promise => { - try { - let response = {} as T & Gitlab.Error - response = (await func()) as T & Gitlab.Error - if (response.message === "404 Project Not Found") return default_value - return response - } catch { - return default_value - } -} - -/** - * GitLab API 的基础 URL。 - * @type {string} - */ -export const GITLAB_BASE_URL = "https://git.n.xiaomi.com/api/v4" - -/** - * GitLab API 的认证头。 - * @type {object} - */ -export const GITLAB_AUTH_HEADER = { "PRIVATE-TOKEN": "Zd1UASPcMwVox5tNS6ep" } diff --git a/service/index.ts b/service/index.ts index 41c86b2..83ca18d 100644 --- a/service/index.ts +++ b/service/index.ts @@ -2,8 +2,8 @@ import gitlab from "./gitlab" import message from "./message" const service = { - gitlab, message, + gitlab, } export default service diff --git a/types/gitlab.ts b/types/gitlab.ts index 6535915..1873d20 100644 --- a/types/gitlab.ts +++ b/types/gitlab.ts @@ -1,11 +1,4 @@ export namespace Gitlab { - /* 错误 */ - export interface Error { - /** - * 错误消息 - */ - message: string - } /* 用户 */ export interface User { /** @@ -34,164 +27,6 @@ export namespace Gitlab { web_url: string } - /* 项目详情 */ - export interface ProjDetail { - /** - * 项目ID - */ - id: number - /** - * 项目描述 - */ - description: string - /** - * 项目名称 - */ - name: string - /** - * 带命名空间的项目路径 - */ - path_with_namespace: string - /** - * 项目网页URL - */ - web_url: string - /** - * 项目头像URL(可选) - */ - avatar_url?: any - /** - * 消息(可选) - */ - message?: string - } - - /* 管道详情 */ - export interface PipelineDetail { - /** - * 管道ID - */ - id: number - /** - * 项目ID - */ - project_id: number - /** - * 分支名 - */ - ref: string - /** - * 状态 - */ - status: string - /** - * 管道网页URL - */ - web_url: string - /** - * 用户信息 - */ - user: User - /** - * 开始时间 - */ - started_at: string - /** - * 完成时间 - */ - finished_at: string - /** - * 持续时间 - */ - duration: number - /** - * 排队持续时间 - */ - queued_duration: number - /** - * 消息(可选) - */ - message?: string - } - - /* 管道 */ - export interface Pipeline { - /** - * 管道ID - */ - id: number - /** - * 项目ID - */ - project_id: number - /** - * SHA值 - */ - sha: string - /** - * 分支名 - */ - ref: string - /** - * 状态 - */ - status: string - /** - * 来源 - */ - source: string - /** - * 创建时间 - */ - created_at: string - /** - * 更新时间 - */ - updated_at: string - /** - * 管道网页URL - */ - web_url: string - } - - /* 任务 */ - export interface Job { - status: string - stage: string - } - - /* 徽章 */ - export interface Badge { - /** - * 徽章ID - */ - id: number - /** - * 徽章名称 - */ - name: string - /** - * 链接URL - */ - link_url: string - /** - * 图片URL - */ - image_url: string - /** - * 渲染后的链接URL - */ - rendered_link_url: string - /** - * 渲染后的图片URL - */ - rendered_image_url: string - /** - * 类型(项目或组) - */ - kind: "project" | "group" - } - /* 管道事件 */ export interface PipelineEvent { /** @@ -297,54 +132,4 @@ export namespace Gitlab { finished_at: string | null }[] } - - /* 合并请求 */ - export interface MergeRequest { - /** - * 合并请求的标题 - */ - title: string - /** - * 目标分支 - */ - target_branch: string - /** - * 源分支 - */ - source_branch: string - /** - * 作者信息 - */ - author: { - /** - * 用户名 - */ - username: string - /** - * 用户姓名 - */ - name: string - } - /** - * 提交的SHA值 - */ - sha: string - /** - * 合并提交的SHA值 - */ - merge_commit_sha: string - /** - * 引用信息 - */ - references: { - /** - * 完整引用 - */ - full: string - } - /** - * 合并请求的web URL - */ - web_url: string - } }