From b905524ae56ddb9e67ca623b0b9b6ff4dedf3a96 Mon Sep 17 00:00:00 2001 From: mfoltz Date: Mon, 18 May 2026 12:00:25 -0500 Subject: [PATCH 1/2] [codex] Add Thunderstore badge to prerelease notes --- .codex/scripts/prerelease-notes.sh | 7 ++++++- .codex/scripts/prerelease-notes.tests.ps1 | 9 ++++++++- .github/assets/ts_badge.png | Bin 0 -> 15058 bytes 3 files changed, 14 insertions(+), 2 deletions(-) create mode 100644 .github/assets/ts_badge.png diff --git a/.codex/scripts/prerelease-notes.sh b/.codex/scripts/prerelease-notes.sh index 1acc09d..a327217 100644 --- a/.codex/scripts/prerelease-notes.sh +++ b/.codex/scripts/prerelease-notes.sh @@ -140,6 +140,11 @@ if [ -n "${GITHUB_REPOSITORY:-}" ] && [ "$RUN_ID" != "unknown" ]; then run_detail="[${RUN_ID}](https://github.com/${GITHUB_REPOSITORY}/actions/runs/${RUN_ID})" fi +handoff_heading="### Thunderstore handoff" +if [ -n "${GITHUB_REPOSITORY:-}" ] && [ "$COMMIT" != "unknown" ]; then + handoff_heading="

\"Thunderstore

