From 0f6e6522e2e49a9b270ce1ec899be48c2406d58d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 29 Jun 2026 12:05:28 +0000 Subject: [PATCH 01/15] Initial plan From 0a3cf7538399b7e5a4e53211a7c93e7c4b50a9b6 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 29 Jun 2026 12:19:00 +0000 Subject: [PATCH 02/15] Plan PM-327 implementation --- .../gh_project_automation.cpython-312.pyc | Bin 0 -> 30765 bytes ...ate_jira_issue_from_gh_issue.cpython-312.pyc | Bin 0 -> 15010 bytes .../__pycache__/jira_sync_logic.cpython-312.pyc | Bin 0 -> 31909 bytes .../jira_sync_modules.cpython-312.pyc | Bin 0 -> 52455 bytes 4 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 __pycache__/gh_project_automation.cpython-312.pyc create mode 100644 scripts/__pycache__/create_jira_issue_from_gh_issue.cpython-312.pyc create mode 100644 scripts/__pycache__/jira_sync_logic.cpython-312.pyc create mode 100644 scripts/__pycache__/jira_sync_modules.cpython-312.pyc diff --git a/__pycache__/gh_project_automation.cpython-312.pyc b/__pycache__/gh_project_automation.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2a65a316d545c20453c3a394f0e82aacec258db9 GIT binary patch literal 30765 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 literal 0 HcmV?d00001 diff --git a/scripts/__pycache__/create_jira_issue_from_gh_issue.cpython-312.pyc b/scripts/__pycache__/create_jira_issue_from_gh_issue.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0e49721855f5a2789e91a3d34d7156bb1133739c GIT binary patch literal 15010 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 Ak^lez literal 0 HcmV?d00001 diff --git a/scripts/__pycache__/jira_sync_logic.cpython-312.pyc b/scripts/__pycache__/jira_sync_logic.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..fb3076186d846a8dace0a353e6cc9f6401162f65 GIT binary patch literal 31909 zcmeHwYj6}-mS$E}O7(u|{gx65C>7{|c-ep@5J-RoNU{)M)NYqc$^=SCRqCt~nA(zC z6XA)5SnpycIs$px4$C_a%VS5ZHo9Y%*qzvL?D{n`e-f+Q$l3bg-gRt5|JhX=W@oHl zd(O>A-6~~)kn#3zGzq$S>*jr)n|bfK-#zEte{j1U3|v=74v+o&pD@gS#~<3|Q$6?p zhlycsGiMl{8D@ABZyq-do5&VHWO|@w|!r;rt2fuyw*VY@4tT+b0~u zjtS?mbHX+3ns5)hO$^Ttd-%Lzuiz63`1}jz3Mfn{7D{*z+`aIJ=?dV_&YLgz_(F(R%5Ue3;9iyyUyECu5x)fDl|%eexL0JvFB6Ik z@-K&Yl@PxI?o}D_wfwcZc=$?)Qw?#e;9ipvw;Jk@9pA^-K)hOrUkmp-zV0<z{*YkdCzfb^lYJ{{6d;rpJ7Pj!)E;lla zSZ-zn%h*Y+JJWXv-~564^8@HxyiCkB^EGpzDRd439AjZI6pUSqj0VS}7sI11lh?Rr zZYVn0JT6=j#<{3CdP#`I#ZWvda-j&%9XZ*<@!{BHC=L%q?g9k&LKYlm(c*9%iALg~ za3sb}gd(AfLU24ZB8&@s@ZzN)K}(KvWw zfhGqpj7(irsy_-P3$H){@k;{Nd1R=kzc1L;b9$h2=*V#{9vT@Jnn(jCpn8n~sA}i< zICn`HpA^Jc69=hd@lYfVUTkGJ!iTSf`Ki!27b1mm;fcv{VFFqZB4u;q;VS|}qv$sg z<)_Al7*Mdq@jE1RU%)08K$S$uB1q_bS-2LH%R)S_&?Oj;D&gT+Y)X(TGvbo4ATIzp z$1&05)TrCO{(JN}N1TTou z3A+5Ei$XleMDEU!+Fxb~0Jkfprbns~ZnZB-Iu>QvZbD{+31!cC5hJ)b< z)FgUQ6k@T2eIzt`c`_=-TU%sbu=|B0C(m?scLh&&9_~JQTFxVNm-9s-J|#v*)i)A} z#aPt8`%U1v%_NyI`YFbMD{fZq45Pixr7&?y(VZKRlOT;opz1-BR$&#hL*M#b=CJl4AQLy-%C zP(dwcrAx&ENae@m#o){^UpsyGoK<(7RjKNxMQ5|bHs6PEMz&3g!FV`6F348!jYRot zvK>5;sfiImlznkAeDR_nh9ei1Y-LCEYD5r&qA(eiZSXP0qnCwe!Y$iI?Y#3@B*OFv@VSd{<1)DVGe3qB)x-nL(X!<@z*Iy0h z^LgtBYKP~{*OoNrd}dEtaz1k;*{o-Ftu{%EMi0?P(as6EF}&+-{V5EjZtA%)y*yf8 z85F1E;yXvKB$G5H^FP3zgKOFvcPl=I8S`kq^gU_Sa-OzPweTiwzhLP8N!sGt^v;mU z!bQdQX?bL|r63(n#V#}qrQ1@Z)h}sFTBx?zlXmg>q_vB==@>O%WJb+D25L_`l8&VP ziYaD#-IjFRGQaL*q1Drl4Yj){UZR(6*XjxVRZQr?Y9S^jX^qhoC`mub=uKk^l%``- zbfGAawD4tw%APny3%)!}3lkIZQfVv5TUANFRn$}CT2wu%7V$Ej7B(nZ{f1tIH*4BC z?V5Hc-8p*0{e*g>n(7U=R@*1u8#P+aIlnFBHOZAUCtXSSf|G1A?}L0LEF+aMrE4Em z0`zws>2GhmN-c^>I(d%Y1aw!&Il~^Wf2$PORa#z=+52TVcFp z-e#vg@j5MD(#HGATiEzEe6uhLc|Ht$kf%H~toydds{3}W4jJ^$_+}na_e|P0@y(B* z?c>$2ds7h!7)u>xC&`O2?uj+(j`od5Mc&0CpL;t2FPS^Nuao zCdT(Gd2n1?3kMud7Nbe>=eV8lOi!h8f(nPnagAw4L#cN_O|=VB0V74)!i8hd62k0> zz|4nYLU3d}I(iw{f3CTM3ysI3SOPb&LruIpyE+-XtQu(#*2|cwRb%WmuET^N!op${ z*z_&2b|wTxLmKz%7#$tIxH6k1MfFTNV+5Q|l$@g~;SooSO`Zp$Q=lYn4O^2Q^lh zN2QkFwsUGQa*}#zI+(1z^ze30b|2|Hd9r&js4SFLEq$$>Y7Pnus>M|@PQN7zJE~@! z=1JA)5WDL1iJpOh?ymhnsZ1W0^RFK8DBn*rZfwCsZiM7q+_TXm}iY4Hh1m_2U|qr5Mkxy17U+-b^YO*w3xD z;kvXJm(--{99h-y!Cn@u3D1rN&>dY#!K=sLkDH&|UsS zoxh1x!Ec<0Ke1VY{(I7F~+R zCu93tTQ9;`G&Rx!gH7vde(NO61g#0@k@08@UY;xA5SMVP!!dj@1B2ZAX4yU-j$95R z>LJ^RcS;;jwEB^PKbZ={a$HS720MK1$#CbVi}wc-0k!%g52YcFbTUg^OWW?YL~G6w z3mO1W35=&)Y-)5AFaey@t_6H@-Xtt&~J#!UC8BSu=~c?2%dgcI7;N zYGN`b+cexkL`F)sj0+JF*%A@?HxU<%q8A-p?gqRf^4lV=x>Q00Jqd#~l)mW8^Hwk*~kmo}Y{94AxkDK&mzu10dS zrq~_IZ>fH#v}uoC5azgTu2ypFNU?1X@)=vDRJko>-M(ydOTO(=({s}H_7%p|u>&0M zjt7j%-uAW40}-h@`%`QqWKQbrte$;g?&^Yl(Yb%7Yq_N2_VBIYId-vR%S<0e>7VVB zsW=eiav0@ppHEp5MQSP1{JMQZE( zsOIxmrM{OWPcUVB`73YHva3KU>`u9kF1ZSohUw+2WXJNCtYuQwt}m>+mTh%&o&|Ox z{H5*CH%O%xsr8`La!5K9lsqq|Y@w_?kgytc+D?4lC%q^vwq3Z(w#=M(qf)AA`K`5_ zw4(#tAvLvs(a??!>A;3`7&PSI#}=vU%;KT5(!q1mIbITC5+9d5Qz_e(hc`xjXOvf~ zYROjc#{SuV0X=+Y?DNJ47IR+y0|)l1-uQzl_K;d}s`0g$rv1*;N6`L(^|XI~ian6d z=AO0wuC;!yBW2yWRJ3(2F*m-j^-jedr&Q2&J%8C&wdAT?@>IY(C{=8qZRGv(uDC`#mXkuVLBCHfYEE(S`0i`@Xbw z)6IBfo(EFwb0p6{?f>rEb7sc(%y-|mFusE^9BV$Y+xzO-Pl{M@Klj=D{OsqIEV!fa zOurCq!XfYe9dH4o(;tkft93m9JY(u=j1I$X7;R-gy^-`5D!pj~<+D_J^9IuAQRyuk zNS{xoXE%`EN~O=+KzbXMK0j%O1)Ppy@;U+qYhE2!93vZWbRWV7nBxN#oi#CbCXIY0 zb%b@=nzUr(t>Y<=lXsHM$b&{D*ImD4UPd0?bj{b_#$Tvg96E`&2 zbL?36U{BvMWecT=tTy}4^}*V0uzR4ti96Oabo|WW;86dG?mlJns<&sbGuU}%=(w`k zp|V=I5yV{yiDBFdi?xt^WSdsH%*a-?eAx~jrF_|!UB2u{mo2;KvSqto?rL+lC`QHo z*diq(pwJa89G8E%n28B-*jnU-iOKl2mfztQuv)k#jeoU*tQRps2vU!Sabqqnz{W^R zVz(MSyMhlbX|+X7m2Sktic=7XG7yt0;vpP9Rs#ByDPi(jiVs!)EY6qgd>h2pR94I3VT`|6sID=9B--k z0>u9%{KZ~^4gwz4#rO(uCT=8dzIx-;*|GWhMQ`)W@nw(i=Gcv~n~@ul+4J+}MbGw` zW6Q;*w|j5(-tN2AH+NvcyjZ+z=G1ao#qGqc#O+say((>e_D=m`S-Zp*FBcTuuDn%w zyY^P?oNIn$v7l|HciCH@mlA<6ZyS{2E4=Nv<+$y+<$)>t@S?AErsucLa>6yXr)(X| zHs?*-4ci+9uRB**Hm`WOxNO$FSiJSR{r3*WRZZe`rEJ|)yx%%YNN`8Wb}%Ejhy))> z**Y_Vi;W8Vh6NtV_lAFVpR{%FlCAKK|MPDgkw}VckW#AjkLai z+9}i90P}OoSI*9t zkv%~KHsH$0$2j+jN7etDSKXU%U1b85p<3u{dT#;|*ZQ6aU|}d+Q%~e|5Q%+qTNAKP zp^QoF7DtrIzP zHi6T(szR=aJ?AE&=*I+`(b)pdstQ;Wpx78t6}ur`qFI3i5zoy{Sp8*6*mW-;raRjJ z5Y0i;9MGVPFg@9f5U!5Jz34oH&a>zc_-`NjbPO=yPP0M^@|OnvhA}20f8u_04xrP4 z&Ovkzq0uZT8~~`|$x5+)?wsWK1d}zpKL!Gmh6)tyg@yti7jF@} zVBjEAtaucC$I$6PrxzT#aIpLNGu@|$KwfsR`)p75x$Z&n1U@~9&M9>I(CJ5K0G;R2 z83ZQ>kRYDM2t(+cLFX(wIDOFof_M%?jb=?`i49Kt~M1&x8UADOEu!Oz~xm zWCYlVA$*dF$A}{sMi3WO2n!JxLjvkV2_z1lz8s#ML~$;^9_j}LHlpf9wjBwK76ZXt zkqE*9%7>I7GQ7fmE^!DY3{hSTM6|T1AWTR_4^as~x=kxjEu%$5$tAG~oJ6rfhjL;w zJ}TF1m)VhAqEUgDP_8d`?_rh29avBs=C)avQG{%-hGK^ANE&&{?${j2lXs)Y6K>_p z`7zLQ6L=zkM&!`~1!57_xELK|p2bV(q*?1nV^Ol5hlU4ON<7a?a_#+d@%A$%Gfh1>Pc#8dvnE+W^|E~dAxp1wgC>D{(qEReYhCmh#FZvqh zPAvL%%=9cZ_>d;6c8q_Pg!T?O|mtB>qI_NNBUO6Oi)90*DMBa&w{ zW#hkcR*@CXz?Zh?zu`8&=Xlp4Z9lNcJtx^}){13)z69( zKpe~M0dXuhM;>g`AN(VEP?%Bk-6?jDiocOsWeZ<2+4u_S)ILiKl@pL1=kp!`}03ucuv>gl-x-d5$xf%H+U`t-a)Bz^L9?fm>l zU?uq)UI2Rh>GE7jYZe+~P0OjSk@V3K9FS=BP`Mblg`SJjCDLut=eML4w4j0I$BSTk zwrN21k`9pc$p_rYNlE&E{7=%MO8PieNuT^_=Z0GEqh=hv4It@LK&V3N=;vo(RFvI; zbJoM#`S!p%n)Bm^uDW96wghehgQBCcmXEq{;-BZ z@Mw9n+NA3jX1*?C_D{ce#x>%!uOfqBL3 z^FIW3mKzO0DW(C{#*PYUwW*L6#}QR(BiOCJlZyyfHLOPiP5>1G)M7vP90VW?)KPCJ z5T%e|!`PVkGQ80nfx=qXDSV`nBjKcI0|H2GZF0U+cTF>sD3BV_2Z;kj7*!||pm434 zhf+=fxIkB2hsKCz@*b{{=)n&*t2t_@9O(6qhQ`OifRAELsy*RRHENZLq7JDlYm`m( z9Ke-(qrjCFdj%PWfQMoe2@jaX7d}*EN_J;7NI{@bW>x1Oi6;|&%4(aKfcXCtzVKL= z0zdr$6L`Oa(w)(+zb~QEJM)Fm)%KVvhsmO3HLG|APyM7mJ^nIkjXhp0#~p zqnkth*jrvR2TxOe03uyblFw90a6sX0U1NE*n6azt%w- z-?}8NvIhCb0BL?`WM&;W%o+s7P(8~CfgzJwz)H=j2)$%){op(s!zoyuCJjKAEc%H_ zhT4=_&YBNVpE(lh)zC`Jh;8B>f>r^;4b0~3eSo}@=rT+60|CkxKnC><&& zI_SOr#OY9(rdkd!@Jvkz)ani4nKPPk z=N|&0p=}sH7Dz)U%r<@urto4Q<^r~}ng@0(W|Lx?z!7So<<_xsC{sBqp*>7ZP0==c zi1}*+OK(LP3TIdjsEH|on$lTDpr&}H1g2$`)HIs%SvpO|JgDVPX{D(#%XQhC%mjY1 z7RJUtBakPtRY7r3KkZ?3?;sjoTOk{;MAim>JK=8^{OwNE5as_67`qEc#c*6TtjINz zE((YZkS49#rkNl^)wbMyMdYtEvtmTn>S0=NZ5k%C)>b(JJ4QyXjA0qX-HCmxY;`uA zH^qJE5HjGN&RRoO)A&3WHUl=c2L^lk2YZIjt2Va9=P*91wPmTg<+f5)p<+*K+bO;V z`9zWX{8t7L&9f^GLifvMU|D_qFOy2Xn>zV)Q zM|q3fQK_y+a`dLy6KZ_>?6hw13G;JHbvqnznC*Gi$VQc}-1WmL#qCV7yP%4wTqc+80ofY>LZtG>yL9!WXNDxtnJ;Z;zbW3a zQ2SAhG;n^gco<9+%I_vs|<3o#8i!=h?-Y z=IecEr>c0*uSV|#ei@PWbbs_?>2ydM9FYn~Q!f6iqOxUQiB#H?^7StHO0%%7|9|xM zY#DMx?J2f{kQO!a4l>0DzWcUXH?_3M-kZmMvYiF@vn}>s2m4to3vLGPgI^gSK2J?8 z0S%Z92?0G(+-Czig0v7(wh$17wmbq;(RtOUrk3zcz{?Q7qUe-`J^f)#E&Zo;hzPBn z!X5*F8tgvRe-@PQ$YB*v*3y!Z=AZ1&C~zI{RH99_N0gE9p%#X|2cm^@|5`mkBX)$q zS_rQr!-$uHYt_yhiJo9J_8JcY9jh}5g-q-sEca!JdW4*Y5L2aATfJS%8o zrQ20NN-xaOE=p!6nI}F2+d4Y5XJ|($PlGI`^V4NeX>{vJ>3Sve`Qi^tG&veAJxErS zrE}mZZM|z{u&tt7Y#h^pz;upaSI`4Mirz+$@=?J{6LTK&)i+Mc6YVFX7rA5M`0=R` zJS6}u@u|mEk<+Hs69XoN(eQ=vC~aaMjFrb@EpmaXbl!coyKgAi*LkX&Xbs6l8R3d8 zciBTs&yn+*dQbQFiN~SFdJbqa@N~~m|KNGqqb5Gm-#66#!cf9RDi(}@o%weEs>z?Q zslp2WgbxK%DC6q>L}A*xdo!tiyFcN=(~02tsi=6Z-7hvmv5B@JI1mA>lv7sod(pHx zQ9Hs1e#PYWQ7{I03T^fK#ci0bLQO{`P8DnDN|Hw13N}bu2z(&1_0{yHQTT{*6d0F& z^6Kwknt_v@xLEKkSkiNQZw}uWzWLIPm!#^pg`JD;y)#FbVb>n)G2eda)=Sdn-3ud& zCHufEv&(a{_eSr{z8hegxp`h(bnTq!re;qnPow0xEq`*ha@IB1DLJ;LSU;}Uj=ymh z%;7;mZHlcU%lGP8s7KR01nH)%YiFlsFU~!mwuqCF&DU0!L*M8!2Fi^vIQ_7jh6hNCXxde<6l`zR?MuuUNb-KSuAP2eiW9^Ki_wQJLg1%9j&E&NX$ zdycx8PhGV~n=PLGw)73ZujNgON)DWC4C<>!-qZC}D&~j0ilTxXmi>E1I zEgn*+jRMLztJX$It0scu{)l>P6Q^vp!fAlWv<57)H|yX)*{2M-YVfJf0b-;xU>4_q zLb45P>|@*c7!EHQ+v|nSBf)A{h<^nScL1XmLv_X(X2r$W3V$BFYu&u$t&nUL%icQW zotx`j^tR3%|H|rJ@|IoqE;&miwnRkR52Ns>UpV1FZp?iYo1)D-7@3adO&_LB3FE1H z2EEH$c$UxmP(OMM4#{GS1W`3*m}ygbrJXbxts%9EaN3;SVdAYs62WGig0MBz1Zo^B zEi7#`A@dHzKI2F*a*gSNzFG*wP==K)ASIIEonwftW?gAPSSmNP7ngNu6w%sCr9(|& za*eGc9ZJG!c}%ku&0NNG0BRA2?QKeEI(?wi7^jp>yF9h`V`gBVR(%KzkT>A#OEi&r znVecg4gw{L#45+qshqdTU5$#DFMy&+3?@=1FDNG?!T~M`oA%WYB@PXNp+WVdgO6W$ zMHroeLwcw)JmDKf9s}+FW^hDGq5z!82%i->zk-)pJfJh-g;QD-Cg3!jsstL$ZaCrs z#u{=o4*bjua1ev+cO=YBU`bD1C7+30j=*k)Rvmw$z~91wC0(!rNJgjFeonEfLzsgC z*%lHnk~vuRbcz?J&|>lcPRXL|LZxhYO2T9ZiG;sn;%8IHbXOk1e~)mcasYsi0)Z-M?aG^2#4D zY+gQSzqktTIjiqFs~4TMGhN@ft7nJa`O%v{T6711Q-DdlfA;9?vvchW#s8t|-&HNR z@0^hwM^bFpQvKHVw!gdmwZlK_{gdA7KfTM=edDRQ=h<}EvuSSYq9-tO>?>#ClCSu- z{g(Z$&2RnmUfr&{b-Nbp_AFNJ{oCSHN8i1U(|0>gFLs<++;{eF<=I8wx$AjkHuul7 z|JM1wb8cGN-Tjg9(K*R;DrM`V7uKxvwVoxXi;RnKMhKWM2FsH{7?N=>yD#9EtwA`& zbTk-Lc3XBqs6y<&0iRr;$XMfnx9Wkd%FYan(U8b#%YuqtH`$}Xb%0`l(21Gk#iwBR z2dp&5McEq+h9Y31S~(Xs7?jzOXmngT)8q^$JB$w6QdU@li|9keYob1-um&jOqi_m8 zLm%>XB6)wvn}X8^>1u2(emc;!Aqab)Av7RZ%c|`;r8ynqe}+f64vD=FuQhNkCeyd9 z&BWd>W=yW%F!tXtj^8lee`4(>^FJ}*+(&1noN+bG*j5~tEoO=Fy|HE1GJAT~cB}P1 zV}Yj*v#DivbcKQ29Dg5gE4FU4sd&j#uwp^a*KXfR9(v$?^A)XFiPy%IRj$~H7qqO3 zSDeJ_V!VYbZsPS|TrctZn0&|m0`%S=V7Hs{S6(t5HK_%lhZKMwwE*I^VXk)KbzrVe z;&m|<)hlk|RSFQ^1xo-5c)@g5D*!#D0Q9H@5U*b0bY9C9 zJtSB3sJRlajVUf$u@kRSZQ@m`O}t9AiC3vMdhfqt2Eu>)qN&ETZRN0u@o-CZ2bOC0 zssA?}{Jq;+WS;S^R5D)wl4t8u`40T=ZCom7f}g+l+KTbrSt)gzO6M#q4BX}|_wn{^ rb*ag{vXfz5*Arh@DwbH+%#oiR|C8f4hW_Q*FWKT13&U2DSNZ<{!+|ds literal 0 HcmV?d00001 diff --git a/scripts/__pycache__/jira_sync_modules.cpython-312.pyc b/scripts/__pycache__/jira_sync_modules.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2211c8c5fcf90161def05d0084795a953e074273 GIT binary patch literal 52455 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 literal 0 HcmV?d00001 From 6ea431bc2da85fc344fd0fd561544b614a7c3207 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 29 Jun 2026 12:19:59 +0000 Subject: [PATCH 03/15] Implement PM-327 Jira PR web-link sync --- scripts/jira_sync_logic.py | 36 ++++++++++++++ scripts/jira_sync_modules.py | 93 +++++++++++++++++++++++++++++++++++- 2 files changed, 128 insertions(+), 1 deletion(-) diff --git a/scripts/jira_sync_logic.py b/scripts/jira_sync_logic.py index 3dd23ac..fb3f9b8 100644 --- a/scripts/jira_sync_logic.py +++ b/scripts/jira_sync_logic.py @@ -21,6 +21,7 @@ apply_jira_labels_to_pr, jira_status_transition, add_comment_to_jira, + add_pr_weblink_to_jira, remove_label_from_jira_issue, get_done_issue_keys, ) @@ -90,6 +91,13 @@ def manage_labeled_gh_event( print("No Jira keys found. Nothing to do.") return + # --- Step 1b: ensure PR URL is linked on Jira issues --- + print("\n" + "=" * 60) + print(" Step 1b / add_pr_weblink_to_jira") + print("=" * 60) + pr_url = f"https://github.com/{owner_repo}/pull/{pr_number}" + add_pr_weblink_to_jira(jira_keys_json, pr_title, pr_url, jira_auth) + # --- Step 2: add the triggering label --- print("\n" + "=" * 60) print(" Step 2 / add_label_to_jira_issue") @@ -263,6 +271,13 @@ def manage_review_gh_event( print("No Jira keys found. Nothing to do.") return + # --- Step 1b: ensure PR URL is linked on Jira issues --- + print("\n" + "=" * 60) + print(" Step 1b / add_pr_weblink_to_jira") + print("=" * 60) + pr_url = f"https://github.com/{owner_repo}/pull/{pr_number}" + add_pr_weblink_to_jira(jira_keys_json, pr_title, pr_url, jira_auth) + # --- Step 2: extract issue details --- print("\n" + "=" * 60) print(" Step 2 / extract_jira_issue_details") @@ -380,6 +395,13 @@ def manage_closed_gh_event( print("No Jira keys found. Nothing to do.") return + # --- Step 1b: ensure PR URL is linked on Jira issues --- + print("\n" + "=" * 60) + print(" Step 1b / add_pr_weblink_to_jira") + print("=" * 60) + pr_url = f"https://github.com/{owner_repo}/pull/{pr_number}" + add_pr_weblink_to_jira(jira_keys_json, pr_title, pr_url, jira_auth) + # --- Step 2: extract issue details --- print("\n" + "=" * 60) print(" Step 2 / extract_jira_issue_details") @@ -530,6 +552,13 @@ def manage_opened_gh_event( print("No Jira keys found. Nothing to do.") return + # --- Step 1b: ensure PR URL is linked on Jira issues --- + print("\n" + "=" * 60) + print(" Step 1b / add_pr_weblink_to_jira") + print("=" * 60) + pr_url = f"https://github.com/{owner_repo}/pull/{pr_number}" + add_pr_weblink_to_jira(jira_keys_json, pr_title, pr_url, jira_auth) + # --- Step 2: extract issue details --- print("\n" + "=" * 60) print(" Step 2 / extract_jira_issue_details") @@ -666,6 +695,13 @@ def manage_unlabeled_gh_event( print("No Jira keys found. Nothing to do.") return + # --- Step 1b: ensure PR URL is linked on Jira issues --- + print("\n" + "=" * 60) + print(" Step 1b / add_pr_weblink_to_jira") + print("=" * 60) + pr_url = f"https://github.com/{owner_repo}/pull/{pr_number}" + add_pr_weblink_to_jira(jira_keys_json, pr_title, pr_url, jira_auth) + # --- Step 2: remove label from Jira (skip priority labels) --- print("\n" + "=" * 60) print(" Step 2 / remove_label_from_jira_issue") diff --git a/scripts/jira_sync_modules.py b/scripts/jira_sync_modules.py index a2b9c6f..5680cb9 100644 --- a/scripts/jira_sync_modules.py +++ b/scripts/jira_sync_modules.py @@ -14,6 +14,7 @@ apply_jira_labels_to_pr jira_status_transition add_comment_to_jira + add_pr_weblink_to_jira The orchestrator functions and CLI dispatcher live in jira_sync_logic.py which imports from this module. @@ -587,7 +588,7 @@ def remove_label_from_jira_issue(jira_keys_json: str, label: str, jira_auth: str _DETAIL_DELIM = ";" -def _jira_get(url: str, jira_auth: str) -> dict | None: +def _jira_get(url: str, jira_auth: str) -> dict | list | None: """GET JSON from a Jira REST endpoint. Returns parsed JSON or None on failure.""" encoded_auth = base64.b64encode(jira_auth.encode()).decode() @@ -1262,6 +1263,96 @@ def add_comment_to_jira( print(f"WARNING: {failed} comment(s) failed. Continuing.") +def _normalize_url(url: str) -> str: + """Normalize URL for stable comparisons.""" + return (url or "").strip().rstrip("/") + + +def add_pr_weblink_to_jira( + jira_keys_json: str, + pr_title: str, + pr_url: str, + jira_auth: str, +) -> None: + """Ensure each Jira issue has a remote link to the PR URL (idempotent).""" + print(f"jira_keys_json={jira_keys_json}") + + if not jira_auth: + print("Error: jira_auth is not set or empty.") + sys.exit(1) + + keys = _parse_jira_keys_json(jira_keys_json) + if not keys: + print("No Jira keys to sync web links for.") + return + + normalized_pr_url = _normalize_url(pr_url) + if not normalized_pr_url: + print("PR URL is empty; skipping Jira web-link sync.") + return + + link_title = (pr_title or "").strip() or normalized_pr_url + payload = { + "object": { + "url": normalized_pr_url, + "title": link_title, + } + } + + ok = 0 + skipped = 0 + failed = 0 + + for key in keys: + get_url = f"{JIRA_BASE_URL}/rest/api/3/issue/{key}/remotelink" + print(f"Fetching existing remote links for {key} ...") + existing = _jira_get(get_url, jira_auth) + if existing is None: + print(f"SKIP {key}: failed to fetch existing remote links.") + skipped += 1 + continue + if not isinstance(existing, list): + print(f"SKIP {key}: unexpected remotelink response format.") + skipped += 1 + continue + + has_pr_link = False + for item in existing: + if not isinstance(item, dict): + continue + obj = item.get("object") or {} + if not isinstance(obj, dict): + continue + existing_url = _normalize_url(obj.get("url", "")) + if existing_url and existing_url == normalized_pr_url: + has_pr_link = True + break + + if has_pr_link: + print(f"SKIP {key}: PR web link already exists.") + skipped += 1 + continue + + post_url = f"{JIRA_BASE_URL}/rest/api/3/issue/{key}/remotelink" + code, body_text = _jira_post(post_url, payload, jira_auth) + if code in (200, 201): + print(f"OK {key} ({code}) web link added.") + ok += 1 + elif code == 404: + print(f"SKIP {key} ({code}) issue not found or no permission. Continuing.") + skipped += 1 + else: + print(f"FAIL {key} ({code}) First 400 chars:") + print(body_text[:400]) + failed += 1 + + time.sleep(0.2) + + print(f"Web-link sync summary: ok={ok} skipped={skipped} failed={failed}") + if failed > 0: + print(f"WARNING: {failed} web-link update(s) failed. Continuing.") + + def get_done_issue_keys(details_csv: str) -> set[str]: """Parse the details CSV and return issue keys whose status is in a closed/done state. From 4d029836e5bf178d4bf571490cd5c2aa1bfcc558 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 29 Jun 2026 12:20:54 +0000 Subject: [PATCH 04/15] Refine PM-327 weblink sync logic --- scripts/jira_sync_modules.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/scripts/jira_sync_modules.py b/scripts/jira_sync_modules.py index 5680cb9..05f6bf1 100644 --- a/scripts/jira_sync_modules.py +++ b/scripts/jira_sync_modules.py @@ -1265,7 +1265,9 @@ def add_comment_to_jira( def _normalize_url(url: str) -> str: """Normalize URL for stable comparisons.""" - return (url or "").strip().rstrip("/") + if not url: + return "" + return url.strip().rstrip("/") def add_pr_weblink_to_jira( @@ -1291,7 +1293,10 @@ def add_pr_weblink_to_jira( print("PR URL is empty; skipping Jira web-link sync.") return - link_title = (pr_title or "").strip() or normalized_pr_url + if pr_title and pr_title.strip(): + link_title = pr_title.strip() + else: + link_title = normalized_pr_url payload = { "object": { "url": normalized_pr_url, @@ -1320,7 +1325,9 @@ def add_pr_weblink_to_jira( for item in existing: if not isinstance(item, dict): continue - obj = item.get("object") or {} + obj = item.get("object") + if obj is None: + obj = {} if not isinstance(obj, dict): continue existing_url = _normalize_url(obj.get("url", "")) From c2d6a46a54520116eb018c7776043494be9ddbe5 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 29 Jun 2026 12:21:43 +0000 Subject: [PATCH 05/15] Tighten PM-327 helper readability --- scripts/jira_sync_modules.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/scripts/jira_sync_modules.py b/scripts/jira_sync_modules.py index 05f6bf1..f4e04c3 100644 --- a/scripts/jira_sync_modules.py +++ b/scripts/jira_sync_modules.py @@ -1293,8 +1293,9 @@ def add_pr_weblink_to_jira( print("PR URL is empty; skipping Jira web-link sync.") return - if pr_title and pr_title.strip(): - link_title = pr_title.strip() + stripped_title = pr_title.strip() if pr_title else "" + if stripped_title: + link_title = stripped_title else: link_title = normalized_pr_url payload = { @@ -1326,8 +1327,6 @@ def add_pr_weblink_to_jira( if not isinstance(item, dict): continue obj = item.get("object") - if obj is None: - obj = {} if not isinstance(obj, dict): continue existing_url = _normalize_url(obj.get("url", "")) From 15f345db334551efdb9498d733e7ae4e5dae7cb0 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 29 Jun 2026 13:35:11 +0000 Subject: [PATCH 06/15] Remove non-Python files from PR diff --- .../workflows/extract_jira_issue_details.yml | 2 +- .../workflows/fill_jira_with_github_data.yml | 150 ------------------ .github/workflows/jira_transition.yml | 1 - .../main_create_jira_issue_from_gh_issue.yml | 4 +- .../workflows/main_jira_sync_add_label.yml | 4 +- .../workflows/main_jira_sync_in_review.yml | 6 +- .../workflows/main_jira_sync_pr_closed.yml | 6 +- .../workflows/main_jira_sync_pr_opened.yml | 6 +- .../workflows/main_jira_sync_remove_label.yml | 6 +- .../workflows/main_pr_events_jira_sync.yml | 2 +- .../main_sync_milestone_to_jira_release.yml | 120 +------------- .../remove_label_from_jira_issue.yml | 4 +- .../gh_project_automation.cpython-312.pyc | Bin 30765 -> 0 bytes ...e_jira_issue_from_gh_issue.cpython-312.pyc | Bin 15010 -> 0 bytes .../jira_sync_logic.cpython-312.pyc | Bin 31909 -> 0 bytes .../jira_sync_modules.cpython-312.pyc | Bin 52455 -> 0 bytes 16 files changed, 21 insertions(+), 290 deletions(-) delete mode 100644 .github/workflows/fill_jira_with_github_data.yml delete mode 100644 __pycache__/gh_project_automation.cpython-312.pyc delete mode 100644 scripts/__pycache__/create_jira_issue_from_gh_issue.cpython-312.pyc delete mode 100644 scripts/__pycache__/jira_sync_logic.cpython-312.pyc delete mode 100644 scripts/__pycache__/jira_sync_modules.cpython-312.pyc diff --git a/.github/workflows/extract_jira_issue_details.yml b/.github/workflows/extract_jira_issue_details.yml index 3de650c..83cb829 100644 --- a/.github/workflows/extract_jira_issue_details.yml +++ b/.github/workflows/extract_jira_issue_details.yml @@ -140,7 +140,7 @@ jobs: - name: Upload CSV artifact id: artifacts - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: jira-details-csv path: jira-details.csv diff --git a/.github/workflows/fill_jira_with_github_data.yml b/.github/workflows/fill_jira_with_github_data.yml deleted file mode 100644 index 00b35c9..0000000 --- a/.github/workflows/fill_jira_with_github_data.yml +++ /dev/null @@ -1,150 +0,0 @@ -name: Fill Jira Field with GitHub PR Data - -on: - workflow_call: - inputs: - details_csv: - description: "Full CSV text (header + rows). Must include a 'key' column." - required: true - type: string - secrets: - jira_auth: - description: "Plain 'email:api_token' for Jira Cloud Basic auth" - required: true - -jobs: - fill_jira_fields: - runs-on: ubuntu-latest - env: - BASE_URL: https://scylladb.atlassian.net - TARGET_FIELD: customfield_10718 - PR_URL: ${{ github.event.pull_request.html_url }} - - steps: - - name: Save CSV - id: save - shell: bash - run: | - set -euo pipefail - cat > details.csv <<'CSV_EOF' - ${{ inputs.details_csv }} - CSV_EOF - - echo "Saved details.csv" - head -n 5 details.csv || true - - - name: Extract Jira keys (case-insensitive 'key' column) - id: extract - shell: bash - run: | - set -euo pipefail - - python3 - <<'PY' - import csv, sys, os - - if not os.path.exists("details.csv") or os.path.getsize("details.csv") == 0: - print("CSV empty → no keys to process.") - open("keys.txt", "w").close() - sys.exit(0) - - with open("details.csv", newline="", encoding="utf-8") as f: - reader = csv.DictReader(f) - if not reader.fieldnames: - open("keys.txt", "w").close() - sys.exit(0) - - # Find the 'key' column - fmap = {(h or "").strip().lower(): h for h in reader.fieldnames} - hkey = fmap.get("key") - if not hkey: - print(f"ERROR: No 'key' column. Found: {reader.fieldnames}", file=sys.stderr) - sys.exit(1) - - keys = [] - for row in reader: - val = (row.get(hkey) or "").strip() - if val: - keys.append(val) - - seen = set() - uniq = [] - for k in keys: - if k not in seen: - uniq.append(k) - seen.add(k) - - with open("keys.txt", "w") as out: - for k in uniq: - out.write(k + "\n") - - print(f"Found {len(uniq)} Jira issues.") - PY - - echo "First few keys:" - head -n 10 keys.txt || true - - - name: Write PR data to Jira custom field - shell: bash - env: - JIRA_AUTH: ${{ secrets.jira_auth }} - PR_URL: ${{ env.PR_URL }} - BASE_URL: ${{ env.BASE_URL }} - FIELD_ID: ${{ env.TARGET_FIELD }} - run: | - set -euo pipefail - - if [ ! -s keys.txt ]; then - echo "No keys found. Done." - exit 0 - fi - - COMMENT_TEXT="This issue will be closed by ${PR_URL}" - - while IFS= read -r key; do - [ -n "$key" ] || continue - - echo "Updating $key - [ $COMMENT_TEXT ]" - - # Build ADF document payload for rich-text custom field - jq -n \ - --arg text "$COMMENT_TEXT" \ - --arg field "$FIELD_ID" \ - '{ - fields: { - ($field): { - "type": "doc", - "version": 1, - "content": [ - { - "type": "paragraph", - "content": [ - { - "type": "text", - "text": $text - } - ] - } - ] - } - } - }' > payload.json - - code=$(curl -sS -o resp.json -w "%{http_code}" \ - -X PUT "$BASE_URL/rest/api/3/issue/$key" \ - --user "$JIRA_AUTH" \ - -H "Content-Type: application/json" \ - --data @payload.json) - - if [[ "$code" == "204" || "$code" == "200" ]]; then - echo "OK $key (${code})" - else - echo "FAIL $key (${code})" - head -c 200 resp.json || true - echo - exit 1 - fi - - sleep 0.2 - done < keys.txt - - echo "All Jira fields updated successfully." diff --git a/.github/workflows/jira_transition.yml b/.github/workflows/jira_transition.yml index fd9303b..59fbdff 100644 --- a/.github/workflows/jira_transition.yml +++ b/.github/workflows/jira_transition.yml @@ -156,7 +156,6 @@ jobs: TODAY=$(date -u +%Y-%m-%d) echo "Setting start date to ${TODAY} for ${key} (field: ${START_DATE_FIELD})" - # Use custom field ID for start date if [[ "$JIRA_AUTH" == Bearer\ * ]]; then RESPONSE=$(curl -sS -w "\n%{http_code}" -X PUT \ -H "Authorization: $JIRA_AUTH" \ diff --git a/.github/workflows/main_create_jira_issue_from_gh_issue.yml b/.github/workflows/main_create_jira_issue_from_gh_issue.yml index 103727e..06c5848 100644 --- a/.github/workflows/main_create_jira_issue_from_gh_issue.yml +++ b/.github/workflows/main_create_jira_issue_from_gh_issue.yml @@ -22,10 +22,10 @@ jobs: issues: write steps: - name: Checkout automation repo - uses: actions/checkout@v4 + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 with: repository: scylladb/github-automation - ref: automation-staging-branch + ref: main - name: Create Jira issue and cross-link env: diff --git a/.github/workflows/main_jira_sync_add_label.yml b/.github/workflows/main_jira_sync_add_label.yml index 1d44bae..767e24f 100644 --- a/.github/workflows/main_jira_sync_add_label.yml +++ b/.github/workflows/main_jira_sync_add_label.yml @@ -15,10 +15,10 @@ jobs: issues: write steps: - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 with: repository: scylladb/github-automation - ref: automation-staging-branch + ref: main - name: Run label-sync orchestrator env: diff --git a/.github/workflows/main_jira_sync_in_review.yml b/.github/workflows/main_jira_sync_in_review.yml index bf6361a..453b905 100644 --- a/.github/workflows/main_jira_sync_in_review.yml +++ b/.github/workflows/main_jira_sync_in_review.yml @@ -1,4 +1,4 @@ -name: Sync with Jira - In Review +name: Sync with Jira - In Review on: workflow_call: @@ -15,10 +15,10 @@ jobs: issues: write steps: - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 with: repository: scylladb/github-automation - ref: automation-staging-branch + ref: main - name: Run in-review orchestrator env: diff --git a/.github/workflows/main_jira_sync_pr_closed.yml b/.github/workflows/main_jira_sync_pr_closed.yml index cca2c5c..ef2421f 100644 --- a/.github/workflows/main_jira_sync_pr_closed.yml +++ b/.github/workflows/main_jira_sync_pr_closed.yml @@ -1,4 +1,4 @@ -name: Sync with Jira - PR Closed +name: Sync with Jira - PR Closed on: workflow_call: @@ -15,10 +15,10 @@ jobs: issues: write steps: - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 with: repository: scylladb/github-automation - ref: automation-staging-branch + ref: main - name: Run pr-closed orchestrator env: diff --git a/.github/workflows/main_jira_sync_pr_opened.yml b/.github/workflows/main_jira_sync_pr_opened.yml index 8498175..1aa0d27 100644 --- a/.github/workflows/main_jira_sync_pr_opened.yml +++ b/.github/workflows/main_jira_sync_pr_opened.yml @@ -1,4 +1,4 @@ -name: Sync With Jira - PR Opened +name: Sync With Jira - PR Opened on: workflow_call: @@ -15,10 +15,10 @@ jobs: issues: write steps: - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 with: repository: scylladb/github-automation - ref: automation-staging-branch + ref: main - name: Run pr-opened orchestrator env: diff --git a/.github/workflows/main_jira_sync_remove_label.yml b/.github/workflows/main_jira_sync_remove_label.yml index 2f79ac5..dd41063 100644 --- a/.github/workflows/main_jira_sync_remove_label.yml +++ b/.github/workflows/main_jira_sync_remove_label.yml @@ -1,4 +1,4 @@ -name: Sync With Jira - Remove Label +name: Sync With Jira - Remove Label on: workflow_call: @@ -12,10 +12,10 @@ jobs: runs-on: ubuntu-slim steps: - name: Checkout scripts - uses: actions/checkout@v4 + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 with: repository: scylladb/github-automation - ref: automation-staging-branch + ref: main path: _automation - name: Run manage_unlabeled_gh_event diff --git a/.github/workflows/main_pr_events_jira_sync.yml b/.github/workflows/main_pr_events_jira_sync.yml index 9cd9031..cd36fdc 100644 --- a/.github/workflows/main_pr_events_jira_sync.yml +++ b/.github/workflows/main_pr_events_jira_sync.yml @@ -41,4 +41,4 @@ jobs: PR_MERGED: ${{ github.event.pull_request.merged }} GITHUB_TOKEN: ${{ github.token }} JIRA_AUTH: ${{ secrets.caller_jira_auth }} - run: python3 scripts/jira_sync_logic.py --action ${{ inputs.caller_action }} \ No newline at end of file + run: python3 scripts/jira_sync_logic.py --action ${{ inputs.caller_action }} diff --git a/.github/workflows/main_sync_milestone_to_jira_release.yml b/.github/workflows/main_sync_milestone_to_jira_release.yml index c4a4fa4..046af99 100644 --- a/.github/workflows/main_sync_milestone_to_jira_release.yml +++ b/.github/workflows/main_sync_milestone_to_jira_release.yml @@ -1,4 +1,4 @@ -name: Sync Jira releases (versions) from GitHub milestone +name: Create Jira releases (versions) from GitHub milestone on: workflow_call: @@ -125,124 +125,6 @@ jobs: exit 1 fi - - update_jira_releases: - if: github.event.action == 'edited' - runs-on: ubuntu-slim - env: - JIRA_BASE_URL: https://scylladb.atlassian.net - JIRA_AUTH: ${{ secrets.caller_jira_auth }} - PROJECT_KEYS: ${{ inputs.jira_project_keys }} - - steps: - - name: Debug milestone input - run: | - echo "Projects: '${{ inputs.jira_project_keys }}'" - echo "Title: '${{ github.event.milestone.title }}'" - echo "Description: '${{ github.event.milestone.description }}'" - echo "Due on: '${{ github.event.milestone.due_on }}'" - echo "Action: '${{ github.event.action }}'" - - - name: Update Jira version details in each project - shell: bash - run: | - set -euo pipefail - - if [ -z "${JIRA_AUTH:-}" ]; then - echo "ERROR: jira_auth secret is not set." - exit 1 - fi - - NAME="${{ github.event.milestone.title }}" - DESC="${{ github.event.milestone.description }}" - DUE_ON="${{ github.event.milestone.due_on }}" - - # GitHub due_on is ISO 8601; Jira expects YYYY-MM-DD - RELEASE_DATE="" - if [ -n "${DUE_ON:-}" ]; then - RELEASE_DATE="${DUE_ON%%T*}" - fi - - echo "Version name: ${NAME}" - echo "Description: ${DESC:-}" - echo "Release date: ${RELEASE_DATE:-}" - echo "Projects: ${PROJECT_KEYS}" - echo - - # Split comma-separated keys safely (trim whitespace) - IFS=',' read -r -a KEYS <<< "${PROJECT_KEYS}" - - ok=0 - skipped=0 - failed=0 - - for raw in "${KEYS[@]}"; do - PROJECT_KEY="$(echo "$raw" | awk '{$1=$1};1')" # trim - [ -n "$PROJECT_KEY" ] || continue - - echo "======================================================" - echo "Updating Jira version in project: ${PROJECT_KEY}" - echo "======================================================" - - # Find the version ID by name - HTTP_CODE=$(curl -sS -o versions.json -w "%{http_code}" \ - "${JIRA_BASE_URL}/rest/api/3/project/${PROJECT_KEY}/versions" \ - --user "${JIRA_AUTH}" \ - -H "Accept: application/json" || true) - - if [ "$HTTP_CODE" != "200" ]; then - echo "FAIL: could not list versions in ${PROJECT_KEY} (HTTP ${HTTP_CODE}). Response:" - cat versions.json || true - echo - failed=$((failed+1)) - continue - fi - - VERSION_ID=$(jq -r --arg name "$NAME" \ - '.[] | select(.name == $name) | .id' versions.json | head -1) - - if [ -z "$VERSION_ID" ]; then - echo "SKIP: version '${NAME}' not found in ${PROJECT_KEY}." - skipped=$((skipped+1)) - continue - fi - - # Build update payload with description and releaseDate - jq -n \ - --arg desc "${DESC:-}" \ - --arg rdate "${RELEASE_DATE:-}" \ - ' - {} - + (if $desc != "" then {description: $desc} else {} end) - + (if $rdate != "" then {releaseDate: $rdate} else {releaseDate: null} end) - ' > update_payload.json - - HTTP_CODE=$(curl -sS -o update_resp.json -w "%{http_code}" \ - -X PUT "${JIRA_BASE_URL}/rest/api/3/version/${VERSION_ID}" \ - --user "${JIRA_AUTH}" \ - -H "Accept: application/json" \ - -H "Content-Type: application/json" \ - --data @update_payload.json || true) - - if [ "$HTTP_CODE" = "200" ]; then - echo "OK: updated version '${NAME}' in ${PROJECT_KEY} (id=${VERSION_ID})." - ok=$((ok+1)) - else - echo "FAIL: could not update version in ${PROJECT_KEY} (HTTP ${HTTP_CODE}). Response:" - cat update_resp.json || true - echo - failed=$((failed+1)) - fi - done - - echo "======================================================" - echo "Summary: ok=${ok} skipped=${skipped} failed=${failed}" - echo "======================================================" - - if [ "$failed" -gt 0 ]; then - exit 1 - fi - release_jira_releases: if: github.event.action == 'closed' runs-on: ubuntu-slim diff --git a/.github/workflows/remove_label_from_jira_issue.yml b/.github/workflows/remove_label_from_jira_issue.yml index f09c469..a9dc927 100644 --- a/.github/workflows/remove_label_from_jira_issue.yml +++ b/.github/workflows/remove_label_from_jira_issue.yml @@ -1,4 +1,4 @@ -name: Remove Label from Jira Issues (from jira_keys_json) +name: Remove Label from Jira Issues on: workflow_call: @@ -18,7 +18,7 @@ on: jobs: remove_labels_from_jira: - runs-on: ubuntu-latest + runs-on: ubuntu-slim env: BASE_URL: https://scylladb.atlassian.net SCYLLA_COMPONENTS_FIELD: customfield_10321 diff --git a/__pycache__/gh_project_automation.cpython-312.pyc b/__pycache__/gh_project_automation.cpython-312.pyc deleted file mode 100644 index 2a65a316d545c20453c3a394f0e82aacec258db9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 30765 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 diff --git a/scripts/__pycache__/create_jira_issue_from_gh_issue.cpython-312.pyc b/scripts/__pycache__/create_jira_issue_from_gh_issue.cpython-312.pyc deleted file mode 100644 index 0e49721855f5a2789e91a3d34d7156bb1133739c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15010 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 Ak^lez diff --git a/scripts/__pycache__/jira_sync_logic.cpython-312.pyc b/scripts/__pycache__/jira_sync_logic.cpython-312.pyc deleted file mode 100644 index fb3076186d846a8dace0a353e6cc9f6401162f65..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 31909 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 diff --git a/scripts/__pycache__/jira_sync_modules.cpython-312.pyc b/scripts/__pycache__/jira_sync_modules.cpython-312.pyc deleted file mode 100644 index 2211c8c5fcf90161def05d0084795a953e074273..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 52455 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 From dd9ddcc3b4b7c9a29ca04b2e5c2d39657fd0f8ec Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 29 Jun 2026 13:35:42 +0000 Subject: [PATCH 07/15] Remove workflow-only changes from PR --- .github/workflows/add_comment_to_jira.yml | 134 ---------- .github/workflows/add_label_to_jira_issue.yml | 223 ---------------- .github/workflows/apply_labels_to_pr.yml | 228 ---------------- .../workflows/extract_jira_issue_details.yml | 152 ----------- .github/workflows/extract_jira_keys.yml | 153 ----------- .github/workflows/jira_transition.yml | 249 ------------------ .../main_create_jira_issue_from_gh_issue.yml | 47 ---- .../workflows/main_jira_sync_add_label.yml | 32 --- .../workflows/main_jira_sync_in_review.yml | 32 --- .../workflows/main_jira_sync_pr_closed.yml | 32 --- .../main_jira_sync_pr_milestone_removed.yml | 140 ---------- .../main_jira_sync_pr_milestone_set.yml | 159 ----------- .../workflows/main_jira_sync_pr_opened.yml | 31 --- .../workflows/main_jira_sync_remove_label.yml | 32 --- .../workflows/main_pr_events_jira_sync.yml | 44 ---- .../main_sync_milestone_to_jira_release.yml | 228 ---------------- .../remove_label_from_jira_issue.yml | 171 ------------ 17 files changed, 2087 deletions(-) delete mode 100644 .github/workflows/add_comment_to_jira.yml delete mode 100644 .github/workflows/add_label_to_jira_issue.yml delete mode 100644 .github/workflows/apply_labels_to_pr.yml delete mode 100644 .github/workflows/extract_jira_issue_details.yml delete mode 100644 .github/workflows/extract_jira_keys.yml delete mode 100644 .github/workflows/jira_transition.yml delete mode 100644 .github/workflows/main_create_jira_issue_from_gh_issue.yml delete mode 100644 .github/workflows/main_jira_sync_add_label.yml delete mode 100644 .github/workflows/main_jira_sync_in_review.yml delete mode 100644 .github/workflows/main_jira_sync_pr_closed.yml delete mode 100644 .github/workflows/main_jira_sync_pr_milestone_removed.yml delete mode 100644 .github/workflows/main_jira_sync_pr_milestone_set.yml delete mode 100644 .github/workflows/main_jira_sync_pr_opened.yml delete mode 100644 .github/workflows/main_jira_sync_remove_label.yml delete mode 100644 .github/workflows/main_pr_events_jira_sync.yml delete mode 100644 .github/workflows/main_sync_milestone_to_jira_release.yml delete mode 100644 .github/workflows/remove_label_from_jira_issue.yml diff --git a/.github/workflows/add_comment_to_jira.yml b/.github/workflows/add_comment_to_jira.yml deleted file mode 100644 index 3cdcd4e..0000000 --- a/.github/workflows/add_comment_to_jira.yml +++ /dev/null @@ -1,134 +0,0 @@ -name: Add Comment to Jira Issue - -on: - workflow_call: - inputs: - jira_key: - description: "The Jira issue key (e.g. STAG-17)" - required: true - type: string - comment: - description: "The comment text to add to the issue (prefix text before the link)" - required: true - type: string - link_text: - description: "Optional: Text to display as a clickable link" - required: false - type: string - default: "" - link_url: - description: "Optional: URL for the clickable link" - required: false - type: string - default: "" - secrets: - jira_auth: - description: 'Plain "email:api_token" for Jira Cloud Basic auth' - required: true - -jobs: - add_comment: - runs-on: ubuntu-slim - env: - JIRA_BASE_URL: https://scylladb.atlassian.net - JIRA_KEY: ${{ inputs.jira_key }} - COMMENT_TEXT: ${{ inputs.comment }} - LINK_TEXT: ${{ inputs.link_text }} - LINK_URL: ${{ inputs.link_url }} - JIRA_AUTH: ${{ secrets.jira_auth }} - - steps: - - name: Post comment to Jira issue - shell: bash - run: | - set -euo pipefail - - if [ -z "$JIRA_KEY" ]; then - echo "JIRA_KEY is empty; nothing to do." - exit 0 - fi - - if [ -z "$COMMENT_TEXT" ]; then - echo "COMMENT_TEXT is empty; nothing to do." - exit 0 - fi - - echo "Adding comment to Jira issue: $JIRA_KEY" - echo "Comment: $COMMENT_TEXT" - echo "Link text: $LINK_TEXT" - echo "Link URL: $LINK_URL" - - # Build ADF payload - with or without clickable link - if [ -n "$LINK_TEXT" ] && [ -n "$LINK_URL" ]; then - # Build ADF with clickable link - PAYLOAD=$(jq -n \ - --arg prefix "$COMMENT_TEXT" \ - --arg linkText "$LINK_TEXT" \ - --arg linkUrl "$LINK_URL" \ - ' - { - body: { - type: "doc", - version: 1, - content: [ - { - type: "paragraph", - content: [ - { "type": "text", "text": $prefix }, - { - "type": "text", - "text": $linkText, - "marks": [ - { "type": "link", "attrs": { "href": $linkUrl } } - ] - } - ] - } - ] - } - } - ') - else - # Build simple ADF with plain text - PAYLOAD=$(jq -n \ - --arg text "$COMMENT_TEXT" \ - ' - { - body: { - type: "doc", - version: 1, - content: [ - { - type: "paragraph", - content: [ - { "type": "text", "text": $text } - ] - } - ] - } - } - ') - fi - - echo "Payload to Jira:" - echo "$PAYLOAD" - - ISSUE_URL="${JIRA_BASE_URL}/rest/api/3/issue/${JIRA_KEY}/comment" - - HTTP_CODE=$(curl -sS -w "%{http_code}" -o response.json \ - --user "$JIRA_AUTH" \ - -H "Accept: application/json" \ - -H "Content-Type: application/json" \ - -X POST "$ISSUE_URL" \ - --data "$PAYLOAD" || echo "000") - - echo "Jira HTTP status: $HTTP_CODE" - echo "Jira response body:" - cat response.json || true - - if [ "$HTTP_CODE" -ge 200 ] && [ "$HTTP_CODE" -lt 300 ]; then - echo "Comment added to $JIRA_KEY" - else - echo "Failed to add comment to $JIRA_KEY (HTTP $HTTP_CODE)" - exit 1 - fi diff --git a/.github/workflows/add_label_to_jira_issue.yml b/.github/workflows/add_label_to_jira_issue.yml deleted file mode 100644 index 0de335e..0000000 --- a/.github/workflows/add_label_to_jira_issue.yml +++ /dev/null @@ -1,223 +0,0 @@ -name: Add Label to Jira Issues (from jira_keys_json) - -on: - workflow_call: - inputs: - jira_keys_json: - description: 'JSON array of Jira keys, e.g. ["STAG-1","STAG-2"] or ["__NO_KEYS_FOUND__"]' - type: string - required: true - label: - description: "Label to add to each Jira issue, or P0..P4 to set priority, or area/* to add Scylla component" - type: string - required: true - secrets: - jira_auth: - description: "Plain 'email:api_token' for Jira Cloud Basic auth" - required: true - -jobs: - add_labels_to_jira: - runs-on: ubuntu-slim - env: - BASE_URL: https://scylladb.atlassian.net - SCYLLA_COMPONENTS_FIELD: customfield_10321 - - steps: - - name: Extract Jira keys from jira_keys_json - id: extract - shell: bash - env: - JIRA_KEYS_JSON: ${{ inputs.jira_keys_json }} - run: | - set -euo pipefail - python3 - <<'PY' - import json, sys, os - - raw = os.environ.get("JIRA_KEYS_JSON", "").strip() - print(f"Incoming jira_keys_json: {raw}") - - # Handle empty / sentinel cases - if (not raw or - raw == "[]" or - raw == '[""]' or - raw == '["__NO_KEYS_FOUND__"]'): - print("No usable Jira keys in jira_keys_json; nothing to update.") - open("keys.txt", "w", encoding="utf-8").close() - sys.exit(0) - - try: - data = json.loads(raw) - except json.JSONDecodeError as e: - print(f"ERROR: jira_keys_json is not valid JSON: {e}", file=sys.stderr) - sys.exit(1) - - if not isinstance(data, list): - print(f"ERROR: jira_keys_json must be a JSON array; got: {type(data)}", file=sys.stderr) - sys.exit(1) - - keys = [] - for item in data: - if not isinstance(item, str): - continue - k = item.strip() - if k and k != "__NO_KEYS_FOUND__": - keys.append(k) - - # Deduplicate, preserve order - seen = set() - uniq = [] - for k in keys: - if k not in seen: - seen.add(k) - uniq.append(k) - - with open("keys.txt","w",encoding="utf-8") as out: - for k in uniq: - out.write(k + "\n") - - print(f"Found {len(uniq)} issues.") - PY - - echo "First 10 keys:" - head -n 10 keys.txt || true - - - name: Prepare payload(s) and mode (priority / label / scylla component) - id: prep - shell: bash - env: - TARGET_IN: ${{ inputs.label }} - SCYLLA_FIELD: ${{ env.SCYLLA_COMPONENTS_FIELD }} - run: | - set -euo pipefail - - TARGET_UP=$(echo "${TARGET_IN}" | tr '[:lower:]' '[:upper:]') - - MODE="" - PRIORITY_NAME="" - echo "Incoming label: '${TARGET_IN}'" - - # 1) P0..P4 → priority field - case "$TARGET_UP" in - P0|P1|P2|P3|P4) - MODE="priority" - PRIORITY_NAME="$TARGET_UP" - ;; - *) - # 2) area/* → scylla_components - if [[ "$TARGET_IN" == area/* ]]; then - MODE="scylla_component" - RAW="${TARGET_IN#area/}" - # Replace underscores with spaces across the entire remainder - COMPONENT_VALUE="${RAW//_/ }" - - echo "Derived Scylla component value: '${COMPONENT_VALUE}' from label '${TARGET_IN}'" - - # JSON-escape the component value - ESCAPED=$(jq -Rn --arg v "$COMPONENT_VALUE" '$v') - # Build payload: update customfield_10321 with add { value: "" } - printf '{"update":{"%s":[{"add":{"value":%s}}]}}\n' "$SCYLLA_FIELD" "$ESCAPED" > payload_scylla.json - echo "Scylla components payload ready." - else - # 3) Fallback: normal Jira label - MODE="label" - fi - ;; - esac - - echo "mode=${MODE}" >> "$GITHUB_OUTPUT" - echo "priority_name=${PRIORITY_NAME}" >> "$GITHUB_OUTPUT" - - # Build the label payload with jq (used when MODE=label) - if [ "$MODE" = "label" ]; then - jq -n --arg label "$TARGET_IN" \ - '{update:{labels:[{add:$label}]}}' > payload_label.json - echo "Label payload ready." - fi - - # Build the priority payload with jq (used when MODE=priority) - if [ "$MODE" = "priority" ]; then - jq -n --arg prio "$PRIORITY_NAME" \ - '{fields:{priority:{name:$prio}}}' > payload_priority.json - echo "Priority payload ready." - fi - - - name: Apply to each issue (Basic auth) - id: apply - shell: bash - env: - JIRA_AUTH: ${{ secrets.jira_auth }} - BASE_URL: ${{ env.BASE_URL }} - MODE: ${{ steps.prep.outputs.mode }} - PRIORITY_NAME: ${{ steps.prep.outputs.priority_name }} - TARGET_LABEL: ${{ inputs.label }} - run: | - set -euo pipefail - - if [ ! -s keys.txt ]; then - echo "No issue keys found; nothing to apply." - exit 0 - fi - - echo "Operation mode: ${MODE}" - if [ "$MODE" = "priority" ]; then - echo "Will set priority to: ${PRIORITY_NAME}" - PAYLOAD_FILE="payload_priority.json" - ACTION_DESC="Set priority" - elif [ "$MODE" = "scylla_component" ]; then - echo "Will add Scylla component derived from label: ${TARGET_LABEL}" - PAYLOAD_FILE="payload_scylla.json" - ACTION_DESC="Add Scylla component" - else - echo "Will add label: ${TARGET_LABEL}" - PAYLOAD_FILE="payload_label.json" - ACTION_DESC="Add label" - fi - - ok=0 - skipped=0 - failed=0 - - while IFS= read -r key; do - [ -n "${key:-}" ] || continue - ISSUE_URL="${BASE_URL}/rest/api/3/issue/${key}" - - echo "${ACTION_DESC} on ${key} ..." - - code=$(curl -sS -o resp.json -w "%{http_code}" \ - -X PUT "${ISSUE_URL}" \ - --user "$JIRA_AUTH" \ - -H "Accept: application/json" \ - -H "Content-Type: application/json" \ - --data @"${PAYLOAD_FILE}") - - if [ "$code" = "204" ] || [ "$code" = "200" ]; then - echo "OK ${key} (${code})" - ok=$((ok+1)) - - elif [ "$code" = "400" ] && [ "$MODE" = "label" ]; then - # Often returned if label already present; treat as skip for labels - echo "SKIP ${key} (${code}) likely already has the label. First 200 chars:" - head -c 200 resp.json || true; echo - skipped=$((skipped+1)) - - elif [ "$code" = "400" ] && [ "$MODE" = "scylla_component" ]; then - # Option value not valid for scylla_components – log and skip - echo "SKIP ${key} (${code}) invalid Scylla component option. First 200 chars:" - head -c 200 resp.json || true; echo - skipped=$((skipped+1)) - - else - echo "FAIL ${key} (${code}) First 400 chars:" - head -c 400 resp.json || true; echo - failed=$((failed+1)) - fi - - # Gentle pacing - sleep 0.2 - done < keys.txt - - echo "Summary: ok=${ok} skipped=${skipped} failed=${failed}" - if [ "$failed" -gt 0 ]; then - exit 1 - fi diff --git a/.github/workflows/apply_labels_to_pr.yml b/.github/workflows/apply_labels_to_pr.yml deleted file mode 100644 index 51f8758..0000000 --- a/.github/workflows/apply_labels_to_pr.yml +++ /dev/null @@ -1,228 +0,0 @@ -name: Apply Labels to PR - -on: - workflow_call: - inputs: - pr_number: - description: "Pull Request number to label" - type: number - required: true - labels_csv: - description: "Comma-separated labels string (e.g. 'bug, needs-triage, backend')" - type: string - required: true - details_csv: - description: "Full CSV from Jira details (header + rows). Must include 'priority' and 'scylla_components' columns." - type: string - required: true - -permissions: - contents: read - pull-requests: write - issues: write - -jobs: - apply_labels_to_pr: - runs-on: ubuntu-slim - steps: - - name: Prepare labels list (trim, dedupe, ignore empties, compute P* & area/* from Jira) - id: prepare - env: - LABELS_CSV: ${{ inputs.labels_csv }} - DETAILS_CSV: ${{ inputs.details_csv }} - NEW_PRIORITY_LABEL: ${{ github.event.label.name }} - run: | - set -euo pipefail - python3 - <<'PY' - import os, io, csv, re - - pr_number = os.environ.get("PR_NUMBER", "") - labels_csv = os.environ.get("LABELS_CSV", "") - details_csv = os.environ.get("DETAILS_CSV", "") - new_p_label = (os.environ.get("NEW_PRIORITY_LABEL") or "").strip() - - print("======================================================") - print(" Apply Labels to PR — Input Parameters") - print("======================================================") - print(f"PR Number: {pr_number}") - print(f"labels_csv: {labels_csv}") - print(f"NEW_PRIORITY_LABEL (from event): {new_p_label or ''}") - print("details_csv (first 5 lines):") - print("------------------------------------------------------") - for i, line in enumerate(details_csv.splitlines()): - print(line) - if i >= 4: - break - print("------------------------------------------------------\n") - - # 1) Parse labels_csv into a deduped list - raw_labels = [s.strip() for s in labels_csv.split(",")] - seen = set() - labels = [] - for s in raw_labels: - if s and s not in seen: - seen.add(s) - labels.append(s) - - # 2) Remove any existing P0..P4 from this base list - priority_labels = {"P0", "P1", "P2", "P3", "P4"} - labels = [l for l in labels if l not in priority_labels] - - # 3) Prepare to compute Jira-based priority and area/* labels - priority_rank_map = { - "p0": 0, "highest": 0, "blocker": 0, - "p1": 1, "critical": 1, "high": 1, - "p2": 2, "medium": 2, "major": 2, - "p3": 3, "low": 3, "minor": 3, - "p4": 4, "lowest": 4, "trivial": 4, - } - - best_rank = None - area_labels = [] - area_seen = set() - - details_csv = details_csv.strip() - if details_csv: - reader = csv.DictReader(io.StringIO(details_csv)) - for row in reader: - # ----- priority → P* from Jira ----- - prio = (row.get("priority") or "").strip() - if prio: - key = prio.lower() - rank = priority_rank_map.get(key) - if rank is not None: - if best_rank is None or rank < best_rank: - best_rank = rank - - # ----- scylla_components → area/* labels ----- - comp_raw = (row.get("scylla_components") or "").strip() - if comp_raw: - for part in comp_raw.split(";"): - comp = part.strip() - if not comp: - continue - safe = re.sub(r"\s+", "_", comp) - label = f"area/{safe}" - if label not in area_seen: - area_seen.add(label) - area_labels.append(label) - - # 4) Decide which P* to use - priority_label = None - if best_rank is not None: - priority_label = f"P{best_rank}" - - # If the event added a P* label, override Jira priority with it - if new_p_label and re.match(r"(?i)^P[0-4]$", new_p_label): - print(f"Overriding Jira priority with PR-added label: {new_p_label}") - priority_label = new_p_label.upper() - - if priority_label: - print(f"Effective priority label: {priority_label}") - if priority_label not in labels: - labels.insert(0, priority_label) - else: - print("No effective P* priority (from Jira or event); not adding P* label.") - - # 5) Append area/* labels (dedup vs other labels) - for area in area_labels: - if area not in labels: - labels.append(area) - - print("Final labels to apply:", labels) - - with open("labels.txt", "w", encoding="utf-8") as f: - for l in labels: - f.write(l + "\n") - PY - - - - name: Skip if no labels - run: | - if [ ! -s labels.txt ]; then - echo "No labels to apply. Skipping." - exit 0 - fi - - - name: Remove existing P0–P4 labels from PR - env: - GH_TOKEN: ${{ github.token }} - OWNER_REPO: ${{ github.repository }} - PR_NUMBER: "${{ inputs.pr_number }}" - run: | - set -euo pipefail - - ISSUE_API_BASE="https://api.github.com/repos/${OWNER_REPO}/issues/${PR_NUMBER}" - - echo "Fetching existing labels for PR #${PR_NUMBER}..." - curl -sS \ - -H "Authorization: Bearer ${GH_TOKEN}" \ - -H "Accept: application/vnd.github+json" \ - -H "X-GitHub-Api-Version: 2022-11-28" \ - "${ISSUE_API_BASE}/labels" > /tmp/existing_labels.json - - jq -r '.[].name' /tmp/existing_labels.json > existing_labels.txt || true - - # Priority labels we *want* after normalization (from labels.txt) - grep -E '^P[0-4]$' labels.txt > desired_p_labels.txt || true - - echo "Desired priority labels:" - cat desired_p_labels.txt || true - echo "Existing labels on PR:" - cat existing_labels.txt || true - - # If we didn't compute any desired P* label, don't touch existing priorities - if [ ! -s desired_p_labels.txt ]; then - echo "No desired P* labels computed; keeping existing P* labels unchanged." - exit 0 - fi - - for p in P0 P1 P2 P3 P4; do - if grep -qix "$p" existing_labels.txt 2>/dev/null; then - if grep -qix "$p" desired_p_labels.txt 2>/dev/null; then - echo "Keeping existing priority label: $p (also desired)" - else - echo "Removing existing priority label not desired anymore: $p" - code=$(curl -sS -o /tmp/del_resp.json -w "%{http_code}" \ - -X DELETE "${ISSUE_API_BASE}/labels/${p}" \ - -H "Authorization: Bearer ${GH_TOKEN}" \ - -H "Accept: application/vnd.github+json" \ - -H "X-GitHub-Api-Version: 2022-11-28" || true) - echo "Delete $p → HTTP ${code}" - fi - fi - done - - - - name: Add labels (after priority & area/* normalization) - env: - GH_TOKEN: ${{ github.token }} - OWNER_REPO: ${{ github.repository }} - PR_NUMBER: "${{ inputs.pr_number }}" - run: | - set -euo pipefail - ISSUE_API="https://api.github.com/repos/${OWNER_REPO}/issues/${PR_NUMBER}/labels" - - while IFS= read -r LABEL || [ -n "$LABEL" ]; do - LBL="$(echo "$LABEL" | awk '{$1=$1};1')" - [ -z "$LBL" ] && continue - - echo "----------------------------------------" - echo "Applying label: '${LBL}'" - - code=$(curl -sS -o /tmp/add_resp.json -w "%{http_code}" \ - -X POST "${ISSUE_API}" \ - -H "Authorization: Bearer ${GH_TOKEN}" \ - -H "Accept: application/vnd.github+json" \ - -H "Content-Type: application/json; charset=utf-8" \ - -H "X-GitHub-Api-Version: 2022-11-28" \ - --data "{\"labels\": [\"${LBL}\"]}" || true) - - if [ "${code}" = "200" ] || [ "${code}" = "201" ]; then - echo "Result: success (HTTP ${code})." - else - echo "Result: failed (HTTP ${code}). Body (first 200 chars):" - head -c 200 /tmp/add_resp.json || true - echo - fi - done < labels.txt diff --git a/.github/workflows/extract_jira_issue_details.yml b/.github/workflows/extract_jira_issue_details.yml deleted file mode 100644 index 83cb829..0000000 --- a/.github/workflows/extract_jira_issue_details.yml +++ /dev/null @@ -1,152 +0,0 @@ -name: Extract Jira Issue Details (CSV - per issue) - -on: - workflow_call: - inputs: - jira_keys_json: - description: 'JSON array of Jira keys, e.g. ["PROJ-1","PROJ-2"]' - required: true - type: string - secrets: - jira_auth: - description: 'Authorization credential: "email:api_token" for Basic, or "Bearer "' - required: true - outputs: - csv: - description: 'Full CSV content (header + rows)' - value: ${{ jobs.build_csv_with_jira_data.outputs.csv }} - csv_path: - description: 'Path to CSV artifact (downloaded filename)' - value: ${{ jobs.build_csv_with_jira_data.outputs.csv_path }} - labels_csv: - description: 'Deduped CSV of all labels across issues (no header)' - value: ${{ jobs.build_csv_with_jira_data.outputs.labels_csv }} - -jobs: - build_csv_with_jira_data: - runs-on: ubuntu-slim - outputs: - csv: ${{ steps.makecsv.outputs.csv }} - csv_path: ${{ steps.artifacts-out.outputs.csv_path }} - labels_csv: ${{ steps.fetch.outputs.labels_csv }} - - env: - JIRA_BASE_URL: https://scylladb.atlassian.net - SCYLLA_COMPONENTS_FIELD: customfield_10321 - START_DATE_FIELD: customfield_10015 - DUE_DATE_FIELD: duedate - DELIM: ";" - - steps: - - name: Validate input keys - id: validate - shell: bash - run: | - keys='${{ inputs.jira_keys_json }}' - if [ -z "$keys" ] || [ "$keys" = "[]" ] || [ "$keys" = '[""]' ] || [[ "$keys" == '["__NO_KEYS_FOUND__"]' ]]; then - echo "empty_keys=true" >> "$GITHUB_OUTPUT" - else - echo "empty_keys=false" >> "$GITHUB_OUTPUT" - fi - - - name: Short-circuit on no keys - if: ${{ steps.validate.outputs.empty_keys == 'true' }} - id: makecsv-empty - shell: bash - run: | - echo "csv=" >> "$GITHUB_OUTPUT" - echo "labels_csv=" >> "$GITHUB_OUTPUT" - printf "key,status,labels,assignee,priority,fixVersions,scylla_components,startDate,dueDate\n" > jira-details.csv - echo "csv_path=jira-details.csv" >> "$GITHUB_OUTPUT" - - echo "---------------------------------------------------" - echo "Generated CSV (empty-keys short-circuit):" - echo "---------------------------------------------------" - cat jira-details.csv - echo "---------------------------------------------------" - - - name: Fetch issues one by one - if: ${{ steps.validate.outputs.empty_keys != 'true' }} - id: fetch - shell: bash - env: - BASE: ${{ env.JIRA_BASE_URL }} - FIELD_ID: ${{ env.SCYLLA_COMPONENTS_FIELD }} - START_DATE_FIELD: ${{ env.START_DATE_FIELD }} - DUE_DATE_FIELD: ${{ env.DUE_DATE_FIELD }} - JIRA_AUTH: ${{ secrets.jira_auth }} - KEYS_JSON: ${{ inputs.jira_keys_json }} - DELIM: ${{ env.DELIM }} - run: | - set -euo pipefail - printf "key,status,labels,assignee,priority,fixVersions,scylla_components,startDate,dueDate\n" > jira-details.csv - - keys=$(echo "$KEYS_JSON" | jq -r '.[]') - all_labels=() - - for key in $keys; do - echo "Fetching Jira issue: $key" - - resp=$(curl -sS --fail \ - --user "$JIRA_AUTH" \ - -H "Accept: application/json" \ - "$BASE/rest/api/3/issue/$key?fields=status,labels,assignee,priority,fixVersions,${FIELD_ID},${START_DATE_FIELD},${DUE_DATE_FIELD}") - - status=$(echo "$resp" | jq -r '.fields.status.name // ""') - assignee=$(echo "$resp" | jq -r '.fields.assignee.displayName // ""') - priority=$(echo "$resp" | jq -r '.fields.priority.name // ""') - labels=$(echo "$resp" | jq -r --arg d "$DELIM" '(.fields.labels // []) | join($d)') - fixVersions=$(echo "$resp" | jq -r --arg d "$DELIM" '(.fields.fixVersions // []) | map(.name // "") | join($d)') - components=$(echo "$resp" | jq -r --arg d "$DELIM" --arg f "$FIELD_ID" ' - (.fields[$f] // []) - | if type=="array" then (map(.value // "") | join($d)) else (tostring) end - ') - startDate=$(echo "$resp" | jq -r --arg f "$START_DATE_FIELD" '.fields[$f] // ""') - dueDate=$(echo "$resp" | jq -r --arg f "$DUE_DATE_FIELD" '.fields[$f] // ""') - - # Append line to CSV - echo "\"$key\",\"$status\",\"$labels\",\"$assignee\",\"$priority\",\"$fixVersions\",\"$components\",\"$startDate\",\"$dueDate\"" >> jira-details.csv - - # Collect labels for aggregation - mapfile -t lbls < <(echo "$resp" | jq -r '.fields.labels[]?') - all_labels+=("${lbls[@]}") - done - - # Deduplicate and join all labels - if [ ${#all_labels[@]} -gt 0 ]; then - deduped=$(printf "%s\n" "${all_labels[@]}" | sort -u | paste -sd, -) - else - deduped="" - fi - echo "labels_csv=$deduped" >> "$GITHUB_OUTPUT" - - echo "---------------------------------------------------" - echo "Generated CSV (after fetching issues):" - echo "Showing first 20 lines:" - echo "---------------------------------------------------" - head -n 20 jira-details.csv - echo "---------------------------------------------------" - - - - name: Collect CSV content - if: ${{ steps.validate.outputs.empty_keys != 'true' }} - id: makecsv - shell: bash - run: | - csv_content=$(cat jira-details.csv) - echo "csv<> "$GITHUB_OUTPUT" - echo "$csv_content" >> "$GITHUB_OUTPUT" - echo "EOF" >> "$GITHUB_OUTPUT" - - - name: Upload CSV artifact - id: artifacts - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 - with: - name: jira-details-csv - path: jira-details.csv - - - name: Set csv_path output - id: artifacts-out - shell: bash - run: | - echo "csv_path=jira-details.csv" >> "$GITHUB_OUTPUT" diff --git a/.github/workflows/extract_jira_keys.yml b/.github/workflows/extract_jira_keys.yml deleted file mode 100644 index 661309e..0000000 --- a/.github/workflows/extract_jira_keys.yml +++ /dev/null @@ -1,153 +0,0 @@ -name: Extract Jira Keys - -on: - workflow_call: - inputs: - pr_title: - required: true - type: string - pr_body: - required: true - type: string - secrets: - jira_auth: - description: 'Authorization credential: "email:api_token" for Basic, or "Bearer "' - required: true - outputs: - jira-keys-json: - description: "JSON array of Jira keys" - value: ${{ jobs.extract_jira_keys_from_pr.outputs.jira-keys-json }} - -jobs: - extract_jira_keys_from_pr: - runs-on: ubuntu-slim - outputs: - jira-keys-json: ${{ steps.process.outputs.jira-keys-json }} - - steps: - - id: save - shell: bash - run: | - # Save PR title/body into files (no env injection) - cat > pr_title.txt <<'EOF' - ${{ inputs.pr_title }} - EOF - - cat > pr_body.txt <<'EOF' - ${{ inputs.pr_body }} - EOF - - - id: process - shell: bash - env: - JIRA_AUTH: ${{ secrets.jira_auth }} - run: | - set -euo pipefail - - # Remove backticks and \r before locating jira keys - title=$(tr -d '\r' < pr_title.txt | tr '\`' ' ') - body=$(tr -d '\r' < pr_body.txt | tr '\`' ' ') - - echo "title: $title" - echo "body: $body" - - > tickets.txt - printf '%s\n' "$title" | grep -oE '[A-Z]+-[0-9]+' >> tickets.txt || true - - printf '%s\n' "$body" | grep -iE '(close|closes|closed|fix|fixes|fixed|resolve|resolves|resolved)[[:space:]]*[: ][[:space:]]*\[?[[:space:]]*((https?://[^[:space:]]*/browse/)?[A-Z]+-[0-9]+)' \ - | grep -oE '[A-Z]+-[0-9]+' >> tickets.txt || true - - sort -u tickets.txt > candidate_tickets.txt - - if [[ ! -s candidate_tickets.txt ]]; then - echo "No Jira-like keys found in PR title or body" - echo 'jira-keys-json=["__NO_KEYS_FOUND__"]' >> "$GITHUB_OUTPUT" - exit 0 - fi - - echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" - echo "Candidate keys:" - cat candidate_tickets.txt || true - echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" - - # ------------------------------------------------------------------ - # 1) Hard-coded list of known Jira project keys (prefixes) - # ------------------------------------------------------------------ - # Edit this list to match your common Jira projects: - # e.g. KNOWN_PROJECT_PREFIXES="SCYLLA STAG DOCS ENG" - KNOWN_PROJECT_PREFIXES="RELENG CLOUD SCYLLADB PKG PM CUSTOMER VECTOR ANSROLES CLOUDEVOPS CXTOOLS DOCTOR FIELDAUTO FIELDENG ILIAD OPERATOR PKGDASH PUB SMI WEBINSTALL STAG" - - echo "Known project prefixes (hard-coded): $KNOWN_PROJECT_PREFIXES" - - # Write known prefixes (one per line) - printf "%s\n" $KNOWN_PROJECT_PREFIXES | sort -u > hardcoded_project_keys.txt - - > unique_tickets.txt - > unknown_prefix_candidates.txt - - # First pass: use only hard-coded project prefixes - while read -r key; do - [ -z "$key" ] && continue - prefix="${key%%-*}" - - if grep -qx "$prefix" hardcoded_project_keys.txt; then - echo "Accepting $key via hard-coded prefix '$prefix'." - echo "$key" >> unique_tickets.txt - else - echo "Deferring $key — prefix '$prefix' not in hard-coded list." - echo "$key" >> unknown_prefix_candidates.txt - fi - done < candidate_tickets.txt - - # ------------------------------------------------------------------ - # 2) Only if we still have keys with unknown prefixes, query Jira - # ------------------------------------------------------------------ - if [[ -s unknown_prefix_candidates.txt ]]; then - echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" - echo "Some prefixes not in hard-coded list; querying Jira for project keys..." - echo "Unknown-prefix candidates:" - cat unknown_prefix_candidates.txt || true - - project_resp=$(curl -sS --fail \ - --user "$JIRA_AUTH" \ - -H "Accept: application/json" \ - "https://scylladb.atlassian.net/rest/api/3/project/search?maxResults=1000") - - echo "$project_resp" | jq -r '.values[].key' | sort -u > jira_project_keys.txt - - echo "Valid Jira project keys from API (first 20):" - head -n 20 jira_project_keys.txt || true - - # Second pass: validate unknown prefixes against Jira project list - while read -r key; do - [ -z "$key" ] && continue - prefix="${key%%-*}" - - if grep -qx "$prefix" jira_project_keys.txt; then - echo "Accepting $key via Jira API (valid project prefix '$prefix')." - echo "$key" >> unique_tickets.txt - else - echo "Skipping $key — unknown project prefix '$prefix' (not in Jira)." - fi - done < unknown_prefix_candidates.txt - else - echo "All prefixes resolved via hard-coded list; no Jira project lookup needed." - fi - - echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" - - # Final result set - if [[ ! -s unique_tickets.txt ]]; then - echo "No valid Jira keys found after validation" - echo 'jira-keys-json=["__NO_KEYS_FOUND__"]' >> "$GITHUB_OUTPUT" - else - sort -u unique_tickets.txt -o unique_tickets.txt - echo "Final Jira keys:" - cat unique_tickets.txt - - json=$(awk '{printf "\"%s\",",$1}' unique_tickets.txt | sed 's/,$//') - json="[${json}]" - - echo "jira-keys-json=$json" >> "$GITHUB_OUTPUT" - - fi diff --git a/.github/workflows/jira_transition.yml b/.github/workflows/jira_transition.yml deleted file mode 100644 index 59fbdff..0000000 --- a/.github/workflows/jira_transition.yml +++ /dev/null @@ -1,249 +0,0 @@ -name: Jira Transition (from CSV) - -on: - workflow_call: - inputs: - # Full CSV text from the details job (header + rows). - # Expected columns include: key,status,labels,assignee,priority,fixVersions,scylla_components - details_csv: - required: true - type: string - transition_name: - required: true - type: string - transition_id: - required: true - type: string - secrets: - jira_auth: - required: true - -jobs: - transition_jira_status: - runs-on: ubuntu-slim - env: - JIRA_BASE_URL: https://scylladb.atlassian.net - START_DATE_FIELD: customfield_10015 - DUE_DATE_FIELD: duedate - - steps: - - name: Write CSV to file - shell: bash - run: | - cat > details.csv <<'CSV_EOF' - ${{ inputs.details_csv }} - CSV_EOF - echo "Wrote details.csv" - head -n 5 details.csv || true - - - name: Plan transitions (parse CSV) - id: plan - shell: bash - env: - TARGET: ${{ inputs.transition_name }} - run: | - set -euo pipefail - python3 - <<'PY' - import csv, sys, io, os - - target = os.environ['TARGET'] - to_transition = [] # list of (key, current_status) - already_ok = [] # list of (key, current_status) - done_issues = [] # list of (key, current_status == Done) - - with open('details.csv', newline='', encoding='utf-8') as f: - reader = csv.DictReader(f) - # Normalize headers - fieldmap = { (h or '').strip().lower(): h for h in reader.fieldnames or [] } - def get(row, name): - h = fieldmap.get(name.lower()) - return (row.get(h) or "").strip() if h else "" - - for row in reader: - key = get(row, 'key') - status = get(row, 'status') - start_date = get(row, 'startdate') - due_date = get(row, 'duedate') - if not key: - continue - - # Skip already correct or Done issues - if status.lower() == target.lower(): - already_ok.append((key, status)) - elif status.lower() in {"done", "duplicate", "won't fix"}: - done_issues.append((key, status)) - else: - to_transition.append((key, status, start_date, due_date)) - - # Write plan files - def write_list(fname, items): - with open(fname, 'w', encoding='utf-8') as out: - for item in items: - if len(item) == 4: - k, s, sd, dd = item - out.write(f"{k}|{s}|{sd}|{dd}\n") - else: - k, s = item - out.write(f"{k}|{s}\n") - - write_list('to_transition.txt', to_transition) - write_list('already_ok.txt', already_ok) - write_list('done_issues.txt', done_issues) - - print(f"{len(to_transition)} need transition, {len(already_ok)} already OK, {len(done_issues)} are Done.", file=sys.stderr) - PY - - echo "----- Already OK (up to 10) -----" - head -n 10 already_ok.txt || true - echo "----- Done issues (up to 10) -----" - head -n 10 done_issues.txt || true - echo "----- Need Transition (up to 10) -----" - head -n 10 to_transition.txt || true - - - name: Show intent summary - shell: bash - env: - TARGET: ${{ inputs.transition_name }} - run: | - need=$(wc -l < to_transition.txt 2>/dev/null || echo 0) - ok=$(wc -l < already_ok.txt 2>/dev/null || echo 0) - done=$(wc -l < done_issues.txt 2>/dev/null || echo 0) - echo "Target status: ${TARGET}" - echo "Issues already at target: ${ok}" - echo "Issues in 'Done' state: ${done}" - echo "Issues to transition: ${need}" - - - name: Transition issues - if: ${{ always() }} - shell: bash - env: - JIRA_AUTH: ${{ secrets.jira_auth }} - TARGET: ${{ inputs.transition_name }} - TRANSITION_ID: ${{ inputs.transition_id }} - BASE: ${{ env.JIRA_BASE_URL }} - START_DATE_FIELD: ${{ env.START_DATE_FIELD }} - DUE_DATE_FIELD: ${{ env.DUE_DATE_FIELD }} - run: | - set -euo pipefail - - if [ ! -s to_transition.txt ]; then - echo "No issues require transition. Done." - exit 0 - fi - - if [ -z "${JIRA_AUTH:-}" ]; then - echo "ERROR: jira_auth secret not set." >&2 - exit 1 - fi - - while IFS='|' read -r key current start_date due_date; do - [ -n "${key:-}" ] || continue - echo "Transitioning ${key} from '${current}' -> '${TARGET}' (id=${TRANSITION_ID})" - - # Check if transitioning to a working state and if start date needs to be set - WORKING_STATES=("in progress" "in review" "ready for merge") - SET_START_DATE=false - for state in "${WORKING_STATES[@]}"; do - if [[ "${TARGET,,}" == "$state" ]]; then - SET_START_DATE=true - break - fi - done - - # If transitioning to working state and start date is empty, set it - if [ "$SET_START_DATE" = true ]; then - if [ -z "$start_date" ] || [ "$start_date" = "null" ]; then - TODAY=$(date -u +%Y-%m-%d) - echo "Setting start date to ${TODAY} for ${key} (field: ${START_DATE_FIELD})" - - if [[ "$JIRA_AUTH" == Bearer\ * ]]; then - RESPONSE=$(curl -sS -w "\n%{http_code}" -X PUT \ - -H "Authorization: $JIRA_AUTH" \ - -H "Accept: application/json" \ - -H "Content-Type: application/json" \ - --data "{\"fields\": {\"${START_DATE_FIELD}\": \"${TODAY}\"}}" \ - "${BASE}/rest/api/3/issue/${key}" 2>&1) - else - RESPONSE=$(curl -sS -w "\n%{http_code}" -X PUT \ - --user "$JIRA_AUTH" \ - -H "Accept: application/json" \ - -H "Content-Type: application/json" \ - --data "{\"fields\": {\"${START_DATE_FIELD}\": \"${TODAY}\"}}" \ - "${BASE}/rest/api/3/issue/${key}" 2>&1) - fi - - HTTP_CODE=$(echo "$RESPONSE" | tail -n1) - if [ "$HTTP_CODE" != "204" ]; then - echo "Warning: Failed to set start date for ${key} (HTTP ${HTTP_CODE})" >&2 - echo "$RESPONSE" | head -n-1 >&2 - fi - sleep 0.2 - else - echo "Start date already set for ${key}: ${start_date}" - fi - fi - - # Check if transitioning to a closed state and if due date needs to be set - CLOSED_STATES=("done" "won't fix") - SET_DUE_DATE=false - for state in "${CLOSED_STATES[@]}"; do - if [[ "${TARGET,,}" == "$state" ]]; then - SET_DUE_DATE=true - break - fi - done - - # If transitioning to closed state and due date is empty, set it - if [ "$SET_DUE_DATE" = true ]; then - if [ -z "$due_date" ] || [ "$due_date" = "null" ]; then - TODAY=$(date -u +%Y-%m-%d) - echo "Setting due date to ${TODAY} for ${key} (field: ${DUE_DATE_FIELD})" - - if [[ "$JIRA_AUTH" == Bearer\ * ]]; then - RESPONSE=$(curl -sS -w "\n%{http_code}" -X PUT \ - -H "Authorization: $JIRA_AUTH" \ - -H "Accept: application/json" \ - -H "Content-Type: application/json" \ - --data "{\"fields\": {\"${DUE_DATE_FIELD}\": \"${TODAY}\"}}" \ - "${BASE}/rest/api/3/issue/${key}" 2>&1) - else - RESPONSE=$(curl -sS -w "\n%{http_code}" -X PUT \ - --user "$JIRA_AUTH" \ - -H "Accept: application/json" \ - -H "Content-Type: application/json" \ - --data "{\"fields\": {\"${DUE_DATE_FIELD}\": \"${TODAY}\"}}" \ - "${BASE}/rest/api/3/issue/${key}" 2>&1) - fi - - HTTP_CODE=$(echo "$RESPONSE" | tail -n1) - if [ "$HTTP_CODE" != "204" ]; then - echo "Warning: Failed to set due date for ${key} (HTTP ${HTTP_CODE})" >&2 - echo "$RESPONSE" | head -n-1 >&2 - fi - sleep 0.2 - else - echo "Due date already set for ${key}: ${due_date}" - fi - fi - - if [[ "$JIRA_AUTH" == Bearer\ * ]]; then - curl -sS --fail -X POST \ - -H "Authorization: $JIRA_AUTH" \ - -H "Accept: application/json" \ - -H "Content-Type: application/json" \ - --data "{\"transition\": {\"id\": \"${TRANSITION_ID}\"}}" \ - "${BASE}/rest/api/3/issue/${key}/transitions" \ - || { echo "Failed to transition ${key}" >&2; exit 1; } - else - curl -sS --fail -X POST \ - --user "$JIRA_AUTH" \ - -H "Accept: application/json" \ - -H "Content-Type: application/json" \ - --data "{\"transition\": {\"id\": \"${TRANSITION_ID}\"}}" \ - "${BASE}/rest/api/3/issue/${key}/transitions" \ - || { echo "Failed to transition ${key}" >&2; exit 1; } - fi - - # Gentle rate limit - sleep 0.2 - done < to_transition.txt diff --git a/.github/workflows/main_create_jira_issue_from_gh_issue.yml b/.github/workflows/main_create_jira_issue_from_gh_issue.yml deleted file mode 100644 index 06c5848..0000000 --- a/.github/workflows/main_create_jira_issue_from_gh_issue.yml +++ /dev/null @@ -1,47 +0,0 @@ -name: Sync GitHub Issue to Jira - -on: - workflow_call: - inputs: - jira_project_key: - description: "Jira project key (e.g. MONITOR)" - required: true - type: string - secrets: - caller_jira_auth: - description: "Plain 'email:api_token' for Jira Cloud Basic auth" - required: true - -jobs: - sync-issue-to-jira: - if: github.event.action == 'opened' - name: "Create Jira issue from GH #${{ github.event.issue.number }}" - runs-on: ubuntu-slim - permissions: - contents: read - issues: write - steps: - - name: Checkout automation repo - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 - with: - repository: scylladb/github-automation - ref: main - - - name: Create Jira issue and cross-link - env: - JIRA_AUTH: ${{ secrets.caller_jira_auth }} - JIRA_PROJECT_KEY: ${{ inputs.jira_project_key }} - GITHUB_TOKEN: ${{ github.token }} - OWNER_REPO: ${{ github.repository }} - ISSUE_TITLE: ${{ github.event.issue.title }} - ISSUE_BODY: ${{ github.event.issue.body }} - ISSUE_NUMBER: ${{ github.event.issue.number }} - ISSUE_HTML_URL: ${{ github.event.issue.html_url }} - ISSUE_LABELS: ${{ join(github.event.issue.labels.*.name, ',') }} - ISSUE_TYPE: ${{ github.event.issue.type.name || '' }} - ISSUE_MILESTONE: ${{ github.event.issue.milestone.title || '' }} - GH_ASSIGNEE_LOGIN: ${{ github.event.issue.assignee.login || '' }} - GH_ASSIGNEE_NAME: ${{ github.event.issue.assignee.name || github.event.issue.assignee.login || '' }} - GH_REPORTER_LOGIN: ${{ github.event.issue.user.login || '' }} - GH_REPORTER_NAME: ${{ github.event.issue.user.name || github.event.issue.user.login || '' }} - run: python3 scripts/create_jira_issue_from_gh_issue.py \ No newline at end of file diff --git a/.github/workflows/main_jira_sync_add_label.yml b/.github/workflows/main_jira_sync_add_label.yml deleted file mode 100644 index 767e24f..0000000 --- a/.github/workflows/main_jira_sync_add_label.yml +++ /dev/null @@ -1,32 +0,0 @@ -name: Sync With Jira - Add Label - -on: - workflow_call: - secrets: - caller_jira_auth: - required: true - -jobs: - manage_labeled_gh_event: - runs-on: ubuntu-slim - permissions: - contents: read - pull-requests: write - issues: write - steps: - - name: Checkout repository - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 - with: - repository: scylladb/github-automation - ref: main - - - name: Run label-sync orchestrator - env: - PR_TITLE: ${{ github.event.pull_request.title }} - PR_BODY: ${{ github.event.pull_request.body }} - PR_NUMBER: ${{ github.event.pull_request.number }} - TRIGGERING_LABEL: ${{ github.event.label.name }} - OWNER_REPO: ${{ github.repository }} - GITHUB_TOKEN: ${{ github.token }} - JIRA_AUTH: ${{ secrets.caller_jira_auth }} - run: python3 scripts/jira_sync_logic.py --action manage_labeled_gh_event diff --git a/.github/workflows/main_jira_sync_in_review.yml b/.github/workflows/main_jira_sync_in_review.yml deleted file mode 100644 index 453b905..0000000 --- a/.github/workflows/main_jira_sync_in_review.yml +++ /dev/null @@ -1,32 +0,0 @@ -name: Sync with Jira - In Review - -on: - workflow_call: - secrets: - caller_jira_auth: - required: true - -jobs: - manage_review_gh_event: - runs-on: ubuntu-slim - permissions: - contents: read - pull-requests: write - issues: write - steps: - - name: Checkout repository - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 - with: - repository: scylladb/github-automation - ref: main - - - name: Run in-review orchestrator - env: - PR_TITLE: ${{ github.event.pull_request.title }} - PR_BODY: ${{ github.event.pull_request.body }} - PR_NUMBER: ${{ github.event.pull_request.number }} - OWNER_REPO: ${{ github.repository }} - REQUESTED_REVIEWER: ${{ github.event.requested_reviewer.login }} - GITHUB_TOKEN: ${{ github.token }} - JIRA_AUTH: ${{ secrets.caller_jira_auth }} - run: python3 scripts/jira_sync_logic.py --action manage_review_gh_event diff --git a/.github/workflows/main_jira_sync_pr_closed.yml b/.github/workflows/main_jira_sync_pr_closed.yml deleted file mode 100644 index ef2421f..0000000 --- a/.github/workflows/main_jira_sync_pr_closed.yml +++ /dev/null @@ -1,32 +0,0 @@ -name: Sync with Jira - PR Closed - -on: - workflow_call: - secrets: - caller_jira_auth: - required: true - -jobs: - manage_closed_gh_event: - runs-on: ubuntu-slim - permissions: - contents: read - pull-requests: write - issues: write - steps: - - name: Checkout repository - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 - with: - repository: scylladb/github-automation - ref: main - - - name: Run pr-closed orchestrator - env: - PR_TITLE: ${{ github.event.pull_request.title }} - PR_BODY: ${{ github.event.pull_request.body }} - PR_NUMBER: ${{ github.event.pull_request.number }} - PR_MERGED: ${{ github.event.pull_request.merged }} - OWNER_REPO: ${{ github.repository }} - GITHUB_TOKEN: ${{ github.token }} - JIRA_AUTH: ${{ secrets.caller_jira_auth }} - run: python3 scripts/jira_sync_logic.py --action manage_closed_gh_event diff --git a/.github/workflows/main_jira_sync_pr_milestone_removed.yml b/.github/workflows/main_jira_sync_pr_milestone_removed.yml deleted file mode 100644 index d51d25d..0000000 --- a/.github/workflows/main_jira_sync_pr_milestone_removed.yml +++ /dev/null @@ -1,140 +0,0 @@ -name: Sync With Jira - PR Milestone Removed - -on: - workflow_call: - secrets: - caller_jira_auth: - required: true - -jobs: - extract: - uses: scylladb/github-automation/.github/workflows/extract_jira_keys.yml@automation-staging-branch - with: - pr_title: ${{ github.event.pull_request.title }} - pr_body: ${{ github.event.pull_request.body }} - secrets: - jira_auth: ${{ secrets.caller_jira_auth }} - - debug: - needs: extract - runs-on: ubuntu-slim - steps: - - name: Debug data - env: - GITHUB_CONTEXT: ${{ toJson(github) }} - run: | - echo "event_name='${{ github.event_name }}'" - echo "action='${{ github.event.action }}'" - echo "removed_milestone_title='${{ github.event.milestone.title }}'" - echo "jira-keys-json='${{ needs.extract.outputs['jira-keys-json'] }}'" - echo "~~~~~~~~~~~ GitHub Context ~~~~~~~~~~~" - echo "$GITHUB_CONTEXT" - - remove_fix_versions: - needs: extract - runs-on: ubuntu-slim - env: - JIRA_BASE_URL: https://scylladb.atlassian.net - JIRA_AUTH: ${{ secrets.caller_jira_auth }} - MILESTONE_TITLE: ${{ github.event.milestone.title }} - JIRA_KEYS_JSON: ${{ needs.extract.outputs['jira-keys-json'] }} - - steps: - - name: Remove Fix Versions from Jira issues - shell: bash - run: | - set -euo pipefail - - if [ -z "${JIRA_AUTH:-}" ]; then - echo "ERROR: jira_auth secret is not set." - exit 1 - fi - - if [ -z "${MILESTONE_TITLE:-}" ]; then - echo "ERROR: No milestone title found." - exit 1 - fi - - echo "Milestone to remove: ${MILESTONE_TITLE}" - echo "Jira keys JSON: ${JIRA_KEYS_JSON}" - - # Parse the JSON array of Jira keys - KEYS=$(echo "$JIRA_KEYS_JSON" | jq -r '.[]') - - if [ "$KEYS" = "__NO_KEYS_FOUND__" ] || [ -z "$KEYS" ]; then - echo "No valid Jira keys found in PR. Skipping." - exit 0 - fi - - ok=0 - skipped=0 - failed=0 - - for KEY in $KEYS; do - echo "======================================================" - echo "Processing Jira issue: ${KEY}" - echo "======================================================" - - # Get current issue to check existing Fix Versions - ISSUE_RESP=$(curl -sS -w "\n%{http_code}" \ - --user "${JIRA_AUTH}" \ - -H "Accept: application/json" \ - "${JIRA_BASE_URL}/rest/api/3/issue/${KEY}?fields=fixVersions") - - HTTP_CODE=$(echo "$ISSUE_RESP" | tail -1) - BODY=$(echo "$ISSUE_RESP" | sed '$d') - - if [ "$HTTP_CODE" != "200" ]; then - echo "FAIL: Could not fetch issue ${KEY} (HTTP ${HTTP_CODE})" - echo "$BODY" - failed=$((failed+1)) - continue - fi - - # Check if the milestone version exists in Fix Versions - EXISTING_VERSIONS=$(echo "$BODY" | jq -r '.fields.fixVersions[]?.name // empty') - - if ! echo "$EXISTING_VERSIONS" | grep -qx "$MILESTONE_TITLE"; then - echo "SKIP: Version '${MILESTONE_TITLE}' not found in Fix Versions for ${KEY}" - skipped=$((skipped+1)) - continue - fi - - # Remove the milestone from Fix Versions - UPDATE_PAYLOAD=$(jq -n --arg name "$MILESTONE_TITLE" ' - { - "update": { - "fixVersions": [ - { "remove": { "name": $name } } - ] - } - } - ') - - UPDATE_RESP=$(curl -sS -w "\n%{http_code}" \ - -X PUT "${JIRA_BASE_URL}/rest/api/3/issue/${KEY}" \ - --user "${JIRA_AUTH}" \ - -H "Accept: application/json" \ - -H "Content-Type: application/json" \ - --data "$UPDATE_PAYLOAD") - - UPDATE_HTTP=$(echo "$UPDATE_RESP" | tail -1) - UPDATE_BODY=$(echo "$UPDATE_RESP" | sed '$d') - - if [ "$UPDATE_HTTP" = "204" ] || [ "$UPDATE_HTTP" = "200" ]; then - echo "OK: Removed '${MILESTONE_TITLE}' from Fix Versions for ${KEY}" - ok=$((ok+1)) - else - echo "FAIL: Could not remove Fix Version for ${KEY} (HTTP ${UPDATE_HTTP})" - echo "$UPDATE_BODY" - failed=$((failed+1)) - fi - done - - echo "======================================================" - echo "Summary: ok=${ok} skipped=${skipped} failed=${failed}" - echo "======================================================" - - if [ "$failed" -gt 0 ]; then - exit 1 - fi diff --git a/.github/workflows/main_jira_sync_pr_milestone_set.yml b/.github/workflows/main_jira_sync_pr_milestone_set.yml deleted file mode 100644 index 4a4708e..0000000 --- a/.github/workflows/main_jira_sync_pr_milestone_set.yml +++ /dev/null @@ -1,159 +0,0 @@ -name: Sync With Jira - PR Milestone Set - -on: - workflow_call: - secrets: - caller_jira_auth: - required: true - -jobs: - extract: - uses: scylladb/github-automation/.github/workflows/extract_jira_keys.yml@automation-staging-branch - with: - pr_title: ${{ github.event.pull_request.title }} - pr_body: ${{ github.event.pull_request.body }} - secrets: - jira_auth: ${{ secrets.caller_jira_auth }} - - debug: - needs: extract - runs-on: ubuntu-slim - steps: - - name: Debug data - env: - GITHUB_CONTEXT: ${{ toJson(github) }} - run: | - echo "event_name='${{ github.event_name }}'" - echo "action='${{ github.event.action }}'" - echo "milestone_title='${{ github.event.pull_request.milestone.title }}'" - echo "jira-keys-json='${{ needs.extract.outputs['jira-keys-json'] }}'" - echo "~~~~~~~~~~~ GitHub Context ~~~~~~~~~~~" - echo "$GITHUB_CONTEXT" - - update_fix_versions: - needs: extract - runs-on: ubuntu-slim - env: - JIRA_BASE_URL: https://scylladb.atlassian.net - JIRA_AUTH: ${{ secrets.caller_jira_auth }} - MILESTONE_TITLE: ${{ github.event.pull_request.milestone.title }} - JIRA_KEYS_JSON: ${{ needs.extract.outputs['jira-keys-json'] }} - - steps: - - name: Replace Fix Versions in Jira issues - shell: bash - run: | - set -euo pipefail - - if [ -z "${JIRA_AUTH:-}" ]; then - echo "ERROR: jira_auth secret is not set." - exit 1 - fi - - if [ -z "${MILESTONE_TITLE:-}" ]; then - echo "ERROR: No milestone title found." - exit 1 - fi - - echo "Milestone title: ${MILESTONE_TITLE}" - echo "Jira keys JSON: ${JIRA_KEYS_JSON}" - - # Parse the JSON array of Jira keys - KEYS=$(echo "$JIRA_KEYS_JSON" | jq -r '.[]') - - if [ "$KEYS" = "__NO_KEYS_FOUND__" ] || [ -z "$KEYS" ]; then - echo "No valid Jira keys found in PR. Skipping." - exit 0 - fi - - ok=0 - skipped=0 - failed=0 - - for KEY in $KEYS; do - echo "======================================================" - echo "Processing Jira issue: ${KEY}" - echo "======================================================" - - # Get the project key from the issue key - PROJECT_KEY="${KEY%%-*}" - - # First, ensure the version exists in the project - VERSION_CHECK=$(curl -sS -w "\n%{http_code}" \ - --user "${JIRA_AUTH}" \ - -H "Accept: application/json" \ - "${JIRA_BASE_URL}/rest/api/3/project/${PROJECT_KEY}/versions") - - VC_HTTP=$(echo "$VERSION_CHECK" | tail -1) - VC_BODY=$(echo "$VERSION_CHECK" | sed '$d') - - VERSION_EXISTS=false - if [ "$VC_HTTP" = "200" ]; then - if echo "$VC_BODY" | jq -e ".[] | select(.name == \"$MILESTONE_TITLE\")" > /dev/null 2>&1; then - VERSION_EXISTS=true - fi - fi - - if [ "$VERSION_EXISTS" = "false" ]; then - echo "Version '${MILESTONE_TITLE}' does not exist in project ${PROJECT_KEY}. Creating it..." - - CREATE_RESP=$(curl -sS -w "\n%{http_code}" \ - -X POST "${JIRA_BASE_URL}/rest/api/3/version" \ - --user "${JIRA_AUTH}" \ - -H "Accept: application/json" \ - -H "Content-Type: application/json" \ - --data "{\"name\": \"${MILESTONE_TITLE}\", \"project\": \"${PROJECT_KEY}\"}") - - CREATE_HTTP=$(echo "$CREATE_RESP" | tail -1) - CREATE_BODY=$(echo "$CREATE_RESP" | sed '$d') - - if [ "$CREATE_HTTP" = "201" ] || [ "$CREATE_HTTP" = "200" ]; then - echo "Created version '${MILESTONE_TITLE}' in project ${PROJECT_KEY}" - elif [ "$CREATE_HTTP" = "400" ]; then - # Might already exist (race condition or case sensitivity) - echo "Version might already exist (HTTP 400). Proceeding with update..." - else - echo "WARNING: Could not create version (HTTP ${CREATE_HTTP}): $CREATE_BODY" - fi - fi - - # Replace Fix Versions - SET to only the new milestone (removes all existing) - UPDATE_PAYLOAD=$(jq -n --arg name "$MILESTONE_TITLE" ' - { - "fields": { - "fixVersions": [ - { "name": $name } - ] - } - } - ') - - echo "Replacing Fix Versions with: ${MILESTONE_TITLE}" - - UPDATE_RESP=$(curl -sS -w "\n%{http_code}" \ - -X PUT "${JIRA_BASE_URL}/rest/api/3/issue/${KEY}" \ - --user "${JIRA_AUTH}" \ - -H "Accept: application/json" \ - -H "Content-Type: application/json" \ - --data "$UPDATE_PAYLOAD") - - UPDATE_HTTP=$(echo "$UPDATE_RESP" | tail -1) - UPDATE_BODY=$(echo "$UPDATE_RESP" | sed '$d') - - if [ "$UPDATE_HTTP" = "204" ] || [ "$UPDATE_HTTP" = "200" ]; then - echo "OK: Set Fix Versions for ${KEY} to '${MILESTONE_TITLE}'" - ok=$((ok+1)) - else - echo "FAIL: Could not update Fix Versions for ${KEY} (HTTP ${UPDATE_HTTP})" - echo "$UPDATE_BODY" - failed=$((failed+1)) - fi - done - - echo "======================================================" - echo "Summary: ok=${ok} skipped=${skipped} failed=${failed}" - echo "======================================================" - - if [ "$failed" -gt 0 ]; then - exit 1 - fi diff --git a/.github/workflows/main_jira_sync_pr_opened.yml b/.github/workflows/main_jira_sync_pr_opened.yml deleted file mode 100644 index 1aa0d27..0000000 --- a/.github/workflows/main_jira_sync_pr_opened.yml +++ /dev/null @@ -1,31 +0,0 @@ -name: Sync With Jira - PR Opened - -on: - workflow_call: - secrets: - caller_jira_auth: - required: true - -jobs: - manage_opened_gh_event: - runs-on: ubuntu-slim - permissions: - contents: read - pull-requests: write - issues: write - steps: - - name: Checkout repository - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 - with: - repository: scylladb/github-automation - ref: main - - - name: Run pr-opened orchestrator - env: - PR_TITLE: ${{ github.event.pull_request.title }} - PR_BODY: ${{ github.event.pull_request.body }} - PR_NUMBER: ${{ github.event.pull_request.number }} - OWNER_REPO: ${{ github.repository }} - GITHUB_TOKEN: ${{ github.token }} - JIRA_AUTH: ${{ secrets.caller_jira_auth }} - run: python3 scripts/jira_sync_logic.py --action manage_opened_gh_event diff --git a/.github/workflows/main_jira_sync_remove_label.yml b/.github/workflows/main_jira_sync_remove_label.yml deleted file mode 100644 index dd41063..0000000 --- a/.github/workflows/main_jira_sync_remove_label.yml +++ /dev/null @@ -1,32 +0,0 @@ -name: Sync With Jira - Remove Label - -on: - workflow_call: - secrets: - caller_jira_auth: - required: true - -jobs: - sync: - name: Remove-label orchestration - runs-on: ubuntu-slim - steps: - - name: Checkout scripts - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 - with: - repository: scylladb/github-automation - ref: main - path: _automation - - - name: Run manage_unlabeled_gh_event - env: - PR_TITLE: ${{ github.event.pull_request.title }} - PR_BODY: ${{ github.event.pull_request.body }} - PR_NUMBER: ${{ github.event.pull_request.number }} - REMOVED_LABEL: ${{ github.event.label.name }} - OWNER_REPO: ${{ github.repository }} - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - JIRA_AUTH: ${{ secrets.caller_jira_auth }} - run: | - cd _automation/scripts - python jira_sync_logic.py --action manage_unlabeled_gh_event diff --git a/.github/workflows/main_pr_events_jira_sync.yml b/.github/workflows/main_pr_events_jira_sync.yml deleted file mode 100644 index cd36fdc..0000000 --- a/.github/workflows/main_pr_events_jira_sync.yml +++ /dev/null @@ -1,44 +0,0 @@ -name: Sync Jira from PR Events - -on: - workflow_call: - inputs: - caller_action: - description: > - The GitHub event action that triggered this workflow (e.g. opened, - labeled, unlabeled, closed, ready_for_review, review_requested). - The Python script maps this to the correct orchestrator function. - required: true - type: string - secrets: - caller_jira_auth: - required: true - -jobs: - jira-sync: - name: "Jira Sync - ${{ inputs.caller_action }}" - runs-on: ubuntu-slim - permissions: - contents: read - pull-requests: write - issues: write - steps: - - name: Checkout repository - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - with: - repository: scylladb/github-automation - ref: automation-staging-branch - - - name: Run Jira sync orchestrator - env: - PR_TITLE: ${{ github.event.pull_request.title }} - PR_BODY: ${{ github.event.pull_request.body }} - PR_NUMBER: ${{ github.event.pull_request.number }} - OWNER_REPO: ${{ github.repository }} - TRIGGERING_LABEL: ${{ github.event.label.name }} - REMOVED_LABEL: ${{ github.event.label.name }} - REQUESTED_REVIEWER: ${{ github.event.requested_reviewer.login }} - PR_MERGED: ${{ github.event.pull_request.merged }} - GITHUB_TOKEN: ${{ github.token }} - JIRA_AUTH: ${{ secrets.caller_jira_auth }} - run: python3 scripts/jira_sync_logic.py --action ${{ inputs.caller_action }} diff --git a/.github/workflows/main_sync_milestone_to_jira_release.yml b/.github/workflows/main_sync_milestone_to_jira_release.yml deleted file mode 100644 index 046af99..0000000 --- a/.github/workflows/main_sync_milestone_to_jira_release.yml +++ /dev/null @@ -1,228 +0,0 @@ -name: Create Jira releases (versions) from GitHub milestone - -on: - workflow_call: - inputs: - jira_project_keys: - description: "Comma-separated Jira project keys (e.g. STAG,VECTOR,PROJ)" - required: true - type: string - secrets: - caller_jira_auth: - description: "Plain 'email:api_token' for Jira Cloud Basic auth" - required: true - -jobs: - create_jira_releases: - if: github.event.action == 'created' - runs-on: ubuntu-slim - env: - JIRA_BASE_URL: https://scylladb.atlassian.net - JIRA_AUTH: ${{ secrets.caller_jira_auth }} - PROJECT_KEYS: ${{ inputs.jira_project_keys }} - - steps: - - name: Debug milestone input - run: | - echo "Projects: '${{ inputs.jira_project_keys }}'" - echo "Title: '${{ github.event.milestone.title }}'" - echo "Description: '${{ github.event.milestone.description }}'" - echo "Due on: '${{ github.event.milestone.due_on }}'" - - - name: Create Jira version in each project (skip if already exists) - shell: bash - run: | - set -euo pipefail - - if [ -z "${JIRA_AUTH:-}" ]; then - echo "ERROR: jira_auth secret is not set." - exit 1 - fi - - NAME="${{ github.event.milestone.title }}" - DESC="${{ github.event.milestone.description }}" - DUE_ON="${{ github.event.milestone.due_on }}" - - # GitHub due_on is ISO 8601; Jira expects YYYY-MM-DD - RELEASE_DATE="" - if [ -n "${DUE_ON:-}" ]; then - RELEASE_DATE="${DUE_ON%%T*}" - fi - - echo "Version name: ${NAME}" - echo "Release date: ${RELEASE_DATE:-}" - echo "Projects: ${PROJECT_KEYS}" - echo - - # Split comma-separated keys safely (trim whitespace) - IFS=',' read -r -a KEYS <<< "${PROJECT_KEYS}" - - ok=0 - skipped=0 - failed=0 - - for raw in "${KEYS[@]}"; do - PROJECT_KEY="$(echo "$raw" | awk '{$1=$1};1')" # trim - [ -n "$PROJECT_KEY" ] || continue - - echo "======================================================" - echo "Creating Jira version in project: ${PROJECT_KEY}" - echo "======================================================" - - # Build payload - jq -n \ - --arg name "$NAME" \ - --arg proj "$PROJECT_KEY" \ - --arg desc "${DESC:-}" \ - --arg rdate "${RELEASE_DATE:-}" \ - ' - { - name: $name, - project: $proj - } - + (if $desc != "" then {description: $desc} else {} end) - + (if $rdate != "" then {releaseDate: $rdate} else {} end) - ' > payload.json - - # Attempt create - HTTP_CODE=$(curl -sS -o resp.json -w "%{http_code}" \ - -X POST "${JIRA_BASE_URL}/rest/api/3/version" \ - --user "${JIRA_AUTH}" \ - -H "Accept: application/json" \ - -H "Content-Type: application/json" \ - --data @payload.json || true) - - if [ "$HTTP_CODE" = "201" ] || [ "$HTTP_CODE" = "200" ]; then - ID=$(jq -r '.id // empty' resp.json) - echo "OK: created version in ${PROJECT_KEY} (id=${ID})." - ok=$((ok+1)) - continue - fi - - # If already exists: treat as SKIP and move on - if [ "$HTTP_CODE" = "400" ] && jq -e ' - (.errorMessages // []) + ((.errors // {}) | to_entries | map(.value)) - | map(tostring) - | any(test("already exists|exists already|A version with this name already exists"; "i")) - ' resp.json > /dev/null 2>&1; then - echo "SKIP: version '${NAME}' already exists in ${PROJECT_KEY}." - skipped=$((skipped+1)) - continue - fi - - # Other failure -> count as failure but continue to next project - echo "FAIL: could not create version in ${PROJECT_KEY} (HTTP ${HTTP_CODE}). Response:" - cat resp.json || true - echo - failed=$((failed+1)) - done - - echo "======================================================" - echo "Summary: ok=${ok} skipped=${skipped} failed=${failed}" - echo "======================================================" - - if [ "$failed" -gt 0 ]; then - exit 1 - fi - - release_jira_releases: - if: github.event.action == 'closed' - runs-on: ubuntu-slim - env: - JIRA_BASE_URL: https://scylladb.atlassian.net - JIRA_AUTH: ${{ secrets.caller_jira_auth }} - PROJECT_KEYS: ${{ inputs.jira_project_keys }} - - steps: - - name: Debug milestone input - run: | - echo "Projects: '${{ inputs.jira_project_keys }}'" - echo "Title: '${{ github.event.milestone.title }}'" - echo "Action: '${{ github.event.action }}'" - - - name: Release Jira version in each project - shell: bash - run: | - set -euo pipefail - - if [ -z "${JIRA_AUTH:-}" ]; then - echo "ERROR: jira_auth secret is not set." - exit 1 - fi - - NAME="${{ github.event.milestone.title }}" - TODAY="$(date -u +%Y-%m-%d)" - - echo "Version name: ${NAME}" - echo "Release date: ${TODAY}" - echo "Projects: ${PROJECT_KEYS}" - echo - - # Split comma-separated keys safely (trim whitespace) - IFS=',' read -r -a KEYS <<< "${PROJECT_KEYS}" - - ok=0 - skipped=0 - failed=0 - - for raw in "${KEYS[@]}"; do - PROJECT_KEY="$(echo "$raw" | awk '{$1=$1};1')" # trim - [ -n "$PROJECT_KEY" ] || continue - - echo "======================================================" - echo "Releasing Jira version in project: ${PROJECT_KEY}" - echo "======================================================" - - # Find the version ID by name - HTTP_CODE=$(curl -sS -o versions.json -w "%{http_code}" \ - "${JIRA_BASE_URL}/rest/api/3/project/${PROJECT_KEY}/versions" \ - --user "${JIRA_AUTH}" \ - -H "Accept: application/json" || true) - - if [ "$HTTP_CODE" != "200" ]; then - echo "FAIL: could not list versions in ${PROJECT_KEY} (HTTP ${HTTP_CODE}). Response:" - cat versions.json || true - echo - failed=$((failed+1)) - continue - fi - - VERSION_ID=$(jq -r --arg name "$NAME" \ - '.[] | select(.name == $name) | .id' versions.json | head -1) - - if [ -z "$VERSION_ID" ]; then - echo "SKIP: version '${NAME}' not found in ${PROJECT_KEY}." - skipped=$((skipped+1)) - continue - fi - - # Mark the version as released - jq -n \ - --arg rdate "${TODAY}" \ - '{"released": true, "releaseDate": $rdate}' > release_payload.json - - HTTP_CODE=$(curl -sS -o release_resp.json -w "%{http_code}" \ - -X PUT "${JIRA_BASE_URL}/rest/api/3/version/${VERSION_ID}" \ - --user "${JIRA_AUTH}" \ - -H "Accept: application/json" \ - -H "Content-Type: application/json" \ - --data @release_payload.json || true) - - if [ "$HTTP_CODE" = "200" ]; then - echo "OK: released version '${NAME}' in ${PROJECT_KEY} (id=${VERSION_ID})." - ok=$((ok+1)) - else - echo "FAIL: could not release version in ${PROJECT_KEY} (HTTP ${HTTP_CODE}). Response:" - cat release_resp.json || true - echo - failed=$((failed+1)) - fi - done - - echo "======================================================" - echo "Summary: ok=${ok} skipped=${skipped} failed=${failed}" - echo "======================================================" - - if [ "$failed" -gt 0 ]; then - exit 1 - fi diff --git a/.github/workflows/remove_label_from_jira_issue.yml b/.github/workflows/remove_label_from_jira_issue.yml deleted file mode 100644 index a9dc927..0000000 --- a/.github/workflows/remove_label_from_jira_issue.yml +++ /dev/null @@ -1,171 +0,0 @@ -name: Remove Label from Jira Issues - -on: - workflow_call: - inputs: - jira_keys_json: - description: 'JSON array of Jira keys, e.g. ["STAG-1","STAG-2"] or ["__NO_KEYS_FOUND__"]' - type: string - required: true - label: - description: "Label that was removed from the PR. For Jira: normal label or area/* (Scylla component)." - type: string - required: true - secrets: - jira_auth: - description: "Plain 'email:api_token' for Jira Cloud Basic auth" - required: true - -jobs: - remove_labels_from_jira: - runs-on: ubuntu-slim - env: - BASE_URL: https://scylladb.atlassian.net - SCYLLA_COMPONENTS_FIELD: customfield_10321 - - steps: - - name: Extract Jira keys from jira_keys_json - id: extract - shell: bash - env: - JIRA_KEYS_JSON: ${{ inputs.jira_keys_json }} - run: | - set -euo pipefail - - python3 - <<'PY' - import json, sys, os - - raw = os.environ.get("JIRA_KEYS_JSON", "").strip() - print(f"Incoming jira_keys_json: {raw}") - - if (not raw or raw == "[]" or raw == '[""]' or raw == '["__NO_KEYS_FOUND__"]'): - print("No usable Jira keys; nothing to update.") - open("keys.txt", "w").close() - sys.exit(0) - - try: - data = json.loads(raw) - except json.JSONDecodeError as e: - print(f"Invalid JSON: {e}", file=sys.stderr) - sys.exit(1) - - if not isinstance(data, list): - print("jira_keys_json must be an array", file=sys.stderr) - sys.exit(1) - - keys = [] - for item in data: - if isinstance(item, str) and item.strip() and item.strip() != "__NO_KEYS_FOUND__": - keys.append(item.strip()) - - uniq = [] - seen = set() - for k in keys: - if k not in seen: - uniq.append(k) - seen.add(k) - - with open("keys.txt", "w") as out: - for k in uniq: - out.write(k + "\n") - - print(f"Found {len(uniq)} issues.") - PY - - - name: Prepare payload(s) and mode (normal label or scylla component) - id: prep - shell: bash - env: - TARGET_IN: ${{ inputs.label }} - SCYLLA_FIELD: ${{ env.SCYLLA_COMPONENTS_FIELD }} - run: | - set -euo pipefail - - TARGET="${TARGET_IN}" - MODE="" - - echo "Incoming removed label: '${TARGET}'" - - # area/* → Scylla component - if [[ "$TARGET" == area/* ]]; then - MODE="scylla_component" - RAW="${TARGET#area/}" - COMPONENT_VALUE="${RAW//_/ }" - ESCAPED=$(jq -Rn --arg v "$COMPONENT_VALUE" '$v') - printf '{"update":{"%s":[{"remove":{"value":%s}}]}}\n' "$SCYLLA_FIELD" "$ESCAPED" \ - > payload_scylla.json - echo "scylla component remove payload ready" - else - # Normal Jira label removal - MODE="label" - jq -n --arg label "$TARGET" \ - '{update:{labels:[{remove:$label}]}}' > payload_label.json - echo "label removal payload ready" - fi - - echo "mode=${MODE}" >> "$GITHUB_OUTPUT" - - - name: Apply to each issue (Basic auth) - id: apply - shell: bash - env: - JIRA_AUTH: ${{ secrets.jira_auth }} - BASE_URL: ${{ env.BASE_URL }} - MODE: ${{ steps.prep.outputs.mode }} - TARGET_LABEL: ${{ inputs.label }} - run: | - set -euo pipefail - - if [ ! -s keys.txt ]; then - echo "No issue keys found; nothing to update." - exit 0 - fi - - echo "Operation mode: ${MODE}" - - if [ "$MODE" = "scylla_component" ]; then - PAYLOAD_FILE="payload_scylla.json" - ACTION_DESC="Remove Scylla component" - else - PAYLOAD_FILE="payload_label.json" - ACTION_DESC="Remove Jira label" - fi - - ok=0; skipped=0; failed=0 - - while IFS= read -r key; do - [ -n "${key:-}" ] || continue - - ISSUE_URL="${BASE_URL}/rest/api/3/issue/${key}" - - echo "${ACTION_DESC} on ${key} ..." - code=$(curl -sS -o resp.json -w "%{http_code}" \ - -X PUT "${ISSUE_URL}" \ - --user "$JIRA_AUTH" \ - -H "Accept: application/json" \ - -H "Content-Type: application/json" \ - --data @"${PAYLOAD_FILE}" || echo "000") - - if [[ "$code" == "204" || "$code" == "200" ]]; then - echo "OK ${key} (${code})" - ok=$((ok+1)) - elif [[ "$code" == "400" ]]; then - echo "SKIP ${key} (${code}) – value may not exist in Jira" - skipped=$((skipped+1)) - head -c 200 resp.json || true - echo - else - echo "FAIL ${key} (${code})" - failed=$((failed+1)) - head -c 400 resp.json || true - echo - fi - - sleep 0.2 - done < keys.txt - - echo "Summary: ok=${ok}, skipped=${skipped}, failed=${failed}" - - if [ "$failed" -gt 0 ]; then - exit 1 - fi From 737104bb5213cab15ae3e0558f6c997e685212fb Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 29 Jun 2026 13:36:12 +0000 Subject: [PATCH 08/15] Remove remaining workflow deletions from PR --- ...main_update_jira_status_to_in_progress.yml | 63 ++++++++++++++++ .../main_update_jira_status_to_in_review.yml | 62 ++++++++++++++++ ..._update_jira_status_to_ready_for_merge.yml | 71 +++++++++++++++++++ 3 files changed, 196 insertions(+) create mode 100644 .github/workflows/main_update_jira_status_to_in_progress.yml create mode 100644 .github/workflows/main_update_jira_status_to_in_review.yml create mode 100644 .github/workflows/main_update_jira_status_to_ready_for_merge.yml diff --git a/.github/workflows/main_update_jira_status_to_in_progress.yml b/.github/workflows/main_update_jira_status_to_in_progress.yml new file mode 100644 index 0000000..923fe87 --- /dev/null +++ b/.github/workflows/main_update_jira_status_to_in_progress.yml @@ -0,0 +1,63 @@ +name: Update Jira Status - In Progress + +on: + workflow_call: + secrets: + jira_auth: + required: true + +jobs: + action-jira-status-update: + runs-on: ubuntu-latest + + steps: + - name: Extract Jira Ticket IDs + id: get-jira + shell: bash + env: + PR_TITLE: ${{ github.event.pull_request.title }} + PR_BODY: ${{ github.event.pull_request.body }} + run: | + set -euo pipefail + + # Replace backticks with spaces (no evaluation) + title="$(printf '%s' "$PR_TITLE" | tr '`' ' ')" + body="$(printf '%s' "$PR_BODY" | tr '`' ' ')" + + > tickets.txt + printf '%s\n' "$title" | grep -oE '[A-Z]+-[0-9]+' >> tickets.txt || true + printf '%s\n' "$body" | grep -iE '^Fixes[[:space:]]*[: ][[:space:]]*[A-Z]+-[0-9]+' \ + | grep -oE '[A-Z]+-[0-9]+' >> tickets.txt || true + + sort -u tickets.txt > unique_tickets.txt + if [[ ! -s unique_tickets.txt ]]; then + echo "ticket-ids=" >> "$GITHUB_OUTPUT" + exit 0 + fi + + tickets_csv=$(paste -sd, unique_tickets.txt) + echo "ticket-ids=$tickets_csv" >> "$GITHUB_OUTPUT" + + - name: Transition Jira Tickets to 'In Progress' + if: steps.get-jira.outputs.ticket-ids != '' + env: + JIRA_AUTH: ${{ secrets.jira_auth }} + shell: bash + run: | + set -euo pipefail + + if [ -z "${JIRA_AUTH:-}" ]; then + echo "ERROR: JIRA_AUTH secret is empty. Secret was not passed correctly from the calling workflow." + exit 1 + fi + + IFS=',' read -ra tickets <<< "${{ steps.get-jira.outputs.ticket-ids }}" + for ticket_id in "${tickets[@]}"; do + echo "Transitioning Jira ticket to 'In Progress': $ticket_id" + curl -v --fail -X POST \ + --url "https://scylladb.atlassian.net/rest/api/3/issue/${ticket_id}/transitions" \ + --user "$JIRA_AUTH" \ + --header "Accept: application/json" \ + --header "Content-Type: application/json" \ + -d '{"transition": {"id": "111"}}' + done diff --git a/.github/workflows/main_update_jira_status_to_in_review.yml b/.github/workflows/main_update_jira_status_to_in_review.yml new file mode 100644 index 0000000..aa3800e --- /dev/null +++ b/.github/workflows/main_update_jira_status_to_in_review.yml @@ -0,0 +1,62 @@ +name: Update Jira Status - In Review + +on: + workflow_call: + secrets: + jira_auth: + required: true + +jobs: + action-jira-status-update-in-review: + runs-on: ubuntu-latest + + steps: + - name: Extract Jira Ticket IDs + id: get-jira + shell: bash + env: + PR_TITLE: ${{ github.event.pull_request.title }} + PR_BODY: ${{ github.event.pull_request.body }} + run: | + set -euo pipefail + + # Single-line: replace backticks with spaces, no evaluation + title="$(printf '%s' "$PR_TITLE" | tr '`' ' ')" + body="$(printf '%s' "$PR_BODY" | tr '`' ' ')" + + > tickets.txt + printf '%s\n' "$title" | grep -oE '[A-Z]+-[0-9]+' >> tickets.txt || true + printf '%s\n' "$body" | grep -iE '^Fixes[[:space:]]*[: ][[:space:]]*[A-Z]+-[0-9]+' \ + | grep -oE '[A-Z]+-[0-9]+' >> tickets.txt || true + + sort -u tickets.txt > unique_tickets.txt + if [[ ! -s unique_tickets.txt ]]; then + echo "ticket-ids=" >> "$GITHUB_OUTPUT" + exit 0 + fi + tickets_csv=$(paste -sd, unique_tickets.txt) + echo "ticket-ids=$tickets_csv" >> "$GITHUB_OUTPUT" + + - name: Transition Jira Tickets to 'In Review' + if: steps.get-jira.outputs.ticket-ids != '' + env: + JIRA_AUTH: ${{ secrets.jira_auth }} + shell: bash + run: | + set -euo pipefail + + IFS=',' read -ra tickets <<< "${{ steps.get-jira.outputs.ticket-ids }}" + if [ -z "${JIRA_AUTH:-}" ]; then + echo "ERROR: JIRA_AUTH secret is empty. Secret was not passed correctly from the calling workflow." + exit 1 + fi + + for ticket_id in "${tickets[@]}"; do + echo "Transitioning Jira ticket to 'In Review': $ticket_id" + curl -v --fail -X POST \ + --url "https://scylladb.atlassian.net/rest/api/3/issue/${ticket_id}/transitions" \ + --user "$JIRA_AUTH" \ + --header "Accept: application/json" \ + --header "Content-Type: application/json" \ + -d '{"transition": {"id": "121"}}' + done diff --git a/.github/workflows/main_update_jira_status_to_ready_for_merge.yml b/.github/workflows/main_update_jira_status_to_ready_for_merge.yml new file mode 100644 index 0000000..4529d83 --- /dev/null +++ b/.github/workflows/main_update_jira_status_to_ready_for_merge.yml @@ -0,0 +1,71 @@ +name: Update Status - Ready For Merge + +on: + workflow_call: + inputs: + label_name: + required: true + type: string + secrets: + jira_auth: + required: true + +jobs: + action-jira-status-update-ready-for-merge: + if: ${{ github.event.label.name == inputs.label_name }} + runs-on: ubuntu-latest + + steps: + - name: Extract Jira Ticket IDs + id: get-jira + shell: bash + env: + PR_TITLE: ${{ github.event.pull_request.title }} + PR_BODY: ${{ github.event.pull_request.body }} + run: | + set -euo pipefail + echo "Label '${{ inputs.label_name }}' detected. Looking for Jira ticket IDs..." + + # Replace backticks with spaces (no evaluation) + title="$(printf '%s' "${PR_TITLE:-}" | tr '`' ' ')" + body="$(printf '%s' "${PR_BODY:-}" | tr '`' ' ')" + + > tickets.txt + printf '%s\n' "$title" | grep -oE '[A-Z]+-[0-9]+' >> tickets.txt || true + printf '%s\n' "$body" | grep -iE '^Fixes[[:space:]]*[: ][[:space:]]*[A-Z]+-[0-9]+' \ + | grep -oE '[A-Z]+-[0-9]+' >> tickets.txt || true + + sort -u tickets.txt > unique_tickets.txt + + if [[ ! -s unique_tickets.txt ]]; then + echo "No Jira tickets found in PR title or body. Skipping Jira update." + echo "ticket-ids=" >> "$GITHUB_OUTPUT" + exit 0 + fi + + tickets_csv=$(paste -sd, unique_tickets.txt) + echo "ticket-ids=$tickets_csv" >> "$GITHUB_OUTPUT" + + - name: Transition Jira Tickets to 'Ready for Merge' + if: steps.get-jira.outputs.ticket-ids != '' + env: + JIRA_AUTH: ${{ secrets.jira_auth }} + shell: bash + run: | + set -euo pipefail + + if [ -z "${JIRA_AUTH:-}" ]; then + echo "ERROR: JIRA_AUTH secret is empty. Secret was not passed correctly from the calling workflow." + exit 1 + fi + + IFS=',' read -ra tickets <<< "${{ steps.get-jira.outputs.ticket-ids }}" + for ticket_id in "${tickets[@]}"; do + echo "Transitioning Jira ticket to 'Ready for Merge': $ticket_id" + curl -v --fail -X POST \ + --url "https://scylladb.atlassian.net/rest/api/3/issue/${ticket_id}/transitions" \ + --user "$JIRA_AUTH" \ + --header "Accept: application/json" \ + --header "Content-Type: application/json" \ + -d '{"transition": {"id": "131"}}' + done From 306b5075d954e90ee76978b9d9762265e509fd26 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 29 Jun 2026 13:37:24 +0000 Subject: [PATCH 09/15] Validation complete for PR cleanup --- ...ate_jira_issue_from_gh_issue.cpython-312.pyc | Bin 0 -> 15010 bytes .../__pycache__/jira_sync_logic.cpython-312.pyc | Bin 0 -> 32894 bytes .../jira_sync_modules.cpython-312.pyc | Bin 0 -> 55553 bytes 3 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 scripts/__pycache__/create_jira_issue_from_gh_issue.cpython-312.pyc create mode 100644 scripts/__pycache__/jira_sync_logic.cpython-312.pyc create mode 100644 scripts/__pycache__/jira_sync_modules.cpython-312.pyc diff --git a/scripts/__pycache__/create_jira_issue_from_gh_issue.cpython-312.pyc b/scripts/__pycache__/create_jira_issue_from_gh_issue.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4efaefabc4fabeff0a7e8e8bd99a6e5569d5bbf9 GIT binary patch literal 15010 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 literal 0 HcmV?d00001 diff --git a/scripts/__pycache__/jira_sync_modules.cpython-312.pyc b/scripts/__pycache__/jira_sync_modules.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..201900e4955964d13217503ece2614345a21e53a GIT binary patch literal 55553 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 Date: Mon, 29 Jun 2026 13:48:39 +0000 Subject: [PATCH 10/15] Plan: limit PR to two Python files --- ...e_jira_issue_from_gh_issue.cpython-312.pyc | Bin 15010 -> 15010 bytes .../jira_sync_logic.cpython-312.pyc | Bin 32894 -> 32894 bytes .../jira_sync_modules.cpython-312.pyc | Bin 55553 -> 55553 bytes 3 files changed, 0 insertions(+), 0 deletions(-) diff --git a/scripts/__pycache__/create_jira_issue_from_gh_issue.cpython-312.pyc b/scripts/__pycache__/create_jira_issue_from_gh_issue.cpython-312.pyc index 4efaefabc4fabeff0a7e8e8bd99a6e5569d5bbf9..0a3b0a71dd33d9652a827aa2ba6d5d75fe5c5a1c 100644 GIT binary patch delta 19 ZcmZ2fx~P=vG%qg~0}xCu-^ew?3IILX1-}3Q delta 19 ZcmZ2fx~P=vG%qg~0}wcuY~-3@1pqth1#AES diff --git a/scripts/__pycache__/jira_sync_logic.cpython-312.pyc b/scripts/__pycache__/jira_sync_logic.cpython-312.pyc index 32ab9690e4f8143b700cfd72fee0a523047c739e..4e42f9859a2ec19a4141a408515049b34a296b78 100644 GIT binary patch delta 21 bcmey@!1S+yiR&~kFBbz4OfKKZRnhw!FBbz4OfKKZ_5B6_Mz03? delta 21 bcmZqN#N4=vnd>w!FBbz4IG1eX`hEidM8F28 From 3479134ef5e659bcc76819980d9f4d359b9c1d7b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 29 Jun 2026 13:49:00 +0000 Subject: [PATCH 11/15] Remove extra script and pycache files from PR --- ...e_jira_issue_from_gh_issue.cpython-312.pyc | Bin 15010 -> 0 bytes .../jira_sync_logic.cpython-312.pyc | Bin 32894 -> 0 bytes .../jira_sync_modules.cpython-312.pyc | Bin 55553 -> 0 bytes scripts/create_jira_issue_from_gh_issue.py | 387 ------------------ 4 files changed, 387 deletions(-) delete mode 100644 scripts/__pycache__/create_jira_issue_from_gh_issue.cpython-312.pyc delete mode 100644 scripts/__pycache__/jira_sync_logic.cpython-312.pyc delete mode 100644 scripts/__pycache__/jira_sync_modules.cpython-312.pyc delete mode 100644 scripts/create_jira_issue_from_gh_issue.py diff --git a/scripts/__pycache__/create_jira_issue_from_gh_issue.cpython-312.pyc b/scripts/__pycache__/create_jira_issue_from_gh_issue.cpython-312.pyc deleted file mode 100644 index 0a3b0a71dd33d9652a827aa2ba6d5d75fe5c5a1c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15010 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 A!vFvP diff --git a/scripts/__pycache__/jira_sync_logic.cpython-312.pyc b/scripts/__pycache__/jira_sync_logic.cpython-312.pyc deleted file mode 100644 index 4e42f9859a2ec19a4141a408515049b34a296b78..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 32894 zcmeHwYfv0lmS$E}LcJfn-;f{)D2a#A%N8<7NFWI$fsBx3VYkZ#nUV@Y6_Zs+rnaz| z2+xib>sVW}6C>R14&&M0H4Zys*_e)9#m@Y2#E#YO*gq*#ZsBZxbjSKnPi(}{mU?HJ zUwh8YN8Kv21j6!m?~YR9=B=CedG5`;=YHqhbN`3i?O@>gcQ=lXy?cXU{wMy>E}!ao z_zxzAxx<`icxIU4O}u&BG;AVw^RSuREyEUaXNOt1TgG!Ha))y#ti#p`+pulIK5U~9KQgaF4_NDKy|)8Wy;c;rfG zv}JOdYvzU`lg;D8bzz)~h@)49XiN;oA|e+I^W3r1y&NBkP6lJ}K;$k%a35sBVHPb8 z$FWE_77T@>+(a-Oydng~gCoMYzz42e4M2Y3Sd;c(DxCF^C|nN-H}oW2W2zFNNSM1k z6&{U&C+cr<@WRN{6{Y&4P_pnk6cD>Aa9ziSdI$Og-M#0|b`2dn$;E;r<3bZ@zywsU z(GOMa8XxDb3geT47;WMpbu<5$ zgpu)3_?jMGDGC#j>uPTWE{l-~x?TlWgjj%&goS`oCu~K$=;gXVpno86s^`+V!100e z{oR2;-4FcccoEPM>e4zI3WUN?SmcT*M5A&0NO1JpWJHX$w#dFf&r8QnpYQJJ4xH{f z+H?AxoI~0q=ZZpXN(_&xBNd6rSk%9VP2jo1B$zS!DaL>+W>)SDqmA-&jNcSLI7ss2 zhQul8tjpX^Qp`>+dNndN&T}IIC%is7KE(?>hmEF2vfnH_pdn%`dLtCOD!L$hze#k% zEsDi+Yvs{VF*F&AwyuAHggat7m3X>7p z1}|AGa!m-!c2cR}RP5@g6|+?@8{Cnc5AQ+f9VVs|k~e8&Gtr@D!%*Y6mIU)7^N)>F zunAMvXE~{^8)LPKrtV{O{ncPTm$!bRc6io&Z3%PMXZD08>oZ4!&3IN^bma% z?VOMs!@GX0KZOshn|f|cFOQa28pY|jPQ6?vVM^qFf;|VFY0UbaK4C$zkTP@mO8OiaQWrRiOodXhGFj44o-icR$b zMel@#FDHHKp=rTaq-bGc!d@zEB^kq2^cbd|8rPzFqgup}(<2x3a<2Bqz5?TT#x>)f z@gzK1dc*USdZUKw4gGz4>b=2jNQVlY4(5bA;YwH%Y$E5ATqSf9BffT{5}?29NPl}{ zReD)2WFYA`%b>@1JW-F=Z(NVD8m;`)oo~?6iB;>q1hrbcgpF?`qtO3jcxUme@afJ^ za+IfrqjlF4)xAlpLmIu)-kA;Ro=)3lzGVa2K3V-*H>%&Xd(>=#Z`O?S2DqBfzdLA! zsc=AN(}AVAE{M|{;dGjjE9asyVG>wX4w!Uc9LAAty&f4Qd@QiR99)CKV$wvDuf3q_$NgtZi5NfC?+fsygZ=rve`aLt`ua6B5p61cOw z)x`TUtCPl2tC99&y^L9FHO2wsI!p*6EN@0(u@K^caHI|?_M3}EfT%%!nk;R$Wx2Ly>2K{)b5IywEv}MrYLqC23!~rE|<&!`h(+ z982&*;7XCO=}}x)j)$VL7Op>%S_MGIz>5H@1Xv@&LU%&oTl&{3xO4bEwQ;TM2m6{A z-;riqAT^IgBjJv}Rd^F|knoX~wGPL3=(LWtTD3wWP$T2@-CDub zSZp%d-r9NvM%vU!3k;>!wcOT8c+XqoYWh8Da?@z6N*IxLgY+s8F33rC(? zb93QHteG^>-_EVI;p(~%fdSI+8;}?yWKv)v0^tf7;&n zY(Bd?UY)(qp}QO6H4ROq3Ju12G{mAvuWRrwbpF32wnyfaq5CSMH!90`>|cd zUz+${rQ`z;Mfu2PF6Z$Jm+?JW(`b?LC5n49BFdJwy>07SpOLB|-lEjuxu8P-OzePb zq(4wQ{cA4zcieewJQ9WRaXl2|;%@be4KLN%LGEL-Y*)|*m>gsq@lJ{3@zw?;(w|I) z03T2jknbVB8RU!DK$pQ!|N0v@0)D8COb!?*P+V*0)vV>$U7VjK$x7T4#d zk}RN|*bPq+eu=Wswpr#;6O-e(+4$DL3Tu}f2a@b_;L(1&YUdm0Dgfq|VODxtHc|EZUcx?X%r0MP+w}Zx7G2OGP_o`!UMET)$MYOL8W9{|l4kJ#do+ zXQiy_gYx&v=ew86{5L&>3T;2#wix=G7OAc4v#KxNkosShJb|R`wXeMeE3P~#zbENB zzU<1+C|~U`QgdsGRI&F<>)sVx&AexkT?~C?JMs)7?&XOl)>ng%62VuNUnp+uA=4Q>gA$}|Lx4RJ0AHMyGJKEjOH%WVI0#( zOgN~!Oc}J_pJWdhmc3$wb}SrU?74gJD_alUj1BWVlw@BZdH&hJ@4vlhW_-{6{@WJD zcQ}fls(Xxmpp3oeV8Q*l)jm+o{ydKbcNCuK7k&}(i}~;_xPUq855{!JRu5vv)b(B} z1Vlt2iqf!ynXRO^Q0YxuD4(U$o41fYhe~hRLi$`PJ-dbURw{kY7Sh|O^tlN$ED?1~ zmbZVRV#u(n)^XA?B5b7l5PDHZ!%U2wNnvXV9WkDm5OCKsR~rZ<5;h#LXwpwb_(*}QE`Oviw?Ghzd@Gu1mz#9Pym z>CKmZiFy0yH<;HgmzWzSe}4S$Q1A!Lg*e?j83FEyy8+k$tc%D3Hw)jOqYFVk3Y=hI zsCVdePZRo%4s>54p8oS^j`j>TaYKW>Cr=~skweZ7NSfv)pICl%q1%Bi8ii@P2aLn!i#wvc>en^wBa$X2y{*$y71 zeA$;-zU)YqExYKlWxHPPT62#mM#Oe(k&+Qm=sFgT3rt+@M1>fLP&r{@GB(}v8+=#R z^4FzlSSuqdQcMtp)Z-x(K*j_R^t8nHsnIhl_}G%xTGUjjMm#?LZZ$sL(8s6HnywS$ zvC%;kD(;8YiwDqo4xN4A$d)K@xUBGcC?;Ew<#t>Mj!y}sGKA^$+ft0O?A8Tg0gy-= zvCM>*jv|Mx@wWy5dwg}Nng z^X$nLkMEtaTVwBpZ-wVBEtr=)yJk z-njjSRR8?lx}}m1i7i~oE4WjByZlb|?do~g!pKry+ic&8H%~7m3}N0jD8-k5$8p86b{3J~&ZO;dT5tggK9aO`r3Dun74{7aJe2R6w #Cw4U+5b*|<>l(mN_2K{^1dEC$3^EaO; zv;3^o1g@Nq3qjB`0L)2|{tKe9|n!BfIS(R~H=ovQEZmKPO9+58O z>oUmH?D{wvq;Y8l8&ZyzaHh+?95c=tSHh*rz5vzNC6R8F4ym#)w=RivZ;950l;ltE zXW#~kHjqRXr&_iNs+XiXZb|jB-}K6uB5f*_Sb;H;LeR_LQqWPN;q!)+yasVaT{jBp;L=a9XS2scJ%H* zryiU&6%j^gJUd0jT^JvAdqh7bQt@xs!7* zNRGxN>sNlBm^&mnG`w%%{i7fBz1R0a|9kxlhwt_*RUVZpdL+kjK;x9yy>lIs!=Ge# zDnI+?Iwi->B)bcKO0I3v_5;$kgOUSbo(%LwD*;i_KNdvsj~k6!IJ)S#d(sGuJD6nK zk^Tf>E}uKJ;9NX^w>QZi{{{ke$WF)F5Swa6PzpJb&l~M0pJPAY!-6{szx7K8qGB-S zp8-)@0D_(YQBMGJJry7-9Yop^5VZ*q$@jg2NFV7SQeOPyO@K%l9K#b}NGY&GL62xK z<4F-C@i=@q$UH5cL|-pDr_ebKj+{T(^WyoQb3>rPJlJ!gx94Kdpm+wK_Mc;3I>wVhGZ-14A1< z0nT^EJvNJQlvSX#>VxX{s-?yk?v5;#bxCaTcf&o3p9a8Dt^ync-H@txFZxx0qxMMv zj;IE3Sebj)=Ht&h$$)+6s_f zl_E1huKzD^4b-iEhHIdHdv*=$?;qF5rqgRYMxO}R(B2EsnMUpPOw35rm)0;N?~EIC zt4khe+antwPW;{%i}Z8RnWLL{k}HOC$_YvKHF8_z_g$L~T7#kkg`q zwk8!lNF@OEL9INsjFxzzL9cRRE3_tFs@EyKH@SGD0*j%#WcDt^ii&%XEPFAx?YinG zWP2kRH5@1@#4NLSvmj=^?}V74fJDxX!j4CQCrW=r2hg9FiJ^^QD^e`|CNVVG&I1Vo zL_^T05*!8IN=Q*=2vHr3qQoN|cY|N)&|3y+#7RgZz=taOjRL*Z|6haNvLSKLaJTQM z1xMp~f>+zA(FH+n6qGh7YQGeWKoZ56Zr0Y#ETD&Q))y zyGGR@LwAjqitB6MjardNhaKtNpPSBu+Tp9{u0iWEbl3793p=`q?wUJokKd+C2i>** zro)Z}@t_@m6m!2H2F z6w;9?3Pgo0BNP&hGeltj4q*lSc8YyLFp?-`DSR$b%F1A5$leCzaH80EI`5(I9BJTW z2K~hw5PumN542M9ox#a8MJ?-6;q#!VwOPP&%PLu`4koYqfp6P=-?k;+j)mg;iZ<6% zQODBI%K1>bHr9?UftBUVz4GQ04$IH%CU8el;;UV#Ob7ED^YHm+2xT_=7W7;JqgA=G zV3QOwkeXKr3Ynv8SLJSix8!P=1L$F;%5x>G8HkQGr5n6XyNc4Tp7v0=7`KIAJ8adZW^ja*{;|G)hW!9>LH5i zY1&negdOZmWYexPrZi=DB1;Ll9gSR&dl_Gz){iRP8RiKrx0GnT1sJ89uOQ>HohsY7 zo*U|Ets8$Sywl280p|f@@Y8AvbEGv2YZC4snRzaa*GP?W;~Ld!?_k<^rut^uqoRE- z&>X7^h9E;Dv~OTi2n+o8g!V;9=6?vZFFSODnqy~Gt57Nk*QSDS97nd}8v%uNU0hhW zp}|oa$^*a^peya%3lM-vRcD={5}HDWEu(o)3%qOHq{5d*ow$=C6)1hRwaK|kQ?$*x zWKXdXxsXMcG&T7!9?}0&DKHrfsOJmeD{l0d-;F!x()- z0nGjYx@yl5vZsiUrEe3}_e0{|XVgq{FHYSJCE1fe^P&=cGsxk^qf3R)&7N7d7S7qe zv~qxj-Haq{)s&us`{vcRz3ZVcbyuism*G~>Q(v5sPQ4<%GA4PhC2ix`0j(Di&{Fi_ z%I$q6?C0BAaMR!`ow48ZFBiT_!9QDpub!$tT*k&q8^vBc9`>NNU}k}zax*qo(&`bL z&N~B~qLvS-WsD)PMAa_?oYDo+8vf7RsQX z_y)x0ae8e5e)>DZLf<IOsU?_z2hx*-IU0y5SqwQa>8z z-+Jdz7zf;{__)oC%AUl>n4UMVZ&;AFEfLFs&4fyzwly&=P}`oU1g7-C)HK=_#Z;QK zSy#)Q+PkR6EY($;(i1d@sLj}Kq*Io$i!olW;7+)U@p0YINw)m$gj~U#UK{-Ffxo@* zw=Z5r>{A56;$tWxhGMF9QLd5nm|tvwG^q`cnjJmd0GYk(h>lxa-787-*&er7vQ5L2 z)*l;ypp=mrH)BW%)$@r3H^WVj4t#nD9YPC~gZX_F6HCOIZ{qU|IcNH&M=)@IcCdF~ zuy^Q^YT#ZxjERn*(}m7abdG@&#VHlLn!Xf1xJ-r6);C%F*O2IKd(;Syxi=JpZvcbX%IBJs)<&Wk)VNT!-~}U7&l}ld(>L<{ zF>amQlVtZo<8TY2T(TeZodC*_N*nLf4U?W5l04_XvR(M5aQ9;MXI0YKOG|~rV2UG` z0Xtqb+kR2dK36;cCyVwk8xHxTz3cy* zu(ZGDvmZ$3g3{oKls}qu@n08|toVwg;@+gMZ`oIzf$ROhv%AxlrmNMFWIG9Iao^@) zrtr}3zpd0wij~^?USRLlvEY7DX+LFRzo=)yO+&75y$+bwGm~OK17=H#S5FnW+QLp! zT5&5=@ruTJ9*@jWg1Icn*E5r1FhXe4YZ>U-AJ(MU-)=%JYyIT+1Q6O_&zXS>utk#` zGV^pTiW%(>mECCtZUSJ7x2blw(h@$_lGb;?-DNsIk*>G(L{_xKmx0h} zQzCMzWJ-Ju+-JrOwlF0<-6;`4ZF2EoTMA$aI}IRF78)IJGE(-Ziv7lHY2h4^$E0fMpF4Zp8npT!}QTDMCIpT9LJ>zy5 zav9nS%h7$Nry|H6Vq%e;v(|TRpkM5R z8tXZrZOn7MLj!}CWRIHo*g*eK&r3sb7pYhv3@0{pG_08#;x<)Vqap4?^&IM$f`)j0 z>YRjTQvHsGxC>7egX82P;&exYi1xqZZ9{Oh2-xeV&Y$Q*BmZQ77(QrFjL#njqnBs! z)QbkO1=E$O>4=uEaxQ?9q)|5(52_{t?~m8Nk-9VrA5)I@<5ExF_zg@ma3Y(W3n%pf z`QxRH>8;nSZ~C*DTfqJ&7yzm_gMCtB|48;Cg}a5(2(K8S^jl>|ii~ouLP5p65yH2! zBSj{2}C41t0I|WioeulM+oy+}_2(rM&0C zVx-&q&hV|_cV4~qs#MvwxM#_I0Bnkb-T_!Fzw_$tSEcRy7Dtwf4uauwm*<_nTYc~J z-vZ<1%?sj^YtL*CHG5Kd8YM@?g41*5bFTR=$x)wV8*sgL^4$wy_7MWAlWYxH_*c$B zJ(?CENH_LgJvTLXW&XvK#ig`ter0t@zQ!+=MYIQJSO|GwExB(kne!yA4FojsFYH(- zSp);?Xt5G%A~|p|{mwUl z&Gs~YW%K{@BP-)8eBj-7-@ENw#srC7dGEIT!d1I!fgfwcR>S9x{l{I*Jy-SdX3M=M z6S)3duT*#S;KOYpLk#RWOGRQ&cTywKB=Fu)K9HI!Xcrd)~cum-b zsIuiEmw3!F_j9slAZzprSHTX=|Sz?UVZx;U=`^^SNQDEEoD1KhF zy^&t%JQA#Sh4>LX9Kv^XH+W{5RTpE+|I5IA>-J@DnPe+l@zy9~ZoY5H+d6ylYpZwJ zTXNI8>@1SlA`wMdqwuF+_-Y7?o5;LO&i^6@`;r~sD#y~L zoS)0xh=|uN!{(kSOr%a;P);<3qmbe@?X4e*9~lA@m+DIgFTe1*FggXtT~TN9!aIsQ z2HLq!h87MiMuYuH@^y-~bBgUH!W`tuwxD>0%)zp!OT03L zmch^Blq||F+&vFZNto;)k??nvyxZbm0i827Qh$PBXt^5BegOmMGK=R$Db^1E13uF2 zH~DkanO~Gyk|pLQTd%@VVW2WA=Rj3Md=y_>{79+$uUR}{P5dtqID#LRe+17gv*Ip# z;NE`Uy?wdxDA>vKvUl9B1}_czMc0GvKN8VD#N8)8PB5c^Yj zF6Swl=6Ha$dH}N`-eKWkN{XYLzk@1|igimO=yBrDc640e$T_hokRyRf@|Y-l1A$-| z?6E6{JqH3ZI}(YEE9d_Z^IYASY#1HF287Tzi4N{tQ}_c^RZ>_3#6<{$Cz3%#h6~Oi zq`$Gr`2IlqEli7*0$=f>@Z7=@7*19mbr6tw%e@_84Emhm`yEnqpJ+u z=J|(sTeY1wn+lgbd8-!m{L1ZH%|Q)lIw} zjO!&{ACv2Nn1|knud=&LxvQ_5&Y08!&_fD9k6Hln+Avo;@j5V9C-J(NvdUFA@hSxn zuTlVdAHHU8fC4U$Mf)*jX)hnu_Nws|?&0ED!PaZDp~^y}E~CT{q)j gTFRDL*X*%BKl!I8Zw>vM3tzE?s}_bWCqw!F0O2?PI?{%s7RyL-E!jTq$bld^3szO zYtEVZ{`*#tpzKQ z`c;!ocSpzRF6uZvXBgLC)U$8HMFaabUNo|A(?t{eHeWQe@2rbi?AvnD!oIB+t@t*M z+a~N6?Rv_~H13#iUUW`mU(9B|&Eu{K_eJ-F=b}fiyQ1T=zN^2O!&xqRIqO9qXSf{Ql-<rAf+rsiB6PQ#AOGIIajcF*u=TNX}VY< z{Voj_7a=O{dT_Ul%VDv~mAhWt-NN~BH#g|#^4QbTU`4PPITq6GPD+r;l-qg2~6#H;2| zPi_mIiM6f>`sG>;TRA^s)Nsgyft*4ZeqF1HA6d^-{9}NGROxx z|IpNAC_FeB4%Pdw1jna?JT3+&Isf2LcywygKRh$ZE<*OHZ+c4U7+74vr6m zr^JV&q0mfFdddeUrmh902*do;#KtIT8MCwlToA1rS4xg!LL zyH9nu<5z!g@2S32R%dTVfA3j*pY4983*TqEPIdJhOJzON#qL`=o)sfnP)cWe-|>{? z>GtlPqi5UcLVRRx@98_+d#bB1W$oxa+jZt_ZzrzK_4W6jMvm5_-Cd_TDNk$fnXa=) zgL{1)7fzjO?>v&Sv8V0l`g^6zj#H?yoz=MOncg$FW--Jj*w1$z>Fz<>PMwOBUkQh& zLv2k>p`jb&?U88h;kKdisZcP=!jSmIMTbXUq`zQ@gl-+Oj2ZgZsbhz z^FCd`9O*dA-e3RFAkU8ujs*Q;$>K6|d2r}zcy#D$$X`3b-iHudxI$Rp#+B77(72}0 zPU+V4Us}`q-`1xrd~kYva3~ni^UbJHh-&FyD-8|tqtoF~llmg5i)hL=5E`7sYaI#l zZHWF9rSl`0(>-#yUp{d2K+F`ooN!dEI0DO#z+%;6DB;*Cn09`OIJ&f6%EArSOEFyB z(S?;h`aVU)XI3Ak=j;>JeP4P$Yl!N{Xi(ODIQ=(uVak(z#%%JH`W-dMd35UJGUPjY zUDzSVjOyjP=yyZpXLee0yTm0Iy+6r~(kj6=1wSpmezu?t@|Q=kOz}7TG%x(MXU_UB zPjNTuvD-{cjE4Oa!B7aJ7Ql`{`SnhY-w;zz^TDAYhi&Qd4ga8@rugXO2tC3k!})8E z(hRTnchC!f@3Z10$5k*q)EHoSVN=6aF%+B*2f0T75&DVbC~=aOUrZ3(7#*3M!rs@& z5}ajo77zR(Y*az6-jDKUrm^LqVH{S{P*{wZHefUuJMs7F0R$&?dN#E$<np z8GLb?KNP7OkT)fz>j$XU8xM?64GoTm4mB!q&mw6kAHm<~{(eq(KksC`ePQs<$nB9k zqsw_Ge;T6q@*Bma`ao977z&2j1WskmOw(|td;?g~`nr3L4V>({aK86!=fK&nlx28y zk{cW!Pi2W66)>_lC1qFY5=xn9m_yV#7*)UfVTy z;v+}yLjOyL=QCEmGQ{FQE=bcOj4y*(^mjj*m`V)Z@N!&1<{K%2BP?vC&38pfB zKXOUg*n2uS6TXr*TFUFS7afb&3sJ?-Ygl^TFlb+{G3uCgA1qp+#@Bz=zc!g(Gda$z zA=4{0Ym6Glve)NJbU$a5mpi>~lQ<^M95uYAdqY_`_27-dZaKH8@%z#&+@+f}g>&Tl zV_x}6{f?T(^3-4Qm0b5HwM#Bz)*LmD704;oZ!T*@C%2?i_j1;d;fij^a0$IRn-$IC zEJT-o+i=Tf!rfUs<*f8iPNCQJ;l7?dyRNI!wP0Dkj^7vXzUg&0tS=fb=&tLlbm2m| z#Bi~EHEh_b<11$^;WGISXNy``e@Xp65;%>#ys?asu|q z3|ldto(a;*CegzFv!Gl2?Pt3EL?Pq-@K5toW5J;?ThXKyPMMZ|P+EAG@fd5%V8~w? zoB&1HHaI;BQtxVTveI9BWH3bJF6J=SN4!S@Q^KcU)HSKJYa&HO+2SE-Vo)~-) z%izp-ICQY3xw$!&)y@{bHP0ZZQ(D8Y>NSmprY2L_?Z|S9AC0hkYguABsjO>*;~?)+ zMl2*fk!|M(`AMv~ZQ_zHH)VWk>gvq2e;9QQa&7*ACzXAo`)vEbk@mi>0nmb}tjmL; z;O^Fx?egx{;N;L07ffZz-&~M>^Ymh+>_nDd2@c{n&!`C#tDAXzYLLV7!Q)BFID++v zUO1lK+mv~lADs;I9k>oy`IB_Z2ud_%5%WiUKKNxy8k%M_>tMe`EUaFt#ST$LGt>^1K3wwpKrlhG^{&_e) zym)@GTiCigY1;GHlx5C)n4P=O_tNu^bq3oBeXReXui#GG?Y0>A=IE=VuU%a!Z(c5M zPL%IR_;${BuI||VN45XF_U_($XA?V)|Jc_ZzrJuR*7ZuyeP8$AnJI&hSvEiYOZm5$ z?aw~T(q-p==S9Kc|3qg%nbvH73x&pR^u$==Q!e^Xtx^JvQUvTBsLo|6!w} zqgMCBeeGEtrN(y-J39)p-gOvo{cg4m58f>>({-u2W1HpO3M1Xw#==^6XOZ#UJq4Y) z#`j!$T)&rVMwqfsU7rl{10b@dQa126lQR>SgM7+5az&i?L$qhe9~v?G{pnk5xgOEY z0xX*~afVql;2&dDhh^Io)g#2RgD@*-wHa?ZuMu{~v2_@mBf z_OL=@g5Y`Dqzlt(&puI`+@`4cD#n=CPht!?eFU4~tm)P#VV@k6^J!8kTN=hZm(7Aa zngwqtV@;c7--eCi)_0VR!X@V$mVsIw+bBwA?V2*3G@rQas2zEm7N?**M_iI zhX;U})GPF|KMcYY01hkb%;3oAB&aozt}|dIv8sav1R-6Eg*rUt-?6J%BDX_+(3Yrz zw4MBf_P?KS2-eDEE)`o#oN6`+-1#s)kr7$bR|T@!&ci>8v~0`aFVNLR z3ZA2Y)_Zlk;V;q8=Mki`(5T=f_Lp&B9xi^E9*j_Mg`R?8WZQ1aL{&{$<(}bRpeSFW zV35U=n#5C&^IxW5itZaHLL(uXk2G)8kGMm*q#a65`xV5S#9!zu7`!>%W3R5dcJA1! z!#UTv>h{hZe`I&9<}@xw7ROg}3S&hv$77v-Yw2p~)>vEonZ?e<-B{W^JLip`S#|FG zg`tXd zKf3BIyi<3(E_N<{B;l=DG%k7tZ~c6SeEZorpYYbLcpI0!jf*$#Rwld$=Q~nv@2aQZ zj_bB7ZjATEA`d)uk8Q{eTe8zVfBmHcvD*8NN))qdbuQ>{+U8A<_vjq%&)Rfm`~30m z^u-EZd48cssNAvCwp4$2@Sg4NR|GqFhEuB!?_AH{1yE7eqMv=_DSCac;NFUz5p8wm z2)T#uhVKsF>v-RIZ$|K*PC9#Vm-a@RcP&KNzz=PX&TYCM=I+48_D+@+*Y6dXJ1Z^k zm0Rd~o4dLv%!M5SewEly?GXR}6ivzBNUwudS#tX6Dt%GQN)rBBqV(&(A^9PlDaDYv$n zu*CA$qb7bPYUV>>1zLz2qo%0&`%*1tZERCIrPDo+<$cyZ>(Ia#4mm$;Lr&DK`j@Di zi7nEaez;YO8fInMYNJlMTx>@@*p3v=OT#rOTZtTZHfvJb<7W9jwwkPvOEVTqN=W4_ zBll&=0$*A2|D%!mG(6q|;&Klr2$n*UC9Y^zzm&mob~IDZ?4H zvaKu|q3aDz?QiWx4@k8F$Em3y$SoKC+?uCu&XcKDnjQr5A%5gq$lvScFSQd3DdwUz z6WPG!a9+7RoR8>*Sx?jxR&u|lD%4R-Z|i_NH!?TbI_~nz4zx(%#=~YJBPa&9pwa5DXVM%J@J!DD&pdMjjQylUNwzd* z!e_y(iwLVE@IfLGlV#E)k<5_EOo_hS(dZYk1To?DD*#;;Yy&_o#0`XIpb`XyfJEaO zh|lNzfD=Uub!VghD9B&P+8`5@fLwsJkS1yI6M{}ei6f!5e!vl<9Lk~mWm31b5xqj9 z1(4F4qO|^6l=WQYz(7wg!IpgkM|;opbPfzuUXpR<^H+kCew7ieM=25`D#|=%W|V=% zzy+?2Qgf(vvapQ}5P(*RVg>C@PtTmK39W;+B_N!hN(8^$%n;yGQG$qv6O2EQaP9^S zFT=SZ#R~^{fYqM^cuVk*O&ZEJf8-g3woXHwCa1z|R76mRVO3xiNKV4apP9TmiEdFk z-G6-)FxKUuKXi2zBrw+)u}DQkEYehobobFS8dUL4gG7z{seKp(!W$6 zxqkzZT|HB*Vh!V?R~cGQT+<9>(3o2CEXB~So203n4I>@d`_*6Y6LEJavJ863+9HN} zKLnm)$E+Cu!e#sYwQ{xE{A>C^WZOxp*F?Bap0fU0^<4n_!ed*9n5lsu!#9tYTowR&Y6@u({526nO=HB~85{;u#$q}kQI}r3nn+QNpE?meq)EzT6_I0oQxo)} ziZ9S6(e{gPA!U350(~|OBqU74EgKsn#plH4H%O(bIDcED;TiUtvb5TCBHKkXtaf-5 z^r3%8Gy0(CC$xh{wz0OdG%SYvs%!fX4L8<6IA>GlSEK|DSEuN@$etR1t<)2gaiB5M z-Oeyrsrlg2ND#`c?`G<&{pcLA`EnB^oO3crLa4?_05empB&#&d3~6c(4&x0KpD{Q! z;yDUtd|b?p%^>idjFluYN6L;hkqZtF0;lD}G!KZO148;@7z`$VjP7*M9n;v<=%mPf z=AZ28J>N3`dG!ehyYbz1wEI~|vCScD4`GH>27G*!lFm{kj=xY3m<3?0wZyS?FN`c)5bRr$CjWkulBB7W zwb5X1K^wjKcLKKqv6FB1zS_Iku@qP;Nt7N;cn{56kkNu+VduiOh1vM|c=zJdf~)C) zwV9yY7WA9hE@t|uxODFLYEjADG4ZAo?IkSvPj)AdJe$~mA+h74(DIyMe?Dot#LBgp z{U|pl_fFC6qS(&3K9N%yZ&}XSHlMZX$VujHUv_KK5%Y%>_%Z9=jyC( z)+@)8)^2ujK52cHUDPG5+gE+X7#CaldqZ}+_Q zLx+!X@$L7j{AA4# zDZJyp?T#BCc(#6oNVa%YJWr@@zgK;)Q0TrON7-yBO`6J37n_=3`o1zdH2F1sSP@RjOkn7MrW9*f5mTxl2h}f3z##jKIpr($`v+z@H?3yF zn1ThXF*ywrPf~}lf@~|j1GxhT`#vy4X0_%~vnqm=%K|o@3!$jO%BiI&c|inS`5XzRQY2+(au0dG$m?GSipQCRzZMby~%%TLzfXTP30#8*u z4A$B4hGzUk1U+n$bIc^mfN1p)MA~Z3CQ(ZAUt%19x?5%qUo|Y~Z{>?u8rfDy_v^$U5Y0Y1IXwgF3bI;y zSP$YE>LZiE@p|as;US|5B3qk`gk+TYuHFZ^!Z zy;8x|lRWqA%DI8%a{~{oUwQ}#-g?uzkaNrND8F#7^I=}$E9ZdddvdWWnM>wP58Xwv zt#28V?ycBUSDl`hPux85(y4iU%Hdqd5%L3xoWSDXQuuc#=-Kg`#}}Tyb&@Vm-aHx8 z|9a2kY~+G{2lUm^@9bO%zp`&(d+efMuT7c)s}A?v$-n=sM(6abIJPW1Kn)qt4yx|H zyH$7d1lQsBhW>QyhuC7CR_gh(<690UCC*(7(bD(_d7WO}dtP5xmGQl8JG;t_KPorl zI%Q`1uxWb`jfoL|pQg~)pSuTXwB5u#h%=N?MNMs+HPt={J>#kx!&GSpLS@(Pdrfm*~qkP{neC1p}cgBFaJNsVr82mg>wGV z9VOe8MY@y9Vi||{w~!_DWe!vJ#E7Qc;32zv&vy4;80cv~4NlUIwHK=S*CF@iX?^AQ zQnUh5`+1ZGX#)UVa|ovCHZwpCwAY;1A&(te@tuu%4tz&JfDqWc#ug1bquHc`~< z6-&Xgr66WWTKucUTi!CpkA2q}&lZXsSBiHp7w=vQ-R(#eKQ+(T5l_oflhAVHUZe2z zGs2nk!ue-K8vc7WQ$pQoA<*;KXee+!Hky3)c?)(EPi4Gyu|RM) z3t-4J1>2LBs@1}>*N5VDuT2T%jY475O5vX6!aaA5cl#2B?ep1e9j;w0TXZjd^#+8+Qp@6biv>#!LhVz6zg^gJWPPdFGva7&jbNpo@f5~t&!O7=ggB&$V? zUmy;&8fhz7rMdYmx(%VgJx%i{ClHj zCs-YYHTt}K75z>}r0dMNevxqioeesekWr?n1C(wW$Xr;KLjam5)fsFlv^$aNA#}@w zOtc?pBy*Skw+)O=O=V34A)Miunhf8A8m~FYND8}9Lq8F_q#VPaLC~{Sq=5IZ5Fx87 zKWJs}8x4L28^4{y_fzC^6g)!#(_A5%J7wl(CZH;9@SUM&3$^p_u<+~~3mnaydfT-^bij_7=rE(_B|0!Zz#7qyB zA(+#BbhlHwKNz-nvmgVz{J;K)gNz;MHCX2a5(X!Or_Qv{G zp=5dB_JLOp#aq9(@3;1ScmGP&uH~v-iK;zYP}5$*oA&+;>ga^Kbm^gJ z^YV)~UtBW&QP#i6iuv9we6{ek;+3Mh<)XS|QT?BE+%x|1alzgBz}oqle%Z9 z`@{3twPsDTW~{Mb4X)N=(&lhkST)qvSV(zP3vNvwKwPU7*OnI7zFre&vKnz6Qe0i?mM_pVln5QC5kL0mj@}n-~RiI^JqE^nxlryah`biEc z3t7wS(FaBBsz#Gbu_l)iZ7yn@sGBS0%2b^L?6@|m1RF}&iG0gZw}-5bdVW<+$!*c( zo~B8l#@U#=`i!ffzUL~X{!(^hXzf&STe)q-L`uw=C#?rP>v}L})*H=XJy@v8UF^Z? zXwK$6IQbsZiT$TdDfXI}vPRo$YR^o54=HO|e`_^8v?&9bQ$pQ01I?q=h?=~iX+<6D z9kDLkwK=MBqF#((VcH1Vr4h7G_F>#MtEV`-e(`#4Q|rKq^%Qg5te!N}HmRoy;EpN4 zv%J;;F0Gd-H9g+NTkogoOEoY(l*XtHuqRl?FOS-(I${=(Pb9;fOLVZPzxz1>7GA512Vx?GZ@4h!XVh- zIPhlnQ8R$)C^~|5G8-4xfHik|Hy>Q9U|49IICe5pi=H418iuTX zpR#gLR#LaYXow1>9ORD7lrUnWG%S~hM@b>)O6=sCS8M3RCPvem$qzRK2pbz4-!}Z@ zeMI}opHp08?@2!tGiv#7(5(f$7YvYCGxweBKI4xx2LS0`4MHD&aGb1);8OtRR)p=d z5}}zSsV6{79x4=}wjTaIG6LC7UBw!?WbfG4SK+qBuPH51Y7aA0@k`AkKy+5+$a~k!N@1Psj zx&k6V&*T82$_nNeR2{%>OrTd`5k`Cr93W7w*w_xw@aP&IlV)lNwz;_9xMn`u-hIly z<_$<))!Hm~)nEVStMvJ^!)wmInTZM5`L_9|t{z;o$qGXU*Q`?a99(PbnF=?EwIJl( zUwd6rE)rcZaGO;CY9j%=C{~D3r~D=b-=%=SAs!Mq9b+<>d;pSz(TN~r5#zz&G}I#g zjGht#CaOimag{O=vXsh}-wOsM@&tIK9HO%efKZ{Klws;Bz%){B3Ua{xn8jPl1(C`C zYlLVgc9xRa*bE(jEgJtW`%RkN1I!ZMBM%(}4-D3X_3UNFEwT${CHq9Zi2}@-OztcA z&rs4NMmhA7k!erl6T06U>k&$}3-%4<;G}ZCh_!MxY z2i85SwrnA%>b|XNHNReZdg$)V-4Vfc^nvvlo-P#Kw-vAES4j_dEd`g(3$B9?tcM=u zS4cPg@jL)luG*wE@W^JLJF@C>1ER`y%^h9!SI+f3a{E5jHJS?{`7YSHFePjQPPQ~7 zbUt^cSPT;}5SyS7B}k(=&$)BGsR@fX^b9c83C&=E5( z%*2kw!m(lChu-R>vu4%lTBx{r>{~}3W#=sPed{@7cm6jAC~{Yx}g+G$oy|K=3Vm`R1u_9Yb0nuXQ=Q^=|IHi_80ZHze;Dyyue6XVR17 zmjKm;bBo7>ojvb|-VX|W=LPSxN#})Cf9>MlrJ1|IrAc8|mr!?9*m6v8mOk84yI3T& zcHSFJY&o;+ES*2LaDLUDAFEq-ZzVMaW2_^#OYrYl+Orh6+aly2OnMHjdb|sRw=K5~ zWE|4*?Q)7|jt#}m36-r&=a;&LgU<{3my(_rU~v&^x$V4d*(Bm)o$gSF0bxO>0TVH& z%OIs#u&jE@S3KL6JrJ3}RD*OO(o5(S^3NnaPowCCkr)>XEleamTUR~#v5MP{+gVb_ zZ|JkDf_FUWgm{Z}@;p>aidUQ!%g%~;)dOcW)IPGk>0`84@a{`G+tNFE)rt1sJUM^# zBdhae`%U}8&VTBDd`XWf^%?MGyg#R6Ubt%Lj*rAIEM8f(v)S`NS=O0#{MX55W7!cuBx?iVo0Tq; z%Va3dDHf7^I}EEKms1Vl)n}Xy(l!OMl}jOw1=ZSd)(lBnx_rv4kxylD?lczLBU*-P zYdARx*9;20tSLoNghw5{>*}aH`$BcJqK+OpXC_0lrq$7xR!7l%A*~lDOSwE)x;nXh zNZ3?XG>a=pOIf(F|G6T-2Su}X{5b$2I5iMLwyIZyQ7ewZ7z7Z4hDBizLJ8gHO4A?& z1=fwaHb4k&m}a=SvULzbIm=~B)Q!B-*mISQWe|d!t56_>ybTaSr6!j&HGh@)i+VU4 zw>2{ZDnSU_7=%D|OotGvHMys;+E2<|ea6+Y-VaFqrG*gIk6VsLW62fGSqC9_XMJF! zsRy+{fY^g|QSatG2nfL|^`ADS*lS|SGy~`VA0*Hf4jB;a5{eotX@F zqS-2woCYB@vfdHv(xlB%?Z+tG6LJ-4Bj}Lo=>UY_-n5?L?E1y)sf7^4dWt!2R!^E~ zo77XaP9Do38sVDN-q`>lv@q~s2Z0CNP6iQZAp~a{gwRTWj25blIsm-=ybyvD5W=oO zG9i`RCrKy*v7hVNLXj;06@UjKnV;Fy+80I;HsS!_y~Uh=1xP?zUT63zXk$(I`$U=h z&xr}7WwoBoW2gZCudzSy#KJOOpZ^P7MN}m+nJbd`;u`*UDCX}{K#XY*PvSqOY`_>s z(!wTBcKi=;J5q2~bc?lqFe6(Szb!`HFx1dW;D3*DWt_cB%0p)EMMObLD&3?MjJqOs zHR6;~uqsD#wM8kdAoiaBHx&FY6bKY7Q;?+K0R_az^FO9w1wo`KASyTbC!oPc8g0-S zgMyj_vutF$8T-z!Qu+@lNKq!m>sfKu4#tf0|CVAsq*(c2tI1PfdQpx1zoQuco`U~C z!6OPjq~I?p_$vxNqTqi;00VK-vf$V8s{exS%}}tHf6|AU6~9 z%Kr^L|04>BW99!h3hq+yw-o&E6#OR&{tpU>JLUgR3WzV|L9grhk16~IauJ9i zR(dGvW0Z=+o%yBZ{|;#r#DZ=&F%~rUSI&Zpx_80&`9)}WG$u_=k1S5D(uTWY-t5R+qGG zTXh$rs3+=bNIDsXi^rBO3EMjaf2XjeYkgTYQdx|3UV@VTo(I;wkKFml94aeU7HgNf zgg~26yI&|fAi)0JqH^0?I9b=|_26aU3n?3EM;((0Q%mLa0 zfQ$zgI~Jjm$iQm1Pu4Bpjr#v^o8!nH-4B~vj%+u+Q(?pPJKN1iS}pH18|k{0g?ro` z6~=e7aymq3WEDn62d62Xld378a^0sp5WpipOqwzogpVBT4vK`BgCc)Gs zB97V>joxt9Q~`5JyP{>V7n?T zDJO0IN=z<`4WVU3M>YUlM$c>D>47c+Y0Fmi^HqFNMe$VZY(#O`0yR~otPyyo1KwuF zACzpMwqv+-2WmSO)oBSx1Nxe85Rd0CD= zExrkL(IPpm`mL%z!tG6O)RxJrjLTL1zRlXB_Kb0q*1xC^!3pQ6E@P}bpt^FM9h>B& zH~@NLPO$b;a&m5xlj73ni8*QO1g~xx>#ZDyA?Ae9bcIXhUd*&ZM-^8fP^B`DZIR=u z-)ao(;F(KR&@-h}&y!2#3cjg}dN%rOhWnR{C8%>-etY1sq(ZJ^)ElmpujRhx%RZ+D zg{XlyLk)bBo~ZZh&hR!l$Ea5+(>G~=?VfLwIx48X5TGp=9Q3pFHov z0l9a=+vO`&nO@FM{+=yjqgljdb_J&F8sbhdTdY}Gm1k)?*5|r!%A5lf8FRSOVjXOT zL6^^#sIj6N*H5?HY071q8bphuMbRwU#R6r6RoDPU50gyONYtE?&ZJ-#uu$LNW`@Xw z69fsgOlAli)tJRf>Ng=j*=$0`!)_<^M{zi`PVFnrb%UtuAQiSbZY%q-tR<2LXN!=c zd%cLRg^0|lCn!&&Ng-KnrQc-6xbQ4QR;Hr!q41T#Fz{Y-0R-c!*5+1%tYH!hl@-x- zB-50a92bcQ>tA4!FoZR-v*G9eL;}a)bR8#cpg8KwTBe>w9(vGuCv8jlzGAn)Wu!lg|7YAH2~6W3&xa?@q+{^eF_2e|oT5oB5~bK=I03faIgT z5I*V+^^N=sX)rJ9#bAC`y`kde|A@7?6^ z1WixCK84sb_EB}qrT*C|_s`oR+adPP+a~@s#D^Se|#H64+m_PlLn9*8j8#+f_8wX}r5Ka+GI)_BL6(DQrQEYUH#D8!`G?q)BLZ|Q<{$a>l84XAL1}omqUS4 zQQpAthBzLjoZ_NHCi8<6DH|>1tR?W>K0Ypr1VS1)!wZz%AO&n$GSVoTC=eGt5#mD* zFz>fZKghJ-gVk^Vaw~@M4Zvdwm8;%KxfG?}5PND@f2W)>0LY%m*0CYUpml&9VPOU8 zCtewGpp8;AT9a~U_9k*XfKeh!pSHryJ|d%Dy!pDuSEI=sO}F0%2hL8j*r1oktm`*d z!28f4`oHN&T05BrA9;mg7t)0tX3vN3UQYPh=dF+OOYe-`9*Y+y z^6T#BBRxbgd6g@9HOqN5i;hHI>%4u{>RquGEnACX&>O6NR8sL~+pBHyi9|{3{gSr3 z2Ekegjl-3Kz;ZzVp7pUW)$I9WP)#BvV{fVLj^R9=EyoJfP zxFmcd6;-bkZC@_h{;`hM=c1a=%=pFt6uWMoKsr~ckX`ezs5JIMqNx7niAO~x^Cun^ zl--Hkj=a^7fN07|d5ymX9})pg9gJAOinbxII?Aiib@MpoRV-w0dst8$JCG=-y?Ojm zLDBs2M|mZ8F5bSF^fxE+TJGoVSvrf>`ikgmf!8M!zJ~k0ol9Qykt^rrD>tt^bQZ*n z2`CrhJ1gPbLf`g;vx>g031@}&+nI1~%k*3u|8bt95S`?3JLZj#3w1X1a^bQSGv>$E zvd6P}Otg=W7~qym8IK=i{UEf|_WiFVY7Zy!p1Ns&lvglsec#|F%w6`v_M3T5 zBGo+R7HLP)w3A&_B~4q|1wC5z6hUiq$AXK@_HyAw!<~;lL<8tCtN}kE+TbUIq5XvR$$&d$m~Kv4u8fY*!D}hYWt_8f73UThrdv{091X>M zuBS}&9QSsRwI??^Gm$b+436P&G{f{xcn`<&V}@xv``rrr{Hg0KFOcBy2|pgO?`Yn! zqoJjxVaHzne?Xx_RI>abw3n*$DOqj7ZHAGrQmLAZf(pfz&yy^qCvheutfV!x4ZJt& z)>%m_;tIJkSmD-NNoR^<25i6XWEub@nPOU0+cudh15{!HWtKU<#`y+2?M4-KD1f45 zRjmj+)VhCPx&%y?qu!OTn2b`F~%?_PK}u6O=59 zO(y87mx4(Ik=$n+L|3Q{?bD+Tl6a5*AL-E+?ePKRJZZmZlo1RcoCyy%?1gg01L(iY1;5-F1(M4s5_vnh~Ao#|hw@s9` zT%oIfNkKOSU!q`;0uDh2LubnXe3=65=l5gV{~Ox&Nd;q0_u=*(w_4YkF((~0cTK7x zbAHm^oMy<}mNe~GEtf|YuPj~^w(d=u_DMGdU*HE=*YMug8z~s?7*_f-_PM2~r?%AmyD5UdIWVlCKv=EvBhd(=f8tum@6|J34^0>|hvz z-_=!7ev@Z$_LNp>R=E#YJ=1|O%5y;N3wnO>$u8_vVQxl06$)6c08)U}nN2Sw6YQWC zW$i+nq>pM}ErE;1C)N|*^Z7l@NkWnuPW7!Wmr!+ z^1$Iy{C(tbR+RV@RH6XZ*oDlQ!~`m&4PnYfz?PYNNE!Vv)I+|g zFGTL`+)>}Jq?dA|xnHoCay7kV*YuKA>LqJN@K)PPmM_vvXxpp_sLE^}%`rI1qT`wj z_+|J){gWTf=UX*nPR!c659f^L%X>0kuDUsd5`F$U#o7F^igk(cQ+fCEqIvu_O?p=} zZ(aJls1fSq<#4`OwJ{&g9nF*Lp(lUzidcwK9Cp#%!hFY`KU)wjpxiK8R^+Gb*=oK~ z1ysj;E5>}YNGUPKpOaD%Y=|i}HOZ0u(@5_g>O=6dcTm8M4mhlu35(9VaNZ+i*vv5^ zjDSVn9oD3N+N^Q@9eGGOb5_ETTN?eMBSy_~PEkZdP-b^|8C0(bZ^|n?4hF3Yh`!&+ zjaHphhUke4?&rIQSwaxXBO|ax1-1fxE3}^u*@bEe&Lf8yMl}iz` zgD?7acAO76cVAx?{L4!ZC1gQU7dv4BJ&^QEN8(BSP^;R+GGH6+;K^?!0p3ts0#tIt z-_zUAj>ravOs1eLC-ey!p~A0u?U~aJJDXbrjnVCiX8INI?B;+yl%Frff}%$SkYINP*~jTWq#6L18}XWv(Ro-=MY_ ziN3IR0+T(Ydrrg%EQ11;g@pe zGBeN>?M}hy;lwWy+&fHhvf$D($cF=kjJ)9wP-h;bfQbZb^b!EIn!F05Q_MpNPD|O? z59Y_xC5@^4NCvwG*i$D-Zpbv1(MwSNW+y3Dq5zyj1;PpEAX4U5LdzIBhSRBdIM$@! zDN|?=-sIn+YBJDFj6mh3T=Mvc#iq=R5=)t=ULj&no{WsSnR*@;4jCW3gc_|8T}-PX zTx*u=;CuQg+>zzv0e33f0yl2OWv^|+HCcE*Ec3s1Ztm10U-^n}>#}ca!dE?aDrNCK zg#YRC+vRT=zUTNY$Kt7ke_tY}4aktM=u=&}Z5O;Y=N8;KcKcZDL?XB5es06!jul_) zvagjKL3e)O_B|{JtQ0gX7c?w#zd!c&*!Ra11^XAEaa$nxs#Xj9LP70f=hD9W^#@kB z*2Zj)3QOL!ylN5rI}?Si_X`04trWB`7qlk|I_8gm;4Z*%T5tBe+OxPbQQGv0&YH7h zp>wrl3qeM&9a!l6pk&Kxq5ok?*_*px-5sxn)1NSKBt$8%ig(6$$9fjJRtrkw-S-O` zRtqcM%ziaH9!wV2uNGFV6xJ;l)-CROP}uS~2iZQ()fJUeP2%=M;r9E5EsOk0!QSP9 zy@`Uh`Q!g~V?}m-!HQJJ!|`FEv_Y)Nsrv=ZtA$%v3Tu}OYvEt1uxYihdZn;oxv*g| z_@J=$6Vzqb;|BEe<0E=qe(_w-s>LH%N>@utV;5p4V_W83kFvMi&)yc_vEr;>cGf4H zjdNWeSe)PSGMukzaaS^@h44y`Y!aM=NpMm5nG7YDq=4@aMr_ry5Q0{EfmCD%)Gr-oXnVr|bx`7+@L?W+EOZ_iXD7$gyhoFpgDDm{wYi}*1-;40?I@?} zpzSuz8NcA9xNMUDi)Z}e955SkLBEpzaiC`v9xAFRM}R&$fnEo11X@46WiIB`#;tAH ztpZKUJ?o9EG`%P~O=Vt|-hkh!w4Tg{st{=zvJdBDrR0+Nn^tA@)+tB}F)!F@#^&qt zxyCl-3iseV^^jysbEdfg9#f<(P10k<*3RVML}-vf3^Wmml#u2sJK%*MMRvvU9&Wa&zNaWq)E}56~)-JQ;TBl^;y*(@9#h37Y%~mMuQ?1C)d|b z-mVl-vI z2FKx^loWko-o@$$SJcO7Q}3qW5~|36AkE2=$8ay;)||)j0>vblNp>3n^eAN*znrp3 zRRHesE@i|3sNbfDR=HnNcKK>xI;EdZS-Idib0)#4wh&>R>$Yc6UR8$kcF8zw09py- z!F9k&h`)*|^JVK0N$a^)tBcTeXT##?;&XS6g8e|!bdb)D%!}`fZ(lqw z_;)S6n8nGq=V(TiLN`$`g6}CGZzGu37?H+7mjwP+fDVspU?-##aywsTp?EA61 zEuOnzT6pFar{HdzgM+=c)h#tY&gqJIf3V~C_rAS%>Eu1{gYBK)t`u^*=1w5^DBHJi zB9V;^Aj{l3ug4jg3$~kwAf6I(cP$Mr_1$#~-s2CP-8h*-$UX6X%llP=w#Q~_DxOgHP65kOZWi1Y;BTWQ8i1ehq4>sF74Os1MjrTE+*eoIe)pQv421Tm+g>g z-U3w|9X*`IIj=sC7e{}q09?L4O?gXEwL{qsxg2swuI?Ii`XP39b(|GdQta$*&8`NS z43vP)-#3Z*z(<{j?dCbmEW-PS87BWenEd;IC|XhTuZlb0*b}55v@dG07)|7E6nngJa%c=ePX+s>fqgt`4toEC8^2* z7m;WLwyFaISx+g5_<{<1!0T3U5XVvz4@jH6xM$M#D|=@5=EMSv$fp^f1yvLh7cMI*eU8REO1jqY&10ZyV*${z@DH12dj%v zBnS6<*y-|Z(xw>65j&7rX6as}qNnS;%I%+OKhkvy{$+In$yfy>X}Brd}3N-4t{d)+@#&douB*}Wt@MO9R$|q56ujb_b|Um zzeNlJta=^Ef#1K?YRFE88hSRfNh=TRLT~doS9&%nNawl zv(T6Z4^M~#BWW1k!{{*(U?Y?d37RxW%rMsz zcqX#V?3}WXvP)wZ7fXcQ#}nDzb4NdPgPF*4%{A-C$N?n6)E8DfacL$(k^L-WQ=Lie(0Dz>MU4Gfm>D=zsj9 z|9xnm{G%wT;HVy{a57DeuE}RQ_|EdYl8e&?b4oqAHA7!harmyK}T+Ck~!PV zY<+(ZWAJM(rpy6n?z2Yxf$hm;qN@mLafC<6Obk`jM3ym6W{p(_aLkHYt@~`WAYzAd z*w;nFPmvWJfvUpGmLbC^0K7}vz;5BF42enAKdH`{6e;BPL@lovZq=BO5ghg>5%SNOlnJ1T| z+T4Qu%+2i6U_+j70vO1koI>#cB4-b4n8#cHJw))zypzCO3xHc^WUBDUPEv}OcuAI*TAaU0Tiz41l`>$0 zWxkS@TLNnN76fUpIUyI+xt}f|_;2-hbT^HeUXv$lWXagfER4(fs?3W6TS6ql-fbk;($qQQ%Zj&Wn}{SiNWa*wFhkF90OQc zsz~_&xb#WQ2!dB+K}w;=X4-wUp{s7R4kX2#$PK&9b{DK|1}rmyRG1^^?z170J9JWn)9i%pAnaPRua=r+ChsozSm< zLu7;6sYwvu;e2TdIw`rGwT8|w3yDp3(j(G|6lL13fsRwXeO;Xcut4eW>H`s>;btrx`HUSapYPRp?=Wjm$(hIMDbve6X)mgCOEMIn($Bpr4VzUpN4Ue2fD^CBi z(+^L|*A`#An=e#6^}yNwxP&SV@x2rNu;Nz*M~h%;`ROOyb)H^5b4BvQqPngU6LUEx zy(R;r9N9Vs$0hM;n)K9xSw`&Ar;Qjat&56GvQhbMeUc`-R*M~OE}(Y~Su9CBjSM4& z!&zLL-%vF2fT2QO8f8ZtLV~Cu!m1`Z;#(*!+Yi-RT{l7=SzoB3mL8L&D*d1kV z&?zaQc@c{Q@rXY2nNK{ZQ`5Mn%wZ~?gj`c_i~{W#5x)6T%CwJy|46}KBR~qa4&25} z;J;15NqY1hx?-x>@6t~Oz7XMtRhNClb-)dE7;#e@U@hQ(1Ict)okN6F!S{`PSn7(i za@kp#aBiLJ0_*`<&T|W=fgzA@xh`hoGmlF9ee7zS!tN?^qa4T*pW7q_2isG|NU37Np-I06T zy=UHs%eK==YYzb_qi`?no1aQr%O9Gozjos5C+0){q?ax0SW#6fd6Y|gS)6DJb?T?T z2N;0POidH){9?kPbiXgZkZ|Z1KF~?oqDkd2tu0z{61A9pK2Ol4iUrhjThqiq+Lw@~ z2m5Ri7fRuq3Ypjo{wokb>3&WD6ppV_+o*CX=skFd{y7CuI@Om9I~ohZtu#M0t|zo# zE0R+Bbkp9_9-E{nhHM%;M_mHdlgra%M=gAv+7Dcs`Y}$T&1K#dWTBmH)~<=0$9(L< zLkAY+v;(bf6@iksrsb>gNrB_8ewlnpZAYDNMKWOu;hqnK?vsRbj;KTB@~)8@i$nE4 zgx}d*@vIAfZv1(O^TQ!w|dF@kqgy zvfe6VhgX%ejdRNz%6Mbec_dMr=hgvD`}{0b1xr=QQdO}Hu|T`&!c?Is>gCPwKE0K3 zd|p+dJ8DyXz~KNcqbyEDiP=cyLn>d!RHTHG=+SNieD~}7{z$gRx zW1r2}91ocn&0n|87r<{x0k<8!qxG&`FU_Tb^>YbANl}pLnmmGZ4Xl0Ilw!Z;M=52a z))%(gqmx>n)J>X_nzixOUXK=HhPG%)3HZwvYvEQ^y~q4g2Wh^z9qN39Vtz%M&~zs| z`mHtUK}~m&5BE2;KB+P5n9pgCS`ThF^Yp$)E3UoayWtD$9UQ?c(68)m8pjq)dN=3? z;SctR*i*2n3QL^%1S%$7Q8&sbidcUxMx00rNK}tPc}e85aaJ`u76+uxpq~!mBrzD( z5$Ajo?ZfyLk+vEgmJV&QQ!Y?2-z1lz@u?7`u9{51>SW3SYUm6AB@jVvEF;yJ09PXM z$QKH{W#SC1(Xb?_t&wD}T2W;t@vG<%WxEtxEra268D+bXz{bd#1tdDU5te(fBR<-If-k>YL! zwa8$KAAKfHI8sZOoPIVPJ!aoI} zekLMkv7idazH3LhgE$R+W*nBx>dO%!{|ju6i>_{*O=@q#QG@yedib2i6ZpSFo7Uj^ zoAm(G(A(?)D>_AYbaDpuYUKX|_4gwReoVoK6#OLxe?`GZ2-a+LmREPru{QtO7Se>6 z07O#JQ!B zVv|`ad}*XXg8VD${#q|d-h0oXJ=Q>KtF6A`nvmJLfa=A#jaz*NRO9Zt&AU$ zE6Zo=G%a*9Aq^nLzm2k-n69DwAnqXw2b@sAgvEQ3*1Z~;_lFMAzs3Hf^+4L~LKa(e zh~aqIdegd)v-y!$kcQi3F}ZzD(zI8VcZ-7ZDWR-Uu#>cfoqT%^vQ{CL@g|^sNn2zK&9G|sqx1dzcS^ZXMvF*EG6RP(Jb~62C^`e{m z6E%B;YG|nMOPbo0y9X0B`-JK?!A=Jpe`pZ}@8m;uwS;_h@Ug?>bTt6o#g2u15^En> z2rUF-J7UAJXCXfK);w_5!j9J#_!y_s`&i#nm#>yo$3u$-93}R}lRJx8@|{U*E2RF9 ze3dJ{+GSsD!dEwUYBi_qtt~=MGjKRh>02(r)0i&x$0=WrS`K}xt2VB zekti3)EpPZT+O;-p;$1!hnX4Nt-iNKcGQ&~LE-$cFpRUxt|YCa=n7~4t1sfr zt!wwUAAIO6iFG6^T9yvnD}rhOJ81xy^BYg3buukhS0H2+C(n(m#saM$xwpewn5a6KTYJXro^4JJB9wLxokyh1| z4GK9|#dGki>=GyBWmamSWevE79ru$KUN?;BxvbZXBZgVy zWR@HUURRBrg@Z!~&K@;#4i?M#x^a|X{p`q(kIamYI4us7tG4xO9{o&86o z(eTtbt3+&Q7!LCx$TZYguu|i%hL~!3%E(O(F)}b^ zgK5~{2z(n~k&|KwnE|7eIAxI>H1U6k1^jIii~KHa9mGKJKcIl_%Q6waxCeL#E>qtR z406L{6h=MH{}H178m<3VQE{yQPFPRfeilAz;^&tEJr|b4BI;3D)#A0K7ooMZoZF7$ z6NEJyl9e<{YwGMVjKet>1UOidhtUdc&MTs>o-${I} z1qd_(#v3?TE$x|x{nA?D0KtavTed=(&C)Pr7LC@i0;_?Yvuas1O?=yW;0HctG)IHc z>$R?5Oli+0Yi^no^Z~w()6nsUqtIaOLzd2Q5=EG7GITb^>)dK?P|{x((1^ zCtgi0lfH!k3Vv9uVz$qOZ3HOE8aPfnb(?0>wz&0wsVK z_QsJ$f6a515MCZ@XsN6hFLqR3su9;vxt-~m_G=blwu(a;I|%JO|K%XW81RZS>7SYw z4ZGP2F3G=HMcDz(>DjSbvHL?<%CQ8((UZS2H~}$A8w`KYKUag3m12dIeMW324)T@? zQd-<8I{EaoilI6i_7gJ6r)>kfk*L%yHBwUmHm*(cKX>*N0~y#(l)h21I;?l7S^^f8 zwUD_(MUir!;$Y#P$hHo7CP}*?bDhd;x7qpGh|f(mM!cAI#8k>@aU1d|#`l3Qi`b-G zz^*$^VasHV#}7OEff|E_#oQIeRWR0)vWfW4KvhedFCDEcP(+?KtR!72oVj?y(+b^- z)6>uABl+K=c)yKclf#K=s}m1=%Eb1$L}!a^7iApZ_bEEtO5;=u#&Z2FT@m9ZDk3x9 z?*;n#E(J^==E4=d3+hMQe0>>SLjGT&jNhT%_dQ&|HDU9{^O`=#H6hLhW>h|%t_v#v zLx-3Bq_c!c)z{^Z7my-u!gXlw7-MkCUk}AwU%L^zinD5E-R1f2g^`5|f_+QU}?yl<4ZpZ7^eV#qRU~Y0H?Vq6kLZT_k>mPj`*%c zlc<9H(LY#<``6u%tI&?ms#T5R4JXfj0eX7~gQyxg#g#Ygz$3QT@zjccSnFEEpQMx zJCGv{mG8bZs8pEt16F%#-QzxlPc>>)nGdbpZ)v4U>q|};Lv^Wif4~MKRjn$uzh}nw zt|2*9Rn-XQd3JYZc6MgG^V{cbT*C;0Co1H-X8#V4@SG-QBQhd*mh8d~)LGeeXXmY* zKkR-iufdkh@sWACS*>Um-x$`bVJcasB`ra^qo~SgQm_o9E7v;y?;u?T9QRg)bh?p& zZlna~?s5=V2K4YnIcOCU4v{Z2{b^%<%sOYB0P_IX~0W8(aZu_S_ z%k5q|TGCJ6^cw2$E?dVA!#H}EtxeH)tf2Qg?;!-8f`#N!gr2gHUI_fDQU6W1a2uR< zmpRFa-V3bo%zs^BR}-Lm5ae?E|X^GQ7B2^r$f%Z7lXP z_7PyW5fxCcb+o9Lq)(0JSN2zx5&B>sp3Ml8gOqEu#n}HGCa;~^*Eb$PWFFy1XMmjN z@sWNOpX`?rABf|^A^?LE8oe?h90&Tr#qo)@_LpH4N&3rRROH6^NYmulIbIXrSO{=x zbD=7T1`0qb@;)NK5X9kyk$*EmNFHfOyo__!E9WjE?hf9_^a_Se4xFUM3~))_BAQI) zrh>1!^cx;X>~ACx6al5F)?EdeIX&u2{`Y2*ru0K%cD7`-T3CB6s4f5Kh= zPAmSWSU~_qUH>%{EeM>ys$G}3K406eRs^2Nt2rv&vtZjxAhm64Z0O$UyQdcdYm?#V zn@=hO*+7s&3$H_HVVftbv}6N~OBS;Nfsw^+jrJn|fW?hg=XRBP%{eYZ#X(NZ6 zf#%p-YH)jUBzY{gQT6SINS6ZJbS6W|?I}P`y6H1`)163Mm{&RwoLW{?xxOT|RU7uJ zzWxR0filswdsVy@5uV*`U!QNWx_(B^`VsfWZm*u%_e@z6A4M^xE$gYxB1UrS-PZUw z=Y1_RA-Xj3S=WNnic8Px+h&8mTK`~ua&5{tzhU=${hpaOa_;(sQ|;)PZ|cc5G{@v8 zo`9yH+NEkz$rNSCYD2f`+r8l2V{GnM)xp@X+Oi`VNsgtuRi%H%Mq=%u*~yfBzOGk@ zwGj&(CUNo_swxyW$F9YD;}h}ks4d%7-;M?6H%k6@{|CAD35KzIaf;;Hs⁣oEXJN zN`G=^>OlH9+#(%E7Ag?Zs4B)jo}y2Wf?)fA>N@y^?T{|mE(6*mOC+$J{}?mb2sVqr z4Et+H%R%eXb=n{e(SqQ%Qj$wvgn8e~e>&J$HsVeRx)v9}n}|vSI1~XK0vKJ+;X;ol zQLvCVeQi4}E7Vdl8T^lGu>$6@+ixJ=W(h#*Pg?8~qsbF;j{y2Adafd8G=RH(4dz=U z>aUpk!^-v^V#64Nbf{_aJWMgTB?h*}!HNnC0Fup!^%}{@c2}=tRN4 z@VoGw+`J!xg%I)dF%|BiWuTXmlKsBHSAlDre}R06M?*IH@FK-S43k(U{39yFjqjU@ z8vGcP4L5!tVY1pSyzz-(%N?jBCTZYZET{0{7P6T@O2WU+{BZTO$0}+mZ2h z%zL-ZSaaC_aL2vfcX$6}?`NkGv_9($@VH>XFPsgU9W_Hs=nSY8e*S$3y#?<^E*Rq6 zUg{i^I7=tmdUKV-c-WEQVX;+b4|NXj+mpDQGhK;@$Ubo#@ueBjcCh|WT!8Z~{qS=x ztcjN{oNF&c#TJpM>8G4?7Osqi!&ky$M^EbO@GVL>5coB5zoEROEW3K)(pb(peCXgn z&+y^ClfwgjImf~NH{TlQ3-t{4h5IP;LrQ*53AvC6{DAmYXfh>ZNOEQbodm>#`|w!! zdvx~4l+dsVr16M2Zh!rPxW7^2rKi>{6#R6^QOdvQD(z(v?xSQECEb+h?)8&&c%KqJ z{kUNRH;dqA52Whn`W`NJ5=e+v{V+|a@NX&UrhDu}@(4yeiwpQCMShB| zgld|xr3!^rCV{|ZBlOUg zCsu3U$ds%{(ac1ff`V?@#_6KPKC?Dvjt$0ax3**~b$JUiX$U`1vnm^?&ibpDsxC6- z%euT8oTZp=vC5-ah@l5kv`Ws}B(GnybJjs;WzIS!w@>4x0cNa@nczn!^KO3SocT58 ziAOXEBr!1?`sIy0vDyK)jy1?MwVq?FZWf(KG=;7qI#;0T+eg)7Lz%Zv=J{#u zka-+elZu8gI>WO#M zcZV}4&ZtMuWcttMc^(a#KiL^)iL+UU9QP)AKw=*xwi4+{Fmd$lCD~eSQYD|}k(9=$ zd&%l%eT-%k(fEjd!lGZ3IV+|dXKBji-NZgWZjzK<7Io*mol%!& z#k`;n07l2;*Kgo-5gX}r#VoOrcqhD-unl`_ z#)ExuHz0IpAQ?%8k{>>7%xvmOcgR76wNMp(TRe;ZeGo- zG*%!@xRc-=G;pFEmOb=!l{i0S zs$ju5ZU>Su=ZR>pxn7IftEIGz;fYJzgl4f)~{bUOb54!zLdKBnCAJWOgvA MJQ#XGEPr?Z8z6~qc>n+a diff --git a/scripts/create_jira_issue_from_gh_issue.py b/scripts/create_jira_issue_from_gh_issue.py deleted file mode 100644 index d968835..0000000 --- a/scripts/create_jira_issue_from_gh_issue.py +++ /dev/null @@ -1,387 +0,0 @@ -#!/usr/bin/env python3 -""" -create_jira_issue_from_gh_issue.py - Create a Jira issue from a newly opened GitHub issue. - -Reads environment variables set by the GitHub Actions workflow and creates -a corresponding Jira issue in the configured project, including: - - Title, description, labels, issue type mapping - - Assignee / reporter lookup (best-effort by display name) - - Clickable cross-links in both the Jira description footer and - the GitHub issue body footer - - Markdown-to-ADF conversion for the issue description - -Reuses HTTP helpers from jira_sync_modules to avoid code duplication. -""" - -import json -import os -import re -import sys -from urllib.parse import quote - -from jira_sync_modules import ( - _jira_get, - _jira_post, - _jira_put, - _gh_api, -) - -# --------------------------------------------------------------------------- -# Constants -# --------------------------------------------------------------------------- -JIRA_BASE_URL = "https://scylladb.atlassian.net" - -# --------------------------------------------------------------------------- -# Environment -# --------------------------------------------------------------------------- -JIRA_AUTH = os.environ.get("JIRA_AUTH", "") # email:api_token -GITHUB_TOKEN = os.environ.get("GITHUB_TOKEN", "") -JIRA_PROJECT_KEY = os.environ.get("JIRA_PROJECT_KEY", "") - -# GitHub issue payload fields (set by the workflow) -ISSUE_TITLE = os.environ.get("ISSUE_TITLE", "") -ISSUE_BODY = os.environ.get("ISSUE_BODY", "") -ISSUE_NUMBER = os.environ.get("ISSUE_NUMBER", "") -ISSUE_HTML_URL = os.environ.get("ISSUE_HTML_URL", "") -ISSUE_LABELS = os.environ.get("ISSUE_LABELS", "") # comma-separated -ISSUE_TYPE = os.environ.get("ISSUE_TYPE", "") # GitHub issue type name -ISSUE_MILESTONE = os.environ.get("ISSUE_MILESTONE", "") -OWNER_REPO = os.environ.get("OWNER_REPO", "") - -# Assignee / reporter (GitHub login + display name) -GH_ASSIGNEE_NAME = os.environ.get("GH_ASSIGNEE_NAME", "") -GH_REPORTER_NAME = os.environ.get("GH_REPORTER_NAME", "") - - -# --------------------------------------------------------------------------- -# Markdown -> ADF conversion -# --------------------------------------------------------------------------- - -def _inline_markdown(text: str) -> list[dict]: - """Convert inline markdown (bold, italic, code, links) to ADF inline nodes.""" - if not text: - return [{"type": "text", "text": ""}] - - nodes: list[dict] = [] - pattern = re.compile( - r"\*\*(.+?)\*\*" # group 1: bold - r"|`([^`]+)`" # group 2: inline code - r"|\[([^\]]+)\]\(([^)]+)\)" # group 3,4: link text + url - r"|(? last_end: - nodes.append({"type": "text", "text": text[last_end:m.start()]}) - - if m.group(1) is not None: - nodes.append({"type": "text", "text": m.group(1), - "marks": [{"type": "strong"}]}) - elif m.group(2) is not None: - nodes.append({"type": "text", "text": m.group(2), - "marks": [{"type": "code"}]}) - elif m.group(3) is not None: - nodes.append({"type": "text", "text": m.group(3), - "marks": [{"type": "link", "attrs": {"href": m.group(4)}}]}) - elif m.group(5) is not None: - nodes.append({"type": "text", "text": m.group(5), - "marks": [{"type": "em"}]}) - - last_end = m.end() - - if last_end < len(text): - remaining = text[last_end:] - if remaining: - nodes.append({"type": "text", "text": remaining}) - - return nodes if nodes else [{"type": "text", "text": text}] - - -def _markdown_to_adf_nodes(text: str) -> list[dict]: - """Convert markdown text to a list of ADF block-level nodes.""" - nodes: list[dict] = [] - lines = text.split("\n") - i = 0 - - while i < len(lines): - line = lines[i] - stripped = line.strip() - - # Blank line - if not stripped: - i += 1 - continue - - # Fenced code block - if stripped.startswith("```"): - lang = stripped[3:].strip() - code_lines: list[str] = [] - i += 1 - while i < len(lines) and not lines[i].strip().startswith("```"): - code_lines.append(lines[i]) - i += 1 - if i < len(lines): - i += 1 - node: dict = { - "type": "codeBlock", - "content": [{"type": "text", "text": "\n".join(code_lines)}], - } - if lang: - node["attrs"] = {"language": lang} - nodes.append(node) - continue - - # Heading - hm = re.match(r"^(#{1,6})\s+(.*)", line) - if hm: - nodes.append({ - "type": "heading", - "attrs": {"level": len(hm.group(1))}, - "content": _inline_markdown(hm.group(2).strip()), - }) - i += 1 - continue - - # Horizontal rule - if re.match(r"^[-*_]{3,}\s*$", stripped): - nodes.append({"type": "rule"}) - i += 1 - continue - - # Blockquote - if stripped.startswith(">"): - quote_lines: list[str] = [] - while i < len(lines) and lines[i].strip().startswith(">"): - quote_lines.append(re.sub(r"^>\s?", "", lines[i])) - i += 1 - inner = _markdown_to_adf_nodes("\n".join(quote_lines)) - if not inner: - inner = [{"type": "paragraph", - "content": [{"type": "text", - "text": "\n".join(quote_lines)}]}] - nodes.append({"type": "blockquote", "content": inner}) - continue - - # Bullet list - if re.match(r"^[\s]*[-*+]\s", line): - items: list[dict] = [] - while i < len(lines) and re.match(r"^[\s]*[-*+]\s", lines[i]): - item_text = re.sub(r"^[\s]*[-*+]\s+", "", lines[i]) - items.append({ - "type": "listItem", - "content": [{"type": "paragraph", - "content": _inline_markdown(item_text)}], - }) - i += 1 - nodes.append({"type": "bulletList", "content": items}) - continue - - # Ordered list - if re.match(r"^[\s]*\d+[.)]\s", line): - items = [] - while i < len(lines) and re.match(r"^[\s]*\d+[.)]\s", lines[i]): - item_text = re.sub(r"^[\s]*\d+[.)]\s+", "", lines[i]) - items.append({ - "type": "listItem", - "content": [{"type": "paragraph", - "content": _inline_markdown(item_text)}], - }) - i += 1 - nodes.append({"type": "orderedList", "content": items}) - continue - - # Regular paragraph - nodes.append({ - "type": "paragraph", - "content": _inline_markdown(stripped), - }) - i += 1 - - return nodes - - -# --------------------------------------------------------------------------- -# Helpers -# --------------------------------------------------------------------------- - -def _map_issue_type(gh_type_name: str, labels: list[str]) -> str: - """Map a GitHub issue type / labels to a Jira issue type name.""" - if gh_type_name: - low = gh_type_name.lower() - if low == "bug": - return "Bug" - if low in ("enhancement", "feature"): - return "Enhancement" - if low == "epic": - return "Epic" - label_set = {l.lower() for l in labels} - if "bug" in label_set: - return "Bug" - if "enhancement" in label_set: - return "Enhancement" - return "Task" - - -def _find_jira_account_id(display_name: str) -> str | None: - """Best-effort lookup of a Jira accountId by display name.""" - if not display_name: - return None - url = f"{JIRA_BASE_URL}/rest/api/3/user/search?query={quote(display_name)}&maxResults=50" - result = _jira_get(url, JIRA_AUTH) - if result and isinstance(result, list): - for user in result: - if user.get("displayName", "").lower() == display_name.lower(): - return user["accountId"] - return None - - -def _build_description_adf(body_text: str, gh_url: str) -> dict: - """Build an ADF document from the GH issue markdown body + a footer link.""" - content_nodes = _markdown_to_adf_nodes(body_text) if body_text else [] - - # Divider before footer - content_nodes.append({"type": "rule"}) - - # Footer with clickable link to original GitHub issue - content_nodes.append({ - "type": "paragraph", - "content": [ - {"type": "text", "text": "Original GitHub issue: "}, - { - "type": "text", - "text": gh_url, - "marks": [{"type": "link", "attrs": {"href": gh_url}}], - }, - ], - }) - - return {"version": 1, "type": "doc", "content": content_nodes} - - -# --------------------------------------------------------------------------- -# Core logic -# --------------------------------------------------------------------------- - -def create_jira_issue() -> str | None: - """Create a Jira issue and return its key, or None on failure.""" - labels = [l.strip() for l in ISSUE_LABELS.split(",") if l.strip()] - issue_type = _map_issue_type(ISSUE_TYPE, labels) - - # Determine priority from labels - priority = None - priority_labels = {"P0", "P1", "P2", "P3", "P4"} - for label in labels: - if label in priority_labels: - priority = label - break - - description_adf = _build_description_adf(ISSUE_BODY, ISSUE_HTML_URL) - - payload: dict = { - "fields": { - "project": {"key": JIRA_PROJECT_KEY}, - "summary": ISSUE_TITLE, - "description": description_adf, - "issuetype": {"name": issue_type}, - "labels": labels if labels else [], - } - } - - if ISSUE_MILESTONE: - payload["fields"]["fixVersions"] = [{"name": ISSUE_MILESTONE}] - - if priority: - payload["fields"]["priority"] = {"name": priority} - - # Reporter - reporter_id = _find_jira_account_id(GH_REPORTER_NAME) - if reporter_id: - payload["fields"]["reporter"] = {"accountId": reporter_id} - - print(f"Creating Jira issue in project {JIRA_PROJECT_KEY}") - print(f" type = {issue_type}") - print(f" summary = {ISSUE_TITLE!r}") - print(f" labels = {labels}") - print(f" priority = {priority}") - print(f" reporter = {GH_REPORTER_NAME!r} -> {reporter_id}") - - url = f"{JIRA_BASE_URL}/rest/api/3/issue" - status, body = _jira_post(url, payload, JIRA_AUTH) - - if status not in (200, 201): - print(f"ERROR: Jira issue creation failed (HTTP {status})") - print(body) - return None - - jira_key = json.loads(body)["key"] - print(f"Created Jira issue: {jira_key}") - - # Assign (separate call) - assignee_id = _find_jira_account_id(GH_ASSIGNEE_NAME) - if assignee_id: - print(f" assignee = {GH_ASSIGNEE_NAME!r} -> {assignee_id}") - assign_url = f"{JIRA_BASE_URL}/rest/api/3/issue/{jira_key}/assignee" - a_status, a_body = _jira_put(assign_url, {"accountId": assignee_id}, JIRA_AUTH) - if a_status not in (200, 204): - print(f"WARNING: Could not assign {jira_key} (HTTP {a_status}): {a_body}") - - return jira_key - - -def append_jira_link_to_gh_issue(jira_key: str) -> None: - """Append a Jira link footer to the GitHub issue body.""" - jira_url = f"{JIRA_BASE_URL}/browse/{jira_key}" - footer = f"\n\n---\nJira issue: [{jira_key}]({jira_url})" - - current_body = ISSUE_BODY or "" - new_body = current_body + footer - - owner, repo = OWNER_REPO.split("/", 1) - url = f"https://api.github.com/repos/{owner}/{repo}/issues/{ISSUE_NUMBER}" - - status, body = _gh_api("PATCH", url, GITHUB_TOKEN, {"body": new_body}) - - if status == 200: - print(f"Updated GitHub issue #{ISSUE_NUMBER} with Jira link to {jira_key}") - else: - print(f"WARNING: Failed to update GitHub issue #{ISSUE_NUMBER} (HTTP {status})") - print(body) - - -# --------------------------------------------------------------------------- -# Main -# --------------------------------------------------------------------------- - -def main(): - print("=" * 60) - print(" create_jira_issue_from_gh_issue") - print("=" * 60) - - if not JIRA_AUTH: - print("ERROR: JIRA_AUTH env var is not set.") - sys.exit(1) - if not JIRA_PROJECT_KEY: - print("ERROR: JIRA_PROJECT_KEY env var is not set.") - sys.exit(1) - if not ISSUE_TITLE: - print("ERROR: ISSUE_TITLE env var is not set.") - sys.exit(1) - if not GITHUB_TOKEN: - print("ERROR: GITHUB_TOKEN env var is not set.") - sys.exit(1) - - jira_key = create_jira_issue() - if not jira_key: - print("ERROR: Failed to create Jira issue. Exiting.") - sys.exit(1) - - append_jira_link_to_gh_issue(jira_key) - - print("=" * 60) - print(f" Done. GitHub #{ISSUE_NUMBER} -> {jira_key}") - print("=" * 60) - - -if __name__ == "__main__": - main() \ No newline at end of file From 3428d7e92a61bba8eaaf142a7a2e7929d95de162 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 29 Jun 2026 13:50:08 +0000 Subject: [PATCH 12/15] Finalize PR file scope to two Python modules --- .../__pycache__/jira_sync_logic.cpython-312.pyc | Bin 0 -> 32948 bytes .../jira_sync_modules.cpython-312.pyc | Bin 0 -> 55607 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 scripts/__pycache__/jira_sync_logic.cpython-312.pyc create mode 100644 scripts/__pycache__/jira_sync_modules.cpython-312.pyc diff --git a/scripts/__pycache__/jira_sync_logic.cpython-312.pyc b/scripts/__pycache__/jira_sync_logic.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2a3bfde524528095035830ddc21754335fa92f8c GIT binary patch literal 32948 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 F{y#+}6E6S& literal 0 HcmV?d00001 diff --git a/scripts/__pycache__/jira_sync_modules.cpython-312.pyc b/scripts/__pycache__/jira_sync_modules.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c7a50e07a054e8b68ca296ad2984a3d12ad1fb67 GIT binary patch literal 55607 zcmeFa33OXmdM1dKSP6gt_e~%vkp#t6qBd$XMN$&Akg`ZwmTZ|t@qrX6ZuJ0477DCl z)l{EQWu;A(Ya%$d$4JU2MW?D0b|=$OpJZlKwrk>?PI?{%s7RyL-E!jTq$bld^3szO zYtEVZ{`*#tpzKQ z`c;!ocSpzRF6uZvXBgLC)U$8HMFaabUNo|A(?t{eHeWQe@2rbi?AvnD!oIB+t@t*M z+a~N6?Rv_~H13#iUUW`mU(9B|&Eu{K_eJ-F=b}fiyQ1T=zN^2O!&xqRIqO9qXSf{Ql-<rAf+rsiB6PQ#AOGIIajcF*u=TNX}VY< z{Voj_7a=O{dT_Ul%VDv~mAhWt-NN~BH#g|#^4QbTU`4PPITq6GPD+r;l-qg2~6#H;2| zPi_mIiM6f>`sG>;TRA^s)Nsgyft*4ZeqF1HA6d^-{9}NGROxx z|IpNAC_FeB4%Pdw1jna?JT3+&Isf2LcywygKRh$ZE<*OHZ+c4U7+74vr6m zr^JV&q0mfFdddeUrmh902*do;#KtIT8MCwlToA1rS4xg!LL zyH9nu<5z!g@2S32R%dTVfA3j*pY4983*TqEPIdJhOJzON#qL`=o)sfnP)cWe-|>{? z>GtlPqi5UcLVRRx@98_+d#bB1W$oxa+jZt_ZzrzK_4W6jMvm5_-Cd_TDNk$fnXa=) zgL{1)7fzjO?>v&Sv8V0l`g^6zj#H?yoz=MOncg$FW--Jj*w1$z>Fz<>PMwOBUkQh& zLv2k>p`jb&?U88h;kKdisZcP=!jSmIMTbXUq`zQ@gl-+Oj2ZgZsbhz z^FCd`9O*dA-e3RFAkU8ujs*Q;$>K6|d2r}zcy#D$$X`3b-iHudxI$Rp#+B77(72}0 zPU+V4Us}`q-`1xrd~kYva3~ni^UbJHh-&FyJKJ<+Y9iRg&rD7R`6gQFnnp&$S7t6Z z49;Nq2I-Z~a3?gxk4}d}P3r5XF1;z+Kxl9hi$NsFx1o@ys5C!2rO1Dh7yjQf@$Zch@(sE+brB*eH+8Y9bH)I+3!BShG9HB=TFwS3ll-`Sae+Rub_&zJX8n_CEhZ+Mc zFKmU_V1|Oz;UL%OKSDo|93@WD2xD5|#^}i86n4x;mf$R#>3HA|VS5X5^?sB;GmVW3 z4dbx>hQeaRv;m{R*onVS4!b`G5FN?C?SC%M7#@l=-BQ2`@+zfyLkE}@i( zhB-u?gJEUWPZexZXZ{3Yb>T16j$lsrnMYT;<+WXNCq8oIF7&^2c&_ttmd@;6G371e zf8NPt;J`|tb2-p?uRjquk;Dzt$&Va43v~%cnP4j8_am2-jlHLMqpzfmmhyV-MaSax zLR9hd8WyZK4BD4#j5=oB2TL7j`1POluT7@cOpY^a$n;9h8l%Rs?DhE)x4;?YMN+TZ zB#wzQM-8v(-cXiXJvgecTh1+N{Jt~`cj;zL;T-w?m{-11zoVwHJoT4+CD;8)?UKuw zHAl^31#(LDo68!}$t~&By__{Q|NVl zxUXl=uIs9FEm+L2x;$#vzD(~`lRpc`s+HeoPa$t!&Z!^XM(h{NffmIET|oS`LXK^cmh|JjU8G81h#JCqRd`4Ni}OK)f29tn}9&84MAT zj5&<;5wDRyQr83`Al!sVO*@;U+?ztdK@gFLCk9`{GB`6H4jpW1Zf;IxwX?-<%`*s^ zmew%Z*TzCqld0@>WI4r;M%cZzEU}za*0sTL5QQlt7LuOGw)2DhB-Y$EaY>h(GCnnR zb!OT>jJgK7Hh;jA%0AJ3wte78dtcW8D9BXS<-t&JcWcUad3S4Ya%hSRrn2O3E=a$5 zda+V=BId6I2l1O{G>D1S%{)Fe$YJ^5@g!v&!Foh598d3U$~?`FPKNmoTnDWDNxEeO z{hG3f`6E6b{4ymCO*2Y&FlCXdoiYYr912;Hg1V7D;*wN2FpLf3ib(KFaoIY`2NCx? z{z89;0Be#{=PH@+6-v4U`_Z|Mk6gJcuJUD9dF;l@mZs$`O^Gcn3D=Gl*S=-fzJzQ4 z+_8`BISW-U)z5XTnk>K8^YxyEy+T=2($p;fJRBchJipj2Y~7tS?RjjG{VxgYASq*8k8~aHs8dTa0^i^wrVVuCA0fFPAqb%6BAuJLfxBckKS7+J9bqckjKk zi5oAGch)Qh(Nu+h;`tNY=;_N?-rQpy42jU&GK%Ak?w3`VXeEf$oTG_g3esydoDe$-^(>4OxdTdgYFstX*QLz zfh(GvnYbL}Q`V6y;=CWCJwyJ`h|%v)-(t)4h;9}T+pLK*%$flj8KXKZ+oq@fMwTx+VmrCI*+J$D5I5y6nVUblRuBb&W1&gdTtZWiv)Pi-N zsCCS-?iPN^3s0tPKz=5dF>B)-^iN$Lzh(>RCr6{UPTeI8+N>k$$h44iF3v5dL3&TI zZq~U;%$!kWxz3oASIucQJDMHR-#UoxDZ|1abw;y?6&e!+&(kJdm{xoCiQ42gMa@?+ z#=L$KW60?v*bHY)w>}B`l(rqtF>C*-{ni=rTeCIfN8Yy6`f`-k6}Ab8lrHFD z+7$dCfUk`XvOPlrT;yFt+8|Ualn74$)UdxcgvB~M0Hmc}p_lz(5T<~ASXpNVM@A<> zt$}ovI2e$CAf#)tP=}}dJ9afooN6`+-1#s)kr7$bR|T@!&ci>8v~0`aFVNLR3ZA2Y)_Zlk;V;q8=Mki`(5T=f_Lp%WB`$uL z9*j_Mg`R@VWZQ1aL{&{$<(}bRpeSFWV35U=n#5C&^IxW5itZaHLL(uXk2G)8kGMm* zq#a65`xV5S#9!zu7`!>%W3R5dcJA1!!#UTv>h{hZe`I&9<}@xw7ROg}3S&hv$77v- zYw2p~)>vEonZ?e<-B{W^JLip`S#|FGg`tXdKf3BIyi<3(E_N<{B;l=DG%k7tZ~c6SeEZor zpYYbLcpI0!jf*$#Rwld$=Q~nv@2aQZj_bB7ZjATEA`d)uk8Q{eTe8zVfBmHcvD*8N zN))qdbuQ>{+U8A<_vjq%&)Rfm`~30m^u-EZd48cssNAvCwp4$2@Sg4NR|GqFhEuB! z?_AH{1yE7eqMv=_DSCac;NFUz5p8wm2)T#uhVKsF>v-RIZ$|K*PC9#Vm-a@RcP&JS z!VhhZ&TYCM=I+48_D+@+*Y6dXJ1Z^km0Rd~o4dLv%MMWtnxEly?GXR}6ivzBNUwudS# ztX6Dt%GQN)rBBqV(&(A^9PlDaDYv$nu*CA$qb7bPYUV>>1zLz2qo%0&`%*1tZERCI zrPDo+<$cyZ>(Ia#4mm$;Lr&DK`j@Dii7nEaez;YO8fInMYNJlMTx>@@*p3v=OT#rO zTZtTZHfvJb<7W9jwwkPvOEVTqO33moBll&=0$*A2|D%!mG(6 zq|;&Klr2$n*UC9Y^zzm&mob~IDZ?4HvaKu|q3aDz?QiWx4@k8F$Em3y$SoKC+?uCu z&XcKDnjQr5A%5gq$lvScFSQd3DdwUz6WPG!a9+7RoR8>*Sx?jxR&u|lD%4R-Z|i_NH!?TbI_~nz4zx(%#=~ zYJBPa&9pwa5DXEGoX3r)`e&pdMjjQylUNwzd*!e_y(iwLVECPE?+lVvg|k<5_EOo_hS(dZYk z1To?DD*#;;Yy&_ogcO8kpb`XyfJEaOh|lNzfD=Uub!VghD9B$(=padyfLwsJkU?qj z6M{}eIVGXCe!vl<9Lk~mWm31b5xqhJ36Rp8qO|^6l=WQYz(7wg!IpgkM|;opbPfzu zUXpR<^H+kCew7ieM=25`DoRRaW|V=%zy+?2Qgf(vvWSii5P(*RVg>C@PtTmK39W;+ zB_N!hN(8^$%n;yGQSOL`6O2EQaP9^SFT=SZ`wItofYqM^cuVk*O&ZEJf8-g3woXHw zCa1z|R76mRVO3xiNV>wxpP9TmiEdFk-G6-)FxKUuKXi2zBrw+)u}DQkEYehobobFS z8dUL4gG7z{seKp(!W$6xqkzZT|HB*Vh!V?R~cGQT+<9B*O*%JEXB~S zo203n4I>@d`_*6Y6LEJavJ863+9HN}Kg6VB$E+Cu!e#sYwQ{xE{A>C^WZOxp*F?Ba zp0fU0^<4n_!ed*9aH@eH!#9tYTowR&Y6@u({526nO=HB~85{;u#$q}k zhnHTvnn+QNpE?meq)EzT6_I0o5Ok?ynK{~i@hzl`Pe2WTO#=xD6LHJN#z^rwvH1;B zsVdIj7HN2fy{0U!Hl4_J(G05{9tC~q-_eXd==lll;E`>ttt<_TA;0R{{zJo!H4y39 zl=&4YLBrK4x-PP(#$PKnkunZ6M!MS>1}m-~SbUiHlw04;)K~k_hhp>PCP+BvWRQeV zjgbImrdUZZix;5!*BNn(za9cv;N93BKt%ZF(m z5JLxq^u;h3O#T?%>7YBNv8mBXk^9U)+0%QzX8=;}6A+Q(yX$E8vygq8L)ad|45`z*uXEW9wcRS-2qBw22M5z?a^@VnHIOW$pxoLV@jbCs*A?pXl`FHsWJ_E7tO5Yk4dL z_R?CjVr^Wuf{%P)-S^mt7#~}8R`2c6-#Y%#>yH;NUbt&bc-!YKtA$$_cY5>qe8+hs!Q6s2dh_oDZU4J7@$>QS#is>V(*tWWLAfpHH?v*L^igr?-0{_-lDT8zO()t*Sn{9j zP9AwSvHwD1$3>y#Il=yX(sYTHYccy#ZcgrMcCadc+VuA zPp>+CFZbN+iS2yg-169s!amN`S>3Exjwh|%?BaaV`YgMsOIo+D`ie0ww(|K7D)z`i zXd$>z_rO_(F|d`RO}X`p-3j0BdFzJ`ALHWN?^XS2?GJ1Je7A7+Vⅆ!t(>dr2*mO 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 kb%7 literal 0 HcmV?d00001 From e98b3980234937f0190feaa8ba9081780bc966b7 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 29 Jun 2026 13:54:00 +0000 Subject: [PATCH 13/15] Restore base branch files to narrow PR scope --- .github/workflows/add_comment_to_jira.yml | 134 ++++++ .github/workflows/add_label_to_jira_issue.yml | 223 ++++++++++ .github/workflows/apply_labels_to_pr.yml | 228 +++++++++++ .../workflows/extract_jira_issue_details.yml | 152 +++++++ .github/workflows/extract_jira_keys.yml | 153 +++++++ .../workflows/fill_jira_with_github_data.yml | 150 +++++++ .github/workflows/jira_transition.yml | 250 +++++++++++ .../main_create_jira_issue_from_gh_issue.yml | 47 +++ .../workflows/main_jira_sync_add_label.yml | 32 ++ .../workflows/main_jira_sync_in_review.yml | 32 ++ .../workflows/main_jira_sync_pr_closed.yml | 32 ++ .../main_jira_sync_pr_milestone_removed.yml | 140 +++++++ .../main_jira_sync_pr_milestone_set.yml | 159 +++++++ .../workflows/main_jira_sync_pr_opened.yml | 31 ++ .../workflows/main_jira_sync_remove_label.yml | 32 ++ .../workflows/main_pr_events_jira_sync.yml | 44 ++ .../main_sync_milestone_to_jira_release.yml | 346 ++++++++++++++++ ...main_update_jira_status_to_in_progress.yml | 63 --- .../main_update_jira_status_to_in_review.yml | 62 --- ..._update_jira_status_to_ready_for_merge.yml | 71 ---- .../remove_label_from_jira_issue.yml | 171 ++++++++ .../jira_sync_logic.cpython-312.pyc | Bin 32948 -> 0 bytes .../jira_sync_modules.cpython-312.pyc | Bin 55607 -> 0 bytes scripts/create_jira_issue_from_gh_issue.py | 387 ++++++++++++++++++ 24 files changed, 2743 insertions(+), 196 deletions(-) create mode 100644 .github/workflows/add_comment_to_jira.yml create mode 100644 .github/workflows/add_label_to_jira_issue.yml create mode 100644 .github/workflows/apply_labels_to_pr.yml create mode 100644 .github/workflows/extract_jira_issue_details.yml create mode 100644 .github/workflows/extract_jira_keys.yml create mode 100644 .github/workflows/fill_jira_with_github_data.yml create mode 100644 .github/workflows/jira_transition.yml create mode 100644 .github/workflows/main_create_jira_issue_from_gh_issue.yml create mode 100644 .github/workflows/main_jira_sync_add_label.yml create mode 100644 .github/workflows/main_jira_sync_in_review.yml create mode 100644 .github/workflows/main_jira_sync_pr_closed.yml create mode 100644 .github/workflows/main_jira_sync_pr_milestone_removed.yml create mode 100644 .github/workflows/main_jira_sync_pr_milestone_set.yml create mode 100644 .github/workflows/main_jira_sync_pr_opened.yml create mode 100644 .github/workflows/main_jira_sync_remove_label.yml create mode 100644 .github/workflows/main_pr_events_jira_sync.yml create mode 100644 .github/workflows/main_sync_milestone_to_jira_release.yml delete mode 100644 .github/workflows/main_update_jira_status_to_in_progress.yml delete mode 100644 .github/workflows/main_update_jira_status_to_in_review.yml delete mode 100644 .github/workflows/main_update_jira_status_to_ready_for_merge.yml create mode 100644 .github/workflows/remove_label_from_jira_issue.yml delete mode 100644 scripts/__pycache__/jira_sync_logic.cpython-312.pyc delete mode 100644 scripts/__pycache__/jira_sync_modules.cpython-312.pyc create mode 100644 scripts/create_jira_issue_from_gh_issue.py diff --git a/.github/workflows/add_comment_to_jira.yml b/.github/workflows/add_comment_to_jira.yml new file mode 100644 index 0000000..3cdcd4e --- /dev/null +++ b/.github/workflows/add_comment_to_jira.yml @@ -0,0 +1,134 @@ +name: Add Comment to Jira Issue + +on: + workflow_call: + inputs: + jira_key: + description: "The Jira issue key (e.g. STAG-17)" + required: true + type: string + comment: + description: "The comment text to add to the issue (prefix text before the link)" + required: true + type: string + link_text: + description: "Optional: Text to display as a clickable link" + required: false + type: string + default: "" + link_url: + description: "Optional: URL for the clickable link" + required: false + type: string + default: "" + secrets: + jira_auth: + description: 'Plain "email:api_token" for Jira Cloud Basic auth' + required: true + +jobs: + add_comment: + runs-on: ubuntu-slim + env: + JIRA_BASE_URL: https://scylladb.atlassian.net + JIRA_KEY: ${{ inputs.jira_key }} + COMMENT_TEXT: ${{ inputs.comment }} + LINK_TEXT: ${{ inputs.link_text }} + LINK_URL: ${{ inputs.link_url }} + JIRA_AUTH: ${{ secrets.jira_auth }} + + steps: + - name: Post comment to Jira issue + shell: bash + run: | + set -euo pipefail + + if [ -z "$JIRA_KEY" ]; then + echo "JIRA_KEY is empty; nothing to do." + exit 0 + fi + + if [ -z "$COMMENT_TEXT" ]; then + echo "COMMENT_TEXT is empty; nothing to do." + exit 0 + fi + + echo "Adding comment to Jira issue: $JIRA_KEY" + echo "Comment: $COMMENT_TEXT" + echo "Link text: $LINK_TEXT" + echo "Link URL: $LINK_URL" + + # Build ADF payload - with or without clickable link + if [ -n "$LINK_TEXT" ] && [ -n "$LINK_URL" ]; then + # Build ADF with clickable link + PAYLOAD=$(jq -n \ + --arg prefix "$COMMENT_TEXT" \ + --arg linkText "$LINK_TEXT" \ + --arg linkUrl "$LINK_URL" \ + ' + { + body: { + type: "doc", + version: 1, + content: [ + { + type: "paragraph", + content: [ + { "type": "text", "text": $prefix }, + { + "type": "text", + "text": $linkText, + "marks": [ + { "type": "link", "attrs": { "href": $linkUrl } } + ] + } + ] + } + ] + } + } + ') + else + # Build simple ADF with plain text + PAYLOAD=$(jq -n \ + --arg text "$COMMENT_TEXT" \ + ' + { + body: { + type: "doc", + version: 1, + content: [ + { + type: "paragraph", + content: [ + { "type": "text", "text": $text } + ] + } + ] + } + } + ') + fi + + echo "Payload to Jira:" + echo "$PAYLOAD" + + ISSUE_URL="${JIRA_BASE_URL}/rest/api/3/issue/${JIRA_KEY}/comment" + + HTTP_CODE=$(curl -sS -w "%{http_code}" -o response.json \ + --user "$JIRA_AUTH" \ + -H "Accept: application/json" \ + -H "Content-Type: application/json" \ + -X POST "$ISSUE_URL" \ + --data "$PAYLOAD" || echo "000") + + echo "Jira HTTP status: $HTTP_CODE" + echo "Jira response body:" + cat response.json || true + + if [ "$HTTP_CODE" -ge 200 ] && [ "$HTTP_CODE" -lt 300 ]; then + echo "Comment added to $JIRA_KEY" + else + echo "Failed to add comment to $JIRA_KEY (HTTP $HTTP_CODE)" + exit 1 + fi diff --git a/.github/workflows/add_label_to_jira_issue.yml b/.github/workflows/add_label_to_jira_issue.yml new file mode 100644 index 0000000..0de335e --- /dev/null +++ b/.github/workflows/add_label_to_jira_issue.yml @@ -0,0 +1,223 @@ +name: Add Label to Jira Issues (from jira_keys_json) + +on: + workflow_call: + inputs: + jira_keys_json: + description: 'JSON array of Jira keys, e.g. ["STAG-1","STAG-2"] or ["__NO_KEYS_FOUND__"]' + type: string + required: true + label: + description: "Label to add to each Jira issue, or P0..P4 to set priority, or area/* to add Scylla component" + type: string + required: true + secrets: + jira_auth: + description: "Plain 'email:api_token' for Jira Cloud Basic auth" + required: true + +jobs: + add_labels_to_jira: + runs-on: ubuntu-slim + env: + BASE_URL: https://scylladb.atlassian.net + SCYLLA_COMPONENTS_FIELD: customfield_10321 + + steps: + - name: Extract Jira keys from jira_keys_json + id: extract + shell: bash + env: + JIRA_KEYS_JSON: ${{ inputs.jira_keys_json }} + run: | + set -euo pipefail + python3 - <<'PY' + import json, sys, os + + raw = os.environ.get("JIRA_KEYS_JSON", "").strip() + print(f"Incoming jira_keys_json: {raw}") + + # Handle empty / sentinel cases + if (not raw or + raw == "[]" or + raw == '[""]' or + raw == '["__NO_KEYS_FOUND__"]'): + print("No usable Jira keys in jira_keys_json; nothing to update.") + open("keys.txt", "w", encoding="utf-8").close() + sys.exit(0) + + try: + data = json.loads(raw) + except json.JSONDecodeError as e: + print(f"ERROR: jira_keys_json is not valid JSON: {e}", file=sys.stderr) + sys.exit(1) + + if not isinstance(data, list): + print(f"ERROR: jira_keys_json must be a JSON array; got: {type(data)}", file=sys.stderr) + sys.exit(1) + + keys = [] + for item in data: + if not isinstance(item, str): + continue + k = item.strip() + if k and k != "__NO_KEYS_FOUND__": + keys.append(k) + + # Deduplicate, preserve order + seen = set() + uniq = [] + for k in keys: + if k not in seen: + seen.add(k) + uniq.append(k) + + with open("keys.txt","w",encoding="utf-8") as out: + for k in uniq: + out.write(k + "\n") + + print(f"Found {len(uniq)} issues.") + PY + + echo "First 10 keys:" + head -n 10 keys.txt || true + + - name: Prepare payload(s) and mode (priority / label / scylla component) + id: prep + shell: bash + env: + TARGET_IN: ${{ inputs.label }} + SCYLLA_FIELD: ${{ env.SCYLLA_COMPONENTS_FIELD }} + run: | + set -euo pipefail + + TARGET_UP=$(echo "${TARGET_IN}" | tr '[:lower:]' '[:upper:]') + + MODE="" + PRIORITY_NAME="" + echo "Incoming label: '${TARGET_IN}'" + + # 1) P0..P4 → priority field + case "$TARGET_UP" in + P0|P1|P2|P3|P4) + MODE="priority" + PRIORITY_NAME="$TARGET_UP" + ;; + *) + # 2) area/* → scylla_components + if [[ "$TARGET_IN" == area/* ]]; then + MODE="scylla_component" + RAW="${TARGET_IN#area/}" + # Replace underscores with spaces across the entire remainder + COMPONENT_VALUE="${RAW//_/ }" + + echo "Derived Scylla component value: '${COMPONENT_VALUE}' from label '${TARGET_IN}'" + + # JSON-escape the component value + ESCAPED=$(jq -Rn --arg v "$COMPONENT_VALUE" '$v') + # Build payload: update customfield_10321 with add { value: "" } + printf '{"update":{"%s":[{"add":{"value":%s}}]}}\n' "$SCYLLA_FIELD" "$ESCAPED" > payload_scylla.json + echo "Scylla components payload ready." + else + # 3) Fallback: normal Jira label + MODE="label" + fi + ;; + esac + + echo "mode=${MODE}" >> "$GITHUB_OUTPUT" + echo "priority_name=${PRIORITY_NAME}" >> "$GITHUB_OUTPUT" + + # Build the label payload with jq (used when MODE=label) + if [ "$MODE" = "label" ]; then + jq -n --arg label "$TARGET_IN" \ + '{update:{labels:[{add:$label}]}}' > payload_label.json + echo "Label payload ready." + fi + + # Build the priority payload with jq (used when MODE=priority) + if [ "$MODE" = "priority" ]; then + jq -n --arg prio "$PRIORITY_NAME" \ + '{fields:{priority:{name:$prio}}}' > payload_priority.json + echo "Priority payload ready." + fi + + - name: Apply to each issue (Basic auth) + id: apply + shell: bash + env: + JIRA_AUTH: ${{ secrets.jira_auth }} + BASE_URL: ${{ env.BASE_URL }} + MODE: ${{ steps.prep.outputs.mode }} + PRIORITY_NAME: ${{ steps.prep.outputs.priority_name }} + TARGET_LABEL: ${{ inputs.label }} + run: | + set -euo pipefail + + if [ ! -s keys.txt ]; then + echo "No issue keys found; nothing to apply." + exit 0 + fi + + echo "Operation mode: ${MODE}" + if [ "$MODE" = "priority" ]; then + echo "Will set priority to: ${PRIORITY_NAME}" + PAYLOAD_FILE="payload_priority.json" + ACTION_DESC="Set priority" + elif [ "$MODE" = "scylla_component" ]; then + echo "Will add Scylla component derived from label: ${TARGET_LABEL}" + PAYLOAD_FILE="payload_scylla.json" + ACTION_DESC="Add Scylla component" + else + echo "Will add label: ${TARGET_LABEL}" + PAYLOAD_FILE="payload_label.json" + ACTION_DESC="Add label" + fi + + ok=0 + skipped=0 + failed=0 + + while IFS= read -r key; do + [ -n "${key:-}" ] || continue + ISSUE_URL="${BASE_URL}/rest/api/3/issue/${key}" + + echo "${ACTION_DESC} on ${key} ..." + + code=$(curl -sS -o resp.json -w "%{http_code}" \ + -X PUT "${ISSUE_URL}" \ + --user "$JIRA_AUTH" \ + -H "Accept: application/json" \ + -H "Content-Type: application/json" \ + --data @"${PAYLOAD_FILE}") + + if [ "$code" = "204" ] || [ "$code" = "200" ]; then + echo "OK ${key} (${code})" + ok=$((ok+1)) + + elif [ "$code" = "400" ] && [ "$MODE" = "label" ]; then + # Often returned if label already present; treat as skip for labels + echo "SKIP ${key} (${code}) likely already has the label. First 200 chars:" + head -c 200 resp.json || true; echo + skipped=$((skipped+1)) + + elif [ "$code" = "400" ] && [ "$MODE" = "scylla_component" ]; then + # Option value not valid for scylla_components – log and skip + echo "SKIP ${key} (${code}) invalid Scylla component option. First 200 chars:" + head -c 200 resp.json || true; echo + skipped=$((skipped+1)) + + else + echo "FAIL ${key} (${code}) First 400 chars:" + head -c 400 resp.json || true; echo + failed=$((failed+1)) + fi + + # Gentle pacing + sleep 0.2 + done < keys.txt + + echo "Summary: ok=${ok} skipped=${skipped} failed=${failed}" + if [ "$failed" -gt 0 ]; then + exit 1 + fi diff --git a/.github/workflows/apply_labels_to_pr.yml b/.github/workflows/apply_labels_to_pr.yml new file mode 100644 index 0000000..51f8758 --- /dev/null +++ b/.github/workflows/apply_labels_to_pr.yml @@ -0,0 +1,228 @@ +name: Apply Labels to PR + +on: + workflow_call: + inputs: + pr_number: + description: "Pull Request number to label" + type: number + required: true + labels_csv: + description: "Comma-separated labels string (e.g. 'bug, needs-triage, backend')" + type: string + required: true + details_csv: + description: "Full CSV from Jira details (header + rows). Must include 'priority' and 'scylla_components' columns." + type: string + required: true + +permissions: + contents: read + pull-requests: write + issues: write + +jobs: + apply_labels_to_pr: + runs-on: ubuntu-slim + steps: + - name: Prepare labels list (trim, dedupe, ignore empties, compute P* & area/* from Jira) + id: prepare + env: + LABELS_CSV: ${{ inputs.labels_csv }} + DETAILS_CSV: ${{ inputs.details_csv }} + NEW_PRIORITY_LABEL: ${{ github.event.label.name }} + run: | + set -euo pipefail + python3 - <<'PY' + import os, io, csv, re + + pr_number = os.environ.get("PR_NUMBER", "") + labels_csv = os.environ.get("LABELS_CSV", "") + details_csv = os.environ.get("DETAILS_CSV", "") + new_p_label = (os.environ.get("NEW_PRIORITY_LABEL") or "").strip() + + print("======================================================") + print(" Apply Labels to PR — Input Parameters") + print("======================================================") + print(f"PR Number: {pr_number}") + print(f"labels_csv: {labels_csv}") + print(f"NEW_PRIORITY_LABEL (from event): {new_p_label or ''}") + print("details_csv (first 5 lines):") + print("------------------------------------------------------") + for i, line in enumerate(details_csv.splitlines()): + print(line) + if i >= 4: + break + print("------------------------------------------------------\n") + + # 1) Parse labels_csv into a deduped list + raw_labels = [s.strip() for s in labels_csv.split(",")] + seen = set() + labels = [] + for s in raw_labels: + if s and s not in seen: + seen.add(s) + labels.append(s) + + # 2) Remove any existing P0..P4 from this base list + priority_labels = {"P0", "P1", "P2", "P3", "P4"} + labels = [l for l in labels if l not in priority_labels] + + # 3) Prepare to compute Jira-based priority and area/* labels + priority_rank_map = { + "p0": 0, "highest": 0, "blocker": 0, + "p1": 1, "critical": 1, "high": 1, + "p2": 2, "medium": 2, "major": 2, + "p3": 3, "low": 3, "minor": 3, + "p4": 4, "lowest": 4, "trivial": 4, + } + + best_rank = None + area_labels = [] + area_seen = set() + + details_csv = details_csv.strip() + if details_csv: + reader = csv.DictReader(io.StringIO(details_csv)) + for row in reader: + # ----- priority → P* from Jira ----- + prio = (row.get("priority") or "").strip() + if prio: + key = prio.lower() + rank = priority_rank_map.get(key) + if rank is not None: + if best_rank is None or rank < best_rank: + best_rank = rank + + # ----- scylla_components → area/* labels ----- + comp_raw = (row.get("scylla_components") or "").strip() + if comp_raw: + for part in comp_raw.split(";"): + comp = part.strip() + if not comp: + continue + safe = re.sub(r"\s+", "_", comp) + label = f"area/{safe}" + if label not in area_seen: + area_seen.add(label) + area_labels.append(label) + + # 4) Decide which P* to use + priority_label = None + if best_rank is not None: + priority_label = f"P{best_rank}" + + # If the event added a P* label, override Jira priority with it + if new_p_label and re.match(r"(?i)^P[0-4]$", new_p_label): + print(f"Overriding Jira priority with PR-added label: {new_p_label}") + priority_label = new_p_label.upper() + + if priority_label: + print(f"Effective priority label: {priority_label}") + if priority_label not in labels: + labels.insert(0, priority_label) + else: + print("No effective P* priority (from Jira or event); not adding P* label.") + + # 5) Append area/* labels (dedup vs other labels) + for area in area_labels: + if area not in labels: + labels.append(area) + + print("Final labels to apply:", labels) + + with open("labels.txt", "w", encoding="utf-8") as f: + for l in labels: + f.write(l + "\n") + PY + + + - name: Skip if no labels + run: | + if [ ! -s labels.txt ]; then + echo "No labels to apply. Skipping." + exit 0 + fi + + - name: Remove existing P0–P4 labels from PR + env: + GH_TOKEN: ${{ github.token }} + OWNER_REPO: ${{ github.repository }} + PR_NUMBER: "${{ inputs.pr_number }}" + run: | + set -euo pipefail + + ISSUE_API_BASE="https://api.github.com/repos/${OWNER_REPO}/issues/${PR_NUMBER}" + + echo "Fetching existing labels for PR #${PR_NUMBER}..." + curl -sS \ + -H "Authorization: Bearer ${GH_TOKEN}" \ + -H "Accept: application/vnd.github+json" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + "${ISSUE_API_BASE}/labels" > /tmp/existing_labels.json + + jq -r '.[].name' /tmp/existing_labels.json > existing_labels.txt || true + + # Priority labels we *want* after normalization (from labels.txt) + grep -E '^P[0-4]$' labels.txt > desired_p_labels.txt || true + + echo "Desired priority labels:" + cat desired_p_labels.txt || true + echo "Existing labels on PR:" + cat existing_labels.txt || true + + # If we didn't compute any desired P* label, don't touch existing priorities + if [ ! -s desired_p_labels.txt ]; then + echo "No desired P* labels computed; keeping existing P* labels unchanged." + exit 0 + fi + + for p in P0 P1 P2 P3 P4; do + if grep -qix "$p" existing_labels.txt 2>/dev/null; then + if grep -qix "$p" desired_p_labels.txt 2>/dev/null; then + echo "Keeping existing priority label: $p (also desired)" + else + echo "Removing existing priority label not desired anymore: $p" + code=$(curl -sS -o /tmp/del_resp.json -w "%{http_code}" \ + -X DELETE "${ISSUE_API_BASE}/labels/${p}" \ + -H "Authorization: Bearer ${GH_TOKEN}" \ + -H "Accept: application/vnd.github+json" \ + -H "X-GitHub-Api-Version: 2022-11-28" || true) + echo "Delete $p → HTTP ${code}" + fi + fi + done + + + - name: Add labels (after priority & area/* normalization) + env: + GH_TOKEN: ${{ github.token }} + OWNER_REPO: ${{ github.repository }} + PR_NUMBER: "${{ inputs.pr_number }}" + run: | + set -euo pipefail + ISSUE_API="https://api.github.com/repos/${OWNER_REPO}/issues/${PR_NUMBER}/labels" + + while IFS= read -r LABEL || [ -n "$LABEL" ]; do + LBL="$(echo "$LABEL" | awk '{$1=$1};1')" + [ -z "$LBL" ] && continue + + echo "----------------------------------------" + echo "Applying label: '${LBL}'" + + code=$(curl -sS -o /tmp/add_resp.json -w "%{http_code}" \ + -X POST "${ISSUE_API}" \ + -H "Authorization: Bearer ${GH_TOKEN}" \ + -H "Accept: application/vnd.github+json" \ + -H "Content-Type: application/json; charset=utf-8" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + --data "{\"labels\": [\"${LBL}\"]}" || true) + + if [ "${code}" = "200" ] || [ "${code}" = "201" ]; then + echo "Result: success (HTTP ${code})." + else + echo "Result: failed (HTTP ${code}). Body (first 200 chars):" + head -c 200 /tmp/add_resp.json || true + echo + fi + done < labels.txt diff --git a/.github/workflows/extract_jira_issue_details.yml b/.github/workflows/extract_jira_issue_details.yml new file mode 100644 index 0000000..3de650c --- /dev/null +++ b/.github/workflows/extract_jira_issue_details.yml @@ -0,0 +1,152 @@ +name: Extract Jira Issue Details (CSV - per issue) + +on: + workflow_call: + inputs: + jira_keys_json: + description: 'JSON array of Jira keys, e.g. ["PROJ-1","PROJ-2"]' + required: true + type: string + secrets: + jira_auth: + description: 'Authorization credential: "email:api_token" for Basic, or "Bearer "' + required: true + outputs: + csv: + description: 'Full CSV content (header + rows)' + value: ${{ jobs.build_csv_with_jira_data.outputs.csv }} + csv_path: + description: 'Path to CSV artifact (downloaded filename)' + value: ${{ jobs.build_csv_with_jira_data.outputs.csv_path }} + labels_csv: + description: 'Deduped CSV of all labels across issues (no header)' + value: ${{ jobs.build_csv_with_jira_data.outputs.labels_csv }} + +jobs: + build_csv_with_jira_data: + runs-on: ubuntu-slim + outputs: + csv: ${{ steps.makecsv.outputs.csv }} + csv_path: ${{ steps.artifacts-out.outputs.csv_path }} + labels_csv: ${{ steps.fetch.outputs.labels_csv }} + + env: + JIRA_BASE_URL: https://scylladb.atlassian.net + SCYLLA_COMPONENTS_FIELD: customfield_10321 + START_DATE_FIELD: customfield_10015 + DUE_DATE_FIELD: duedate + DELIM: ";" + + steps: + - name: Validate input keys + id: validate + shell: bash + run: | + keys='${{ inputs.jira_keys_json }}' + if [ -z "$keys" ] || [ "$keys" = "[]" ] || [ "$keys" = '[""]' ] || [[ "$keys" == '["__NO_KEYS_FOUND__"]' ]]; then + echo "empty_keys=true" >> "$GITHUB_OUTPUT" + else + echo "empty_keys=false" >> "$GITHUB_OUTPUT" + fi + + - name: Short-circuit on no keys + if: ${{ steps.validate.outputs.empty_keys == 'true' }} + id: makecsv-empty + shell: bash + run: | + echo "csv=" >> "$GITHUB_OUTPUT" + echo "labels_csv=" >> "$GITHUB_OUTPUT" + printf "key,status,labels,assignee,priority,fixVersions,scylla_components,startDate,dueDate\n" > jira-details.csv + echo "csv_path=jira-details.csv" >> "$GITHUB_OUTPUT" + + echo "---------------------------------------------------" + echo "Generated CSV (empty-keys short-circuit):" + echo "---------------------------------------------------" + cat jira-details.csv + echo "---------------------------------------------------" + + - name: Fetch issues one by one + if: ${{ steps.validate.outputs.empty_keys != 'true' }} + id: fetch + shell: bash + env: + BASE: ${{ env.JIRA_BASE_URL }} + FIELD_ID: ${{ env.SCYLLA_COMPONENTS_FIELD }} + START_DATE_FIELD: ${{ env.START_DATE_FIELD }} + DUE_DATE_FIELD: ${{ env.DUE_DATE_FIELD }} + JIRA_AUTH: ${{ secrets.jira_auth }} + KEYS_JSON: ${{ inputs.jira_keys_json }} + DELIM: ${{ env.DELIM }} + run: | + set -euo pipefail + printf "key,status,labels,assignee,priority,fixVersions,scylla_components,startDate,dueDate\n" > jira-details.csv + + keys=$(echo "$KEYS_JSON" | jq -r '.[]') + all_labels=() + + for key in $keys; do + echo "Fetching Jira issue: $key" + + resp=$(curl -sS --fail \ + --user "$JIRA_AUTH" \ + -H "Accept: application/json" \ + "$BASE/rest/api/3/issue/$key?fields=status,labels,assignee,priority,fixVersions,${FIELD_ID},${START_DATE_FIELD},${DUE_DATE_FIELD}") + + status=$(echo "$resp" | jq -r '.fields.status.name // ""') + assignee=$(echo "$resp" | jq -r '.fields.assignee.displayName // ""') + priority=$(echo "$resp" | jq -r '.fields.priority.name // ""') + labels=$(echo "$resp" | jq -r --arg d "$DELIM" '(.fields.labels // []) | join($d)') + fixVersions=$(echo "$resp" | jq -r --arg d "$DELIM" '(.fields.fixVersions // []) | map(.name // "") | join($d)') + components=$(echo "$resp" | jq -r --arg d "$DELIM" --arg f "$FIELD_ID" ' + (.fields[$f] // []) + | if type=="array" then (map(.value // "") | join($d)) else (tostring) end + ') + startDate=$(echo "$resp" | jq -r --arg f "$START_DATE_FIELD" '.fields[$f] // ""') + dueDate=$(echo "$resp" | jq -r --arg f "$DUE_DATE_FIELD" '.fields[$f] // ""') + + # Append line to CSV + echo "\"$key\",\"$status\",\"$labels\",\"$assignee\",\"$priority\",\"$fixVersions\",\"$components\",\"$startDate\",\"$dueDate\"" >> jira-details.csv + + # Collect labels for aggregation + mapfile -t lbls < <(echo "$resp" | jq -r '.fields.labels[]?') + all_labels+=("${lbls[@]}") + done + + # Deduplicate and join all labels + if [ ${#all_labels[@]} -gt 0 ]; then + deduped=$(printf "%s\n" "${all_labels[@]}" | sort -u | paste -sd, -) + else + deduped="" + fi + echo "labels_csv=$deduped" >> "$GITHUB_OUTPUT" + + echo "---------------------------------------------------" + echo "Generated CSV (after fetching issues):" + echo "Showing first 20 lines:" + echo "---------------------------------------------------" + head -n 20 jira-details.csv + echo "---------------------------------------------------" + + + - name: Collect CSV content + if: ${{ steps.validate.outputs.empty_keys != 'true' }} + id: makecsv + shell: bash + run: | + csv_content=$(cat jira-details.csv) + echo "csv<> "$GITHUB_OUTPUT" + echo "$csv_content" >> "$GITHUB_OUTPUT" + echo "EOF" >> "$GITHUB_OUTPUT" + + - name: Upload CSV artifact + id: artifacts + uses: actions/upload-artifact@v4 + with: + name: jira-details-csv + path: jira-details.csv + + - name: Set csv_path output + id: artifacts-out + shell: bash + run: | + echo "csv_path=jira-details.csv" >> "$GITHUB_OUTPUT" diff --git a/.github/workflows/extract_jira_keys.yml b/.github/workflows/extract_jira_keys.yml new file mode 100644 index 0000000..661309e --- /dev/null +++ b/.github/workflows/extract_jira_keys.yml @@ -0,0 +1,153 @@ +name: Extract Jira Keys + +on: + workflow_call: + inputs: + pr_title: + required: true + type: string + pr_body: + required: true + type: string + secrets: + jira_auth: + description: 'Authorization credential: "email:api_token" for Basic, or "Bearer "' + required: true + outputs: + jira-keys-json: + description: "JSON array of Jira keys" + value: ${{ jobs.extract_jira_keys_from_pr.outputs.jira-keys-json }} + +jobs: + extract_jira_keys_from_pr: + runs-on: ubuntu-slim + outputs: + jira-keys-json: ${{ steps.process.outputs.jira-keys-json }} + + steps: + - id: save + shell: bash + run: | + # Save PR title/body into files (no env injection) + cat > pr_title.txt <<'EOF' + ${{ inputs.pr_title }} + EOF + + cat > pr_body.txt <<'EOF' + ${{ inputs.pr_body }} + EOF + + - id: process + shell: bash + env: + JIRA_AUTH: ${{ secrets.jira_auth }} + run: | + set -euo pipefail + + # Remove backticks and \r before locating jira keys + title=$(tr -d '\r' < pr_title.txt | tr '\`' ' ') + body=$(tr -d '\r' < pr_body.txt | tr '\`' ' ') + + echo "title: $title" + echo "body: $body" + + > tickets.txt + printf '%s\n' "$title" | grep -oE '[A-Z]+-[0-9]+' >> tickets.txt || true + + printf '%s\n' "$body" | grep -iE '(close|closes|closed|fix|fixes|fixed|resolve|resolves|resolved)[[:space:]]*[: ][[:space:]]*\[?[[:space:]]*((https?://[^[:space:]]*/browse/)?[A-Z]+-[0-9]+)' \ + | grep -oE '[A-Z]+-[0-9]+' >> tickets.txt || true + + sort -u tickets.txt > candidate_tickets.txt + + if [[ ! -s candidate_tickets.txt ]]; then + echo "No Jira-like keys found in PR title or body" + echo 'jira-keys-json=["__NO_KEYS_FOUND__"]' >> "$GITHUB_OUTPUT" + exit 0 + fi + + echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + echo "Candidate keys:" + cat candidate_tickets.txt || true + echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + + # ------------------------------------------------------------------ + # 1) Hard-coded list of known Jira project keys (prefixes) + # ------------------------------------------------------------------ + # Edit this list to match your common Jira projects: + # e.g. KNOWN_PROJECT_PREFIXES="SCYLLA STAG DOCS ENG" + KNOWN_PROJECT_PREFIXES="RELENG CLOUD SCYLLADB PKG PM CUSTOMER VECTOR ANSROLES CLOUDEVOPS CXTOOLS DOCTOR FIELDAUTO FIELDENG ILIAD OPERATOR PKGDASH PUB SMI WEBINSTALL STAG" + + echo "Known project prefixes (hard-coded): $KNOWN_PROJECT_PREFIXES" + + # Write known prefixes (one per line) + printf "%s\n" $KNOWN_PROJECT_PREFIXES | sort -u > hardcoded_project_keys.txt + + > unique_tickets.txt + > unknown_prefix_candidates.txt + + # First pass: use only hard-coded project prefixes + while read -r key; do + [ -z "$key" ] && continue + prefix="${key%%-*}" + + if grep -qx "$prefix" hardcoded_project_keys.txt; then + echo "Accepting $key via hard-coded prefix '$prefix'." + echo "$key" >> unique_tickets.txt + else + echo "Deferring $key — prefix '$prefix' not in hard-coded list." + echo "$key" >> unknown_prefix_candidates.txt + fi + done < candidate_tickets.txt + + # ------------------------------------------------------------------ + # 2) Only if we still have keys with unknown prefixes, query Jira + # ------------------------------------------------------------------ + if [[ -s unknown_prefix_candidates.txt ]]; then + echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + echo "Some prefixes not in hard-coded list; querying Jira for project keys..." + echo "Unknown-prefix candidates:" + cat unknown_prefix_candidates.txt || true + + project_resp=$(curl -sS --fail \ + --user "$JIRA_AUTH" \ + -H "Accept: application/json" \ + "https://scylladb.atlassian.net/rest/api/3/project/search?maxResults=1000") + + echo "$project_resp" | jq -r '.values[].key' | sort -u > jira_project_keys.txt + + echo "Valid Jira project keys from API (first 20):" + head -n 20 jira_project_keys.txt || true + + # Second pass: validate unknown prefixes against Jira project list + while read -r key; do + [ -z "$key" ] && continue + prefix="${key%%-*}" + + if grep -qx "$prefix" jira_project_keys.txt; then + echo "Accepting $key via Jira API (valid project prefix '$prefix')." + echo "$key" >> unique_tickets.txt + else + echo "Skipping $key — unknown project prefix '$prefix' (not in Jira)." + fi + done < unknown_prefix_candidates.txt + else + echo "All prefixes resolved via hard-coded list; no Jira project lookup needed." + fi + + echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + + # Final result set + if [[ ! -s unique_tickets.txt ]]; then + echo "No valid Jira keys found after validation" + echo 'jira-keys-json=["__NO_KEYS_FOUND__"]' >> "$GITHUB_OUTPUT" + else + sort -u unique_tickets.txt -o unique_tickets.txt + echo "Final Jira keys:" + cat unique_tickets.txt + + json=$(awk '{printf "\"%s\",",$1}' unique_tickets.txt | sed 's/,$//') + json="[${json}]" + + echo "jira-keys-json=$json" >> "$GITHUB_OUTPUT" + + fi diff --git a/.github/workflows/fill_jira_with_github_data.yml b/.github/workflows/fill_jira_with_github_data.yml new file mode 100644 index 0000000..00b35c9 --- /dev/null +++ b/.github/workflows/fill_jira_with_github_data.yml @@ -0,0 +1,150 @@ +name: Fill Jira Field with GitHub PR Data + +on: + workflow_call: + inputs: + details_csv: + description: "Full CSV text (header + rows). Must include a 'key' column." + required: true + type: string + secrets: + jira_auth: + description: "Plain 'email:api_token' for Jira Cloud Basic auth" + required: true + +jobs: + fill_jira_fields: + runs-on: ubuntu-latest + env: + BASE_URL: https://scylladb.atlassian.net + TARGET_FIELD: customfield_10718 + PR_URL: ${{ github.event.pull_request.html_url }} + + steps: + - name: Save CSV + id: save + shell: bash + run: | + set -euo pipefail + cat > details.csv <<'CSV_EOF' + ${{ inputs.details_csv }} + CSV_EOF + + echo "Saved details.csv" + head -n 5 details.csv || true + + - name: Extract Jira keys (case-insensitive 'key' column) + id: extract + shell: bash + run: | + set -euo pipefail + + python3 - <<'PY' + import csv, sys, os + + if not os.path.exists("details.csv") or os.path.getsize("details.csv") == 0: + print("CSV empty → no keys to process.") + open("keys.txt", "w").close() + sys.exit(0) + + with open("details.csv", newline="", encoding="utf-8") as f: + reader = csv.DictReader(f) + if not reader.fieldnames: + open("keys.txt", "w").close() + sys.exit(0) + + # Find the 'key' column + fmap = {(h or "").strip().lower(): h for h in reader.fieldnames} + hkey = fmap.get("key") + if not hkey: + print(f"ERROR: No 'key' column. Found: {reader.fieldnames}", file=sys.stderr) + sys.exit(1) + + keys = [] + for row in reader: + val = (row.get(hkey) or "").strip() + if val: + keys.append(val) + + seen = set() + uniq = [] + for k in keys: + if k not in seen: + uniq.append(k) + seen.add(k) + + with open("keys.txt", "w") as out: + for k in uniq: + out.write(k + "\n") + + print(f"Found {len(uniq)} Jira issues.") + PY + + echo "First few keys:" + head -n 10 keys.txt || true + + - name: Write PR data to Jira custom field + shell: bash + env: + JIRA_AUTH: ${{ secrets.jira_auth }} + PR_URL: ${{ env.PR_URL }} + BASE_URL: ${{ env.BASE_URL }} + FIELD_ID: ${{ env.TARGET_FIELD }} + run: | + set -euo pipefail + + if [ ! -s keys.txt ]; then + echo "No keys found. Done." + exit 0 + fi + + COMMENT_TEXT="This issue will be closed by ${PR_URL}" + + while IFS= read -r key; do + [ -n "$key" ] || continue + + echo "Updating $key - [ $COMMENT_TEXT ]" + + # Build ADF document payload for rich-text custom field + jq -n \ + --arg text "$COMMENT_TEXT" \ + --arg field "$FIELD_ID" \ + '{ + fields: { + ($field): { + "type": "doc", + "version": 1, + "content": [ + { + "type": "paragraph", + "content": [ + { + "type": "text", + "text": $text + } + ] + } + ] + } + } + }' > payload.json + + code=$(curl -sS -o resp.json -w "%{http_code}" \ + -X PUT "$BASE_URL/rest/api/3/issue/$key" \ + --user "$JIRA_AUTH" \ + -H "Content-Type: application/json" \ + --data @payload.json) + + if [[ "$code" == "204" || "$code" == "200" ]]; then + echo "OK $key (${code})" + else + echo "FAIL $key (${code})" + head -c 200 resp.json || true + echo + exit 1 + fi + + sleep 0.2 + done < keys.txt + + echo "All Jira fields updated successfully." diff --git a/.github/workflows/jira_transition.yml b/.github/workflows/jira_transition.yml new file mode 100644 index 0000000..fd9303b --- /dev/null +++ b/.github/workflows/jira_transition.yml @@ -0,0 +1,250 @@ +name: Jira Transition (from CSV) + +on: + workflow_call: + inputs: + # Full CSV text from the details job (header + rows). + # Expected columns include: key,status,labels,assignee,priority,fixVersions,scylla_components + details_csv: + required: true + type: string + transition_name: + required: true + type: string + transition_id: + required: true + type: string + secrets: + jira_auth: + required: true + +jobs: + transition_jira_status: + runs-on: ubuntu-slim + env: + JIRA_BASE_URL: https://scylladb.atlassian.net + START_DATE_FIELD: customfield_10015 + DUE_DATE_FIELD: duedate + + steps: + - name: Write CSV to file + shell: bash + run: | + cat > details.csv <<'CSV_EOF' + ${{ inputs.details_csv }} + CSV_EOF + echo "Wrote details.csv" + head -n 5 details.csv || true + + - name: Plan transitions (parse CSV) + id: plan + shell: bash + env: + TARGET: ${{ inputs.transition_name }} + run: | + set -euo pipefail + python3 - <<'PY' + import csv, sys, io, os + + target = os.environ['TARGET'] + to_transition = [] # list of (key, current_status) + already_ok = [] # list of (key, current_status) + done_issues = [] # list of (key, current_status == Done) + + with open('details.csv', newline='', encoding='utf-8') as f: + reader = csv.DictReader(f) + # Normalize headers + fieldmap = { (h or '').strip().lower(): h for h in reader.fieldnames or [] } + def get(row, name): + h = fieldmap.get(name.lower()) + return (row.get(h) or "").strip() if h else "" + + for row in reader: + key = get(row, 'key') + status = get(row, 'status') + start_date = get(row, 'startdate') + due_date = get(row, 'duedate') + if not key: + continue + + # Skip already correct or Done issues + if status.lower() == target.lower(): + already_ok.append((key, status)) + elif status.lower() in {"done", "duplicate", "won't fix"}: + done_issues.append((key, status)) + else: + to_transition.append((key, status, start_date, due_date)) + + # Write plan files + def write_list(fname, items): + with open(fname, 'w', encoding='utf-8') as out: + for item in items: + if len(item) == 4: + k, s, sd, dd = item + out.write(f"{k}|{s}|{sd}|{dd}\n") + else: + k, s = item + out.write(f"{k}|{s}\n") + + write_list('to_transition.txt', to_transition) + write_list('already_ok.txt', already_ok) + write_list('done_issues.txt', done_issues) + + print(f"{len(to_transition)} need transition, {len(already_ok)} already OK, {len(done_issues)} are Done.", file=sys.stderr) + PY + + echo "----- Already OK (up to 10) -----" + head -n 10 already_ok.txt || true + echo "----- Done issues (up to 10) -----" + head -n 10 done_issues.txt || true + echo "----- Need Transition (up to 10) -----" + head -n 10 to_transition.txt || true + + - name: Show intent summary + shell: bash + env: + TARGET: ${{ inputs.transition_name }} + run: | + need=$(wc -l < to_transition.txt 2>/dev/null || echo 0) + ok=$(wc -l < already_ok.txt 2>/dev/null || echo 0) + done=$(wc -l < done_issues.txt 2>/dev/null || echo 0) + echo "Target status: ${TARGET}" + echo "Issues already at target: ${ok}" + echo "Issues in 'Done' state: ${done}" + echo "Issues to transition: ${need}" + + - name: Transition issues + if: ${{ always() }} + shell: bash + env: + JIRA_AUTH: ${{ secrets.jira_auth }} + TARGET: ${{ inputs.transition_name }} + TRANSITION_ID: ${{ inputs.transition_id }} + BASE: ${{ env.JIRA_BASE_URL }} + START_DATE_FIELD: ${{ env.START_DATE_FIELD }} + DUE_DATE_FIELD: ${{ env.DUE_DATE_FIELD }} + run: | + set -euo pipefail + + if [ ! -s to_transition.txt ]; then + echo "No issues require transition. Done." + exit 0 + fi + + if [ -z "${JIRA_AUTH:-}" ]; then + echo "ERROR: jira_auth secret not set." >&2 + exit 1 + fi + + while IFS='|' read -r key current start_date due_date; do + [ -n "${key:-}" ] || continue + echo "Transitioning ${key} from '${current}' -> '${TARGET}' (id=${TRANSITION_ID})" + + # Check if transitioning to a working state and if start date needs to be set + WORKING_STATES=("in progress" "in review" "ready for merge") + SET_START_DATE=false + for state in "${WORKING_STATES[@]}"; do + if [[ "${TARGET,,}" == "$state" ]]; then + SET_START_DATE=true + break + fi + done + + # If transitioning to working state and start date is empty, set it + if [ "$SET_START_DATE" = true ]; then + if [ -z "$start_date" ] || [ "$start_date" = "null" ]; then + TODAY=$(date -u +%Y-%m-%d) + echo "Setting start date to ${TODAY} for ${key} (field: ${START_DATE_FIELD})" + + # Use custom field ID for start date + if [[ "$JIRA_AUTH" == Bearer\ * ]]; then + RESPONSE=$(curl -sS -w "\n%{http_code}" -X PUT \ + -H "Authorization: $JIRA_AUTH" \ + -H "Accept: application/json" \ + -H "Content-Type: application/json" \ + --data "{\"fields\": {\"${START_DATE_FIELD}\": \"${TODAY}\"}}" \ + "${BASE}/rest/api/3/issue/${key}" 2>&1) + else + RESPONSE=$(curl -sS -w "\n%{http_code}" -X PUT \ + --user "$JIRA_AUTH" \ + -H "Accept: application/json" \ + -H "Content-Type: application/json" \ + --data "{\"fields\": {\"${START_DATE_FIELD}\": \"${TODAY}\"}}" \ + "${BASE}/rest/api/3/issue/${key}" 2>&1) + fi + + HTTP_CODE=$(echo "$RESPONSE" | tail -n1) + if [ "$HTTP_CODE" != "204" ]; then + echo "Warning: Failed to set start date for ${key} (HTTP ${HTTP_CODE})" >&2 + echo "$RESPONSE" | head -n-1 >&2 + fi + sleep 0.2 + else + echo "Start date already set for ${key}: ${start_date}" + fi + fi + + # Check if transitioning to a closed state and if due date needs to be set + CLOSED_STATES=("done" "won't fix") + SET_DUE_DATE=false + for state in "${CLOSED_STATES[@]}"; do + if [[ "${TARGET,,}" == "$state" ]]; then + SET_DUE_DATE=true + break + fi + done + + # If transitioning to closed state and due date is empty, set it + if [ "$SET_DUE_DATE" = true ]; then + if [ -z "$due_date" ] || [ "$due_date" = "null" ]; then + TODAY=$(date -u +%Y-%m-%d) + echo "Setting due date to ${TODAY} for ${key} (field: ${DUE_DATE_FIELD})" + + if [[ "$JIRA_AUTH" == Bearer\ * ]]; then + RESPONSE=$(curl -sS -w "\n%{http_code}" -X PUT \ + -H "Authorization: $JIRA_AUTH" \ + -H "Accept: application/json" \ + -H "Content-Type: application/json" \ + --data "{\"fields\": {\"${DUE_DATE_FIELD}\": \"${TODAY}\"}}" \ + "${BASE}/rest/api/3/issue/${key}" 2>&1) + else + RESPONSE=$(curl -sS -w "\n%{http_code}" -X PUT \ + --user "$JIRA_AUTH" \ + -H "Accept: application/json" \ + -H "Content-Type: application/json" \ + --data "{\"fields\": {\"${DUE_DATE_FIELD}\": \"${TODAY}\"}}" \ + "${BASE}/rest/api/3/issue/${key}" 2>&1) + fi + + HTTP_CODE=$(echo "$RESPONSE" | tail -n1) + if [ "$HTTP_CODE" != "204" ]; then + echo "Warning: Failed to set due date for ${key} (HTTP ${HTTP_CODE})" >&2 + echo "$RESPONSE" | head -n-1 >&2 + fi + sleep 0.2 + else + echo "Due date already set for ${key}: ${due_date}" + fi + fi + + if [[ "$JIRA_AUTH" == Bearer\ * ]]; then + curl -sS --fail -X POST \ + -H "Authorization: $JIRA_AUTH" \ + -H "Accept: application/json" \ + -H "Content-Type: application/json" \ + --data "{\"transition\": {\"id\": \"${TRANSITION_ID}\"}}" \ + "${BASE}/rest/api/3/issue/${key}/transitions" \ + || { echo "Failed to transition ${key}" >&2; exit 1; } + else + curl -sS --fail -X POST \ + --user "$JIRA_AUTH" \ + -H "Accept: application/json" \ + -H "Content-Type: application/json" \ + --data "{\"transition\": {\"id\": \"${TRANSITION_ID}\"}}" \ + "${BASE}/rest/api/3/issue/${key}/transitions" \ + || { echo "Failed to transition ${key}" >&2; exit 1; } + fi + + # Gentle rate limit + sleep 0.2 + done < to_transition.txt diff --git a/.github/workflows/main_create_jira_issue_from_gh_issue.yml b/.github/workflows/main_create_jira_issue_from_gh_issue.yml new file mode 100644 index 0000000..103727e --- /dev/null +++ b/.github/workflows/main_create_jira_issue_from_gh_issue.yml @@ -0,0 +1,47 @@ +name: Sync GitHub Issue to Jira + +on: + workflow_call: + inputs: + jira_project_key: + description: "Jira project key (e.g. MONITOR)" + required: true + type: string + secrets: + caller_jira_auth: + description: "Plain 'email:api_token' for Jira Cloud Basic auth" + required: true + +jobs: + sync-issue-to-jira: + if: github.event.action == 'opened' + name: "Create Jira issue from GH #${{ github.event.issue.number }}" + runs-on: ubuntu-slim + permissions: + contents: read + issues: write + steps: + - name: Checkout automation repo + uses: actions/checkout@v4 + with: + repository: scylladb/github-automation + ref: automation-staging-branch + + - name: Create Jira issue and cross-link + env: + JIRA_AUTH: ${{ secrets.caller_jira_auth }} + JIRA_PROJECT_KEY: ${{ inputs.jira_project_key }} + GITHUB_TOKEN: ${{ github.token }} + OWNER_REPO: ${{ github.repository }} + ISSUE_TITLE: ${{ github.event.issue.title }} + ISSUE_BODY: ${{ github.event.issue.body }} + ISSUE_NUMBER: ${{ github.event.issue.number }} + ISSUE_HTML_URL: ${{ github.event.issue.html_url }} + ISSUE_LABELS: ${{ join(github.event.issue.labels.*.name, ',') }} + ISSUE_TYPE: ${{ github.event.issue.type.name || '' }} + ISSUE_MILESTONE: ${{ github.event.issue.milestone.title || '' }} + GH_ASSIGNEE_LOGIN: ${{ github.event.issue.assignee.login || '' }} + GH_ASSIGNEE_NAME: ${{ github.event.issue.assignee.name || github.event.issue.assignee.login || '' }} + GH_REPORTER_LOGIN: ${{ github.event.issue.user.login || '' }} + GH_REPORTER_NAME: ${{ github.event.issue.user.name || github.event.issue.user.login || '' }} + run: python3 scripts/create_jira_issue_from_gh_issue.py \ No newline at end of file diff --git a/.github/workflows/main_jira_sync_add_label.yml b/.github/workflows/main_jira_sync_add_label.yml new file mode 100644 index 0000000..1d44bae --- /dev/null +++ b/.github/workflows/main_jira_sync_add_label.yml @@ -0,0 +1,32 @@ +name: Sync With Jira - Add Label + +on: + workflow_call: + secrets: + caller_jira_auth: + required: true + +jobs: + manage_labeled_gh_event: + runs-on: ubuntu-slim + permissions: + contents: read + pull-requests: write + issues: write + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + repository: scylladb/github-automation + ref: automation-staging-branch + + - name: Run label-sync orchestrator + env: + PR_TITLE: ${{ github.event.pull_request.title }} + PR_BODY: ${{ github.event.pull_request.body }} + PR_NUMBER: ${{ github.event.pull_request.number }} + TRIGGERING_LABEL: ${{ github.event.label.name }} + OWNER_REPO: ${{ github.repository }} + GITHUB_TOKEN: ${{ github.token }} + JIRA_AUTH: ${{ secrets.caller_jira_auth }} + run: python3 scripts/jira_sync_logic.py --action manage_labeled_gh_event diff --git a/.github/workflows/main_jira_sync_in_review.yml b/.github/workflows/main_jira_sync_in_review.yml new file mode 100644 index 0000000..bf6361a --- /dev/null +++ b/.github/workflows/main_jira_sync_in_review.yml @@ -0,0 +1,32 @@ +name: Sync with Jira - In Review + +on: + workflow_call: + secrets: + caller_jira_auth: + required: true + +jobs: + manage_review_gh_event: + runs-on: ubuntu-slim + permissions: + contents: read + pull-requests: write + issues: write + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + repository: scylladb/github-automation + ref: automation-staging-branch + + - name: Run in-review orchestrator + env: + PR_TITLE: ${{ github.event.pull_request.title }} + PR_BODY: ${{ github.event.pull_request.body }} + PR_NUMBER: ${{ github.event.pull_request.number }} + OWNER_REPO: ${{ github.repository }} + REQUESTED_REVIEWER: ${{ github.event.requested_reviewer.login }} + GITHUB_TOKEN: ${{ github.token }} + JIRA_AUTH: ${{ secrets.caller_jira_auth }} + run: python3 scripts/jira_sync_logic.py --action manage_review_gh_event diff --git a/.github/workflows/main_jira_sync_pr_closed.yml b/.github/workflows/main_jira_sync_pr_closed.yml new file mode 100644 index 0000000..cca2c5c --- /dev/null +++ b/.github/workflows/main_jira_sync_pr_closed.yml @@ -0,0 +1,32 @@ +name: Sync with Jira - PR Closed + +on: + workflow_call: + secrets: + caller_jira_auth: + required: true + +jobs: + manage_closed_gh_event: + runs-on: ubuntu-slim + permissions: + contents: read + pull-requests: write + issues: write + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + repository: scylladb/github-automation + ref: automation-staging-branch + + - name: Run pr-closed orchestrator + env: + PR_TITLE: ${{ github.event.pull_request.title }} + PR_BODY: ${{ github.event.pull_request.body }} + PR_NUMBER: ${{ github.event.pull_request.number }} + PR_MERGED: ${{ github.event.pull_request.merged }} + OWNER_REPO: ${{ github.repository }} + GITHUB_TOKEN: ${{ github.token }} + JIRA_AUTH: ${{ secrets.caller_jira_auth }} + run: python3 scripts/jira_sync_logic.py --action manage_closed_gh_event diff --git a/.github/workflows/main_jira_sync_pr_milestone_removed.yml b/.github/workflows/main_jira_sync_pr_milestone_removed.yml new file mode 100644 index 0000000..d51d25d --- /dev/null +++ b/.github/workflows/main_jira_sync_pr_milestone_removed.yml @@ -0,0 +1,140 @@ +name: Sync With Jira - PR Milestone Removed + +on: + workflow_call: + secrets: + caller_jira_auth: + required: true + +jobs: + extract: + uses: scylladb/github-automation/.github/workflows/extract_jira_keys.yml@automation-staging-branch + with: + pr_title: ${{ github.event.pull_request.title }} + pr_body: ${{ github.event.pull_request.body }} + secrets: + jira_auth: ${{ secrets.caller_jira_auth }} + + debug: + needs: extract + runs-on: ubuntu-slim + steps: + - name: Debug data + env: + GITHUB_CONTEXT: ${{ toJson(github) }} + run: | + echo "event_name='${{ github.event_name }}'" + echo "action='${{ github.event.action }}'" + echo "removed_milestone_title='${{ github.event.milestone.title }}'" + echo "jira-keys-json='${{ needs.extract.outputs['jira-keys-json'] }}'" + echo "~~~~~~~~~~~ GitHub Context ~~~~~~~~~~~" + echo "$GITHUB_CONTEXT" + + remove_fix_versions: + needs: extract + runs-on: ubuntu-slim + env: + JIRA_BASE_URL: https://scylladb.atlassian.net + JIRA_AUTH: ${{ secrets.caller_jira_auth }} + MILESTONE_TITLE: ${{ github.event.milestone.title }} + JIRA_KEYS_JSON: ${{ needs.extract.outputs['jira-keys-json'] }} + + steps: + - name: Remove Fix Versions from Jira issues + shell: bash + run: | + set -euo pipefail + + if [ -z "${JIRA_AUTH:-}" ]; then + echo "ERROR: jira_auth secret is not set." + exit 1 + fi + + if [ -z "${MILESTONE_TITLE:-}" ]; then + echo "ERROR: No milestone title found." + exit 1 + fi + + echo "Milestone to remove: ${MILESTONE_TITLE}" + echo "Jira keys JSON: ${JIRA_KEYS_JSON}" + + # Parse the JSON array of Jira keys + KEYS=$(echo "$JIRA_KEYS_JSON" | jq -r '.[]') + + if [ "$KEYS" = "__NO_KEYS_FOUND__" ] || [ -z "$KEYS" ]; then + echo "No valid Jira keys found in PR. Skipping." + exit 0 + fi + + ok=0 + skipped=0 + failed=0 + + for KEY in $KEYS; do + echo "======================================================" + echo "Processing Jira issue: ${KEY}" + echo "======================================================" + + # Get current issue to check existing Fix Versions + ISSUE_RESP=$(curl -sS -w "\n%{http_code}" \ + --user "${JIRA_AUTH}" \ + -H "Accept: application/json" \ + "${JIRA_BASE_URL}/rest/api/3/issue/${KEY}?fields=fixVersions") + + HTTP_CODE=$(echo "$ISSUE_RESP" | tail -1) + BODY=$(echo "$ISSUE_RESP" | sed '$d') + + if [ "$HTTP_CODE" != "200" ]; then + echo "FAIL: Could not fetch issue ${KEY} (HTTP ${HTTP_CODE})" + echo "$BODY" + failed=$((failed+1)) + continue + fi + + # Check if the milestone version exists in Fix Versions + EXISTING_VERSIONS=$(echo "$BODY" | jq -r '.fields.fixVersions[]?.name // empty') + + if ! echo "$EXISTING_VERSIONS" | grep -qx "$MILESTONE_TITLE"; then + echo "SKIP: Version '${MILESTONE_TITLE}' not found in Fix Versions for ${KEY}" + skipped=$((skipped+1)) + continue + fi + + # Remove the milestone from Fix Versions + UPDATE_PAYLOAD=$(jq -n --arg name "$MILESTONE_TITLE" ' + { + "update": { + "fixVersions": [ + { "remove": { "name": $name } } + ] + } + } + ') + + UPDATE_RESP=$(curl -sS -w "\n%{http_code}" \ + -X PUT "${JIRA_BASE_URL}/rest/api/3/issue/${KEY}" \ + --user "${JIRA_AUTH}" \ + -H "Accept: application/json" \ + -H "Content-Type: application/json" \ + --data "$UPDATE_PAYLOAD") + + UPDATE_HTTP=$(echo "$UPDATE_RESP" | tail -1) + UPDATE_BODY=$(echo "$UPDATE_RESP" | sed '$d') + + if [ "$UPDATE_HTTP" = "204" ] || [ "$UPDATE_HTTP" = "200" ]; then + echo "OK: Removed '${MILESTONE_TITLE}' from Fix Versions for ${KEY}" + ok=$((ok+1)) + else + echo "FAIL: Could not remove Fix Version for ${KEY} (HTTP ${UPDATE_HTTP})" + echo "$UPDATE_BODY" + failed=$((failed+1)) + fi + done + + echo "======================================================" + echo "Summary: ok=${ok} skipped=${skipped} failed=${failed}" + echo "======================================================" + + if [ "$failed" -gt 0 ]; then + exit 1 + fi diff --git a/.github/workflows/main_jira_sync_pr_milestone_set.yml b/.github/workflows/main_jira_sync_pr_milestone_set.yml new file mode 100644 index 0000000..4a4708e --- /dev/null +++ b/.github/workflows/main_jira_sync_pr_milestone_set.yml @@ -0,0 +1,159 @@ +name: Sync With Jira - PR Milestone Set + +on: + workflow_call: + secrets: + caller_jira_auth: + required: true + +jobs: + extract: + uses: scylladb/github-automation/.github/workflows/extract_jira_keys.yml@automation-staging-branch + with: + pr_title: ${{ github.event.pull_request.title }} + pr_body: ${{ github.event.pull_request.body }} + secrets: + jira_auth: ${{ secrets.caller_jira_auth }} + + debug: + needs: extract + runs-on: ubuntu-slim + steps: + - name: Debug data + env: + GITHUB_CONTEXT: ${{ toJson(github) }} + run: | + echo "event_name='${{ github.event_name }}'" + echo "action='${{ github.event.action }}'" + echo "milestone_title='${{ github.event.pull_request.milestone.title }}'" + echo "jira-keys-json='${{ needs.extract.outputs['jira-keys-json'] }}'" + echo "~~~~~~~~~~~ GitHub Context ~~~~~~~~~~~" + echo "$GITHUB_CONTEXT" + + update_fix_versions: + needs: extract + runs-on: ubuntu-slim + env: + JIRA_BASE_URL: https://scylladb.atlassian.net + JIRA_AUTH: ${{ secrets.caller_jira_auth }} + MILESTONE_TITLE: ${{ github.event.pull_request.milestone.title }} + JIRA_KEYS_JSON: ${{ needs.extract.outputs['jira-keys-json'] }} + + steps: + - name: Replace Fix Versions in Jira issues + shell: bash + run: | + set -euo pipefail + + if [ -z "${JIRA_AUTH:-}" ]; then + echo "ERROR: jira_auth secret is not set." + exit 1 + fi + + if [ -z "${MILESTONE_TITLE:-}" ]; then + echo "ERROR: No milestone title found." + exit 1 + fi + + echo "Milestone title: ${MILESTONE_TITLE}" + echo "Jira keys JSON: ${JIRA_KEYS_JSON}" + + # Parse the JSON array of Jira keys + KEYS=$(echo "$JIRA_KEYS_JSON" | jq -r '.[]') + + if [ "$KEYS" = "__NO_KEYS_FOUND__" ] || [ -z "$KEYS" ]; then + echo "No valid Jira keys found in PR. Skipping." + exit 0 + fi + + ok=0 + skipped=0 + failed=0 + + for KEY in $KEYS; do + echo "======================================================" + echo "Processing Jira issue: ${KEY}" + echo "======================================================" + + # Get the project key from the issue key + PROJECT_KEY="${KEY%%-*}" + + # First, ensure the version exists in the project + VERSION_CHECK=$(curl -sS -w "\n%{http_code}" \ + --user "${JIRA_AUTH}" \ + -H "Accept: application/json" \ + "${JIRA_BASE_URL}/rest/api/3/project/${PROJECT_KEY}/versions") + + VC_HTTP=$(echo "$VERSION_CHECK" | tail -1) + VC_BODY=$(echo "$VERSION_CHECK" | sed '$d') + + VERSION_EXISTS=false + if [ "$VC_HTTP" = "200" ]; then + if echo "$VC_BODY" | jq -e ".[] | select(.name == \"$MILESTONE_TITLE\")" > /dev/null 2>&1; then + VERSION_EXISTS=true + fi + fi + + if [ "$VERSION_EXISTS" = "false" ]; then + echo "Version '${MILESTONE_TITLE}' does not exist in project ${PROJECT_KEY}. Creating it..." + + CREATE_RESP=$(curl -sS -w "\n%{http_code}" \ + -X POST "${JIRA_BASE_URL}/rest/api/3/version" \ + --user "${JIRA_AUTH}" \ + -H "Accept: application/json" \ + -H "Content-Type: application/json" \ + --data "{\"name\": \"${MILESTONE_TITLE}\", \"project\": \"${PROJECT_KEY}\"}") + + CREATE_HTTP=$(echo "$CREATE_RESP" | tail -1) + CREATE_BODY=$(echo "$CREATE_RESP" | sed '$d') + + if [ "$CREATE_HTTP" = "201" ] || [ "$CREATE_HTTP" = "200" ]; then + echo "Created version '${MILESTONE_TITLE}' in project ${PROJECT_KEY}" + elif [ "$CREATE_HTTP" = "400" ]; then + # Might already exist (race condition or case sensitivity) + echo "Version might already exist (HTTP 400). Proceeding with update..." + else + echo "WARNING: Could not create version (HTTP ${CREATE_HTTP}): $CREATE_BODY" + fi + fi + + # Replace Fix Versions - SET to only the new milestone (removes all existing) + UPDATE_PAYLOAD=$(jq -n --arg name "$MILESTONE_TITLE" ' + { + "fields": { + "fixVersions": [ + { "name": $name } + ] + } + } + ') + + echo "Replacing Fix Versions with: ${MILESTONE_TITLE}" + + UPDATE_RESP=$(curl -sS -w "\n%{http_code}" \ + -X PUT "${JIRA_BASE_URL}/rest/api/3/issue/${KEY}" \ + --user "${JIRA_AUTH}" \ + -H "Accept: application/json" \ + -H "Content-Type: application/json" \ + --data "$UPDATE_PAYLOAD") + + UPDATE_HTTP=$(echo "$UPDATE_RESP" | tail -1) + UPDATE_BODY=$(echo "$UPDATE_RESP" | sed '$d') + + if [ "$UPDATE_HTTP" = "204" ] || [ "$UPDATE_HTTP" = "200" ]; then + echo "OK: Set Fix Versions for ${KEY} to '${MILESTONE_TITLE}'" + ok=$((ok+1)) + else + echo "FAIL: Could not update Fix Versions for ${KEY} (HTTP ${UPDATE_HTTP})" + echo "$UPDATE_BODY" + failed=$((failed+1)) + fi + done + + echo "======================================================" + echo "Summary: ok=${ok} skipped=${skipped} failed=${failed}" + echo "======================================================" + + if [ "$failed" -gt 0 ]; then + exit 1 + fi diff --git a/.github/workflows/main_jira_sync_pr_opened.yml b/.github/workflows/main_jira_sync_pr_opened.yml new file mode 100644 index 0000000..8498175 --- /dev/null +++ b/.github/workflows/main_jira_sync_pr_opened.yml @@ -0,0 +1,31 @@ +name: Sync With Jira - PR Opened + +on: + workflow_call: + secrets: + caller_jira_auth: + required: true + +jobs: + manage_opened_gh_event: + runs-on: ubuntu-slim + permissions: + contents: read + pull-requests: write + issues: write + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + repository: scylladb/github-automation + ref: automation-staging-branch + + - name: Run pr-opened orchestrator + env: + PR_TITLE: ${{ github.event.pull_request.title }} + PR_BODY: ${{ github.event.pull_request.body }} + PR_NUMBER: ${{ github.event.pull_request.number }} + OWNER_REPO: ${{ github.repository }} + GITHUB_TOKEN: ${{ github.token }} + JIRA_AUTH: ${{ secrets.caller_jira_auth }} + run: python3 scripts/jira_sync_logic.py --action manage_opened_gh_event diff --git a/.github/workflows/main_jira_sync_remove_label.yml b/.github/workflows/main_jira_sync_remove_label.yml new file mode 100644 index 0000000..2f79ac5 --- /dev/null +++ b/.github/workflows/main_jira_sync_remove_label.yml @@ -0,0 +1,32 @@ +name: Sync With Jira - Remove Label + +on: + workflow_call: + secrets: + caller_jira_auth: + required: true + +jobs: + sync: + name: Remove-label orchestration + runs-on: ubuntu-slim + steps: + - name: Checkout scripts + uses: actions/checkout@v4 + with: + repository: scylladb/github-automation + ref: automation-staging-branch + path: _automation + + - name: Run manage_unlabeled_gh_event + env: + PR_TITLE: ${{ github.event.pull_request.title }} + PR_BODY: ${{ github.event.pull_request.body }} + PR_NUMBER: ${{ github.event.pull_request.number }} + REMOVED_LABEL: ${{ github.event.label.name }} + OWNER_REPO: ${{ github.repository }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + JIRA_AUTH: ${{ secrets.caller_jira_auth }} + run: | + cd _automation/scripts + python jira_sync_logic.py --action manage_unlabeled_gh_event diff --git a/.github/workflows/main_pr_events_jira_sync.yml b/.github/workflows/main_pr_events_jira_sync.yml new file mode 100644 index 0000000..9cd9031 --- /dev/null +++ b/.github/workflows/main_pr_events_jira_sync.yml @@ -0,0 +1,44 @@ +name: Sync Jira from PR Events + +on: + workflow_call: + inputs: + caller_action: + description: > + The GitHub event action that triggered this workflow (e.g. opened, + labeled, unlabeled, closed, ready_for_review, review_requested). + The Python script maps this to the correct orchestrator function. + required: true + type: string + secrets: + caller_jira_auth: + required: true + +jobs: + jira-sync: + name: "Jira Sync - ${{ inputs.caller_action }}" + runs-on: ubuntu-slim + permissions: + contents: read + pull-requests: write + issues: write + steps: + - name: Checkout repository + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + repository: scylladb/github-automation + ref: automation-staging-branch + + - name: Run Jira sync orchestrator + env: + PR_TITLE: ${{ github.event.pull_request.title }} + PR_BODY: ${{ github.event.pull_request.body }} + PR_NUMBER: ${{ github.event.pull_request.number }} + OWNER_REPO: ${{ github.repository }} + TRIGGERING_LABEL: ${{ github.event.label.name }} + REMOVED_LABEL: ${{ github.event.label.name }} + REQUESTED_REVIEWER: ${{ github.event.requested_reviewer.login }} + PR_MERGED: ${{ github.event.pull_request.merged }} + GITHUB_TOKEN: ${{ github.token }} + JIRA_AUTH: ${{ secrets.caller_jira_auth }} + run: python3 scripts/jira_sync_logic.py --action ${{ inputs.caller_action }} \ No newline at end of file diff --git a/.github/workflows/main_sync_milestone_to_jira_release.yml b/.github/workflows/main_sync_milestone_to_jira_release.yml new file mode 100644 index 0000000..c4a4fa4 --- /dev/null +++ b/.github/workflows/main_sync_milestone_to_jira_release.yml @@ -0,0 +1,346 @@ +name: Sync Jira releases (versions) from GitHub milestone + +on: + workflow_call: + inputs: + jira_project_keys: + description: "Comma-separated Jira project keys (e.g. STAG,VECTOR,PROJ)" + required: true + type: string + secrets: + caller_jira_auth: + description: "Plain 'email:api_token' for Jira Cloud Basic auth" + required: true + +jobs: + create_jira_releases: + if: github.event.action == 'created' + runs-on: ubuntu-slim + env: + JIRA_BASE_URL: https://scylladb.atlassian.net + JIRA_AUTH: ${{ secrets.caller_jira_auth }} + PROJECT_KEYS: ${{ inputs.jira_project_keys }} + + steps: + - name: Debug milestone input + run: | + echo "Projects: '${{ inputs.jira_project_keys }}'" + echo "Title: '${{ github.event.milestone.title }}'" + echo "Description: '${{ github.event.milestone.description }}'" + echo "Due on: '${{ github.event.milestone.due_on }}'" + + - name: Create Jira version in each project (skip if already exists) + shell: bash + run: | + set -euo pipefail + + if [ -z "${JIRA_AUTH:-}" ]; then + echo "ERROR: jira_auth secret is not set." + exit 1 + fi + + NAME="${{ github.event.milestone.title }}" + DESC="${{ github.event.milestone.description }}" + DUE_ON="${{ github.event.milestone.due_on }}" + + # GitHub due_on is ISO 8601; Jira expects YYYY-MM-DD + RELEASE_DATE="" + if [ -n "${DUE_ON:-}" ]; then + RELEASE_DATE="${DUE_ON%%T*}" + fi + + echo "Version name: ${NAME}" + echo "Release date: ${RELEASE_DATE:-}" + echo "Projects: ${PROJECT_KEYS}" + echo + + # Split comma-separated keys safely (trim whitespace) + IFS=',' read -r -a KEYS <<< "${PROJECT_KEYS}" + + ok=0 + skipped=0 + failed=0 + + for raw in "${KEYS[@]}"; do + PROJECT_KEY="$(echo "$raw" | awk '{$1=$1};1')" # trim + [ -n "$PROJECT_KEY" ] || continue + + echo "======================================================" + echo "Creating Jira version in project: ${PROJECT_KEY}" + echo "======================================================" + + # Build payload + jq -n \ + --arg name "$NAME" \ + --arg proj "$PROJECT_KEY" \ + --arg desc "${DESC:-}" \ + --arg rdate "${RELEASE_DATE:-}" \ + ' + { + name: $name, + project: $proj + } + + (if $desc != "" then {description: $desc} else {} end) + + (if $rdate != "" then {releaseDate: $rdate} else {} end) + ' > payload.json + + # Attempt create + HTTP_CODE=$(curl -sS -o resp.json -w "%{http_code}" \ + -X POST "${JIRA_BASE_URL}/rest/api/3/version" \ + --user "${JIRA_AUTH}" \ + -H "Accept: application/json" \ + -H "Content-Type: application/json" \ + --data @payload.json || true) + + if [ "$HTTP_CODE" = "201" ] || [ "$HTTP_CODE" = "200" ]; then + ID=$(jq -r '.id // empty' resp.json) + echo "OK: created version in ${PROJECT_KEY} (id=${ID})." + ok=$((ok+1)) + continue + fi + + # If already exists: treat as SKIP and move on + if [ "$HTTP_CODE" = "400" ] && jq -e ' + (.errorMessages // []) + ((.errors // {}) | to_entries | map(.value)) + | map(tostring) + | any(test("already exists|exists already|A version with this name already exists"; "i")) + ' resp.json > /dev/null 2>&1; then + echo "SKIP: version '${NAME}' already exists in ${PROJECT_KEY}." + skipped=$((skipped+1)) + continue + fi + + # Other failure -> count as failure but continue to next project + echo "FAIL: could not create version in ${PROJECT_KEY} (HTTP ${HTTP_CODE}). Response:" + cat resp.json || true + echo + failed=$((failed+1)) + done + + echo "======================================================" + echo "Summary: ok=${ok} skipped=${skipped} failed=${failed}" + echo "======================================================" + + if [ "$failed" -gt 0 ]; then + exit 1 + fi + + + update_jira_releases: + if: github.event.action == 'edited' + runs-on: ubuntu-slim + env: + JIRA_BASE_URL: https://scylladb.atlassian.net + JIRA_AUTH: ${{ secrets.caller_jira_auth }} + PROJECT_KEYS: ${{ inputs.jira_project_keys }} + + steps: + - name: Debug milestone input + run: | + echo "Projects: '${{ inputs.jira_project_keys }}'" + echo "Title: '${{ github.event.milestone.title }}'" + echo "Description: '${{ github.event.milestone.description }}'" + echo "Due on: '${{ github.event.milestone.due_on }}'" + echo "Action: '${{ github.event.action }}'" + + - name: Update Jira version details in each project + shell: bash + run: | + set -euo pipefail + + if [ -z "${JIRA_AUTH:-}" ]; then + echo "ERROR: jira_auth secret is not set." + exit 1 + fi + + NAME="${{ github.event.milestone.title }}" + DESC="${{ github.event.milestone.description }}" + DUE_ON="${{ github.event.milestone.due_on }}" + + # GitHub due_on is ISO 8601; Jira expects YYYY-MM-DD + RELEASE_DATE="" + if [ -n "${DUE_ON:-}" ]; then + RELEASE_DATE="${DUE_ON%%T*}" + fi + + echo "Version name: ${NAME}" + echo "Description: ${DESC:-}" + echo "Release date: ${RELEASE_DATE:-}" + echo "Projects: ${PROJECT_KEYS}" + echo + + # Split comma-separated keys safely (trim whitespace) + IFS=',' read -r -a KEYS <<< "${PROJECT_KEYS}" + + ok=0 + skipped=0 + failed=0 + + for raw in "${KEYS[@]}"; do + PROJECT_KEY="$(echo "$raw" | awk '{$1=$1};1')" # trim + [ -n "$PROJECT_KEY" ] || continue + + echo "======================================================" + echo "Updating Jira version in project: ${PROJECT_KEY}" + echo "======================================================" + + # Find the version ID by name + HTTP_CODE=$(curl -sS -o versions.json -w "%{http_code}" \ + "${JIRA_BASE_URL}/rest/api/3/project/${PROJECT_KEY}/versions" \ + --user "${JIRA_AUTH}" \ + -H "Accept: application/json" || true) + + if [ "$HTTP_CODE" != "200" ]; then + echo "FAIL: could not list versions in ${PROJECT_KEY} (HTTP ${HTTP_CODE}). Response:" + cat versions.json || true + echo + failed=$((failed+1)) + continue + fi + + VERSION_ID=$(jq -r --arg name "$NAME" \ + '.[] | select(.name == $name) | .id' versions.json | head -1) + + if [ -z "$VERSION_ID" ]; then + echo "SKIP: version '${NAME}' not found in ${PROJECT_KEY}." + skipped=$((skipped+1)) + continue + fi + + # Build update payload with description and releaseDate + jq -n \ + --arg desc "${DESC:-}" \ + --arg rdate "${RELEASE_DATE:-}" \ + ' + {} + + (if $desc != "" then {description: $desc} else {} end) + + (if $rdate != "" then {releaseDate: $rdate} else {releaseDate: null} end) + ' > update_payload.json + + HTTP_CODE=$(curl -sS -o update_resp.json -w "%{http_code}" \ + -X PUT "${JIRA_BASE_URL}/rest/api/3/version/${VERSION_ID}" \ + --user "${JIRA_AUTH}" \ + -H "Accept: application/json" \ + -H "Content-Type: application/json" \ + --data @update_payload.json || true) + + if [ "$HTTP_CODE" = "200" ]; then + echo "OK: updated version '${NAME}' in ${PROJECT_KEY} (id=${VERSION_ID})." + ok=$((ok+1)) + else + echo "FAIL: could not update version in ${PROJECT_KEY} (HTTP ${HTTP_CODE}). Response:" + cat update_resp.json || true + echo + failed=$((failed+1)) + fi + done + + echo "======================================================" + echo "Summary: ok=${ok} skipped=${skipped} failed=${failed}" + echo "======================================================" + + if [ "$failed" -gt 0 ]; then + exit 1 + fi + + release_jira_releases: + if: github.event.action == 'closed' + runs-on: ubuntu-slim + env: + JIRA_BASE_URL: https://scylladb.atlassian.net + JIRA_AUTH: ${{ secrets.caller_jira_auth }} + PROJECT_KEYS: ${{ inputs.jira_project_keys }} + + steps: + - name: Debug milestone input + run: | + echo "Projects: '${{ inputs.jira_project_keys }}'" + echo "Title: '${{ github.event.milestone.title }}'" + echo "Action: '${{ github.event.action }}'" + + - name: Release Jira version in each project + shell: bash + run: | + set -euo pipefail + + if [ -z "${JIRA_AUTH:-}" ]; then + echo "ERROR: jira_auth secret is not set." + exit 1 + fi + + NAME="${{ github.event.milestone.title }}" + TODAY="$(date -u +%Y-%m-%d)" + + echo "Version name: ${NAME}" + echo "Release date: ${TODAY}" + echo "Projects: ${PROJECT_KEYS}" + echo + + # Split comma-separated keys safely (trim whitespace) + IFS=',' read -r -a KEYS <<< "${PROJECT_KEYS}" + + ok=0 + skipped=0 + failed=0 + + for raw in "${KEYS[@]}"; do + PROJECT_KEY="$(echo "$raw" | awk '{$1=$1};1')" # trim + [ -n "$PROJECT_KEY" ] || continue + + echo "======================================================" + echo "Releasing Jira version in project: ${PROJECT_KEY}" + echo "======================================================" + + # Find the version ID by name + HTTP_CODE=$(curl -sS -o versions.json -w "%{http_code}" \ + "${JIRA_BASE_URL}/rest/api/3/project/${PROJECT_KEY}/versions" \ + --user "${JIRA_AUTH}" \ + -H "Accept: application/json" || true) + + if [ "$HTTP_CODE" != "200" ]; then + echo "FAIL: could not list versions in ${PROJECT_KEY} (HTTP ${HTTP_CODE}). Response:" + cat versions.json || true + echo + failed=$((failed+1)) + continue + fi + + VERSION_ID=$(jq -r --arg name "$NAME" \ + '.[] | select(.name == $name) | .id' versions.json | head -1) + + if [ -z "$VERSION_ID" ]; then + echo "SKIP: version '${NAME}' not found in ${PROJECT_KEY}." + skipped=$((skipped+1)) + continue + fi + + # Mark the version as released + jq -n \ + --arg rdate "${TODAY}" \ + '{"released": true, "releaseDate": $rdate}' > release_payload.json + + HTTP_CODE=$(curl -sS -o release_resp.json -w "%{http_code}" \ + -X PUT "${JIRA_BASE_URL}/rest/api/3/version/${VERSION_ID}" \ + --user "${JIRA_AUTH}" \ + -H "Accept: application/json" \ + -H "Content-Type: application/json" \ + --data @release_payload.json || true) + + if [ "$HTTP_CODE" = "200" ]; then + echo "OK: released version '${NAME}' in ${PROJECT_KEY} (id=${VERSION_ID})." + ok=$((ok+1)) + else + echo "FAIL: could not release version in ${PROJECT_KEY} (HTTP ${HTTP_CODE}). Response:" + cat release_resp.json || true + echo + failed=$((failed+1)) + fi + done + + echo "======================================================" + echo "Summary: ok=${ok} skipped=${skipped} failed=${failed}" + echo "======================================================" + + if [ "$failed" -gt 0 ]; then + exit 1 + fi diff --git a/.github/workflows/main_update_jira_status_to_in_progress.yml b/.github/workflows/main_update_jira_status_to_in_progress.yml deleted file mode 100644 index 923fe87..0000000 --- a/.github/workflows/main_update_jira_status_to_in_progress.yml +++ /dev/null @@ -1,63 +0,0 @@ -name: Update Jira Status - In Progress - -on: - workflow_call: - secrets: - jira_auth: - required: true - -jobs: - action-jira-status-update: - runs-on: ubuntu-latest - - steps: - - name: Extract Jira Ticket IDs - id: get-jira - shell: bash - env: - PR_TITLE: ${{ github.event.pull_request.title }} - PR_BODY: ${{ github.event.pull_request.body }} - run: | - set -euo pipefail - - # Replace backticks with spaces (no evaluation) - title="$(printf '%s' "$PR_TITLE" | tr '`' ' ')" - body="$(printf '%s' "$PR_BODY" | tr '`' ' ')" - - > tickets.txt - printf '%s\n' "$title" | grep -oE '[A-Z]+-[0-9]+' >> tickets.txt || true - printf '%s\n' "$body" | grep -iE '^Fixes[[:space:]]*[: ][[:space:]]*[A-Z]+-[0-9]+' \ - | grep -oE '[A-Z]+-[0-9]+' >> tickets.txt || true - - sort -u tickets.txt > unique_tickets.txt - if [[ ! -s unique_tickets.txt ]]; then - echo "ticket-ids=" >> "$GITHUB_OUTPUT" - exit 0 - fi - - tickets_csv=$(paste -sd, unique_tickets.txt) - echo "ticket-ids=$tickets_csv" >> "$GITHUB_OUTPUT" - - - name: Transition Jira Tickets to 'In Progress' - if: steps.get-jira.outputs.ticket-ids != '' - env: - JIRA_AUTH: ${{ secrets.jira_auth }} - shell: bash - run: | - set -euo pipefail - - if [ -z "${JIRA_AUTH:-}" ]; then - echo "ERROR: JIRA_AUTH secret is empty. Secret was not passed correctly from the calling workflow." - exit 1 - fi - - IFS=',' read -ra tickets <<< "${{ steps.get-jira.outputs.ticket-ids }}" - for ticket_id in "${tickets[@]}"; do - echo "Transitioning Jira ticket to 'In Progress': $ticket_id" - curl -v --fail -X POST \ - --url "https://scylladb.atlassian.net/rest/api/3/issue/${ticket_id}/transitions" \ - --user "$JIRA_AUTH" \ - --header "Accept: application/json" \ - --header "Content-Type: application/json" \ - -d '{"transition": {"id": "111"}}' - done diff --git a/.github/workflows/main_update_jira_status_to_in_review.yml b/.github/workflows/main_update_jira_status_to_in_review.yml deleted file mode 100644 index aa3800e..0000000 --- a/.github/workflows/main_update_jira_status_to_in_review.yml +++ /dev/null @@ -1,62 +0,0 @@ -name: Update Jira Status - In Review - -on: - workflow_call: - secrets: - jira_auth: - required: true - -jobs: - action-jira-status-update-in-review: - runs-on: ubuntu-latest - - steps: - - name: Extract Jira Ticket IDs - id: get-jira - shell: bash - env: - PR_TITLE: ${{ github.event.pull_request.title }} - PR_BODY: ${{ github.event.pull_request.body }} - run: | - set -euo pipefail - - # Single-line: replace backticks with spaces, no evaluation - title="$(printf '%s' "$PR_TITLE" | tr '`' ' ')" - body="$(printf '%s' "$PR_BODY" | tr '`' ' ')" - - > tickets.txt - printf '%s\n' "$title" | grep -oE '[A-Z]+-[0-9]+' >> tickets.txt || true - printf '%s\n' "$body" | grep -iE '^Fixes[[:space:]]*[: ][[:space:]]*[A-Z]+-[0-9]+' \ - | grep -oE '[A-Z]+-[0-9]+' >> tickets.txt || true - - sort -u tickets.txt > unique_tickets.txt - if [[ ! -s unique_tickets.txt ]]; then - echo "ticket-ids=" >> "$GITHUB_OUTPUT" - exit 0 - fi - tickets_csv=$(paste -sd, unique_tickets.txt) - echo "ticket-ids=$tickets_csv" >> "$GITHUB_OUTPUT" - - - name: Transition Jira Tickets to 'In Review' - if: steps.get-jira.outputs.ticket-ids != '' - env: - JIRA_AUTH: ${{ secrets.jira_auth }} - shell: bash - run: | - set -euo pipefail - - IFS=',' read -ra tickets <<< "${{ steps.get-jira.outputs.ticket-ids }}" - if [ -z "${JIRA_AUTH:-}" ]; then - echo "ERROR: JIRA_AUTH secret is empty. Secret was not passed correctly from the calling workflow." - exit 1 - fi - - for ticket_id in "${tickets[@]}"; do - echo "Transitioning Jira ticket to 'In Review': $ticket_id" - curl -v --fail -X POST \ - --url "https://scylladb.atlassian.net/rest/api/3/issue/${ticket_id}/transitions" \ - --user "$JIRA_AUTH" \ - --header "Accept: application/json" \ - --header "Content-Type: application/json" \ - -d '{"transition": {"id": "121"}}' - done diff --git a/.github/workflows/main_update_jira_status_to_ready_for_merge.yml b/.github/workflows/main_update_jira_status_to_ready_for_merge.yml deleted file mode 100644 index 4529d83..0000000 --- a/.github/workflows/main_update_jira_status_to_ready_for_merge.yml +++ /dev/null @@ -1,71 +0,0 @@ -name: Update Status - Ready For Merge - -on: - workflow_call: - inputs: - label_name: - required: true - type: string - secrets: - jira_auth: - required: true - -jobs: - action-jira-status-update-ready-for-merge: - if: ${{ github.event.label.name == inputs.label_name }} - runs-on: ubuntu-latest - - steps: - - name: Extract Jira Ticket IDs - id: get-jira - shell: bash - env: - PR_TITLE: ${{ github.event.pull_request.title }} - PR_BODY: ${{ github.event.pull_request.body }} - run: | - set -euo pipefail - echo "Label '${{ inputs.label_name }}' detected. Looking for Jira ticket IDs..." - - # Replace backticks with spaces (no evaluation) - title="$(printf '%s' "${PR_TITLE:-}" | tr '`' ' ')" - body="$(printf '%s' "${PR_BODY:-}" | tr '`' ' ')" - - > tickets.txt - printf '%s\n' "$title" | grep -oE '[A-Z]+-[0-9]+' >> tickets.txt || true - printf '%s\n' "$body" | grep -iE '^Fixes[[:space:]]*[: ][[:space:]]*[A-Z]+-[0-9]+' \ - | grep -oE '[A-Z]+-[0-9]+' >> tickets.txt || true - - sort -u tickets.txt > unique_tickets.txt - - if [[ ! -s unique_tickets.txt ]]; then - echo "No Jira tickets found in PR title or body. Skipping Jira update." - echo "ticket-ids=" >> "$GITHUB_OUTPUT" - exit 0 - fi - - tickets_csv=$(paste -sd, unique_tickets.txt) - echo "ticket-ids=$tickets_csv" >> "$GITHUB_OUTPUT" - - - name: Transition Jira Tickets to 'Ready for Merge' - if: steps.get-jira.outputs.ticket-ids != '' - env: - JIRA_AUTH: ${{ secrets.jira_auth }} - shell: bash - run: | - set -euo pipefail - - if [ -z "${JIRA_AUTH:-}" ]; then - echo "ERROR: JIRA_AUTH secret is empty. Secret was not passed correctly from the calling workflow." - exit 1 - fi - - IFS=',' read -ra tickets <<< "${{ steps.get-jira.outputs.ticket-ids }}" - for ticket_id in "${tickets[@]}"; do - echo "Transitioning Jira ticket to 'Ready for Merge': $ticket_id" - curl -v --fail -X POST \ - --url "https://scylladb.atlassian.net/rest/api/3/issue/${ticket_id}/transitions" \ - --user "$JIRA_AUTH" \ - --header "Accept: application/json" \ - --header "Content-Type: application/json" \ - -d '{"transition": {"id": "131"}}' - done diff --git a/.github/workflows/remove_label_from_jira_issue.yml b/.github/workflows/remove_label_from_jira_issue.yml new file mode 100644 index 0000000..f09c469 --- /dev/null +++ b/.github/workflows/remove_label_from_jira_issue.yml @@ -0,0 +1,171 @@ +name: Remove Label from Jira Issues (from jira_keys_json) + +on: + workflow_call: + inputs: + jira_keys_json: + description: 'JSON array of Jira keys, e.g. ["STAG-1","STAG-2"] or ["__NO_KEYS_FOUND__"]' + type: string + required: true + label: + description: "Label that was removed from the PR. For Jira: normal label or area/* (Scylla component)." + type: string + required: true + secrets: + jira_auth: + description: "Plain 'email:api_token' for Jira Cloud Basic auth" + required: true + +jobs: + remove_labels_from_jira: + runs-on: ubuntu-latest + env: + BASE_URL: https://scylladb.atlassian.net + SCYLLA_COMPONENTS_FIELD: customfield_10321 + + steps: + - name: Extract Jira keys from jira_keys_json + id: extract + shell: bash + env: + JIRA_KEYS_JSON: ${{ inputs.jira_keys_json }} + run: | + set -euo pipefail + + python3 - <<'PY' + import json, sys, os + + raw = os.environ.get("JIRA_KEYS_JSON", "").strip() + print(f"Incoming jira_keys_json: {raw}") + + if (not raw or raw == "[]" or raw == '[""]' or raw == '["__NO_KEYS_FOUND__"]'): + print("No usable Jira keys; nothing to update.") + open("keys.txt", "w").close() + sys.exit(0) + + try: + data = json.loads(raw) + except json.JSONDecodeError as e: + print(f"Invalid JSON: {e}", file=sys.stderr) + sys.exit(1) + + if not isinstance(data, list): + print("jira_keys_json must be an array", file=sys.stderr) + sys.exit(1) + + keys = [] + for item in data: + if isinstance(item, str) and item.strip() and item.strip() != "__NO_KEYS_FOUND__": + keys.append(item.strip()) + + uniq = [] + seen = set() + for k in keys: + if k not in seen: + uniq.append(k) + seen.add(k) + + with open("keys.txt", "w") as out: + for k in uniq: + out.write(k + "\n") + + print(f"Found {len(uniq)} issues.") + PY + + - name: Prepare payload(s) and mode (normal label or scylla component) + id: prep + shell: bash + env: + TARGET_IN: ${{ inputs.label }} + SCYLLA_FIELD: ${{ env.SCYLLA_COMPONENTS_FIELD }} + run: | + set -euo pipefail + + TARGET="${TARGET_IN}" + MODE="" + + echo "Incoming removed label: '${TARGET}'" + + # area/* → Scylla component + if [[ "$TARGET" == area/* ]]; then + MODE="scylla_component" + RAW="${TARGET#area/}" + COMPONENT_VALUE="${RAW//_/ }" + ESCAPED=$(jq -Rn --arg v "$COMPONENT_VALUE" '$v') + printf '{"update":{"%s":[{"remove":{"value":%s}}]}}\n' "$SCYLLA_FIELD" "$ESCAPED" \ + > payload_scylla.json + echo "scylla component remove payload ready" + else + # Normal Jira label removal + MODE="label" + jq -n --arg label "$TARGET" \ + '{update:{labels:[{remove:$label}]}}' > payload_label.json + echo "label removal payload ready" + fi + + echo "mode=${MODE}" >> "$GITHUB_OUTPUT" + + - name: Apply to each issue (Basic auth) + id: apply + shell: bash + env: + JIRA_AUTH: ${{ secrets.jira_auth }} + BASE_URL: ${{ env.BASE_URL }} + MODE: ${{ steps.prep.outputs.mode }} + TARGET_LABEL: ${{ inputs.label }} + run: | + set -euo pipefail + + if [ ! -s keys.txt ]; then + echo "No issue keys found; nothing to update." + exit 0 + fi + + echo "Operation mode: ${MODE}" + + if [ "$MODE" = "scylla_component" ]; then + PAYLOAD_FILE="payload_scylla.json" + ACTION_DESC="Remove Scylla component" + else + PAYLOAD_FILE="payload_label.json" + ACTION_DESC="Remove Jira label" + fi + + ok=0; skipped=0; failed=0 + + while IFS= read -r key; do + [ -n "${key:-}" ] || continue + + ISSUE_URL="${BASE_URL}/rest/api/3/issue/${key}" + + echo "${ACTION_DESC} on ${key} ..." + code=$(curl -sS -o resp.json -w "%{http_code}" \ + -X PUT "${ISSUE_URL}" \ + --user "$JIRA_AUTH" \ + -H "Accept: application/json" \ + -H "Content-Type: application/json" \ + --data @"${PAYLOAD_FILE}" || echo "000") + + if [[ "$code" == "204" || "$code" == "200" ]]; then + echo "OK ${key} (${code})" + ok=$((ok+1)) + elif [[ "$code" == "400" ]]; then + echo "SKIP ${key} (${code}) – value may not exist in Jira" + skipped=$((skipped+1)) + head -c 200 resp.json || true + echo + else + echo "FAIL ${key} (${code})" + failed=$((failed+1)) + head -c 400 resp.json || true + echo + fi + + sleep 0.2 + done < keys.txt + + echo "Summary: ok=${ok}, skipped=${skipped}, failed=${failed}" + + if [ "$failed" -gt 0 ]; then + exit 1 + fi diff --git a/scripts/__pycache__/jira_sync_logic.cpython-312.pyc b/scripts/__pycache__/jira_sync_logic.cpython-312.pyc deleted file mode 100644 index 2a3bfde524528095035830ddc21754335fa92f8c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 32948 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 F{y#+}6E6S& diff --git a/scripts/__pycache__/jira_sync_modules.cpython-312.pyc b/scripts/__pycache__/jira_sync_modules.cpython-312.pyc deleted file mode 100644 index c7a50e07a054e8b68ca296ad2984a3d12ad1fb67..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 55607 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ⅆ!t(>dr2*mO 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 kb%7 diff --git a/scripts/create_jira_issue_from_gh_issue.py b/scripts/create_jira_issue_from_gh_issue.py new file mode 100644 index 0000000..d968835 --- /dev/null +++ b/scripts/create_jira_issue_from_gh_issue.py @@ -0,0 +1,387 @@ +#!/usr/bin/env python3 +""" +create_jira_issue_from_gh_issue.py - Create a Jira issue from a newly opened GitHub issue. + +Reads environment variables set by the GitHub Actions workflow and creates +a corresponding Jira issue in the configured project, including: + - Title, description, labels, issue type mapping + - Assignee / reporter lookup (best-effort by display name) + - Clickable cross-links in both the Jira description footer and + the GitHub issue body footer + - Markdown-to-ADF conversion for the issue description + +Reuses HTTP helpers from jira_sync_modules to avoid code duplication. +""" + +import json +import os +import re +import sys +from urllib.parse import quote + +from jira_sync_modules import ( + _jira_get, + _jira_post, + _jira_put, + _gh_api, +) + +# --------------------------------------------------------------------------- +# Constants +# --------------------------------------------------------------------------- +JIRA_BASE_URL = "https://scylladb.atlassian.net" + +# --------------------------------------------------------------------------- +# Environment +# --------------------------------------------------------------------------- +JIRA_AUTH = os.environ.get("JIRA_AUTH", "") # email:api_token +GITHUB_TOKEN = os.environ.get("GITHUB_TOKEN", "") +JIRA_PROJECT_KEY = os.environ.get("JIRA_PROJECT_KEY", "") + +# GitHub issue payload fields (set by the workflow) +ISSUE_TITLE = os.environ.get("ISSUE_TITLE", "") +ISSUE_BODY = os.environ.get("ISSUE_BODY", "") +ISSUE_NUMBER = os.environ.get("ISSUE_NUMBER", "") +ISSUE_HTML_URL = os.environ.get("ISSUE_HTML_URL", "") +ISSUE_LABELS = os.environ.get("ISSUE_LABELS", "") # comma-separated +ISSUE_TYPE = os.environ.get("ISSUE_TYPE", "") # GitHub issue type name +ISSUE_MILESTONE = os.environ.get("ISSUE_MILESTONE", "") +OWNER_REPO = os.environ.get("OWNER_REPO", "") + +# Assignee / reporter (GitHub login + display name) +GH_ASSIGNEE_NAME = os.environ.get("GH_ASSIGNEE_NAME", "") +GH_REPORTER_NAME = os.environ.get("GH_REPORTER_NAME", "") + + +# --------------------------------------------------------------------------- +# Markdown -> ADF conversion +# --------------------------------------------------------------------------- + +def _inline_markdown(text: str) -> list[dict]: + """Convert inline markdown (bold, italic, code, links) to ADF inline nodes.""" + if not text: + return [{"type": "text", "text": ""}] + + nodes: list[dict] = [] + pattern = re.compile( + r"\*\*(.+?)\*\*" # group 1: bold + r"|`([^`]+)`" # group 2: inline code + r"|\[([^\]]+)\]\(([^)]+)\)" # group 3,4: link text + url + r"|(? last_end: + nodes.append({"type": "text", "text": text[last_end:m.start()]}) + + if m.group(1) is not None: + nodes.append({"type": "text", "text": m.group(1), + "marks": [{"type": "strong"}]}) + elif m.group(2) is not None: + nodes.append({"type": "text", "text": m.group(2), + "marks": [{"type": "code"}]}) + elif m.group(3) is not None: + nodes.append({"type": "text", "text": m.group(3), + "marks": [{"type": "link", "attrs": {"href": m.group(4)}}]}) + elif m.group(5) is not None: + nodes.append({"type": "text", "text": m.group(5), + "marks": [{"type": "em"}]}) + + last_end = m.end() + + if last_end < len(text): + remaining = text[last_end:] + if remaining: + nodes.append({"type": "text", "text": remaining}) + + return nodes if nodes else [{"type": "text", "text": text}] + + +def _markdown_to_adf_nodes(text: str) -> list[dict]: + """Convert markdown text to a list of ADF block-level nodes.""" + nodes: list[dict] = [] + lines = text.split("\n") + i = 0 + + while i < len(lines): + line = lines[i] + stripped = line.strip() + + # Blank line + if not stripped: + i += 1 + continue + + # Fenced code block + if stripped.startswith("```"): + lang = stripped[3:].strip() + code_lines: list[str] = [] + i += 1 + while i < len(lines) and not lines[i].strip().startswith("```"): + code_lines.append(lines[i]) + i += 1 + if i < len(lines): + i += 1 + node: dict = { + "type": "codeBlock", + "content": [{"type": "text", "text": "\n".join(code_lines)}], + } + if lang: + node["attrs"] = {"language": lang} + nodes.append(node) + continue + + # Heading + hm = re.match(r"^(#{1,6})\s+(.*)", line) + if hm: + nodes.append({ + "type": "heading", + "attrs": {"level": len(hm.group(1))}, + "content": _inline_markdown(hm.group(2).strip()), + }) + i += 1 + continue + + # Horizontal rule + if re.match(r"^[-*_]{3,}\s*$", stripped): + nodes.append({"type": "rule"}) + i += 1 + continue + + # Blockquote + if stripped.startswith(">"): + quote_lines: list[str] = [] + while i < len(lines) and lines[i].strip().startswith(">"): + quote_lines.append(re.sub(r"^>\s?", "", lines[i])) + i += 1 + inner = _markdown_to_adf_nodes("\n".join(quote_lines)) + if not inner: + inner = [{"type": "paragraph", + "content": [{"type": "text", + "text": "\n".join(quote_lines)}]}] + nodes.append({"type": "blockquote", "content": inner}) + continue + + # Bullet list + if re.match(r"^[\s]*[-*+]\s", line): + items: list[dict] = [] + while i < len(lines) and re.match(r"^[\s]*[-*+]\s", lines[i]): + item_text = re.sub(r"^[\s]*[-*+]\s+", "", lines[i]) + items.append({ + "type": "listItem", + "content": [{"type": "paragraph", + "content": _inline_markdown(item_text)}], + }) + i += 1 + nodes.append({"type": "bulletList", "content": items}) + continue + + # Ordered list + if re.match(r"^[\s]*\d+[.)]\s", line): + items = [] + while i < len(lines) and re.match(r"^[\s]*\d+[.)]\s", lines[i]): + item_text = re.sub(r"^[\s]*\d+[.)]\s+", "", lines[i]) + items.append({ + "type": "listItem", + "content": [{"type": "paragraph", + "content": _inline_markdown(item_text)}], + }) + i += 1 + nodes.append({"type": "orderedList", "content": items}) + continue + + # Regular paragraph + nodes.append({ + "type": "paragraph", + "content": _inline_markdown(stripped), + }) + i += 1 + + return nodes + + +# --------------------------------------------------------------------------- +# Helpers +# --------------------------------------------------------------------------- + +def _map_issue_type(gh_type_name: str, labels: list[str]) -> str: + """Map a GitHub issue type / labels to a Jira issue type name.""" + if gh_type_name: + low = gh_type_name.lower() + if low == "bug": + return "Bug" + if low in ("enhancement", "feature"): + return "Enhancement" + if low == "epic": + return "Epic" + label_set = {l.lower() for l in labels} + if "bug" in label_set: + return "Bug" + if "enhancement" in label_set: + return "Enhancement" + return "Task" + + +def _find_jira_account_id(display_name: str) -> str | None: + """Best-effort lookup of a Jira accountId by display name.""" + if not display_name: + return None + url = f"{JIRA_BASE_URL}/rest/api/3/user/search?query={quote(display_name)}&maxResults=50" + result = _jira_get(url, JIRA_AUTH) + if result and isinstance(result, list): + for user in result: + if user.get("displayName", "").lower() == display_name.lower(): + return user["accountId"] + return None + + +def _build_description_adf(body_text: str, gh_url: str) -> dict: + """Build an ADF document from the GH issue markdown body + a footer link.""" + content_nodes = _markdown_to_adf_nodes(body_text) if body_text else [] + + # Divider before footer + content_nodes.append({"type": "rule"}) + + # Footer with clickable link to original GitHub issue + content_nodes.append({ + "type": "paragraph", + "content": [ + {"type": "text", "text": "Original GitHub issue: "}, + { + "type": "text", + "text": gh_url, + "marks": [{"type": "link", "attrs": {"href": gh_url}}], + }, + ], + }) + + return {"version": 1, "type": "doc", "content": content_nodes} + + +# --------------------------------------------------------------------------- +# Core logic +# --------------------------------------------------------------------------- + +def create_jira_issue() -> str | None: + """Create a Jira issue and return its key, or None on failure.""" + labels = [l.strip() for l in ISSUE_LABELS.split(",") if l.strip()] + issue_type = _map_issue_type(ISSUE_TYPE, labels) + + # Determine priority from labels + priority = None + priority_labels = {"P0", "P1", "P2", "P3", "P4"} + for label in labels: + if label in priority_labels: + priority = label + break + + description_adf = _build_description_adf(ISSUE_BODY, ISSUE_HTML_URL) + + payload: dict = { + "fields": { + "project": {"key": JIRA_PROJECT_KEY}, + "summary": ISSUE_TITLE, + "description": description_adf, + "issuetype": {"name": issue_type}, + "labels": labels if labels else [], + } + } + + if ISSUE_MILESTONE: + payload["fields"]["fixVersions"] = [{"name": ISSUE_MILESTONE}] + + if priority: + payload["fields"]["priority"] = {"name": priority} + + # Reporter + reporter_id = _find_jira_account_id(GH_REPORTER_NAME) + if reporter_id: + payload["fields"]["reporter"] = {"accountId": reporter_id} + + print(f"Creating Jira issue in project {JIRA_PROJECT_KEY}") + print(f" type = {issue_type}") + print(f" summary = {ISSUE_TITLE!r}") + print(f" labels = {labels}") + print(f" priority = {priority}") + print(f" reporter = {GH_REPORTER_NAME!r} -> {reporter_id}") + + url = f"{JIRA_BASE_URL}/rest/api/3/issue" + status, body = _jira_post(url, payload, JIRA_AUTH) + + if status not in (200, 201): + print(f"ERROR: Jira issue creation failed (HTTP {status})") + print(body) + return None + + jira_key = json.loads(body)["key"] + print(f"Created Jira issue: {jira_key}") + + # Assign (separate call) + assignee_id = _find_jira_account_id(GH_ASSIGNEE_NAME) + if assignee_id: + print(f" assignee = {GH_ASSIGNEE_NAME!r} -> {assignee_id}") + assign_url = f"{JIRA_BASE_URL}/rest/api/3/issue/{jira_key}/assignee" + a_status, a_body = _jira_put(assign_url, {"accountId": assignee_id}, JIRA_AUTH) + if a_status not in (200, 204): + print(f"WARNING: Could not assign {jira_key} (HTTP {a_status}): {a_body}") + + return jira_key + + +def append_jira_link_to_gh_issue(jira_key: str) -> None: + """Append a Jira link footer to the GitHub issue body.""" + jira_url = f"{JIRA_BASE_URL}/browse/{jira_key}" + footer = f"\n\n---\nJira issue: [{jira_key}]({jira_url})" + + current_body = ISSUE_BODY or "" + new_body = current_body + footer + + owner, repo = OWNER_REPO.split("/", 1) + url = f"https://api.github.com/repos/{owner}/{repo}/issues/{ISSUE_NUMBER}" + + status, body = _gh_api("PATCH", url, GITHUB_TOKEN, {"body": new_body}) + + if status == 200: + print(f"Updated GitHub issue #{ISSUE_NUMBER} with Jira link to {jira_key}") + else: + print(f"WARNING: Failed to update GitHub issue #{ISSUE_NUMBER} (HTTP {status})") + print(body) + + +# --------------------------------------------------------------------------- +# Main +# --------------------------------------------------------------------------- + +def main(): + print("=" * 60) + print(" create_jira_issue_from_gh_issue") + print("=" * 60) + + if not JIRA_AUTH: + print("ERROR: JIRA_AUTH env var is not set.") + sys.exit(1) + if not JIRA_PROJECT_KEY: + print("ERROR: JIRA_PROJECT_KEY env var is not set.") + sys.exit(1) + if not ISSUE_TITLE: + print("ERROR: ISSUE_TITLE env var is not set.") + sys.exit(1) + if not GITHUB_TOKEN: + print("ERROR: GITHUB_TOKEN env var is not set.") + sys.exit(1) + + jira_key = create_jira_issue() + if not jira_key: + print("ERROR: Failed to create Jira issue. Exiting.") + sys.exit(1) + + append_jira_link_to_gh_issue(jira_key) + + print("=" * 60) + print(f" Done. GitHub #{ISSUE_NUMBER} -> {jira_key}") + print("=" * 60) + + +if __name__ == "__main__": + main() \ No newline at end of file From f6e0007da35e878723a426accb84ae8db7a268d1 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 29 Jun 2026 13:54:50 +0000 Subject: [PATCH 14/15] Remove debug output from Jira web-link sync helper --- .../__pycache__/jira_sync_logic.cpython-312.pyc | Bin 0 -> 32948 bytes .../jira_sync_modules.cpython-312.pyc | Bin 0 -> 55554 bytes scripts/jira_sync_modules.py | 7 +------ 3 files changed, 1 insertion(+), 6 deletions(-) create mode 100644 scripts/__pycache__/jira_sync_logic.cpython-312.pyc create mode 100644 scripts/__pycache__/jira_sync_modules.cpython-312.pyc diff --git a/scripts/__pycache__/jira_sync_logic.cpython-312.pyc b/scripts/__pycache__/jira_sync_logic.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..68b085ce979dc1c9b4bf41aae76c2692cee34cc0 GIT binary patch literal 32948 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 F{{dHD6G;F7 literal 0 HcmV?d00001 diff --git a/scripts/__pycache__/jira_sync_modules.cpython-312.pyc b/scripts/__pycache__/jira_sync_modules.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e67e208a0c8502ff49bdc06ec1b587edcee28eed GIT binary patch literal 55554 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 DJ1KX` literal 0 HcmV?d00001 diff --git a/scripts/jira_sync_modules.py b/scripts/jira_sync_modules.py index f4e04c3..398c375 100644 --- a/scripts/jira_sync_modules.py +++ b/scripts/jira_sync_modules.py @@ -1277,8 +1277,6 @@ def add_pr_weblink_to_jira( jira_auth: str, ) -> None: """Ensure each Jira issue has a remote link to the PR URL (idempotent).""" - print(f"jira_keys_json={jira_keys_json}") - if not jira_auth: print("Error: jira_auth is not set or empty.") sys.exit(1) @@ -1294,10 +1292,7 @@ def add_pr_weblink_to_jira( return stripped_title = pr_title.strip() if pr_title else "" - if stripped_title: - link_title = stripped_title - else: - link_title = normalized_pr_url + link_title = stripped_title or normalized_pr_url payload = { "object": { "url": normalized_pr_url, From 4a5fc0af0de9ee41057ee32620dd1b8297a76a8c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 29 Jun 2026 14:02:43 +0000 Subject: [PATCH 15/15] Remove tracked Python cache artifacts --- .../__pycache__/jira_sync_logic.cpython-312.pyc | Bin 32948 -> 0 bytes .../jira_sync_modules.cpython-312.pyc | Bin 55554 -> 0 bytes 2 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 scripts/__pycache__/jira_sync_logic.cpython-312.pyc delete mode 100644 scripts/__pycache__/jira_sync_modules.cpython-312.pyc diff --git a/scripts/__pycache__/jira_sync_logic.cpython-312.pyc b/scripts/__pycache__/jira_sync_logic.cpython-312.pyc deleted file mode 100644 index 68b085ce979dc1c9b4bf41aae76c2692cee34cc0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 32948 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 F{{dHD6G;F7 diff --git a/scripts/__pycache__/jira_sync_modules.cpython-312.pyc b/scripts/__pycache__/jira_sync_modules.cpython-312.pyc deleted file mode 100644 index e67e208a0c8502ff49bdc06ec1b587edcee28eed..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 55554 zcmeFa33OXmdM1dKSP6gt_e~%vkp#t6qBd$XMN$&Akg`ZwmTZ|t@qrX6ZuJ0477DCl z)l{EQWu;A(Ya%$d$4JU2MW?D0b|=$OpJZlKwrk>?PI?{%s7RyL-E!jTq$bld^3szO zYtEVZ{`*#tpzKvc%+L@ zziQIy?&vt(MIEQ-4CDHXdiHI&Xkg#Qi$?Zsx@cnG=8IhD3O&3d~ z-=)FgB1FYq5AK$6IV@JWa@UKyTR0!?<_7&-9(!6EtOyn(Cj+HqsjXZ-;#Jyo^pET1 z3J|Xlf0Wz$v|@QKuIQWQi&Y%*L9NtUlpvq29Dd_2D}^&eEIM6qoA^C!lxkasc-0*0 z$!)|-@L z#A;N5lG*sOnPie@l6+U4TO034b0CX5j6B=8r;uMe{*K^}^)_oo2cGR$%Ii#f)`e#W zxTCmt41dS*=L&AajOoVxgKP#r&Bl&mP>xD0HH9okSKDuO=27sEU%JHVQGHFzT=-5=z*f$_o1!SR9c zl=yHo6q*T2Px;`))U}`#VVIwq*cc@(W0rP+3!-)7N(s}`<2S@~te_B;G|fvTh}|9@ z4A0;`KR6j0r4H3pZfI&^A~+eAtEYJ~%@14;qS2FAm526zbo~@RbR`%H$&|M=*&pnr7Iua5or)X3-%M&5q?%IMG)Wmu@`7}n8{Uz{9`_Mgzo z-V@NLOdN(KU`Scc2EROmVpEnGetc>=IEj1Kb7xO=@%$8@veCG)%R?1Nm@;&9r3`0I zg?_4?>&p}v)#{h;rndYsji-5sjO$Z*nLaKvtmRGO6hFxJD##U z-QL}E^lUp_h>xu8J$+|;Pj&UBtR1~)yUv{L?Znl&zW(0R$kBSVyX#aZH`@eRWNjdA!QOroiFa^@Rrxnb`=RX~yWb;BN>1 zcH*x!WeVeMNoDcD@C-jWB#{*~k#rz~bVmGrdKAGOT~s%weTsYZ!3JfJNs5fmjhsn- z-lq$gBOPbi`|BSXOKW=n+xnD+4^EE{4g~{xz8N(NQ7!#zXPd4}O$3|xnaRl@-$W~2)5vJ}%FN}4 z!5IwSAidHV?u3T;(dlrgNqzm)r8i|82n|kRF^B~DHWcy{mF7n zVI0=qP*{wZHefUuJMs7F0R$&?diFwG%B6wAkSN0^ccV_}@Mp)TPl6HI0Ne&mv}vG){j^p&*HQeLmU=vcg7 zh$?<`W7Ig7y*^*!7C584Na}T) z#4&N^sNpr;8_II42S*il%eh63-kiL;lL(1nAJV!Rb*Dh*yJ?mHyfzgCQc4 zF^91};x+O|>Y6|VgqsklX=js^ds8Sl2qN@9P=>1)0jaJQxb@ZcW)P?`{oF4oz{vRF?eB1?e|W zFILJ<#Qc@uAb#_V1~IX^na8IFIV>MMo}`Q;SdZw1D$uQr6>wuL%Nw5ea@NE?YBa)s^z*6de9fbOw}Z%@#bn zmWGzj39kJ~>w$-E?@Kek?)=$fGajymdeQbDHaa?LbwAwKp4CxmeCM#Uqaf>DhXL2` zX4~-K-2yXRmzq1aS>CNM(w%KAtaW!58QBHUSu;Q*V^oJ_+Z5F!#Il1h zD{8`vZJo_h>85CwvNTzumN9MaQYoB8yU=VB$Hv(+EV2s46}8BvV3D_qLSus9dD^54(`wH?QJdVRsQD_! znAcBY3^{!So8heK)+b?~9Fy~DQYl*+#ypqJf;^f9Zzy9;n`PgIjpEjKl#RkA=Np#c zT^-vfN@nevGMzM^xa_DMd7I>#(ze4nX6;|K-#R0HYqo~`$lG>WUyjnc!Zrbs(gi(C zn}Qz%@U_uFwr5Cyi@a+{8-z-Q62a-88ur(Quvmu&fV9*r^s+w;!W6I%E9=bQ$mk@f zHIS|n2Lloigmf(y>hP3*$F63H+z$CcTcQfmcJdS2|9-+DSSyoxTWl?jB0JQGietN( zo(eTZEKSoh$CZ+i7vv0h(S74YXe31Qk>-v15qBt; zv_r{hzk+y^_zQgngEyyp?A2A*&K+BIIOjT7-QKz5kL<41oW{k-;`nM#VXP?Tc&yWJ zEnO|$8f%L`v)H+~8%w)q=e+SVtInOjF!a*+ym8g)c-eK+weX@)aVTj$EdTu4V$D+R zQn65bAZb1L*krbOA0kKJE2YRWdw)FlVR8AJb+6XN`@eVLw=R75xs`2umbdLmY}=P8 zZdc#B)m0?#zn8-t)K6ZZ$BI7 z6W+QNZ{xDJaq-68%7pjed`HUdUG)^)aou*sjq$!%S6mRSCJ)Wpw3&3q`VKnqc0)D$&;U#i8djcrP& zbh_uUywBQa9UAz;A?Jr}$cegD{}OdGu|-mkOZPY23i|wcf+mXU~X}Bh3 zE0N>QW=(2)+$`V6R+ANSX~sfH30a*`e8Tq17{yocr|&1 zbUKWjvL$NnS~xp{8O77Qm{8ml9a#`#0 zq8_v^U)#E(^GE6_O{*%{NL8|YsNDxm-qfvf>(csLGd59I+WWgr zjW4~wnbrrF983P5^=fKYE#Ji(?fs&o8TA5Mtr^^fh0;!Rz*)f8418qdq73*k1c70F zHzvmYOa??^q3IdmnP+Z*v7eME$(F`U_$-)p5n+|YL`WoJvP|YAk{L3YDbbfZ8vP=c zASS$i1)!^fZ2+i+kb=+*RDz%okZ4>3@%fw|aH2?|?riiQ1^EjJ9VCeokPEODGAJ#6 zLePmQrzF(Y4>)3!LphYcOzO5aqE|>D0aAKXl-6I1vYx9P80hIG*s^cnXz#h6&Vhl- zOES)U{z`DtuQH6x=Np>@!< z1ccL5iQt!;83J4?${q1=g7F6u&fS3FWjHrvf8ihxu=;ZVZwVf*(Je}+`>&4z#=0Ezhpvu-1m+qe7O9AcMVcy+?ml`( zgDT!>kf?D#wGTs~u=@b4q)u*9`j_e>_irGwt7nQ;tYLigDnsjuYnp-N8dFQ2r5M_E zlQfmHVWcB_zxoS)BJK`FmO(FBTf|WBhnQ6Cm^A}HxNN__R<2f?e@!2VY&$9Snh5vF zQ`TRrz6)Sqcx>wsPBrjj_~!AF>mqjXy`s*G6f(w8O(6|}zb0a+X^hxAgTp||SWE}x z@X~8n6Dg|kQzxQ_G)bAPB66$`f-ZF|Ge_GmzJ-+W38(?EX&@nCB5v8(7%4s{HorkC zRmJ(+A`Q>5*OaBzrW4sNnqjrWqo5D{JDSl4JwKrxJhF|om8D@Z*G2Z!_-mymQpSPCNOwEKV8!(Viw_f@a_hU9`f5M=P;9>31PSMy43ZG4 zF%rPc6f4OpO*2E9nuEi5L&awdPK|huf*Btdb7M0Id?#ZiNz9S5V@>3O!-K$S`7q4` zV(5U7z8D6B$seOT9dySuHZ?jaa-aDpdwS3J3_!|#0wQvJcOC717P4=12-`!LA(a6i zAEl(T6c8}Fjz{H>Q=Se~X8^b_(1H+8Vj=zp1;m8%5f(vwvls%JvPdygR#}S1&rzf- zaT4G*plWI$$%q*POoXY*zbaQEBb&2f|Kh)m_^;zH)B|P#7;7zYY~2eZ3l{|YmZZu5 zp(7UnC73h!as6jHy{%gh_|h9#EJ)Esur3 zURrBbtc}Z7@R1L!`yLw+<72DN>b*VsTgM-I{qf?(3wNyvZ~MGuwQvjLPH!Hc?^y6X zEN)qlcixo{|+$^|Gfr9$Gw-@HDM>b}xH&-z~W3yJued+5^uq z7pcQDrIdnm|M_BZ~mRY?Lh40o4v30E_N&hmP!((2NT{y z^A=>ZU|86>ux(*Bem>s4__W|^dSGoPD7OXuX10r&J}NGqJHA>}GIvb8=|p=8Oa7DH z$s^Au_FqWsxG1zdC)l4)nl7<&EoMK;&B?t}bh{|FGpDL7{5@-J?LIcL?62N$0UuXYR|rH+y3p51jswcDGHAB_fsUKLG#O&?Z-lQI(+I-n`V8dk)V zD#$_g3llKNK4VV#O8x$USuS!^D%+A*>+VO7B4K0K&cx43Sx_dDN_m zAmy@vjpsrrs<3iuDN0@tfg)B71fjO8d$1ttZ#6`LgJ09*Y6pa}C2AV^N|kF6);*>O zH|6K(TTL5ooddHdK{8o8%lb$ub~XJp_@qnzKoilKht# z2cYhjS;JQi3;J96;*|z>cSgQ;W{?M8LJWjPZ^J+6Khf9Q145o3yg_KXvVX6~+b8|O ziD~F5GT8k(F$hGnk4{d{fVzULmLArFc!v7OWN^G5ntOQ2Xab4)F6xH3bAkw|F;dT@ zt#N>0Z%9dv5yNwrBBtjmD=$UzGIA!7eV{OALW7sbwK_DQ>eBNfLItXQC<9ozsG|Ym zr0eY2-m`7%qEe-a9+JowbOI^@6~JLgZW#&M6KTnuZ~}U4MD%OBZohwIDhwL-YnTm@ ztfP!7kJwQL^e+LjH$o6>h8pAOv`FhH$a>06-QURszoK@bF+?Oo2viWyr%b^YN5d)m zD71S>WpyZ+GEx6S`RoQ@^bQmT&_B$ljF1+K^wJFO1uXn4_~I{9Kxlf(#0U{nC>Wef znMT9G3BDb-LnMcj=n#<#$%D)SvqTj5DkH>y7xAEauM0IH0IF`+Ib1IXZU$c3KG#9( zu5(*_D1J_`Z%>-)KXkYjs)VAamc380CA&LmJ+bP}nYTSQnasHl-M*J2HzTpCm%cV{ z`pk|Eet~`La6dDBC8QEcm5#-w{I_S99U=j9VOPrP($UY~L}7jlIBKq4ow zIJgx4-3fYj{O0k6r*EC4%ab=x#`M45^Eey1VBZ0Kb@V$s7s9XXTi71EDA;S0rogJh zJ$Lf&KdaF>Ju8ka%MMUO2DF2!yYFt*-8{i{_`RV&9s41+n5UI`zU=sxgGq^V*Fv;3 z{y|=+SNERR*HvYFZ`;nUa^sK6&A3jPnHFu@9zW;e3^PN$h3Sz7GIZLrF6Nn7;6q~%lV}GC) zu@B_LMp{XkRMMaYrZ{I<*^{_z&J{IMEl1>A@SM1hQ^@uBD^|)Qo~J3Evo)9GnP(nHiXznxxxengMQfC@e`gPa}S) z&0i^}sI2!_ikiCvSf;0uY%ERxpanILkDxN1ZmnPu;<;X5&Z z_%{)x%q&jIv%b1(){t1)rbwZjzjQ~*Hf53Sq_SAXA^t6734NKvlsz$`DK~h??%uQA z{TBv$+E0U%v}5gsLjQHB!Sb}e@_Q*-fv7V*(9wJPOm9zDPd|V((yUHp_gy%B2D;Yb z&w!bgkaDo%2AKXL#9QKkq})ow2gF8YOVty9hKM?3E3~*iyGb8E$YU1`l4(Pb|5te4 zLM!u^#Fg2p^A+CNetY{X4Ra^i%3Kx;#?Hsv1$%YUR0HbQ>if>rvSr(x^d$#f>Y)yO)c1 zFNN-QB#NJ!XY7clWvNMMIdZR2c={RP%z5Gbvmy=u$eH`lQ?s~hY0uqWVaF+o#KKr}{yNRbV-nv*IxSItqWSWBQNlVpgVcF|L@w(Thgz`qAuxX`m&vN0O zyT-eHiNf~zY_<;9E|x92m%e&0c<=oC?X-1Rds(Sv@w~-?r3Rt)DZ$?^Y&o*NRO}gX zG`B{uQqOn_W3}<%;<@+>!q!%yXqVvHO_F2pLT9W-a8wAU3dS{vV(Wj2eos@yA>y4a z+y9=i4l33?Mo8AWPt=e}z9^Hs@8QfE|<$h9k)TVvqJv8QL_`Qj=~y!UcQQcrz6sJ=3KwXIDpOu9Zbk5Q`7-U zHw|PiEXyGP&6Da3wiMc(Nc9l9XdIO#j;kMyIB-CV~*oa7;~x??H{%oMc*s zU8td-h+R^S;m;uGSu0Y&d)Sqbg@PZnGWd-KKZA|m&f)th@;M5gp@3>KbDGL-Snd;?p6q_ipl!<<)48zm>e@FM|^=7-n+g5b}5Opk_l6vI;X`=Go6!A+G z3{pVUcLv2uo1{`X6XyREF)m`JhsqGl=|1umt@x^zeO2-9m94GITU!%bcPD&%R(yw+ zeTNdhr{+#QgvmtP&9;S+grj`Lv2EG0E#at{>tq_0vChT3q`hfVwaP<6)vlyzw^qyY z`NbY#>;9zaz+;oeT%u@M>TP>t{i{&2JaGHKD~IB(-`n?F`@Xw>rE1r5)viR<9>KQ< zIxM!me+Q^(FX2sle+G4Q!d<%bP_%jZ#hWiK8UHBjUu4C6Zx+5<_*(HwQQdM;U9zbD zPde@y|MPxhbkytKscr1=8{f^h;rd;_xg%g9wMtwESXgiCsyDv7t6kT*-}v4xJ$}5m--+-? zmg24&GelqKuWYU<|>Wn~VMVp64 zp-v@AKQ9kewNe8eL3=)AAh=20Gt~XzdF)!Vrdc!ASg;0HYcXkaxGbz1YHKW{JgNn^ zCJ!L4Rf=m%i)&x6i8EP^xDF|*eC+cj}>UfY=JLjeQoKLH+sM!Ov0V^pxAk)Zk&AOv5E*H#Gk)}uT zST6Zd7xF65GBHsrXJpEm)&>0}hm?h^<@M-;B6d}y$)#A6ONllYHBQvcm2zdO&H;8@ zn^b}gCG14L<*3_3R!2R*s;1<&XmU@}Bv9jQ%w2uPRZ!n^l~R8xyD_wOs<^G(Hewj0P5%aocP@8YfZ)AXepm>x=F)P`|xVmfFV z*fr|lwVGkgQAheZ6SZ@mtKj?iyf3~2Mjg-+X&GF^^3~44bi~j2E|oK8$m9mD6J$*A z8fjZFQij2HBr~o{-yP}{rd!fH5!D(*B@=+Bn;2j>k|qjr+o*#gGU0X+gKO}gX>M#h z(<&iy^wn^P)Dgr|#7fD0wVyHCN=n9FA5fUdLtw6=DGDXwS}NEYle3w=Pk zKvt-Ql#_JNpPm63?y4CK;tgRCY;YWSGyA9+z~B@e!8)0Z3v0ldJH49^u2nEBv`rj4 z8L3525UR|O=0*n5u5FXzvGhcLWsbXu$r^F?A-&vvk^J+dxhc0COwC_F0M0Op??Spd}9#icnh*e;*lvY^Sbbja)OIZ$I1P zUuz8b#fc?OP6>dQjG;DW6e&Ck*5*$ZAYt~9?$mVO%zka$<6Gb3si3%q) zXw3@^3Ry{qRk_|D+44D!`pI|D4QpKi5uj&s08wQH^9!mDU^gbvtFQb&fAdxP{Mq3(XWz`k1nhj<{8LvC zuGwUTp@VByse2Btwe?Je8^l@=^6sy_E-4p@jvKhmDgd>SfL#}z;BI3A8nFv`*Wy|jcgA#cHJW>wPMFv2q z&``=SbroP5DK`Z<;C{^FE#-npWq>t8v=ci^$!u(f4!{j2{>b5vmnR&}bDbYJ+)SSFQPqwmutNKmP5!yg`G#1* zBa34`a^F(4n!k14!8n@g_-uR%IMM^_o>g16kW+QvR<)X6FFieUcjoSh;5z!idJIn& zitgKrSM#f+hr5=7OXmgG!3WkukMb*|oBntn04rB*(i(VVv(Ft_b-4jiWxM8%uKFwI zdLFrbpXwUTg^+v~Y+aZVwgD$wnh|mj&f8F(g_4ErSU<_#U1qs+&uQJBagCk7W%&R z9I`wAn*$WND^?ZDi(QWA#cY9jW5Uj!_e1Xog}(EG_t~WL!m7V^aqrU1 z-Qd!su&Ya`J1T5BCOAtUZmC@?5?VX&jV897S$3ArA6q!T>dueVExWgpnu0Ob5!)sB zcP#B$3fyfG@((6GhgLn_g~8jF+XgZY>G*az#WTl-V&{a))}`}H-NM1=h5SoN&kL}) zh_&2y-nMKK@v%;KsKbD;pwobfnA2sDQY=_jJ>@H&ZOa~r%wVcPx)A9l^a}ZBlAfng z^ukDti-i^@lAf)rp8QzFZO82_spB{F*;TE z;ujXLEL~f=BG?ZnO;3Gb5ltmeynjeIaZzwRm$W{=YRO*Ee) z?Ko?OBrRP&W!A{2vN(4di|r9DL$x)WoP=uz1zy&aqA0?nj^1^3RGxjII$BXjkDN1; zp;^=F=u4}kXugovi<6~X9xPp*Ts|ahDl3}B6{Mvs+}QtI5#WQOSv&q5fDoJ-2q9b5 ztHG!hM_~*C2tmW5FbJW9?sKJS5P|~hMqL{q1UF1G++5i@2%((ivL)(9UTN&P%EmGX z!Oc}D5JKJt2%%DwOPZR$%KSw=oQ>O>nE{m`gl!B$pgN{Q2-TY0(^%~%<*q*CYFY0G zr2f)E2C!Y1k$ov&*m{yfdALnA9!M68L!X(1+F5h5}C{u zNqlh)|2q`(cPSvow1+40A5%793?pe_lm9#Z2e=(6I4e5ST0fYPEsWn5qiz^#XeIE! zN4YZ2-X-NBGxs8*ASIPCBe~k5lvWUX&;J_={uc@a3YIBIQt*HR z;^X-rQ?P;{(i9Mt8~hW{;3JJT=!`)@O@diAvfYe*=T|BH2Na|zlj8NPIBN%E#`%9s zu^v*ae6ZEzUogF>M*iPXjDJtTf1uzI1s_uImlXUJ1s_rHzaoHvIB8k%>v+|FLHA}T z*h|45Q1FKor1P)*f24bVjUbSliFxJ!hMxZs1;nxP{~HB&Dfn9o{&x!g69xYV1;m~5 z|0e~+m-3+3b^ON^d_uve2tv6CL=Y=I6!kGm#o^BU((-?Yv)uE1d}I!ll`D(2OI<>sO{m>3lpPRY|87ya?XB^1@nefEf~z5EZTyGK zAD^dVn-7lOuC!D(=crPZM&xsuJi}&(`-N%Go$A!9X zVatjCVk~l>kl&y5ocl)>`IlpnBhLc`tcT_qys6f+RX0>m-ZV#Gb5$>6bM>(OdUtZxo(}ma>^-MK>G?}KqL$0>^O)5(nyb~#Ww5sFJ zT)?^Ilw%5qD&K)>kLgK@NKa~)+;%7&ndzUZM77Zq&keKUiH9~I_6g_9SCS_lvr1FL zvlEaKC{&T4UZXew^W1B)GtP)TH9wc97_mhVRWf4I$YWRLEL%`Hc^ z8{et0;rgBJ<|D0^cbbiK-O9o}?v4uMyIDCMqBF7zBcp@U6wgW36i~VD(;W!l#~&t5 znT&F@j%y=`31?IY!7v#kPo3unr~QKxISK-ln}Q?jV8fSZrpWsed3fsRdj?KOVfxH0 zqM;}T^KDpziZS4ywlZRY7!Ag?TSWkIBTkaIi+3EGT3qb3KV-XD&-iU?sH7# z@u4t@)s;SJZWuI}$>+rlTgCKHe9V-SHh(21m&JzAGNL0J04}5FHSqL67lE{8tNQsW zzNn&jDt0!aIBbEMs#4YnJktShGvg0RHc;C!T)G3b9gFI;1S^<}A#84@7-~*)@Zs6u zl(Il>Z`2BPCTV=hq0U@|rmws#N1qnogt};voL2o-)gR&ZrZ;NKWL3uHs(#;Q?NNKi zI7;hZ)Q8}Nb5xfxRvu7Yxz3JFa#9=sJuxR(dnq|NH_1tH>GQ;#v~_}4w~X~xj?fTu z!f3j}rE)K3+M%P0D-ftsna8%san)}%26phwr7Gx|QmW_4rE&$|)I~iTeKy1WOU4q^ zxh=mva9C0y*D>l1SIXCNU-M<3Q-ea(z?-24zDZBi`*mk{o1A0RtCZ=RG{APxw@Dop zR9}gotEpq|FHpxK)G;?h9rIAf+_XC8DrM%eI_7OsM}=mRoen-8W^<0g8+{TxqcmHp8IHXG_#rQH|@TTkbUFGEEJl#nGZ@7VTnzvcW2B zfTD*V%1e%mM1=J(Fi9A~8rj+K^M4|NV{p2T^Epr) z^<^zn&ms>!=sa@F*)TN956z5*18r-1JM&JtrmrUhS7L1WB@_-<84_R1FVatkhN)#x zXvBJ0G%Gt8$z#JxxTHF=aGS#a6C{kdp}r=zQq)G_zei1bo8?I-g^Um0=z%fX2C8=_ zVto1(0>wW)Sgp5BJma(IHKCt#mK>>2y0y5&;;?3DZGZISH|`{!*F{~F@M z6*Y_!SywSr3#Gq?e%bztQ-AG35mJ8{>s^m>^FA}`YFd_Z{;)Gyy>CH($9&riJqteR zsr-}By_P?|mhg0aY(&hTeoD;fH}>rN2iJ+b9jhDfK%jJ0=$Gv(8tSyJs{6uSRp`AL)H%i&QAk7AfevGIgEq$bOHoicP{4mH#F>JdmGBI*@Vcu60`(KGj5r2IDH^RwIW&6{IUc|$5v5OC;btF^Q7_(n zUE{0KWR9lW?}Gzpr&(;!%VXB{n=9ab=n(zibR?~vOoNZS!mtbJ&aJCSYq5I6T^#F& zZ<_dyI4`&Z0(9qm`FHl--n(k`EY!wMEZUb&KeTRnt1Q|4)O(GO&Bn5?%Z?pjDN9Par8g!*?gNT*5g?npX!YE-q7&T9BCc$AZOr|>peqaI1*)XZl+lDq;x zoA6fO_tq~~uH?YMP|H#^JOJk$grA|@;yWj9pNK^gxpnt*n-?#y_;xM(b}dc7`@Qe@ zymhnZ!*?$yeC_krNBO09#%_H%}m) zt5nFYd012$dm&L&fAhqnqLTR&j|$4}L~cjkYDhpd<)pmE-+~W`fTj*cEMP_3kXIe$ zRp`2ToboCbvbQ}fD2^RS6x7~4{-~g6{`jN3k~a&^8+y5L*@_wSV{6&tSv@A&$43ls%cYFR53+s`T59|L*Algd6M0YF zv_Hx#n72QYyk2!nE~=8It?Ysxt$K=}wYg)#MP_@s zaH3(&p67nuL4J~QmGqAs`S9q}BRF;lrX8XI^cdEFpAc>E6T;AbLi=REoia=}rz}@S zN9ee=l;twc*|~~y3k=gODJzbK!r@ed<0%t8$Gsh7?a7VKOr*>cgJU>S%`m+a-ovr{ zm|@z^ez(Ftf9g8R3nVyv!jDJnJDPXwXlQ9^*s+)YA5iEJl`MY*ENn_=Xu zRH`PUph9uw^CS!DNt`4JD`^dF1Mkhcbym`fxI(TBR=D+6(wX9z0o$)TnFat!rkEDh zwoRtW0F{_PnPrZzalXM$yHQ0Q3ZN)iRV%^{weH`SE&-F}sCVTn`RS9yAk3+4!K-rRb8n5lCPLm^)FaYP^~3$J}Q(TSyk($({0$dMsQ+}betZ9 z|II9D~lI}t$UNEebP+$2gYBNHf;Ea?*f)ofGNO>oN*KzKq zmLD?15D0jt(F#I~a!GcXd^i-{e`GJ*8EeRqg{;&vYP+@*Gh6f}US| zvI{#^n48g0g#wl7&|LOW>mMiS>l{e7;c?S!7b6hSKH} z))1v`ILhVgwy5dr=4f`*bQRN?H$=0c2<^y}rz+C3z2&}chvVQ>80Fg?icK(Tum?8HN9k&ddZp* zyw&!S<%{$Z+BRzfsxq5La|}+h=(r{Wei^<{|KvyW`Bu%C6SKDN!#Sh*@}A6>t8NaV zM4!J-aW;RfVqIeVRNno(Xdb^!lin50TbDjBYJ@s@Ih-$6ZOn&rNAu)*=*b_wA{OEl zhg~$cFyFD~&lW@rC^w9j75OQ9wwiBL0o5_ziZS0TQc8^R=cH5w8)8aLO>!jvG}60= z`VhSA9Tae*0}iWZ!lLsooc9PBHgk*!BVdtthc&66Hfx-JM;=nnoRu)-mPWtmh*7hg zQxwqd$Hbcl5P)I_W*N)DO=Mb zGRvwlQXsnC7Mrb1P?(Q;nJY>DH>fQ}qA%>7z+}&|(+5+A(J7n{&Ez26y`sx)uj(P~ zYEV#4`^5H-sBX9Tv z)R_kQmR*=yTyO%|RH z%lxmMn>+Q$SH9xgy6oGU@Kw*9N?Cjl;eWdPcKKU|?>T}w@Q(48N+eGdx)D+LY91r3Yb?~lDb_Wkih z!Ttqk+!hGFs?`F&P*A(rxwP+o{eji3wK3bH!jd;FuUZ8E&O~AB{XzghD+TS#1?`D~ zj``ysxC?Nc)|)-A_AKs9ls0{$v*zqr=v*z?LXgpG2NpU%DA}@F=zmyJ_U7(acgL&Y z^d}4)2~oJ^_x*x~)xwH5vtP}Q2a|>MtA$l7g>}n?b&I{up-s*aC}%OZ4hg6>V84< zYT?$E!rJA+TKHEgY+5a>UMXx?E^Jr~J}7Mc1a;ZnA_=sMYUp&{dYVin`($$jE z*oD~1*p_+MqwFpBv$w@}tT^kJo%IQ4<6PGV7Uy@o4CiZF+?C8}A-vKfn*=9e5?oaN zX3481ua(WaK9tNW>lP0Qb#3BNlrW}@=Px^8lIwl>^v%<;ir5Peob~XZF1Y%V)_$5m zrQ}-4&tS)eYxf;xa@4KlN*r#_{qVe(!`zuZDH2XXgKu_TkPms&Lk6FgX1g}l}XS6#ZfcP z!!0vGnFwdeO9%{`}@!MMT4NX(V$4h$@R69w=0FzaQkc7xja%E1CiaVCmGR5hC_6bo{06K z+$HetGBL%2#!F>Ea@N(~6|qW{$1#|l!Ev}JB}HGDcd@#`74KrsnslHEoCJxUqIFQ;r$6@YuZOBpc$>bEJPRqmIRUA`KaPU)vpRxUWs zoJlaMEks!7y6st%SC!$sT`~?EfL6kIa2>D`;;*7g{a6x0)C%m;E}gG=$-WrHNeLPUA z*|0de_}pEiU_X#F9i+1(^WyvB+ZWFZ{#{EiCUTzo`U$v|*t!a*5}|K=h3yW9@0spi zy9b+?V@d0A$|lh8`^9e;FLfpY`+n?hi{~zw7M^*IVbI(g6gV0-7cD}|h{xf2LJ%JwasNMvIJ$TGLi>v2Zrg6-xZh^K_yT}y*YeRti0 z_xJ;6H%_Jya!VxssA+y)$97$oV| zu~>U-XKZxQ8jnE2^}x9k=Q@~MfBH$8F6X5Fr=R5OJo|r|%IRXV#9uGzEHu4sLhz2m z*;!_Kr>vy2()7+g6T-}AKMrFcfbW~Yz+g1Q4>U5QYp5bgYqw69(N~^w4jgfpX?ZB} zfS)H1O&v7KNSeC}a+9Vcl{qd`;@29lYVxtLeN$6=%`@=C5>p6TWjkb=w?Gv~M-OLl&a2Pk#nIm?0GF>%Q{GZk?NGKu zE{EKatGfoBeu$l29cM+A6g#_Hv#UWS10`Vd_f29x@KNVsyLk>Xi}1c-hRMGVCjUMl zidNM8tK!Z#_5|q%?Tic^QcKq$1)4fZz5unmrRpz@D~Q^nX09;mBwu-Q{aCMIH;iU; zMc8}uG`TUS16+wVH<*?im`_3btxKAirOa@=OdC^u3cqr0?OBBw3x|}88^1zM#S$@VXTo#Ie-G1JY(M z?wPdxN=U@Iqp2ZG5fewMB|l{9X>OSvk&);$vQ>(#obo1}M3Ls-Y;E_!U+5F5A%q44 zc8a1dD}$`Pe+N0FOlNxg`WcV` zH);2A=O=$g8Rws62Z6QuLo-9}`nU|Xj-m9hmVXC|0xCKP_?EHtLU!xQ4bNE(LsFnSCG*a+oAf+h_TGfejw zDW)Igx6w1gW_XUS{+6!(69qx~$tbeN__;ZeRUobaV|4h7G|$*Fz+XoOv}=b}a51O* z*e@UZwL59uqwyak9|F~ywC>W}W~vHDk|uT%iG63%)XFp*bQTNAKp}D@>YBJn}ZFl;!&)g6A2~mdw=`^YZ0_i)9ZSd>K}=-7i0T^Vyd! z&Ko{(=Rj$QasGRg)_sgptcX{_6&EPQnxwV%BM@xWi-DzQ?^)m9@%~ofa4(T->-~KR zxpj-Ji`7d8!Mii*Y?WMn-8{m`zrf39v)H8){&H<*|LA|e7*lQC=l@6k_m9#B^UFKn=f6yA zx2lNJgC1jwCK@AN{(qvIv@!DcDEJYA42m9h$)o)gaQCkv*LP__{}s8k-=GQ7lr%NV znjrsGyR_%uM{lOwVaOsv(2<*(WX?7-Ti@Tq82p-xDRaP?`>YXvV0$u|=qf^59N`f% z6GIg>k!8%2S!0y}9J8WU>pmMTh}fYV_I1(lQ)ER)psMh)WymlJ0PoT^uv<7PLt;|( zPpWe!MGCn+QOhfaTQw%+IBWTqi!-Py9h_0ML*-2B^>Eg_Ygo^jzv%=knFYr04^R`E zftW=b&ak3cjnAxIx}(}rI;1;RIS%S>)9a+W>d974>5e^PJcoRD7S@ztCZEcz2BEZ1 z|D@J4Ut|zwXHtEL+M|wP4LERX=E)_gHn(6ub2Ixi*pTO&00uHBr%*hA$l1dh=JD2l z4-vdF?<6qS0^rse`Ol*GTLfgoa32t2c0+V7;Sj8dMsR#p1oB}rX@Z#&6W%JeQlJ;r zR|Q9riw=tirmoh*)Eq}5Nj3%|Q`SYSTv`f0oqR`(SuMHNfUjbnhY*@TKk~5wTQ5ie znJPT8la%5mUXtad7Uyr$miNSLr3{#0nXjbfmVjEm1wqSu!>=3*&OWD)Zt1*LtW0eU#Tx!Q{pJ6v|T)M&WwsJQ#Xd17P0-G)KoDrFM|C zIABuSl+s^GS(!k7VsJV{?Ezak#{gEADpEcGE`3rnf}uvm$O&E<{+4!(HYEG|IUNYv zmrvb170V^1@z+Wd&gyyn2Mvu2#yghVmYDt(`+bi;c6r5Jv+S-(kWT;Zr6UML{p7P$ zMKZ5Q+1QXWGY9dq6ElqeDV{TDC-f`e5ZR!1Y7)eEIA5BAPD*ZPt)cVFLSmDh^oVpK zMVYp1pyO0;UsvY&2Tg+8x@~Lwb@?}X*%|A_<|2Gt{ zK4x=8Z3^PC*%?k{vAG%Mzlo?BxUHu|NIPdkXY=IxdxbiA92e;1$6np;y>q8mYwKX# z5Wrc{kKDy8ZvV2|pKw>s9sj`LTXmP>l(6lBdzWC{^-;FxAc^Br((rZv+Su!cmj(p%bxoC z?w+~hk4*;ip6}#7hIn$%>wWC&t-k+Ezo4Y=$^S%`Z9bx(H-6yCS*Ti=d1(rlIk^jc zvD!pV)qK_mzWjwy>}0}Md*9docE^%&>A6Hb%oxNtIO=ih{ha-88*%z`QKEJ~;=8?M zRN=^Z`M}KsFCB^vtd#9oF58hPYrXFPn!Ko) zY*c<*pQOpI)nbR63+SCg7E2OOBg07Ha2D6*Hx!LLV5pFnM%mGZkRU3Eu&RlU_!deF zIiFd@Y-L0k*e|r>poOpC$~b+BN)^kqN3&RYird>X1lmFlC$tVPRjfDTal{%d`GzCl zitHg@|AT&d^Ce&O@Kqz7Q^ht32I@_5gEwkIVyxP8{T+Z|tVqa2U=b5ViI^Eb3V{~z zEDRL9`hSC7|L;-oZzxzs5Ghb3c1M{TbV^ESUc@3nJfhEh<`WO<)HJRsbC`-JA=eZf zqd+@Ggm3f}SPS^yKr$Ux=MW)P@O>j6mb&7sTy|C_oLlF*0DC}|^W4H|UD*iR-+r&iqsuutj|it6A>eD2u8{4H-CjN|;jj(Z*V;8nZ({XIher9}P1E40R#cTr9_7+r7AKlQo%-qT0S2HmQ_}=HznE|+-S5jUBpmvM4|GztXi_;$ zYl~K#L@j2Y&l7a1VgdEs)-*AY_9dk0!9JVBg;MyYLMHZt{|W?9x}Q@3h2yK#HmaNo zdJi6=e@+3EPW2_jj>dv;E6op$>j~}Gilmf2-L$u~$0jL?A)Cg|QI|mVZxphF(K0ixU z!BSPSR8?$4EYNPcFjXjudU-RvPj6)$pI24rj@ncoa5#X=D2o$OVm4Cwkjj@a73n34 z?{u{`RagPZFzPj|cC}E=%Hsk!Fv>vw*k|)K$3x~t^VeqGXuWIKOLM7U z{ak`jQWRvmCXXOp18bi)rP#0eQA*jU^@XkW=%m&sb(5x~W^H`6*Q14)p)Fcc0{*ha zTDVnJ?=ipBL7FdahdLjjm|u}5G~LOLert_-P}5!H!~G4dPio9M=5yMk)`Q#4JiYJH zifeE9ZukOw2S@M<^ecOt#<2yH-VORe_=7zn_7rTY!V+gbfr?32)Q$3qBG#Xa5hs!Y z64j$nUJ|)%oK?+^#Q~`^=%+(CNeo7H#5tct`!Ie*q^(AWr9+$SlnWHhH_2sad@2N~ zt0oh$I+?P78ae|&2}DpE%SbgQz?Dcm@`VC#nK%P$G%N{fYb4pLR#cfu{3<#`*)GLa z%V79iM%iv8urcx|moX~;7no-J1cp7bT^#N{Hnx7vEXXLa)jTJz6tdSG&8_ZE658@~ z=nX$b0f|oeX)30uUpt3nc`uDdq_~?wEi#zmN1urkj?~hnXAsk9$A;1?&oKUK_lP-1 zDwqV--!2^})qB!kJ2Op0aSKkHV$XW`Y3hToQ=mAtj%*jxb%H+z#3B_bO}F(qM5-X# zm7bB|CDc$g6>0QSCXEcYK15gq1hG--4hnGnB3<7QuOoC#H*lX_(|ysmb`c2v;P4Ec z^F-Ar9Wl}0drc&(hVF<0--t^c28s&0pNYs>EU3b<@7huBAWlP{8HXja`f^0b{{oxi zqN^KcliHhb)S&)=9zLh>1pe>PrZu?!W<9_(^fo)dicZlTot#0v8u|Y~{r!l7A5-ul z1%FAwUs3Q8f;AhR<<;GDtj)i+g)|{10Fl*(0?H{~n(P8O>qO2xt#|wk1?-$L=FgkJ zA{d{Z?>&1G*-BUmf0H5+FT#5%@KM0n9ugjCc%LE_Q{nH>BgXq&qbnwn{uW)mM8Pcz zRKUb3&f)=PmXNZKh6bcXide1zac*g(*kqOpUm9tUApcJ(%a;+P@&}Igo;}jt+1b@I z&<~r3zV3dQ(DsQ&vFn&H(&MF9E8|Dx%JSJdO$*&jNCSxRZ=)qjZ?QjVJ&<<0ki`}qVmMy5-n1^{Y<{E_q~Ug1Om5$kH0@R8-J+m; zN+@d->?CcWCy<;^#0DVGO_~~6%wM61yy4K@ue{%zXn20vR5y2ep)K|mrX#rx$7gNZ zEhv?9R=*WmZ2Rulgz7zlolJjOz3ArtM9m(d8XD^RlBPE0?!iROKB2lzu+ss@A6i7g zJNZyuEg>HreC#keT@65Yv11{h#M(y|LJPszj@WSQS%}ZQH4mJ%u;aA_KE|o^KGwI? z<*Oyt@zA0HM~Qv$?l=`j$)Z zG^R`aamv@DmP4QFs?G2Y(J*hEe*x9I_KC?{X&0>JkDa>g5)qS1I4k3)2z%Ofa@oP; z^z2|Rp?uF>m$2v9y=(7J38!BWUKkL(UrIU$HOECUSF^5IC>D(GVP*z*tM6?Qo_bn% z`n>RLP&hv<4CAb_D@p4py26?N>WesY>)QS82Om01VjanfmZbytil7=m5A$9fUd&pm zzF)hSJ$$Qtsrc@Nr1RKkSvv0))o04M;Odw+uKKpbw=QN26}tuRo_Wi|;;r$%#hRsk ziQB=3kx9Q(lF zEmj>X1UM+T+8bZX6|8KRfc{ zBQvApI3;z`-yR+(H*C1-oEn1O5X=WbrU94o*S2>a#mSE1R^XS;>67SCSRU3Xt*B!r zisElH1wXMTL%-u1>odm)!^=2=5}W?$(A7bB4JO60t7P&A zB9Fg5ilan{+LJRtTF7pokBE$MQlzNY_!0^i10_d`57n0=I9~-UCtj9X5Ig3rqA*~#UkVNc3I(W}X$De6p zt%DuX&n?%0S5Fo=YtKGcQDTkDcM@M~0RoMH@dgf7OM9kazqD33K(HbFmaR}`vos8u zMWc1Bz-nOUtXdXL6W_KT_<@fZ&Cy`=dadghQ`&RMnw#bXeSojyG<5voC^T66kfn2+ zMA51vTGRz%V}vd+40%7d>Gt8Y3KRdacb!@tqf?wOSH{d)Un$Q){6`*5zu|i1; zA*g@iQ@{|DL5!Ad{~R8jPAru&Aw_5+1vlr@RfS!)Myjf*>?b25$=BupIfL;-voy@J z2Sj_G=X<`U-MiggqOz}S}NRF|4njN6e>n&-2E5`-`lqHv!)~^MOY(14QFcIcdUmWNY1_bVBr0`Fjnou? zjce2V&z(KRKnAuGrEgTM4(lDNmViZNEoAOcQKa0bI9RwRvaLg&Nz!h}T&FVIZFYV( z;&W4t5ih14F_m&!+=e`g@qOUSA~q=(ucj(|GO>Lw(b*!~ zMH$EUeTvSu(m2(Ev0Q&kSH!r9ipY%jdx3twO92yzxo}1Ag8C6RUtflokpEXG<9BHH zeGeCKP1wBgyr$1_O^CCB8I@0`>w?Pv(BWl2=`3MV^>z8<1*C|Za2=XE#u%LP*F*8v z*KWkF;;dR(cX_^hVPxTgVBeB7`9HAGA;k-hSa)o{sLlIfZiU$ zU@9LFGa^}Y6cW@c>mf>coD`SjB?7!X5wUpNKs^4x zyMyk51)c(G6d>KQss`}6f z&iBpCIcH|h9MAd9cZH63BHYeRXue_{0FggM-^fVEZ9fnvm?o`0(S>6KLGVO}JZttJ za0@SJVm6>6f@jGNWT4K-j@vtK?)YKPV|fiyHpfQOa+7Lo65kl+D%fdDzob&XsO{Y7(ZY&uRlnjyJz+DdXif{~?AQ&cuT+jx|`NyFng(rj{ zeP*&o6b4N*Ccr9W!U2r2dloYZ)hMog-IY3DnFuN}8)eZ{gQ_Dua8vp1wQg zMmQ)3;3Le2Zn$*)x=L1l#eUf>?~H4?{G_EE!#CWzKHSUpv0e8R-OKjoDOp$2o12di z!b-sg@(6-UnMm^k{v;gooWe11##!bDCq~b!A9vk7|9yogr<5`x%_y+(EO$TmB9M}I z%=Zcm_VXuPJ>$i5uF->2ScnQekrgo5i!7qJ<}y8(xJJ>kwyb5*VXq7Z*Xho*T3^33 z-)4Mc#<4YJFu3TpR|-{lVYL`heK}TN7-wV(V7CzWuhi>U9@cUgzV@{Ys`8liH6YwX zwZ;Pa@xN}oZft9w-rGMBM(iEoDW?OK=kOVR1|Q{@5CMoIzXHU9n;E?nA^rxw!NG~i zwsxTb;ofj0#xKK2;p-EljZ@=ic_%z;5U|qbd@uO!&!eR92MF&%_=Pt{{mq0Ac^Dz_ zrp=l!pS^&fI(XgE`xOQ^@PHcEVIjFgTrIVm4!rKKue%qKyhy+!LP685JM#i@y31Fb z^Y!i8spi#*@sFzqo31^sA1b(_U4qQx`p(A7AM7q^0XTYtD`9b1uU;Wrs+IHr&R6vS z_b^5wTD636B}aJwqJ2N7;!`T@bQG^FiMtEvB>sK@{buOUAF0wI;^HW>?&7jI2LDl7 z;IfW_{p1LLyog_orz!XqL1MNN`c%HKlIk@pW9m|O)H3vII*$P}Cu=Xp5}@-~t^h9c zHYITBN8J*z)N^?$KY>hij8PO(g>) zWN!gi=B3BaYSzcErEA(%qwfoOHE+6m(XxjSXWN$O@ZD2)PA&S@B|?Zq<8FB5?p6cc zk%LPXS4L^h_!^#@3<_jFCZ{azyq4J?5m196kD)qHn2zZHdvu z(d0(evk%f)ic!;*2qv~Afgb6UPvIDMJbpf{bRy2Qtf+EbQ2?vf?^8Vki}w9xQfB9> zSSx}xJKMg#-jcs=R?c`4!p3U#&+dJytci`GnbMYV)npLvxb;qJ?3-y%^K6g~jegd> zsI=nH)4H~~z;9aaw|8tN(- zGeob(`eKu@@2Jh&RL}NB`!|ZNbpHnt^>K!0_wpo(s8##=cql%G?~Q@Pj^zINWAJda z9bPmdI#E@WeKJj75qTN)e${c{bIZY!jJganlUR^&bM6z&TfHf20e>M?hO`_?E*_^` zX9)ZQ50s*a@d7OMUi~Yfie-c66a|ZgmF@-t%mDXSJDFN^kR`gXx5&$^j+~s6Vwt_zd|5)$FeR4~E$OwYO z(|1v*mtOjPR1{6|b#4b-ar{fvLueT?w}(S0ZeoNaETJD!BW_3EL>xbd0bH1Dkm;)M zm;e5!6@WM77cZLs6;%&ohKBEY62{{2VJK-}}#u_5KykaldsA&>8F%bgaOw0i=NJZn_wf*4fzR#rniV}m;b-@$Mlb)=g9?HVBbV`TZVwGkh1g3w+WNAU zBe>bokr9z~vzG>kkL?K@&Q@Fwiy%EQZ1IH{fpf6hPo9S#F8%Pc4y=F|&!2722e=kN zrRk@fwdaqFheDS_A~`3Gb?7D)eA)jkalfOwr1!dV{^EGnK63EDVDHGG{u3jE{aM?A zfp5Px*dOd2>JRl(DTDW5%#e-JCOhL9}H2>i6$A@#3#%gq;yg)dkEfJ??u3+8K zAiObHcPxm+4Xj(UIaz%?ph+Nb01w}9%Mq(Jdzo*}ph+O`z6d_ByTQZxh6 z#(fhE)vGc-f5z*7UUh*nPsZWa;P=ElOI0q- zL=4@KqE&L%BDuYqm9sY5D|6N^IXxP04KQQ2%?3U`k#q7RXANtaD;Cxykoe?W@K@J! z#A^H5de#){(j*WF!j!qu#NPWClFjqpha1(l{#0NeRPC%u8)R-)7ezggINVi05*Q7T zKZ@efx-dbU5|)i5%ap9W+efXhP8t5eK!0 z1YO8e%G!PM{nXJ@Ieu8XXpo$jSVYb!>s85>ao0v17-V|VRm@8l2ND-#t~=3uzbENU zZQPxs-CAP>>x_o!k#@$y^hi53+lP#G&0!zWWS-7nT^LdakE+MtRo@#)9Y3ueKAjpk zljC(XDDh-_jK$AnY;w#U?*)l|7~evqH_pV?JI`gaze1HfnoCj|BF^V#C+lZ4n~26n z1)UobG}%4h{IEyx>LBb3-c{c}tqz|~4dR^CKx;mZM<2)d5v4IFy3i%4Iz&xUL+|DI zZf&w+4eRC;4|EBW!32tV<69L|?i|o6Y0E;B#7dkEb0jAd_bs-Uu@1bXH3KnAm{BHT z(A4A8DmiOGgh|cHSp-Y;YBFcVl;bQ-xtx>O7so0jrH@6NS$9{&p_wr+XaGRs&0_B0 z`f2WLn^)#X=W8Cmk)Jy)Y-;=-9%!KRZ*wVO1VZnNH+P=n0e8%Dgc}lR)Ul3X;S?f-DH4 z4j#+VrdAVXEXepJaBj(0qXEHSA4bAktyKyhu33s^6}%Wk!Cy11W@dU;APGTeUSVr~ zGDk#%1(?5ve&g~1ekSy3;2i&zb1wfg7rZ!=;BEBaL^~{d80#vrf4IWP0x_HpByPwN z(H!qEc8DR=sb=6DlD23j&Y^p}P$~s4x);2-5y79U@GxI|NRvS3h7!vC;g`hnclUn) DJ1KX`