From 72e0a9401a92f32473730176ec0f8d90755d352f Mon Sep 17 00:00:00 2001
From: Harsh-Microsoft
Date: Mon, 1 Dec 2025 17:00:55 +0530
Subject: [PATCH 01/13] Update deployment guide and quota check documentation
for VS Code Web usage
---
docs/DeploymentGuide.md | 13 +++++++++++--
docs/images/vscodeweb_intialize.png | Bin 35612 -> 0 bytes
docs/quota_check.md | 10 +++++++---
3 files changed, 18 insertions(+), 5 deletions(-)
delete mode 100644 docs/images/vscodeweb_intialize.png
diff --git a/docs/DeploymentGuide.md b/docs/DeploymentGuide.md
index 8abf4f58..d67bf4da 100644
--- a/docs/DeploymentGuide.md
+++ b/docs/DeploymentGuide.md
@@ -100,9 +100,18 @@ You can run this solution in VS Code Dev Containers, which will open the project
2. Sign in with your Azure account when prompted
3. Select the subscription where you want to deploy the solution
4. Wait for the environment to initialize (includes all deployment tools)
-5. When prompted in the VS Code Web terminal, choose one of the available options shown below:
+5. Once the solution opens, the **AI Foundry terminal** will automatically start running the following command to install the required dependencies:
- 
+ ```shell
+ sh install.sh
+ ```
+ During this process, youβll be prompted with the message:
+ ```
+ What would you like to do with these files?
+ - Overwrite with versions from template
+ - Keep my existing files unchanged
+ ```
+ Choose β**Overwrite with versions from template**β and provide a unique environment name when prompted.
6. Continue with the [deploying steps](#deploying-with-azd)
diff --git a/docs/images/vscodeweb_intialize.png b/docs/images/vscodeweb_intialize.png
deleted file mode 100644
index 1ef8ce8174399d32bdaf028eb9a2c84a06b30f3b..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 35612
zcmeFZg;QKX^EOJ*7$iWDph1EJcXtn#KoZ<71ZRN-7AHXPAi-gANeHfsEKbnHb#YmA
z2`sL6$@~85`~HCYRoz?no+=9V>^U>jJw4q|Khs0_I}IiL#}tn-Ffi~{l;yQBFtC|1
zFdk$)#6{oP!RW6=|9Sw>Qj*0e8>ZSuf55hpQJ2BMsEmDbZH9yX{K#2Z4}gI|`uhIo
zfr=L6Ukr?hN)>sT51z*RH@OXw3|hD%!dZQ<*u!5}eX(UIam%gecx_Bs0|jP*~iv#myO4T*{bjK{-$
z=n+{9)AOFTR)`~9E7k~F8Q8ix{rP*AtO^VH>VE|51;x-k43)-
zk(R%|x;R)_!}IeQcg-7RySlsM5)?S{q?En&)@$VB&u6qUoRF2A|XF?#e0n&QNIFi
z!Iq)IzjxLn&^_ew_T^Hn^cZ{y#iuMpzv=xy5`smjVjlPlY`k-fY6>P&QBgr_C^$Zd
z_+PtYT=DVoxct(D(TfzLFUZJ>vcDQu{*R=735kjPruc{)qKt2mkql^6q6hJS%^)tY
zaQW*$L5_cQb;+Ygn<}z{)0!i4PACv$DJ1y{w{N{h#LL)qH%!`}+E(y3HuJRD|$k
z(H}L6_`Z}|l7!>@k9_jo-Q7I)GZm81%W5esVk0A?DFv)yAr?Z~^1{@o4x(89hGHrG
zRV*y1=}bWwj9-|S*9rODhMvd&X!+Z-%t!yU!D|Y40zb4m4+5Dh7md#%jLAM_W@b()
z5GH^B-d17Oi5B3dRf;~?2wwa?FLw#tR~QxbbeI00(GU{8%*S}r|v#@eTJVneNpW}&A7
z*V=e*@ziPU^N#nq#G#tT&4D7@%(I^$v=A
zUfma8T6%
z`iw2SA9T{u$ZahR*qD$0fP~Io%CJiLZWg;UylY53^71^|vb%)&5B!|hDn6XeD(^Pv
zZxma5QSc=4QN;#1aWV4ruLMvvKe&bjiZRP3oW{_*N{DwkeGui7qmzEtC
z``;rBd<>M+N;P}pviykR*QI0-3?C1M{|zSja)2F7DHNu3+uPerx_+QwQbGBDWJw^kHf9!|q)>j6#R!1Cj95
zzjfk+p{n(-Ivrvw-t1O1vOBjtse_+c!@a2kG2EHk1h7nxR+UV{Y6cAwvB
z*1KyMl(*Nls>-pSNl*KsmpB!FX&%_;@H9Qc{;kc?VBge7NsXhq`64<*`QLoVK4JBP
zxtoET$a+=1t5aL1L8I;rm)qUziG9Qkg)-D5%3XblKXcP<9NSME*z6u{2B-4N7?;=9
zKC@yrsf53n*pFRl>+;+z<#lp|EWFBGudSUI?z2o{M{duYLPvHcp1-RHkJVm@WGXHqo1Jd2rWmw^_x#YcZ~(G1d09
zG1jx3OGYir7F(y(OL&_&Wh>b(0o(03HCe=+Cxp^pe8I^}-2tDqexcJGT3{S`kSgEb
z{Yn2f8)k__cS$6x+8g$syYl1Zm~FUlbEw?>o!ahS%2dBFf%YG5HxkztnhVrYz#p@w
zNSbqrMhlL4$$&mpkXSjU5A@9R8cs_oqd4Hc9$AkkV~UyLGmf1m2}(G#Gwo2%*{gI>
zPffroT0+9I16y3l(DqrlEDya1D)*t>rh5s?C?U??yjd1vprzWh)D~^LV^9uw6+gD}
z3znt~-5(Axxm3hL_%0sQEo~nIGZ=Fnn-coA)icCj?0IZIIfar%r-Pk$CVspTbd+9*
z_O`Q-;P1IuJZ?{KhXF6&(Tur=tdf7WY1hg=e%KBDZ
zT6iVK+}gU{b!S1!U>ZB=fl@s<*ZrK4=1ENpM&aGLqShBF>)xhrs-OEb;*I7RH;)er
z+0sc?^@khc@c@OU|l)
zL%SSe$u)g3#ryVul?N>*-nWan-h#CFnNI#e^Fy?S)=+Odg&79zwas_eZ~165`tEYd
zmUij(w1*E-l#o-uEd5Sq$EUbwLDmuCBDa*#I@ycV48an)*tXrOWPU4Ul+O6=ks%+|
z&fUBy_bQ8%@5tN!=<%i#kCfXrN|nZQo0wbLfrzYTgTVpXn$sD|PCK46c#`Z8bB}Z^
zHTW1FY4MH{z_IN!q~qS!VAmMBI6RPWZSzn9`x?3gI_>uVFy4i|S(?VTHB6f~9p)AN
z^D1R0%Ud_C2X@0l{B6)TBJ+O?LMpY{^HIXMCaSgeS6#Uapy960O#^DF9O3;)A0a
zT#V;i7E9aQbDQSIbjLq(VSl+SFxBcy;kt=N3Ams1C`o-6rfJktc0tYP5qu7?{QD(tn~-1L8EIQ^wd+fp2vPk8v`_Uk8klo+C88zov(s!3KUy4
zng;r;7efn2b`sA&i}ndFiNYNQ&uveyN|#RcI8`Ay+?UqZ@Q;2%Z3`5a@10%4c$9i?
zBsMmJr=xf;viqKXICW~o23$HUt&w;lW7-P~O9O&1!CrMCHX#c=K+;i7yTlp_L^qla@l5wLn804Dq+~E3n(7l3!K#<5sOmP
z@2`2Vr33dXR->jVu6N`p{4ETLHpmjgIj?tVfzSyZw>_bL?I2doK~K4LQDD8idRF_L&j}FQ`P!q|9W80WJlKjiXNUKd{F|TY659VQ7-Te`5p)cnna!F-r7C9oalYwDy>Lwb$$2e
zbxVCCx$JYlHK{~YEgtPPbJ4ahX5a14*sS`NWB%sO-ahIcXLbhvoISg5(@cle7J9Y^
zo$QMe{a~&_?(MAZcb?A@LZ_WsW_A_iYAj|CO6dMBW!}4&oY1AK(_0pn?Cj;U31=M5
zsPMC>
zC3gM((mdm!c)ODb7z3+TOG9f%?291
zY7O;qAc}k!sz+6DzCiJ(HDpK#F>={%Alb>$Q5(ErCGg!>DBbDQ$nkjaFYVZh_0#=_
z{4$6id1olsqg4@^P2Ho>{i~bDZu2HQbbr=!kdGu=5{^R!GtdTIAeRGIkPm&1!;CxA
zCzs^-jkejkRjvi3GkgfpsazKnzIf||B2e3mE9kM4U^sHa6p#LKobf1s`r792byRxi
zPsdInSqC+R0kS==1=x0m$O9&v%s~dqP3|0P=pDJ$*}LR|q(@Rtps%lQCcYtu#c}I7
zDkpvf3g3?M`61s3vS&V}wckahtf0H&VeY*X$n5#`cT;yWf*h9d@c{*+B*N~j@pY7t
z;c=HI@0URibBU$KeL_IG*+j4D&M9gWPrb)$x7zb)6^T-Hdm?x|P^*HuWc3Lm&
z&J&ig_v!Z9Z^>KT)854KDO=z0A!n0?s1QLfDv971HF%;8jWs0ygn1lyfs8$*xX=*Z
zv>Bi6tC`0_>k^3D5Bbv(@#Apwca|{&l~ICI+Vg95S)`DAYT)AcFu-vqu;f2sgjDFu
zL^0=Xhi-CQoQ#D+1Zqo=wFCr3wRbdukHK>GXYCF5L5aB>c#nhx$jSLnZD&d<*s
zZRO454jN?x0PP$zN2ZvQchUo^YtboohK7c1C;y=fK`$~MX1BCtswQ)eE-oT3!f_rw
zdc?@YL_|xgsij4P=1H@b6msc4!AR=S^e6-ZQC3syT5=?7y|e=)oeqlK1;}
z^g-)Y47wRToo;?$=Kyu7va<5lVTqfMPctUP7<2H6p$kAX6V1j(t*=||zWK+6g=69{
z2Mi>00aiLfQb0SDDrllJ%QSR+yKCF+=ac5+{tZ``l@1(HQPI+0xCQ6uo?2R3$|@?A
zW%mn;Fzx~WdN47X*rg`pG_2sHaa~*XlO{s-eRDvtc+7%U;p#x&)Ee9-4OlI3iJ(5<7Q6!EBt#s(|u;tn1TkI+Bdfc6QppeQq~5w-Gqp-iTeNqOPuvZPPtx<%@&EsXoo-Q7+L9wrgbfGbfxYm?=Fc{UklL#)S1%17+cxyRpl2=Be7?shN%;`>f>PylreQ
z_JuY=^$RqRrl%*BD@4eHKuws$zWl{ZifUddWA**4{ueI0X>^6(hc-46p_N%BQy*mv
zTYdBbA8D(q4zvwRxC}TG1q_!%tIEPNI))OHldBs?Ah~yg!vpOPzGwB;82q-w%PT4M
z&&xP+1%tB@DVa5dycoUrJZpY=sG75EV0f#YlT+`8s~#E1&8H!KN)I+Jx_eQ4miC7u
zqenh0@@GQ1fsP87TiN-OU*g7I;{eW@+ty*o)Y1^Kvd{Jbd7b}jR-g^m^Se$jMyRJk
z&FTZ;cY483vPr*upnp_rmL^Vop|Vt|D96?aT(p>N)vs^SIUD|7qg?SPw;;8%_jpi
zWgg%>Q?OC)owVqUN9wftp3v;lpuui-Ku}Qhhht&j&&-;8y~<60f2d(;WAiLt(S7d<
z*>qs;m)n&XX7fG$@d-1~wGE=>U7*u@8ENQCt2(B6$F)Yk_j66_(5~i2sLg9`s~r9d`yhax>POb;(TBO{^Mi!
zV%R6Mec`xxq4bV01fK|VboWmC9Q5)<%z6dGK`_9Fe)fFVbJ787=`M6>0eY36S2Tmh1~zL
z6wQ5ds70!tuAG$mQb!v<%;W}#tK}@(L{!`s@W=Ha!ywX$=4oKv)!qChKjkeL=A)%z
zXh@}}r#ID|gHnsJ&3uls&cM544wpuN?`T^M4mnhy2H!dl{Xb`FZzgd1RO=-2`d7ht
z982;p+jd{H_>HCi(f0T6KP{XTmy`m#D2C*>9$`dAc2HATP5Cb+ut-Z_18EesDqUE^
zP=0-Rz|9m1YD4~yKPqh(c0cG3Zy28q!OOEI-+ii}I~NK)5
zwg9Z?9>``pqYSL)7O%?j=8<=v&Mi*7571tn{sUrui&rVCYw29drL;Nq{KN8Y`R_-a
zywGEgtcG#dDDB=j;F2t+dJDJf99ts0tC0Q!t-k)ISn5_1-dwFd-&K++_y&O*hOjc&
zlh#h>N|V+W{rtH9bXcHyJyouM)cp=rP}6EKF?umj&di>M1^jUb2<5B!WehdJtLL1o
zyVqaX#b?uG#i_nI@u?B|8$h6ANBl9A>YyZ-{3Zr`frIfb9DZp;&QX$Jx|jK;t5+
zx+;o-tl>+)=Vv)uuvg50&09$1Wkk#MYCGm*Km9H-0nS&EaIt8^{6Q|Om97t;f9CFm
z6f9mReH{H7obghVdme7s-&rs?>=N)Rrjv^um2af)M!xG7CE;);tCRb>_IYK1p+K^x
z5%(Qfc5EZIjJzs5gFhT0ok6y0{SS11Gil(tW%AWDib-Df>z59=o
zx-&d%e-v;ZA?de+(c#9?s+$-Xm*9Atme!f63GKLiiNpxG&~KG4U!}YfPGA;w{zz@1
z-6n+D+#A~cta7Kj-m82{jB)i(B&`eXtJfjFd=swTrnX-eA>zjM+o$NEm6R(klK}Hw
z26p2!QCeTDnombs8!s`mw4w|LvoeB%nKYU!BKDP{+%c5u%FUe$o@n*D{+i9zO_3tR
z$
z!quNrq_Q*}Gxgt(S1zBEm?g?RrLwqpNT&3FUTV44E2J0^5mCd=PiLniD{1wtp)NP)
z$(GLkAiP=qQSAJLJ9$>NLSyx}#*!A=fm4N!YqdqB8WvO>A7~#*`iWW{b(Z>jkvaWH
zm*DFkVC4cUIWdesQO$ZKRS;TbGkpS^$2GJO_Gsg^`FfFm7U+KPAfa!_6=Pcsy`YSv
z!AhtocReo*?U!Oi%i;ooVo~Q?UQL>d9{4&Y)CTGmpV2$IvAWKf*>(d4hG{3_OTP9c
zx-oIWv{$U*3D;y{n;0-hDH-CDb$D&)(NX=(iR&Y_P27W46TsjlQ?$1}!+CDJ^l%3J
zg)Gh9fkAOci==$mjqA6Ne{Oe^)3CRkg&YOA3#ha7_
zrJ!$QZ_?U$V#KDe)0UFpDx~jpDq(j3)@OWNTqHYE^nbn)q(G8%vRY%WUAB)U+0ZoG
zNmGhYT~=p$#0*kO#|r!PO2rk+_(pCYq%?i89@L31q)Ucx8y=3uKheE{%{g)kkMz09
z0X6grFy8u?)iOR+-;Ki;KOU#AYt@!fZ;3p1@q%A$ak2W_@r6_h`37+i&en66KO21!
z=XxJj!sFQ_g%2lnOb$<`O(-o=3rytsh0RWB{`&5A$GJZ{{GvdOq}x^hQGPU|y14QX
z!-6(z@IEkG7(5cr#YzF`NNxxGLUMDRM~!l_u;lfm%_JH$q%t4nnD4$Z7M}$qhabn?
z=G6fZiwYVulSql-47_5*U#(qXuY=h48cQQ{kA=rx?n)^!HHLVdbM5#x-Cd#ME>!cW
zI~GaCH%(1!ecQV;0?6$W>?X|n>#y2)EUw=c7pr(I=eC4mZ0T)roqHV@Q;ETvQU?aY
z(_twiu#Hz}7f!^Xl%u_uA!v(KY;&A%3`u8A6-wf>f>o6jRZ^*Q8cKUF`fMUz0xSkS
zefV~1hdL$P6@>{tOg_+q>uJ4RiOMQm{gr>@^W=MXO)XoBw}A7>Z}Db7yw@mKhy)JO
zp(!n|8$7;U!@0xkA8i4I%E1V8EVv+gnmzO1rl(QQO>{
zmq-FAir+`_PwA_4hx6575Ga{^u}%!BbXuyRKsXK85Ye;>ICF_MO@}F`S9&CiusX9o
z!`s0jR1~>Kon2M;yT14k9X(4+%aNIx&qnZHXmp$uNyep57O6gM4En8k5I)Ly>qs~J
zVe8ykC^<{gMupmo^;vS&Zfkf=);Z2Ihlf*6m_4M9)_{N>h?43(F0dK2;&JC_no`@Q
zYj`J@3M#xyyhudqcXc^ZI_8$V&UEvsQ>9BEK*X(G)d!{Z&l%aJ5U~@t&NsLVi1~>`
zv)iQ=QtZULk|UDC7VE`8o4l>Aw%p!ma5imBxmfWyw%{zm^-MVX9>rdkHoQc%-`O_j
zFno(yYig{Ki~@Yw@m|zTIPg{fO-m+VHK5nJu;=^XzX;~yOqZ7lY$VrevQXI$cXXCS
ze9si0nH8!xMTBY6*c;KJJ=wC)n0LzbBVdH%hIuvBUgAAKS5AC-&G45cqKEj7Z3w*|
zKrdFx@bsBx*0;`&-793lcuW|>_9nxp7Vi8PHH`*4zl59J*_d~HwK0jK8@Xi1AhGTS
z&$JPID{`tvIAW1Wu6xZ+vQ3K?on!PKS$|;wX<7&KjVa;@FXQPMS)*=^h$LhIh}3%t
ziLL(X$@7(PH>n&46c6VeknNUmRn=|c<7k~1$TRR!l+KDH$FJ<+1B|B6CFQG`(Xnn$
z&Ci%t_U4t+XO4Fs4cJ`ILL}wk9{n0AWQj>{-o)rlhv^aAgHIlN<&z8yVgFn4`*MhG
zqTK(0#j{!SM34p?l4JzUkk#7wM8on}khpMWa&of!0)^P#p>RtM^V?WbWl@s>X`FM9
zyHPC+7Z9Bw@3XwP9GgGxuSX2TI+9aTK0i{EU%C#t$RC%t8qsl67QWB;G@msd{2^iG
z;P`zI82-FFnwmgbCjs+c*$OW|eq$E#XJmKS@wgMe`FFT73jYM|m
z86jDVM6E$*8OolvultDay&H7o_F$^^ULJa#R=Q~bCVEJaQ|bEh;ZauyS*kq>bMLEOcx(g%X@o6DC{sL5pN9*Gu$V$
zlhHYvx3}njYMt(-;l&8ut04G=PI2ev=FU&&om?7ymMEq8MW_hSIbT^%nj7GCCYwf4
z!ml#O=MYkr8-6+kPc$d3J%fnwpoKbHqC*e$ypy!3i>aj*wF>Cjgu5tg>IQT
z4sr)0>blznN1m%UZ;C6fsTQVC>Lz!a?QB}}B!t^Sd1Mt12yHkIQ#22deYJ6W3LC4~
z6O4egl+QrMvXqVduRu-Xs$g>s4~o?K@|}~Wx9GXRO$s7j`P-QD{60(ci#ngM!pUukS^>A*ro-
zFw$1Cv|m$p+Caw@3+J&Fj&7#6$aC<
z1qYjNyvKaVESIF;FVO}(d#jxViV&IA$c~=7QDC1145wL+L`<9rP3+G#O77`tb=}Sh
zwyB(E6tR5tK@&ENOkMX?j{^|yDXag+SSpeyb<|dq`TQu>8Mmap%EE8#2TSEv{{I%Zf?vb49@%JScJSB|rAnV5eMlvp)IlMX
zE%6Ib1LZQ}xt~A)i2a51q2!xQORRTIQs9f=^ZY7b-;^V&D}RAV9*oJWKPI~7>h~TA
zORYUza)(2BMQ_PD!@XRv`tRuWx-~_t$6T772*m28=FPB=_vU!p+2rra1AyGi3>dzC
z@w~v0PgP<_HIqwc3V*d2$Hdo&~((@Pp8223Bb~
z?)YBe3D<9*X^vE9?{=u8ast;B#9YK{BUEfhK3$ZChpHzXn#kMA0m0UEY*NO%N4{l(st-xt^3JQ-R$8Byhhs^BPy$}zlg?4
z+e(lpOV**LieevNc@gf(s2B+uuE(bOP%=W0BEswV0Qm}b)n7#+lvfx
zZjB6n?Z&2WLDx8YWrB`lE{kn$XGWJYSlB|#2
zn+lUczbxKNBRpLL4^xAbRK3nh8+rL+MOK<`hBat>PGRR>@xe&w(x-u(cyo=0@wwSD
zrGsAc<9JYNBJPOVNvpe}$cz2Lxoa$k$)=lu8QiOld63`!jvY;wm?L~_ZP2=(epkIE
zv!G$d$6AM@LnqWqoxxdvAm%f`A$SwaYflF;ZdV)-r%P)L*=ZO&bDRnUQxh&theOz
z!iPrwa*JiZcjYiPdN1IK#MCGT~I0a>d
z9={#kFTWEpjg*Bj*vCDyj|#sVC8KM0eaDp+gB)HD^3p(EzYOq3fFRY+RM0AeG`$`*
z9J(c1<3Tja!9WziVIHC9i>g~4tV@e1J56CPZb)|%>Ti=(Sh3)=rLmJQS#D;{4U7MS
z3nb0r{Fumw-)ed%c>dOmKVSk{6{=zSUPf=B*_QDi4uk
z3mObXGC)FVY&AIDYv$&qB8Msi(EIP$&K;l?v4(rW?o6hSVy)x2AR$3S@v`Z8QROja
z7)rhN%mUSz@+0Z(9rtYaq=gZMbe^dse6OeX3PzkW#uQ#Brq7o-rv?T-n1r2_YMwd|
zQy278she~}qK$A2_*mmnzYb_KMIa_yt4mVfLw=f&S@;v`uk>k(DK@RLZ
z5bhD5F9uRWj!RdS=cS|ejrkkA13n!-ax#Pf*P%=&VWqQKQCSP94+vInbcz~j6M2N=Z9Cp(lHAKS`naT-)g-8s~4amctiWv6O0be4U0r1j9eJmP>L7F{@*b
z@wzThej~p^SaVrzQj%X>3(F`aK27l}v$^?WW^|w3Vxdcs5BUl_X~n>4o%wqs#(kvk
z^T7F*sUocRO4VZ?j>?YUXyWmHR1{ZV@iiji@o6bImN5PE=EOmro)l5MF3Xbgdb^d;
z2$q;_=jM(D@Ptj_#ekVrYZIMRsF<<4P>sn30Z>&6g=?*+lqA2O0b{HM4~Mj({Xvv|
zs*%~8VOJ0TJbEN@$w9uX2A!TZ6M;L->ET2{__CclA
z+cV`U!7Mk1gEx1%@TA!jI};Kb+B3daADR4)zFx@k;_6xF{5uFD+!3KoJ-VU3VjGej
zXwI|}i)7*6w!S8%_dphx66T%$=y&0Dq&)a<4nJg*q3Z({~pAA0%b*5E#4-cp(MQ?`Zj@t&02S!*>IvvIEr#}gHBM)
zJWSGLYa{h`TpUm8-kT5Z;R^Rs<;7y^ou-4?XnARi@?Ji^(SdtQ2Eqeka|-0$B;Xs$Dr)G2
zH*W6S*n3G{i+^1OUa?7N_Vo_F$!Tu>8se2YGPSuq`dn|6D-6eLI$Z)ovgk->sul*?
z%rqT58GPw*kP-XgB1x(~K^u84zvwfS?%rSyEBD+%M|B~-$xA{?0+$hLp8mnL#Q@^+
z8F3*w&T3bWtYU!y>!;OI2RXUmes-NtCO6jAO){YA9|Y-_&9BKSp=GFFkunq
znc3Hq9YwB9T*gRj1!pS202PpSL}+dF=G@vIr|9S5Dq626g$Qp)#XKtnQf>m5P0NPD
zf{7#l{Nl%yKubi((SEFWjli_450G$Nj(o|H*&$Z8co%WXZYDG87&9$+B>=gHdbI~4
zguxak+MIO3@pSvAWWRQVI@*Th{~f^iU%TdMkhk=f$C!2ddfoZ_%X=~r
zG`-t4Dt
za!36bj2*52WO#88XuK?x)eJbUbcU6}?veTB1VFZ{U*ct9A5RYzlt&bNojRScf;3-%
zD>qbYe)}_`-CCM*Q|o|kg{Y2WXF%2Awc(SxAD)OE;p66iqy>*G`q0O(Jh02u0-xs~
z`@szANJme~KVGEK0;|ZwNk$@2fzgeb#kj5;mA0xfP*+jVmZnH=dkMH2qA_;hr&`Kg
zWJ9}29{Kxb0I+K3Q2e|(S&xY;U5j;rGtX1QKd}s{-q+6ApxMq`HvS2b;
zpv%g?#o#I|00$Dvn4yO3jJKI
zgNG5SAE@kY+CT5kweP=O6hd=i%G2(Igy=%2%d!~-h3?m{XEXXBv-neQH5Yn^wiY^q5}
zjq~|gk)4@0<@@Nky1etUFNOQEZy=G~o>^=NV*Ppc&KA=F1OE|~#1|t<&>mHNd!3W3
zRl1%}YF=-XNvFl6=|K5Y{L$93XLTs^iVY#H4+O3S=wf9>e#mNRB&1JG;MP48Ws;Tr
z#G&?(f213KTSu%2e)3@MAx?%whu;u?$WhQ4cGgB3EEMMMT%_lVy-){C1`
zK~i(l7_C;TU9+by%213r_qQiJiSL66`4=)*^`;49s}_RlU4G6&rofpsai892bnRdC
zt;610#%^SUD|o~huw0R<_R5yozs%#9-XyjBEJq=acxO70bXnhX^qWW`)Ly
zbKz=>eETZf9!~C3JbFI8T~SsU(Rl_Dgv=;#{+%6Vl(fS@;8TllS1;GOBCl!XLLYN$mOhYs(`9v#!)jVnrKFM(58e;>?oOWj}Na)|k+~
zgI+E*h?s|ogTb>r=mYZzRj(e{O4V@(o2dBuBUP_dES3#kLXZNpkIyF>SbU~+o>=t&
z?ZEDWGBEb=5Ogj!lsuFdsw#A_Z^*Dz)XvvDNE^
zz6?16?rm)}gfu&uRcJGl{m>tW%;>!kb|}WgUlaA4=td$S4ejwBCLuuG$$kgU1Mbqb
zz}<>W-zVWBFC5PLk@J#}@?a2$J9GR+Er4Bi&aoH~0;_2Km=NV)2|Fwl@H512_%P24
zuoAlhv6{#>Bptto<`_>i6ioY~+~vq%dc%2nSMz$d#jdJ|=}e|O|2UQ7E;m;s>9y@@6n6|dm3wiAp^$9I
z+|TtqgOJs8tB4}cFe4o*;QJj(Zb2y4-ouhx#h+B{<}0oGp)@$m<_hl3Cb16#7D$qX
zTgR_9GDuC?FV$zI-7#TUpctl+r*Ll8F0SJ!PB^uIVbVtq1ELaK*COC|C%tL17Dpjy
za5E3aAr*(p@>h4?XPfZFaAIfc`s#|_vX^mjA_dX$A^TB>+s4VMh+NOeyAb~kq+nLs
zq)Z{~(5=v&d$&aJlmzcC{$W3_QcphrtKXR){Y>tZ<;Vg$3;_XDx&k|
zWlN=eU%aJ}w2Q%m{P}ZISlO?P^=%C$Hzkm>Meh_IS!C^gzQMq8#;d6pqj1=&%APS1
zyTIHj>=Xx+xKli>MAj`_%_Dh3tI?+%(oyj}J&E7h6M&
zrz6jdc0361n@3RS()28{(=xF*G>?_4&B-SpbX_mCLXx?%FaZo0Z5X?Bm})=V;0HNhc*M`OHA*&>0yyHP8Ay95-yuldl%KE$7=W4yU&$gps$b-ZF{|9zw$};f(d{KnU*l-hp%25D%;kH$<mW`2B3gV7GjyUMk6CP4FwzCv6PXVe0=kN4rEXbB;q@kCIxZOP3>Wf&Xh~=
zg71@%1yPaLWS><{ml76hG#yoPkL(Xno5#f>F*`tNaYXfkR<&eQ-)_Fa532Fud^KTE
zf4e9kCMLKRBNNU&P|W3VHdIzq!#PJmB;k%2^%wBY69LS#)+(AXd|!GO8?vxZ)bF*z
zS6Y6YczE{Z476KxxVA;gSjoUqeRhO@qEF=LC)Ze}^!Cq{^_-SZsy%a!z&RBHE$W`;
za;ZCe{sQVZ*g?ecY2;wj!q~TggI7|NpOr0_H10mqRW~}dOu1JJ^=8;-b7TR1!_vys
zb}H))SoVyk<@%id(0dwx1uSg;7`mPtlGC?lc9vfZLAkvgfmB(sJ(SY*S
zq0QmvyB(*m1OK%KR$)RmNj^lpGr3TS=BB%}ocPeNMqx^{ryVTZ>LOEG9PEhV6g%{y
z8jc^vUZ+xEO`cU8S!4Q=5p7gJi^$5D7i+(S*!Zn&<;P5l-)dE6An4_
z8T`uJj=LwE2j0R4scm|YKbekjAK`#HQdI6L&8;&!&`VZ}9`NU7G+wj_B@NR6tBQ-B
zXeeOfv8}zTUnrk<0iQG&0q!z9!+g*ASK)-Kx*tHfS5N1Ml8RmlMLpPBJw3UVka_cl
z^APBTKC3N$2Rp9+P&CT7@h$-C?iVcjs1~>5(%_HRd8SM7vg0*Zb525C^&x+eJGbux
z?(r1i+D4vh)!A9%M=dl$Y0=_Vo3+}8rji@O2e}OmnLMqCjaQcS8l(;?`GK5OHno*S
zt3*m?CWXg+t+Cp)zD~^Zr?oEd_^|A?#`HB2$ha1=yC=VPJeho8A3a$%QjrH9H`fcZ
zuiSYsFYr%vXBIfo{*;jP?M0{$$0Kc)=@aG3TBpVy=bX(QWG~0_d4vJ>-mh<1q7A;O
zLY_4&<-~JD!XH+XCrF#FNZ%R>F|o%WP|hI0ao)QlO52zlR<1ZlrOKWEd4(2KeO8ODf94_uYIfxXqmRBA&oDGU)tR9qTbvn!Sw&SN|=X$}9r
zzGNqEWIAYNe9|&<+^gFEf&Rt(En@kKSZL?eQt_yAXvt=JS>jQ)NH?F3>$
zj?+F`!zsgmnSk*l4Q)O$YR6ww!g{P<;aiWXES~(m7?qcF+FiYzZ+g|aH|osU(H@9M
z5cVWh-ZdTe&coBX_~kIzw;xpJN#H;!nmh&o5vBeB4?=0w^6ThgYIvyOhd_rt9_D9H
z27)|J#W&2g>Sh67o>TIf#&R;av6~yV9pNA9^Rmps>jihQwF0~TTzqOB-|`Y9bVoLA|d)B7x<_=EWeKz%UQf))I?RK?_5}(~N-^XZ)OH;&H^aJ>sMazKzTJIOtPt
zL>JBY*}>bICse{OqlN`c-Nt<`kV+@!X9$Xb8VyI?
zk-n2*Psw>|SPASEDpbRI(<5GyDjIp4A6J!~Io~U70H7L@G|EVWp<~;OOy$XF-zy@=
z%@^Dd151j9Kb*X&WKgpyjOIy$)TZX^g0&HI_>
z5_=vU2|!|`D~>{>dIQtLwU!lVOT%}md5}7d=VuXAuAJ#q_mR=Ld2XgxfzNF8nt(UF
zsAI14PpI;K`Y-(K$k8MVo`M-Gah7;T^A!kjw772hdk^`aw~BdG@*M@s@}(|rylmwO
zb+ENrtc-bZo1SPN8#i;gI2nR^Z1lVQ`+z5E?UEMuwy|~P_21`V0zL0-J#@fT#la3&bC(l8CZ}3M=s5Bsx2-L#-29lko90slddScG|LROl
zv{e5vq3rFL^5`7d;*HTebpxXsY0s0L$P~nylFKvg!VU6|=9kd!xI8|p?KWi~ac_57
z1$^^{<%`Xo#=*QOy?bj&-ugRC2e){j6W+MfR_bHArI^^a+K7zgCpivQQJ0MLiLm)11FF`Ug%6Ia|^YFPfST>jo=aYr3l$Zb<}>A
z?{r_r$DSi}X28A3oz{lDX3Xlfrm?50Pc7hli+otMP$&F_E#A{l@2s-OL-)>F$ZXHR
z`4(aR$9>F~Q+GV&dM5_|qMOrrpB0*fGB@ddT_q>3BfBUh=FPq&tnousZ?$^#+xqlo
zTY8OgZA(K`wio=v>lP%dx@3iP1`1o)@R4*%^qvP9
zUL4vNVCqoTV*2Dt+f9Z!_?u!RauH5JSO>mUbM+S^h~0LJw`OKBa|9g+Gp$RJftvQ%
z;yr{%P7kZe2)3myrSJa!e$s)2+c%#ZmF^^RzSTY|QF)nW@@io=bv0iqp@Tl_(3ys_
zMAA_BNySYN2ogZWb17;gbo<#vO!Xhk?{aP%M!`Ro%#E7A~@ebq}?y
zX*8ssCuVfC#NX@-OJYun7zC$)F!uu-SrCJ?N9qSREI{Jfv>NJtOxxT!VpkIukkqBV
zj>f8z=Mv4aZ(Ly-_u0yR*Y3j727iTZ`%j`xXnK)cv=UDSe9}X19-l1FGk!+vX10`b
zg{7k=QbdO`U9>8Dl0{ZO-Fx?EuaFD|DYV$f-!-3v-AZhKU0ag)B-|TtNIJ^)ggt^=
zbib(WY-Q^A{QVwbT$nXUb<`VV{Lb6c`!UloP($kasbaF={r+PIryu@D`G`M%x5DaL
zngUNnt{ArqJ
zSN+`f3Wn>G6C4{fjuv3J^w|J0L;90R<`m!Xut0GZI(%YFO>o%`$
z1y@u>f{J8yPbss{xOp>Rp1tJtd>UxQ-
z*F*W4JL`mf0qV(LF3}wg05<$l8{hD12rj#II4vl_gOC5zn||EsSMgo5oT}>rE--@P
z04Vk+K~jGmr#sz`!dBdom%U}th4zhyw^e5>nSYaRy8oq)S=eYnn8vi>I(7E=TL?sK
zo27A*NhK6VPt&rqAH09~$#{$HO;^fJe{CM17YP-HHZ_DjxbtcohHjV?Nu7
z>W)4i$|iN+Nmj4xS9p%GT0BKj=YG%pS~sg$UsdC({TWr>aZ+sbP+
z`)(&z&^?^ksr!%$1H?VUG%B54-)V=?kD?b-K*uYP(U-5fa@|UFHs&OlA4Q)%p|>{0
zh-!j~^;GE+(57z|nx1C`e{kT=QqoYT!c}04Y*>qCe(>dA!jY__e+frwqlp;eW_9u7CBPGL4o$YYJa9aVd&1IMJJyBF-=k5q>*Tu=k7y+8T|&zSe`Z}>Z3
zt1VImB73b;^9u-jHAPrg=Fx>^3-9rh4&J8-O9e0%Abo{z^KxggZ*XruIX(=>C%k4z
z?*S}+PM1AF(!76(E(Qj`&z@oP#Q#fnQEu>;bawz0m&b-2tk2}a4XR5>VWYT33Fztl
zX*tQ`?5mN$kCbV$93wAlh#A_Fo3Kr!$}~e#}@xh{qX%@CO*CZ
zJ6TE$A74G))BM5Q;KdEvnWj&T3Eawb{YAUC!v5~sw}ACQ;PY;hG2RdU&^3Njj?{3zrJor{X&P27vX))$ljq62@sCediyOqy>5Nv{8Lj3YYUF
z%8il|tqZ&w<&2(&JTm}SOoufc3L;r^-xq}7NWiN6nd+EQ%_y42O^;1TiN4u~{C)CZ
zmDaGYuQv^IBXIOo$+$8XZ*m)Ma!l72f84?LCY66Be>fN1k881h=oxs%j(|tpT)Ie!
zE-dgqptl|Z-JvkB%W!Q+3oK!?|9Pa?XY#FKPg){=)km1$1jipjiru)>8U>=?8vaetgzwEg%W7#^-ucblcjisgb-#3Koa;(S6huyixVfpL?uCoN4VxA^(_Z5$i`Ib``N96=O>Lf0h(R%zbQZB4
zhdrRTdS2&N%bw%-kN9n}DaQBPF>gEg;FG%H&mW>zCd3IwCogQ9>c-a((;ku1ZbYOV
zJ_g4hEn6l5H0<#LwjcK84iai4{a}=PB1L0gSRJcx^{lp8rvwed0fE{yik>EsybLK%
zclq+>-*6=N$y?(N_J=gs8`G%pz9Loj@&>OJ=mQ?)QN}8yV`TiYHPP(v8
ze724PDO0B?RSn1A10k(=#n|ZZTh0Xd#zq(%&K~@Ib4}XAVNVu|3KtJl->WZU1r}t2
zcsQ+e)GCkhjr{+fB{?OeKqLq+A_Oe}BG68N)oX3SiJh?;-My)Nws_LhN842zd~=Tj
znCGiA?vg@`n2$8_Qcdt~)dc`E14G&DKhID2UpK^S-tGTwW4jX4>&M?HFzQR@eKHp?
zLt&Zjzly;0%gcw9)}-}O2IvVNP)O&v&%N2&e6~rYSe&Vp3M&s6+&<@{7&_yMHw75T
z#iJ6G=n-P)8+1wBE8<4#<7Mi;9!;~U{7kvU0YO4%`A_d!0yb<;>JPE+m)H8zizR;N
zdO&l%I}^V@yYH0in_2cDwfsh+*#RztY05gFO}K2J)wW&fAXJ?Jj#F@BHKt0d>;T()
zdSXQI)}{ftdpb(LCbLtP9wr`isoQJ3
z#WDU8+WbPp>&z&AsJeJ70E8&cJz6(uKtZi;7d=t%=0ihizkLN_5&Z7c4?8%MsQqB?
z2+&tw5F>Hfo6T7hNxv!is}}itU+GtqSCk(;VaxKe_aCJBPHZ$q^bsB;;_4lDwn~wF
zO2wS$+ZOyt!Z-1(=6eJ|fsFYY7xV!?<)ir{)+w&5V0$;oZ@bT>$@wb4GtKZiAAhw}
z@N1@zs#(x6qPM0$cB?~tj{27o=^kb$A`1gEJcV12Uf$LS-kN_i
z6J9obaEYc8;L;CdtVv}B;Y7uAZgJ?4vlC%a6rrGQmpl?zx~x&E-J|Hst%v0q>$rc8
z!qT!E$QYIAwkH)h43o*WX`(NxhU>(0jZ@sD4rQgf%CwrwVnU~Rv%JnWx&lmu8j#`m
zk*@V$0&l365Xg#mEt@c$FZgVEwhVMvl+fpP4JdDRpr^~ub?xn9u}MU%?)3KFvo>MG
zx&8;s%E9eU^;G!#3;A@5OWV0=ILGe4&)?Et{n~)jhrGQAA)K3^n^tbe-8$cW^PM(l
z4|t6gI&UY6mkOq?TB_ln%|(VPayByh>%Pz|==U$ZX!NU{(f54(R1Z>1`kRtiHqNz|
zzgfwU9geHCrHx4h^U(zF(%`
zs&SN-<&0Xj?@<=g7#hFY^0$9a@6{zS760NMB(T=U0Zg}dam2@==hLm!tn)Uaup1F4
zGxR%f%kJm$K9tE+e4{aCAg%HJ2Ulb-T~ZWV*RtK$COD-;mS5OO(*Xm5K7HX}TF2n3
zi~3N2B=yy)tTx&bClXGGY
zDyvUyysNdU9Iasvi7Cxgg#oJ!y_&ejueKYkAG|yFJCbl63cKDE7|_=9hSeVg{O;mQ
zhyeL9$E%iKXJk}Xi3UpjNyd`L)Mf#7Q;2q~S{ArWd(WKjnCXx8i#BU85zI$dxD4-M?iPea7V(|u>^#G|c0T|^
zsc0D3+<6w)-E;9wxHnVMS7rQb0KDz$OazP8RoY@c(orhvK)9<;1mZoeIq=B6Pvqu1
zINe5W;&_@b!y8l+xGLE-yOv10t1~?^0)v69@Jzb6cY`Xgeoq;n1gVj7`}LkRR@ffL
z>)i6Hfj=rnqZ#7n4+-+jyhkpdm4ty^F6YCvkgQpIK2T%Iui{j
zYre6C47DdEk*Y!gOZ|TKoHV}?E~OPqDq;
zNs&>ks3Y24!vnzzDb?HTzAGAszBpvbAXm1<&QydRS#4Cw-tywFiK8%RLT*@2-i;bj
zGgmwy8@QOI-c9{Ij)eos5pe2bdTwgaf2Sgu$!gp9xhas{$2()wL@bMzR)1#2((cWK
zONocns`U#+n=cSB^O6v*^9EWK!YuJvzvRCuFngU1$gT@(`}3aR#H4n1)I;~7aO`A-
zhuYn38d6&)lEKbSipGzpDwGMih#9AP0cl%PRY?7zFZB#%Hy2`v?XmIiih&__Io%$(
z3rOReOV$@TI}9}_<%|rP>v-GidihNjMGrF%Uy7s--BEkZB%AKh+;iG|uqcnil4GiL
zZUV)dU`hAbTk;X$v{kYY@E$FxJ6W>`l^
z2VaDKd03eYuhSa#N?ZvuGSgbQo;AHvMqo_sQ1~ZrKO-_zJtE^w085-(5U1VQ!gKr-
zZA7XQc#Jpvd8A)NTXwD*BFZY&{$r0=#OWxmq87eO7jgD1myhA;p__%8sblUPK4PrUgNcoV1ltXXKPO1N$`^7i&J4Yp~=4#No?ao{RCL92GfjX`aQ1FSr7wo
zACLO}L`wG1d(mZd-#mETQEY1ZmjqSwKi791g2Z
z+OoC)P0WM~(#~3_Q`N=4&AkCaz(3>0h$pgpwM^f?Q7u6$N~`{Imopo%RnRM#4{~%p
z$T-jbmH(-|#K~eNsH;dN=(T-^jPiZ;mb?^IGyc
zP_|#3%1>|T(NW>#uxw?8zR5MeUOL5zuQYV$`F54DBNU}fM<{{fB=suwaSHK`a7--G
zvze-hk>@3@+FWb1RTHF{Ms@oypUw3PH}x(5Wc39NR#nlkf29YdIqalG@*|T0+lGOs
z{XBbpd^iW{FSmF7gYl!SDKUO*#y?m3i%wEjOZL9GYf`DB1~DpZ#a0t1q3s_yhIYL>
z)X=xg8gvwBG(t3uma`V4RPXvC_ashvH0kM=!vn59yFXmd#fnVjlVNd{r-5NM)CDf>
zhWtkHEIzxB!)7(oM3H>omR*<0nl30@VVMB~arg-0h`f9{GaAd!F>i!<(|P#qP;3!d
zmmkl%`IR9zigwE@UNn6@_sp~|ybQS9VA5w(UU*vp)0x*g;i4UiP!qp8w6}Bj`$(uv
z?@H(ULUBhIMCsDjV_cdLs^jbP^Ak~e4rYnr0z)p@zEAt*K(5I>z)zuEBcu&lw!b^K
z@7v#TJQNv037!!-`AO1lTXHp`<0RxGlXF-30zGP!*i??M3ZJRhb
zqw%+#0Cv&QXyeFN>2tNogoy2v^!=o^?XcCB^)?0aT7fQE_d1ev8{6zYo+9AHvSy#v
zBWRhMgn!eb^+Z7DHAdwMJP&qGeh7t9R%eQ}<;Lx@ePz#ycFWrdm{f-s_}{xN(Ct`g*UZq8n}8QI~M$suGE(2@;u~CE8Clo1
z{=k9j5Ue(kMm
zIu`0f-&Pc7P|f|ObG{dAqUl7Kr`Y=zY?FT1-G|(BtS|AlK#L{j$hJrCR@*}LVjpL6
z;yK6SOihGakVSDsi`|9|_UG;x;R7pI1ECBz8N}AqW!AO?I9-|PuJ5lC|0W5KK4b4s
z{aK5{XEN2#Hc=6j8z-^%E<*@Qu7bOWF)7Eo9^fh+W6Tm@kH{i^83#I2vzbOdL=e?x
z@n6xv{O#r`I@yfsgpN{=87QTlMfV@&RZI1JFB$aPI%Q6hNgk|~p@|HBQLX+Sc~`L=
z5Wwh_(=ktvy{Irz?RSK`K9xYg<9FCL5}ma_TRBPlE$)#hjMcQ(ym%^>Q8f70
zlXPZ4Zj!CCQf};oOUlZrHbw9YYJ5sEoJo(3IcF1AGkt?#b-}Im-bqlJ3O4t}X!F#~
zmi1JTvyv$apT433_p&muarZ9~D%)%`BH?J~9{_=DpFr67bcB@hmT(7`II!9pO~2(d
z1FMaPd#rTJYSVq5VG)4uezInDL3#leRO@ZWxMjB3
zX$1DFKk)7bNkEb{!OY8QgI?dBWu^|v!_r3W1nM8
z&a7~1GC^t3WmsaeYGS=pF1(^EkH-59yw|o+At(e`L*kzQJrl#V=(p3;a7fc`9e9%)
zG_JQ=Wz3s&5r8Bqa^MieH%%Q=(;*rO;fkh_6Pua&-7i3GTb8@xso{@l{T7^Xy@N3y
zDa}(VwCU;=ETHF6h=6a`a7yX9T(QsTRF0)lJ;{R7p>m*F@ukld_avEaKwAw>Mi&Hs
zOWor~u~#Yyal`Nlrq`n$sa%okYG1T2o3T!NKH=Hs1s?%lB%P!R$8}hIDTB&H_M$$F
zDl5~*5+a6IZlq69wojys0c8pFBS&TzDn4q;%x6p^$G^}dnm^WQ*oBX|Xsu-qt}Y2Z
zKm$n&l9K(Mz-nEQ=a>41&F1{dRCxc<)#W=hSiVL>vBTc@hh1PtSVW(P$OHliiEbl@
z1b1I8Fi4u7tDXdY*dhc?YZ>3*(*kY$(ZO+7IC6)uc>82bg6HOU4Qu`4NU#$*TTQIGbCxZO?|*&SG|X
zX`b$~#p5OQqw}A1V;}2Mqt|;<2HM$Us(E2GVji!YIiG&}-N%VvP5$$zByv-rc0_!C
z;qvyv^gY7vY%}ER)p^McbS>kcRfdC9TS(~bX?@*i>VDyfLA87Xv9)1jhJ7pC9sfZZ
zn%pJj>@-(s9}=w}Pg-ce@Fix53*N6@kS}q_NI^5F+*g+pdm_~zylyEScEh*0IbyMO
zy16-P;GkXQh^jz(X?Ee)7q(ZGCRp11%1aE&RQRyW+5T#-c9lkF?i|rDd}EaK-A^%n
zB5ks>)we2Q@u%<^TnLmKducIC4bjV>FWAucYP{vC1Ff3&Jn61F`
zK7KpH2)y&n*e>Q@iMbrjGy{dS71r;JKKZyvFI`YwAly%e5kTR2B=7F8MZQ5I)uhkT
zj#EdYTWk?d15sgW{+@WQ$cUyDu1O`&h09RTS6Vz}`x(|gy9ge2r6C7X|9KH_GnK}A
z6cF&uP6sKLkmEdlV?h(B(r5*q?THHI_12-<8S7_#9#2t9^lb%kdyZz^hn>U_z;LR0
z+UT86AA{16g)V~R*d0G~|G4OcANis-tn>OF?Fqw>Rgel$(Z6Q;wYF!5|1_z3xN!pp
zdBq7Ypp$_k)eFRsi13*7K~$#7iGR@64aI6l)g(JuR*5tUX7`vj&Z&!_GV2n@%oA=|
z1KjERZn^5>rKN5-;FsT!nRJU_zzHnCn1ID{?y#934H_pHtIAESW-p$fnMf?c7_OZVrVZDGZ0sQI^Km%P$KVOi8`SfdwqM80zBtZ
z`9G@ML1WyW((F)##k$;Dr8J9uv#hWD7)TO>YQmbW<~KEyOV9m^Q*2xd6BF`cc@yW2
z@ze9I7__`r?r@3rq@~kX4e$_z@_nNlk#7|9KZk}+Re;?0cUzN8b}>||J!YduBD0G%
zU^Tjk!TzpiQj@S0X+yL~IHQN~6Q{;m&jpZK^_DyQkw$9V&4@Hz8;y_C
z^6REq9^qZGVt115s=!i#Bv}yN-QqlhJ+GY(6{43ZxUte70yw>rdqIP4de#DNySJZv
zB-~pPv+MCL+7gad==tX=pvpDv_rN*=(>p+W+eqCLiY+mB!1i_LJt{+J$qs(;_UV5H
zT7i->r0M_xAMA^T|4p_Rn*bKOA^DV*>f|zY&3>Ruwk=w@ZU@Ui49m9@9hC_O3Ivt|=t~4Uk4yRF@%lwJuI=N3>4}
z3Gw`BJ7gSF8J5Vyd$KddVg_2Ye>CvO3(i34_l*pwW?Yqx3N>D~DJTyu{bX2Mk+i@0
z$|OtIRczI2%ylf#s>xYKt^7sP^6xr}m(!KK(%rMsjeg+~ki*v+^eLjTvDFtJeL)#Zv^4#1=VjZD4TftL!Dcykgc}tVm7uV&AqBDM
zDqR(v$1L9YJTl8jd-_EW{Lssa8E2E2$MPWDIuO7EQIEZ>EZScEiu2Lk0d1a(=*MN*
z4N30_tokln4I7gRS$45lSEw#75e)lG-f+!B0Zu+9_PNQf*r(+ejrSfnad!)JDvT5O
zAB^Bhry8{xMZ;5`C6RNOdIq{FJ+$odHa$~1k-WL^>*db+yH{N_Tz}nB20bgnc#;T{
z+JArET@(SQ;3706svrVs3vq(yw@VjF2e_9b*$yR3P~UdxZqxhp@~GtW0SqQfa?@FI
z4q<9daUH8d>u#CU67jcy%UNam&g9d+JJ6=XXf*=ed*)D;=zE)WMIiH_3~%y$$!Rf>
z9a>QIy}qd-6es6p2EK&b7y|hYu<@$tZUnhk(M08MdA0jy*r;|Y(%%~CY#HLKii1L%
zX4nPd%%qChx1fZer}Nrf!3Hye4BO_UHSyMzwHEZY*rCdmqrMPagp6=~cQkNRg!(H7
zva`Jt=59h#n)z+guU-j+@EElJV&?3f=l1Q{a6GnNi?073u{YQ!Y$`+b5$2v{zP9O=
z^Wmu4A!q0N05`pHtKKeu{W=zz6_u2h;ngLHD^c*I1!g=bLir}J_%54wMaE`1V7$gi
zQV<5yeW!vu4~oXamOztpocMd~st%S{VRpIErHA{srX-u*FH?q?oEmC
zMaJJPQ76Lt+tp#wz9dAcDSHLIX*K+=!X
zAPsb@!b^F&nuC^PNaz`f5k>knodhkz!H&K@hYCY{b!y-B(W)F@Df^xu^7c>y~jhW0HG?WV}04TbQ}gkND~RvktCa
zTA4ifR=nmHj{7xf?{z#d!^K%bvF1(h!kz?f);;@UP9`^+@YYPCl$3sXvoqjzM~(4T
z>i&1h_FtM8>3lLhtYV|}qKrau1=bhods6!m;7!IapTSS;YwwIKwoC>14gz1dj23Zq
zgF-(0_Hk92^rFcLWqDw&)nRgYh=aKG`SK(ELb*e$;}oP
zpl$Z!gRXJGD?p{i=}OgPgG)t~V!?eXG_`nG4ZUf8N|KL6@JUiFF{y)P9Oq9lNX4Nn
zAtyhw?qSdxS6m@OL$;g0WHgWP!obEAD(*?K5hkGlT(|Oxnwz)2R_`HnuOl}
z1Dpm$!P9R|3GwhBwr0g7-Wlnt&NGG2Go0_gbw48Nl0K44Z~3mHiCkw`JT^EJOu2e1
z!%X__Tt>?SqZHBadc#q0=L}HZoU!22R>%lWiR@1{Uj&Dn;jDd5zPiH*hyo-+M>O~m?)>*fS%?8V~?FC1vNWmRo8->Ts6{t
z)}vVlGgQx$mszmrDD1?VPxzWHXH9VyjH0t&4f_t|1*2;=i3TnKbT+y46GogWjNDM8viltyNI->X<^)<&opim3bUnN}ewb41t7+xS|$h%soT+
za+qG9g`~nDr`w>B%iDRrK2Pu~G^$=T^@=dVop(Ih4w9PIE*1lFSCxii5>{EH)6b+F
zpl))vPy<%}e$fX3J0elev)Adg(?xK}aWT9;9Q*i5@G6PSu0k=Umt~AUB<{CPQ*oV)
z%khbQ1a2$`{`I1NCM(6(hCIPhXVnj-@SPpmw_uQ%LkdLYH;X-QNP
z{nj5-D_mx9ewSOT{#t`o_Fky3S_j{aFL$TTbfo)zW}R|;J_PF!Nu8-P^f798
zL3Us=%DGg@Sjv>KgTL_`?(S$QG-uXswcGJ$o{D_~9|<2}uaJcbtboY{4$1fUjRwqL
zerw)yjKN`HA!c(N3$oyuSx%efT?vi2M9&yI;<4V+Z;I{N6NnH*d`Vd%^L56&jPf%%9w&qSInO}otG4>2N=
zDl;J>nHAw-3k##L^|lwv6Itj^X-*Dc1TX<_pU3tOa8P#w)BHOot(dRobl{LY^^+I%
zuK0+nv8O(v);eF4c;YC9yQLz2MnVGuy5e9JR{pC>7cryboN`s987yO}XS2O~Sift1
zcar2}v*W5{9CP4HNsF*2BHBpz2Xt6eQ(j{s9abjQM#Bz>DVK<=t(QTyl4*R<^LyFH
zT^vJuLjCS>V#Xzl#wpGM%!-OlwAcK%HyJ>!Z0Ofm|@Dv8MzdI9h!
z3h73JoO$0Iu{TLsF6tXmXGEpBM2g%uJ`WE0S<%9x?H}VPsnER7Xib!C(kHP9AKSZ9
z7QoWbb~;b-V0NOAUTZcDm_NNblNqx+CVluQ?zkjU^Rt6+A6ru|3V_nvWKz)5;$--N
zXA~Dlr3*b9a$-kcG}rHuI0`Ztw@+OmV1ahCcJm7(87!%;k3+c6Q3D)aD{sci5jQ5^
zW?osR23(OfVJ1>JZVus7@hzT$mDH(#%F_&P)2d?=`m)*i>%uAOr-MCc!u0Ie$UjJ}
zW%@WT(m!$v$zUX{$g@tPAy%p94AjDYx2<1Zwt#=vjYOnKzHj?sU4`_C?J_y>iE>6W
zG_3PFT+l%~7*EB__G+@=hFRw1j?G`sG#dO!UmNk%KffuW%5
zGOZR0Z0yjw?Q%s7uM2pHLMz6s9-3iZbE9L$3R`{`Z_nZSwr$STWSvMTzGX-p(cN0a
zYXR4k4m#X)G*X*7Q(RTQ#T4
z$Uo$QS(P!Q2;u1i)|VzsFjVuIubnXSo=@U6U15HOUvd6E{E2%BUo;^ke;39HoQLyv
zm?^rqhqr*lGZrTOyUe$pJyciq%iy_>{D&9Ag=ZC*MRjJ_>0rvi_iEZ3HwR=%L=LGG
zCHJLQ{Y*)AB%0-Yf0Wrq^Y%Rh77$ApP^z^K=r67J;PuyL4SVWyiB9+5@VC!4b*rqa
zKd^$JZ2F(K@Qqz=K0S#<0rfzB>IN0qRczT~bZ8DMj^KWzb$PuSsc%;!{)1DJH;_mQ
zDF&)8nHYW|8;2#*81Gd(i1=WhH#Tcb`0WHa&uru276&a@cR(W&sIKu)ONn7ADGH}}
zp!^*C5Z^JJornYF>d*XWW&K|9Yd5Je6lb8lKOlZnr$p>DRiUKESgmOqb!MB_E;73tyd-T>
zBG|rA{ymj$=|Gr_ry6>C*mPrTo5Ggoba=E+(AGuyvU)y&gz!PD!<djUI3p}xsLsE;)sZq0%-pE!G^^MR&&^$wY_
z4H$lSX815EI81`_QsnD^7R}%v-(D*H|C$e{dQ80FOIi-kTA#fWK?4nvK@>z6t^R7~
z^~MMJnUdMKZD`V*9RdY&iYT`KW
zm$uB-g#p9erTEh35n?Iyk$bM*-K#N|_FXW<(69ov$K|vq`eWn{>yU5O-sQuV?f25D
z#D=U_gof_YXsbM0hf*D)*jbT1cP=zUHO1P&r+R0Wq|+N-PyDWOD*nI>PWHxVou<9Rk^73Y(1%=ZqE(
zxVjg|R&*GEjL^c^^hD}#a%X;f`0u2!Ot>;}f?b^v;XsXNq!iJLAy9kWgm;i&hMc6J
zusxxAvTawma*;W?036ZV8GB81bz^p}=BN{$?zR4O-{Z7H`H!9N9TwnX3A6&>vDu>p5;hX5
zd;jN`tW?*3cd!NSl7Gkl#kRF8nDde=?~%qLoRK;4e|$voJ@14c$}-ddf-#76fe24RniWx2Abk#VmbWG9$7%-;261o1?H=h9UC5t{YV|C0RI6=p>DI6uB
z&H3a}BJF?h@!R9{^!tjdZ%l+gWQq+{ex72~cCM7i%e`Q3GCBBqPUL#tNC+YUPX#cC
zeO9JYRJ(%uOhuuN%yF{2720K&{qdKjuNWE^2x_`4c*N=CqdYy6?Q(`!&Pq0>qkz+=
z6li#dM7(oruvVEvH#K(G;a^k66vEva{}3)am;j;wd;}_*{}Ej(M^(A6&o8%MJr6|^
z%9yeB?&1qKsPBkCQGYH+{P%5S2lTc7*?OVWS7MFaDc8c3Xd>Qu_;3e0fu-ix5U()K
z`Z>YwV)vTrRnWZj{iLq?Q1&@6>xW*T{Moa6XvN~Zk+?+#ok8;|^2UzdK+QrQUNkE0Koxi8klnKW
z?3cmtHmwM=Bas30Zs^NDopdZ7UKarRxYojE#6(j$rVa0l^71tw-31yeG>YLvauATI
z)TwD>QK(3MQRUL>?FK#1S)RtAqx5?HM*pS&Z5l-l)4_%?I3Astn$e3sGM%wOSVgiV
zSlYMp9huuxJMMA#xgTxdhchzg5m{91{tdFPiS5VP3omOQ3V}(!BO8&v1Nx00FWy34
z?GV+o^I5x4
zwk2BSJ#@fj>(P@vY4^h846nBw1yj{K>adtM)jZr^dFbJhN%p6MHmuW%)aq#QA&?eVV`;g1gXR5zRm3Jj;@IYO(C*|N~
zMZ5A=VrphoLDT!jVd{+}r=l+e5ViEd+xDEy^7#e^H9t+)TPZkfu*bS1gHri*izU^h
zmU{Xu`S;IzIgCYnGLB2H@Vcajio~8?DsBIA&%gDq$i-%%yRPVg;PUI0HqzVOvV9S#
z`|vzD9bBWS9pp@Th8NN86yZ_qVvb{OpOLswOP=@_279hws(DTd=WLuxa|f)YL*C!G
zE!oIgnu0H9XU8GgtvN!3D<{m9Ti}1EB&G7o?B-^EWoItJ4xh=B(?N>>RT<_X`}3*h48K
zZ4t4ExI`_a{kO~+F(+Un@=J7M7mE`$mkz|a+m4!V&IcI%iGc5cxMj0eDSJ5n6|?64
zUMfB7-%5$-^aDL?fQ0RW;m>22;T5+A|1sqNc#AkQm%*AoGu2m@
zNyu7f^%=Z}Y6wSbxU6U{zu4*fgNMD(NJswg23lg{y4$6B*r+6cCMz{R#H$h@rW3EL
zX$_+bS7$snA!07cjdj5&!2P@KJ${6&YY3FQg)i}9X3@%cCwAvP7xy87uzY3#hLVSq
zYXub@;k3`t=ow6%bRvqyEBxW*mwXpCo)k-{H=LyeEcuKsCR1p%zE!KSItpJBn_OTT
z2q%ioE#Yp-a#t0440tonY2wjF6%j5AbqziB0k8=d3m=kj98{N`_$b=lEBbCY!<)%)
zFfw!aCZm$+#YX`wc6Q?(1G`)7&BB{08LRMJ+gG)he5R7xTPi-e648VZCK>PB>HlVAVUT_Qm5^zhJyeoz2vxjv)5<|QbWHHY_7d0E+s^m3pBap355`WlhusO*Bbwxq>Uu{_5tS~KQIED}LH~)zm);MA%ELy=%NDEp
zIT0CZ%j4se_%()TeYWf_CqGJyZpSxuGt)BnTpkv|lTmjcV^Ipve>Yu4n_xl-pkz)88pmy5vm2apXJobNXLC3
z;yB)F|03?hI<H{66BkZKgqpbVwu2n^dq~_r+|bd>K@rh!?M6S)#1s8?Q}n=F
z6i574JuN^1?KD}XonY`u0HIU-}z=fl?G^r$l+Qv-gg@|nO
z*D|oZ^)ctMc7{DG(6eX(E{TN1KAeU%3C<4I`t=wfMPR!Q6O=|Gjf1&G-9Olbl);Jj
z)J^*PC7v7bd2r0^ww@Iwyi6CBBV2+cgLw`P)C&%dB&-byh+%egqYMT*djrfF>Pj9VIu
z(+%%y;aUWNy~HKfq3hnHKMU`FYYyH@vx`c0)vy?TY;oBy@SbSv)&~HHJa_&-Xq$0f
zjR?I?tBwr*TgSa1vt_G3#JZLa{HnvfGs1v!zaT%ZZwYQdb1RKJ+uq
z-67up019W{c|4Z?{_Bwt?Z2dKy!oPKiY1b^Un91N>w<|OV4)n6|wz5
zHuzV4sQZ+0pKHOsiBI{@K?z`IADh2uN_+!#or|1y`zoDk=6=__Ez;cCKueKel%)N(
z1-+>pXr$LLFzyl6K3dcr{!!|u_4SqnKrGTY?Jf=Y@@JC^kUx+Ilwt)Gy39AcZ%6MoQ?8fk4@9uOLOmkbZ3s*6uBAdh{(%uAUWJiC
z<7(2)wA)x%dQ#n{`U9-Ls2@4}`>QGj$_|3g-4cQplpG9eW6M8@rxqfyYEpj`_=ZMC
z|7d;e_uc!C5!`>=^#DBX`bmND|Ecfet9i34l$nPC1<{`_mBu1Ap8b>ze|fiN*M
u%K5_p`C{4E@BbG%UGs1N
diff --git a/docs/quota_check.md b/docs/quota_check.md
index 3f922743..37da7db5 100644
--- a/docs/quota_check.md
+++ b/docs/quota_check.md
@@ -5,9 +5,12 @@ Before deploying the accelerator, **ensure sufficient quota availability** for t
### Login if you have not done so already
```
-azd auth login
+az login
+```
+If using VS Code Web:
+```
+az login --use-device-code
```
-
### π Default Models & Capacities:
```
@@ -75,7 +78,7 @@ The final table lists regions with available quota. You can select any of these
### **If using VS Code or Codespaces**
1. Open the terminal in VS Code or Codespaces.
-2. If you're using VS Code, click the dropdown on the right side of the terminal window, and select `Git Bash`.
+2. If you're using VS Code, click the dropdown on the right side of the terminal window, and select `Git Bash` / `bash`.

3. Navigate to the `scripts` folder where the script files are located and make the script as executable:
```sh
@@ -97,4 +100,5 @@ The final table lists regions with available quota. You can select any of these
curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash
az login
```
+ > Note: Use `az login --use-device-code` in VS Code Web.
6. Rerun the script after installing Azure CLI.
From 26aa44bf6c1512319c8c2a3fb7f9e45047ae41da Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Tue, 2 Dec 2025 07:14:58 +0000
Subject: [PATCH 02/13] Initial plan
From d2a1f23445e0b1eeb2178ccf59b65d77305a1eba Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Tue, 2 Dec 2025 07:17:07 +0000
Subject: [PATCH 03/13] Add dgp10801 to CODEOWNERS file
Co-authored-by: Prekshith-Microsoft <216912978+Prekshith-Microsoft@users.noreply.github.com>
---
.github/CODEOWNERS | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
index 52471219..c850ddd2 100644
--- a/.github/CODEOWNERS
+++ b/.github/CODEOWNERS
@@ -2,4 +2,4 @@
# Each line is a file pattern followed by one or more owners.
# These owners will be the default owners for everything in the repo.
-* @Avijit-Microsoft @Roopan-Microsoft @Prajwal-Microsoft @aniaroramsft @marktayl1 @Vinay-Microsoft @toherman-msft @nchandhi
+* @Avijit-Microsoft @Roopan-Microsoft @Prajwal-Microsoft @aniaroramsft @marktayl1 @Vinay-Microsoft @toherman-msft @nchandhi @dgp10801
From 961ac74543e606747a63e5b09b7938de1c04aa17 Mon Sep 17 00:00:00 2001
From: Shreyas-Microsoft
Date: Fri, 12 Dec 2025 12:07:44 +0530
Subject: [PATCH 04/13] add known issues
---
docs/DeploymentGuide.md | 41 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 41 insertions(+)
diff --git a/docs/DeploymentGuide.md b/docs/DeploymentGuide.md
index d67bf4da..8e40ee77 100644
--- a/docs/DeploymentGuide.md
+++ b/docs/DeploymentGuide.md
@@ -257,3 +257,44 @@ To help you get started, here's the [Sample Workflow](./SampleWorkflow.md) you c
provisioned using `azd provision` or `azd up`, a `.env` file is automatically generated in the `.azure//.env`
file. To get your `` run `azd env list` to see which env is default.
5. Ensure that `APP_ENV` is set to "**dev**" in your `.env` file.
+
+### Known Issues
+
+**Unable to update/add environment variables in Azure Container App**
+
+You may encounter issues when attempting to modify environment variables or container configuration in Azure Container Apps:
+
+**Affected Scenarios:**
+- **App Authentication Setup:** When adding authentication-related environment variables (CRUD operations on env variables)
+- **Container Configuration:** When trying to edit ACR name, image, or tag information for Container Apps
+
+**Root Cause:**
+This is an ongoing issue in Azure that affects the Azure Portal's ability to update Container Apps configurations.
+
+**Workaround - Use Azure CLI:**
+
+Until this issue is resolved, use Azure CLI commands to add or update environment variables and container configurations:
+
+**For Environment Variables:**
+```bash
+# Update environment variables
+az containerapp update \
+ --name \
+ --resource-group \
+ --set-env-vars "KEY1=value1" "KEY2=value2"
+```
+
+**For Container Image Updates:**
+```bash
+# Update container image
+az containerapp update \
+ --name \
+ --resource-group \
+ --image /:
+```
+
+π **Detailed CLI Documentation:**
+- [Manage environment variables](https://learn.microsoft.com/en-us/azure/container-apps/environment-variables?tabs=cli)
+- [Manage revisions](https://learn.microsoft.com/en-us/azure/container-apps/revisions-manage?tabs=bash)
+
+> **Note:** This is a temporary workaround. The documentation will be updated once the Azure Portal issue is resolved.
\ No newline at end of file
From d7fc9c76d448533079874fcfff9f87d0b3ecb4dd Mon Sep 17 00:00:00 2001
From: Shreyas-Microsoft
Date: Fri, 12 Dec 2025 12:09:27 +0530
Subject: [PATCH 05/13] remove #
---
docs/DeploymentGuide.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/DeploymentGuide.md b/docs/DeploymentGuide.md
index 8e40ee77..e5c3745f 100644
--- a/docs/DeploymentGuide.md
+++ b/docs/DeploymentGuide.md
@@ -258,7 +258,7 @@ To help you get started, here's the [Sample Workflow](./SampleWorkflow.md) you c
file. To get your `` run `azd env list` to see which env is default.
5. Ensure that `APP_ENV` is set to "**dev**" in your `.env` file.
-### Known Issues
+## Known Issues
**Unable to update/add environment variables in Azure Container App**
From 65a605746693c42f14400c0492c002c08e5d33ea Mon Sep 17 00:00:00 2001
From: Roopan-Microsoft <168007406+Roopan-Microsoft@users.noreply.github.com>
Date: Tue, 16 Dec 2025 00:24:00 +0530
Subject: [PATCH 06/13] Delete
src/frontend/src/components/errorWarningSection.tsx
---
.../src/components/errorWarningSection.tsx | 58 -------------------
1 file changed, 58 deletions(-)
delete mode 100644 src/frontend/src/components/errorWarningSection.tsx
diff --git a/src/frontend/src/components/errorWarningSection.tsx b/src/frontend/src/components/errorWarningSection.tsx
deleted file mode 100644
index 86eb5b89..00000000
--- a/src/frontend/src/components/errorWarningSection.tsx
+++ /dev/null
@@ -1,58 +0,0 @@
-import * as React from "react";
-import { ErrorWarningProps } from "../types/types";
-
-export const ErrorWarningSection: React.FC = ({ title, count, type, items }) => {
- return (
-
-
-
-
- {title} ({count})
-
-
-
-

-
-
-
-
-
- {items.map((item, index) => (
-
-
-
-
-

-
-
-
-
- {item.fileName} ({item.count})
-
-
-
-
- {item.messages.map((message, msgIndex) => (
-
-
-

-
-
-
-
- {message.message}
-
-
-
-
- ))}
-
- ))}
-
-
- );
-};
\ No newline at end of file
From a04b7b884722ff50f92f41cac19b96465b887093 Mon Sep 17 00:00:00 2001
From: Shreyas-Microsoft
Date: Tue, 16 Dec 2025 08:57:40 +0530
Subject: [PATCH 07/13] Remove known issues about Azure Container Apps
Removed known issues section regarding environment variables and container configuration in Azure Container Apps, including affected scenarios, root cause, workarounds, and related CLI documentation.
---
docs/DeploymentGuide.md | 41 -----------------------------------------
1 file changed, 41 deletions(-)
diff --git a/docs/DeploymentGuide.md b/docs/DeploymentGuide.md
index e5c3745f..d67bf4da 100644
--- a/docs/DeploymentGuide.md
+++ b/docs/DeploymentGuide.md
@@ -257,44 +257,3 @@ To help you get started, here's the [Sample Workflow](./SampleWorkflow.md) you c
provisioned using `azd provision` or `azd up`, a `.env` file is automatically generated in the `.azure//.env`
file. To get your `` run `azd env list` to see which env is default.
5. Ensure that `APP_ENV` is set to "**dev**" in your `.env` file.
-
-## Known Issues
-
-**Unable to update/add environment variables in Azure Container App**
-
-You may encounter issues when attempting to modify environment variables or container configuration in Azure Container Apps:
-
-**Affected Scenarios:**
-- **App Authentication Setup:** When adding authentication-related environment variables (CRUD operations on env variables)
-- **Container Configuration:** When trying to edit ACR name, image, or tag information for Container Apps
-
-**Root Cause:**
-This is an ongoing issue in Azure that affects the Azure Portal's ability to update Container Apps configurations.
-
-**Workaround - Use Azure CLI:**
-
-Until this issue is resolved, use Azure CLI commands to add or update environment variables and container configurations:
-
-**For Environment Variables:**
-```bash
-# Update environment variables
-az containerapp update \
- --name \
- --resource-group \
- --set-env-vars "KEY1=value1" "KEY2=value2"
-```
-
-**For Container Image Updates:**
-```bash
-# Update container image
-az containerapp update \
- --name \
- --resource-group \
- --image /:
-```
-
-π **Detailed CLI Documentation:**
-- [Manage environment variables](https://learn.microsoft.com/en-us/azure/container-apps/environment-variables?tabs=cli)
-- [Manage revisions](https://learn.microsoft.com/en-us/azure/container-apps/revisions-manage?tabs=bash)
-
-> **Note:** This is a temporary workaround. The documentation will be updated once the Azure Portal issue is resolved.
\ No newline at end of file
From 12a7906a17d404be0e33d4e0510678864e469847 Mon Sep 17 00:00:00 2001
From: Vamshi-Microsoft
Date: Thu, 18 Dec 2025 10:27:36 +0530
Subject: [PATCH 08/13] added Deployment v2 workflow
---
.github/workflows/deploy-linux.yml | 88 +++++
.github/workflows/deploy-orchestrator.yml | 138 +++++++
.github/workflows/deploy-windows.yml | 92 +++++
.github/workflows/job-cleanup-deployment.yml | 114 ++++++
.github/workflows/job-deploy-linux.yml | 180 ++++++++++
.github/workflows/job-deploy-windows.yml | 181 ++++++++++
.github/workflows/job-deploy.yml | 355 +++++++++++++++++++
.github/workflows/job-docker-build.yml | 113 ++++++
.github/workflows/job-send-notification.yml | 224 ++++++++++++
.github/workflows/test-automation-v2.yml | 185 ++++++++++
infra/main.bicep | 7 +-
infra/main.parameters.json | 6 +
infra/main.waf.parameters.json | 6 +
13 files changed, 1687 insertions(+), 2 deletions(-)
create mode 100644 .github/workflows/deploy-linux.yml
create mode 100644 .github/workflows/deploy-orchestrator.yml
create mode 100644 .github/workflows/deploy-windows.yml
create mode 100644 .github/workflows/job-cleanup-deployment.yml
create mode 100644 .github/workflows/job-deploy-linux.yml
create mode 100644 .github/workflows/job-deploy-windows.yml
create mode 100644 .github/workflows/job-deploy.yml
create mode 100644 .github/workflows/job-docker-build.yml
create mode 100644 .github/workflows/job-send-notification.yml
create mode 100644 .github/workflows/test-automation-v2.yml
diff --git a/.github/workflows/deploy-linux.yml b/.github/workflows/deploy-linux.yml
new file mode 100644
index 00000000..aecf5071
--- /dev/null
+++ b/.github/workflows/deploy-linux.yml
@@ -0,0 +1,88 @@
+name: Deploy-Test-Cleanup (v2) Linux
+on:
+ workflow_dispatch:
+ inputs:
+ azure_location:
+ description: 'Azure Location For Deployment'
+ required: false
+ default: 'australiaeast'
+ type: choice
+ options:
+ - 'australiaeast'
+ - 'centralus'
+ - 'eastasia'
+ - 'eastus2'
+ - 'japaneast'
+ - 'northeurope'
+ - 'southeastasia'
+ - 'uksouth'
+ resource_group_name:
+ description: 'Resource Group Name (Optional)'
+ required: false
+ default: ''
+ type: string
+ waf_enabled:
+ description: 'Enable WAF'
+ required: false
+ default: false
+ type: boolean
+ EXP:
+ description: 'Enable EXP'
+ required: false
+ default: false
+ type: boolean
+ build_docker_image:
+ description: 'Build & Push Docker Image (Optional)'
+ required: false
+ default: false
+ type: boolean
+ cleanup_resources:
+ description: 'Cleanup Deployed Resources'
+ required: false
+ default: false
+ type: boolean
+ run_e2e_tests:
+ description: 'Run End-to-End Tests'
+ required: false
+ default: 'GoldenPath-Testing'
+ type: choice
+ options:
+ - 'GoldenPath-Testing'
+ - 'Smoke-Testing'
+ - 'None'
+ AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID:
+ description: 'Log Analytics Workspace ID (Optional)'
+ required: false
+ default: ''
+ type: string
+ AZURE_EXISTING_AI_PROJECT_RESOURCE_ID:
+ description: 'AI Project Resource ID (Optional)'
+ required: false
+ default: ''
+ type: string
+ existing_webapp_url:
+ description: 'Existing Container WebApp URL (Skips Deployment)'
+ required: false
+ default: ''
+ type: string
+
+ schedule:
+ - cron: '0 5,17 * * *' # Runs at 5:00 AM and 5:00 PM GMT
+
+jobs:
+ Run:
+ uses: ./.github/workflows/deploy-orchestrator.yml
+ with:
+ runner_os: ubuntu-latest
+ azure_location: ${{ github.event.inputs.azure_location || 'australiaeast' }}
+ resource_group_name: ${{ github.event.inputs.resource_group_name || '' }}
+ waf_enabled: ${{ github.event.inputs.waf_enabled == 'true' }}
+ EXP: ${{ github.event.inputs.EXP == 'true' }}
+ build_docker_image: ${{ github.event.inputs.build_docker_image == 'true' }}
+ cleanup_resources: ${{ github.event.inputs.cleanup_resources == 'true' }}
+ run_e2e_tests: ${{ github.event.inputs.run_e2e_tests || 'GoldenPath-Testing' }}
+ AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID: ${{ github.event.inputs.AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID || '' }}
+ AZURE_EXISTING_AI_PROJECT_RESOURCE_ID: ${{ github.event.inputs.AZURE_EXISTING_AI_PROJECT_RESOURCE_ID || '' }}
+ existing_webapp_url: ${{ github.event.inputs.existing_webapp_url || '' }}
+ trigger_type: ${{ github.event_name }}
+ secrets: inherit
diff --git a/.github/workflows/deploy-orchestrator.yml b/.github/workflows/deploy-orchestrator.yml
new file mode 100644
index 00000000..23a59b4d
--- /dev/null
+++ b/.github/workflows/deploy-orchestrator.yml
@@ -0,0 +1,138 @@
+name: Deployment orchestrator
+
+on:
+ workflow_call:
+ inputs:
+ runner_os:
+ description: 'Runner OS (ubuntu-latest or windows-latest)'
+ required: true
+ type: string
+ azure_location:
+ description: 'Azure Location For Deployment'
+ required: false
+ default: 'australiaeast'
+ type: string
+ resource_group_name:
+ description: 'Resource Group Name (Optional)'
+ required: false
+ default: ''
+ type: string
+ waf_enabled:
+ description: 'Enable WAF'
+ required: false
+ default: false
+ type: boolean
+ EXP:
+ description: 'Enable EXP'
+ required: false
+ default: false
+ type: boolean
+ build_docker_image:
+ description: 'Build And Push Docker Image (Optional)'
+ required: false
+ default: false
+ type: boolean
+ cleanup_resources:
+ description: 'Cleanup Deployed Resources'
+ required: false
+ default: false
+ type: boolean
+ run_e2e_tests:
+ description: 'Run End-to-End Tests'
+ required: false
+ default: 'GoldenPath-Testing'
+ type: string
+ AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID:
+ description: 'Log Analytics Workspace ID (Optional)'
+ required: false
+ default: ''
+ type: string
+ AZURE_EXISTING_AI_PROJECT_RESOURCE_ID:
+ description: 'AI Project Resource ID (Optional)'
+ required: false
+ default: ''
+ type: string
+ existing_webapp_url:
+ description: 'Existing Container WebApp URL (Skips Deployment)'
+ required: false
+ default: ''
+ type: string
+ trigger_type:
+ description: 'Trigger type (workflow_dispatch, pull_request, schedule)'
+ required: true
+ type: string
+
+env:
+ AZURE_DEV_COLLECT_TELEMETRY: ${{ vars.AZURE_DEV_COLLECT_TELEMETRY }}
+
+jobs:
+ docker-build:
+ uses: ./.github/workflows/job-docker-build.yml
+ with:
+ trigger_type: ${{ inputs.trigger_type }}
+ build_docker_image: ${{ inputs.build_docker_image }}
+ secrets: inherit
+
+ deploy:
+ if: "!cancelled() && (inputs.trigger_type != 'workflow_dispatch' || inputs.existing_webapp_url == '' || inputs.existing_webapp_url == null)"
+ needs: docker-build
+ uses: ./.github/workflows/job-deploy.yml
+ with:
+ trigger_type: ${{ inputs.trigger_type }}
+ runner_os: ${{ inputs.runner_os }}
+ azure_location: ${{ inputs.azure_location }}
+ resource_group_name: ${{ inputs.resource_group_name }}
+ waf_enabled: ${{ inputs.waf_enabled }}
+ EXP: ${{ inputs.EXP }}
+ build_docker_image: ${{ inputs.build_docker_image }}
+ existing_webapp_url: ${{ inputs.existing_webapp_url }}
+ AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID: ${{ inputs.AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID }}
+ AZURE_EXISTING_AI_PROJECT_RESOURCE_ID: ${{ inputs.AZURE_EXISTING_AI_PROJECT_RESOURCE_ID }}
+ docker_image_tag: ${{ needs.docker-build.outputs.IMAGE_TAG }}
+ run_e2e_tests: ${{ inputs.run_e2e_tests }}
+ cleanup_resources: ${{ inputs.cleanup_resources }}
+ secrets: inherit
+
+ e2e-test:
+ if: "!cancelled() && ((needs.deploy.result == 'success' && needs.deploy.outputs.CONTAINER_WEB_APPURL != '') || (inputs.existing_webapp_url != '' && inputs.existing_webapp_url != null)) && (inputs.trigger_type != 'workflow_dispatch' || (inputs.run_e2e_tests != 'None' && inputs.run_e2e_tests != '' && inputs.run_e2e_tests != null))"
+ needs: [docker-build, deploy]
+ uses: ./.github/workflows/test-automation-v2.yml
+ with:
+ TEST_URL: ${{ needs.deploy.outputs.CONTAINER_WEB_APPURL || inputs.existing_webapp_url }}
+ TEST_SUITE: ${{ inputs.trigger_type == 'workflow_dispatch' && inputs.run_e2e_tests || 'GoldenPath-Testing' }}
+ secrets: inherit
+
+ send-notification:
+ if: "!cancelled()"
+ needs: [docker-build, deploy, e2e-test]
+ uses: ./.github/workflows/job-send-notification.yml
+ with:
+ trigger_type: ${{ inputs.trigger_type }}
+ waf_enabled: ${{ inputs.waf_enabled }}
+ EXP: ${{ inputs.EXP }}
+ run_e2e_tests: ${{ inputs.run_e2e_tests }}
+ existing_webapp_url: ${{ inputs.existing_webapp_url }}
+ deploy_result: ${{ needs.deploy.result }}
+ e2e_test_result: ${{ needs.e2e-test.result }}
+ CONTAINER_WEB_APPURL: ${{ needs.deploy.outputs.CONTAINER_WEB_APPURL }}
+ RESOURCE_GROUP_NAME: ${{ needs.deploy.outputs.RESOURCE_GROUP_NAME }}
+ QUOTA_FAILED: ${{ needs.deploy.outputs.QUOTA_FAILED }}
+ TEST_SUCCESS: ${{ needs.e2e-test.outputs.TEST_SUCCESS }}
+ TEST_REPORT_URL: ${{ needs.e2e-test.outputs.TEST_REPORT_URL }}
+ secrets: inherit
+
+ cleanup-deployment:
+ if: "!cancelled() && needs.deploy.result == 'success' && needs.deploy.outputs.RESOURCE_GROUP_NAME != '' && inputs.existing_webapp_url == '' && (inputs.trigger_type != 'workflow_dispatch' || inputs.cleanup_resources)"
+ needs: [docker-build, deploy, e2e-test]
+ uses: ./.github/workflows/job-cleanup-deployment.yml
+ with:
+ runner_os: ${{ inputs.runner_os }}
+ trigger_type: ${{ inputs.trigger_type }}
+ cleanup_resources: ${{ inputs.cleanup_resources }}
+ existing_webapp_url: ${{ inputs.existing_webapp_url }}
+ RESOURCE_GROUP_NAME: ${{ needs.deploy.outputs.RESOURCE_GROUP_NAME }}
+ AZURE_LOCATION: ${{ needs.deploy.outputs.AZURE_LOCATION }}
+ AZURE_ENV_OPENAI_LOCATION: ${{ needs.deploy.outputs.AZURE_ENV_OPENAI_LOCATION }}
+ ENV_NAME: ${{ needs.deploy.outputs.ENV_NAME }}
+ IMAGE_TAG: ${{ needs.deploy.outputs.IMAGE_TAG }}
+ secrets: inherit
diff --git a/.github/workflows/deploy-windows.yml b/.github/workflows/deploy-windows.yml
new file mode 100644
index 00000000..5ac5f7c2
--- /dev/null
+++ b/.github/workflows/deploy-windows.yml
@@ -0,0 +1,92 @@
+name: Deploy-Test-Cleanup (v2) Windows
+on:
+ workflow_dispatch:
+ inputs:
+ azure_location:
+ description: 'Azure Location For Deployment'
+ required: false
+ default: 'australiaeast'
+ type: choice
+ options:
+ - 'australiaeast'
+ - 'centralus'
+ - 'eastasia'
+ - 'eastus2'
+ - 'japaneast'
+ - 'northeurope'
+ - 'southeastasia'
+ - 'uksouth'
+ resource_group_name:
+ description: 'Resource Group Name (Optional)'
+ required: false
+ default: ''
+ type: string
+
+ waf_enabled:
+ description: 'Enable WAF'
+ required: false
+ default: false
+ type: boolean
+ EXP:
+ description: 'Enable EXP'
+ required: false
+ default: false
+ type: boolean
+ build_docker_image:
+ description: 'Build & Push Docker Image (Optional)'
+ required: false
+ default: false
+ type: boolean
+
+ cleanup_resources:
+ description: 'Cleanup Deployed Resources'
+ required: false
+ default: false
+ type: boolean
+
+ run_e2e_tests:
+ description: 'Run End-to-End Tests'
+ required: false
+ default: 'GoldenPath-Testing'
+ type: choice
+ options:
+ - 'GoldenPath-Testing'
+ - 'Smoke-Testing'
+ - 'None'
+
+ AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID:
+ description: 'Log Analytics Workspace ID (Optional)'
+ required: false
+ default: ''
+ type: string
+ AZURE_EXISTING_AI_PROJECT_RESOURCE_ID:
+ description: 'AI Project Resource ID (Optional)'
+ required: false
+ default: ''
+ type: string
+ existing_webapp_url:
+ description: 'Existing Container WebApp URL (Skips Deployment)'
+ required: false
+ default: ''
+ type: string
+
+ # schedule:
+ # - cron: '0 5,17 * * *' # Runs at 5:00 AM and 5:00 PM GMT
+
+jobs:
+ Run:
+ uses: ./.github/workflows/deploy-orchestrator.yml
+ with:
+ runner_os: windows-latest
+ azure_location: ${{ github.event.inputs.azure_location || 'australiaeast' }}
+ resource_group_name: ${{ github.event.inputs.resource_group_name || '' }}
+ waf_enabled: ${{ github.event.inputs.waf_enabled == 'true' }}
+ EXP: ${{ github.event.inputs.EXP == 'true' }}
+ build_docker_image: ${{ github.event.inputs.build_docker_image == 'true' }}
+ cleanup_resources: ${{ github.event.inputs.cleanup_resources == 'true' }}
+ run_e2e_tests: ${{ github.event.inputs.run_e2e_tests || 'GoldenPath-Testing' }}
+ AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID: ${{ github.event.inputs.AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID || '' }}
+ AZURE_EXISTING_AI_PROJECT_RESOURCE_ID: ${{ github.event.inputs.AZURE_EXISTING_AI_PROJECT_RESOURCE_ID || '' }}
+ existing_webapp_url: ${{ github.event.inputs.existing_webapp_url || '' }}
+ trigger_type: ${{ github.event_name }}
+ secrets: inherit
diff --git a/.github/workflows/job-cleanup-deployment.yml b/.github/workflows/job-cleanup-deployment.yml
new file mode 100644
index 00000000..6b920a4e
--- /dev/null
+++ b/.github/workflows/job-cleanup-deployment.yml
@@ -0,0 +1,114 @@
+name: Cleanup Deployment Job
+on:
+ workflow_call:
+ inputs:
+ runner_os:
+ description: 'Runner OS (ubuntu-latest or windows-latest)'
+ required: true
+ type: string
+ trigger_type:
+ description: 'Trigger type (workflow_dispatch, pull_request, schedule)'
+ required: true
+ type: string
+ cleanup_resources:
+ description: 'Cleanup Deployed Resources'
+ required: false
+ default: false
+ type: boolean
+ existing_webapp_url:
+ description: 'Existing Container WebApp URL (Skips Deployment)'
+ required: false
+ default: ''
+ type: string
+ RESOURCE_GROUP_NAME:
+ description: 'Resource Group Name to cleanup'
+ required: true
+ type: string
+ AZURE_LOCATION:
+ description: 'Azure Location'
+ required: true
+ type: string
+ AZURE_ENV_OPENAI_LOCATION:
+ description: 'Azure OpenAI Location'
+ required: true
+ type: string
+ ENV_NAME:
+ description: 'Environment Name'
+ required: true
+ type: string
+ IMAGE_TAG:
+ description: 'Docker Image Tag'
+ required: true
+ type: string
+
+jobs:
+ cleanup-deployment:
+ runs-on: ${{ inputs.runner_os }}
+ continue-on-error: true
+ env:
+ RESOURCE_GROUP_NAME: ${{ inputs.RESOURCE_GROUP_NAME }}
+ AZURE_LOCATION: ${{ inputs.AZURE_LOCATION }}
+ AZURE_ENV_OPENAI_LOCATION: ${{ inputs.AZURE_ENV_OPENAI_LOCATION }}
+ ENV_NAME: ${{ inputs.ENV_NAME }}
+ IMAGE_TAG: ${{ inputs.IMAGE_TAG }}
+ steps:
+ - name: Setup Azure CLI
+ shell: bash
+ run: |
+ if [[ "${{ runner.os }}" == "Linux" ]]; then
+ curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash
+ fi
+ az --version
+
+ - name: Login to Azure
+ shell: bash
+ run: |
+ az login --service-principal -u ${{ secrets.AZURE_CLIENT_ID }} -p ${{ secrets.AZURE_CLIENT_SECRET }} --tenant ${{ secrets.AZURE_TENANT_ID }}
+ az account set --subscription ${{ secrets.AZURE_SUBSCRIPTION_ID }}
+
+ - name: Delete Resource Group (Optimized Cleanup)
+ id: delete_rg
+ shell: bash
+ run: |
+ set -e
+ echo "ποΈ Starting optimized resource cleanup..."
+ echo "Deleting resource group: ${{ env.RESOURCE_GROUP_NAME }}"
+
+ az group delete \
+ --name "${{ env.RESOURCE_GROUP_NAME }}" \
+ --yes \
+ --no-wait
+
+ echo "β
Resource group deletion initiated (running asynchronously)"
+ echo "Note: Resources will be cleaned up in the background"
+
+ - name: Logout from Azure
+ if: always()
+ shell: bash
+ run: |
+ azd auth logout || true
+ az logout || echo "Warning: Failed to logout from Azure CLI"
+ echo "Logged out from Azure."
+
+ - name: Generate Cleanup Job Summary
+ if: always()
+ shell: bash
+ run: |
+ echo "## π§Ή Cleanup Job Summary" >> $GITHUB_STEP_SUMMARY
+ echo "" >> $GITHUB_STEP_SUMMARY
+ echo "| Field | Value |" >> $GITHUB_STEP_SUMMARY
+ echo "|-------|--------|" >> $GITHUB_STEP_SUMMARY
+ echo "| **Resource Group deletion Status** | ${{ steps.delete_rg.outcome == 'success' && 'β
Initiated' || 'β Failed' }} |" >> $GITHUB_STEP_SUMMARY
+ echo "| **Resource Group** | \`${{ env.RESOURCE_GROUP_NAME }}\` |" >> $GITHUB_STEP_SUMMARY
+ echo "" >> $GITHUB_STEP_SUMMARY
+ if [[ "${{ steps.delete_rg.outcome }}" == "success" ]]; then
+ echo "### β
Cleanup Details" >> $GITHUB_STEP_SUMMARY
+ echo "- Successfully initiated deletion for Resource Group \`${{ env.RESOURCE_GROUP_NAME }}\`" >> $GITHUB_STEP_SUMMARY
+ echo "" >> $GITHUB_STEP_SUMMARY
+ else
+ echo "### β Cleanup Failed" >> $GITHUB_STEP_SUMMARY
+ echo "- Cleanup process encountered an error" >> $GITHUB_STEP_SUMMARY
+ echo "- Manual cleanup may be required for:" >> $GITHUB_STEP_SUMMARY
+ echo " - Resource Group: \`${{ env.RESOURCE_GROUP_NAME }}\`" >> $GITHUB_STEP_SUMMARY
+ echo "- Check the cleanup-deployment job logs for detailed error information" >> $GITHUB_STEP_SUMMARY
+ fi
diff --git a/.github/workflows/job-deploy-linux.yml b/.github/workflows/job-deploy-linux.yml
new file mode 100644
index 00000000..4bd437b1
--- /dev/null
+++ b/.github/workflows/job-deploy-linux.yml
@@ -0,0 +1,180 @@
+name: Deploy Steps - Linux
+
+on:
+ workflow_call:
+ inputs:
+ ENV_NAME:
+ required: true
+ type: string
+ AZURE_ENV_OPENAI_LOCATION:
+ required: true
+ type: string
+ AZURE_LOCATION:
+ required: true
+ type: string
+ RESOURCE_GROUP_NAME:
+ required: true
+ type: string
+ IMAGE_TAG:
+ required: true
+ type: string
+ BUILD_DOCKER_IMAGE:
+ required: true
+ type: string
+ EXP:
+ required: true
+ type: string
+ WAF_ENABLED:
+ required: false
+ type: string
+ default: 'false'
+ AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID:
+ required: false
+ type: string
+ AZURE_EXISTING_AI_PROJECT_RESOURCE_ID:
+ required: false
+ type: string
+ outputs:
+ CONTAINER_WEB_APPURL:
+ description: "Container Web App URL"
+ value: ${{ jobs.deploy-linux.outputs.WEBAPP_URL }}
+
+jobs:
+ deploy-linux:
+ runs-on: ubuntu-latest
+ env:
+ AZURE_DEV_COLLECT_TELEMETRY: ${{ vars.AZURE_DEV_COLLECT_TELEMETRY }}
+ outputs:
+ WEBAPP_URL: ${{ steps.get_output_linux.outputs.WEBAPP_URL }}
+ steps:
+ - name: Checkout Code
+ uses: actions/checkout@v4
+
+ - name: Configure Parameters Based on WAF Setting
+ shell: bash
+ run: |
+ if [[ "${{ inputs.WAF_ENABLED }}" == "true" ]]; then
+ cp infra/main.waf.parameters.json infra/main.parameters.json
+ echo "β
Successfully copied WAF parameters to main parameters file"
+ else
+ echo "π§ Configuring Non-WAF deployment - using default main.parameters.json..."
+ fi
+
+ - name: Setup Azure CLI
+ shell: bash
+ run: |
+ curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash
+
+ - name: Setup Azure Developer CLI (Linux)
+ if: runner.os == 'Linux'
+ shell: bash
+ run: |
+ curl -fsSL https://aka.ms/install-azd.sh | sudo bash
+ azd version
+
+ - name: Login to AZD
+ id: login-azure
+ shell: bash
+ run: |
+ az login --service-principal -u ${{ secrets.AZURE_CLIENT_ID }} -p ${{ secrets.AZURE_CLIENT_SECRET }} --tenant ${{ secrets.AZURE_TENANT_ID }}
+ az account set --subscription ${{ secrets.AZURE_SUBSCRIPTION_ID }}
+ azd auth login --client-id ${{ secrets.AZURE_CLIENT_ID }} --client-secret ${{ secrets.AZURE_CLIENT_SECRET }} --tenant-id ${{ secrets.AZURE_TENANT_ID }}
+
+ - name: Deploy using azd up and extract values (Linux)
+ id: get_output_linux
+ shell: bash
+ run: |
+ set -e
+
+ echo "Creating environment..."
+ azd env new ${{ inputs.ENV_NAME }} --no-prompt
+ echo "Environment created: ${{ inputs.ENV_NAME }}"
+
+ echo "Setting default subscription..."
+ azd config set defaults.subscription ${{ vars.AZURE_SUBSCRIPTION_ID }}
+
+ # Set additional parameters
+ azd env set AZURE_SUBSCRIPTION_ID="${{ vars.AZURE_SUBSCRIPTION_ID }}"
+ azd env set AZURE_ENV_AI_SERVICE_LOCATION="${{ inputs.AZURE_ENV_OPENAI_LOCATION }}"
+ azd env set AZURE_LOCATION="${{ inputs.AZURE_LOCATION }}"
+ azd env set AZURE_RESOURCE_GROUP="${{ inputs.RESOURCE_GROUP_NAME }}"
+ azd env set AZURE_ENV_IMAGETAG="${{ inputs.IMAGE_TAG }}"
+
+ if [[ "${{ inputs.BUILD_DOCKER_IMAGE }}" == "true" ]]; then
+ ACR_NAME=$(echo "${{ secrets.ACR_TEST_LOGIN_SERVER }}")
+ azd env set AZURE_ENV_ACR_NAME="$ACR_NAME"
+ echo "Set ACR name to: $ACR_NAME"
+ else
+ echo "Skipping ACR name configuration (using existing image)"
+ fi
+
+ if [[ "${{ inputs.EXP }}" == "true" ]]; then
+ echo "β
EXP ENABLED - Setting EXP parameters..."
+
+ if [[ -n "${{ inputs.AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID }}" ]]; then
+ EXP_LOG_ANALYTICS_ID="${{ inputs.AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID }}"
+ else
+ EXP_LOG_ANALYTICS_ID="${{ vars.AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID }}"
+ fi
+
+ if [[ -n "${{ inputs.AZURE_EXISTING_AI_PROJECT_RESOURCE_ID }}" ]]; then
+ EXP_AI_PROJECT_ID="${{ inputs.AZURE_EXISTING_AI_PROJECT_RESOURCE_ID }}"
+ else
+ EXP_AI_PROJECT_ID="${{ vars.AZURE_EXISTING_AI_PROJECT_RESOURCE_ID }}"
+ fi
+
+ echo "AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID: $EXP_LOG_ANALYTICS_ID"
+ echo "AZURE_EXISTING_AI_PROJECT_RESOURCE_ID: $EXP_AI_PROJECT_ID"
+ azd env set AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID="$EXP_LOG_ANALYTICS_ID"
+ azd env set AZURE_EXISTING_AI_PROJECT_RESOURCE_ID="$EXP_AI_PROJECT_ID"
+ else
+ echo "β EXP DISABLED - Skipping EXP parameters"
+ fi
+
+ azd up --no-prompt
+ echo "β
Deployment succeeded"
+
+ WEBAPP_URL=$(azd env get-value WEB_APP_URL)
+ echo "WEBAPP_URL=${WEBAPP_URL}" >> $GITHUB_ENV
+ echo "WEBAPP_URL=${WEBAPP_URL}" >> $GITHUB_OUTPUT
+
+ - name: Assign Contributor role to Service Principal
+ if: always()
+ run: |
+ echo "Assigning Contributor role to SPN for RG: ${{ inputs.RESOURCE_GROUP_NAME }}"
+ az role assignment create \
+ --assignee ${{ secrets.AZURE_CLIENT_ID }} \
+ --role "Contributor" \
+ --scope /subscriptions/${{ secrets.AZURE_SUBSCRIPTION_ID }}/resourceGroups/${{ inputs.RESOURCE_GROUP_NAME }}
+
+ - name: Generate Deployment Summary
+ if: always()
+ shell: bash
+ run: |
+ echo "## π Deploy Job Summary (Linux)" >> $GITHUB_STEP_SUMMARY
+ echo "" >> $GITHUB_STEP_SUMMARY
+ echo "| Field | Value |" >> $GITHUB_STEP_SUMMARY
+ echo "|-------|--------|" >> $GITHUB_STEP_SUMMARY
+ echo "| **Job Status** | ${{ job.status == 'success' && 'β
Success' || 'β Failed' }} |" >> $GITHUB_STEP_SUMMARY
+ echo "| **Resource Group** | \`${{ inputs.RESOURCE_GROUP_NAME }}\` |" >> $GITHUB_STEP_SUMMARY
+ echo "| **Configuration Type** | \`${{ inputs.WAF_ENABLED == 'true' && inputs.EXP == 'true' && 'WAF + EXP' || inputs.WAF_ENABLED == 'true' && inputs.EXP != 'true' && 'WAF + Non-EXP' || inputs.WAF_ENABLED != 'true' && inputs.EXP == 'true' && 'Non-WAF + EXP' || 'Non-WAF + Non-EXP' }}\` |" >> $GITHUB_STEP_SUMMARY
+ echo "| **Azure Region (Infrastructure)** | \`${{ inputs.AZURE_LOCATION }}\` |" >> $GITHUB_STEP_SUMMARY
+ echo "| **Azure OpenAI Region** | \`${{ inputs.AZURE_ENV_OPENAI_LOCATION }}\` |" >> $GITHUB_STEP_SUMMARY
+ echo "| **Docker Image Tag** | \`${{ inputs.IMAGE_TAG }}\` |" >> $GITHUB_STEP_SUMMARY
+ echo "" >> $GITHUB_STEP_SUMMARY
+ if [[ "${{ job.status }}" == "success" ]]; then
+ echo "### β
Deployment Details" >> $GITHUB_STEP_SUMMARY
+ echo "- **Container Web App URL**: [${{ steps.get_output_linux.outputs.WEBAPP_URL }}](${{ steps.get_output_linux.outputs.WEBAPP_URL }})" >> $GITHUB_STEP_SUMMARY
+ echo "- Successfully deployed to Azure with all resources configured" >> $GITHUB_STEP_SUMMARY
+ else
+ echo "### β Deployment Failed" >> $GITHUB_STEP_SUMMARY
+ echo "- Deployment process encountered an error" >> $GITHUB_STEP_SUMMARY
+ echo "- Check the deployment steps above for detailed error information" >> $GITHUB_STEP_SUMMARY
+ fi
+
+ - name: Logout from Azure
+ if: always()
+ shell: bash
+ run: |
+ az logout || true
+ echo "Logged out from Azure."
diff --git a/.github/workflows/job-deploy-windows.yml b/.github/workflows/job-deploy-windows.yml
new file mode 100644
index 00000000..fc016103
--- /dev/null
+++ b/.github/workflows/job-deploy-windows.yml
@@ -0,0 +1,181 @@
+name: Deploy Steps - Windows
+
+on:
+ workflow_call:
+ inputs:
+ ENV_NAME:
+ required: true
+ type: string
+ AZURE_ENV_OPENAI_LOCATION:
+ required: true
+ type: string
+ AZURE_LOCATION:
+ required: true
+ type: string
+ RESOURCE_GROUP_NAME:
+ required: true
+ type: string
+ IMAGE_TAG:
+ required: true
+ type: string
+ BUILD_DOCKER_IMAGE:
+ required: true
+ type: string
+ EXP:
+ required: true
+ type: string
+ WAF_ENABLED:
+ required: false
+ type: string
+ default: 'false'
+ AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID:
+ required: false
+ type: string
+ AZURE_EXISTING_AI_PROJECT_RESOURCE_ID:
+ required: false
+ type: string
+ outputs:
+ CONTAINER_WEB_APPURL:
+ description: "Container Web App URL"
+ value: ${{ jobs.deploy-windows.outputs.WEBAPP_URL }}
+
+jobs:
+ deploy-windows:
+ runs-on: windows-latest
+ env:
+ AZURE_DEV_COLLECT_TELEMETRY: ${{ vars.AZURE_DEV_COLLECT_TELEMETRY }}
+ outputs:
+ WEBAPP_URL: ${{ steps.get_output_windows.outputs.WEBAPP_URL }}
+ steps:
+ - name: Checkout Code
+ uses: actions/checkout@v4
+
+ - name: Configure Parameters Based on WAF Setting
+ shell: bash
+ run: |
+ if [[ "${{ inputs.WAF_ENABLED }}" == "true" ]]; then
+ cp infra/main.waf.parameters.json infra/main.parameters.json
+ echo "β
Successfully copied WAF parameters to main parameters file"
+ else
+ echo "π§ Configuring Non-WAF deployment - using default main.parameters.json..."
+ fi
+
+ - name: Setup Azure Developer CLI (Windows)
+ uses: Azure/setup-azd@v2
+
+ - name: Login to AZD
+ id: login-azure
+ shell: bash
+ run: |
+ az login --service-principal -u ${{ secrets.AZURE_CLIENT_ID }} -p ${{ secrets.AZURE_CLIENT_SECRET }} --tenant ${{ secrets.AZURE_TENANT_ID }}
+ az account set --subscription ${{ secrets.AZURE_SUBSCRIPTION_ID }}
+ azd auth login --client-id ${{ secrets.AZURE_CLIENT_ID }} --client-secret ${{ secrets.AZURE_CLIENT_SECRET }} --tenant-id ${{ secrets.AZURE_TENANT_ID }}
+
+
+ - name: Deploy using azd up and extract values (Windows)
+ id: get_output_windows
+ shell: pwsh
+ run: |
+ $ErrorActionPreference = "Stop"
+ Write-Host "Starting azd deployment..."
+ Write-Host "EXP: ${{ inputs.EXP }}"
+ Write-Host "Using Docker Image Tag: ${{ inputs.IMAGE_TAG }}"
+
+ Write-Host "Creating environment..."
+ azd env new ${{ inputs.ENV_NAME }} --no-prompt
+ Write-Host "Environment created: ${{ inputs.ENV_NAME }}"
+
+ Write-Host "Setting default subscription..."
+ azd config set defaults.subscription ${{ vars.AZURE_SUBSCRIPTION_ID }}
+
+ # Set additional parameters
+ azd env set AZURE_SUBSCRIPTION_ID="${{ vars.AZURE_SUBSCRIPTION_ID }}"
+ azd env set AZURE_ENV_AI_SERVICE_LOCATION="${{ inputs.AZURE_ENV_OPENAI_LOCATION }}"
+ azd env set AZURE_LOCATION="${{ inputs.AZURE_LOCATION }}"
+ azd env set AZURE_RESOURCE_GROUP="${{ inputs.RESOURCE_GROUP_NAME }}"
+ azd env set AZURE_ENV_IMAGETAG="${{ inputs.IMAGE_TAG }}"
+
+ # Set ACR name only when building Docker image
+ if ("${{ inputs.BUILD_DOCKER_IMAGE }}" -eq "true") {
+ $ACR_NAME = "${{ secrets.ACR_TEST_LOGIN_SERVER }}"
+ azd env set AZURE_ENV_ACR_NAME="$ACR_NAME"
+ Write-Host "Set ACR name to: $ACR_NAME"
+ } else {
+ Write-Host "Skipping ACR name configuration (using existing image)"
+ }
+
+ if ("${{ inputs.EXP }}" -eq "true") {
+ Write-Host "EXP ENABLED β
- Setting EXP parameters..."
+
+ # Set EXP variables dynamically
+ if ("${{ inputs.AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID }}" -ne "") {
+ $EXP_LOG_ANALYTICS_ID = "${{ inputs.AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID }}"
+ } else {
+ $EXP_LOG_ANALYTICS_ID = "${{ vars.AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID }}"
+ }
+
+ if ("${{ inputs.AZURE_EXISTING_AI_PROJECT_RESOURCE_ID }}" -ne "") {
+ $EXP_AI_PROJECT_ID = "${{ inputs.AZURE_EXISTING_AI_PROJECT_RESOURCE_ID }}"
+ } else {
+ $EXP_AI_PROJECT_ID = "${{ vars.AZURE_EXISTING_AI_PROJECT_RESOURCE_ID }}"
+ }
+
+ Write-Host "AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID: $EXP_LOG_ANALYTICS_ID"
+ Write-Host "AZURE_EXISTING_AI_PROJECT_RESOURCE_ID: $EXP_AI_PROJECT_ID"
+ azd env set AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID="$EXP_LOG_ANALYTICS_ID"
+ azd env set AZURE_EXISTING_AI_PROJECT_RESOURCE_ID="$EXP_AI_PROJECT_ID"
+ } else {
+ Write-Host "EXP DISABLED - Skipping EXP parameters"
+ }
+
+ # Deploy using azd up
+ azd up --no-prompt
+ Write-Host "β
Deployment succeeded."
+
+ $WEBAPP_URL = azd env get-value WEB_APP_URL
+ "WEBAPP_URL=$WEBAPP_URL" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
+ "WEBAPP_URL=$WEBAPP_URL" | Out-File -FilePath $env:GITHUB_OUTPUT -Encoding utf8 -Append
+
+ - name: Assign Contributor role to Service Principal
+ if: always()
+ shell: bash
+ run: |
+ az account set --subscription ${{ secrets.AZURE_SUBSCRIPTION_ID }}
+ echo "Assigning Contributor role to SPN for RG: ${{ inputs.RESOURCE_GROUP_NAME }}"
+ az role assignment create \
+ --assignee ${{ secrets.AZURE_CLIENT_ID }} \
+ --role "Contributor" \
+ --scope /subscriptions/${{ secrets.AZURE_SUBSCRIPTION_ID }}/resourceGroups/${{ inputs.RESOURCE_GROUP_NAME }}
+
+ - name: Generate Deployment Summary
+ if: always()
+ shell: bash
+ run: |
+ echo "## π Deploy Job Summary (Windows)" >> $GITHUB_STEP_SUMMARY
+ echo "" >> $GITHUB_STEP_SUMMARY
+ echo "| Field | Value |" >> $GITHUB_STEP_SUMMARY
+ echo "|-------|--------|" >> $GITHUB_STEP_SUMMARY
+ echo "| **Job Status** | ${{ job.status == 'success' && 'β
Success' || 'β Failed' }} |" >> $GITHUB_STEP_SUMMARY
+ echo "| **Configuration Type** | \`${{ inputs.WAF_ENABLED == 'true' && inputs.EXP == 'true' && 'WAF + EXP' || inputs.WAF_ENABLED == 'true' && inputs.EXP != 'true' && 'WAF + Non-EXP' || inputs.WAF_ENABLED != 'true' && inputs.EXP == 'true' && 'Non-WAF + EXP' || 'Non-WAF + Non-EXP' }}\` |" >> $GITHUB_STEP_SUMMARY
+ echo "| **Resource Group** | \`${{ inputs.RESOURCE_GROUP_NAME }}\` |" >> $GITHUB_STEP_SUMMARY
+ echo "| **Azure Region (Infrastructure)** | \`${{ inputs.AZURE_LOCATION }}\` |" >> $GITHUB_STEP_SUMMARY
+ echo "| **Azure OpenAI Region** | \`${{ inputs.AZURE_ENV_OPENAI_LOCATION }}\` |" >> $GITHUB_STEP_SUMMARY
+ echo "| **Docker Image Tag** | \`${{ inputs.IMAGE_TAG }}\` |" >> $GITHUB_STEP_SUMMARY
+ echo "" >> $GITHUB_STEP_SUMMARY
+ if [ "${{ job.status }}" == "success" ]; then
+ echo "### β
Deployment Details" >> $GITHUB_STEP_SUMMARY
+ echo "- **Container Web App URL**: [${{ steps.get_output_windows.outputs.WEBAPP_URL }}](${{ steps.get_output_windows.outputs.WEBAPP_URL }})" >> $GITHUB_STEP_SUMMARY
+ echo "- Successfully deployed to Azure with all resources configured" >> $GITHUB_STEP_SUMMARY
+ echo "- Schemas registered and sample data uploaded successfully" >> $GITHUB_STEP_SUMMARY
+ else
+ echo "### β Deployment Failed" >> $GITHUB_STEP_SUMMARY
+ echo "- Deployment process encountered an error" >> $GITHUB_STEP_SUMMARY
+ echo "- Check the deployment steps above for detailed error information" >> $GITHUB_STEP_SUMMARY
+ fi
+
+ - name: Logout from Azure
+ if: always()
+ shell: bash
+ run: |
+ az logout || true
+ echo "Logged out from Azure."
diff --git a/.github/workflows/job-deploy.yml b/.github/workflows/job-deploy.yml
new file mode 100644
index 00000000..6ac84e16
--- /dev/null
+++ b/.github/workflows/job-deploy.yml
@@ -0,0 +1,355 @@
+name: Deploy Job
+
+on:
+ workflow_call:
+ inputs:
+ trigger_type:
+ description: 'Trigger type (workflow_dispatch, pull_request, schedule)'
+ required: true
+ type: string
+ runner_os:
+ description: 'Runner OS (ubuntu-latest or windows-latest)'
+ required: true
+ type: string
+ azure_location:
+ description: 'Azure Location For Deployment'
+ required: false
+ default: 'australiaeast'
+ type: string
+ resource_group_name:
+ description: 'Resource Group Name (Optional)'
+ required: false
+ default: ''
+ type: string
+ waf_enabled:
+ description: 'Enable WAF'
+ required: false
+ default: false
+ type: boolean
+ EXP:
+ description: 'Enable EXP'
+ required: false
+ default: false
+ type: boolean
+ build_docker_image:
+ description: 'Build And Push Docker Image (Optional)'
+ required: false
+ default: false
+ type: boolean
+ cleanup_resources:
+ description: 'Cleanup Deployed Resources'
+ required: false
+ default: false
+ type: boolean
+ run_e2e_tests:
+ description: 'Run End-to-End Tests'
+ required: false
+ default: 'GoldenPath-Testing'
+ type: string
+ existing_webapp_url:
+ description: 'Existing Container WebApp URL (Skips Deployment)'
+ required: false
+ default: ''
+ type: string
+ AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID:
+ description: 'Log Analytics Workspace ID (Optional)'
+ required: false
+ default: ''
+ type: string
+ AZURE_EXISTING_AI_PROJECT_RESOURCE_ID:
+ description: 'AI Project Resource ID (Optional)'
+ required: false
+ default: ''
+ type: string
+ docker_image_tag:
+ description: 'Docker Image Tag from build job'
+ required: false
+ default: ''
+ type: string
+ outputs:
+ RESOURCE_GROUP_NAME:
+ description: "Resource Group Name"
+ value: ${{ jobs.azure-setup.outputs.RESOURCE_GROUP_NAME }}
+ CONTAINER_WEB_APPURL:
+ description: "Container Web App URL"
+ value: ${{ jobs.deploy-linux.outputs.CONTAINER_WEB_APPURL || jobs.deploy-windows.outputs.CONTAINER_WEB_APPURL }}
+ ENV_NAME:
+ description: "Environment Name"
+ value: ${{ jobs.azure-setup.outputs.ENV_NAME }}
+ AZURE_LOCATION:
+ description: "Azure Location"
+ value: ${{ jobs.azure-setup.outputs.AZURE_LOCATION }}
+ AZURE_ENV_OPENAI_LOCATION:
+ description: "Azure OpenAI Location"
+ value: ${{ jobs.azure-setup.outputs.AZURE_ENV_OPENAI_LOCATION }}
+ IMAGE_TAG:
+ description: "Docker Image Tag Used"
+ value: ${{ jobs.azure-setup.outputs.IMAGE_TAG }}
+ QUOTA_FAILED:
+ description: "Quota Check Failed Flag"
+ value: ${{ jobs.azure-setup.outputs.QUOTA_FAILED }}
+
+env:
+ GPT_MIN_CAPACITY: 150
+ BRANCH_NAME: ${{ github.event.workflow_run.head_branch || github.head_ref || github.ref_name }}
+ WAF_ENABLED: ${{ inputs.trigger_type == 'workflow_dispatch' && (inputs.waf_enabled || false) || false }}
+ EXP: ${{ inputs.trigger_type == 'workflow_dispatch' && (inputs.EXP || false) || false }}
+ CLEANUP_RESOURCES: ${{ inputs.trigger_type != 'workflow_dispatch' || inputs.cleanup_resources }}
+ RUN_E2E_TESTS: ${{ inputs.trigger_type == 'workflow_dispatch' && (inputs.run_e2e_tests || 'GoldenPath-Testing') || 'GoldenPath-Testing' }}
+ BUILD_DOCKER_IMAGE: ${{ inputs.trigger_type == 'workflow_dispatch' && (inputs.build_docker_image || false) || false }}
+
+jobs:
+ azure-setup:
+ name: Azure Setup
+ if: inputs.trigger_type != 'workflow_dispatch' || inputs.existing_webapp_url == '' || inputs.existing_webapp_url == null
+ runs-on: ubuntu-latest
+ outputs:
+ RESOURCE_GROUP_NAME: ${{ steps.check_create_rg.outputs.RESOURCE_GROUP_NAME }}
+ ENV_NAME: ${{ steps.generate_env_name.outputs.ENV_NAME }}
+ AZURE_LOCATION: ${{ steps.set_region.outputs.AZURE_LOCATION }}
+ AZURE_ENV_OPENAI_LOCATION: ${{ steps.set_region.outputs.AZURE_ENV_OPENAI_LOCATION }}
+ IMAGE_TAG: ${{ steps.determine_image_tag.outputs.IMAGE_TAG }}
+ QUOTA_FAILED: ${{ steps.quota_failure_output.outputs.QUOTA_FAILED }}
+
+ steps:
+ - name: Validate and Auto-Configure EXP
+ shell: bash
+ run: |
+ echo "π Validating EXP configuration..."
+
+ if [[ "${{ inputs.EXP }}" != "true" ]]; then
+ if [[ -n "${{ inputs.AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID }}" ]] || [[ -n "${{ inputs.AZURE_EXISTING_AI_PROJECT_RESOURCE_ID }}" ]]; then
+ echo "π§ AUTO-ENABLING EXP: EXP parameter values were provided but EXP was not explicitly enabled."
+ echo ""
+ echo "You provided values for:"
+ [[ -n "${{ inputs.AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID }}" ]] && echo " - Azure Log Analytics Workspace ID: '${{ inputs.AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID }}'"
+ [[ -n "${{ inputs.AZURE_EXISTING_AI_PROJECT_RESOURCE_ID }}" ]] && echo " - Azure AI Project Resource ID: '${{ inputs.AZURE_EXISTING_AI_PROJECT_RESOURCE_ID }}'"
+ echo ""
+ echo "β
Automatically enabling EXP to use these values."
+ echo "EXP=true" >> $GITHUB_ENV
+ echo "π EXP has been automatically enabled for this deployment."
+ fi
+ fi
+
+ - name: Checkout Code
+ uses: actions/checkout@v4
+
+ - name: Login to Azure
+ shell: bash
+ run: |
+ az login --service-principal -u ${{ secrets.AZURE_CLIENT_ID }} -p ${{ secrets.AZURE_CLIENT_SECRET }} --tenant ${{ secrets.AZURE_TENANT_ID }}
+ az account set --subscription ${{ secrets.AZURE_SUBSCRIPTION_ID }}
+
+ - name: Run Quota Check
+ id: quota-check
+ run: |
+ export AZURE_CLIENT_ID=${{ secrets.AZURE_CLIENT_ID }}
+ export AZURE_TENANT_ID=${{ secrets.AZURE_TENANT_ID }}
+ export AZURE_CLIENT_SECRET=${{ secrets.AZURE_CLIENT_SECRET }}
+ export AZURE_SUBSCRIPTION_ID="${{ secrets.AZURE_SUBSCRIPTION_ID }}"
+ export AZURE_REGIONS="${{ vars.AZURE_REGIONS }}"
+ export GPT_MIN_CAPACITY=${{ env.GPT_MIN_CAPACITY }}
+
+ chmod +x scripts/checkquota.sh
+ if ! scripts/checkquota.sh; then
+ # If quota check fails due to insufficient quota, set the flag
+ if grep -q "No region with sufficient quota found" scripts/checkquota.sh; then
+ echo "QUOTA_FAILED=true" >> $GITHUB_ENV
+ fi
+ exit 1 # Fail the pipeline if any other failure occurs
+ fi
+
+ - name: Set Quota Failure Output
+ id: quota_failure_output
+ if: env.QUOTA_FAILED == 'true'
+ shell: bash
+ run: |
+ echo "QUOTA_FAILED=true" >> $GITHUB_OUTPUT
+ echo "Quota check failed - will notify via separate notification job"
+
+ - name: Fail Pipeline if Quota Check Fails
+ if: env.QUOTA_FAILED == 'true'
+ shell: bash
+ run: exit 1
+
+ - name: Set Deployment Region
+ id: set_region
+ shell: bash
+ run: |
+ echo "Selected Region from Quota Check: $VALID_REGION"
+ echo "AZURE_ENV_OPENAI_LOCATION=$VALID_REGION" >> $GITHUB_ENV
+ echo "AZURE_ENV_OPENAI_LOCATION=$VALID_REGION" >> $GITHUB_OUTPUT
+
+ if [[ "${{ inputs.trigger_type }}" == "workflow_dispatch" && -n "${{ inputs.azure_location }}" ]]; then
+ USER_SELECTED_LOCATION="${{ inputs.azure_location }}"
+ echo "Using user-selected Azure location: $USER_SELECTED_LOCATION"
+ echo "AZURE_LOCATION=$USER_SELECTED_LOCATION" >> $GITHUB_ENV
+ echo "AZURE_LOCATION=$USER_SELECTED_LOCATION" >> $GITHUB_OUTPUT
+ else
+ echo "Using location from quota check for automatic triggers: $VALID_REGION"
+ echo "AZURE_LOCATION=$VALID_REGION" >> $GITHUB_ENV
+ echo "AZURE_LOCATION=$VALID_REGION" >> $GITHUB_OUTPUT
+ fi
+
+ - name: Generate Resource Group Name
+ id: generate_rg_name
+ shell: bash
+ run: |
+ # Check if a resource group name was provided as input
+ if [[ -n "${{ inputs.resource_group_name }}" ]]; then
+ echo "Using provided Resource Group name: ${{ inputs.resource_group_name }}"
+ echo "RESOURCE_GROUP_NAME=${{ inputs.resource_group_name }}" >> $GITHUB_ENV
+ else
+ echo "Generating a unique resource group name..."
+ ACCL_NAME="codmodv2" # Account name as specified
+ SHORT_UUID=$(uuidgen | cut -d'-' -f1)
+ UNIQUE_RG_NAME="arg-${ACCL_NAME}-${SHORT_UUID}"
+ echo "RESOURCE_GROUP_NAME=${UNIQUE_RG_NAME}" >> $GITHUB_ENV
+ echo "Generated RESOURCE_GROUP_NAME: ${UNIQUE_RG_NAME}"
+ fi
+
+ - name: Install Bicep CLI
+ shell: bash
+ run: az bicep install
+
+ - name: Check and Create Resource Group
+ id: check_create_rg
+ shell: bash
+ run: |
+ set -e
+ echo "π Checking if resource group '$RESOURCE_GROUP_NAME' exists..."
+ rg_exists=$(az group exists --name $RESOURCE_GROUP_NAME)
+ if [ "$rg_exists" = "false" ]; then
+ echo "π¦ Resource group does not exist. Creating new resource group '$RESOURCE_GROUP_NAME' in location '$AZURE_LOCATION'..."
+ az group create --name $RESOURCE_GROUP_NAME --location $AZURE_LOCATION || { echo "β Error creating resource group"; exit 1; }
+ echo "β
Resource group '$RESOURCE_GROUP_NAME' created successfully."
+ else
+ echo "β
Resource group '$RESOURCE_GROUP_NAME' already exists. Deploying to existing resource group."
+ fi
+ echo "RESOURCE_GROUP_NAME=$RESOURCE_GROUP_NAME" >> $GITHUB_OUTPUT
+ echo "RESOURCE_GROUP_NAME=$RESOURCE_GROUP_NAME" >> $GITHUB_ENV
+
+ - name: Generate Unique Solution Prefix
+ id: generate_solution_prefix
+ shell: bash
+ run: |
+ set -e
+ COMMON_PART="psldg"
+ TIMESTAMP=$(date +%s)
+ UPDATED_TIMESTAMP=$(echo $TIMESTAMP | tail -c 6)
+ UNIQUE_SOLUTION_PREFIX="${COMMON_PART}${UPDATED_TIMESTAMP}"
+ echo "SOLUTION_PREFIX=${UNIQUE_SOLUTION_PREFIX}" >> $GITHUB_ENV
+ echo "Generated SOLUTION_PREFIX: ${UNIQUE_SOLUTION_PREFIX}"
+
+ - name: Determine Docker Image Tag
+ id: determine_image_tag
+ shell: bash
+ run: |
+ if [[ "${{ env.BUILD_DOCKER_IMAGE }}" == "true" ]]; then
+ if [[ -n "${{ inputs.docker_image_tag }}" ]]; then
+ IMAGE_TAG="${{ inputs.docker_image_tag }}"
+ echo "π Using Docker image tag from build job: $IMAGE_TAG"
+ else
+ echo "β Docker build job failed or was skipped, but BUILD_DOCKER_IMAGE is true"
+ exit 1
+ fi
+ else
+ echo "π·οΈ Using existing Docker image based on branch..."
+ BRANCH_NAME="${{ env.BRANCH_NAME }}"
+ echo "Current branch: $BRANCH_NAME"
+
+ if [[ "$BRANCH_NAME" == "main" ]]; then
+ IMAGE_TAG="latest"
+ elif [[ "$BRANCH_NAME" == "dev" ]]; then
+ IMAGE_TAG="dev"
+ elif [[ "$BRANCH_NAME" == "demo" ]]; then
+ IMAGE_TAG="demo"
+ else
+ IMAGE_TAG="latest"
+ echo "Using default for branch '$BRANCH_NAME' - image tag: latest"
+ fi
+ echo "Using existing Docker image tag: $IMAGE_TAG"
+ fi
+
+ echo "IMAGE_TAG=$IMAGE_TAG" >> $GITHUB_ENV
+ echo "IMAGE_TAG=$IMAGE_TAG" >> $GITHUB_OUTPUT
+
+ - name: Generate Unique Environment Name
+ id: generate_env_name
+ shell: bash
+ run: |
+ COMMON_PART="pslc"
+ TIMESTAMP=$(date +%s)
+ UPDATED_TIMESTAMP=$(echo $TIMESTAMP | tail -c 6)
+ UNIQUE_ENV_NAME="${COMMON_PART}${UPDATED_TIMESTAMP}"
+ echo "ENV_NAME=${UNIQUE_ENV_NAME}" >> $GITHUB_ENV
+ echo "Generated Environment Name: ${UNIQUE_ENV_NAME}"
+ echo "ENV_NAME=${UNIQUE_ENV_NAME}" >> $GITHUB_OUTPUT
+
+ - name: Display Workflow Configuration to GitHub Summary
+ shell: bash
+ run: |
+ echo "## π Workflow Configuration Summary" >> $GITHUB_STEP_SUMMARY
+ echo "" >> $GITHUB_STEP_SUMMARY
+ echo "| Configuration | Value |" >> $GITHUB_STEP_SUMMARY
+ echo "|---------------|-------|" >> $GITHUB_STEP_SUMMARY
+ echo "| **Branch** | \`${{ env.BRANCH_NAME }}\` |" >> $GITHUB_STEP_SUMMARY
+ echo "| **WAF Enabled** | ${{ env.WAF_ENABLED == 'true' && 'β
Yes' || 'β No' }} |" >> $GITHUB_STEP_SUMMARY
+ echo "| **EXP Enabled** | ${{ env.EXP == 'true' && 'β
Yes' || 'β No' }} |" >> $GITHUB_STEP_SUMMARY
+ echo "| **Run E2E Tests** | \`${{ env.RUN_E2E_TESTS }}\` |" >> $GITHUB_STEP_SUMMARY
+ echo "| **Cleanup Resources** | ${{ env.CLEANUP_RESOURCES == 'true' && 'β
Yes' || 'β No' }} |" >> $GITHUB_STEP_SUMMARY
+ echo "| **Build Docker Image** | ${{ env.BUILD_DOCKER_IMAGE == 'true' && 'β
Yes' || 'β No' }} |" >> $GITHUB_STEP_SUMMARY
+
+ if [[ "${{ inputs.trigger_type }}" == "workflow_dispatch" && -n "${{ inputs.azure_location }}" ]]; then
+ echo "| **Azure Location** | \`${{ inputs.azure_location }}\` (User Selected) |" >> $GITHUB_STEP_SUMMARY
+ fi
+
+ if [[ -n "${{ inputs.resource_group_name }}" ]]; then
+ echo "| **Resource Group** | \`${{ inputs.resource_group_name }}\` (Pre-specified) |" >> $GITHUB_STEP_SUMMARY
+ else
+ echo "| **Resource Group** | \`${{ env.RESOURCE_GROUP_NAME }}\` (Auto-generated) |" >> $GITHUB_STEP_SUMMARY
+ fi
+
+ echo "" >> $GITHUB_STEP_SUMMARY
+
+ if [[ "${{ inputs.trigger_type }}" != "workflow_dispatch" ]]; then
+ echo "βΉοΈ **Note:** Automatic Trigger - Using Non-WAF + Non-EXP configuration" >> $GITHUB_STEP_SUMMARY
+ else
+ echo "βΉοΈ **Note:** Manual Trigger - Using user-specified configuration" >> $GITHUB_STEP_SUMMARY
+ fi
+
+ deploy-linux:
+ name: Deploy on Linux
+ needs: azure-setup
+ if: inputs.runner_os == 'ubuntu-latest' && !cancelled() && needs.azure-setup.result == 'success'
+ uses: ./.github/workflows/job-deploy-linux.yml
+ with:
+ ENV_NAME: ${{ needs.azure-setup.outputs.ENV_NAME }}
+ AZURE_ENV_OPENAI_LOCATION: ${{ needs.azure-setup.outputs.AZURE_ENV_OPENAI_LOCATION }}
+ AZURE_LOCATION: ${{ needs.azure-setup.outputs.AZURE_LOCATION }}
+ RESOURCE_GROUP_NAME: ${{ needs.azure-setup.outputs.RESOURCE_GROUP_NAME }}
+ IMAGE_TAG: ${{ needs.azure-setup.outputs.IMAGE_TAG }}
+ BUILD_DOCKER_IMAGE: ${{ inputs.build_docker_image || 'false' }}
+ EXP: ${{ inputs.EXP || 'false' }}
+ WAF_ENABLED: ${{ inputs.waf_enabled == true && 'true' || 'false' }}
+ AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID: ${{ inputs.AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID }}
+ AZURE_EXISTING_AI_PROJECT_RESOURCE_ID: ${{ inputs.AZURE_EXISTING_AI_PROJECT_RESOURCE_ID }}
+ secrets: inherit
+
+ deploy-windows:
+ name: Deploy on Windows
+ needs: azure-setup
+ if: inputs.runner_os == 'windows-latest' && !cancelled() && needs.azure-setup.result == 'success'
+ uses: ./.github/workflows/job-deploy-windows.yml
+ with:
+ ENV_NAME: ${{ needs.azure-setup.outputs.ENV_NAME }}
+ AZURE_ENV_OPENAI_LOCATION: ${{ needs.azure-setup.outputs.AZURE_ENV_OPENAI_LOCATION }}
+ AZURE_LOCATION: ${{ needs.azure-setup.outputs.AZURE_LOCATION }}
+ RESOURCE_GROUP_NAME: ${{ needs.azure-setup.outputs.RESOURCE_GROUP_NAME }}
+ IMAGE_TAG: ${{ needs.azure-setup.outputs.IMAGE_TAG }}
+ BUILD_DOCKER_IMAGE: ${{ inputs.build_docker_image || 'false' }}
+ EXP: ${{ inputs.EXP || 'false' }}
+ WAF_ENABLED: ${{ inputs.waf_enabled == true && 'true' || 'false' }}
+ AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID: ${{ inputs.AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID }}
+ AZURE_EXISTING_AI_PROJECT_RESOURCE_ID: ${{ inputs.AZURE_EXISTING_AI_PROJECT_RESOURCE_ID }}
+ secrets: inherit
diff --git a/.github/workflows/job-docker-build.yml b/.github/workflows/job-docker-build.yml
new file mode 100644
index 00000000..818e8457
--- /dev/null
+++ b/.github/workflows/job-docker-build.yml
@@ -0,0 +1,113 @@
+name: Docker Build Job
+
+on:
+ workflow_call:
+ inputs:
+ trigger_type:
+ description: 'Trigger type (workflow_dispatch, pull_request, schedule)'
+ required: true
+ type: string
+ build_docker_image:
+ description: 'Build And Push Docker Image (Optional)'
+ required: false
+ default: false
+ type: boolean
+ outputs:
+ IMAGE_TAG:
+ description: "Generated Docker Image Tag"
+ value: ${{ jobs.docker-build.outputs.IMAGE_TAG }}
+
+env:
+ BRANCH_NAME: ${{ github.event.workflow_run.head_branch || github.head_ref || github.ref_name }}
+
+jobs:
+ docker-build:
+ if: inputs.trigger_type == 'workflow_dispatch' && inputs.build_docker_image == true
+ runs-on: ubuntu-latest
+ outputs:
+ IMAGE_TAG: ${{ steps.generate_docker_tag.outputs.IMAGE_TAG }}
+ steps:
+ - name: Checkout Code
+ uses: actions/checkout@v4
+
+ - name: Generate Unique Docker Image Tag
+ id: generate_docker_tag
+ shell: bash
+ run: |
+ echo "π¨ Building new Docker image - generating unique tag..."
+ TIMESTAMP=$(date +%Y%m%d-%H%M%S)
+ RUN_ID="${{ github.run_id }}"
+ BRANCH_NAME="${{ github.head_ref || github.ref_name }}"
+ CLEAN_BRANCH_NAME=$(echo "$BRANCH_NAME" | sed 's/[^a-zA-Z0-9._-]/-/g' | sed 's/--*/-/g' | sed 's/^-\|-$//g')
+ UNIQUE_TAG="${CLEAN_BRANCH_NAME}-${TIMESTAMP}-${RUN_ID}"
+ echo "IMAGE_TAG=$UNIQUE_TAG" >> $GITHUB_ENV
+ echo "IMAGE_TAG=$UNIQUE_TAG" >> $GITHUB_OUTPUT
+ echo "Generated unique Docker tag: $UNIQUE_TAG"
+
+ - name: Set up Docker Buildx
+ uses: docker/setup-buildx-action@v3
+
+ - name: Log in to Azure Container Registry
+ uses: azure/docker-login@v2
+ with:
+ login-server: ${{ secrets.ACR_TEST_LOGIN_SERVER }}
+ username: ${{ secrets.ACR_TEST_USERNAME }}
+ password: ${{ secrets.ACR_TEST_PASSWORD }}
+
+ - name: Build and Push Cod Mod backend Docker image
+ uses: docker/build-push-action@v6
+ env:
+ DOCKER_BUILD_SUMMARY: false
+ with:
+ context: .
+ file: docker/Backend.Dockerfile
+ push: true
+ tags: |
+ ${{ secrets.ACR_TEST_LOGIN_SERVER }}/cmsabackend:${{ steps.generate_docker_tag.outputs.IMAGE_TAG }}
+ ${{ secrets.ACR_TEST_LOGIN_SERVER }}/cmsabackend:${{ steps.generate_docker_tag.outputs.IMAGE_TAG }}_${{ github.run_number }}
+
+ - name: Build and Push Cod Mod frontend Docker image
+ uses: docker/build-push-action@v6
+ env:
+ DOCKER_BUILD_SUMMARY: false
+ with:
+ context: .
+ file: docker/Frontend.Dockerfile
+ push: true
+ tags: |
+ ${{ secrets.ACR_TEST_LOGIN_SERVER }}/cmsafrontend:${{ steps.generate_docker_tag.outputs.IMAGE_TAG }}
+ ${{ secrets.ACR_TEST_LOGIN_SERVER }}/cmsafrontend:${{ steps.generate_docker_tag.outputs.IMAGE_TAG }}_${{ github.run_number }}
+
+ - name: Verify Docker Image Build
+ shell: bash
+ run: |
+ echo "β
Docker image successfully built and pushed"
+ echo "Image tag: ${{ steps.generate_docker_tag.outputs.IMAGE_TAG }}"
+
+ - name: Generate Docker Build Summary
+ if: always()
+ shell: bash
+ run: |
+ ACR_NAME=$(echo "${{ secrets.ACR_TEST_LOGIN_SERVER }}")
+ echo "## π³ Docker Build Job Summary" >> $GITHUB_STEP_SUMMARY
+ echo "" >> $GITHUB_STEP_SUMMARY
+ echo "| Field | Value |" >> $GITHUB_STEP_SUMMARY
+ echo "|-------|--------|" >> $GITHUB_STEP_SUMMARY
+ echo "| **Job Status** | ${{ job.status == 'success' && 'β
Success' || 'β Failed' }} |" >> $GITHUB_STEP_SUMMARY
+ echo "| **Image Tag** | \`${{ steps.generate_docker_tag.outputs.IMAGE_TAG }}\` |" >> $GITHUB_STEP_SUMMARY
+ echo "| **Branch** | \`${{ env.BRANCH_NAME }}\` |" >> $GITHUB_STEP_SUMMARY
+ echo "" >> $GITHUB_STEP_SUMMARY
+ if [[ "${{ job.status }}" == "success" ]]; then
+ echo "### β
Build Details" >> $GITHUB_STEP_SUMMARY
+ echo "Successfully built and pushed Docker images to Azure Container Registry" >> $GITHUB_STEP_SUMMARY
+ echo "" >> $GITHUB_STEP_SUMMARY
+ echo "**Built Images:**" >> $GITHUB_STEP_SUMMARY
+ echo "- **Backend**: \`${ACR_NAME}/cmsabackend:${{ steps.generate_docker_tag.outputs.IMAGE_TAG }}\`" >> $GITHUB_STEP_SUMMARY
+ echo "- **Frontend**: \`${ACR_NAME}/cmsafrontend:${{ steps.generate_docker_tag.outputs.IMAGE_TAG }}\`" >> $GITHUB_STEP_SUMMARY
+ echo "" >> $GITHUB_STEP_SUMMARY
+ else
+ echo "### β Build Failed" >> $GITHUB_STEP_SUMMARY
+ echo "- Docker build process encountered an error" >> $GITHUB_STEP_SUMMARY
+ echo "- Check the docker-build job steps above for detailed error information" >> $GITHUB_STEP_SUMMARY
+ echo "- Verify ACR credentials and Docker build context" >> $GITHUB_STEP_SUMMARY
+ fi
diff --git a/.github/workflows/job-send-notification.yml b/.github/workflows/job-send-notification.yml
new file mode 100644
index 00000000..e4a12491
--- /dev/null
+++ b/.github/workflows/job-send-notification.yml
@@ -0,0 +1,224 @@
+name: Send Notification Job
+
+on:
+ workflow_call:
+ inputs:
+ trigger_type:
+ description: 'Trigger type (workflow_dispatch, pull_request, schedule)'
+ required: true
+ type: string
+ waf_enabled:
+ description: 'Enable WAF'
+ required: false
+ default: false
+ type: boolean
+ EXP:
+ description: 'Enable EXP'
+ required: false
+ default: false
+ type: boolean
+ run_e2e_tests:
+ description: 'Run End-to-End Tests'
+ required: false
+ default: 'GoldenPath-Testing'
+ type: string
+ existing_webapp_url:
+ description: 'Existing Container WebApp URL (Skips Deployment)'
+ required: false
+ default: ''
+ type: string
+ deploy_result:
+ description: 'Deploy job result (success, failure, skipped)'
+ required: true
+ type: string
+ e2e_test_result:
+ description: 'E2E test job result (success, failure, skipped)'
+ required: true
+ type: string
+ CONTAINER_WEB_APPURL:
+ description: 'Container Web App URL'
+ required: false
+ default: ''
+ type: string
+ RESOURCE_GROUP_NAME:
+ description: 'Resource Group Name'
+ required: false
+ default: ''
+ type: string
+ QUOTA_FAILED:
+ description: 'Quota Check Failed Flag'
+ required: false
+ default: 'false'
+ type: string
+ TEST_SUCCESS:
+ description: 'Test Success Flag'
+ required: false
+ default: ''
+ type: string
+ TEST_REPORT_URL:
+ description: 'Test Report URL'
+ required: false
+ default: ''
+ type: string
+
+env:
+ GPT_MIN_CAPACITY: 100
+ BRANCH_NAME: ${{ github.event.workflow_run.head_branch || github.head_ref || github.ref_name }}
+ WAF_ENABLED: ${{ inputs.trigger_type == 'workflow_dispatch' && (inputs.waf_enabled || false) || false }}
+ EXP: ${{ inputs.trigger_type == 'workflow_dispatch' && (inputs.EXP || false) || false }}
+ RUN_E2E_TESTS: ${{ inputs.trigger_type == 'workflow_dispatch' && (inputs.run_e2e_tests || 'GoldenPath-Testing') || 'GoldenPath-Testing' }}
+
+jobs:
+ send-notification:
+ runs-on: ubuntu-latest
+ continue-on-error: true
+ env:
+ accelerator_name: "Code Modernization"
+ steps:
+ - name: Determine Test Suite Display Name
+ id: test_suite
+ shell: bash
+ run: |
+ if [ "${{ env.RUN_E2E_TESTS }}" = "GoldenPath-Testing" ]; then
+ TEST_SUITE_NAME="Golden Path Testing"
+ elif [ "${{ env.RUN_E2E_TESTS }}" = "Smoke-Testing" ]; then
+ TEST_SUITE_NAME="Smoke Testing"
+ elif [ "${{ env.RUN_E2E_TESTS }}" = "None" ]; then
+ TEST_SUITE_NAME="None"
+ else
+ TEST_SUITE_NAME="${{ env.RUN_E2E_TESTS }}"
+ fi
+ echo "TEST_SUITE_NAME=$TEST_SUITE_NAME" >> $GITHUB_OUTPUT
+ echo "Test Suite: $TEST_SUITE_NAME"
+
+ - name: Send Quota Failure Notification
+ if: inputs.deploy_result == 'failure' && inputs.QUOTA_FAILED == 'true'
+ shell: bash
+ run: |
+ RUN_URL="https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}"
+ EMAIL_BODY=$(cat <Dear Team,
We would like to inform you that the ${{ env.accelerator_name }} deployment has failed due to insufficient quota in the requested regions.
Issue Details:
β’ Quota check failed for GPT model
β’ Required GPT Capacity: ${{ env.GPT_MIN_CAPACITY }}
β’ Checked Regions: ${{ vars.AZURE_REGIONS }}
Run URL: ${RUN_URL}
Please resolve the quota issue and retry the deployment.
Best regards,
Your Automation Team
",
+ "subject": "${{ env.accelerator_name }} Pipeline - Failed (Insufficient Quota)"
+ }
+ EOF
+ )
+
+ curl -X POST "${{ secrets.EMAILNOTIFICATION_LOGICAPP_URL_TA }}" \
+ -H "Content-Type: application/json" \
+ -d "$EMAIL_BODY" || echo "Failed to send quota failure notification"
+
+ - name: Send Deployment Failure Notification
+ if: inputs.deploy_result == 'failure' && inputs.QUOTA_FAILED != 'true'
+ shell: bash
+ run: |
+ RUN_URL="https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}"
+ RESOURCE_GROUP="${{ inputs.RESOURCE_GROUP_NAME }}"
+
+ EMAIL_BODY=$(cat <Dear Team,We would like to inform you that the ${{ env.accelerator_name }} deployment process has encountered an issue and has failed to complete successfully.
Deployment Details:
β’ Resource Group: ${RESOURCE_GROUP}
β’ WAF Enabled: ${{ env.WAF_ENABLED }}
β’ EXP Enabled: ${{ env.EXP }}
Run URL: ${RUN_URL}
Please investigate the deployment failure at your earliest convenience.
Best regards,
Your Automation Team
",
+ "subject": "${{ env.accelerator_name }} Pipeline - Failed"
+ }
+ EOF
+ )
+
+ curl -X POST "${{ secrets.EMAILNOTIFICATION_LOGICAPP_URL_TA }}" \
+ -H "Content-Type: application/json" \
+ -d "$EMAIL_BODY" || echo "Failed to send deployment failure notification"
+
+ - name: Send Success Notification
+ if: inputs.deploy_result == 'success' && (inputs.e2e_test_result == 'skipped' || inputs.TEST_SUCCESS == 'true')
+ shell: bash
+ run: |
+ RUN_URL="https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}"
+ WEBAPP_URL="${{ inputs.CONTAINER_WEB_APPURL || inputs.existing_webapp_url }}"
+ RESOURCE_GROUP="${{ inputs.RESOURCE_GROUP_NAME }}"
+ TEST_REPORT_URL="${{ inputs.TEST_REPORT_URL }}"
+ TEST_SUITE_NAME="${{ steps.test_suite.outputs.TEST_SUITE_NAME }}"
+
+ if [ "${{ inputs.e2e_test_result }}" = "skipped" ]; then
+ EMAIL_BODY=$(cat <Dear Team,We would like to inform you that the ${{ env.accelerator_name }} deployment has completed successfully.
Deployment Details:
β’ Resource Group: ${RESOURCE_GROUP}
β’ Web App URL: ${WEBAPP_URL}
β’ E2E Tests: Skipped (as configured)
Configuration:
β’ WAF Enabled: ${{ env.WAF_ENABLED }}
β’ EXP Enabled: ${{ env.EXP }}
Run URL: ${RUN_URL}
Best regards,
Your Automation Team
",
+ "subject": "${{ env.accelerator_name }} Pipeline - Deployment Success"
+ }
+ EOF
+ )
+ else
+ EMAIL_BODY=$(cat <Dear Team,We would like to inform you that the ${{ env.accelerator_name }} deployment and testing process has completed successfully.
Deployment Details:
β’ Resource Group: ${RESOURCE_GROUP}
β’ Web App URL: ${WEBAPP_URL}
β’ E2E Tests: Passed β
β’ Test Suite: ${TEST_SUITE_NAME}
β’ Test Report: View Report
Configuration:
β’ WAF Enabled: ${{ env.WAF_ENABLED }}
β’ EXP Enabled: ${{ env.EXP }}
Run URL: ${RUN_URL}
Best regards,
Your Automation Team
",
+ "subject": "${{ env.accelerator_name }} Pipeline - Test Automation - Success"
+ }
+ EOF
+ )
+ fi
+
+ curl -X POST "${{ secrets.EMAILNOTIFICATION_LOGICAPP_URL_TA }}" \
+ -H "Content-Type: application/json" \
+ -d "$EMAIL_BODY" || echo "Failed to send success notification"
+
+ - name: Send Test Failure Notification
+ if: inputs.deploy_result == 'success' && inputs.e2e_test_result != 'skipped' && inputs.TEST_SUCCESS != 'true'
+ shell: bash
+ run: |
+ RUN_URL="https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}"
+ TEST_REPORT_URL="${{ inputs.TEST_REPORT_URL }}"
+ WEBAPP_URL="${{ inputs.CONTAINER_WEB_APPURL || inputs.existing_webapp_url }}"
+ RESOURCE_GROUP="${{ inputs.RESOURCE_GROUP_NAME }}"
+ TEST_SUITE_NAME="${{ steps.test_suite.outputs.TEST_SUITE_NAME }}"
+
+ EMAIL_BODY=$(cat <Dear Team,We would like to inform you that ${{ env.accelerator_name }} accelerator test automation process has encountered issues and failed to complete successfully.
Deployment Details:
β’ Resource Group: ${RESOURCE_GROUP}
β’ Web App URL: ${WEBAPP_URL}
β’ Deployment Status: β
Success
β’ E2E Tests: β Failed
β’ Test Suite: ${TEST_SUITE_NAME}
Test Details:
β’ Test Report: View Report
Run URL: ${RUN_URL}
Please investigate the matter at your earliest convenience.
Best regards,
Your Automation Team
",
+ "subject": "${{ env.accelerator_name }} Pipeline - Test Automation - Failed"
+ }
+ EOF
+ )
+
+ curl -X POST "${{ secrets.EMAILNOTIFICATION_LOGICAPP_URL_TA }}" \
+ -H "Content-Type: application/json" \
+ -d "$EMAIL_BODY" || echo "Failed to send test failure notification"
+
+ - name: Send Existing URL Success Notification
+ if: inputs.deploy_result == 'skipped' && inputs.existing_webapp_url != '' && inputs.e2e_test_result == 'success' && (inputs.TEST_SUCCESS == 'true' || inputs.TEST_SUCCESS == '')
+ shell: bash
+ run: |
+ RUN_URL="https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}"
+ EXISTING_URL="${{ inputs.existing_webapp_url }}"
+ TEST_REPORT_URL="${{ inputs.TEST_REPORT_URL }}"
+ TEST_SUITE_NAME="${{ steps.test_suite.outputs.TEST_SUITE_NAME }}"
+
+ EMAIL_BODY=$(cat <Dear Team,The ${{ env.accelerator_name }} pipeline executed against the specified Target URL and testing process has completed successfully.
Test Results:
β’ Status: β
Passed
β’ Test Suite: ${TEST_SUITE_NAME}
${TEST_REPORT_URL:+β’ Test Report: View Report}
β’ Target URL: ${EXISTING_URL}
Deployment: Skipped
Run URL: ${RUN_URL}
Best regards,
Your Automation Team
",
+ "subject": "${{ env.accelerator_name }} Pipeline - Test Automation Passed "
+ }
+ EOF
+ )
+
+ curl -X POST "${{ secrets.EMAILNOTIFICATION_LOGICAPP_URL_TA }}" \
+ -H "Content-Type: application/json" \
+ -d "$EMAIL_BODY" || echo "Failed to send existing URL success notification"
+
+ - name: Send Existing URL Test Failure Notification
+ if: inputs.deploy_result == 'skipped' && inputs.existing_webapp_url != '' && inputs.e2e_test_result == 'failure'
+ shell: bash
+ run: |
+ RUN_URL="https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}"
+ EXISTING_URL="${{ inputs.existing_webapp_url }}"
+ TEST_REPORT_URL="${{ inputs.TEST_REPORT_URL }}"
+ TEST_SUITE_NAME="${{ steps.test_suite.outputs.TEST_SUITE_NAME }}"
+
+ EMAIL_BODY=$(cat <Dear Team,The ${{ env.accelerator_name }} pipeline executed against the specified Target URL and the test automation has encountered issues and failed to complete successfully.
Failure Details:
β’ Target URL: ${EXISTING_URL}
${TEST_REPORT_URL:+β’ Test Report: View Report}
β’ Test Suite: ${TEST_SUITE_NAME}
β’ Deployment: Skipped
Run URL: ${RUN_URL}
Best regards,
Your Automation Team
",
+ "subject": "${{ env.accelerator_name }} Pipeline - Test Automation Failed "
+ }
+ EOF
+ )
+
+ curl -X POST "${{ secrets.EMAILNOTIFICATION_LOGICAPP_URL_TA }}" \
+ -H "Content-Type: application/json" \
+ -d "$EMAIL_BODY" || echo "Failed to send existing URL test failure notification"
diff --git a/.github/workflows/test-automation-v2.yml b/.github/workflows/test-automation-v2.yml
new file mode 100644
index 00000000..1c710b61
--- /dev/null
+++ b/.github/workflows/test-automation-v2.yml
@@ -0,0 +1,185 @@
+name: Test Automation Code Modernization - v2
+
+on:
+ workflow_call:
+ inputs:
+ TEST_URL:
+ required: true
+ type: string
+ description: "Web URL for code modernization"
+ TEST_SUITE:
+ required: false
+ type: string
+ default: "GoldenPath-Testing"
+ description: "Test suite to run: 'Smoke-Testing', 'GoldenPath-Testing' "
+ outputs:
+ TEST_SUCCESS:
+ description: "Whether tests passed"
+ value: ${{ jobs.test.outputs.TEST_SUCCESS }}
+ TEST_REPORT_URL:
+ description: "URL to test report artifact"
+ value: ${{ jobs.test.outputs.TEST_REPORT_URL }}
+
+env:
+ url: ${{ inputs.TEST_URL }}
+ accelerator_name: "Code Modernization"
+ test_suite: ${{ inputs.TEST_SUITE }}
+
+jobs:
+ test:
+ runs-on: ubuntu-latest
+ outputs:
+ TEST_SUCCESS: ${{ steps.test1.outcome == 'success' || steps.test2.outcome == 'success' || steps.test3.outcome == 'success' }}
+ TEST_REPORT_URL: ${{ steps.upload_report.outputs.artifact-url }}
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v5
+
+ - name: Set up Python
+ uses: actions/setup-python@v6
+ with:
+ python-version: '3.13'
+
+ - name: Login to Azure
+ run: |
+ az login --service-principal -u ${{ secrets.AZURE_CLIENT_ID }} -p ${{ secrets.AZURE_CLIENT_SECRET }} --tenant ${{ secrets.AZURE_TENANT_ID }}
+ az account set --subscription ${{ secrets.AZURE_SUBSCRIPTION_ID }}
+
+ - name: Install dependencies
+ run: |
+ python -m pip install --upgrade pip
+ pip install -r tests/e2e-test/requirements.txt
+
+ - name: Ensure browsers are installed
+ run: python -m playwright install --with-deps chromium
+
+ - name: Validate URL
+ run: |
+ if [ -z "${{ env.url }}" ]; then
+ echo "ERROR: No URL provided for testing"
+ exit 1
+ fi
+ echo "Testing URL: ${{ env.url }}"
+ echo "Test Suite: ${{ env.test_suite }}"
+
+
+ - name: Wait for Application to be Ready
+ run: |
+ echo "Waiting for application to be ready at ${{ env.url }} "
+ max_attempts=10
+ attempt=1
+
+ while [ $attempt -le $max_attempts ]; do
+ echo "Attempt $attempt: Checking if application is ready..."
+ if curl -f -s "${{ env.url }}" > /dev/null; then
+ echo "Application is ready!"
+ break
+
+ fi
+
+ if [ $attempt -eq $max_attempts ]; then
+ echo "Application is not ready after $max_attempts attempts"
+ exit 1
+ fi
+
+ echo "Application not ready, waiting 30 seconds..."
+ sleep 30
+ attempt=$((attempt + 1))
+ done
+
+ - name: Run tests(1)
+ id: test1
+ run: |
+ if [ "${{ env.test_suite }}" == "GoldenPath-Testing" ]; then
+ xvfb-run pytest --html=report/report.html --self-contained-html
+ fi
+ working-directory: tests/e2e-test
+ continue-on-error: true
+
+ - name: Sleep for 30 seconds
+ if: ${{ steps.test1.outcome == 'failure' }}
+ run: sleep 30s
+ shell: bash
+
+ - name: Run tests(2)
+ id: test2
+ if: ${{ steps.test1.outcome == 'failure' }}
+ run: |
+ if [ "${{ env.test_suite }}" == "GoldenPath-Testing" ]; then
+ xvfb-run pytest --html=report/report.html --self-contained-html
+ fi
+ working-directory: tests/e2e-test
+ continue-on-error: true
+
+ - name: Sleep for 60 seconds
+ if: ${{ steps.test2.outcome == 'failure' }}
+ run: sleep 60s
+ shell: bash
+
+ - name: Run tests(3)
+ id: test3
+ if: ${{ steps.test2.outcome == 'failure' }}
+ run: |
+ if [ "${{ env.test_suite }}" == "GoldenPath-Testing" ]; then
+ xvfb-run pytest --html=report/report.html --self-contained-html
+ fi
+ working-directory: tests/e2e-test
+
+ - name: Upload test report
+ id: upload_report
+ uses: actions/upload-artifact@v4
+ if: ${{ !cancelled() }}
+ with:
+ name: test-report
+ path: tests/e2e-test/report/*
+
+ - name: Generate E2E Test Summary
+ if: always()
+ run: |
+ # Determine test suite type for title
+ if [ "${{ env.test_suite }}" == "GoldenPath-Testing" ]; then
+ echo "## π§ͺ E2E Test Job Summary : Golden Path Testing" >> $GITHUB_STEP_SUMMARY
+ else
+ echo "## π§ͺ E2E Test Job Summary : Smoke Testing" >> $GITHUB_STEP_SUMMARY
+ fi
+ echo "" >> $GITHUB_STEP_SUMMARY
+ echo "| Field | Value |" >> $GITHUB_STEP_SUMMARY
+ echo "|-------|--------|" >> $GITHUB_STEP_SUMMARY
+
+ # Determine overall test result
+ OVERALL_SUCCESS="${{ steps.test1.outcome == 'success' || steps.test2.outcome == 'success' || steps.test3.outcome == 'success' }}"
+ if [[ "$OVERALL_SUCCESS" == "true" ]]; then
+ echo "| **Job Status** | β
Success |" >> $GITHUB_STEP_SUMMARY
+ else
+ echo "| **Job Status** | β Failed |" >> $GITHUB_STEP_SUMMARY
+ fi
+
+ echo "| **Target URL** | [${{ env.url }}](${{ env.url }}) |" >> $GITHUB_STEP_SUMMARY
+ echo "| **Test Suite** | \`${{ env.test_suite }}\` |" >> $GITHUB_STEP_SUMMARY
+ echo "| **Test Report** | [Download Artifact](${{ steps.upload_report.outputs.artifact-url }}) |" >> $GITHUB_STEP_SUMMARY
+ echo "" >> $GITHUB_STEP_SUMMARY
+
+ echo "### π Test Execution Details" >> $GITHUB_STEP_SUMMARY
+ echo "| Attempt | Status | Notes |" >> $GITHUB_STEP_SUMMARY
+ echo "|---------|--------|-------|" >> $GITHUB_STEP_SUMMARY
+ echo "| **Test Run 1** | ${{ steps.test1.outcome == 'success' && 'β
Passed' || 'β Failed' }} | Initial test execution |" >> $GITHUB_STEP_SUMMARY
+
+ if [[ "${{ steps.test1.outcome }}" == "failure" ]]; then
+ echo "| **Test Run 2** | ${{ steps.test2.outcome == 'success' && 'β
Passed' || steps.test2.outcome == 'failure' && 'β Failed' || 'βΈοΈ Skipped' }} | Retry after 30s delay |" >> $GITHUB_STEP_SUMMARY
+ fi
+
+ if [[ "${{ steps.test2.outcome }}" == "failure" ]]; then
+ echo "| **Test Run 3** | ${{ steps.test3.outcome == 'success' && 'β
Passed' || steps.test3.outcome == 'failure' && 'β Failed' || 'βΈοΈ Skipped' }} | Final retry after 60s delay |" >> $GITHUB_STEP_SUMMARY
+ fi
+
+ echo "" >> $GITHUB_STEP_SUMMARY
+
+ if [[ "$OVERALL_SUCCESS" == "true" ]]; then
+ echo "### β
Test Results" >> $GITHUB_STEP_SUMMARY
+ echo "- End-to-end tests completed successfully" >> $GITHUB_STEP_SUMMARY
+ echo "- Application is functioning as expected" >> $GITHUB_STEP_SUMMARY
+ else
+ echo "### β Test Results" >> $GITHUB_STEP_SUMMARY
+ echo "- All test attempts failed" >> $GITHUB_STEP_SUMMARY
+ echo "- Check the e2e-test/test job for detailed error information" >> $GITHUB_STEP_SUMMARY
+ fi
\ No newline at end of file
diff --git a/infra/main.bicep b/infra/main.bicep
index a6472f5c..34d5b1fc 100644
--- a/infra/main.bicep
+++ b/infra/main.bicep
@@ -105,6 +105,9 @@ param gptModelName string = 'gpt-4o'
@description('Optional. Set the Image tag. Defaults to latest_2025-11-10_599.')
param imageVersion string = 'latest_2025-11-10_599'
+@description('Optional. Azure Container Registry name. Defaults to cmsacontainerreg.azurecr.io')
+param acrName string = 'cmsacontainerreg.azurecr.io'
+
@minLength(1)
@description('Optional. Version of the GPT model to deploy. Defaults to 2024-08-06.')
param gptModelVersion string = '2024-08-06'
@@ -856,7 +859,7 @@ module containerAppBackend 'br/public:avm/res/app/container-app:0.19.0' = {
containers: [
{
name: 'cmsabackend'
- image: 'cmsacontainerreg.azurecr.io/cmsabackend:${imageVersion}'
+ image: '${acrName}/cmsabackend:${imageVersion}'
env: concat(
[
{
@@ -1044,7 +1047,7 @@ module containerAppFrontend 'br/public:avm/res/app/container-app:0.19.0' = {
value: 'prod'
}
]
- image: 'cmsacontainerreg.azurecr.io/cmsafrontend:${imageVersion}'
+ image: '${acrName}/cmsafrontend:${imageVersion}'
name: 'cmsafrontend'
resources: {
cpu: 1
diff --git a/infra/main.parameters.json b/infra/main.parameters.json
index b5371502..da8b3cc7 100644
--- a/infra/main.parameters.json
+++ b/infra/main.parameters.json
@@ -23,6 +23,9 @@
"imageVersion": {
"value": "${AZURE_ENV_IMAGETAG=latest}"
},
+ "acrName": {
+ "value": "${AZURE_ENV_ACR_NAME=cmsacontainerreg.azurecr.io}"
+ },
"existingLogAnalyticsWorkspaceId": {
"value": "${AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID}"
},
@@ -32,6 +35,9 @@
"secondaryLocation": {
"value": "${AZURE_ENV_COSMOS_SECONDARY_LOCATION}"
},
+ "azureAiServiceLocation": {
+ "value": "${AZURE_ENV_AI_SERVICE_LOCATION}"
+ },
"vmSize": {
"value": "${AZURE_ENV_JUMPBOX_SIZE}"
},
diff --git a/infra/main.waf.parameters.json b/infra/main.waf.parameters.json
index 7bd336b2..98a1ead9 100644
--- a/infra/main.waf.parameters.json
+++ b/infra/main.waf.parameters.json
@@ -23,6 +23,9 @@
"imageVersion": {
"value": "${AZURE_ENV_IMAGETAG=latest}"
},
+ "acrName": {
+ "value": "${AZURE_ENV_ACR_NAME=cmsacontainerreg.azurecr.io}"
+ },
"existingLogAnalyticsWorkspaceId": {
"value": "${AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID}"
},
@@ -32,6 +35,9 @@
"secondaryLocation": {
"value": "${AZURE_ENV_COSMOS_SECONDARY_LOCATION}"
},
+ "azureAiServiceLocation": {
+ "value": "${AZURE_ENV_AI_SERVICE_LOCATION}"
+ },
"vmSize": {
"value": "${AZURE_ENV_JUMPBOX_SIZE}"
},
From 7726d6bacba9cd733a0fabf57015bdfbb17d9bd1 Mon Sep 17 00:00:00 2001
From: Vamshi-Microsoft
Date: Thu, 18 Dec 2025 10:36:15 +0530
Subject: [PATCH 09/13] Added workflow trigger
---
.github/workflows/deploy-linux.yml | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/.github/workflows/deploy-linux.yml b/.github/workflows/deploy-linux.yml
index aecf5071..d5e7d029 100644
--- a/.github/workflows/deploy-linux.yml
+++ b/.github/workflows/deploy-linux.yml
@@ -1,5 +1,13 @@
name: Deploy-Test-Cleanup (v2) Linux
on:
+ workflow_run:
+ workflows: ["Build Docker and Optional Push"]
+ types:
+ - completed
+ branches:
+ - main
+ - dev
+ - demo
workflow_dispatch:
inputs:
azure_location:
From 03c07466bc83dba1d038647651a50de469ad13b0 Mon Sep 17 00:00:00 2001
From: Vamshi-Microsoft
Date: Thu, 18 Dec 2025 10:49:51 +0530
Subject: [PATCH 10/13] removed SecurityControl tag
---
.github/workflows/deploy.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml
index dd0e0d83..8ba97981 100644
--- a/.github/workflows/deploy.yml
+++ b/.github/workflows/deploy.yml
@@ -142,7 +142,7 @@ jobs:
azureAiServiceLocation='${{ env.AZURE_LOCATION }}' \
imageVersion="${IMAGE_TAG}" \
createdBy="Pipeline" \
- tags="{'SecurityControl':'Ignore','Purpose':'Deploying and Cleaning Up Resources for Validation','CreatedDate':'$current_date'}"
+ tags="{'Purpose':'Deploying and Cleaning Up Resources for Validation','CreatedDate':'$current_date'}"
- name: Assign Contributor role to Service Principal
if: always()
From 5449c84137832bc3bbc4f3be793354e8fc956115 Mon Sep 17 00:00:00 2001
From: Vamshi-Microsoft
Date: Thu, 18 Dec 2025 16:18:23 +0530
Subject: [PATCH 11/13] Updated readme
---
docs/CustomizingAzdParameters.md | 3 +++
1 file changed, 3 insertions(+)
diff --git a/docs/CustomizingAzdParameters.md b/docs/CustomizingAzdParameters.md
index bfcffe6d..b71a16a3 100644
--- a/docs/CustomizingAzdParameters.md
+++ b/docs/CustomizingAzdParameters.md
@@ -10,6 +10,7 @@ By default this template will use the environment name as the prefix to prevent
| -------------------------------------- | ------- | ---------------- | ---------------------------------------------------------------------------------------------------- |
| `AZURE_ENV_NAME` | string | `azdtemp` | Used as a prefix for all resource names to ensure uniqueness across environments. |
| `AZURE_LOCATION` | string | `` | Location of the Azure resources. Controls where the infrastructure will be deployed. |
+| `AZURE_ENV_AI_SERVICE_LOCATION` | string | `` | Location of the Azure resources. Controls where the Azure AI Services will be deployed. |
| `AZURE_ENV_MODEL_DEPLOYMENT_TYPE` | string | `GlobalStandard` | Change the Model Deployment Type (allowed values: Standard, GlobalStandard). |
| `AZURE_ENV_MODEL_NAME` | string | `gpt-4o` | Set the Model Name (allowed values: gpt-4o). |
| `AZURE_ENV_MODEL_VERSION` | string | `2024-08-06` | Set the Azure model version (allowed values: 2024-08-06) |
@@ -21,6 +22,8 @@ By default this template will use the environment name as the prefix to prevent
| `AZURE_ENV_JUMPBOX_ADMIN_PASSWORD` | string | `JumpboxAdminP@ssw0rd1234!` | Specifies the administrator password for the Jumpbox Virtual Machine. |
| `AZURE_ENV_COSMOS_SECONDARY_LOCATION` | string | *(not set by default)* | Specifies the secondary region for Cosmos DB. Required if `enableRedundancy` is `true`. |
| `AZURE_EXISTING_AI_PROJECT_RESOURCE_ID` | string | *(not set by default)* | Specifies the existing AI Foundry Project Resource ID if it needs to be reused. |
+| `AZURE_ENV_ACR_NAME` | string | `cmsacontainerreg.azurecr.io` | Specifies the Azure Container Registry name to use for container images. |
+
---
## How to Set a Parameter
From ecca2f5e08b5a6aa834c3ff45814ccdbd897eb93 Mon Sep 17 00:00:00 2001
From: Vamshi-Microsoft
Date: Thu, 18 Dec 2025 16:43:21 +0530
Subject: [PATCH 12/13] Change account name in resource group generation
---
.github/workflows/job-deploy.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/job-deploy.yml b/.github/workflows/job-deploy.yml
index 6ac84e16..0f0812b4 100644
--- a/.github/workflows/job-deploy.yml
+++ b/.github/workflows/job-deploy.yml
@@ -201,7 +201,7 @@ jobs:
echo "RESOURCE_GROUP_NAME=${{ inputs.resource_group_name }}" >> $GITHUB_ENV
else
echo "Generating a unique resource group name..."
- ACCL_NAME="codmodv2" # Account name as specified
+ ACCL_NAME="codmod" # Account name as specified
SHORT_UUID=$(uuidgen | cut -d'-' -f1)
UNIQUE_RG_NAME="arg-${ACCL_NAME}-${SHORT_UUID}"
echo "RESOURCE_GROUP_NAME=${UNIQUE_RG_NAME}" >> $GITHUB_ENV
From 3cd8b4c5fc1d75317e9fcca99ac8788c3eaa0d19 Mon Sep 17 00:00:00 2001
From: Vamshi-Microsoft
Date: Tue, 23 Dec 2025 10:05:04 +0530
Subject: [PATCH 13/13] Update subscription ID references to use secrets in
deployment workflows
---
.github/workflows/job-deploy-linux.yml | 4 ++--
.github/workflows/job-deploy-windows.yml | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/.github/workflows/job-deploy-linux.yml b/.github/workflows/job-deploy-linux.yml
index 4bd437b1..2b69d56e 100644
--- a/.github/workflows/job-deploy-linux.yml
+++ b/.github/workflows/job-deploy-linux.yml
@@ -91,10 +91,10 @@ jobs:
echo "Environment created: ${{ inputs.ENV_NAME }}"
echo "Setting default subscription..."
- azd config set defaults.subscription ${{ vars.AZURE_SUBSCRIPTION_ID }}
+ azd config set defaults.subscription ${{ secrets.AZURE_SUBSCRIPTION_ID }}
# Set additional parameters
- azd env set AZURE_SUBSCRIPTION_ID="${{ vars.AZURE_SUBSCRIPTION_ID }}"
+ azd env set AZURE_SUBSCRIPTION_ID="${{ secrets.AZURE_SUBSCRIPTION_ID }}"
azd env set AZURE_ENV_AI_SERVICE_LOCATION="${{ inputs.AZURE_ENV_OPENAI_LOCATION }}"
azd env set AZURE_LOCATION="${{ inputs.AZURE_LOCATION }}"
azd env set AZURE_RESOURCE_GROUP="${{ inputs.RESOURCE_GROUP_NAME }}"
diff --git a/.github/workflows/job-deploy-windows.yml b/.github/workflows/job-deploy-windows.yml
index fc016103..a67bf146 100644
--- a/.github/workflows/job-deploy-windows.yml
+++ b/.github/workflows/job-deploy-windows.yml
@@ -86,10 +86,10 @@ jobs:
Write-Host "Environment created: ${{ inputs.ENV_NAME }}"
Write-Host "Setting default subscription..."
- azd config set defaults.subscription ${{ vars.AZURE_SUBSCRIPTION_ID }}
+ azd config set defaults.subscription ${{ secrets.AZURE_SUBSCRIPTION_ID }}
# Set additional parameters
- azd env set AZURE_SUBSCRIPTION_ID="${{ vars.AZURE_SUBSCRIPTION_ID }}"
+ azd env set AZURE_SUBSCRIPTION_ID="${{ secrets.AZURE_SUBSCRIPTION_ID }}"
azd env set AZURE_ENV_AI_SERVICE_LOCATION="${{ inputs.AZURE_ENV_OPENAI_LOCATION }}"
azd env set AZURE_LOCATION="${{ inputs.AZURE_LOCATION }}"
azd env set AZURE_RESOURCE_GROUP="${{ inputs.RESOURCE_GROUP_NAME }}"