" +fi + mkdir -p "$(dirname "$OUTPUT_PATH")" cat > "$OUTPUT_PATH" < "$OUTPUT_PATH" < [!NOTE] > This GitHub pre-release is the source artifact for the matching Thunderstore publish. Thunderstore receives package version \`${VERSION}\` from tag \`${TAG}\`. -### 📦 Thunderstore handoff +${handoff_heading} | Signal | Detail | | --- | --- | diff --git a/.codex/scripts/prerelease-notes.tests.ps1 b/.codex/scripts/prerelease-notes.tests.ps1 index 9d75f88..b63eb7c 100644 --- a/.codex/scripts/prerelease-notes.tests.ps1 +++ b/.codex/scripts/prerelease-notes.tests.ps1 @@ -41,7 +41,9 @@ function Invoke-PrereleaseNotes { function Test-PrereleaseNotesIncludesChangelogAndDetailsCard { $FixtureRoot = New-Fixture + $PreviousRepository = $env:GITHUB_REPOSITORY try { + $env:GITHUB_REPOSITORY = "mfoltz/Eclipse" $ChangelogPath = Join-Path $FixtureRoot "CHANGELOG.md" $OutputPath = Join-Path $FixtureRoot "prerelease-notes.md" Set-Content -Path $ChangelogPath -Value @' @@ -72,7 +74,11 @@ function Test-PrereleaseNotesIncludesChangelogAndDetailsCard { throw "Release notes should keep the Thunderstore handoff card visible without a dropdown." } - Assert-Match -Text $Notes -Pattern '### 📦 Thunderstore handoff' -Message "Release notes did not include the handoff card heading." + if ($Notes -match '### 📦 Thunderstore handoff') { + throw "Release notes should use the Thunderstore badge instead of the emoji heading." + } + + Assert-Match -Text $Notes -Pattern 'Px#1ZP1_K>z@;j|==^1poj532;bRa{vGf5&!@T5&_cPe*6FcI%i2lK~#8N?R|Ni zWmR?Vx7Ob0PBrxe4T1y2D0ZO`8$nd)?gVG@;?vwBc_zN-QyCR#a7J&H2tfho35S@x z_mXIpFA32&YjratAcA(&45C0pnr`T!s_t~oUhDm_&$;*9Q@7^s2H)f3x9Pg)>@)4P z_S$Q$z4qF`Q+Ntb;VC?Yr|=a1e*|R@JmF9!3=co~-s>ssN2oH!$1PN!BK!fy6WZVv zRUR2021Z6CIkxiOuItmB9S9m~3k9HF@4Tka`4e?yDx_-ozq02unBz3MJTr}XT;3Ih z1z(t4Fx%VA195{kTuu$b;E7{^(NTk;AqN15|L|uoYDUrPMd@S`KBC@eF3acgmYLz4 zi!X@4op%5Lh-&L^Rsi7m-}snI{pbd1pU*Z1DPSbIZ+B?w`2Y~PsN*-q_ot+q`mgBr zEuGI1khZVyguj|v-KINO{WqoW8#)If6(g`pxH|jI2L>_mgKyt{?DCwsI0tuXa;n)# z2;LnOH(<8mRefu)rW!l0mu`UMgOg+F`=qZ!s!sMex<23k?s!&A!1VQ5!mG5YNN6(% z;(I0c?R;Jarl0pnq=OKk>f-t;mY787fnu&Oc-zC@s?Xlq`x2w01{*d+ z`S1MT%tKZVT;wL}VUH;QqDEDaEwdrr`17fMppYf*fkHRpCs6W52!N923k3r7-M5{7 zToqW)2Sfr?RC$C*SO56-HLf{vJ0V~W`ddx>k8RSI# z#YiiONYziCqKT50IX@G!5@5ET$O=HbWJ-`oumo92GVS>pC6Kf26Q9ps=S4mcnz)?= z&H#o4o41~G()#kKnz12rGq?6W#K_nf0nqSq{d6GtzzTyw1QHNYoA~oYy2p#^jKu%{ z9YW#@oRTsi>_lZF0E~?d0jZ9#|1hcsLqo3j2lu_cxO(*;LkiBgoQYTvng}wNE%PK3 z^S^IUj-V`#!N#chyKV1S_p|cosKMBn1AzT&1*j4R0jzmt!4dsyV0pO-LjXj=3Xp@> zg45l$+o+TluMAFU&e07?p>NDY{R(C#L|8y-F3@Y>cLJAlobEta!iU1NjL}IO$Gy*|D5P$?s)GB^B=`6`PLj+>~FQaX0CFc{U zsvnnSdQnyHn911o08-C1Nd6--AhJ;Qg~)bZ)D;ZUcJU-)u=!}` zG+j3<0RSNFW=VQRH)csofKER`XWgvpHjS(V=mu8qxM#XPYdox_kgn_R-`z}1_xQ8~ z=w^QU6L27y$*GC&KKPzjy(TgHGPU-j1W+ZJkWZ*HM8Zf4)E9yQ!L-IP6TeED`19%c zlp6Pv`pHm`E||yt5&|dhlr1wMIZuh6kQs|R(H_^kmrU)-T1i0(2zUihj;u{U+?l41MC*6Ys^KcnZW9at)i{c4axl% z^NcLAjNut^ejd$*B1`<4phONJ2Fd5QyzRuh%A?8{^E0nm?AswAj^LXzUg8)LAN0w?Kvdzy+2KON;x|d@jm1I)qB=vYvkyxy#OPD~-)`?7Q0-CuDIOmief0JZ1jvm!J(W~4pW->uGk;o!f89l^9Fas)UPTI8&>v<;PW1mU@RR*B_ zKl$a6rI3ChRLwV=bqY+8+KQge?RTxmV}rITJX-IL`ljr8dB0>DN>*{)=LD68Jl9KP2$X9HLa3%@{lrE+666V zPpZU9bE{+&#`b#))Jp(J7;PLI8gk{bf5r6sW-*OGi$ZMn4P1TG9|y($A3HeLjP{zG zVHmMq`%lJ5@eGi_WL{w=36LC5TnQ{GAF^7IdM}$|3ZSS(fWY}i4Hg=ziamX7*2sv^L3c|hh zZ{Gi&SC`A9qh>4)xtk69LIO~wT-LIxk+5;4NCf8`3>%1&*T!38es;X>j--Bfr~q)n zL;x|VVI#z>#H`A!0kh1HLc|I8_-RrgGVwh5Jdu?moY?Kk5Ec~!1`Gp+ zBPMoCEHDfW7#hTXw|{4gVEVDnGW~iM|Gid&z=&=11ikNpDvfQ~GE)O~U;&>$1L7#3 z{%dbJJ%_>cUh%hN~zP3KxqlqXdLGSVNH^ z4Wu#km96hO>2J&BQ8PA!*_XxA7@$&N0O&vQmCK@h?k;V(RXq{ID6u0i?pRG6_T(Ef zE9SZ}K&Nhy5I_YWw$|LNiZ7@{n+wYhdE|jjzll};O{r_vw|@@~DzL_2=;-D%{^e(X z=bFtovmg?NW%UfXSOy?6V3%_sF-~fuE5gEG)s`1%>y{moJbxY5r>;ikJriW>EDoDT zHbhXR*|h#Fmc{_B=-yjCxvIDK+}f_)Q4a?e02&5xAm6yM1O`y2An!_6=tVnUf8wRS zE6o#egXF()!?RadyCtZ*z=(gaQg)1;&Hzf%>b2Q-hZqeCeHu006uH{quikR}Lwo zKeVngZsWUV-{ZiP1ri_eg^NSn`&a(^?cW8{tBi^xg-Lppl7mpUUeo!=WDcN(w4z9n zvnDj5HCJzc%}Za0TW<}pc5O8853N)fBO`k7H-CBrIoXnPnkV()XxW~h^zxRKp@35Z zha6Y|gE}bIYm|Tn2g1UXYvOLMZa?O zxI`yO3c88Rg+Nt(OpDfP_4)-+C9GZR=1qJ67#t=5T5$UA9+(0I4n$rjT>#SceS;MPkm7kmz|;g#g`(N=U>e6RP?)AP|Lu`CpYXl(GPmD1 zESv$x#u!90VC3u|pF7GEW#-AAxsaYYYrBY505t;hpCR1eqEcZDuU}XL4-ONEG_-PI zzK}15VdRLtXEHrmq|#}cd4EOh--k?}TM$)-qd>xHDS($u^R&62j93`qDiy|-En52a z&4-i_e$W~xDiJ4+8&!p<#HH=-6;%jahjyQJ_9XQhjSy24buAQo$u;HukG<|?6G?PY ztMXi^D5DHne$}Z9J^#&vw9l)^y7-gSjk&r8`VDc z;2V#>ADcFrbd25a8x|(IV^O#ITQ_~Vf7!rWckP{U-Zrb%1FMbKe#(2TvbyN+8$Q}Om&7Wck-bpYK2-f#*@10DLW&p&p2g!Sp z_*FH&1{hAPi-;Sw`&X>&fBq|nPHc<-GfuT;K&b4Gp)!M!1q_o5Vt|c-bM}SF~Z*N zpAQ4HCUnr6d{J<0(L}Dmp()7Z>wf;0S6@9}fBTae3uXZP@VZSaN-Neyd-ggTsWC7e z0Y6y=XjuXY1HdVYAD@l5?1e0SFLf$0R0j&F|j()|b6z{>1l=p_l#b1Is6uJ#c89G1Bibk-@Y>60CK+43}{!#H*+XdpQYE0{J}j7aYoIL0pdo@{rJ|h6&lS)?1IP{ z6OWCWYPjs|7N>goG$_NVj|&VWRB)tI&8exC%bvC7zE}U@Z!rv7kVuPr|Ehnv=8z)i zwz*o^XVrjV{C8&NA-bBW85=P$gles-xt<<%A%&>wF~2$MMfadG&v)~_2s!2xH$JP* zlRsxu>SYD;5)w$!Ai$+`=qy39a~1K?_}|pJLnSd$iGs$;H{SfgBfl|U2Ax|8R3((l zihsYg~rx7cQ9Lagh zdk6X@B&T5S^qCLwr$Nw&s>l}t#{`ZdeEc_O9e;OubOG-+G9u+sHFunU;%}(XdzoWv z6c$Q`6<~rg!7;(HQH^Ib+eJy)u`fb?R#QmhLM&wBLMF`B&7R@|AAP~)-|rdQvPI{U zb7@Wrmf=_TaM51SSL`{$3b`c4Z+Gkn-n1W+hV6LQ1w{kbN80_wH+Z2ehLsW8fA zIpUvgTuqTZedqS7x{yt0kjQ)>?LrPF$KqVWG^VN#_V*VrMMZgRf$ugp1VKf)mOJE= zb<6iQjpK+S2ZRdMgqjLfC7~Hhx^DU!Z@UsH5cL#`&oqVpcVT2i%42iWclHVuLC^zlKB7)a?*zpyUiNL$nDrzEJt4xW#$|5rWUq}xje2d` z!IxIU#ic{cXYU6%n6 z;wpfsLkCITt>uS^-#e+psW2@lyL^7Y?45Ey{>|G@8ujlseR0KnFg8T4JgVk_(~tW% zQ_~+8dY73xj6+Kjb}xpsRs6gA@Ux_Jwl@*6RT1fdhL?dz%Y$RH4g=k2Ga$!4x*%?IP7_RcU0iq1=;iShmU;iS)M<~DJ_p8I8qR+OjD|6 zf~tVh$sAObl~LU@6&8csc>u_V*exDoTZRSG()tiyRLbNk>7;3w)L0l-2P3h7J zA{g>>9;dzVmn+WGvrDzu8;{7O)i;Pf~P#0!V;Mk#r$XQ zf79{5Tvr*NmsUM1VukRYcb|M`ZDQg}rCiY{0*N?>h;wi#Af#NYxVQ+CVj-G?!cS3q zXSFX*0jFtCCIA#aQK=}yFAC~Pt?8|UILvEk$n_1r>P-f8d>lDFBNxpZX=12fMNzBO z9=A>Y5Goa(ZyZ|(Hf=H>Qb%%@XtWZJ9f2t6A!$n`>D@F-q_Bqy2u7j5)~V`;kVM-o z0&6Oxx%BU`EyIdRg>yk}xL&V61`zphUhi*6_iir{yd$bZpKpCrC;5`^A%anb69j9o z?!WoXV`D>ZU1hv0{ibt8lB;*{Wqr$g2e#T!4>f8OAoe|e=1!npB6_k>zm@`sI5g@F zSL!dBiAL?b-G6@KrxN#VN9DN?n>hpjbltMPT<&fwv?^*iKNiLWPwQ(j&&4`G_ua6f8HIt z|7~x#6++V(psZ@fh+O_Vn?JfN-}`QvbP>U%G8@cHqxmvGquy}&e2$xNcRl?XIQG=F zYuyO75(dm4aX{)}|MS}SEgx8R>Ey(eQ)xwD0@>$FJLq&)21p^`jt<<433MPR7!fh7 zFbZLWzyZZV9=oR|(0j-V?0o#OFWqL1p`?Cu|ccSTXBxso# z9@!_iF&_qCWjGO+&*x1olvnR~!?E96O7A~%?6&?!wR$%Z9n8$r)**IdfSHI7bb1R_ zL>a8r+ZT#(C6dxgZ@n@#bX z3B*jyhOM<61i82b90UOyV>vL)0Yz*$VqxWo019l5^5y}Gnr}>XuxSrZwDUX8edP}n z`tKkZ==9!|e*c8{X-s1f^-S!i;6YI&nq!maYV!&Jx;0}KwtvJLc>YJXyu8rN{~#Y3 zXGD!~J0K!iyPs~%>{>mzS@=a&T_{>87Q^afcONt^GdF;0Ac1M)F~T=z>vtr^{^A^~Yz;%XARkcyK`Z2l~~RM1v8Os-HRkczX248y(ZmiNBm`|0;e zTEqMM$Hy(4xl+M!KrJABh1m(LeCYBoRn*c*@AmP8k2Yt4yR^Vgl#w^>JrszOAR zrx6QYRL<9Dk(jth^}KH2SX*HQtT0$DNCU@U)10iH@$0kK-?FYUZf7Mv{M>zcRQZ;- zpKwnUg`YOovR~Wpkq|%0bwG10T~E-K7=CzSC4#Ct)hpLtb!)I@OIef7&+y}sCq&hr z9!T!_0J(;BreUL)3HAk4K*}QSk({+3NqqO&T602`uztNe=(E4~+34N1749kaUg9G6J5n|6uoMqs zpW$pF;FzHU2L#SAi4g-k=yp7I=Ew+1Vis~@fA{|Tt*d%WVc3WYiLj4`5vWGq-`{0j zA7{p>ZsOl_VEj7d*m3ou2mb3H?Jh4g%qxKp4%HPs^p^gC{=-AnjvNHp`7cS?)ya{h z_;hofwSD5sR2}UsfM3h6>Y%DH8aRu3S{@vv+fF}j zkB0IA5Rv*cYBREAI@E49v?LV(R${0Tjm(FRz2usMHe-{ZQejHQ{#94s{MkZJ&)KzV zBLX2d`+Sz^giM-QyN5*SNMZVUhN`-JiOoc9$89@h*9icyV2>Z#WB;LFx~(|S+jEz3 z?&(vgsxzH(sx2lNh=Q2(KEEI%1VbQ625q$v;;!jr7~cDthNdTtl%%8ut~cbthRGdw z-?=Z`iAseQ6C+ruD31U*y8oJ+a(#st?b$WudV5L+Vc60ESOJOMuQLhePMt?#q@A=% zfv8k0+C3Ayzj(*+%g-#2s$mQb$>INT$McK1!s*&itGprBWz}jXrT#(r}Hw5*1)fsC{6uQx!ultj0 z7B$<4xc3jQcLQI$ec9e-H2m=7UIYXE0T8fp0b9wjl^h%Af0G1$i8z!&j{PuU7@A`s zAiti$H*UwAhIUEDkUpjiCIhf_j$t0HPMxv!y)XIcx{7z7r|z^Mc(YK=_2-;;9q*}r zeIO_qR})7-YchDrAR=O;y?s5VROlH709rnF?Vz#tXU5n7M3f!tvs{)H@maIW#|Xwy zRo4`7&P?TcO3#1bRYyI5;o(Jz$XILD98oW9vJyQ;`-lH40$>4H zSVv^lXyC%b7`1;O6)O}F(3#sW0V!bP39vL2hzPJw&8N4W`I2+jjjP?fA+>m5v4}(3 zUi#7Np57q4C0FX{sn;g~_R5v2K!p5I9AA>|uSt(j-q-sLI=?LpLzD_d4Wlr!Y+p!+ ze(TnYL3B~<;xk#rBAd4_>*>pinGVmJa>OREb#a&Ne8V5TFLB+b>pu}V@+&|6h}GH$ zjJik>SV=KJM}x*XK>8b<6IUt~O|uz}-}$@mol+hgrm-Os&lgL_x{9|Tj=J>vONyo3 z`!%XZtcgz6twVPFY|VAF(8VvJ3P;}YbO{~u?OSgk(20J0B;IEX5Wi`tXf~}oYR~Il zyp-Ob29-xgxqI5fS+MI!#={eO$kPu#tVbJn8J#RxjUW`z{24$cm&>zr?jecXad)2e z(jALc`esBd1)h7^P0t+YD{Kp^Q#qd)J9ZAu!T^5UpIt)x`kvNMy@?L~)-5{-v;ZGUuo|88je zxd&J~cWdZyn`DcK0_w7XO0D7>%d;;5U=>&wnSC`rE*9l@p=h>Xo#!6^cgZ;2`ILPQ4H0s7nm60|C>7kIs!(;U ztzuecY)3N66nsoN?E<>UmM-8KxUM@ij><7dK$S2wwC~2rg`iU5u`=YCzrX!3WqB(! zRMJ-3$PT0%Gl2`$^_2Q88{PEN$^SU7JgR2%$O1fli@?|r2~>%VI|2ZFGMjyfgw~2( ztj=vy=TueHhj@27c0}4`VIUT$x*&H{@BhB}c~JE;jt3Y?@84USxG)GzuM)ZRaF--( zOpo`iA|%D0WyW#v&_sRWFEBEqabV{{8)N<`j~b}rk3PEjsAjW%6#Q_tpy9JcyP5hl z`EYIpZDS?+zHgB3m=1$?-8G0+PL z=oO#anUMOv^mqyYmJM7OL5W;{U!UP-_00P&c*RZoQ|W7=TsC7vlhLjeTPmEA4`K%^dSWrwVIL$2gX#R5Z~bKe|GGz#mU$E2L_1QFH~3x z(%eQ0G9ffCVgu){%+}qnh&BJ`e&xES5u3L{RpFfJ)+5qTRpj#ds8lN1J$oiTd*|6F zef0n-eZKbt$Pry>K!K{4)3d$rTr-1``QBW<;7X+ug`xY#ts^Jh&rqcxpS!qGuTK%r z;1gXWi~xBN6F4|!{K>)Jxb?ptC@IjIZYH{bfId+_n0B{z(?cw|zMdXCF*&jMu7e&r zAW9!vk-|gn*pJ=vXF-&ExvDs^k!e{0tqH0nKvgXh*Xp%uwNbqo05LXgGLM|P_JJ_O z<$XN^9M7Dz&|wND<75|Y88cW2qyWK@pMf(UJNz3D7Evy1%k#27P^s`(xh&89%5_gu zGH+Aox{m$rScPPvixXur6MG;3&s?*98is~szbk$4gYwuG=rb$h1(M)$a!?_mnKsqz z5c?UVY146@1VrMBg*?}r%`5M`U-9KMYw#U|8b_cS9QQu;l#|9XeNP zZ$!jQO+r3DvrtO9iLgdS8?^@;Y(9pH^5)_7jzOdt9HZ^8Ja($#8t;jiNXTgNpsW&+ zEwdpBo$`I%F{={|tM6U$_dhxe!|NR?KG*O*MXdQh{VTUUtq|ni#-d89M!G0Sh+|lV z1Y+QzYD_IU>z8M|`o?vY%KlgS(AHI6@|oM77B;Kz7j1|lVu8ldOr1!#dA9u%sgS0P zg5j8<3N=b36V>-_9oaBhj#oMRC&c6O&hiPP4WrkD3_}oS;tW~)1mu@M_4f4i4-|VY z^^7;TABF+1`S<6su{Rg=5s{Nvk;=lcKuQ)nr}jk4di$)M3_rK+9k2L`SNcZwyV8f0 zw3@6}FDaA?1L|dUmv%`!d-I2a5i%oE>j>5ak-2{SvRD6exjfohATo``oSKbLBP@Q! zOP0%Kf>&4l-{~=`LxWYd6MH8df&Thg|8(OC`&=Q6d(+C#{NQP>-gtX+YEsEbD}8M@ zRO@xO;-Hmw&!ao8S+nwya}Si#2LK5n)?Bvv_Tio`P8&N=N?!)X;Ny)(og0l>Y`FNzx}-4Ty^-T~ zPeYRhBdL(_L|-tZ;4pM0%SI&phaX@3a=%s~wM?y30>pV`!eakLQ!d<1`5ftNo86|M zu~Q;T(KNTJD%i5wyJxRkHZXAFVWU5L<35uD@!0>2FK#~6Fuz@)Dnw?+*|9j?iXj`4 z)AH7HHat=u)dQpSC1&5)kXw7{HGfHN;CYRoD`O6+IkNIu=(sick0AoY~Rh|fPpWU_RvAdy;vkMiL z0vlL_VZ=d@lYvt2(_!sXAeP>hWcUh|wrPp@7GB2qG{#OSsGXm+mIFPQL)COWy+yOY9Z2xANyjXF1L4H>Y# z8xQ{KPmf%RS(t2&D9CRlrG5fA3!*@LFo#mqk^<_C3n*_*7+yQL>V$WCrEh_WsF#9x zsCvPtZ#seuE`*2#PS`p{t3(PLIk0o^;b3vwiq8p>&Kopc&+<&K>O-*d(06Sf*-(!c zg-&Cc?hPJ~%MZWyrQe3?_u;dH%%hQ}G1$x?A`;S4u2{7B!p9bE7FH^}d3e2B^R=4~ zsn(;nGoVJ)P@H)ud8at4U&vSkk>9#KkDoR+L~d-$BJvU}0m)FMu5p=@Mu|j~;~h*m z-qDm|T`Joc+{O0qhD4trxF6nj>C3P7)<$=qMt24PP$~Nbga&+pLPMa73c5rn!|a{h z;|%x>tG{{shQ%m^iRPa(ym9$Je?LHuNGTyc$63NSDk_{0ht3CXXxl|^_+5E))XY2K z<32zVL-@Q;Tz_)F7%Bw$X^LMKb8Un@4GE1@Lj_#`0BhEiXS{eu1{fg{R4V47@(Ei= z=?mVvm|tUM&8>7nYYg+IVpwmWXbei=kC#VV{`xHQcSkHvpZVGGLz<1|=}{P}5jEMd zlgPlDqGQb&vbnQwearDT9FXbVEXMp2Fs?U0&dmt5iK!XK`Ncv(LIk5kSKaiX^}i^O zs!1n=$YMqYh#{y{SZey=FmyW#g*;7H2>sX&B-^BRj!Dx?Ja-@rBaDGU!PsWQMfLiz zH-tC76+=S~GbA+1BI*6boIPJu`jyBLTOu+o8@e{xgrR&CkhKQp3%@yI?UxR;(g*mc znh*DX`Gyt1CYjSLjC=o@uZu@w>`YHg~$ub@gAMUI(h zc=LrDc9sX{UWYOF8w?EzMn}z#d%`bIRVVM5DV52B5pRX=2v8yp9BD4H2lqF7KRBN} zx2Y2L889AiMMnVoa zWIJ6gUnE+NB%)t%Gr9`i%{(jdF)s#4Oox#T5u244IOIB4tfpMSi$UU?VIelEvb=ZT ztYg3Wn>AxYBq-0I5XPGS3IBBGYN6ce4#xL>k~p1>0II4@)u`#Bu-+Wnw(&*3E05{{ zRr&xw=8p|Qj=p64sGKq9D5)saXlo;i*-4NV@iRghqB%fv2qbsG=8+B2e0C1UT=#8Z zXvkqy&7*%g_~Tkw`qx5fnIWeRp`S})G8{eSircXJ%jC}QGsLbHKP4jUw`pQKTM*FvhUIj^J4%2 z*aC$rImWxDCMIh=y(JP6O-q0UOMzJ7X}M}yj8M}#8@~F8uif<8u4bVsjg=useDcQC zYWWNZsSz@)9Ov1!aIg`nwW9ei-f_;0u6jb0zLeSb;wx`>)$+dnQ{k*5u>YO~2%@YN zl|Y%GN-7Yl*Bf|H{-*)6TH(boDO0iz=r4bSUC+u+RAeq&-WkwH_Mo8=nfF zWDM)WND<^$)Q^2H}=+(#?Ko7@SPT>AwWoRMS{ zL5HW-|C_W=H!nM@x3bcVz-$plArx>0OGd(}pI*1xocqML7ziK8AD#AwPNQA?%bx8WsxE0n5b!hhLtF^ zVjVZG^2Dz^fyDP=UdMj;d&l$-47^oD9mI#FEoE-MI~WwvMvRQeOcv8zSR4by+WEFO zo^YdM{G+lMsJQg<;~67yy28JPI@QoMDc@JRaO=>~O~fWtGPWK0`RfmMj5GaYvoj!p zcmv5Ak?SA)tvkmneZvdx3Ht<<3O~B#AOe6q@}I6&tJW*F-GV&lk906g7&Tz6ak;>l zx~u>5b$|QX>z9(KVsQ+BcKFzo*4}3dW&#|Ngbnp+)CeF0M;y-_v>!8F0rcls;F!cX zt$p|YH@@gQ>1<-j*w2jfSaq2IjzMHZrO4LgLj9fFv9s;zL+pM%5T#OKlt<0F%DBbI zh-@C&5FK~f_+>5^oLqO2pO$T{KyH_Ws?#MxTc2_uIA%l?@6kjKil!1bsoK~(DMfxS zx`cTx1WV$~gh+?{!=?|c>R<7Zy*qcgd{8h-K99btf?X7o*h`1>fT08^TR>H( z)^;8Hz}cs6YvtaF$NnR~aKk})#@z%r&|)YxVg#s9Ha6V*p7qxzV{iKj2Nr8DyLG^! zb{P?!;YAdT$yhsC9bkG4MZ2?T9QCW}KPgVa5tWK1Tdh_rKdrpt!%O|!*3>&ohP7g2RS*>U^;a z{>FE>r&JuM*XvLs=b0e-(p{&oJAGYc+#=rBXU)gP-xl=cuBe*G zS+<6&0(SA9#hK>=@mxk1B$~Gi!&w_iA_Vz-zE~&}P@S5BLp!>6u?*m!?HRztZg%*@ zy-o|(km_kSec+_grS^X869zz=37-C?YkpF+g$+=+hJ|quzoszxpj5*GK3W$lu9(l8 z`rg{<_nx)>OX=N1k`Fxk%Qs%4s_zHbsfyne3AmxCx%EdbzhBmr%Q`YVj29pN%4OAN zxQ##uIpjdfu+FEv^%5y7egT&aZ^$5N{4^0e6endsRXtNGb2@M`L%{i>Wg1eP&_D&o z!4ZpzSU2DD!Bf_k%boH4i^bxVz%Fpn;}?WfcXbm|gF81x?gkdPys>6#qI&zWs~-KT zXQY^;W1s)CzxuO-6z0r$*(rSQ(nkV^q1#SBE*#skMYoQP5k^L2cO4alImju6l-gQV zkg>u1!h65^KKb7aC7HTPe#0lzX%(nXx#sQsIX-wEm?q5CD})3AG;;Ok<4f3IaXOa# z!hkmm%cG;_;j>75oOZ{VFZpe!E3kR0>bYX^hKoCysCuvS^g*^r!3imWf8RdU7`iHkCk#3czM zYOl#@|Cv5Nt;`CUqs$CaM&KB^2rj2$nCf5q#l=InWmoqs1^b2p0E}(fqNr3jZ}>w{ z_c%d`L}NEGTGO<|&QFFYJ5^&`Q@(lkJ5Jh^Hv1Bv{~@3H&Ow3DSuCVR;1`>l<~#2? zRqE%W%?pXfy9_s= zR0FtI^YmQ`ivwwUJtV~E zO-zcwKeu%}R)m!ae(S|}CNQ~1{P^D5j6(dHibOgP1QIsg@@4%j&F~|eM^1fYK4D%9 zL6`opBoHbUS~FO-jYjx$iu5Rrn#vS1sP20|0Ew)#X266YedJfCANRq;)B|GE62P-R zeeJ4}DctRx=`WUYW^eWJ8~X}9>yBK$R>sN@5CIjXXRo+7$kEO_NcA}&s6jlrK+?*a zqv9Js-ILoJFZ$}q22I&9IIF-VE9z$gOCs_7^IG>KX$5d-+A2y-5GKcye@P$(OJtgI z_e!(+m^B!TMn*_6k4T^SV)n0DI240}v~}p{X5=O>=(PcPMa&0ls2He{*nl~TCLhX& zg^!}5jP!hcvL%cb-g(f#isg}YRI_fo=EAa9`Vtdy++c(xj~(wI;JNC%SC{We&%bx; zIPq9abC1c3LdX1nm-{E@yTl0yi$+#yQfe2DjU3&aX?4$1(51nah1O8No#4e6QU4HRe2nzgXc&5r3=>5w3+CvfIk742|_rIEHdI*)sQ zLZey#-cK(*^*?4?-Ln)dtVQOFcv~_f_QE{pnnaf10)^xpQD7c>eCPEKp81-8OlHnn z*Tucx1@4_uFRzGl%8`LLkYx~3g4f2=#PD&7$<}GfL((c- zXO5$!Inu}2g_L8JmKj*4jS4BB{MrlPKcGdQNdFvT3 z{alA@IL@l^+|P_3N5;N6yRLqw9yK2%7QjM~t)G<=jJ8yoiRjt)^=V?jj`RyZ898NZ z5?$1B;XcCtVF0wl#~x|oVkf%YQl5wdGd0=#pZEUFDLrnbquHk2W@w(Fj%O^)o zX+&gH?|L2E-JgIeb%?aM_doM%-(Pxm=C+_jW2)ww1CcvGKQhg``iuB5V$Q?U9k{F zL@*Rl4pGYdPZL1ZJAjgXkO+W@r(2WFq!ZV$#=#ff8b~4K2wEruB==0-14ucF00?nw z!i-fSg4n5A?f?Apve*3izL@Hr5B9eNXroeT@641sws~YjwEELmAK~iZb9PVG{wk~V z0YKs_n3{U*GOOr;7!5g35!nvk{%piq3>JI8M61sVr|I{L7qbY9pGwBwfn|Lgy}y6< zW!?J<2aW+oMr67&<2SGDD;@S<^5OCees}tRsb&{)Bt7AXkN)VSo_yb5sP?$X445ff z!c>rhi^V4;`SV+X)$aqu!Z5HfuwdBKSzi(#Kz5tfgjmVnY2qbzezv3upZrep_i=oG zKQG}6tH5X|s!mmf_ddS+E!V&IqzB7e2luJJe>OakLjVEL=UlOE6;|PC_x#OKccP*^ zZ6QZ_)L_jPJ?@#Wy&0;TN8r75ENVl6K{2cnCNMwQ>*w!kB?^pL8Rrd={P)X z2*|Q<8r^*T+55HLPF02A)L1L3h^o~yZ@=u-2Yfxlfs+8!p#X5`#P4?B^EXG`302Ax zzdWi2V?%CD|B3&-IxkcY@|M`%Q-xD#1R_#aTcfG% zj_a>~B8ZPCSOTOmeUd}HcX#a-<0~6f-KK0-lC@yd0Eq=fJs`1g#^(c2_2NEBo1SPJ z+2l%z6zC=akm(VuUIJvrf5-V0G_CY?IZu#y*a4uj*BSlCYNK|^9hd&;Zx58xm&KEX z0j44G6t2DM+wZN1xs6)YW Date: Mon, 18 May 2026 18:23:06 -0500 Subject: [PATCH 2/2] ci: standardize release changelog contract --- .codex/scripts/bump-version.ps1 | 9 ++- .codex/scripts/prerelease-notes.sh | 8 +-- .codex/scripts/prerelease-notes.tests.ps1 | 23 +++++-- .codex/scripts/release-hygiene.tests.ps1 | 7 +- .codex/scripts/release-nudge.ps1 | 2 +- .codex/scripts/version-metadata.sh | 3 +- CHANGELOG.md | 80 +++++++++++++++-------- 7 files changed, 87 insertions(+), 45 deletions(-) diff --git a/.codex/scripts/bump-version.ps1 b/.codex/scripts/bump-version.ps1 index e21e069..5960c79 100644 --- a/.codex/scripts/bump-version.ps1 +++ b/.codex/scripts/bump-version.ps1 @@ -65,12 +65,12 @@ function Update-Changelog { $Text = Get-Content -Raw -Path $Path - $VersionHeadingPattern = '(?m)^`' + [regex]::Escape($Version) + '`$' + $VersionHeadingPattern = '(?m)^## v' + [regex]::Escape($Version) + '$' if ($Text -match $VersionHeadingPattern) { - throw "CHANGELOG.md already contains a $Version entry." + throw "CHANGELOG.md already contains a v$Version entry." } - $UnreleasedPattern = '(?ms)^## Unreleased\s*(?.*?)(?=^`[^`]+`\s*$|^## |\z)' + $UnreleasedPattern = '(?ms)^## Unreleased\s*(?.*?)(?=^## |\z)' $Match = [regex]::Match($Text, $UnreleasedPattern) if (-not $Match.Success) { throw "CHANGELOG.md must contain an '## Unreleased' section before bumping." @@ -82,8 +82,7 @@ function Update-Changelog { } $ReleasedBody = if ([string]::IsNullOrWhiteSpace($Body)) { "- No user-facing changes recorded." } else { $Body } - $VersionHeading = '`' + $Version + '`' - $Replacement = "## Unreleased`r`n`r`n$VersionHeading`r`n$ReleasedBody`r`n`r`n" + $Replacement = "## Unreleased`r`n`r`n## v$Version`r`n`r`n$ReleasedBody`r`n`r`n" $Updated = $Text.Substring(0, $Match.Index) + $Replacement + $Text.Substring($Match.Index + $Match.Length) Set-TextPreservingUtf8Bom -Path $Path -Value $Updated } diff --git a/.codex/scripts/prerelease-notes.sh b/.codex/scripts/prerelease-notes.sh index a327217..d68c228 100644 --- a/.codex/scripts/prerelease-notes.sh +++ b/.codex/scripts/prerelease-notes.sh @@ -97,7 +97,7 @@ fi unreleased_body=$( awk ' /^##[[:space:]]*Unreleased[[:space:]]*$/ { in_unreleased = 1; next } - in_unreleased && (/^`[^`]+`[[:space:]]*$/ || /^## /) { exit } + in_unreleased && /^## / { exit } in_unreleased { print } ' "$CHANGELOG_PATH" ) @@ -108,8 +108,8 @@ fi version_body=$( awk -v version="$VERSION" ' - $0 == "`" version "`" { in_version = 1; next } - in_version && (/^`[^`]+`[[:space:]]*$/ || /^## /) { exit } + $0 == "## v" version { in_version = 1; next } + in_version && /^## / { exit } in_version { print } ' "$CHANGELOG_PATH" ) @@ -156,7 +156,7 @@ ${handoff_heading} | Signal | Detail | | --- | --- | -| 📝 Changelog | \`## Unreleased\` is empty; notes below come from \`${VERSION}\`. | +| 📝 Changelog | \`## Unreleased\` is empty; notes below come from \`v${VERSION}\`. | | 🌿 Branch | \`${BRANCH}\` | | 🔖 Commit | \`${short_commit}\` | | ▶️ Run | ${run_detail} | diff --git a/.codex/scripts/prerelease-notes.tests.ps1 b/.codex/scripts/prerelease-notes.tests.ps1 index b63eb7c..ebf8bba 100644 --- a/.codex/scripts/prerelease-notes.tests.ps1 +++ b/.codex/scripts/prerelease-notes.tests.ps1 @@ -47,13 +47,17 @@ function Test-PrereleaseNotesIncludesChangelogAndDetailsCard { $ChangelogPath = Join-Path $FixtureRoot "CHANGELOG.md" $OutputPath = Join-Path $FixtureRoot "prerelease-notes.md" Set-Content -Path $ChangelogPath -Value @' +# Changelog + ## Unreleased -`1.2.3` +## v1.2.3 + - fixed the client widget timing - added a runtime receipt -`1.2.2` +## v1.2.2 + - previous release '@ @@ -101,10 +105,13 @@ function Test-PrereleaseNotesRejectsUnreleasedContent { try { $ChangelogPath = Join-Path $FixtureRoot "CHANGELOG.md" Set-Content -Path $ChangelogPath -Value @' +# Changelog + ## Unreleased - still parked for the next release -`1.2.3` +## v1.2.3 + - fixed the client widget timing '@ @@ -128,7 +135,10 @@ function Test-PrereleaseNotesRejectsMissingUnreleasedHeader { try { $ChangelogPath = Join-Path $FixtureRoot "CHANGELOG.md" Set-Content -Path $ChangelogPath -Value @' -`1.2.3` +# Changelog + +## v1.2.3 + - fixed the client widget timing '@ @@ -152,9 +162,12 @@ function Test-PrereleaseNotesRejectsMissingVersionEntry { try { $ChangelogPath = Join-Path $FixtureRoot "CHANGELOG.md" Set-Content -Path $ChangelogPath -Value @' +# Changelog + ## Unreleased -`1.2.2` +## v1.2.2 + - previous release '@ diff --git a/.codex/scripts/release-hygiene.tests.ps1 b/.codex/scripts/release-hygiene.tests.ps1 index a1f6546..ebc9266 100644 --- a/.codex/scripts/release-hygiene.tests.ps1 +++ b/.codex/scripts/release-hygiene.tests.ps1 @@ -79,11 +79,14 @@ versionNumber = "1.2.3" "@ -NoNewline Set-Content -Path (Join-Path $FixtureRoot "CHANGELOG.md") -Value @" +# Changelog + ## Unreleased - planned fix -`1.2.3` +## v1.2.3 + - previous release "@ -NoNewline @@ -112,7 +115,7 @@ function Test-BumpVersionUpdatesEclipseMetadata { Assert-Match -Text $ProjectText -Pattern '1\.2\.4' -Message "Project version was not updated." Assert-Match -Text $ThunderstoreText -Pattern 'versionNumber = "1\.2\.4"' -Message "Thunderstore version was not updated." - Assert-Match -Text $ChangelogText -Pattern '(?m)^## Unreleased\s+`1\.2\.4`\s+- planned fix' -Message "Changelog release entry was not created." + Assert-Match -Text $ChangelogText -Pattern '(?m)^## Unreleased\s+## v1\.2\.4\s+- planned fix' -Message "Changelog release entry was not created." } finally { Remove-Item -LiteralPath $FixtureRoot -Recurse -Force diff --git a/.codex/scripts/release-nudge.ps1 b/.codex/scripts/release-nudge.ps1 index eba9d6b..bf76beb 100644 --- a/.codex/scripts/release-nudge.ps1 +++ b/.codex/scripts/release-nudge.ps1 @@ -46,7 +46,7 @@ function Write-Nudge { function Get-UnreleasedBody { $Text = Get-Content -Raw -Path $ChangelogPath - $Match = [regex]::Match($Text, '(?ms)^## Unreleased\s*(?.*?)(?=^`[^`]+`\s*$|^## |\z)') + $Match = [regex]::Match($Text, '(?ms)^## Unreleased\s*(?.*?)(?=^## |\z)') if (-not $Match.Success) { return $null diff --git a/.codex/scripts/version-metadata.sh b/.codex/scripts/version-metadata.sh index de7d397..fe411e6 100644 --- a/.codex/scripts/version-metadata.sh +++ b/.codex/scripts/version-metadata.sh @@ -38,8 +38,7 @@ read_thunderstore_version() { read_latest_changelog_entry() { local entry - # sed needs literal backticks to match the repo's changelog header format. - entry=$(sed -n '/^`[^`][^`]*`$/ { s/^`//; s/`$//; p; q; }' "$CHANGELOG_PATH" | tr -d '\r') + entry=$(sed -n 's/^## v\([0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\)$/\1/p' "$CHANGELOG_PATH" | head -n 1 | tr -d '\r') if [ -z "$entry" ]; then fail "Unable to determine the latest CHANGELOG entry from $CHANGELOG_PATH." diff --git a/CHANGELOG.md b/CHANGELOG.md index ab6469b..2201788 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,99 +1,127 @@ +# Changelog + ## Unreleased -`1.3.17` +## v1.3.17 + - added prerelease note generation and changelog turnover validation for GitHub and Thunderstore release flows -`1.3.16` +## v1.3.16 + - hardened attribute UI initialization so runtime-loaded clients defer when the inventory attribute hierarchy is not ready - collapsed Emberglass bridge progress receipts to one client log line per config/progress batch -`1.3.15` +## v1.3.15 + - added release hygiene helper scripts for changelog/version bump review and metadata updates - added CI coverage for the release hygiene nudge before build verification -`1.3.14` +## v1.3.14 + - optional Emberglass bridge support for Bloodcraft registration and server messages - release workflow hardening for safer prerelease and Thunderstore publishing -`1.3.13` +## v1.3.13 + - primal weapons -`1.3.12` +## v1.3.12 + - attributes -`1.3.11` +## v1.3.11 + - decreased update interval for more responsive UI elements (1s -> 0.1s), added config option if you prefer the old behavior; for noticeable effect requires Bloodcraft v1.11.14 or higher with fast updates enabled (Eclipsed = true) -`1.3.10` +## v1.3.10 + - gamepad mode (position of quest windows and profession bars will change based on detected input) - ability slot click-toggle for profession bars functional again -`1.3.9` +## v1.3.9 + - preventing duplicate coroutine instances from being created if one is already present -`1.3.8` +## v1.3.8 + - removing interact progress bar when unlocking familiars from buff entity on client - changed abbreviation for PrimaryLifeLeech to PAL -`1.3.7` +## v1.3.7 + - adjusted name trimming to target only vBloods for fam bar/quest targets - handling for movementSpeed to show correctly on expertise bar and weapon tooltips -`1.3.6` +## v1.3.6 + - small fix for legacy bar errors in console - weapon expertise stats (most, not all) appear on tooltips -`1.3.5` +## v1.3.5 + - Updated for VRising 1.1 compatibility -`1.3.3` +## v1.3.3 + - small changes to accomodate minor version increases without needing to add more boilerplate logic to client/server - minor recipe adjustments to match server-side changes for the client visually -`1.3.2` +## v1.3.2 + - backwards compatible with Bloodcraft 1.5.3 (will show NPC spell cooldown's on shift when using 1.6.4 #soonYM, other changes below do not require additional information from Bloodcraft) - weapon expertise stats show on tooltips accordingly (not all stats will show there for some reason but works for most) - new recipe/salvage additions and changes added in 1.6.4 with ExtraRecipes enabled are best experienced with Eclipse - profession bars no longer an eyesore (thin gold bar represents progress to max level, icon indicates profession, reordered to crafting profs then gathering profs) -`1.2.2` +## v1.2.2 + - added bar for basic familiar info - added bargraph of sorts for professions - can toggle individual parts by clicking on ability slots 1-7 -`1.1.2` +## v1.1.2 + - removed unneeded dependency like I meant to for 1.1.1, oopsie -`1.1.1` +## v1.1.1 + - class text under experience bar formatted more aesthetically - improved positioning for UI elements at various resolutions (probably >_>) -`1.0.0` +## v1.0.0 + - versioning for Thunderstore/sanity - requires Bloodcraft 1.4.0 -`0.2.1` +## v0.2.1 + - fixed loop update if more than 3 bonus stats were chosen - added quest icons for crafting and gathering -`0.2.0` +## v0.2.0 + - added icons for quests based on normal/vblood target - handled displaying stats in different locales -`0.1.4` +## v0.1.4 + - making an attempt at handling scaling for UI elements at various resolutions, will need feedback on this although seems decent so far -`0.1.3` +## v0.1.3 + - changed click detection to work off the same blood object that shows blood information when hovered over (this should fix any issues with errant clicks as if the blood object is not present it cannot be interacted with) - quests should reliably be on the bottom right of the screen now -`0.1.2` +## v0.1.2 + - clicking blood orb area if UI not active in-game will not do anything -`0.1.1` +## v0.1.1 + - fixed extra bar at top of screen if only experience is enabled -`0.1.0` +## v0.1.0 + - initial test release - config values for experience, prestige, legacy, expertise, and quests (should be okay to mix and match but probably works best with all atm) - progress bars for experience, legacies, expertise with bonus stats displayed beneath and prestige in bar header if enabled with current level on the left