From 1a3bcf0238a9ec7535d86218dbe8034a5cbe3328 Mon Sep 17 00:00:00 2001 From: Kemi-Elizabeth <97071326+Kemi-Elizabeth@users.noreply.github.com> Date: Fri, 7 Nov 2025 14:17:57 +0000 Subject: [PATCH 01/12] feat: added app lifecycle page added app life cycle page --- .../src/learn/overview/app-life-cycle.md | 96 ++++++++++++++++++ sites/upsun/static/images/hook-cycle.png | Bin 0 -> 12025 bytes 2 files changed, 96 insertions(+) create mode 100644 sites/upsun/src/learn/overview/app-life-cycle.md create mode 100644 sites/upsun/static/images/hook-cycle.png diff --git a/sites/upsun/src/learn/overview/app-life-cycle.md b/sites/upsun/src/learn/overview/app-life-cycle.md new file mode 100644 index 0000000000..fdb5ad03c8 --- /dev/null +++ b/sites/upsun/src/learn/overview/app-life-cycle.md @@ -0,0 +1,96 @@ +--- +title: The application lifecycle +weight: 3 +description: "Understand the {{% vendor/name %}} application lifecycle and learn how to use build, deploy, and runtime hooks to control app behavior" +--- + +Hooks let you run custom commands at specific points in your application’s lifecycle during [`build`, `deploy`](/learn/overview/build-deploy.html), or `runtime`. They’re essential for setting up your app, managing graceful shutdowns, or preparing instances to handle traffic in autoscaling environments. + +Each web application on {{% vendor/name %}} can define web commands inside its `.upsun/config.yaml` file: + +```yaml +applications: + myapp: + type: 'python:3.13' + web: + commands: + pre_start: "./scripts/setup.sh" + start: "uwsgi --ini conf/server.ini" + post_start: "./scripts/warm-up.sh" +``` +## Web commands + +| Name | Type | Required | Description | +|------|------|-----------|--------------| +| **pre_start** | string | No | Runs just before `start`. Useful for short setup actions that must run per instance, such as moving cache files or setting permissions. | +| **start** | string | Yes | The main command that launches your app. If it terminates, {{% vendor/name %}} restarts it immediately. | +| **post_start** | string | No | Runs after the `start` command but before the container is added to the router. This lets you complete warm-up tasks before the app starts handling traffic. | + +{{< note theme="info" title="Note" >}} + +For more information about web commands, visit the [Single-runtime Image page](/create-apps/app-reference/single-runtime-image.html#web-commands). + +{{< /note >}} + +## Lifecycle overview + +Every application instance follows the same start-up flow: + +- Pre-start prepares each instance before launch. +- Post-start completes warm-up tasks before the instance is routed into live traffic. + +![The steps in the start-up flow](/images/hook-cycle.png "0.50") + +This structure ensures applications can start cleanly, scale horizontally, and serve requests reliably, especially in autoscaling environments. + +## Use cases + +| Hook | When to use | Example task | +|------|--------------|----------------| +| **pre_start** | For configuration and prep that must complete before your app starts | Moving cache, updating file permissions | +| **post_start** | For initialization after your app starts but before it serves traffic | Cache warming, dependency loading | + +### Autoscaling example + +When autoscaling [adds new instances](/manage-resources/autoscaling.html#thresholds) in response to traffic spikes, each instance must start and warm up before serving live requests. Use `post-start` to complete initialization tasks such as: + +- Cache priming or session loading +- Running lightweight readiness checks +- Loading config or dependencies into memory + +This ensures new instances are ready to perform immediately when the router adds them. + +{{< note theme="tip" title="Autoscaling" >}} + +For more information about Autoscaling, visit the [Autoscaling docs page](/manage-resources/autoscaling.html). + +{{< /note >}} + +### Zero-downtime example + +If your [application takes longer to become responsive](/learn/overview/build-deploy.html#application-is-slow-to-start), traffic might be switched back to your original application before it’s fully ready. This can cause temporary errors immediately after deployment. + +If your framework needs time to initialize, `post_start` can help co-ordinate so the app receives traffic only when it’s ready. An example of a `post_start` command waiting for your application would be: + +``` +web: + commands: + post_start: | + date + curl -sS --retry 20 --retry-delay 1 --retry-connrefused localhost -o /dev/null +``` +{{< note theme="info" title="Zero Downtime Deployment" >}} + +For more information about Zero Downtime Deployment, visit the [build deploy documentation page](/learn/overview/build-deploy.html#zero-downtime-deployments). + +{{< /note >}} + +## Related content + +- [Build and Deploy overview](/learn/overview/build-deploy.html) +- [Autoscaling](/manage-resources/autoscaling.html) +- [Single-runtime Image reference](/create-apps/app-reference/single-runtime-image.html#web-commands) +- [Zero-downtime deployments](/learn/overview/build-deploy.html#zero-downtime-deployments) + + + diff --git a/sites/upsun/static/images/hook-cycle.png b/sites/upsun/static/images/hook-cycle.png new file mode 100644 index 0000000000000000000000000000000000000000..83b0222606cc094d9defc8e9047becd13af44eb8 GIT binary patch literal 12025 zcmeHtWmHsczc(n-igZc}NDC-ROLxx@gM>6lNH>U}NS6%V-3>C7puiwV57Iq!cXRf5 z-_JSkdd`=#-gB?_)5}`dx;C5H*Iawp^Z(U9L|s+xJ}wn58XDSt1$k*rV4grjyQ7MY z2^IAZq49$DCpGJ{_@r#?G3gbJMn(wA$a| zyxI>>yG?bT72c_1LL2-UiS~*k2>%uTzl|Cn@@i(&?~{Z{=`3*m95V0zr_t@w=hCfs zdg$I8uZMqGTlG{&Vl?ia-B=|rDDn3sJgn|cDhVbATdSwipI$rC3(W=f;+yiJ{d)Kh z3|nlc_=;T*o00r<CNoxms%_cKxw5?NVL&1RlBA6#b93c5o8|e^|F%Rb$9l|%D^e0l^l zRA={GKEI{v5R~g}5xC?8lr63B6NixS&C#s4R-sYbo6#y$0$c)dm0svCCb%!Q9xXP3 zcn&1DHr;3Vqt`K&yrB8zNkt*3Xn3?>V1_qkD_vI3s9=6R2cr>>q4%ye9-XG5BChZC zu@KesVjkb4Axw6i{xn)do)USH}D-eORZMD*puYLV!wJqAS4$Sap^p~0?*jG-W$ z)}uoE+2*WJHcBIMCpt+BW?NfZ`1c&XG+}bLIoEJmCUcz_#?B`U3=A`Tf;WNF!5i7} z@+vA|)92&~d^WAG(7hFvl|cpyHF)HV)h(jr(CyxF*JF? zo%ZELYw9BlnBnwD|L@7z+FmKYqTu;h@0X#O& zYBR6$tankCChhapo9MUuR847k2~m$f;WL_y`1UL-oy)aeYA^J6cdte#hT}yiATh|E zvfLfSXF!dmRfvg+$qCQy9nS|0OWi~L{SQp7WgqhSg-%XRF4~BM)0j~OnWWuI=Z-GrI{zgGTfephJc!|g4)Rbu(?}xNbH6O`4elvYIl3h`8IXO&< zXTS<*$qZ&!sWJONh#Sy@IaP7FnT{QaH!AN65Z+(aH!S63!KsV+1}m`eSbeFJmY1~ z(C6FQ9&F&%{Y`LuNz6YN`h6V02hN}-H!^XBm-?hU!1ho6n*ZDixyIT2J>Ubl|B=A3 zvL;bMMWrP=H8p&Wo9{z3uc@i&Qsf-458&`A#j*#!&ZHTJj;-0ZsVV)BiWtf>kB97@ ziPO-MkSt3W*S%~0h(07EV*mCnM*%c*CMAlTVBm434L0T7Yy^bCzM?4j=S zpm21@*S7IiEsVq5{7K6Dj2?K{rL@H$d}$dON&^D}B)N$*Vf~#`vRg_DikGS1HnNya z8M(Rb;}cWkPh~jVi@`o7SFLjsvMO?Qmrpy@7Ss96)pnB%Gt)7z~?ZiGCs^^-d=ZH zlDUh_J#3jWMJ{J0=6*4QaP2Uf(R}^=L=ss{!Z^QlR5hOa!^~@I-V%)Z@BR~m%4K^p z)qd_~HK?sKl(Zn0St%w;O=@Gr5}TA$H`-}(Yry*pBL zS&(Rb1JUcUAc=8(w)6lO_rl;_*1H8pjPtva`60HA&CMHm`eS)Y4paiAtiMuTq*?Uo z%14XO<99U5WA6IjQcDCA&}AO3e&^~v-I`D}?ZVGgO-n9Ze=%pP&XqZFv|drNGe23^ zyWUAot#x^Fe;uK7IXqEQuzLyF-`~&fOqFc$ZU7HZ0(H}F?k3(#xjx@+ax{mSbvOg2 zVXwwbfP=#b7sS@%emh#2lzg)<_dfaN>W~{!X^iRVrJaW;X&CwzP%+#vXP=4ey={aB zrKLT(heZcIZLqtH*DkwAPEAvat=Qc(duHKlK2@Y;l+&BQ)G35#H3OrQKCNTsGPt1q z_$i&O)&BUEp=}o-V!g<1aT&ap67#E4 zUZ{92;#iWtzqt+$duo@Tm}u2|7#mBpj!eKRS%tx%;LX=fZp^*ftMC{j#DU{dzGgi8 zbI>~!nmm8&752?Hd(3*SmHPaATa|qHF4l=AuU^`O{VN?P>+ODML35b~%Mu~n&xYI;` z+FY^q^~FG8CY->pM0>l)dIXv@=IY92*+@s1A*PIjgJYA->k}KN#jt;trrf)<@fT*#c_Few_t@~mBFlWZM5j&WV7e}I{O(3QrgD^Q9n26ohF^yY-h?} zpDRVo^>ut77>uBvb0^GFvM6N*aB+ z$$P1ieh8+VuMqdCWG7c|D7({YqWTnE!sM{|y8Wfen@(BX>~6PTtQ$E=Y4` zmy|{IVuQ=N*JSOw^Tp8!0r*7)q;7J)u0yopoL%g0b zfkRgs^8mApqk8}qGx6H4yNzjSX|dX84>3PPY~~><-|%ZVzAl25W@1U^x4)P>6Ybkr zUeQixQQq^N7pm4hIOq)=<>JuFZ%(i`)FxZ))04bqd9wByx74=h6+sYZ2JQo~{0G{- zOBTROqD)Px7|hN`ryQa*4SwBTJLDF+2(S!dF_;=}jGnR;Y>zvBrg#4fp8j_QOthY% z>D>WK=WCV6^GwV=W@=Gc-F#*W4O%*>;*M{{ML(%Z-#mrac|^?gf9#bTUSfmN@?+l7 z_VMvq?h)*|hk-%EVvPP@#MiH!nT3T4XZ#iX%(1qn=DTh(fV~;n_4V~H3j_f06=%Z? zY?uCq31DnmkC~)<4B;Ot9-dK|o105=M*x6tk?rm6syT}G{zX$tsPEPL2 z9;E~v?U@w(Ofaki3k8F;Pki?NM%V#17jjPt_*qft4kORF9_mBsOH|GuTwXSFAqTEY zfdYxCJJ|5*AiY(%*=VRS;wfoGJJMJOW(k)WGVFvN?pe)^RBE zkm?>o`PWA2u5dFbfitLSi_0UR1Xh3`|81CU=n4u9X!(106{od{FNp0e_LDe~kAJn);% zf(PE+>@bh%u`z8`E{UcWbUd`_3dV?se3;TDb&}Ke=KF(sL!o61e=vIS>p1(6mrSmK z1z*yl%pTc8T~SaG#plpaJ{S!4ljp|@qwT#Nt{eWRPv5-^Ku7`D`}*}XJFg(eZkYB~ zq*W&wVdZ;hc*xqCRZdt~ScFwia>#`GP-q0baeyn%ZQ$Z(F>O`<2UahhzL z^RnSz!=jP#vF48=o@cmrjUVv3u3CiRQ#yXi0Hc`EKQTn_7|rdwtPS3{^oEjg$s&8j zWei}=$^#;YH0blw6j6oBNlr&Mm%WJXmQ%6(R^Q;*hzPDdYToW#caeH(!_jYofK8=Ioc%Q z&njzba&SpSp0IC(CP#h7&RO{G9WrLe%Vj8%5=!p>LG0#CNl`%|3sI6V6vKqIK3T^B zs>y%Ra%Mu{b+OJuFnt3s1?%lem-dSI-`a z(`M4%?sxB6pYG&f5D+koEH8FCFYnxZfjL;ZpB^1k3zTL9b+qWI0-f)X*!DzCgluH0 zyh=(vqrbm+vZyzaO7b(MzJ})AdUDQ0hC4psdmS?^*&D-LdVD$&_byNAxOvniE>Cx} zcv{D^#?<8H9~w-sfeKXbCckw21aX`H7WK?-^5wkqgjl?7*KQ?;hu0n2Fb z|K$acRrM>APCFr|t@{$uO(3%eA|4*tNto5(uTDs!`_w0}2x3 zD+9ewXfk05ngI5$E%z7?5taEE!*9-*-Wz%qwN0i!vl_G_9X9CmhSK=kL+lePUek@ZEf{)g3aB(#3AuD!#t9$)>|ibY?VGLhIkFdDpSwu7%kFLGYNiW>HT}U3r@nzj$b>bccJU{Divp9-YOh zLCH+>Vok2b9Z|8b*eh=eo-k|vNDU4lauD*3S&spmMlPAlw34~ zi^_9+Ue9)PNOo?6pcTv+T3_F3D1FNf#PVl^KYB@#CTI5f;+Q%=l!k#p!p7&Mmq$Eg zXIdTtJDRx^Q**=mU3M9?(&s5vXEHSO8|-O-*+(N!X)L&NaC%A%?mq-onJ_=Uy*@Q6 z`HtCkyQ3BmAO}j&c4MZ?Ri=D_u=`bVcQfj4t(m91Hg<+rF`wORGsJfdIbIB4eo~i* zwV)s=(NeAF;>#(KUJq5;IBGt#QmYxE;&aUV$%TvXa7yA)9(7=QisaluVeiUw3B*%N zies0$FNXn3qqC|CvG`T*H7r{h!qYqmCbec!^NV-e5s}>6(>20)*E3#;6TeCBU0|OQ zdk>pd>0nqvSWJwLf6-UX(gc_5j~qqmxPNABNu8V;;ne%nd}i?w$$OkfoD{^&QZvYN74MPYEjnqW4WL`H}`v823kl5-D=+6-ditZD{Ia|fRZqOTQcDTtkK;wG(^bk0|@p%pxOU7Xkz^V%|8;^8Fxko zg{{TeO>jInGSmme&l1P>48YPE8Q?k#d`u})0QLU`-~g5b1fad$%A&I74^3!iTSx@X zup#H?jg?TGLoId4>W4p|fC1!RH88{cYpYmo9hN9AfSQEEG9IUvg`(8H_n#T{L4;?7 zp@>HG{?aFacZ}=x<>u!b%B!k&Is9Q3RaI4v-3}=Bfg%}BBA+;mq{|; z$+wSP6G*0eK!A&TKwk-YIot7mjghvYt}b3nX>jLPcUZ6`(H}uQWK;IAL0?bAMZ4DI zEp{oDWY_zb-1UmJhJ@A$Ny_;igw6LbvzFSALTm>^X$7@V1a@D>u9Tw7c;VS-d!m?!vHiO6gHa=qVf&BhmcU=xZ+1PWGkqQ#(T3N%^Wn1@RH^rxFmH!Y z^H4ouP1~K(JwH@e9!?WJNpS|1^a(a3rPk66AsGbOz$#r%UvC|FhpY zqqb(60#CN5WC#f@*G{(emv;$rUs*a;WBC^5bI#)hTJ2BE^Sc&$xGV-#hWX3gw)}E~%g<={ zD>>r=oSjSLomZMAva%R#ZUBW&LQO3txBw_T49~lO=U7!Wbiny73HrNyTPj6h8+;lV z7&V-$;6BhHYW#}TX0(v<{DNDZE7o=&AQa>b&C)0aVmIZM|KJg<#FdG$!|H6$@R{?9 z2?9a}$UCo{i{p~fC6x3IA+}TpgdC0&7T_J)AP%y&r(U2Wn`VnwgfyNu!-!BdbDTsH z;3SqAUO#FClx}YVk5OjFbBn&I4I)Kyp7fkNrMVohC7q+@GGfk&C z$_AnpF+6gnj8p zh!kM-4#{oyw6`<#uKu)Nai6oxWs>vDgToJ@$Q5XRsV1|VC4;{$gPCWcW?u0I3uS~X z_~H3l&Z+fOy~@$B(lvh>56>H6*9{6lEN270W*(%f<73$1W(C2|+VYl`y8*7RaKsbx za&y%^&XSaSkw|M{x2-H(%F_~zPao5W;=74aEXivnX%+M>SHHoYNS6n26CMdVMazb- zmBG9zdzMUjd4KmzG@3yNS{#|QRg|Ed=6Y^7K3`!0$0&6@qV@tj)7q z`YBh}*Eg;Pa6O7RB;N#ADz9k_`@-e?&RIWWESVJ`&7@e0P2D8 z%8_fc7A(iSK=y{Al_&a~bYpHCKo*A;8aFr32^)5Qq!dS84=&w7GFkPY3gkaGdK(y; zJOCAGsPq^vTGTaq=X`%!viw1&EoBzsKej7M z_FV-rGc)HsL_yM$wSz;{br&|^obCf&NYNj|_a)%kWCsmk|7EZa=mDlKu-N`9z~lYP z$n{gr0ssd<3-Et}i)oh`-$xc!)|@6dfO+BV#)TjLQ)XVx8$aU*!WK5&}%zr^3 zAzOo4-M}D16Q&06$tcY2!R0mF$j>q;dtk;pAirc z@Exa=7Q)A}xVWet(xc~TRBPfc%~AjP{k>W0sbt7D+!l`5XK zwz8xURlON`lA-wT!1F~dFQ4ip{CsdEBXQpC>13B#_Ih24pq3xqTSHZO9sqoWdX zp#caZJ*o^avf;AGDg;#}H@k_3N-Hsn6C*)a}*tr>@?_orSjc?nH*P}tg?~X8Fz;2%8V zvigvcqR6aA(}wEd9yLmML+WjL#8SlvrySapewQ2MGb_!4qga`li|8lD$A`Bjl-6e4 z#aV=fg_Fg6X_y~B9&Gl^P)8I$M+J)699~DQ=y6=DfJ}l0_*lW zM#pFMc5TJ$Umdl;-*N$MJ)EynQsjN=wywP^+D$1~gU&7+kR zCh)0>-)B>k>>{OvStwc$J>Zz5QAV&$_-zxjegJKb0NQHf!n``Z^mQW)xBJ>I7NJng0b!%;J7~fSCd3xTjEz#i#;rYnJSw?;J0(-)rzDbj^@$1)6hbtK<#~WGc zR1Lc2+T~!Q*v@buOqA~o6PGw#y$l`Oxu=m^!M-5?@#Pj;=XOGAR zoAZ1XY9-eV5taMYVjNw;_5{GTtIN9jT;d{A_Ido57*8Jxe zEmJy5SgCTlNUUlaZdG4}UX4oKhZ;+Nc`Sk(=?vd`>4>I{QR`RN7x%TYe*G-S;Lb8= zsxP)T0r(AQ^Yna`4zkDd4h`)A6xA0{gli3`^Nt)TU@zf_&hWkkMftCB_Ko-nkMZsU z`Sd+UTf0(RJM}@reTF%f2k6SgGhYj;X#!hLCiPubRh!LQUDo+*AZ>o8u5nW_rtM|= zZ6L0xd=+ngJ1H{V*4vx6hzQ?>kK9mXgZ<3o!MhA2ugIP*k8dsaEUiORRynjwb8(rS zT2)daij-{UWvpEu3^99t-?sh^&=1~4$fyXpZYbQ`_+@jPG0!wpvUa@t0%Yxl#qZP8!B4n% zFu7j8)NoE#4SlrAmajXv0s+X269Hi$w2kV2lMBE4YA=1->LA)SQ!)GIPe?>=nA+Bs~U@8 zL>fAag-@ZNU+=@9h~xqVd&`keb5zr~;U(39cTBZXEi6K{spz(o9ZZ?@?KG_ahjbuj+A z>Rl{1ZPTv-cjb!AMZIdXIdr(q&mm5IXIFyvc%uUkqeecCzu# zft33H%j5r)#~#Kw{ypRTzdCaT1HkhC&QdVO7~+X!{dL!8E=8{#uyRro*p1%7l+Hh3 zjJ1bh{#01?egQY_A|Xz@;1ZCSz8+v;qO43F5F$o1gQh03OPzdk-K$~$XL^OkQ;Bxc z+*!0z1dgq`Be{OG4`zv4^~AcMa07lUbEPV$q#Hm{gj}q|8ymry8UC{h zd+z{8EzWKGBC?b+`1H)E3Onfv>gL2Qog>>K!K#WelBX1dG2wo3q)_cfGrQ#9$!O+% zYF{85k*u*j>54+{qopX}VNt)8J~o88kjI`Sl~{8EY_7>&A5vwKWuC^RKc)e+D8c9E zqP&j1(kJW7)GC^XWo$Puv06_Woh_}`hfl5c=68-3!y;q`FD*8z)5Ynyp{F@OhCNto zZ3-x>XyvJ%ej!#h+Jc5zDw!FWDC?}g&c$+^3<;gT@Qe^psqzEv3TvJ2a9Q2>7!4VO z`^{e__=f>SW++>xrtt0W6)3XWa&M!=ceJfYEra}rH-{dbGcTqh zDTbyF#!(X7J9a8|*L#0a5UL~$5I6OKxRKiBi-Wn-%+s%y18!9O7Vj@odQkCtw53|T z$jz`4*E+yha&d@1724@?ln^A@)-4BDnD?G+3`=n7w?-G~zp-?0@H<2%WB@t1}|7%@G%whRq%~trb9!dPm4@E80fJa^OZi zsHO&YCWfi4xH~Q`ZhgB!ZX`|(Huy7M-)b=P_mBGDnl49kP&+frw6+_Vd>m_3?vEcB z`wZ8q`Dz(z3k#N3i$Aiy#5$b{Z5;&Opqj40B@Y(oD&tX(GSGCDgEdjVy>m(P!oK({ z`l9F(9ldR+FNqj2=K{p^KfJwlFt!fvb_ct;xvRCez4^{gxaarGZHwf28z55m-Dj1h zK82I|-_ATU{w6Q<&bY#(?D&g;UQ0LdjLG1U_0g*h6xVtk3lRR)k;xP&ypA~$-JU+@ z^7H^@H9CtkzBNB)i1Yt3oY$*f25}wrX>v1IyEuLVgrQLD8OwC*tg*U=h60OU5Um+l z1gNlYIk--%z!2p>vuox)Io^Ds>?(DAYcd_15R#Q=erCI_%uv{149nuh=J zS6k7X?DAsu1a@%p&jkNa6gvbEzt)yXcoSZge>JF_B489DiWEAKA}1p&h8QXMS;JRP z*ZFl@{LlTC=a$}-=^gSuw;q7hy)nvlRh|4xG4)#5hOXI=8%5L|~+;`4bg&|PD?8yUEKA$Tk^LYeRd!pJN z=o|5Xne)+GII#kMB<9k?5M2}XIh~Omx^U4lAo7f(lXiZwJ)9S|ytXFK&0P*%{qjUZ zvkqc0p|=Xqh~xHnIxqf4za&276M#`yr{R(g8-cXMR^P}-r}i8*1L;MHb(g(?to5y5 zOw1}cx>&m`$@N)>Y9Rv0W=9q@s z{&Z0;*gJ<V8$FZD!Rx;o4X3IuDNVV1sB2bGmt8!6X7 z|BgnQ(0$Hcb9ys$S>ORoym)H<<>Y&Enk&%hqWLR%wpi(l2GF&@H5Ic9Yy|$mnI32W zG;4fxE>>Lv1U9!Yu0wKZ*%e0%?Pc-|e4BsuY|tjO5U7?40RQS~4F)O^k8m3azF6PA z7H{`lyovp#?$PmY%8{1rpgrZ&=FH4Fu1&bZ5ghJ3TKQ&#bMAWtwflgh{ev%$OM(t8 zcItb$)2`-wv!y#j-Hnv$tDUB;plPn@Ud6E+RKJUnIk+O$Mg!AcJ=-*5KCkL3S6qQA zNbW^ZjrO?7xjOL+)U(y3Q*mN;OiK-{{kt3*3?6n9H%Ef%&klAic9?UoV`F-UZ>DM% z7c}&Ilk#Rxt6iI%kQFX7whv0(lut&~=1Ry)6yl(IVzaf@9Ju%*CX^UTa#6IJ2Fg8i zb7~}Vk(yy-+niCo1S?}@)SVPtG$`v2En4F3Y_lD-f+39HK&sKampr?KtRS7W#M5cd z|9Hc^E>fhH9*--Gd_Y?wmX7v(lSGjIMQ^{5LDPxGLJWexF|yR79CDoXME(f0@a6A5 zN*@BJ(kHjR)zzo;)!v-qTR^sfxNr{>7e&m;LEDgRO56#-!pn)>BQ?0@37oBPn_ZwQ zv}mu_u7@WSh<=OwqprLYICKo}scHuyy`dH24zn)D(^xIt0Gkc@j_E8WDV#7he zdidROMuxwAgPI_kYMcPmr33pB-~?1)nI;_d@Re#zg6f6E z8|jV`Jds`ffR2hi^gpJgH>V^Ehg*|79nd%9nT#4S1++U>2%o^?IYz>bMh bsCUtXcP>iOOq2P6GiVAjs?z0>#vlFztHJLC literal 0 HcmV?d00001 From 706227aeddd1182b7018e90e7d4dd80339740fc7 Mon Sep 17 00:00:00 2001 From: GitHub Action Date: Fri, 7 Nov 2025 14:21:17 +0000 Subject: [PATCH 02/12] Optimize images Automatically optimized images using optipng and jpegoptim via GitHub Actions --- sites/upsun/static/images/hook-cycle.png | Bin 12025 -> 9085 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/sites/upsun/static/images/hook-cycle.png b/sites/upsun/static/images/hook-cycle.png index 83b0222606cc094d9defc8e9047becd13af44eb8..6d88befbb6d6d7b7d2ce18a81fa1702f8a632042 100644 GIT binary patch literal 9085 zcmeI2c|4SDy#Ghql$0b%_8DsIBeKiBMzUppWNabImc8PkL>LX(x9nSuEz3|LCR-RL*UFF^A!4 zg&;*rX>f5Co7m+S6LkZdLd2r{qQ?<+bHQ_kdNZXp;NpM%%w>c54p(=<6$a_f5 zgPQ8G^f;-BIC^k^;0~i`P~5Cstl+>1r3Hg7gJIMm|L<3wzM!roUo_s@+DfH6d^k2X zHVfl1F`oPU%lZ=mn0>_tg(7R?OYAeAoEp6AYGb)o>erJddz_o~qAPBbv?xL#9N??> zvB!O?JqkNtkVemO4t|_-$7C^xT`^c|auNk@sw5i;H*Eb{Z0de-->K6HI}<^?tXyWy zs8X8@+x@R@=X`3=)7AAfs^LnMG%Z&Ubt5g{N(Ve{Q%E7tiU@^YM9qT;h(w3zpV~xFbg*pBopOOnW;MeI1-+{MYV6L*HFmvCVbtu@+Wo zP1Yu@v>km8rWPJ?u~$Jjc`~cvPt_hE{wY4h}N?I};dG}5j_5J&J7iEozKaR`1-7P$)QOv`e-=3wyZ#B#ZbBle# zE}JCD87O+~$vJ74;O@@O!U0dr^XKb&FCT;k=-j%M^~102NvP(*W2OiNuBg91dT!Q# zR|Y5$UQj^cppN$AVxzeJSvP-s6%3))&`m)?H!~T^KXsunLNG@7B-G_IwB^(x*|NNs zW65-(lN}0lJ=!bN<4R+w-OsvVml6_$ET(1q!qXv_5fCUXgp69eHC$P!C{J_M7sc*6 z*5K#jzwh1z&%HrypU$2hk$dToOcV_lE96z8t4f7Kmw7J}#0UW?M+=U$wMASAguq!L zD4KhRaD7P|zee6o5JXS#K+yCM9ON}^V`Jm|8R30bagbPgh@8&5W~ZNTxy+1OL3>c= zT26>sw%Y&mDn{I_8E+4P-|yBSHGWjXe@*X*s}@_KxeTNIW^G>S^b*~(H(>*dqN3uC zehS1}RP|JJd3m{1(X&TYopC4q4`)uRv>bgh2V`0oAi?L$YS}|Ha_pNCP)RHece}7`!b#AxO!{}w)+L6nP<0;M(0ZZ-D z{)DL^iQ?;EfPwIe>{ICmOTOCW>o^JvG?@D zL0v#_Ks-Qg06hsk$YU14z;4w@tkFp<`##vj5U2KdGPh(wEv>;(w{sjS7svxjJWf!? zKOE`EqG>YVOn7y>M$mG@mpD*b9~K_WRpTBKg9POyfp*>55`haf1#icBEevUa8V8r) zHnY;qGpqM0W>rp?x0tl7b~enTXFJWOq@*-G-d}u4+waG6_c}aRyVBJxyV7mMWZ%Ah zP$=?Qs*HDY4$^mN>pVWcCvIsp;F+7UN`%(UImrsW;$n{G-kce$Cs)Y%9iE;?+*|j)kvJS=kCVFiVl=^8Lf*iG8Qna^Fsgd zTbo@$+(EwT*z8InKWu7hit9${7Jq7vXp$cJGGim&hjh#+gc5eP+q&w+9V4ws#gkW3 z&)5f>5WQw^Y84R&-R}urKhfsFc=id>9NdUAFCCptU8xUHU1=D;2yo_tV;_LeV975{Kb<<91p(c~RD37@ZKz zAA0alDe|Al&s8YU8*rWU-N_PzUlp_*X%-hb~{M^i)Jv z^%L)u@)3zPN!*!@1GcGp*ztODg&`s+wp2y7ROT$Zf`78rN4k@x*Hyyl6PftS+PhNp zJ3F)Li9cSwf{KSlMJ9K9BEAXZ7RV+tkMj+ew6x~C=xkmF*-p3_j(R0qXE+yLhDQV) zu{mJgDA#&8i?T3U?~d-lc{$wP+R$>iqf*lgPe@8KBw|a=w0-Ae>Bp|)Zpy+5&%~JK zkmHXYIjawC`bz>m9ry!=50GKcp1ZpK`o5fk$pKB15fpJ%nps!zZL1?oRV{y*00@7{mR7}F_noT}L?*(J#aTSrlTbOPCtDoi&bZ?N6qqmLA!K;;B- zvvz`kay%A4Gl%|P(f%Kc_RguvoJiWeuU2O=r>uuf)&p0O)a<)(Q@4p6`7FCIb#Yx) zS$AbE`f-Q#w1XUTpQz_uom%Kl>4rr&$^YrX=Xc+2GUOP!kBQsoHi3ry`>FqI&wEJ6 z3)J%;s!VO-)Kfnj_`furi?snqMZBs$Q%B#WPipE<=o3flW4P#m*1Bm906E5W3yb33 z%Lv&7*Q%+~I(DDZ@$gtSCkzf(S=di^#>CO%=JYXdLRAEWLN>l#A`&VR z&1^W^s+|$cJl+_ps&>Vf!EL77%4t8=Z}pLLd_pz8{n9PV z=dL3@m%B4|-w6)d<)OFKl{3CIA_ z7n#Jb)2EZ|HDc0z2{Q>o0bO@WT?amVh>XnY06kPQQP|4<%>$`6(QgHEcfS>PD16e& zQyFl^D_m?gro1e(s2Nqm$odAWBJO%RvXl-9gj*rl$ILp`IB;p1Cf(^maod!bdO^I_ z;nC{KHCZjqjca2eyX6jkpzYfOA27|)lZM>m^z0nR_BdY0=%>R2X~+QupmQ4m7*nl; zjF2ute0+WO^RuPr;qfMN0{-rfE4z;O_dMNCA^7#SB(hfZ?c0Qo z)Tn&rvknaI7c?-NP=z8XQSQ9+)nfK2^bSG$kA+}~hcgvw)BP)=FV1fc9MDrkotlst($5~G+1jQiFjt#t2sY2d>C0_>mW>!*p|bLc-=`SB7nc? zGm#`w^lbu0H8IGIfMKC7_0t>*1`i%QKz1cxxpw{f+{?7cYcEkm&?`uZB_()uRpt_4 z=rJL?w<{W7e5)on480K5($h<9Xy|aL)xH7?Rp(98yVcUN)n#TjT;(Fd$SCIUY6FhD zHM*H^*%;W9I~vQ~Y(Lh}Iz6*G(Pw1*fHE*Lu0p%+>n2~4j~H0Q(JLV?TP z6-i2xR^R86{gxw0VE}lHB*opMH7IteSV!v-ejT8{w`DC=5l)pT;tLPp9QqoA4ryH( zoen&MwQE!ITgEE&zSGRTMs;0z`WbdDn3^@vr?B4^_A58I5IU6ic7bsMfB?2T1t^Rhu0kzd4M$yj!7joy|Ted452|}yv z&MNv4pkyEq2*CMVavT1bkq#-4#W6^_k2Ofh)4cXzeC-00ot~LtxvUTQsVARwsDsG2gUov=7H)x4)W)bt<}Nz@JeHBwF|;r(CgMPp+#?){gvrNgFdFaDG~s%&XX zQRnj2c}M=8I{<~#-xJ6N3rtR+1@m9>IPz>SwYV!HWL`P+-f>SW#~x>7aPH<`xhHdm zC-U9kpy@f|&KC1&O*;AgS68_w4`{5TB5w=s_Hvt@p`Ot`JyCE&@m1Uc50>`o(T$Cb zhEipNR>+)B`z#>fO~#zMGj9wY@~{YH2n``l9szFljVKCoWs(1E4!9# z!Ki)WC7;6FX2VO`M7b2{z_zk?qsLqC4}n}}JL7Aw8Y*Sw>BT-*OG^@hJMXTHO#zlH+bJ1zJy9;9Em+1@Fa_3eSOQ8>r|EvL41 zlMse|_@*MX-P~|hie;S_3of?g7K}1iyr4Y~crV#|IInuleW0YaipOkuEXYL-186H{ zoDmGOhROzSq0I8pUFOw}`ek8Z^yq505$za`Hzyexc>(Bnl!*umN*Jpbs{pcsA?`$e z0rcgaqaN+enqUH32ELtru}$mh)!4Pgk@1IqV5yinj%xr~>cY4;{!mH~(s`Ptq9Ijd z_TrDEPgqL4XGU+YICAcz8OF(=fglN-tG$h^FNZP$O7Vn^H2B4s`A)W=Lo(j%GV#i$Y0GMTN)oU^x}o734(IM zRUxU068Mi7Rhzp`jg13=0$aI@`O79xKn@OLTxmS&rI%Ryhgf z&+qv2sIMhyLJy-6vttim06Kp~ts?kPX^9U`SvkCR;VAWyI0G8F`NIZ4hhxdW=9hSN){ zv*lASF$%O{ubyl4#;7eXu1UeQ^H@SNGkq{#M0g_AJ3K^wmPa`&t0;>08KoZhxTv4r zaI0wOU39(Gz`Uqlah%Dsxv_YA#|$xaXX65B!_z@tv)2s}X&$|U&d#!_i{43kfn2P2 z(Z~VUsbq1a~vUZ-E5m(xiLAww3{+tDPGK)w;lGaJ)o5Pg^ zb&q*Nfh8!OG~i)c%m;iURy(g5!F*ZYW0X(oRn3oCboxiqp`p?Grul}pv$B$Jr3DIb zIBCbQ4;nO^ny*JGPRyGim6|q7T~gVlwi^3=NNV!dSRO=SaA+@T)(a}jy9UVG#0cAj z&lst6whQ**Pf{nBj_eUbY}7Y`+V5?Qzv;;D(E2|UA!=y-FJJsynXr#gt*5rr<5!F{ zr#j!Y+Ka?d1>>;_X6Rk&?;P8?Gw1}T@wtb`t~&lNJpYg3`B)g(-O_u~g1W@}j}*I? z)BS38q(i?dW~lVGFYMCP1@4wBm>T&wG(IwF;}02xNjsP_)s;JJgpxHU;L_CRW!ij6W3xNo!|hx@ zPx1`drY{4Xw@vkOgd-S}qky;o!P>&jGOUyjBLL5qZ0 zjDq5BvUG3bCfwrSu_I!NzRP1O3KZAEiYwRp4ifuvi;)h~n!sk}0_5#0ABPYy_U`EA zplRKgE$@U8#zw`?PO~qxRR$^?bz-@fzIB}$=$qRgZhpuFoC*^S5!g$6w=tVQ%;-F-KxMsl)>{;cxA3Dz9UG_M}#tuX`xoz9M8X3t==(3KEde>@v$RY(#+N2nJ zN2N&GzkgwCo7c1UAHh7xnByc|BysI=6Al(oN@#CUF8i~1&+Z261}UYnpql&9~<7r!;O{wXVZn|7o>T|fE*BU+Veb`m+Varz@ZK=9oEA3pH;mzUMfcfRM zZxim_m>N?*$-MPWb!3`H!YkvZ;f>-pI#Jc==iWk z9j81YJ|3Ue=fpXurXykv`i}@JYee*UkOUVCCDq$~s$RTjmbYzawDxf=1nd`38Qzf% zZ6#toJ%VI2tfWMn>t-iqq4d^P^?_bp?P!m+E7u=c7KJRnh&OJXw75jb| zhF2`WUeRn9755|(&#XNkv~}Fwp|uK^7?AXLHNOwPm2YZAy+u}_{PfHM)xGh(C(Q*? z7$ioGHwWVcMMXcDIWNTP3=2zmTcA-yQM`GcinZ^Jo5uLB=Fz(kkuo2R{FqKQdJ(3F zt0MA7%dE`wa3w)p1kNZ1+^20$J_#kI#niXgQH0_YZ?%5P{(2E$TD`fkM#K|lk;9kV75s#7a=7PB#lkkV zh$?Ly2>g5n;_HhFPVO+`md3Vmb~ZyXRxrxsV`fd0c-<6ImNagCtT~0^H!qNpCQ+qcC1{ zN&OhVzIAyuQszfrowtkl{c9@<=F1}MQl(ANdX_^Gd39FCDB=M}ki?epS59&0@17o@ z=SB64f*lg}a;E)D1M?+W-b}9B+}<0xH-;h*B!Ze-`6Q8Zt~Vz{dZ+!iG1$juHgtrp ze;HuXuAy4gI1B#c3&-EDS21|r`gGTIX}t1*`99ug#vtsiU{p5@NmVygpL*^I*{sJ#Wc>4RI^7XfwsVBLE&ywif}Okw!q{Ponfy7GX2Ped94Kao{EICIlK!iX9MI%*%t{p1hvR{YFsE!Cu)9_~f)lzz0X2$w(OHSV8cf!!gc*i?>#&ho z&4JsL;S4(yIraIM_Z5zQd>m)}d~Kg|22u&5D3*X6sJQ6+63&`Y^LsPk#7@9}**In5 z|J_M}R|kDn`D_x>VrohIiONM~&96xJfNOR*nL?+qSolffi}ON%{r?IC@=bDwWxuf{ U{LQ_IKI&;LH9gfb6lNH>U}NS6%V-3>C7puiwV57Iq!cXRf5 z-_JSkdd`=#-gB?_)5}`dx;C5H*Iawp^Z(U9L|s+xJ}wn58XDSt1$k*rV4grjyQ7MY z2^IAZq49$DCpGJ{_@r#?G3gbJMn(wA$a| zyxI>>yG?bT72c_1LL2-UiS~*k2>%uTzl|Cn@@i(&?~{Z{=`3*m95V0zr_t@w=hCfs zdg$I8uZMqGTlG{&Vl?ia-B=|rDDn3sJgn|cDhVbATdSwipI$rC3(W=f;+yiJ{d)Kh z3|nlc_=;T*o00r<CNoxms%_cKxw5?NVL&1RlBA6#b93c5o8|e^|F%Rb$9l|%D^e0l^l zRA={GKEI{v5R~g}5xC?8lr63B6NixS&C#s4R-sYbo6#y$0$c)dm0svCCb%!Q9xXP3 zcn&1DHr;3Vqt`K&yrB8zNkt*3Xn3?>V1_qkD_vI3s9=6R2cr>>q4%ye9-XG5BChZC zu@KesVjkb4Axw6i{xn)do)USH}D-eORZMD*puYLV!wJqAS4$Sap^p~0?*jG-W$ z)}uoE+2*WJHcBIMCpt+BW?NfZ`1c&XG+}bLIoEJmCUcz_#?B`U3=A`Tf;WNF!5i7} z@+vA|)92&~d^WAG(7hFvl|cpyHF)HV)h(jr(CyxF*JF? zo%ZELYw9BlnBnwD|L@7z+FmKYqTu;h@0X#O& zYBR6$tankCChhapo9MUuR847k2~m$f;WL_y`1UL-oy)aeYA^J6cdte#hT}yiATh|E zvfLfSXF!dmRfvg+$qCQy9nS|0OWi~L{SQp7WgqhSg-%XRF4~BM)0j~OnWWuI=Z-GrI{zgGTfephJc!|g4)Rbu(?}xNbH6O`4elvYIl3h`8IXO&< zXTS<*$qZ&!sWJONh#Sy@IaP7FnT{QaH!AN65Z+(aH!S63!KsV+1}m`eSbeFJmY1~ z(C6FQ9&F&%{Y`LuNz6YN`h6V02hN}-H!^XBm-?hU!1ho6n*ZDixyIT2J>Ubl|B=A3 zvL;bMMWrP=H8p&Wo9{z3uc@i&Qsf-458&`A#j*#!&ZHTJj;-0ZsVV)BiWtf>kB97@ ziPO-MkSt3W*S%~0h(07EV*mCnM*%c*CMAlTVBm434L0T7Yy^bCzM?4j=S zpm21@*S7IiEsVq5{7K6Dj2?K{rL@H$d}$dON&^D}B)N$*Vf~#`vRg_DikGS1HnNya z8M(Rb;}cWkPh~jVi@`o7SFLjsvMO?Qmrpy@7Ss96)pnB%Gt)7z~?ZiGCs^^-d=ZH zlDUh_J#3jWMJ{J0=6*4QaP2Uf(R}^=L=ss{!Z^QlR5hOa!^~@I-V%)Z@BR~m%4K^p z)qd_~HK?sKl(Zn0St%w;O=@Gr5}TA$H`-}(Yry*pBL zS&(Rb1JUcUAc=8(w)6lO_rl;_*1H8pjPtva`60HA&CMHm`eS)Y4paiAtiMuTq*?Uo z%14XO<99U5WA6IjQcDCA&}AO3e&^~v-I`D}?ZVGgO-n9Ze=%pP&XqZFv|drNGe23^ zyWUAot#x^Fe;uK7IXqEQuzLyF-`~&fOqFc$ZU7HZ0(H}F?k3(#xjx@+ax{mSbvOg2 zVXwwbfP=#b7sS@%emh#2lzg)<_dfaN>W~{!X^iRVrJaW;X&CwzP%+#vXP=4ey={aB zrKLT(heZcIZLqtH*DkwAPEAvat=Qc(duHKlK2@Y;l+&BQ)G35#H3OrQKCNTsGPt1q z_$i&O)&BUEp=}o-V!g<1aT&ap67#E4 zUZ{92;#iWtzqt+$duo@Tm}u2|7#mBpj!eKRS%tx%;LX=fZp^*ftMC{j#DU{dzGgi8 zbI>~!nmm8&752?Hd(3*SmHPaATa|qHF4l=AuU^`O{VN?P>+ODML35b~%Mu~n&xYI;` z+FY^q^~FG8CY->pM0>l)dIXv@=IY92*+@s1A*PIjgJYA->k}KN#jt;trrf)<@fT*#c_Few_t@~mBFlWZM5j&WV7e}I{O(3QrgD^Q9n26ohF^yY-h?} zpDRVo^>ut77>uBvb0^GFvM6N*aB+ z$$P1ieh8+VuMqdCWG7c|D7({YqWTnE!sM{|y8Wfen@(BX>~6PTtQ$E=Y4` zmy|{IVuQ=N*JSOw^Tp8!0r*7)q;7J)u0yopoL%g0b zfkRgs^8mApqk8}qGx6H4yNzjSX|dX84>3PPY~~><-|%ZVzAl25W@1U^x4)P>6Ybkr zUeQixQQq^N7pm4hIOq)=<>JuFZ%(i`)FxZ))04bqd9wByx74=h6+sYZ2JQo~{0G{- zOBTROqD)Px7|hN`ryQa*4SwBTJLDF+2(S!dF_;=}jGnR;Y>zvBrg#4fp8j_QOthY% z>D>WK=WCV6^GwV=W@=Gc-F#*W4O%*>;*M{{ML(%Z-#mrac|^?gf9#bTUSfmN@?+l7 z_VMvq?h)*|hk-%EVvPP@#MiH!nT3T4XZ#iX%(1qn=DTh(fV~;n_4V~H3j_f06=%Z? zY?uCq31DnmkC~)<4B;Ot9-dK|o105=M*x6tk?rm6syT}G{zX$tsPEPL2 z9;E~v?U@w(Ofaki3k8F;Pki?NM%V#17jjPt_*qft4kORF9_mBsOH|GuTwXSFAqTEY zfdYxCJJ|5*AiY(%*=VRS;wfoGJJMJOW(k)WGVFvN?pe)^RBE zkm?>o`PWA2u5dFbfitLSi_0UR1Xh3`|81CU=n4u9X!(106{od{FNp0e_LDe~kAJn);% zf(PE+>@bh%u`z8`E{UcWbUd`_3dV?se3;TDb&}Ke=KF(sL!o61e=vIS>p1(6mrSmK z1z*yl%pTc8T~SaG#plpaJ{S!4ljp|@qwT#Nt{eWRPv5-^Ku7`D`}*}XJFg(eZkYB~ zq*W&wVdZ;hc*xqCRZdt~ScFwia>#`GP-q0baeyn%ZQ$Z(F>O`<2UahhzL z^RnSz!=jP#vF48=o@cmrjUVv3u3CiRQ#yXi0Hc`EKQTn_7|rdwtPS3{^oEjg$s&8j zWei}=$^#;YH0blw6j6oBNlr&Mm%WJXmQ%6(R^Q;*hzPDdYToW#caeH(!_jYofK8=Ioc%Q z&njzba&SpSp0IC(CP#h7&RO{G9WrLe%Vj8%5=!p>LG0#CNl`%|3sI6V6vKqIK3T^B zs>y%Ra%Mu{b+OJuFnt3s1?%lem-dSI-`a z(`M4%?sxB6pYG&f5D+koEH8FCFYnxZfjL;ZpB^1k3zTL9b+qWI0-f)X*!DzCgluH0 zyh=(vqrbm+vZyzaO7b(MzJ})AdUDQ0hC4psdmS?^*&D-LdVD$&_byNAxOvniE>Cx} zcv{D^#?<8H9~w-sfeKXbCckw21aX`H7WK?-^5wkqgjl?7*KQ?;hu0n2Fb z|K$acRrM>APCFr|t@{$uO(3%eA|4*tNto5(uTDs!`_w0}2x3 zD+9ewXfk05ngI5$E%z7?5taEE!*9-*-Wz%qwN0i!vl_G_9X9CmhSK=kL+lePUek@ZEf{)g3aB(#3AuD!#t9$)>|ibY?VGLhIkFdDpSwu7%kFLGYNiW>HT}U3r@nzj$b>bccJU{Divp9-YOh zLCH+>Vok2b9Z|8b*eh=eo-k|vNDU4lauD*3S&spmMlPAlw34~ zi^_9+Ue9)PNOo?6pcTv+T3_F3D1FNf#PVl^KYB@#CTI5f;+Q%=l!k#p!p7&Mmq$Eg zXIdTtJDRx^Q**=mU3M9?(&s5vXEHSO8|-O-*+(N!X)L&NaC%A%?mq-onJ_=Uy*@Q6 z`HtCkyQ3BmAO}j&c4MZ?Ri=D_u=`bVcQfj4t(m91Hg<+rF`wORGsJfdIbIB4eo~i* zwV)s=(NeAF;>#(KUJq5;IBGt#QmYxE;&aUV$%TvXa7yA)9(7=QisaluVeiUw3B*%N zies0$FNXn3qqC|CvG`T*H7r{h!qYqmCbec!^NV-e5s}>6(>20)*E3#;6TeCBU0|OQ zdk>pd>0nqvSWJwLf6-UX(gc_5j~qqmxPNABNu8V;;ne%nd}i?w$$OkfoD{^&QZvYN74MPYEjnqW4WL`H}`v823kl5-D=+6-ditZD{Ia|fRZqOTQcDTtkK;wG(^bk0|@p%pxOU7Xkz^V%|8;^8Fxko zg{{TeO>jInGSmme&l1P>48YPE8Q?k#d`u})0QLU`-~g5b1fad$%A&I74^3!iTSx@X zup#H?jg?TGLoId4>W4p|fC1!RH88{cYpYmo9hN9AfSQEEG9IUvg`(8H_n#T{L4;?7 zp@>HG{?aFacZ}=x<>u!b%B!k&Is9Q3RaI4v-3}=Bfg%}BBA+;mq{|; z$+wSP6G*0eK!A&TKwk-YIot7mjghvYt}b3nX>jLPcUZ6`(H}uQWK;IAL0?bAMZ4DI zEp{oDWY_zb-1UmJhJ@A$Ny_;igw6LbvzFSALTm>^X$7@V1a@D>u9Tw7c;VS-d!m?!vHiO6gHa=qVf&BhmcU=xZ+1PWGkqQ#(T3N%^Wn1@RH^rxFmH!Y z^H4ouP1~K(JwH@e9!?WJNpS|1^a(a3rPk66AsGbOz$#r%UvC|FhpY zqqb(60#CN5WC#f@*G{(emv;$rUs*a;WBC^5bI#)hTJ2BE^Sc&$xGV-#hWX3gw)}E~%g<={ zD>>r=oSjSLomZMAva%R#ZUBW&LQO3txBw_T49~lO=U7!Wbiny73HrNyTPj6h8+;lV z7&V-$;6BhHYW#}TX0(v<{DNDZE7o=&AQa>b&C)0aVmIZM|KJg<#FdG$!|H6$@R{?9 z2?9a}$UCo{i{p~fC6x3IA+}TpgdC0&7T_J)AP%y&r(U2Wn`VnwgfyNu!-!BdbDTsH z;3SqAUO#FClx}YVk5OjFbBn&I4I)Kyp7fkNrMVohC7q+@GGfk&C z$_AnpF+6gnj8p zh!kM-4#{oyw6`<#uKu)Nai6oxWs>vDgToJ@$Q5XRsV1|VC4;{$gPCWcW?u0I3uS~X z_~H3l&Z+fOy~@$B(lvh>56>H6*9{6lEN270W*(%f<73$1W(C2|+VYl`y8*7RaKsbx za&y%^&XSaSkw|M{x2-H(%F_~zPao5W;=74aEXivnX%+M>SHHoYNS6n26CMdVMazb- zmBG9zdzMUjd4KmzG@3yNS{#|QRg|Ed=6Y^7K3`!0$0&6@qV@tj)7q z`YBh}*Eg;Pa6O7RB;N#ADz9k_`@-e?&RIWWESVJ`&7@e0P2D8 z%8_fc7A(iSK=y{Al_&a~bYpHCKo*A;8aFr32^)5Qq!dS84=&w7GFkPY3gkaGdK(y; zJOCAGsPq^vTGTaq=X`%!viw1&EoBzsKej7M z_FV-rGc)HsL_yM$wSz;{br&|^obCf&NYNj|_a)%kWCsmk|7EZa=mDlKu-N`9z~lYP z$n{gr0ssd<3-Et}i)oh`-$xc!)|@6dfO+BV#)TjLQ)XVx8$aU*!WK5&}%zr^3 zAzOo4-M}D16Q&06$tcY2!R0mF$j>q;dtk;pAirc z@Exa=7Q)A}xVWet(xc~TRBPfc%~AjP{k>W0sbt7D+!l`5XK zwz8xURlON`lA-wT!1F~dFQ4ip{CsdEBXQpC>13B#_Ih24pq3xqTSHZO9sqoWdX zp#caZJ*o^avf;AGDg;#}H@k_3N-Hsn6C*)a}*tr>@?_orSjc?nH*P}tg?~X8Fz;2%8V zvigvcqR6aA(}wEd9yLmML+WjL#8SlvrySapewQ2MGb_!4qga`li|8lD$A`Bjl-6e4 z#aV=fg_Fg6X_y~B9&Gl^P)8I$M+J)699~DQ=y6=DfJ}l0_*lW zM#pFMc5TJ$Umdl;-*N$MJ)EynQsjN=wywP^+D$1~gU&7+kR zCh)0>-)B>k>>{OvStwc$J>Zz5QAV&$_-zxjegJKb0NQHf!n``Z^mQW)xBJ>I7NJng0b!%;J7~fSCd3xTjEz#i#;rYnJSw?;J0(-)rzDbj^@$1)6hbtK<#~WGc zR1Lc2+T~!Q*v@buOqA~o6PGw#y$l`Oxu=m^!M-5?@#Pj;=XOGAR zoAZ1XY9-eV5taMYVjNw;_5{GTtIN9jT;d{A_Ido57*8Jxe zEmJy5SgCTlNUUlaZdG4}UX4oKhZ;+Nc`Sk(=?vd`>4>I{QR`RN7x%TYe*G-S;Lb8= zsxP)T0r(AQ^Yna`4zkDd4h`)A6xA0{gli3`^Nt)TU@zf_&hWkkMftCB_Ko-nkMZsU z`Sd+UTf0(RJM}@reTF%f2k6SgGhYj;X#!hLCiPubRh!LQUDo+*AZ>o8u5nW_rtM|= zZ6L0xd=+ngJ1H{V*4vx6hzQ?>kK9mXgZ<3o!MhA2ugIP*k8dsaEUiORRynjwb8(rS zT2)daij-{UWvpEu3^99t-?sh^&=1~4$fyXpZYbQ`_+@jPG0!wpvUa@t0%Yxl#qZP8!B4n% zFu7j8)NoE#4SlrAmajXv0s+X269Hi$w2kV2lMBE4YA=1->LA)SQ!)GIPe?>=nA+Bs~U@8 zL>fAag-@ZNU+=@9h~xqVd&`keb5zr~;U(39cTBZXEi6K{spz(o9ZZ?@?KG_ahjbuj+A z>Rl{1ZPTv-cjb!AMZIdXIdr(q&mm5IXIFyvc%uUkqeecCzu# zft33H%j5r)#~#Kw{ypRTzdCaT1HkhC&QdVO7~+X!{dL!8E=8{#uyRro*p1%7l+Hh3 zjJ1bh{#01?egQY_A|Xz@;1ZCSz8+v;qO43F5F$o1gQh03OPzdk-K$~$XL^OkQ;Bxc z+*!0z1dgq`Be{OG4`zv4^~AcMa07lUbEPV$q#Hm{gj}q|8ymry8UC{h zd+z{8EzWKGBC?b+`1H)E3Onfv>gL2Qog>>K!K#WelBX1dG2wo3q)_cfGrQ#9$!O+% zYF{85k*u*j>54+{qopX}VNt)8J~o88kjI`Sl~{8EY_7>&A5vwKWuC^RKc)e+D8c9E zqP&j1(kJW7)GC^XWo$Puv06_Woh_}`hfl5c=68-3!y;q`FD*8z)5Ynyp{F@OhCNto zZ3-x>XyvJ%ej!#h+Jc5zDw!FWDC?}g&c$+^3<;gT@Qe^psqzEv3TvJ2a9Q2>7!4VO z`^{e__=f>SW++>xrtt0W6)3XWa&M!=ceJfYEra}rH-{dbGcTqh zDTbyF#!(X7J9a8|*L#0a5UL~$5I6OKxRKiBi-Wn-%+s%y18!9O7Vj@odQkCtw53|T z$jz`4*E+yha&d@1724@?ln^A@)-4BDnD?G+3`=n7w?-G~zp-?0@H<2%WB@t1}|7%@G%whRq%~trb9!dPm4@E80fJa^OZi zsHO&YCWfi4xH~Q`ZhgB!ZX`|(Huy7M-)b=P_mBGDnl49kP&+frw6+_Vd>m_3?vEcB z`wZ8q`Dz(z3k#N3i$Aiy#5$b{Z5;&Opqj40B@Y(oD&tX(GSGCDgEdjVy>m(P!oK({ z`l9F(9ldR+FNqj2=K{p^KfJwlFt!fvb_ct;xvRCez4^{gxaarGZHwf28z55m-Dj1h zK82I|-_ATU{w6Q<&bY#(?D&g;UQ0LdjLG1U_0g*h6xVtk3lRR)k;xP&ypA~$-JU+@ z^7H^@H9CtkzBNB)i1Yt3oY$*f25}wrX>v1IyEuLVgrQLD8OwC*tg*U=h60OU5Um+l z1gNlYIk--%z!2p>vuox)Io^Ds>?(DAYcd_15R#Q=erCI_%uv{149nuh=J zS6k7X?DAsu1a@%p&jkNa6gvbEzt)yXcoSZge>JF_B489DiWEAKA}1p&h8QXMS;JRP z*ZFl@{LlTC=a$}-=^gSuw;q7hy)nvlRh|4xG4)#5hOXI=8%5L|~+;`4bg&|PD?8yUEKA$Tk^LYeRd!pJN z=o|5Xne)+GII#kMB<9k?5M2}XIh~Omx^U4lAo7f(lXiZwJ)9S|ytXFK&0P*%{qjUZ zvkqc0p|=Xqh~xHnIxqf4za&276M#`yr{R(g8-cXMR^P}-r}i8*1L;MHb(g(?to5y5 zOw1}cx>&m`$@N)>Y9Rv0W=9q@s z{&Z0;*gJ<V8$FZD!Rx;o4X3IuDNVV1sB2bGmt8!6X7 z|BgnQ(0$Hcb9ys$S>ORoym)H<<>Y&Enk&%hqWLR%wpi(l2GF&@H5Ic9Yy|$mnI32W zG;4fxE>>Lv1U9!Yu0wKZ*%e0%?Pc-|e4BsuY|tjO5U7?40RQS~4F)O^k8m3azF6PA z7H{`lyovp#?$PmY%8{1rpgrZ&=FH4Fu1&bZ5ghJ3TKQ&#bMAWtwflgh{ev%$OM(t8 zcItb$)2`-wv!y#j-Hnv$tDUB;plPn@Ud6E+RKJUnIk+O$Mg!AcJ=-*5KCkL3S6qQA zNbW^ZjrO?7xjOL+)U(y3Q*mN;OiK-{{kt3*3?6n9H%Ef%&klAic9?UoV`F-UZ>DM% z7c}&Ilk#Rxt6iI%kQFX7whv0(lut&~=1Ry)6yl(IVzaf@9Ju%*CX^UTa#6IJ2Fg8i zb7~}Vk(yy-+niCo1S?}@)SVPtG$`v2En4F3Y_lD-f+39HK&sKampr?KtRS7W#M5cd z|9Hc^E>fhH9*--Gd_Y?wmX7v(lSGjIMQ^{5LDPxGLJWexF|yR79CDoXME(f0@a6A5 zN*@BJ(kHjR)zzo;)!v-qTR^sfxNr{>7e&m;LEDgRO56#-!pn)>BQ?0@37oBPn_ZwQ zv}mu_u7@WSh<=OwqprLYICKo}scHuyy`dH24zn)D(^xIt0Gkc@j_E8WDV#7he zdidROMuxwAgPI_kYMcPmr33pB-~?1)nI;_d@Re#zg6f6E z8|jV`Jds`ffR2hi^gpJgH>V^Ehg*|79nd%9nT#4S1++U>2%o^?IYz>bMh bsCUtXcP>iOOq2P6GiVAjs?z0>#vlFztHJLC From c06fcadd9d4321243ce59029a679f13e29cc27d9 Mon Sep 17 00:00:00 2001 From: Kemi Elizabeth <97071326+Kemi-Elizabeth@users.noreply.github.com> Date: Thu, 13 Nov 2025 16:49:00 +0000 Subject: [PATCH 03/12] Update sites/upsun/src/learn/overview/app-life-cycle.md Co-authored-by: Tyler Mills <4887071+tylers-username@users.noreply.github.com> --- sites/upsun/src/learn/overview/app-life-cycle.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sites/upsun/src/learn/overview/app-life-cycle.md b/sites/upsun/src/learn/overview/app-life-cycle.md index fdb5ad03c8..b008ddf202 100644 --- a/sites/upsun/src/learn/overview/app-life-cycle.md +++ b/sites/upsun/src/learn/overview/app-life-cycle.md @@ -52,7 +52,7 @@ This structure ensures applications can start cleanly, scale horizontally, and s ### Autoscaling example -When autoscaling [adds new instances](/manage-resources/autoscaling.html#thresholds) in response to traffic spikes, each instance must start and warm up before serving live requests. Use `post-start` to complete initialization tasks such as: +When autoscaling [adds new instances](/manage-resources/autoscaling.html#thresholds), each instance must start and warm up before serving live requests. Use `post-start` to complete initialization tasks such as: - Cache priming or session loading - Running lightweight readiness checks From a9e5ff9cd5f1210cb190a2976fd357cace963be1 Mon Sep 17 00:00:00 2001 From: Kemi Elizabeth <97071326+Kemi-Elizabeth@users.noreply.github.com> Date: Thu, 20 Nov 2025 14:47:09 +0000 Subject: [PATCH 04/12] Apply suggestion from @Kemi-Elizabeth --- sites/upsun/src/learn/overview/app-life-cycle.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sites/upsun/src/learn/overview/app-life-cycle.md b/sites/upsun/src/learn/overview/app-life-cycle.md index b008ddf202..7f63db1f8a 100644 --- a/sites/upsun/src/learn/overview/app-life-cycle.md +++ b/sites/upsun/src/learn/overview/app-life-cycle.md @@ -4,7 +4,7 @@ weight: 3 description: "Understand the {{% vendor/name %}} application lifecycle and learn how to use build, deploy, and runtime hooks to control app behavior" --- -Hooks let you run custom commands at specific points in your application’s lifecycle during [`build`, `deploy`](/learn/overview/build-deploy.html), or `runtime`. They’re essential for setting up your app, managing graceful shutdowns, or preparing instances to handle traffic in autoscaling environments. +Hooks let you run custom commands at specific points in your application’s lifecycle: during [`build`, `deploy`](/learn/overview/build-deploy.html), and at `runtime`. They’re essential for setting up your app, managing graceful shutdowns, or preparing instances to handle traffic in autoscaling environments. Each web application on {{% vendor/name %}} can define web commands inside its `.upsun/config.yaml` file: From 1216c2c81b9d25d46be67c9081d44b92278804d4 Mon Sep 17 00:00:00 2001 From: Kemi-Elizabeth <97071326+Kemi-Elizabeth@users.noreply.github.com> Date: Thu, 20 Nov 2025 14:52:17 +0000 Subject: [PATCH 05/12] feat: added note and adjusted table adjusted table and added note --- .../src/learn/overview/app-life-cycle.md | 21 +++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/sites/upsun/src/learn/overview/app-life-cycle.md b/sites/upsun/src/learn/overview/app-life-cycle.md index b008ddf202..d4ad2ca52b 100644 --- a/sites/upsun/src/learn/overview/app-life-cycle.md +++ b/sites/upsun/src/learn/overview/app-life-cycle.md @@ -20,18 +20,27 @@ applications: ``` ## Web commands -| Name | Type | Required | Description | -|------|------|-----------|--------------| -| **pre_start** | string | No | Runs just before `start`. Useful for short setup actions that must run per instance, such as moving cache files or setting permissions. | -| **start** | string | Yes | The main command that launches your app. If it terminates, {{% vendor/name %}} restarts it immediately. | -| **post_start** | string | No | Runs after the `start` command but before the container is added to the router. This lets you complete warm-up tasks before the app starts handling traffic. | -{{< note theme="info" title="Note" >}} +| Name | Type | Required | Blocks Traffic | Description | +|---------------|--------|----------|------------------|-------------| +| **pre_start** | string | No | No | Runs just before `start`. Useful for short per-instance setup actions, such as moving cache files or setting permissions. | +| **start** | string | Yes | Yes (until running) | The main command that launches your app. The instance cannot serve traffic until `start` is successfully running. If it terminates, {{% vendor/name %}} restarts it immediately. | +| **post_start**| string | No | Yes (until completed) | Runs after the `start` command but *before* the container is added to the router. Instances will not receive traffic until this script completes successfully, making it ideal for warm-up tasks that must finish before the app begins handling requests. | For more information about web commands, visit the [Single-runtime Image page](/create-apps/app-reference/single-runtime-image.html#web-commands). +{{< note theme="info" title="Blocking vs. non-blocking hooks" >}} + +A hook is considered *blocking* if the instance cannot receive traffic until that hook finishes successfully. + +- `start` blocks traffic until the application is running. +- `post_start` blocks traffic until all warm-up tasks complete. + +Non-blocking hooks, such as `pre_start`, run before traffic concerns and do not affect when an instance begins receiving requests. + {{< /note >}} + ## Lifecycle overview Every application instance follows the same start-up flow: From 71ebbf1045ef7b5ccecfe160d04828041be0b522 Mon Sep 17 00:00:00 2001 From: Kemi-Elizabeth <97071326+Kemi-Elizabeth@users.noreply.github.com> Date: Thu, 20 Nov 2025 14:53:50 +0000 Subject: [PATCH 06/12] feat: adjusted vale allowances turned vale off --- sites/upsun/src/learn/overview/app-life-cycle.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sites/upsun/src/learn/overview/app-life-cycle.md b/sites/upsun/src/learn/overview/app-life-cycle.md index 4a21863db0..6f526bc732 100644 --- a/sites/upsun/src/learn/overview/app-life-cycle.md +++ b/sites/upsun/src/learn/overview/app-life-cycle.md @@ -3,7 +3,7 @@ title: The application lifecycle weight: 3 description: "Understand the {{% vendor/name %}} application lifecycle and learn how to use build, deploy, and runtime hooks to control app behavior" --- - + Hooks let you run custom commands at specific points in your application’s lifecycle: during [`build`, `deploy`](/learn/overview/build-deploy.html), and at `runtime`. They’re essential for setting up your app, managing graceful shutdowns, or preparing instances to handle traffic in autoscaling environments. Each web application on {{% vendor/name %}} can define web commands inside its `.upsun/config.yaml` file: @@ -102,4 +102,4 @@ For more information about Zero Downtime Deployment, visit the [build deploy doc - [Zero-downtime deployments](/learn/overview/build-deploy.html#zero-downtime-deployments) - + From 1feed1dd8badcdf260802516aeb41204a27d228a Mon Sep 17 00:00:00 2001 From: Kemi-Elizabeth <97071326+Kemi-Elizabeth@users.noreply.github.com> Date: Wed, 26 Nov 2025 15:32:50 +0100 Subject: [PATCH 07/12] feat: adjusted to include deploy hooks Added more info as Florian suggested --- .../src/learn/overview/app-life-cycle.md | 88 ++++++++++++++---- .../static/images/lifecycle/app-lifecycle.png | Bin 0 -> 26944 bytes 2 files changed, 71 insertions(+), 17 deletions(-) create mode 100644 sites/upsun/static/images/lifecycle/app-lifecycle.png diff --git a/sites/upsun/src/learn/overview/app-life-cycle.md b/sites/upsun/src/learn/overview/app-life-cycle.md index 6f526bc732..712242775f 100644 --- a/sites/upsun/src/learn/overview/app-life-cycle.md +++ b/sites/upsun/src/learn/overview/app-life-cycle.md @@ -1,10 +1,24 @@ --- title: The application lifecycle weight: 3 -description: "Understand the {{% vendor/name %}} application lifecycle and learn how to use build, deploy, and runtime hooks to control app behavior" +description: "Understand the {{% vendor/name %}} application lifecycle and learn how to use web commands and hooks to control app behavior" --- -Hooks let you run custom commands at specific points in your application’s lifecycle: during [`build`, `deploy`](/learn/overview/build-deploy.html), and at `runtime`. They’re essential for setting up your app, managing graceful shutdowns, or preparing instances to handle traffic in autoscaling environments. + +Hooks and web commands let you automate and control different stages of your [application’s lifecycle](#lifecycle-overview). + +- Web commands (`pre_start`, `start`, `post_start`) run per instance, ensuring each container is correctly initialized before it receives traffic. +- Hooks [(`build`, `deploy`, `post_deploy`)](/learn/overview/build-deploy.html) run at the application level and control environment-wide tasks during deployment, such as preparing images, running migrations, or performing background jobs. + +Together, hooks and web commands help manage the application lifecycle, ensuring smooth start-up, reliable [autoscaling](/manage-resources/autoscaling.html), and safe deployments. + +## Lifecycle overview + +Every application instance follows this flow: + +![The steps in the start-up flow](/images/lifecycle/app-lifecycle.png "0.50") + +## Web commands Each web application on {{% vendor/name %}} can define web commands inside its `.upsun/config.yaml` file: @@ -18,8 +32,6 @@ applications: start: "uwsgi --ini conf/server.ini" post_start: "./scripts/warm-up.sh" ``` -## Web commands - | Name | Type | Required | Blocks Traffic | Description | |---------------|--------|----------|------------------|-------------| @@ -31,33 +43,75 @@ For more information about web commands, visit the [Single-runtime Image page](/ {{< note theme="info" title="Blocking vs. non-blocking hooks" >}} -A hook is considered *blocking* if the instance cannot receive traffic until that hook finishes successfully. +A hook is considered blocking if the instance cannot receive traffic until it finishes successfully. - `start` blocks traffic until the application is running. - `post_start` blocks traffic until all warm-up tasks complete. +- `pre_start` is non-blocking. -Non-blocking hooks, such as `pre_start`, run before traffic concerns and do not affect when an instance begins receiving requests. +This principle applies both to instance-level and deployment-level hooks. {{< /note >}} +## Web comannd use cases -## Lifecycle overview +| Hook | When to use | Example task | +|------|--------------|----------------| +| **pre_start** | For configuration and prep that must complete before your app starts | Moving cache, updating file permissions | +| **post_start** | For initialization after your app starts but before it serves traffic | Cache warming, dependency loading | + +## Deploy and post_deploy hooks + +While [web commands](#web-commands) (`pre_start`, `start`, `post_start`) control per-instance startup behaviour, the `build`, `deploy`, and `post_deploy` hooks run at the application level during a deployment. Use these hooks to automate image preparation, environment-wide tasks, migrations, and background jobs that should run when the application is deployed. + +Define hooks in `.upsun/config.yaml`: -Every application instance follows the same start-up flow: +```yaml +applications: + myapp: + type: "python:3.13" + hooks: + build: "pip install -r requirements.txt" + deploy: "./scripts/migrate.sh" + post_deploy: "./scripts/warm-cache.sh" +``` -- Pre-start prepares each instance before launch. -- Post-start completes warm-up tasks before the instance is routed into live traffic. +| Hook | When it runs | Blocks traffic | Purpose | +|--------------|-----------------------------------------------------|------------------|-------------------------------------------------------------------| +| **build** | During image build (before deployment) | N/A | Install dependencies, compile assets, prepare runtime image | +| **deploy** | After containers start, before they handle requests | Yes | Critical, environment-wide tasks that must finish before traffic | +| **post_deploy** | After deployment is live and serving traffic | No | Non-blocking background work safe to run while serving requests | -![The steps in the start-up flow](/images/hook-cycle.png "0.50") +### `deploy` -This structure ensures applications can start cleanly, scale horizontally, and serve requests reliably, especially in autoscaling environments. +The `deploy` hook runs after new containers are created but before they are added to the router. Because it blocks traffic until it finishes, use it only for tasks that must complete before the new version goes live. -## Use cases +{{< note theme="note" title="Note" >}} -| Hook | When to use | Example task | -|------|--------------|----------------| -| **pre_start** | For configuration and prep that must complete before your app starts | Moving cache, updating file permissions | -| **post_start** | For initialization after your app starts but before it serves traffic | Cache warming, dependency loading | +Keep `deploy` short. Long-running deploy hooks delay releases and may cause timeouts. + +{{< /note >}} + +### `post_deploy` + +The `post_deploy` hook runs after the deployment is successful and the application is already serving traffic. It is intended for non-blocking, background-safe tasks. + +{{< note theme="info" title="Note" >}} + +`post_deploy` executes on every redeploy (even without code changes), so it’s ideal for tasks triggered by: + +- configuration changes +- new or updated environment variables +- dependency or service updates + +{{< /note >}} + +## Deploy and post_deploy use cases + +| Hook | When to use | Example task | +|---------------|---------------------------------------------------|-----------------------------------------| +| **deploy** | Environment-wide tasks that must complete first | Database migrations, cache clearing, updating indexes | +| **post_deploy** | Non-blocking background tasks safe to run while serving traffic | Cache warming, background imports, notifications | ### Autoscaling example diff --git a/sites/upsun/static/images/lifecycle/app-lifecycle.png b/sites/upsun/static/images/lifecycle/app-lifecycle.png new file mode 100644 index 0000000000000000000000000000000000000000..49339c1dd431fef05604e541dbea3ac0da0bfbc5 GIT binary patch literal 26944 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 WGKg)XMsvU|O!svS?^I~ph5avFqdG+Z literal 0 HcmV?d00001 From c4a36524a7eef555aa609c2bda3f1cd61d36a152 Mon Sep 17 00:00:00 2001 From: GitHub Action Date: Wed, 26 Nov 2025 14:33:26 +0000 Subject: [PATCH 08/12] Optimize images Automatically optimized images using optipng and jpegoptim via GitHub Actions --- .../static/images/lifecycle/app-lifecycle.png | Bin 26944 -> 21791 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/sites/upsun/static/images/lifecycle/app-lifecycle.png b/sites/upsun/static/images/lifecycle/app-lifecycle.png index 49339c1dd431fef05604e541dbea3ac0da0bfbc5..c42218b0d7c3660210a5c9faf7d2f72843b8aec0 100644 GIT binary patch literal 21791 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 literal 26944 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 WGKg)XMsvU|O!svS?^I~ph5avFqdG+Z From 79f3c8d6011d96d0806f0bb89500cdf20defc27b Mon Sep 17 00:00:00 2001 From: Kemi-Elizabeth <97071326+Kemi-Elizabeth@users.noreply.github.com> Date: Wed, 26 Nov 2025 15:35:56 +0100 Subject: [PATCH 09/12] Removed sentence start Removed sentence starter for better readability --- sites/upsun/src/learn/overview/app-life-cycle.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sites/upsun/src/learn/overview/app-life-cycle.md b/sites/upsun/src/learn/overview/app-life-cycle.md index 712242775f..4d61a1c715 100644 --- a/sites/upsun/src/learn/overview/app-life-cycle.md +++ b/sites/upsun/src/learn/overview/app-life-cycle.md @@ -133,7 +133,7 @@ For more information about Autoscaling, visit the [Autoscaling docs page](/manag If your [application takes longer to become responsive](/learn/overview/build-deploy.html#application-is-slow-to-start), traffic might be switched back to your original application before it’s fully ready. This can cause temporary errors immediately after deployment. -If your framework needs time to initialize, `post_start` can help co-ordinate so the app receives traffic only when it’s ready. An example of a `post_start` command waiting for your application would be: +`post_start` can help co-ordinate so the app receives traffic only when it’s ready. An example of a `post_start` command waiting for your application would be: ``` web: From a5cdfecfec17782e7add3b5fc515a85f42f03156 Mon Sep 17 00:00:00 2001 From: Kemi-Elizabeth <97071326+Kemi-Elizabeth@users.noreply.github.com> Date: Wed, 26 Nov 2025 15:40:27 +0100 Subject: [PATCH 10/12] feat: removed diagram removed diagram --- sites/upsun/static/images/hook-cycle.png | Bin 9085 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 sites/upsun/static/images/hook-cycle.png diff --git a/sites/upsun/static/images/hook-cycle.png b/sites/upsun/static/images/hook-cycle.png deleted file mode 100644 index 6d88befbb6d6d7b7d2ce18a81fa1702f8a632042..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9085 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 U{LQ_IKI&;LH9gfb Date: Thu, 27 Nov 2025 11:12:14 +0100 Subject: [PATCH 11/12] feat: added new diagrams added new diagrams, changed text according to feedback from Florian --- .../src/learn/overview/app-life-cycle.md | 120 +++++++++++------- 1 file changed, 77 insertions(+), 43 deletions(-) diff --git a/sites/upsun/src/learn/overview/app-life-cycle.md b/sites/upsun/src/learn/overview/app-life-cycle.md index 4d61a1c715..32c702a847 100644 --- a/sites/upsun/src/learn/overview/app-life-cycle.md +++ b/sites/upsun/src/learn/overview/app-life-cycle.md @@ -5,18 +5,48 @@ description: "Understand the {{% vendor/name %}} application lifecycle and learn --- -Hooks and web commands let you automate and control different stages of your [application’s lifecycle](#lifecycle-overview). +Hooks and web commands let you automate and control different stages of your [application’s lifecycle](#lifecycle-overview). -- Web commands (`pre_start`, `start`, `post_start`) run per instance, ensuring each container is correctly initialized before it receives traffic. -- Hooks [(`build`, `deploy`, `post_deploy`)](/learn/overview/build-deploy.html) run at the application level and control environment-wide tasks during deployment, such as preparing images, running migrations, or performing background jobs. +- **Web commands** (`pre_start`, `start`, `post_start`) run **on every instance**, every time that instance starts. They ensure each container is correctly initialised before it receives traffic, including during [horizontal](/manage-resources/adjust-resources.html#horizontal-scaling) autoscaling. -Together, hooks and web commands help manage the application lifecycle, ensuring smooth start-up, reliable [autoscaling](/manage-resources/autoscaling.html), and safe deployments. +- **Hooks** (`build`, `deploy`, `post_deploy`) run **once per deployment**, on a single instance. They are used for environment-wide tasks such as preparing the image, running database migrations, or triggering background jobs. + +Together, hooks and web commands give you fine-grained control of the application lifecycle, ensuring smooth start-up, reliable [autoscaling](/manage-resources/autoscaling.html), and safe deployments. ## Lifecycle overview -Every application instance follows this flow: +The {{% vendor/name %}} deployment lifecycle has two parallel tracks: + +- Deployment process (runs once per deployment) +This is where your environment is built, deployed, updated, and released. +- Instance startup process (runs on every container instance) +Each new application instance goes through its own startup steps before it can receive traffic. + +Understanding how these two tracks interact helps you choose the right hook for each task. + +### Deployment Lifecycle (Environment-level) + +These steps run once per deployment, no matter how many instances you have: + +- `build` → Create the application image +- `deploy` → Run blocking environment-wide tasks before going live +- `post-deploy` → Run safe, non-blocking background tasks after the deployment is live + +[![The steps in the deployment flow](https://mermaid.ink/img/pako:eNplkt2O0zAQhV9l5L0BKa3c_NEECalN1DskhPYKglhjTxqrjh05zpal6i0PwCPyJDhpWoq48xyd74w94xPhRiDJSa3MkTfMOngsKw3wSD9XpMROmZcWtYMP1nDse1iAHXQPRnOEDi2Im6UiXyp9QWGxeAcbH1BYZA5B4xFY1ynJmZNGAzfaManR9hMEsJmIrSc-DhqeLqFP0BhzgFet3NuJ6wNA_QyO9Yf-9UxuJ7Lw5EaIu2BwBqwZnL_i75-_wFlW15LPUDFB5bVdZ3r39d-e3xg_7D2vxX27keWK-TFs4Fkahe7tX2kLSrZ4JxT_e8qr5yaVWM82qKVS-UNK43S3C7hRxubHRrq7yNE8BszWku4iGs7WB0qpd5KA7K0UJHd2wIC0aFs2luQ0plTENdhiRXJ_FFizQfm9VfrssY7pT8a0V9I_ft-QvGaq99XQCb_IUjK_ivamWtQCbeHH5EierqYMkp_Id5KH8XqZrsJkHa2TlIZRFJAXkkfxck2TMKSrLI3DMKLxOSA_pq50-SYNkyxOs2ydZOkq83EopDP2_eWHTh_1_AfE39-r?type=png)](https://mermaid.live/edit#pako:eNplkt2O0zAQhV9l5L0BKa3c_NEECalN1DskhPYKglhjTxqrjh05zpal6i0PwCPyJDhpWoq48xyd74w94xPhRiDJSa3MkTfMOngsKw3wSD9XpMROmZcWtYMP1nDse1iAHXQPRnOEDi2Im6UiXyp9QWGxeAcbH1BYZA5B4xFY1ynJmZNGAzfaManR9hMEsJmIrSc-DhqeLqFP0BhzgFet3NuJ6wNA_QyO9Yf-9UxuJ7Lw5EaIu2BwBqwZnL_i75-_wFlW15LPUDFB5bVdZ3r39d-e3xg_7D2vxX27keWK-TFs4Fkahe7tX2kLSrZ4JxT_e8qr5yaVWM82qKVS-UNK43S3C7hRxubHRrq7yNE8BszWku4iGs7WB0qpd5KA7K0UJHd2wIC0aFs2luQ0plTENdhiRXJ_FFizQfm9VfrssY7pT8a0V9I_ft-QvGaq99XQCb_IUjK_ivamWtQCbeHH5EierqYMkp_Id5KH8XqZrsJkHa2TlIZRFJAXkkfxck2TMKSrLI3DMKLxOSA_pq50-SYNkyxOs2ydZOkq83EopDP2_eWHTh_1_AfE39-r) -![The steps in the start-up flow](/images/lifecycle/app-lifecycle.png "0.50") +This lifecycle details the kind of work that affects the entire environment, such as migrations, asset compilation, cache resets, and index updates. + +### Instance Startup Lifecycle (per-instance) + +Every application container goes through the following before it can handle traffic: + +- `pre_start` → Quick per-instance setup +- `start` → Launch the application (traffic is blocked until this completes) +- `post_start` → Warm-up tasks before instance is added to router + +[![The steps in the start-up flow](https://mermaid.ink/img/pako:eNplkk2L2zAQQP_KMHtpwQ6Kv2q7UNjEBHroqXtqXYrWHseismQkedNtyH-v7HXSQG-a0XszGkZnbHRLWGIn9anpuXHwVNUK4Il9r_Gzso6rhuCr8zfTCCGYSVkYyYBY72r8Uas3A8LwEzx6bzT0084KvLPkvQCUVuGz1M0voY7vFwXgceF3nl9ZySfV9AEsoIVJOSHnhupO2i3Sfm6irbt2OXEzhP59z9RpQ2CIt69XY78Y1f04lswLWXCGd51obhM0klvrn_UitCT38V9qB1IMdJfY_89UV-aWqqhbMeiElOVDxpLscAgaLbUpT71wdyVneC6wohU7xCxa0QfGmCcxwKMRLZbOTBTgQGbgc4jnuUqNrqfBr6P0x5Y6PklXY60uXhu5-qb1cDWNno49lh2X1kfT2HJHleBHw4db1pBqyey1XwKWUbrUwPKMv32U5JtsG6V5nKcZi-I4wFcs42STszSK2LbIkiiKWXIJ8M_SlW0-ZFFaJFlR5GmRbYttgNQKp82Xt8-3_MHLX2fu0Mg?type=png)](https://mermaid.live/edit#pako:eNplkk2L2zAQQP_KMHtpwQ6Kv2q7UNjEBHroqXtqXYrWHseismQkedNtyH-v7HXSQG-a0XszGkZnbHRLWGIn9anpuXHwVNUK4Il9r_Gzso6rhuCr8zfTCCGYSVkYyYBY72r8Uas3A8LwEzx6bzT0084KvLPkvQCUVuGz1M0voY7vFwXgceF3nl9ZySfV9AEsoIVJOSHnhupO2i3Sfm6irbt2OXEzhP59z9RpQ2CIt69XY78Y1f04lswLWXCGd51obhM0klvrn_UitCT38V9qB1IMdJfY_89UV-aWqqhbMeiElOVDxpLscAgaLbUpT71wdyVneC6wohU7xCxa0QfGmCcxwKMRLZbOTBTgQGbgc4jnuUqNrqfBr6P0x5Y6PklXY60uXhu5-qb1cDWNno49lh2X1kfT2HJHleBHw4db1pBqyey1XwKWUbrUwPKMv32U5JtsG6V5nKcZi-I4wFcs42STszSK2LbIkiiKWXIJ8M_SlW0-ZFFaJFlR5GmRbYttgNQKp82Xt8-3_MHLX2fu0Mg) + +This is the work that every instance must do to be ready for traffic, like preparing local caches, installing runtime files, or loading ML models. ## Web commands @@ -33,36 +63,38 @@ applications: post_start: "./scripts/warm-up.sh" ``` -| Name | Type | Required | Blocks Traffic | Description | -|---------------|--------|----------|------------------|-------------| -| **pre_start** | string | No | No | Runs just before `start`. Useful for short per-instance setup actions, such as moving cache files or setting permissions. | -| **start** | string | Yes | Yes (until running) | The main command that launches your app. The instance cannot serve traffic until `start` is successfully running. If it terminates, {{% vendor/name %}} restarts it immediately. | -| **post_start**| string | No | Yes (until completed) | Runs after the `start` command but *before* the container is added to the router. Instances will not receive traffic until this script completes successfully, making it ideal for warm-up tasks that must finish before the app begins handling requests. | +| Name | Type | Required | Blocks Traffic | Description | +| -------------- | ------ | -------- | --------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- | +| **pre_start** | string | No | No | Runs before `start`. Ideal for short per-instance setup tasks, such as preparing local caches or setting file permissions. | +| **start** | string | Yes | Yes (until running) | The main command that launches your app. Traffic is blocked until this command successfully runs. If it exits, {{% vendor/name %}} restarts the instance. | +| **post_start** | string | No | Yes (until completed) | Runs after the app starts but before the instance is added to the router. Use for warm-up tasks that must complete before serving traffic. | For more information about web commands, visit the [Single-runtime Image page](/create-apps/app-reference/single-runtime-image.html#web-commands). -{{< note theme="info" title="Blocking vs. non-blocking hooks" >}} +{{< note theme="info" title="Blocking vs. non-blocking commands" >}} -A hook is considered blocking if the instance cannot receive traffic until it finishes successfully. +A command is blocking if an instance cannot receive traffic until it completes successfully. - `start` blocks traffic until the application is running. - `post_start` blocks traffic until all warm-up tasks complete. - `pre_start` is non-blocking. -This principle applies both to instance-level and deployment-level hooks. +These rules apply only to instance startup, not to deployments. {{< /note >}} ## Web comannd use cases -| Hook | When to use | Example task | -|------|--------------|----------------| -| **pre_start** | For configuration and prep that must complete before your app starts | Moving cache, updating file permissions | -| **post_start** | For initialization after your app starts but before it serves traffic | Cache warming, dependency loading | +| Command | When to use | Example task | +| -------------- | ---------------------------------------- | ------------------------------------------- | +| **pre_start** | Per-instance setup before app launch | Preparing local caches, setting permissions | +| **post_start** | Warm-up before instance receives traffic | Cache priming, loading dependencies | + +## Deploy and `post_deploy` hooks -## Deploy and post_deploy hooks +While [web commands](#web-commands) run on every instance during startup, deployment-level hooks run only once per deployment, on a single container. They do not run during [horizontal](/manage-resources/adjust-resources.html#horizontal-scaling) autoscaling or instance restarts. -While [web commands](#web-commands) (`pre_start`, `start`, `post_start`) control per-instance startup behaviour, the `build`, `deploy`, and `post_deploy` hooks run at the application level during a deployment. Use these hooks to automate image preparation, environment-wide tasks, migrations, and background jobs that should run when the application is deployed. +Use `build`, `deploy`, and `post_deploy` for image preparation, environment-wide tasks, or background jobs that should run per-deployment. Define hooks in `.upsun/config.yaml`: @@ -76,52 +108,54 @@ applications: post_deploy: "./scripts/warm-cache.sh" ``` -| Hook | When it runs | Blocks traffic | Purpose | -|--------------|-----------------------------------------------------|------------------|-------------------------------------------------------------------| -| **build** | During image build (before deployment) | N/A | Install dependencies, compile assets, prepare runtime image | -| **deploy** | After containers start, before they handle requests | Yes | Critical, environment-wide tasks that must finish before traffic | -| **post_deploy** | After deployment is live and serving traffic | No | Non-blocking background work safe to run while serving requests | +| Hook | When it runs | Blocks traffic | Purpose | +|---------------|---------------------------------------------------|----------------|--------------------------------------------------------------| +| **build** | During the image build (before deployment) | N/A | Install dependencies, compile assets, prepare the runtime image | +| **deploy** | After new containers start but before they serve traffic | Yes | Environment-wide tasks that must complete before the new version goes live | +| **post_deploy** | After deployment is live and serving traffic | No | Non-blocking background work safe to run after the deployment completes | ### `deploy` -The `deploy` hook runs after new containers are created but before they are added to the router. Because it blocks traffic until it finishes, use it only for tasks that must complete before the new version goes live. +`deploy` runs once per deployment, **never** per instance. Because it blocks traffic until it completes, use it only for tasks that must finish before the application is switched over. -{{< note theme="note" title="Note" >}} +{{< note theme="note" title="Keep deploy short" >}} -Keep `deploy` short. Long-running deploy hooks delay releases and may cause timeouts. +Long-running deploy tasks slow down releases and may cause timeouts. {{< /note >}} ### `post_deploy` -The `post_deploy` hook runs after the deployment is successful and the application is already serving traffic. It is intended for non-blocking, background-safe tasks. +`post_deploy` runs after the deployment is successful and traffic has already switched to the new version. Use it for background tasks that don’t need to block deployment. -{{< note theme="info" title="Note" >}} +{{< note theme="info" title="Runs on every redeploy" >}} -`post_deploy` executes on every redeploy (even without code changes), so it’s ideal for tasks triggered by: +`post_deploy` runs on every redeploy (even without code changes). It’s ideal for tasks triggered by: -- configuration changes -- new or updated environment variables +- configuration changes +- new or updated environment variables - dependency or service updates {{< /note >}} -## Deploy and post_deploy use cases +## Deploy and `post_deploy` use cases -| Hook | When to use | Example task | -|---------------|---------------------------------------------------|-----------------------------------------| -| **deploy** | Environment-wide tasks that must complete first | Database migrations, cache clearing, updating indexes | -| **post_deploy** | Non-blocking background tasks safe to run while serving traffic | Cache warming, background imports, notifications | +| Hook | When to use | Example task | +|-----------------|------------------------------------------------------|--------------------------------------------------| +| **deploy** | Environment-wide tasks that must run before traffic | Database migrations, index updates | +| **post_deploy** | Background tasks safe while serving traffic | CDN cache clearing, cache warming, notifications | ### Autoscaling example -When autoscaling [adds new instances](/manage-resources/autoscaling.html#thresholds), each instance must start and warm up before serving live requests. Use `post-start` to complete initialization tasks such as: +When autoscaling [adds new instances](/manage-resources/autoscaling.html#thresholds), only web commands run, not `deploy` or `post_deploy`. Each new instance must run `start` and `post_start` before receiving traffic. + +Good uses for post_start during scaling include: - Cache priming or session loading -- Running lightweight readiness checks -- Loading config or dependencies into memory +- Lightweight readiness checks +- Loading configuration or dependencies into memory -This ensures new instances are ready to perform immediately when the router adds them. +This ensures new instances are ready before the router adds them. {{< note theme="tip" title="Autoscaling" >}} @@ -133,7 +167,7 @@ For more information about Autoscaling, visit the [Autoscaling docs page](/manag If your [application takes longer to become responsive](/learn/overview/build-deploy.html#application-is-slow-to-start), traffic might be switched back to your original application before it’s fully ready. This can cause temporary errors immediately after deployment. -`post_start` can help co-ordinate so the app receives traffic only when it’s ready. An example of a `post_start` command waiting for your application would be: +`post_start` can help co-ordinate so the app receives traffic only when it’s fully ready. An example of a `post_start` command waiting for your application would be: ``` web: From ebbc9d35be9c070c33b863ef039ace667fc0c7f2 Mon Sep 17 00:00:00 2001 From: Kemi-Elizabeth <97071326+Kemi-Elizabeth@users.noreply.github.com> Date: Thu, 27 Nov 2025 11:14:51 +0100 Subject: [PATCH 12/12] feat: removed image removed diagram --- .../static/images/lifecycle/app-lifecycle.png | Bin 21791 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 sites/upsun/static/images/lifecycle/app-lifecycle.png diff --git a/sites/upsun/static/images/lifecycle/app-lifecycle.png b/sites/upsun/static/images/lifecycle/app-lifecycle.png deleted file mode 100644 index c42218b0d7c3660210a5c9faf7d2f72843b8aec0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 21791 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