From be1b27960a46b8e0d658ce9f2579700824823f41 Mon Sep 17 00:00:00 2001 From: "Luke \"Jared\" Bennett" Date: Tue, 27 Jun 2017 12:49:18 +0100 Subject: [PATCH 001/237] Add yellow favicon --- app/assets/images/favicon-yellow.ico | Bin 0 -> 5430 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 app/assets/images/favicon-yellow.ico diff --git a/app/assets/images/favicon-yellow.ico b/app/assets/images/favicon-yellow.ico new file mode 100644 index 0000000000000000000000000000000000000000..52618311ca6e331e078bd8c095e0aec3117608d1 GIT binary patch literal 5430 zcmcIoZ){W76~FJMO9aIXsX(2 zUlMHvVkfYzqm-hqV~ABNyqoT^Z%ZE&pG#52u1;e)xcp24i}H%rk}{3 zvG0X`ToT(xe?G659bI0L&R@&N!Fb552jrR>yiEf}?Lf5uCB} zEpdyqKbJ`RBjlnk@LW4KPfTN;;9H|lvJ5{)Z(nnpZNC)Ef|ibx_pb#KN5TJV$i`gI zUcv|*(}JluG4CBtVlUR(63(XfyRy^d|0ql1h|8<}yh@(ukY}3z!z}DfOC6n#bKp)Z zH5AMwC~(;Z&%A5<4e+w>W&1qW4wiL*C-9j~EYmTa7-@dy>AqmbCVjl<+F;-JEg{c1 z_5q-uC_>($Wj}sq-2-1=Yxv%sy&?{P_BsG|^j$QeZKt!M}fSjT9psb{_6M)%sU2RJQ8R}>#)UQyJ}AC5mL_ZjQ;4qwA7x*D5ev|q*qXTto> z_(KZsyMG`ehAGE7%pY9CE4msZkB)DWc7`c$Y#eA)cpmi;Iu0FqixE|e(XZ722YwsSL zTa>rA!&a@%4k!6Y;AqKScBGVQPbI%wOTS(3cOCwZ(UwcZ0_O{)qkianhyv#d1l*3E z3m0yvmfoswpSzUkZp~VUgLZ*DW2gtHKMXo@KbV}O)*1U~mu0QERsD_R+NZ3(P|p6h zS;$e-siLgI$a|9T2jus=MKWh|6q<29UY<;DXr$|AX>FF(ADXdK=3I*W6Em{j>c7P) zA96w8ixDyKzn>>_&Vdhh<_^nx{ATUc@~^o}&8_L=PIERz!MsHQ?q8_&8rRzAVYA$a z^k2C+?gN4IX~}CA(iBPCyT3Fw)l#eXM&4IkwO57H$rENNhn|AoG@T^RUrKJBM<3Bp z6ICD4hT#wQ7Wm~kJ}-G$hGoMU=bi2;=dK&EsdzdPiH)J0GZ`#$PlFzS@gDjo_wHk` z^$JFgz3O9_>%Vhp%wwFHlQJwDEM_R2vp;FKtOu0-dLzn~h$NGnaUaM9XC2pecAA?1 ziT=yBu|9!wufK?~*8XmnCVBW?@llRU$Vwmb4w?B>9`}K#*v3-Ns&keZNhM!43mMtN zr5wwD=8!(-_HWj$jRJPSmRfsxL{F78X`lJvXUiq5LHU5Yg*lg@)>Lxeii;Qd3RrpW zjHg$(X6@5*uQP}l#|@)tC&>FY`oCH`$Nn|guD(MkKY-JJ4;px+4>*e~YbFy?m(Tw_8`{A1i-rG1%eXUe%&UW3$yxO(`mw^ZzvPoR0Y zE>`aW>p%>Q)5uA_kI@Vs503Gr8x6ERST99j;Hx(JBhhu*TdaG)lih1qGJhB!pp@;oy z`80(bNK?CQZ&LO@pSju*vaGoGv|C?g{5XaRjzcGUoZ!628EXjOkvR&PioDVTpS-6^ z6ta?5cRb#u>~l?Oeq(M_dlhTkzZkgQ8ZXd6eTa7IvFiYMj9qkqWtP&#HkuC=IkF3$ zrk~N{a(#ThssVed4UyeBNOkYe3l!nS9Ha<*jmtc(*2Qzg2evlX$^=JfHS#BiyZXZX z0>39l$7=bn_YRp+fxFRy^8wxHmHEIB$=X+~=>^!?b#`U)l7^bf*=5CB>*-BsJwJwM!)?&mcR!`C& zqrL?>#{NcWV$F+7`&&;B<2MYF7xDaCbv#+OKT6-MC)YVl&4|x=_07n!z_;N@J^t(A zjVNuc#FOhnj6R7xM`k0rrYOCvWTd~_=)Ok$jcER@w5}3QoJIMa+eiR3?9YQT56k|x z4mI|-k-GLlYQg@w@q~TE&`Pp%#vI`*V~94fE}X^VH6^dE%BF3!8T(d1?Emj?skSI}aUSA-k*Dh# ztRZx6qgBhd&`)d7xBS|*g$BE0wB$Dc@iRX_lwV0?hlnP9L?=BcoPy?s7$^#{J}<<| zNg;eEh42jG?*xD-k382-01qLmD@M87E!jWhfYTA+~T literal 0 HcmV?d00001 From ed31624970323c13326c3bfc1e154fa4938c5a6d Mon Sep 17 00:00:00 2001 From: "Luke \"Jared\" Bennett" Date: Tue, 27 Jun 2017 12:49:50 +0100 Subject: [PATCH 002/237] Add temporary CANARY env vars to be set in Kubernetes-with-canary.gitlab-ci.yml and used in page_layout_helper.rb --- app/helpers/page_layout_helper.rb | 4 +++- .../autodeploy/Kubernetes-with-canary.gitlab-ci.yml | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/app/helpers/page_layout_helper.rb b/app/helpers/page_layout_helper.rb index 3286a92a8a7..7279d5fb2d4 100644 --- a/app/helpers/page_layout_helper.rb +++ b/app/helpers/page_layout_helper.rb @@ -35,7 +35,9 @@ module PageLayoutHelper end def favicon - Rails.env.development? ? 'favicon-blue.ico' : 'favicon.ico' + return 'favicon-yellow.ico' if ENV['CANARY'] == 'true' + return 'favicon-blue.ico' if Rails.env.development? + 'favicon.ico' end def page_image diff --git a/vendor/gitlab-ci-yml/autodeploy/Kubernetes-with-canary.gitlab-ci.yml b/vendor/gitlab-ci-yml/autodeploy/Kubernetes-with-canary.gitlab-ci.yml index 555a51d35b9..0af826e7743 100644 --- a/vendor/gitlab-ci-yml/autodeploy/Kubernetes-with-canary.gitlab-ci.yml +++ b/vendor/gitlab-ci-yml/autodeploy/Kubernetes-with-canary.gitlab-ci.yml @@ -25,7 +25,7 @@ build: canary: stage: canary script: - - command canary + - CANARY=true command canary environment: name: production url: http://$CI_PROJECT_NAME.$KUBE_DOMAIN From 8887c2457f25edab81887a09cf45ed68c9a53656 Mon Sep 17 00:00:00 2001 From: "Luke \"Jared\" Bennett" Date: Tue, 27 Jun 2017 12:57:05 +0100 Subject: [PATCH 003/237] Added canary conditional to status_entity.rb --- app/serializers/status_entity.rb | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/app/serializers/status_entity.rb b/app/serializers/status_entity.rb index 3e40ecf1c1c..1338068068a 100644 --- a/app/serializers/status_entity.rb +++ b/app/serializers/status_entity.rb @@ -8,7 +8,12 @@ class StatusEntity < Grape::Entity expose :favicon do |status| dir = 'ci_favicons' - dir = File.join(dir, 'dev') if Rails.env.development? + + if ENV['CANARY'] + dir = File.join(dir, 'canary') + elsif Rails.env.development? + dir = File.join(dir, 'dev') + end ActionController::Base.helpers.image_path(File.join(dir, "#{status.favicon}.ico")) end From dc5b5130d573a48fc34fa62862a1ad6da776b0d0 Mon Sep 17 00:00:00 2001 From: "Luke \"Jared\" Bennett" Date: Tue, 27 Jun 2017 13:43:30 +0100 Subject: [PATCH 004/237] Update canary yellow icon to be darker and added canary ci_favicons --- .../canary/favicon_status_canceled.ico | Bin 0 -> 4286 bytes .../canary/favicon_status_created.ico | Bin 0 -> 4286 bytes .../canary/favicon_status_failed.ico | Bin 0 -> 4286 bytes .../canary/favicon_status_manual.ico | Bin 0 -> 4286 bytes .../canary/favicon_status_not_found.ico | Bin 0 -> 4286 bytes .../canary/favicon_status_pending.ico | Bin 0 -> 4286 bytes .../canary/favicon_status_running.ico | Bin 0 -> 4286 bytes .../canary/favicon_status_skipped.ico | Bin 0 -> 4286 bytes .../canary/favicon_status_success.ico | Bin 0 -> 4286 bytes .../canary/favicon_status_warning.ico | Bin 0 -> 4286 bytes app/assets/images/favicon-yellow.ico | Bin 5430 -> 5430 bytes 11 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 app/assets/images/ci_favicons/canary/favicon_status_canceled.ico create mode 100644 app/assets/images/ci_favicons/canary/favicon_status_created.ico create mode 100644 app/assets/images/ci_favicons/canary/favicon_status_failed.ico create mode 100644 app/assets/images/ci_favicons/canary/favicon_status_manual.ico create mode 100644 app/assets/images/ci_favicons/canary/favicon_status_not_found.ico create mode 100644 app/assets/images/ci_favicons/canary/favicon_status_pending.ico create mode 100644 app/assets/images/ci_favicons/canary/favicon_status_running.ico create mode 100644 app/assets/images/ci_favicons/canary/favicon_status_skipped.ico create mode 100644 app/assets/images/ci_favicons/canary/favicon_status_success.ico create mode 100644 app/assets/images/ci_favicons/canary/favicon_status_warning.ico diff --git a/app/assets/images/ci_favicons/canary/favicon_status_canceled.ico b/app/assets/images/ci_favicons/canary/favicon_status_canceled.ico new file mode 100644 index 0000000000000000000000000000000000000000..48b1095370d446df1f3107565b1c5e72c0128c7d GIT binary patch literal 4286 zcmb`Je@t6d6vrQ##y>GJ(Fmo`Qu@ju;IbISe}L%7Lgt_Rq5g%2Kb9B-GvfLK)++N4 zl`M);853LW{^<}q-Jr_ZO)dyzT^2mc1 zd(Zitd(Qn)LCE93k`e*`g|8kLgeL_-aItWgP{)FPrSRBJm!_tsUFGHFjZUYt&*gH> zar>4iiZQN3T#s}A+Z7cR)}7|U9`g<`;~F!lva&MS+}uoFua~;JyQ!_MjT#ynB#iOA z1lPS>Kd}>jV9ji+2e#|$>!s1rQHsT4WL6dz7s>5*6Z29}$G7#o2x6Jsi6ZEP$CdC!@MP{GAM-Jb4g+Dz#t>Zrk z8wPM!^BI^k@?C@SIq{+-D{NkS*>IffXQE{Pd_m#&_V()dfj~g%-`vm2nKR3`Rta}C z-V4_0Q~9OCMO3a*2iG^);15Ts?1e^pXY80f)9v8rgcLJ?*-m0-h0=ScMS2qbU)sT z590|cJ^k-}HuFn9T%`j4&m4pORQ=4JZO`GBb0!VESy(&g{s7kQx*#QV>qgE8|I@Lt z{=#>!DEz`h-;!9hmulc2<+~&DfV7k1A}eA5!$@u;K&a zfLv(zgUON!?*-m0usQBSi2DYe*MBN`ROLI*r?Rnj+eZ-{A3h)s$OUX-PvTtQY~p^v z9ff-mcQy7#`R?5$x+?JYA5yt$y|<6@aleT_aLxzsq{JQkqW7+*@YPsgPvTs_4>NJ? zd6t~7du8zzf0fEK*3O{xr(^J*DcjzEJ1txF0k!?uf^tVW-s&gE!B5E1@g2XXgozv@PtaN>r&Y4(>4d2z9>E>(u zi#^v*8g;Fn`CqhiGPSLqKYlXWV7tSa^e}GmhaCm}%eoxc+)Hm{qpQxbA6|M*&%Z1? zIztuec&56jbM|jlzp(39iSLrUOghH#!mg==YQy5YvSu9L?z`Bta8}i|dVinYZf?3U zt8acvwZZnzrJHBgZ+mCCx*)KTgObBHvi@zVwN>K2aZu$uyvxsP$Fga24x$BJQ%SxT zAI)aIaZXc^c5x0Qi|@C)#<6U^i`~};tls&_Z04q$gLA-k&ZHaH_7e%UBn$Zz6CPvP zMQcJHEh!?rgu31T9!4Fn!stFc93m5EByl0SnmSVpk)GBghqIQCoj;OLkYZTg) KC`IWG#p!=)nEBZN literal 0 HcmV?d00001 diff --git a/app/assets/images/ci_favicons/canary/favicon_status_created.ico b/app/assets/images/ci_favicons/canary/favicon_status_created.ico new file mode 100644 index 0000000000000000000000000000000000000000..623c728faf6981b0b21af20b6b351ddd277fffb7 GIT binary patch literal 4286 zcmb`JUrbwd6vr}8le;l9c^Ob%zW{Uy_o1SABl-R_@K$+%aR$5qx@M>G4ao0 z%zPNz+y*Q`na=rVL6mG{wzQ>X$e%!=g|+-!g)u1`(9+v`Jl{*NyS=^rL&lFBe!ain z`JK->=l46mdj+A0|0*j5{1?7^QV^aN1i{L}L&8B8jLVJZ_PP;KvBTjw=WxtEc5Kc{zvtJ?R0=03cNKtE;QT=bVrm2k8f=k&sh3I=~!=A=4khGa&j^+A3oqr zsvGVo9*Qa;r zblsI1b8~ZAQ#3L%l9P|xR5#q!cwaETP2pE}lG*yB7*V)#-@Prf!LRC!Qb&)A2ECcF z;9k@70p||2scov99RlBSo{rY^B*ZlKZ=ClI=7J459i_U{J9QR`M6@R5XV}Ggz?no{ zXln&Zr~|ySIQ9vCESB?q<6*vKANmqheR1OSChiB^QP_Lj)p%bxoKCv=ms8}NzprqW{>3&b!To0Gsi@~59kkExGUdL zM}C>5qrV2}t*c>r^@lrT>DVC4WpPoUv&C~v_u&q2>X7@1oFKyY`gUaK#3;s4$+p4U;{jS0{ zH!QrQo-5=x??JS**_Y&d@$o|RwK{d(RLpxI8XEt8pq(q^xuQOB-q_&x6r!6=2X(-9 zE@hinj}r;CBnc%H6P{oxrZu66Lb3?dFYJh&dtM~6;DZ&1s-MNq!VPB>?=wgVONCt! aYGpamU)xWi6N-drjlwC3Qk3pfoc;s0mi`_9 literal 0 HcmV?d00001 diff --git a/app/assets/images/ci_favicons/canary/favicon_status_failed.ico b/app/assets/images/ci_favicons/canary/favicon_status_failed.ico new file mode 100644 index 0000000000000000000000000000000000000000..3073fe5a761ba1825bfbab4337a0eacf36b848c9 GIT binary patch literal 4286 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 literal 0 HcmV?d00001 diff --git a/app/assets/images/ci_favicons/canary/favicon_status_pending.ico b/app/assets/images/ci_favicons/canary/favicon_status_pending.ico new file mode 100644 index 0000000000000000000000000000000000000000..ccd00606aeb39546a35b0fc902765d0a085f394d GIT binary patch literal 4286 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 Tg7t_XR#=4bEpdPYuu8#y89IH8 literal 0 HcmV?d00001 diff --git a/app/assets/images/ci_favicons/canary/favicon_status_skipped.ico b/app/assets/images/ci_favicons/canary/favicon_status_skipped.ico new file mode 100644 index 0000000000000000000000000000000000000000..7e3be35cc3a5f869c574290f58ca1bbc6f4095ef GIT binary patch literal 4286 zcmb_eT})e59KQsOkC>Qfgi2Tc}Vmdt1zm<%m zqyeP&eLkP@pmE8b)9HK-?N1;cxLmHx`1m-4LLr!*o`zsB2*bm}BJog0!1=7l<9X^J z{Ggc8<{7f>^?Jpnr6tH@GPs>PwzjsIPbe=T&7lv6AJqr6(?!_fa2O;>$_3TfSzliV z#HM^~Jcev2{Sb z4(z$i_V#v;<&BMvy*;YQ=H}+!TKz#iinfGe&IQ_d40Tqgrl!>9ARdpCJy=*+V7%Gc zS+-tTS;>*54eCj%A=1f0b8yq{f0=ZamzQ&FilPXkqoaF1q|<2_85!Bv2RfVR^FSf^ z{6%=>-9HzSgipR}jbeSE`vLKz`S2~B;(2~Rluq_XS347dibUb@C<(~bCr!W@cvCIuHot z+)ukbcwY?3;G8g;2H83?E}48gpIMEA#56T zKZs!^{-GX4&3AKOdp^OiDSo1(Uptu(l!roULGJ~l=mHUjQ?_`UB<7wk&8{S zo4$%?;gb)P2dV|xq@JX6L1&Zh2fByoo}{~)`p}MV!=1k!BIf)98CRZP?0_=5-}rv4 zdFO+iyc2%qC*wKzaxSPR>0FQ>TJ)FQ4WHc!N$q{p&&!zVxvp27HFs`lV%J<)*Tt57 zp!vw@?--yDiKP~{@wF&$+@n1Eja&2l~{G!qp1T8YP#l}q5yWi%e zwt2snKJA%4jen!WQ-4=km!GY$c_d{#^0%oe+Mt%#TBF?SvQF0A=8&YwktE{2#)VfA%a7ZbW@7rjdva4;N-R^vP#5dUH z%;h$BRt-#zk#`Ewm1Sy9Mc&HBcT47$=yNhZ-(1-;wj%3Sw0h}>MoB&$HNT?OC&)Go z&7*5-{(kE!Yq&?&H8xF-?I)|pGd2f(vJJF%T~AJH-}F)JaCzHK4XRJg6#Uy%X{)+% z<~aYIV^h#mh^(Fr zoddLURgbUS2jJ>K;>sY&J%LmTYg`FL7;!Mj?T`&;R1%Ts2P-wzAd(FU2lXhuXGCR4 dRW^>RXLNe7eh?z3Ws1NWM0Y6x33vc0_z#P^91;Kk literal 0 HcmV?d00001 diff --git a/app/assets/images/ci_favicons/canary/favicon_status_success.ico b/app/assets/images/ci_favicons/canary/favicon_status_success.ico new file mode 100644 index 0000000000000000000000000000000000000000..a1fb6e91d653f60418ab8d1c1925b7f99aa69c2f GIT binary patch literal 4286 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 literal 0 HcmV?d00001 diff --git a/app/assets/images/favicon-yellow.ico b/app/assets/images/favicon-yellow.ico index 52618311ca6e331e078bd8c095e0aec3117608d1..b650f277fb66d6193e27e1f2bfe59f751159270b 100644 GIT binary patch literal 5430 zcmb_geM}VT8GrRIB{5da#a7(eot^!faeIy0=I+uqHTp->f7)CvX^b_ExtJJeqvmSW zhW%g>?@J3xv3K>WD6onWRspw&7A(259-_!e!6;oR7^MwRZuvM4cLv`+&&Pc#Tw?{U6^#nzqX;)X|51 zd`+}5%eu;>=lGfL*ed7QksjfSNL}Y=sJ(iea({ZL#ap3{KI}t`vv%Z;Bk$OEkz?sw zht>Ug^ z=Y|%KbvyWw!vPqfCC+hCoDdqsTNv*QeJPI-F}A}aTCBPT+@FUPZk$JGS{Xxw*qyVj zqLBaVV=Wfr*#q~J;@Q&sN<7X3IQZ~mnzOy4c=?9HH|)noD0k$)npt*VyZMbR)d}X< z^^co+j16LP))juw?RFE!-#M&~lPT;RTd>4EU%x+CUjjbBjp}ftUuP7YX=le#&Ak`x# zseWUbwQS`=z#uO6HK^M6(GQ$ReceB|?hksl8B#Dz@JrRIF=~5Y;GE@(c%y1($--vl|oSKXO33i)0@Z8mlF?VP-;y5(MeHHFZF|N{~H-!t*knlHA za#TVdJvI)xpk2-f_9Kvgs-`G^S){@RamZ0Rl$(j~dHQW7kq?AsX&CdgE2!jQ+reQi z7ugO#4udst2EUYZIb!Xlk&@@pNQM2*-rj{=Nq1PdERJD*hx-b2lswM9_b*MKeK(%R zaUVjEg8>UMQCmrO^S6q66V7ugom4)XzjMW_A+a5JW-yP#T>^Pl(YBw!weQgMv5r2> z(N4S*F9IH8Al4m{+HFOh@|~1QCza1q@X02jQTj}15ha-i@3vDkUZU=1KfjhDHarGB&La@m@~)|6+|{B}5J%T?(#+`FS%9FD&+2Ip(?DL34=mOWib z`b=>bwO1;8Am7IjBQ!pp19HN?jJ{SkdnV_1;e_`LCco~7!g(poUyAQF>Y~AUa-M>- z2G138%68=QByIKXu^;~YDGu-sh((Ts`G5vrFEug0sauO{zbvnMqtGyW74|6+2l}qF z%30I2aqUb0lUAQA8A{N{al6jIv!KpLEm5ms_S&*7m79bRJZE@b)V_GhpNF$nrCay- z{4MX?Nvm&pr#Dd_*8rXy{+#YvP<2o~NGmDk`e#&f4U`|A3e zimp>TVD#&Sbw@S4n>8u#W_m5is`J~&~`681bk23z@P+PSM^u$7G@=_~sH z?{`@x<&7y}m01d#*cc`nj<0_h-~+--{&c|(yZl!^wqtiM;HIpe|#?XqvGMC>>nSb>>SrC0(oP2ZKRk_H{*#>!`LF|E&pkZZPHdoywsvb9009nP>8KO}w!!m~aoUo_j5- zp0Q*-cQd|!>-Dj2@!oAS@~Ca-OL|Xd3m$G(`;Dc|JFvsZpQ+9H2l9t10BZ^Sg7_&2u+d`mZ;dnHvo>$`K;h_`rq z`%_`(;xl`DBSt>6w literal 5430 zcmcIoZ){W76~FJMO9aIXsX(2 zUlMHvVkfYzqm-hqV~ABNyqoT^Z%ZE&pG#52u1;e)xcp24i}H%rk}{3 zvG0X`ToT(xe?G659bI0L&R@&N!Fb552jrR>yiEf}?Lf5uCB} zEpdyqKbJ`RBjlnk@LW4KPfTN;;9H|lvJ5{)Z(nnpZNC)Ef|ibx_pb#KN5TJV$i`gI zUcv|*(}JluG4CBtVlUR(63(XfyRy^d|0ql1h|8<}yh@(ukY}3z!z}DfOC6n#bKp)Z zH5AMwC~(;Z&%A5<4e+w>W&1qW4wiL*C-9j~EYmTa7-@dy>AqmbCVjl<+F;-JEg{c1 z_5q-uC_>($Wj}sq-2-1=Yxv%sy&?{P_BsG|^j$QeZKt!M}fSjT9psb{_6M)%sU2RJQ8R}>#)UQyJ}AC5mL_ZjQ;4qwA7x*D5ev|q*qXTto> z_(KZsyMG`ehAGE7%pY9CE4msZkB)DWc7`c$Y#eA)cpmi;Iu0FqixE|e(XZ722YwsSL zTa>rA!&a@%4k!6Y;AqKScBGVQPbI%wOTS(3cOCwZ(UwcZ0_O{)qkianhyv#d1l*3E z3m0yvmfoswpSzUkZp~VUgLZ*DW2gtHKMXo@KbV}O)*1U~mu0QERsD_R+NZ3(P|p6h zS;$e-siLgI$a|9T2jus=MKWh|6q<29UY<;DXr$|AX>FF(ADXdK=3I*W6Em{j>c7P) zA96w8ixDyKzn>>_&Vdhh<_^nx{ATUc@~^o}&8_L=PIERz!MsHQ?q8_&8rRzAVYA$a z^k2C+?gN4IX~}CA(iBPCyT3Fw)l#eXM&4IkwO57H$rENNhn|AoG@T^RUrKJBM<3Bp z6ICD4hT#wQ7Wm~kJ}-G$hGoMU=bi2;=dK&EsdzdPiH)J0GZ`#$PlFzS@gDjo_wHk` z^$JFgz3O9_>%Vhp%wwFHlQJwDEM_R2vp;FKtOu0-dLzn~h$NGnaUaM9XC2pecAA?1 ziT=yBu|9!wufK?~*8XmnCVBW?@llRU$Vwmb4w?B>9`}K#*v3-Ns&keZNhM!43mMtN zr5wwD=8!(-_HWj$jRJPSmRfsxL{F78X`lJvXUiq5LHU5Yg*lg@)>Lxeii;Qd3RrpW zjHg$(X6@5*uQP}l#|@)tC&>FY`oCH`$Nn|guD(MkKY-JJ4;px+4>*e~YbFy?m(Tw_8`{A1i-rG1%eXUe%&UW3$yxO(`mw^ZzvPoR0Y zE>`aW>p%>Q)5uA_kI@Vs503Gr8x6ERST99j;Hx(JBhhu*TdaG)lih1qGJhB!pp@;oy z`80(bNK?CQZ&LO@pSju*vaGoGv|C?g{5XaRjzcGUoZ!628EXjOkvR&PioDVTpS-6^ z6ta?5cRb#u>~l?Oeq(M_dlhTkzZkgQ8ZXd6eTa7IvFiYMj9qkqWtP&#HkuC=IkF3$ zrk~N{a(#ThssVed4UyeBNOkYe3l!nS9Ha<*jmtc(*2Qzg2evlX$^=JfHS#BiyZXZX z0>39l$7=bn_YRp+fxFRy^8wxHmHEIB$=X+~=>^!?b#`U)l7^bf*=5CB>*-BsJwJwM!)?&mcR!`C& zqrL?>#{NcWV$F+7`&&;B<2MYF7xDaCbv#+OKT6-MC)YVl&4|x=_07n!z_;N@J^t(A zjVNuc#FOhnj6R7xM`k0rrYOCvWTd~_=)Ok$jcER@w5}3QoJIMa+eiR3?9YQT56k|x z4mI|-k-GLlYQg@w@q~TE&`Pp%#vI`*V~94fE}X^VH6^dE%BF3!8T(d1?Emj?skSI}aUSA-k*Dh# ztRZx6qgBhd&`)d7xBS|*g$BE0wB$Dc@iRX_lwV0?hlnP9L?=BcoPy?s7$^#{J}<<| zNg;eEh42jG?*xD-k382-01qLmD@M87E!jWhfYTA+~T From 08416f0ec7bd76938e8925ebbd4fbc52a8185ad3 Mon Sep 17 00:00:00 2001 From: Tom Grace Date: Fri, 2 Feb 2018 09:39:41 +0000 Subject: [PATCH 005/237] Update Jira integration docs for new Jira UI Closes https://gitlab.com/gitlab-org/gitlab-ce/issues/42663 The new Jira UI doesn't show transition IDs in the admin interface. This updates the docs to list a couple of alternative methods of getting the required ID. --- .../img/jira_workflow_screenshot.png | Bin 66685 -> 0 bytes doc/user/project/integrations/jira.md | 11 ++++++++++- 2 files changed, 10 insertions(+), 1 deletion(-) delete mode 100644 doc/user/project/integrations/img/jira_workflow_screenshot.png diff --git a/doc/user/project/integrations/img/jira_workflow_screenshot.png b/doc/user/project/integrations/img/jira_workflow_screenshot.png deleted file mode 100644 index e62fb202613febb8cc0a681944aad7e028f12db6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 66685 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

``Dj4EZ{nCuFLlGD>LEINPs=Px=vYF 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 diff --git a/doc/user/project/integrations/jira.md b/doc/user/project/integrations/jira.md index f77569e4886..0be86915448 100644 --- a/doc/user/project/integrations/jira.md +++ b/doc/user/project/integrations/jira.md @@ -113,7 +113,16 @@ in the table below. | `JIRA API URL` | The base URL to the JIRA instance API. Web URL value will be used if not set. E.g., `https://jira-api.example.com`. | | `Username` | The user name created in [configuring JIRA step](#configuring-jira). | | `Password` |The password of the user created in [configuring JIRA step](#configuring-jira). | -| `Transition ID` | This is the ID of a transition that moves issues to a closed state. You can find this number under JIRA workflow administration ([see screenshot](img/jira_workflow_screenshot.png)). **Closing JIRA issues via commits or Merge Requests won't work if you don't set the ID correctly.** | +| `Transition ID` | This is the ID of a transition that moves issues to the desired state. **Closing JIRA issues via commits or Merge Requests won't work if you don't set the ID correctly.** | + +### Getting a Transition ID + +In the most recent Jira UI, you can no longer see transition IDs in the workflow administration UI. You can get the ID you need in either of the following ways: + +1. Use the API, with a request like https://yourcompany.atlassian.net/rest/api/2/issue/ISSUE-123/transitions using an issue that is in the appropriate "open" state +1. By mousing over the link for the transition you want and looking for the "action" parameter in the URL + +Note that the transition ID may vary between workflows (i.e. bug vs. story), even if the status you are changing to is the same. After saving the configuration, your GitLab project will be able to interact with all JIRA projects in your JIRA instance. From da6157a544a01faf5aa99537c8bb35d3ef2a3a6f Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Fri, 23 Feb 2018 14:47:13 +0100 Subject: [PATCH 006/237] Move some predefined variables to reflect hierarchy --- app/models/ci/build.rb | 11 ----------- app/models/ci/pipeline.rb | 12 +++++++++++- app/models/project.rb | 5 ++++- 3 files changed, 15 insertions(+), 13 deletions(-) diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb index 490edf4ac57..acba0c7d72a 100644 --- a/app/models/ci/build.rb +++ b/app/models/ci/build.rb @@ -282,19 +282,14 @@ module Ci # contain unexpanded variables. def variables(environment: persisted_environment) variables = predefined_variables - variables += project.predefined_variables variables += pipeline.predefined_variables variables += runner.predefined_variables if runner - variables += project.container_registry_variables variables += project.deployment_variables if has_environment? - variables += project.auto_devops_variables variables += yaml_variables variables += user_variables variables += project.group.secret_variables_for(ref, project).map(&:to_runner_variable) if project.group variables += secret_variables(environment: environment) variables += trigger_request.user_variables if trigger_request - variables += pipeline.variables.map(&:to_runner_variable) - variables += pipeline.pipeline_schedule.job_variables if pipeline.pipeline_schedule variables += persisted_environment_variables if environment variables @@ -570,12 +565,6 @@ module Ci def predefined_variables variables = [ - { key: 'CI', value: 'true', public: true }, - { key: 'GITLAB_CI', value: 'true', public: true }, - { key: 'GITLAB_FEATURES', value: project.namespace.features.join(','), public: true }, - { key: 'CI_SERVER_NAME', value: 'GitLab', public: true }, - { key: 'CI_SERVER_VERSION', value: Gitlab::VERSION, public: true }, - { key: 'CI_SERVER_REVISION', value: Gitlab::REVISION, public: true }, { key: 'CI_JOB_ID', value: id.to_s, public: true }, { key: 'CI_JOB_NAME', value: name, public: true }, { key: 'CI_JOB_STAGE', value: stage, public: true }, diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb index 2abe90dd181..d5424dee798 100644 --- a/app/models/ci/pipeline.rb +++ b/app/models/ci/pipeline.rb @@ -473,11 +473,21 @@ module Ci end def predefined_variables - [ + variables = [ + { key: 'CI', value: 'true', public: true }, + { key: 'GITLAB_CI', value: 'true', public: true }, + { key: 'GITLAB_FEATURES', value: project.namespace.features.join(','), public: true }, + { key: 'CI_SERVER_NAME', value: 'GitLab', public: true }, + { key: 'CI_SERVER_VERSION', value: Gitlab::VERSION, public: true }, + { key: 'CI_SERVER_REVISION', value: Gitlab::REVISION, public: true }, { key: 'CI_PIPELINE_ID', value: id.to_s, public: true }, { key: 'CI_CONFIG_PATH', value: ci_yaml_file_path, public: true }, { key: 'CI_PIPELINE_SOURCE', value: source.to_s, public: true } ] + + variables += project.predefined_variables + variables += variables.map(&:to_runner_variable) + variables += pipeline_schedule.job_variables if pipeline_schedule end def queued_duration diff --git a/app/models/project.rb b/app/models/project.rb index 2ba6a863500..995575718f8 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -1554,7 +1554,7 @@ class Project < ActiveRecord::Base end def predefined_variables - [ + variables = [ { key: 'CI_PROJECT_ID', value: id.to_s, public: true }, { key: 'CI_PROJECT_NAME', value: path, public: true }, { key: 'CI_PROJECT_PATH', value: full_path, public: true }, @@ -1563,6 +1563,9 @@ class Project < ActiveRecord::Base { key: 'CI_PROJECT_URL', value: web_url, public: true }, { key: 'CI_PROJECT_VISIBILITY', value: Gitlab::VisibilityLevel.string_level(visibility_level), public: true } ] + + variables += container_registry_variables + variables += auto_devops_variables end def container_registry_variables From 7bb0c79b8e0c3b28d79a9471ed516651abfa1a6c Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Fri, 23 Feb 2018 14:59:34 +0100 Subject: [PATCH 007/237] Fix pipeline variables when pipeline has no schedule --- app/models/ci/pipeline.rb | 10 ++++++---- app/models/project.rb | 2 ++ 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb index d5424dee798..85024408cf2 100644 --- a/app/models/ci/pipeline.rb +++ b/app/models/ci/pipeline.rb @@ -473,7 +473,7 @@ module Ci end def predefined_variables - variables = [ + predefined = [ { key: 'CI', value: 'true', public: true }, { key: 'GITLAB_CI', value: 'true', public: true }, { key: 'GITLAB_FEATURES', value: project.namespace.features.join(','), public: true }, @@ -485,9 +485,11 @@ module Ci { key: 'CI_PIPELINE_SOURCE', value: source.to_s, public: true } ] - variables += project.predefined_variables - variables += variables.map(&:to_runner_variable) - variables += pipeline_schedule.job_variables if pipeline_schedule + predefined += project.predefined_variables + predefined += pipeline_schedule.job_variables if pipeline_schedule + predefined += self.variables.map(&:to_runner_variable) + + predefined end def queued_duration diff --git a/app/models/project.rb b/app/models/project.rb index 995575718f8..f7c41ab5fa4 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -1566,6 +1566,8 @@ class Project < ActiveRecord::Base variables += container_registry_variables variables += auto_devops_variables + + variables end def container_registry_variables From d25c4803f4429d5aeb2ec1eeb920da216d33f024 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Tue, 27 Feb 2018 11:21:40 +0100 Subject: [PATCH 008/237] Fix pipeline build specs related to variables order --- spec/models/ci/build_spec.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/spec/models/ci/build_spec.rb b/spec/models/ci/build_spec.rb index 2b6b6a61182..43fba1349e3 100644 --- a/spec/models/ci/build_spec.rb +++ b/spec/models/ci/build_spec.rb @@ -1854,7 +1854,8 @@ describe Ci::Build do end allow_any_instance_of(Ci::Pipeline) - .to receive(:predefined_variables) { [pipeline_pre_var] } + .to receive(:predefined_variables) + .and_return([project_pre_var] + [pipeline_pre_var]) end it do From 4f472d49b52452b0377fa0701dfe970f3e83bb85 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Tue, 27 Feb 2018 12:24:16 +0100 Subject: [PATCH 009/237] Make pipeline priority variables concept explicit --- app/models/ci/build.rb | 3 ++- app/models/ci/pipeline.rb | 16 +++++++----- app/models/project.rb | 3 ++- spec/models/ci/build_spec.rb | 26 ++++++++++++++++++++ spec/models/ci/pipeline_spec.rb | 43 ++++++++++++++++++++++++++++----- 5 files changed, 77 insertions(+), 14 deletions(-) diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb index 8e2b9dd570b..137ccfbed89 100644 --- a/app/models/ci/build.rb +++ b/app/models/ci/build.rb @@ -262,8 +262,9 @@ module Ci variables += secret_variables(environment: environment) variables += trigger_request.user_variables if trigger_request variables += persisted_environment_variables if environment + variables += pipeline.priority_variables - variables + variables.reverse.uniq { |variable| variable.fetch(:key) }.reverse end def features diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb index 2eb0fa1897f..0435f6b2f9d 100644 --- a/app/models/ci/pipeline.rb +++ b/app/models/ci/pipeline.rb @@ -473,10 +473,9 @@ module Ci end def predefined_variables - predefined = [ + pipeline_predefined = [ { key: 'CI', value: 'true', public: true }, { key: 'GITLAB_CI', value: 'true', public: true }, - { key: 'GITLAB_FEATURES', value: project.namespace.features.join(','), public: true }, { key: 'CI_SERVER_NAME', value: 'GitLab', public: true }, { key: 'CI_SERVER_VERSION', value: Gitlab::VERSION, public: true }, { key: 'CI_SERVER_REVISION', value: Gitlab::REVISION, public: true }, @@ -485,11 +484,16 @@ module Ci { key: 'CI_PIPELINE_SOURCE', value: source.to_s, public: true } ] - predefined += project.predefined_variables - predefined += pipeline_schedule.job_variables if pipeline_schedule - predefined += self.variables.map(&:to_runner_variable) + Array(project.predefined_variables) + pipeline_predefined + end - predefined + def priority_variables + Array(pipeline_schedule&.job_variables) + + self.variables.map(&:to_runner_variable) + end + + def runtime_variables + predefined_variables + priority_variables end def queued_duration diff --git a/app/models/project.rb b/app/models/project.rb index fdaa41a79d6..62a7e10a5cf 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -1589,7 +1589,8 @@ class Project < ActiveRecord::Base { key: 'CI_PROJECT_PATH_SLUG', value: full_path_slug, public: true }, { key: 'CI_PROJECT_NAMESPACE', value: namespace.full_path, public: true }, { key: 'CI_PROJECT_URL', value: web_url, public: true }, - { key: 'CI_PROJECT_VISIBILITY', value: Gitlab::VisibilityLevel.string_level(visibility_level), public: true } + { key: 'CI_PROJECT_VISIBILITY', value: Gitlab::VisibilityLevel.string_level(visibility_level), public: true }, + { key: 'GITLAB_FEATURES', value: namespace.features.join(','), public: true } ] variables += container_registry_variables diff --git a/spec/models/ci/build_spec.rb b/spec/models/ci/build_spec.rb index 5a4080f9c6c..d1db61084c3 100644 --- a/spec/models/ci/build_spec.rb +++ b/spec/models/ci/build_spec.rb @@ -1891,6 +1891,32 @@ describe Ci::Build do end end end + + context 'when there are duplicated variables present ' do + context 'when there are duplicated YAML variables' do + before do + build.yaml_variables = [{ key: 'MYVAR', value: 'first', public: true }, + { key: 'MYVAR', value: 'second', public: true}] + end + + it 'keeps the last occurence of a variable by given key' do + expect(subject).not_to include(key: 'MYVAR', value: 'first', public: true) + expect(subject).to include(key: 'MYVAR', value: 'second', public: true) + end + end + + context 'when pipeline trigger variable overrides YAML variables' do + before do + build.yaml_variables = [{ key: 'MYVAR', value: 'myvar', public: true }] + pipeline.variables.build(key: 'MYVAR', value: 'pipeline value') + end + + it 'overrides YAML variable with a pipeline trigger variable' do + expect(subject).not_to include(key: 'MYVAR', value: 'myvar', public: true) + expect(subject).to include(key: 'MYVAR', value: 'pipeline value', public: false) + end + end + end end describe 'state transition: any => [:pending]' do diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb index 14d234f6aab..4d5fc1dfcd8 100644 --- a/spec/models/ci/pipeline_spec.rb +++ b/spec/models/ci/pipeline_spec.rb @@ -167,15 +167,46 @@ describe Ci::Pipeline, :mailer do end end - describe '#predefined_variables' do - subject { pipeline.predefined_variables } + describe 'pipeline variables' do + describe '#predefined_variables' do + subject { pipeline.predefined_variables } - it { is_expected.to be_an(Array) } + it { is_expected.to be_an(Array) } - it 'includes the defined keys' do - keys = subject.map { |v| v[:key] } + it 'includes the defined keys' do + keys = subject.map { |v| v.fetch(:key) } - expect(keys).to include('CI_PIPELINE_ID', 'CI_CONFIG_PATH', 'CI_PIPELINE_SOURCE') + expect(keys).to include('CI_PIPELINE_ID', 'CI_CONFIG_PATH', 'CI_PIPELINE_SOURCE') + end + + it 'includes project-level predefined variables' do + keys = subject.map { |v| v.fetch(:key) } + + expect(keys).to include('CI_PROJECT_NAME') + end + end + + describe '#priority_variables' do + before do + pipeline.variables.build(key: 'MY_VAR', value: 'my var') + end + + it 'returns trigger variables' do + expect(pipeline.priority_variables) + .to include(key: 'MY_VAR', value: 'my var', public: false) + end + end + + describe '#runtime_variables' do + before do + pipeline.variables.build(key: 'MY_VAR', value: 'my var') + end + + it 'includes predefined and priority variables' do + variables = pipeline.runtime_variables.map { |v| v.fetch(:key) } + + expect(variables).to include('MY_VAR', 'CI_PIPELINE_ID', 'CI_PROJECT_ID') + end end end From c52255884ea1a54d66c0e5e52a67c25ad1a62644 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Wed, 28 Feb 2018 10:50:02 +0100 Subject: [PATCH 010/237] Add support for only/except: variables CI/CD config --- lib/gitlab/ci/config/entry/policy.rb | 20 +++++++++- .../ci/pipeline/expression/statement.rb | 14 ++++++- .../lib/gitlab/ci/config/entry/policy_spec.rb | 25 ++++++++++++ .../ci/pipeline/expression/statement_spec.rb | 40 ++++++++++++++----- spec/models/ci/build_spec.rb | 2 +- 5 files changed, 88 insertions(+), 13 deletions(-) diff --git a/lib/gitlab/ci/config/entry/policy.rb b/lib/gitlab/ci/config/entry/policy.rb index 0027e9ec8c5..b6d137a7e68 100644 --- a/lib/gitlab/ci/config/entry/policy.rb +++ b/lib/gitlab/ci/config/entry/policy.rb @@ -25,15 +25,31 @@ module Gitlab include Entry::Validatable include Entry::Attributable - attributes :refs, :kubernetes + attributes :refs, :kubernetes, :variables validations do validates :config, presence: true - validates :config, allowed_keys: %i[refs kubernetes] + validates :config, allowed_keys: %i[refs kubernetes variables] + validate :variables_expressions_syntax with_options allow_nil: true do validates :refs, array_of_strings_or_regexps: true validates :kubernetes, allowed_values: %w[active] + validates :variables, array_of_strings: true + end + + def variables_expressions_syntax + return unless variables.is_a?(Array) + + statements = variables.map do |statement| + ::Gitlab::Ci::Pipeline::Expression::Statement.new(statement) + end + + statements.each do |statement| + unless statement.valid? + errors.add(:variables, "Invalid expression #{statement.inspect}") + end + end end end end diff --git a/lib/gitlab/ci/pipeline/expression/statement.rb b/lib/gitlab/ci/pipeline/expression/statement.rb index 08e662eccf9..616a9fe204c 100644 --- a/lib/gitlab/ci/pipeline/expression/statement.rb +++ b/lib/gitlab/ci/pipeline/expression/statement.rb @@ -14,9 +14,11 @@ module Gitlab %w[variable] ].freeze - def initialize(statement, pipeline) + def initialize(statement, pipeline = nil) @lexer = Expression::Lexer.new(statement) + return if pipeline.nil? + @variables = pipeline.variables.map do |variable| [variable.key.to_sym, variable.value] end @@ -35,6 +37,16 @@ module Gitlab def evaluate parse_tree.evaluate(@variables.to_h) end + + def inspect + "syntax: #{@lexer.lexemes.join(' ')}" + end + + def valid? + parse_tree.is_a?(Lexeme::Base) + rescue StatementError + false + end end end end diff --git a/spec/lib/gitlab/ci/config/entry/policy_spec.rb b/spec/lib/gitlab/ci/config/entry/policy_spec.rb index 5e83abf645b..f06d3a13ce0 100644 --- a/spec/lib/gitlab/ci/config/entry/policy_spec.rb +++ b/spec/lib/gitlab/ci/config/entry/policy_spec.rb @@ -83,6 +83,31 @@ describe Gitlab::Ci::Config::Entry::Policy do end end + context 'when specifying valid variables expressions policy' do + let(:config) { { variables: ['$VAR == null'] } } + + it 'is a correct configuraton' do + expect(entry).to be_valid + expect(entry.value).to eq(config) + end + end + + context 'when specifying variables expressions in invalid format' do + let(:config) { { variables: '$MY_VAR' } } + + it 'reports an error about invalid format' do + expect(entry.errors).to include /should be an array of strings/ + end + end + + context 'when specifying invalid variables expressions statement' do + let(:config) { { variables: ['$MY_VAR =='] } } + + it 'reports an error about invalid statement' do + expect(entry.errors).to include /invalid expression syntax: variable equals/ + end + end + context 'when specifying unknown policy' do let(:config) { { refs: ['master'], invalid: :something } } diff --git a/spec/lib/gitlab/ci/pipeline/expression/statement_spec.rb b/spec/lib/gitlab/ci/pipeline/expression/statement_spec.rb index 472a58599d8..3d97d71d629 100644 --- a/spec/lib/gitlab/ci/pipeline/expression/statement_spec.rb +++ b/spec/lib/gitlab/ci/pipeline/expression/statement_spec.rb @@ -11,6 +11,16 @@ describe Gitlab::Ci::Pipeline::Expression::Statement do pipeline.variables.build([key: 'VARIABLE', value: 'my variable']) end + describe '.new' do + context 'when pipeline is not provided' do + it 'allows to properly initialize the statement' do + statement = described_class.new('$VARIABLE') + + expect(statement.evaluate).to be_nil + end + end + end + describe '#parse_tree' do context 'when expression is empty' do let(:text) { '' } @@ -23,18 +33,26 @@ describe Gitlab::Ci::Pipeline::Expression::Statement do context 'when expression grammar is incorrect' do table = [ - '$VAR "text"', # missing operator - '== "123"', # invalid right side - "'single quotes'", # single quotes string - '$VAR ==', # invalid right side - '12345', # unknown syntax - '' # empty statement + '$VAR "text"', # missing operator + '== "123"', # invalid left side + '"some string"', # only string provided + '$VAR ==', # invalid right side + '12345', # unknown syntax + '' # empty statement ] table.each do |syntax| - it "raises an error when syntax is `#{syntax}`" do - expect { described_class.new(syntax, pipeline).parse_tree } - .to raise_error described_class::StatementError + context "when expression grammar is #{syntax.inspect}" do + let(:text) { syntax } + + it 'aises a statement error exception' do + expect { subject.parse_tree } + .to raise_error described_class::StatementError + end + + it 'is an invalid statement' do + expect(subject).not_to be_valid + end end end end @@ -47,6 +65,10 @@ describe Gitlab::Ci::Pipeline::Expression::Statement do expect(subject.parse_tree) .to be_a Gitlab::Ci::Pipeline::Expression::Lexeme::Equals end + + it 'is a valid statement' do + expect(subject).to be_valid + end end context 'when using a single token' do diff --git a/spec/models/ci/build_spec.rb b/spec/models/ci/build_spec.rb index d1db61084c3..2328c3ee902 100644 --- a/spec/models/ci/build_spec.rb +++ b/spec/models/ci/build_spec.rb @@ -1896,7 +1896,7 @@ describe Ci::Build do context 'when there are duplicated YAML variables' do before do build.yaml_variables = [{ key: 'MYVAR', value: 'first', public: true }, - { key: 'MYVAR', value: 'second', public: true}] + { key: 'MYVAR', value: 'second', public: true }] end it 'keeps the last occurence of a variable by given key' do From 8a7c89adfb6f6013a8db7550958637d4815ed0d5 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Wed, 28 Feb 2018 11:37:23 +0100 Subject: [PATCH 011/237] Use pipeline runtime variables in expressions --- lib/gitlab/ci/pipeline/expression/statement.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/gitlab/ci/pipeline/expression/statement.rb b/lib/gitlab/ci/pipeline/expression/statement.rb index 0b522d90e40..cd0d3089d0c 100644 --- a/lib/gitlab/ci/pipeline/expression/statement.rb +++ b/lib/gitlab/ci/pipeline/expression/statement.rb @@ -19,8 +19,8 @@ module Gitlab return if pipeline.nil? - @variables = pipeline.variables.map do |variable| - [variable.key, variable.value] + @variables = pipeline.runtime_variables.map do |variable| + [variable.fetch(:key), variable.fetch(:value)] end end From 64e86dab627681c52ffa78e99415b3b9d00b2f43 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Wed, 28 Feb 2018 12:06:50 +0100 Subject: [PATCH 012/237] Allow using an empty string with pipeline expressions --- .../ci/pipeline/expression/lexeme/string.rb | 2 +- .../ci/pipeline/expression/lexeme/string_spec.rb | 16 ++++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/lib/gitlab/ci/pipeline/expression/lexeme/string.rb b/lib/gitlab/ci/pipeline/expression/lexeme/string.rb index 48bde213d44..346c92dc51e 100644 --- a/lib/gitlab/ci/pipeline/expression/lexeme/string.rb +++ b/lib/gitlab/ci/pipeline/expression/lexeme/string.rb @@ -4,7 +4,7 @@ module Gitlab module Expression module Lexeme class String < Lexeme::Value - PATTERN = /("(?.+?)")|('(?.+?)')/.freeze + PATTERN = /("(?.*?)")|('(?.*?)')/.freeze def initialize(value) @value = value diff --git a/spec/lib/gitlab/ci/pipeline/expression/lexeme/string_spec.rb b/spec/lib/gitlab/ci/pipeline/expression/lexeme/string_spec.rb index 86234dfb9e5..1ccb792d1da 100644 --- a/spec/lib/gitlab/ci/pipeline/expression/lexeme/string_spec.rb +++ b/spec/lib/gitlab/ci/pipeline/expression/lexeme/string_spec.rb @@ -73,6 +73,22 @@ describe Gitlab::Ci::Pipeline::Expression::Lexeme::String do expect(token).not_to be_nil expect(token.build.evaluate).to eq 'some " string' end + + it 'allows to use an empty string inside single quotes' do + scanner = StringScanner.new(%('')) + + token = described_class.scan(scanner) + + expect(token.build.evaluate).to eq '' + end + + it 'allow to use an empty string inside double quotes' do + scanner = StringScanner.new(%("")) + + token = described_class.scan(scanner) + + expect(token.build.evaluate).to eq '' + end end end From 1926eca04d36793b9d9646d5a0e720e4b835fd3c Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Wed, 28 Feb 2018 12:10:32 +0100 Subject: [PATCH 013/237] Add method that checks if pipeline expression is truthy --- .../ci/pipeline/expression/statement.rb | 4 ++ .../ci/pipeline/expression/statement_spec.rb | 49 ++++++++++++++----- 2 files changed, 42 insertions(+), 11 deletions(-) diff --git a/lib/gitlab/ci/pipeline/expression/statement.rb b/lib/gitlab/ci/pipeline/expression/statement.rb index cd0d3089d0c..017c7f11657 100644 --- a/lib/gitlab/ci/pipeline/expression/statement.rb +++ b/lib/gitlab/ci/pipeline/expression/statement.rb @@ -38,6 +38,10 @@ module Gitlab parse_tree.evaluate(@variables.to_h) end + def truthful? + evaluate.present? + end + def inspect "syntax: #{@lexer.lexemes.join(' ')}" end diff --git a/spec/lib/gitlab/ci/pipeline/expression/statement_spec.rb b/spec/lib/gitlab/ci/pipeline/expression/statement_spec.rb index 3d97d71d629..475ac7afcb3 100644 --- a/spec/lib/gitlab/ci/pipeline/expression/statement_spec.rb +++ b/spec/lib/gitlab/ci/pipeline/expression/statement_spec.rb @@ -8,13 +8,16 @@ describe Gitlab::Ci::Pipeline::Expression::Statement do end before do - pipeline.variables.build([key: 'VARIABLE', value: 'my variable']) + variables = [{ key: 'PRESENT_VARIABLE', value: 'my variable' }, + { key: 'EMPTY_VARIABLE', value: '' }] + + pipeline.variables.build(variables) end describe '.new' do context 'when pipeline is not provided' do it 'allows to properly initialize the statement' do - statement = described_class.new('$VARIABLE') + statement = described_class.new('$PRESENT_VARIABLE') expect(statement.evaluate).to be_nil end @@ -72,7 +75,7 @@ describe Gitlab::Ci::Pipeline::Expression::Statement do end context 'when using a single token' do - let(:text) { '$VARIABLE' } + let(:text) { '$PRESENT_VARIABLE' } it 'returns a single token instance' do expect(subject.parse_tree) @@ -84,14 +87,17 @@ describe Gitlab::Ci::Pipeline::Expression::Statement do describe '#evaluate' do statements = [ - ['$VARIABLE == "my variable"', true], - ["$VARIABLE == 'my variable'", true], - ['"my variable" == $VARIABLE', true], - ['$VARIABLE == null', false], - ['$VAR == null', true], - ['null == $VAR', true], - ['$VARIABLE', 'my variable'], - ['$VAR', nil] + ['$PRESENT_VARIABLE == "my variable"', true], + ["$PRESENT_VARIABLE == 'my variable'", true], + ['"my variable" == $PRESENT_VARIABLE', true], + ['$PRESENT_VARIABLE == null', false], + ['$EMPTY_VARIABLE == null', false], + ['"" == $EMPTY_VARIABLE', true], + ['$EMPTY_VARIABLE', ''], + ['$UNDEFINED_VARIABLE == null', true], + ['null == $UNDEFINED_VARIABLE', true], + ['$PRESENT_VARIABLE', 'my variable'], + ['$UNDEFINED_VARIABLE', nil] ] statements.each do |expression, value| @@ -104,4 +110,25 @@ describe Gitlab::Ci::Pipeline::Expression::Statement do end end end + + describe '#truthful?' do + statements = [ + ['$PRESENT_VARIABLE == "my variable"', true], + ["$PRESENT_VARIABLE == 'no match'", false], + ['$UNDEFINED_VARIABLE == null', true], + ['$PRESENT_VARIABLE', true], + ['$UNDEFINED_VARIABLE', false], + ['$EMPTY_VARIABLE', false] + ] + + statements.each do |expression, value| + context "when using expression `#{expression}`" do + let(:text) { expression } + + it "returns `#{value.inspect}`" do + expect(subject.truthful?).to eq value + end + end + end + end end From 52b34969a50312104d2d439c452a5bbb79085945 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Wed, 28 Feb 2018 13:08:42 +0100 Subject: [PATCH 014/237] Add build policy for pipeline expressions --- lib/gitlab/ci/build/policy/variables.rb | 22 ++++++++++ .../gitlab/ci/build/policy/variables_spec.rb | 41 +++++++++++++++++++ 2 files changed, 63 insertions(+) create mode 100644 lib/gitlab/ci/build/policy/variables.rb create mode 100644 spec/lib/gitlab/ci/build/policy/variables_spec.rb diff --git a/lib/gitlab/ci/build/policy/variables.rb b/lib/gitlab/ci/build/policy/variables.rb new file mode 100644 index 00000000000..eeb0f3f2cb7 --- /dev/null +++ b/lib/gitlab/ci/build/policy/variables.rb @@ -0,0 +1,22 @@ +module Gitlab + module Ci + module Build + module Policy + class Variables < Policy::Specification + def initialize(expressions) + @expressions = Array(expressions) + end + + def satisfied_by?(pipeline) + statements = @expressions.map do |statement| + ::Gitlab::Ci::Pipeline::Expression::Statement + .new(statement, pipeline) + end + + statements.any? { |statement| statement.truthful? } + end + end + end + end + end +end diff --git a/spec/lib/gitlab/ci/build/policy/variables_spec.rb b/spec/lib/gitlab/ci/build/policy/variables_spec.rb new file mode 100644 index 00000000000..6596237ff9c --- /dev/null +++ b/spec/lib/gitlab/ci/build/policy/variables_spec.rb @@ -0,0 +1,41 @@ +require 'spec_helper' + +describe Gitlab::Ci::Build::Policy::Variables do + let(:pipeline) { build(:ci_pipeline, ref: 'master') } + + before do + pipeline.variables.build(key: 'CI_PROJECT_NAME', value: '') + end + + describe '#satisfied_by?' do + it 'is satisfied by a defined and existing variable' do + policy = described_class.new(['$CI_PROJECT_ID', '$UNDEFINED']) + + expect(policy).to be_satisfied_by(pipeline) + end + + it 'is not satisfied by an overriden empty variable' do + policy = described_class.new(['$CI_PROJECT_NAME']) + + expect(policy).not_to be_satisfied_by(pipeline) + end + + it 'is satisfied by a truthy pipeline expression' do + policy = described_class.new([%($CI_PIPELINE_SOURCE == "#{pipeline.source}")]) + + expect(policy).to be_satisfied_by(pipeline) + end + + it 'is not satisfied by a falsy pipeline expression' do + policy = described_class.new([%($CI_PIPELINE_SOURCE == "invalid source")]) + + expect(policy).not_to be_satisfied_by(pipeline) + end + + it 'is satisfied by a truthy expression using undefined variable' do + policy = described_class.new(['$UNDEFINED', '$UNDEFINED == null']) + + expect(policy).to be_satisfied_by(pipeline) + end + end +end From 51727377a243238984425d7e3c8ca48658613733 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Wed, 28 Feb 2018 13:13:14 +0100 Subject: [PATCH 015/237] Use squiggly heredoc to improve YAML processor specs --- spec/lib/gitlab/ci/yaml_processor_spec.rb | 46 +++++++++++------------ 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/spec/lib/gitlab/ci/yaml_processor_spec.rb b/spec/lib/gitlab/ci/yaml_processor_spec.rb index f83f932e61e..b9fccf47e79 100644 --- a/spec/lib/gitlab/ci/yaml_processor_spec.rb +++ b/spec/lib/gitlab/ci/yaml_processor_spec.rb @@ -1344,13 +1344,13 @@ module Gitlab context 'when template is a job' do let(:config) do - <

+ role="group" + >
{ }); it('should render user avatar', () => { - expect(vm.$el.querySelector('.user-avatar-link')).toBeDefined(); + expect(vm.$el.querySelector('.user-avatar-link')).not.toBeNull(); }); it('should render discussion header', () => { - expect(vm.$el.querySelector('.discussion-header')).toBeDefined(); + expect(vm.$el.querySelector('.discussion-header')).not.toBeNull(); expect(vm.$el.querySelector('.notes').children.length).toEqual(discussionMock.notes.length); }); describe('actions', () => { it('should render reply button', () => { - expect(vm.$el.querySelector('.js-vue-discussion-reply').textContent.trim()).toEqual('Reply...'); + expect(vm.$el.querySelector('.js-vue-discussion-reply').textContent.trim()).toEqual( + 'Reply...', + ); }); - it('should toggle reply form', (done) => { + it('should toggle reply form', done => { vm.$el.querySelector('.js-vue-discussion-reply').click(); Vue.nextTick(() => { - expect(vm.$refs.noteForm).toBeDefined(); + expect(vm.$refs.noteForm).not.toBeNull(); expect(vm.isReplying).toEqual(true); done(); }); }); + + it('does not render jump to discussion button', () => { + expect( + vm.$el.querySelector('*[data-original-title="Jump to next unresolved discussion"]'), + ).toBeNull(); + }); }); }); From f62359c23b86bb8c8dc241ff4e09bab24e74ccbd Mon Sep 17 00:00:00 2001 From: Tim Zallmann Date: Fri, 23 Mar 2018 11:45:43 +0100 Subject: [PATCH 070/237] Basic Setup for MR Showing --- app/assets/javascripts/api.js | 150 ++++++++------ .../ide/components/editor_mode_dropdown.vue | 71 ++++--- app/assets/javascripts/ide/components/ide.vue | 85 ++++---- .../ide/components/repo_editor.vue | 23 ++- .../javascripts/ide/components/repo_tabs.vue | 72 +++---- app/assets/javascripts/ide/ide_router.js | 81 +++++++- .../javascripts/ide/lib/common/model.js | 14 ++ .../javascripts/ide/lib/diff/revert_patch.js | 183 ++++++++++++++++++ app/assets/javascripts/ide/lib/editor.js | 7 + app/assets/javascripts/ide/services/index.js | 9 +- app/assets/javascripts/ide/stores/actions.js | 1 + .../javascripts/ide/stores/actions/file.js | 177 ++++++++++++----- .../ide/stores/actions/merge_request.js | 96 +++++++++ .../javascripts/ide/stores/actions/tree.js | 112 ++++++----- app/assets/javascripts/ide/stores/getters.js | 2 + .../javascripts/ide/stores/mutation_types.js | 9 + .../javascripts/ide/stores/mutations.js | 2 + .../javascripts/ide/stores/mutations/file.js | 15 ++ .../ide/stores/mutations/merge_request.js | 40 ++++ .../ide/stores/mutations/project.js | 1 + app/assets/javascripts/ide/stores/state.js | 1 + app/assets/javascripts/ide/stores/utils.js | 54 ++++-- .../components/mr_widget_header.vue | 103 ++++++---- 23 files changed, 1000 insertions(+), 308 deletions(-) create mode 100644 app/assets/javascripts/ide/lib/diff/revert_patch.js create mode 100644 app/assets/javascripts/ide/stores/actions/merge_request.js create mode 100644 app/assets/javascripts/ide/stores/mutations/merge_request.js diff --git a/app/assets/javascripts/api.js b/app/assets/javascripts/api.js index cbcefb2c18f..bed20b36868 100644 --- a/app/assets/javascripts/api.js +++ b/app/assets/javascripts/api.js @@ -10,6 +10,9 @@ const Api = { projectsPath: '/api/:version/projects.json', projectPath: '/api/:version/projects/:id', projectLabelsPath: '/:namespace_path/:project_path/labels', + mergeRequestPath: '/api/:version/projects/:id/merge_requests/:mrid', + mergeRequestChangesPath: + '/api/:version/projects/:id/merge_requests/:mrid/changes', groupLabelsPath: '/groups/:namespace_path/-/labels', licensePath: '/api/:version/templates/licenses/:key', gitignorePath: '/api/:version/templates/gitignores/:key', @@ -22,25 +25,27 @@ const Api = { createBranchPath: '/api/:version/projects/:id/repository/branches', group(groupId, callback) { - const url = Api.buildUrl(Api.groupPath) - .replace(':id', groupId); - return axios.get(url) - .then(({ data }) => { - callback(data); + const url = Api.buildUrl(Api.groupPath).replace(':id', groupId); + return axios.get(url).then(({ data }) => { + callback(data); - return data; - }); + return data; + }); }, // Return groups list. Filtered by query groups(query, options, callback = $.noop) { const url = Api.buildUrl(Api.groupsPath); - return axios.get(url, { - params: Object.assign({ - search: query, - per_page: 20, - }, options), - }) + return axios + .get(url, { + params: Object.assign( + { + search: query, + per_page: 20, + }, + options, + ), + }) .then(({ data }) => { callback(data); @@ -51,12 +56,13 @@ const Api = { // Return namespaces list. Filtered by query namespaces(query, callback) { const url = Api.buildUrl(Api.namespacesPath); - return axios.get(url, { - params: { - search: query, - per_page: 20, - }, - }) + return axios + .get(url, { + params: { + search: query, + per_page: 20, + }, + }) .then(({ data }) => callback(data)); }, @@ -73,9 +79,10 @@ const Api = { defaults.membership = true; } - return axios.get(url, { - params: Object.assign(defaults, options), - }) + return axios + .get(url, { + params: Object.assign(defaults, options), + }) .then(({ data }) => { callback(data); @@ -85,8 +92,28 @@ const Api = { // Return single project project(projectPath) { - const url = Api.buildUrl(Api.projectPath) - .replace(':id', encodeURIComponent(projectPath)); + const url = Api.buildUrl(Api.projectPath).replace( + ':id', + encodeURIComponent(projectPath), + ); + + return axios.get(url); + }, + + // Return Merge Request for project + mergeRequest(projectPath, mergeRequestId) { + const url = Api.buildUrl(Api.mergeRequestPath) + .replace(':id', encodeURIComponent(projectPath)) + .replace(':mrid', mergeRequestId); + + return axios.get(url); + }, + + // Return Merge Request Changes + mergeRequestChanges(projectPath, mergeRequestId) { + const url = Api.buildUrl(Api.mergeRequestChangesPath) + .replace(':id', encodeURIComponent(projectPath)) + .replace(':mrid', mergeRequestId); return axios.get(url); }, @@ -99,33 +126,39 @@ const Api = { .replace(':namespace_path', namespacePath) .replace(':project_path', projectPath); } else { - url = Api.buildUrl(Api.groupLabelsPath).replace(':namespace_path', namespacePath); + url = Api.buildUrl(Api.groupLabelsPath).replace( + ':namespace_path', + namespacePath, + ); } - return axios.post(url, { - label: data, - }) + return axios + .post(url, { + label: data, + }) .then(res => callback(res.data)) .catch(e => callback(e.response.data)); }, // Return group projects list. Filtered by query groupProjects(groupId, query, callback) { - const url = Api.buildUrl(Api.groupProjectsPath) - .replace(':id', groupId); - return axios.get(url, { - params: { - search: query, - per_page: 20, - }, - }) + const url = Api.buildUrl(Api.groupProjectsPath).replace(':id', groupId); + return axios + .get(url, { + params: { + search: query, + per_page: 20, + }, + }) .then(({ data }) => callback(data)); }, commitMultiple(id, data) { // see https://docs.gitlab.com/ce/api/commits.html#create-a-commit-with-multiple-files-and-actions - const url = Api.buildUrl(Api.commitPath) - .replace(':id', encodeURIComponent(id)); + const url = Api.buildUrl(Api.commitPath).replace( + ':id', + encodeURIComponent(id), + ); return axios.post(url, JSON.stringify(data), { headers: { 'Content-Type': 'application/json; charset=utf-8', @@ -136,39 +169,34 @@ const Api = { branchSingle(id, branch) { const url = Api.buildUrl(Api.branchSinglePath) .replace(':id', encodeURIComponent(id)) - .replace(':branch', branch); + .replace(':branch', encodeURIComponent(branch)); return axios.get(url); }, // Return text for a specific license licenseText(key, data, callback) { - const url = Api.buildUrl(Api.licensePath) - .replace(':key', key); - return axios.get(url, { - params: data, - }) + const url = Api.buildUrl(Api.licensePath).replace(':key', key); + return axios + .get(url, { + params: data, + }) .then(res => callback(res.data)); }, gitignoreText(key, callback) { - const url = Api.buildUrl(Api.gitignorePath) - .replace(':key', key); - return axios.get(url) - .then(({ data }) => callback(data)); + const url = Api.buildUrl(Api.gitignorePath).replace(':key', key); + return axios.get(url).then(({ data }) => callback(data)); }, gitlabCiYml(key, callback) { - const url = Api.buildUrl(Api.gitlabCiYmlPath) - .replace(':key', key); - return axios.get(url) - .then(({ data }) => callback(data)); + const url = Api.buildUrl(Api.gitlabCiYmlPath).replace(':key', key); + return axios.get(url).then(({ data }) => callback(data)); }, dockerfileYml(key, callback) { const url = Api.buildUrl(Api.dockerfilePath).replace(':key', key); - return axios.get(url) - .then(({ data }) => callback(data)); + return axios.get(url).then(({ data }) => callback(data)); }, issueTemplate(namespacePath, projectPath, key, type, callback) { @@ -177,7 +205,8 @@ const Api = { .replace(':type', type) .replace(':project_path', projectPath) .replace(':namespace_path', namespacePath); - return axios.get(url) + return axios + .get(url) .then(({ data }) => callback(null, data)) .catch(callback); }, @@ -185,10 +214,13 @@ const Api = { users(query, options) { const url = Api.buildUrl(this.usersPath); return axios.get(url, { - params: Object.assign({ - search: query, - per_page: 20, - }, options), + params: Object.assign( + { + search: query, + per_page: 20, + }, + options, + ), }); }, diff --git a/app/assets/javascripts/ide/components/editor_mode_dropdown.vue b/app/assets/javascripts/ide/components/editor_mode_dropdown.vue index 170347881e0..42b00b5d9df 100644 --- a/app/assets/javascripts/ide/components/editor_mode_dropdown.vue +++ b/app/assets/javascripts/ide/components/editor_mode_dropdown.vue @@ -1,31 +1,36 @@