From 265ec100ffae17fb958ef61bdc7a784a03b21651 Mon Sep 17 00:00:00 2001 From: Parker Brown <17183625+parkerbxyz@users.noreply.github.com> Date: Thu, 8 Aug 2024 17:08:26 -0700 Subject: [PATCH 1/6] Run all tests --- tests/index.js | 16 ++++++++-- ...private-key-with-escaped-newlines.test.js} | 2 +- ...in-repo-skew.js => main-repo-skew.test.js} | 0 tests/snapshots/index.js.md | 30 ++++++++++++++++++ tests/snapshots/index.js.snap | Bin 1128 -> 1310 bytes 5 files changed, 44 insertions(+), 4 deletions(-) rename tests/{main-private-key-with-escaped-newlines.js => main-private-key-with-escaped-newlines.test.js} (79%) rename tests/{main-repo-skew.js => main-repo-skew.test.js} (100%) diff --git a/tests/index.js b/tests/index.js index 5d481644..f300270c 100644 --- a/tests/index.js +++ b/tests/index.js @@ -1,11 +1,21 @@ import { readdirSync } from "node:fs"; -import { execa } from "execa"; import test from "ava"; +import { execa } from "execa"; + +// Get all files in tests directory +const files = readdirSync("tests"); + +// Files to ignore +const ignore = ["index.js", "main.js", "README.md", "snapshots"]; -const tests = readdirSync("tests").filter((file) => file.endsWith(".test.js")); +const testFiles = files.filter((file) => !ignore.includes(file)); -for (const file of tests) { +// Throw an error if there is a file that does not end with test.js in the tests directory +for (const file of testFiles) { + if (!file.endsWith(".test.js")) { + throw new Error(`File ${file} does not end with .test.js`); + } test(file, async (t) => { // Override Actions environment variables that change `core`’s behavior const env = { diff --git a/tests/main-private-key-with-escaped-newlines.js b/tests/main-private-key-with-escaped-newlines.test.js similarity index 79% rename from tests/main-private-key-with-escaped-newlines.js rename to tests/main-private-key-with-escaped-newlines.test.js index a19ada7d..d18e9317 100644 --- a/tests/main-private-key-with-escaped-newlines.js +++ b/tests/main-private-key-with-escaped-newlines.test.js @@ -1,4 +1,4 @@ -import { test, DEFAULT_ENV } from "./main.js"; +import { DEFAULT_ENV, test } from "./main.js"; // Verify `main` works correctly when `private-key` input has escaped newlines await test(() => { diff --git a/tests/main-repo-skew.js b/tests/main-repo-skew.test.js similarity index 100% rename from tests/main-repo-skew.js rename to tests/main-repo-skew.test.js diff --git a/tests/snapshots/index.js.md b/tests/snapshots/index.js.md index c458d391..0f799ec7 100644 --- a/tests/snapshots/index.js.md +++ b/tests/snapshots/index.js.md @@ -75,6 +75,26 @@ Generated by [AVA](https://avajs.dev). '' +## main-repo-skew.test.js + +> stderr + + `'Issued at' claim ('iat') must be an Integer representing the time that the assertion was issued.␊ + [@octokit/auth-app] GitHub API time and system time are different by 30 seconds. Retrying request with the difference accounted for.` + +> stdout + + `owner and repositories set, creating token for repositories "failed-repo" owned by "actions"␊ + ::add-mask::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊ + ␊ + ::set-output name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊ + ␊ + ::set-output name=installation-id::123456␊ + ␊ + ::set-output name=app-slug::github-actions␊ + ::save-state name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊ + ::save-state name=expiresAt::2016-07-11T22:14:10Z` + ## main-token-get-owner-set-repo-fail-response.test.js > stderr @@ -229,6 +249,16 @@ Generated by [AVA](https://avajs.dev). ::save-state name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊ ::save-state name=expiresAt::2016-07-11T22:14:10Z` +## main.js + +> stderr + + '' + +> stdout + + '' + ## post-revoke-token-fail-response.test.js > stderr diff --git a/tests/snapshots/index.js.snap b/tests/snapshots/index.js.snap index 5a0653706ded1917da4cb52e95edaeab23821f70..1e4d8c6470ce7f398e21bf9fa5ec6ffa928fbec5 100644 GIT binary patch literal 1310 zcmV+(1>yQZRzVg)}LGa{7(7WP4;D4Y8kK)Cn;H#>hA4R5di8m)UaG(DcKpa4@Gl;LV8Vxogt~%7q2)oGfJ+5<77OE4@QMH~Dj##kLmKmb zB=~2KJdX2WCSi|KFM_wzI~I+Zl_q|X)%?j=&F@RmNeGFWN&<1jnTQewoNy59#7%$-7WRmeO}bHH z4qDN;@eMT)CMvUut`KS6Bc0Rn(3NG!p`K?2ln)%I*XM1!@lF#qYjRlBehU>@7#^gVgfxIRm4{*`Wc;b`QOC9iv+IiCn@^XV26<)JdIhi=-}{v`{0B3b`MErZJh*|A2R=Ny^vB;zNPHHRlb^3Vo05; z7Wsl5L-6{Ak(@GmHI1(t8pru~j>LUKqH`vu7e;gAmUMH)pbnK@X~5zGILVj!w^5n? zSSq(TPh|{6nYcb>0a-0GyjUB{q#@fEuzRfAg#?|+%2uyp zxZEi8c!eB-NKT~!2>{L$w+GQz0!CkP(SqwnX(%@kEU1;4Mfy7<6kio9(p}1YYy{-Z zML~Xi1-Y)c*BgFMikE9>$!VxukgI~9c#N8%$cFxp!OEZWW#x`~E^C9{@}~@$-(95w zQzjO~UUQ~%N)|&p#F4b)!vekepl6?tp8Oyp411WrX)0T)m5 zU?Oqmsr8hwLiu`p!w~h{Bt8T1E{uuNTqq{58}45|vpn)VJo7SB&5KiN3YMdMHI#-iUC)?%G85m zp)w(w3XS5Kfr#3u1|ZuShH3z5)S1V{VkdIc%F(f0=3tU`72{|v%OMw%c4LDoqFK&1s3VgRe8tAV4CePV5sp3?51a*CU|We38< zWj4_=Nz{GPc|0Ck-eipXJ`K4UFxI~?ZLj%$3mWx%^}Twxx#!gnS}m{E-QC&UX|(pi zYwg}`@Xbxe3?Nl8Mllk}LwMIlC?=8Qp9cZAdq((-dG(#f?dH6p$(&3O_Zb^aGM!H{ zln;R#%gOoe zX$ne}VuW~i3#IZV6E%FUB$8dFNCZ|NN z=J8F(<9I(Vuz2KHWHUKkn$25xk}y|I>W(#>R=$3+trAU|Y_LR?_P7YB1`{c1ph#u= z%c*RC6sv5BEAXwuxmE0*eV-&Lt$kBM?r*m^B7_kV?VWt2N{`g)=shYG3B$WF?5aGZzs{#JK4xg2pcn z8b4&+&MXt@^U3o6!!}1q(v7tSiJ8*Y_%yq@MrSqX&}HZpt}8z}@O+ooDle)qcmZQF zCRZtBtDJ|@8kZH}Qi+to>}EWp=9=1_^SX2Y^%i57TuUMQjGb8!lAv9iM3P?JFf#ul z(^^curBlqmVO{R3>A2cTtz@!QlKfi`O<0{+oabyfWvtMiI=|tVdTElM0r*REVm%ki u$=go&*JqaJk{gmmnd|1&DK`bn%lR9QmzPs7Vq8v~_ Date: Thu, 8 Aug 2024 17:08:29 -0700 Subject: [PATCH 2/6] Update package-lock.json --- package-lock.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index a318de79..262dd0f7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "create-github-app-token", - "version": "1.10.2", + "version": "1.10.3", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "create-github-app-token", - "version": "1.10.2", + "version": "1.10.3", "license": "MIT", "dependencies": { "@actions/core": "^1.10.1", From 36d74b372abb0c2309135ed8e138d9e9fdf8d499 Mon Sep 17 00:00:00 2001 From: Parker Brown <17183625+parkerbxyz@users.noreply.github.com> Date: Thu, 8 Aug 2024 17:42:55 -0700 Subject: [PATCH 3/6] Update main-private-key-with-escaped-newlines.test.js --- tests/main-private-key-with-escaped-newlines.test.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/main-private-key-with-escaped-newlines.test.js b/tests/main-private-key-with-escaped-newlines.test.js index d18e9317..baa7f07c 100644 --- a/tests/main-private-key-with-escaped-newlines.test.js +++ b/tests/main-private-key-with-escaped-newlines.test.js @@ -2,5 +2,8 @@ import { DEFAULT_ENV, test } from "./main.js"; // Verify `main` works correctly when `private-key` input has escaped newlines await test(() => { - process.env['INPUT_PRIVATE-KEY'] = DEFAULT_ENV.PRIVATE_KEY.replace(/\n/g, '\\n') + process.env["INPUT_PRIVATE-KEY"] = DEFAULT_ENV["INPUT_PRIVATE-KEY"].replace( + /\n/g, + "\\n" + ); }); From 91d2d94e86e9861144fb4c38247077bd3934b7a8 Mon Sep 17 00:00:00 2001 From: Parker Brown <17183625+parkerbxyz@users.noreply.github.com> Date: Thu, 8 Aug 2024 17:43:18 -0700 Subject: [PATCH 4/6] Update main.js --- tests/main.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tests/main.js b/tests/main.js index 3e52f69d..245b6e6e 100644 --- a/tests/main.js +++ b/tests/main.js @@ -46,7 +46,7 @@ export async function test(cb = (_mockPool) => {}, env = DEFAULT_ENV) { // Set up mocking const baseUrl = new URL(env["INPUT_GITHUB-API-URL"]); - const basePath = baseUrl.pathname === '/' ? '' : baseUrl.pathname; + const basePath = baseUrl.pathname === "/" ? "" : baseUrl.pathname; const mockAgent = new MockAgent(); mockAgent.disableNetConnect(); setGlobalDispatcher(mockAgent); @@ -58,8 +58,9 @@ export async function test(cb = (_mockPool) => {}, env = DEFAULT_ENV) { const mockInstallationId = "123456"; const mockAppSlug = "github-actions"; const owner = env.INPUT_OWNER ?? env.GITHUB_REPOSITORY_OWNER; + const currentRepoName = env.GITHUB_REPOSITORY.split("/")[1]; const repo = encodeURIComponent( - (env.INPUT_REPOSITORIES ?? env.GITHUB_REPOSITORY).split(",")[0] + (env.INPUT_REPOSITORIES ?? currentRepoName).split(",")[0] ); mockPool .intercept({ @@ -73,7 +74,7 @@ export async function test(cb = (_mockPool) => {}, env = DEFAULT_ENV) { }) .reply( 200, - { id: mockInstallationId, "app_slug": mockAppSlug }, + { id: mockInstallationId, app_slug: mockAppSlug }, { headers: { "content-type": "application/json" } } ); From c2242c56b9dad816bdc25e63e2a799b9c2c0db9d Mon Sep 17 00:00:00 2001 From: Parker Brown <17183625+parkerbxyz@users.noreply.github.com> Date: Thu, 8 Aug 2024 17:44:32 -0700 Subject: [PATCH 5/6] Update snapshots --- tests/snapshots/index.js.md | 39 +++++++++++++++++++++++++--------- tests/snapshots/index.js.snap | Bin 1310 -> 1340 bytes 2 files changed, 29 insertions(+), 10 deletions(-) diff --git a/tests/snapshots/index.js.md b/tests/snapshots/index.js.md index 0f799ec7..6a915ec7 100644 --- a/tests/snapshots/index.js.md +++ b/tests/snapshots/index.js.md @@ -75,6 +75,25 @@ Generated by [AVA](https://avajs.dev). '' +## main-private-key-with-escaped-newlines.test.js + +> stderr + + '' + +> stdout + + `owner and repositories not set, creating token for the current repository ("create-github-app-token")␊ + ::add-mask::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊ + ␊ + ::set-output name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊ + ␊ + ::set-output name=installation-id::123456␊ + ␊ + ::set-output name=app-slug::github-actions␊ + ::save-state name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊ + ::save-state name=expiresAt::2016-07-11T22:14:10Z` + ## main-repo-skew.test.js > stderr @@ -249,16 +268,6 @@ Generated by [AVA](https://avajs.dev). ::save-state name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊ ::save-state name=expiresAt::2016-07-11T22:14:10Z` -## main.js - -> stderr - - '' - -> stdout - - '' - ## post-revoke-token-fail-response.test.js > stderr @@ -308,3 +317,13 @@ Generated by [AVA](https://avajs.dev). > stdout 'Token is not set' + +## main.js + +> stderr + + '' + +> stdout + + '' diff --git a/tests/snapshots/index.js.snap b/tests/snapshots/index.js.snap index 1e4d8c6470ce7f398e21bf9fa5ec6ffa928fbec5..90abcced6c8c6b7123524a7c1aa06bae235aef03 100644 GIT binary patch literal 1340 zcmV-C1;hG5RzV zq@5d)Egy>r00000000B+na^+IL=?vx5JIYi1UJMY7*$AVp-$tZo3z$~=%Q|$19Vlo zq6a!-J^VQCv&NT6P2If~f;?X>%F zntI8cDCTNp$Vv^3{fRz{+A{0|Z^tme|EbqAr;GVk<}7W_nwT3Yn1($}M?nebSxS%D~bIg+5Fka<`1QC$RXBKi6IIFlVQw25CL+XxG_-4c#mk=q#MTO zpp_Iiv7raTROM)*D@0lMNau7ibYQP?hN?LU zKk1>v(InIPsG)QK78;UpHDPBhz=MdzAafx3v9t%2$(045^uJ zkuTUW1g~Eh$&AsfX?)$#IH|{TB<>p$oij1LFq#{;l$)ytwW0-Q=4}nJge(v)jc|eD zF!ULRLQB+7MpOGPuc_%wn+?7`U8XbV^oN@_O6aqLa;~lMOU3Dg~D4!!RG~ ze~hI6xm0cmk*J!JW#amj1!T3%@XOi+YsyKBOXz`K$50n0TT_6!mn^`K6DsvLDg?wT zEM!OpF8j)GW%-kLLlO|1=kG|t~MOVX=Nt=-y5O$y4a%LrOd~= zR3{e;_~To^>zey?gV<-Z0if6bSbJNkFEmZWVoW5~RA zl}ap`ND_O^$<~x=*>r#-X~%~Jdhze5@iTI`OV%#HaNxF^0RO=w#n zG8aVNnu&-eVzTKeg2t}~8b6M9J7<|l&rj3;KesuIPac7#mR2XL+2U!}oY1i@LZ@(F zSv(wlif}1o@a5gphp^wEt&X20*z5>svI z6!Tw1U975Ms9H^>jLfbR^-?vOvO1MG^T~2XSfQFazF~-ZVH%%4co)V*Yc3R%Hx2i% yo=J~-Wb7gH^4(oSai@2Qq|C2!}vZTb)1c-2b`Apiic8-yQZRzVg)}LGa{7(7WP4;D4Y8kK)Cn;H#>hA4R5di8m)UaG(DcKpa4@Gl;LV8Vxogt~%7q2)oGfJ+5<77OE4@QMH~Dj##kLmKmb zB=~2KJdX2WCSi|KFM_wzI~I+Zl_q|X)%?j=&F@RmNeGFWN&<1jnTQewoNy59#7%$-7WRmeO}bHH z4qDN;@eMT)CMvUut`KS6Bc0Rn(3NG!p`K?2ln)%I*XM1!@lF#qYjRlBehU>@7#^gVgfxIRm4{*`Wc;b`QOC9iv+IiCn@^XV26<)JdIhi=-}{v`{0B3b`MErZJh*|A2R=Ny^vB;zNPHHRlb^3Vo05; z7Wsl5L-6{Ak(@GmHI1(t8pru~j>LUKqH`vu7e;gAmUMH)pbnK@X~5zGILVj!w^5n? zSSq(TPh|{6nYcb>0a-0GyjUB{q#@fEuzRfAg#?|+%2uyp zxZEi8c!eB-NKT~!2>{L$w+GQz0!CkP(SqwnX(%@kEU1;4Mfy7<6kio9(p}1YYy{-Z zML~Xi1-Y)c*BgFMikE9>$!VxukgI~9c#N8%$cFxp!OEZWW#x`~E^C9{@}~@$-(95w zQzjO~UUQ~%N)|&p#F4b)!vekepl6?tp8Oyp411WrX)0T)m5 zU?Oqmsr8hwLiu`p!w~h{Bt8T1E{uuNTqq{58}45|vpn)VJo7SB&5KiN3YM Date: Thu, 22 Aug 2024 16:11:09 -0700 Subject: [PATCH 6/6] Remove owner from repositories input in tests --- tests/main-custom-github-api-url.test.js | 5 +++-- ...ken-get-owner-set-repo-set-to-many.test.js | 3 ++- ...oken-get-owner-set-repo-set-to-one.test.js | 3 ++- ...ain-token-get-owner-unset-repo-set.test.js | 3 ++- tests/snapshots/index.js.md | 18 ++++-------------- tests/snapshots/index.js.snap | Bin 1340 -> 1326 bytes 6 files changed, 13 insertions(+), 19 deletions(-) diff --git a/tests/main-custom-github-api-url.test.js b/tests/main-custom-github-api-url.test.js index eb2cffa0..0579fafa 100644 --- a/tests/main-custom-github-api-url.test.js +++ b/tests/main-custom-github-api-url.test.js @@ -1,10 +1,11 @@ -import { test, DEFAULT_ENV } from "./main.js"; +import { DEFAULT_ENV, test } from "./main.js"; // Verify that main works with a custom GitHub API URL passed as `github-api-url` input await test( () => { process.env.INPUT_OWNER = process.env.GITHUB_REPOSITORY_OWNER; - process.env.INPUT_REPOSITORIES = process.env.GITHUB_REPOSITORY; + const currentRepoName = process.env.GITHUB_REPOSITORY.split("/")[1]; + process.env.INPUT_REPOSITORIES = currentRepoName; }, { ...DEFAULT_ENV, diff --git a/tests/main-token-get-owner-set-repo-set-to-many.test.js b/tests/main-token-get-owner-set-repo-set-to-many.test.js index fa18b1a4..173fcf45 100644 --- a/tests/main-token-get-owner-set-repo-set-to-many.test.js +++ b/tests/main-token-get-owner-set-repo-set-to-many.test.js @@ -3,5 +3,6 @@ import { test } from "./main.js"; // Verify `main` successfully obtains a token when the `owner` and `repositories` inputs are set (and the latter is a list of repos). await test(() => { process.env.INPUT_OWNER = process.env.GITHUB_REPOSITORY_OWNER; - process.env.INPUT_REPOSITORIES = `${process.env.GITHUB_REPOSITORY},actions/toolkit`; + const currentRepoName = process.env.GITHUB_REPOSITORY.split("/")[1]; + process.env.INPUT_REPOSITORIES = `${currentRepoName},toolkit`; }); diff --git a/tests/main-token-get-owner-set-repo-set-to-one.test.js b/tests/main-token-get-owner-set-repo-set-to-one.test.js index 3e0f7335..78bd93eb 100644 --- a/tests/main-token-get-owner-set-repo-set-to-one.test.js +++ b/tests/main-token-get-owner-set-repo-set-to-one.test.js @@ -3,5 +3,6 @@ import { test } from "./main.js"; // Verify `main` successfully obtains a token when the `owner` and `repositories` inputs are set (and the latter is a single repo). await test(() => { process.env.INPUT_OWNER = process.env.GITHUB_REPOSITORY_OWNER; - process.env.INPUT_REPOSITORIES = process.env.GITHUB_REPOSITORY; + const currentRepoName = process.env.GITHUB_REPOSITORY.split("/")[1]; + process.env.INPUT_REPOSITORIES = currentRepoName; }); diff --git a/tests/main-token-get-owner-unset-repo-set.test.js b/tests/main-token-get-owner-unset-repo-set.test.js index 89d6a850..99638639 100644 --- a/tests/main-token-get-owner-unset-repo-set.test.js +++ b/tests/main-token-get-owner-unset-repo-set.test.js @@ -3,5 +3,6 @@ import { test } from "./main.js"; // Verify `main` successfully obtains a token when the `owner` input is not set, but the `repositories` input is set. await test(() => { delete process.env.INPUT_OWNER; - process.env.INPUT_REPOSITORIES = process.env.GITHUB_REPOSITORY; + const currentRepoName = process.env.GITHUB_REPOSITORY.split("/")[1]; + process.env.INPUT_REPOSITORIES = currentRepoName; }); diff --git a/tests/snapshots/index.js.md b/tests/snapshots/index.js.md index 6a915ec7..023d104b 100644 --- a/tests/snapshots/index.js.md +++ b/tests/snapshots/index.js.md @@ -24,7 +24,7 @@ Generated by [AVA](https://avajs.dev). > stdout - `owner and repositories set, creating token for repositories "actions/create-github-app-token" owned by "actions"␊ + `owner and repositories set, creating token for repositories "create-github-app-token" owned by "actions"␊ ::add-mask::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊ ␊ ::set-output name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊ @@ -142,7 +142,7 @@ Generated by [AVA](https://avajs.dev). > stdout - `owner and repositories set, creating token for repositories "actions/create-github-app-token,actions/toolkit" owned by "actions"␊ + `owner and repositories set, creating token for repositories "create-github-app-token,toolkit" owned by "actions"␊ ::add-mask::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊ ␊ ::set-output name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊ @@ -161,7 +161,7 @@ Generated by [AVA](https://avajs.dev). > stdout - `owner and repositories set, creating token for repositories "actions/create-github-app-token" owned by "actions"␊ + `owner and repositories set, creating token for repositories "create-github-app-token" owned by "actions"␊ ::add-mask::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊ ␊ ::set-output name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊ @@ -238,7 +238,7 @@ Generated by [AVA](https://avajs.dev). > stdout - `owner not set, creating owner for given repositories "actions/create-github-app-token" in current owner ("actions")␊ + `owner not set, creating owner for given repositories "create-github-app-token" in current owner ("actions")␊ ::add-mask::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊ ␊ ::set-output name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊ @@ -317,13 +317,3 @@ Generated by [AVA](https://avajs.dev). > stdout 'Token is not set' - -## main.js - -> stderr - - '' - -> stdout - - '' diff --git a/tests/snapshots/index.js.snap b/tests/snapshots/index.js.snap index 90abcced6c8c6b7123524a7c1aa06bae235aef03..89369aac6f4c1bc3492e578620e484db70cc9830 100644 GIT binary patch literal 1326 zcmV+}1=0FJRzVQng$u(pyYZ}#h2Z|m_Fk8 zBIfw&v>%HI00000000B+nL%&kL=?vx5JIYiwA>JjU{tM?7V2!Ac9Ygx5M9)5bAYZ& zS9DpSXkx#lL+r8fjFasR@fm88P1{T_7<8;SkR;PAKUmGKqlgJM(zvHHY{y}3klS#Ek-dLqMgnF zj#DqW6XjfGhOE@ki9a!5QAdUY;GGzT_&@b}>U25Z%ABRmSz~jVf=SrJM4sewDWHs7 zZX#qDSbZjslCDJ~W+ky-CY!$++5D*zjyS}6DltT%U^0vu2qHkP5;q1a8SfJyBOjbSfs-H6{TQ z0uyDWwN%K*;jMi3E7i7Y4w%y~67-t_%|l5<5=A}(&mpP3DIgV*mQ(h+p-gjDENsUR zwz<8y_{5HNX>PL zV!@6fc=g;!=8RrW<6DNtaUGr^ao3ROoQmnW(Y$$Exw&jmYg%w_-qr|9$O7Tg2p1*} zBcE|7wKV-=G_xOznwic-K|_;AK-?sbfy>E7$7H#%x2?=O*-SdwP~)OfV2J^Yin0FJ zNcvw3)wU3csySIDu1{G&ma7cEtc{NPb3knA}aeWb0l#HKCvr$GDyc*>~Ikc&yh0O%|?% zYjtGM4Y?<3WFKUFtQ4q*f%7D)GPHn`OI)6*|Kt1|E|`Ow2kHrnb$5; zi6s+BVy`&)no=#B4sj&y`Y=atHt5-Bqo)pJh+*f&n~V#9_qze!&ojB>Se0SuV}qVI zuBS&&{X+DFyj0hk->yDi&@>96QLM!2jg6JyS|`h3^MirSx0MUu4q%*3Xw=C*8{*F? zdUHZ%Oi1%ALK57bU)`4IAA^!Vu96ZFgzmtHvv)!#gXX)SXLAF70^Bp-lg6~o5t#`h z?@UER6EWWGltJS+1C1xyF6T58>G?_eFSxy7eEf(jwXi&1#pX}5W`vA&9x|o-$^7Bx zbA(G3gDgphp^wEq%roYe85>svI6pLRp zov*5Cs9H{?WM)^1dRZDxSe;0m`s6q#tW-@MUN=O&GKtRsymMosHJ6IX+lKo$PNhdZ klg_+MRr6X-P099h_@<%dTB?PO+lk@-f9lZ=`G_C@0MRCd*Z=?k literal 1340 zcmV-C1;hG5RzV zq@5d)Egy>r00000000B+na^+IL=?vx5JIYi1UJMY7*$AVp-$tZo3z$~=%Q|$19Vlo zq6a!-J^VQCv&NT6P2If~f;?X>%F zntI8cDCTNp$Vv^3{fRz{+A{0|Z^tme|EbqAr;GVk<}7W_nwT3Yn1($}M?nebSxS%D~bIg+5Fka<`1QC$RXBKi6IIFlVQw25CL+XxG_-4c#mk=q#MTO zpp_Iiv7raTROM)*D@0lMNau7ibYQP?hN?LU zKk1>v(InIPsG)QK78;UpHDPBhz=MdzAafx3v9t%2$(045^uJ zkuTUW1g~Eh$&AsfX?)$#IH|{TB<>p$oij1LFq#{;l$)ytwW0-Q=4}nJge(v)jc|eD zF!ULRLQB+7MpOGPuc_%wn+?7`U8XbV^oN@_O6aqLa;~lMOU3Dg~D4!!RG~ ze~hI6xm0cmk*J!JW#amj1!T3%@XOi+YsyKBOXz`K$50n0TT_6!mn^`K6DsvLDg?wT zEM!OpF8j)GW%-kLLlO|1=kG|t~MOVX=Nt=-y5O$y4a%LrOd~= zR3{e;_~To^>zey?gV<-Z0if6bSbJNkFEmZWVoW5~RA zl}ap`ND_O^$<~x=*>r#-X~%~Jdhze5@iTI`OV%#HaNxF^0RO=w#n zG8aVNnu&-eVzTKeg2t}~8b6M9J7<|l&rj3;KesuIPac7#mR2XL+2U!}oY1i@LZ@(F zSv(wlif}1o@a5gphp^wEt&X20*z5>svI z6!Tw1U975Ms9H^>jLfbR^-?vOvO1MG^T~2XSfQFazF~-ZVH%%4co)V*Yc3R%Hx2i% yo=J~-Wb7gH^4(oSai@2Qq|C2!}vZTb)1c-2b`Apiic8-