diff --git a/adapter-battleshiper/index.js b/adapter-battleshiper/index.js index 426755a..1c0f21d 100644 --- a/adapter-battleshiper/index.js +++ b/adapter-battleshiper/index.js @@ -2,6 +2,7 @@ import { writeFileSync } from 'node:fs'; import esbuild from 'esbuild'; import { fileURLToPath } from 'node:url'; import { posix } from 'node:path'; +import AdmZip from "adm-zip"; /** @param {import('./index.js').default} */ export default function (options = {}) { @@ -50,7 +51,6 @@ export default function (options = {}) { bundle: true, sourcemap: "linked", }) - if (result.warnings.length > 0) { console.error((await esbuild.formatMessages(result.warnings, { kind: "warning", @@ -66,6 +66,15 @@ export default function (options = {}) { })).join("\n")) return } + + try { + const zip = new AdmZip(); + zip.addLocalFile(`${dest}/server/index.js`, "", "index.js"); + await zip.writeZipPromise(`${dest}/server/handler.zip`); + } catch (err) { + console.error("failed to create zip file:") + console.error(err.message) + } }, }; diff --git a/adapter-battleshiper/package-lock.json b/adapter-battleshiper/package-lock.json index 720ac8c..14c28fb 100644 --- a/adapter-battleshiper/package-lock.json +++ b/adapter-battleshiper/package-lock.json @@ -1,15 +1,16 @@ { "name": "@megakuul/adapter-battleshiper", - "version": "0.3.0", + "version": "0.4.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@megakuul/adapter-battleshiper", - "version": "0.3.0", + "version": "0.4.0", "license": "MIT", "dependencies": { - "esbuild": "^0.23.0" + "adm-zip": "^0.5.16", + "esbuild": "^0.23.1" }, "devDependencies": { "@types/aws-lambda": "^8.10.140" @@ -33,9 +34,9 @@ } }, "node_modules/@esbuild/aix-ppc64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.23.0.tgz", - "integrity": "sha512-3sG8Zwa5fMcA9bgqB8AfWPQ+HFke6uD3h1s3RIwUNK8EG7a4buxvuFTs3j1IMs2NXAk9F30C/FF4vxRgQCcmoQ==", + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.23.1.tgz", + "integrity": "sha512-6VhYk1diRqrhBAqpJEdjASR/+WVRtfjpqKuNw11cLiaWpAT/Uu+nokB+UJnevzy/P9C/ty6AOe0dwueMrGh/iQ==", "cpu": [ "ppc64" ], @@ -49,9 +50,9 @@ } }, "node_modules/@esbuild/android-arm": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.23.0.tgz", - "integrity": "sha512-+KuOHTKKyIKgEEqKbGTK8W7mPp+hKinbMBeEnNzjJGyFcWsfrXjSTNluJHCY1RqhxFurdD8uNXQDei7qDlR6+g==", + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.23.1.tgz", + "integrity": "sha512-uz6/tEy2IFm9RYOyvKl88zdzZfwEfKZmnX9Cj1BHjeSGNuGLuMD1kR8y5bteYmwqKm1tj8m4cb/aKEorr6fHWQ==", "cpu": [ "arm" ], @@ -65,9 +66,9 @@ } }, "node_modules/@esbuild/android-arm64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.23.0.tgz", - "integrity": "sha512-EuHFUYkAVfU4qBdyivULuu03FhJO4IJN9PGuABGrFy4vUuzk91P2d+npxHcFdpUnfYKy0PuV+n6bKIpHOB3prQ==", + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.23.1.tgz", + "integrity": "sha512-xw50ipykXcLstLeWH7WRdQuysJqejuAGPd30vd1i5zSyKK3WE+ijzHmLKxdiCMtH1pHz78rOg0BKSYOSB/2Khw==", "cpu": [ "arm64" ], @@ -81,9 +82,9 @@ } }, "node_modules/@esbuild/android-x64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.23.0.tgz", - "integrity": "sha512-WRrmKidLoKDl56LsbBMhzTTBxrsVwTKdNbKDalbEZr0tcsBgCLbEtoNthOW6PX942YiYq8HzEnb4yWQMLQuipQ==", + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.23.1.tgz", + "integrity": "sha512-nlN9B69St9BwUoB+jkyU090bru8L0NA3yFvAd7k8dNsVH8bi9a8cUAUSEcEEgTp2z3dbEDGJGfP6VUnkQnlReg==", "cpu": [ "x64" ], @@ -97,9 +98,9 @@ } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.23.0.tgz", - "integrity": "sha512-YLntie/IdS31H54Ogdn+v50NuoWF5BDkEUFpiOChVa9UnKpftgwzZRrI4J132ETIi+D8n6xh9IviFV3eXdxfow==", + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.23.1.tgz", + "integrity": "sha512-YsS2e3Wtgnw7Wq53XXBLcV6JhRsEq8hkfg91ESVadIrzr9wO6jJDMZnCQbHm1Guc5t/CdDiFSSfWP58FNuvT3Q==", "cpu": [ "arm64" ], @@ -113,9 +114,9 @@ } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.23.0.tgz", - "integrity": "sha512-IMQ6eme4AfznElesHUPDZ+teuGwoRmVuuixu7sv92ZkdQcPbsNHzutd+rAfaBKo8YK3IrBEi9SLLKWJdEvJniQ==", + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.23.1.tgz", + "integrity": "sha512-aClqdgTDVPSEGgoCS8QDG37Gu8yc9lTHNAQlsztQ6ENetKEO//b8y31MMu2ZaPbn4kVsIABzVLXYLhCGekGDqw==", "cpu": [ "x64" ], @@ -129,9 +130,9 @@ } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.23.0.tgz", - "integrity": "sha512-0muYWCng5vqaxobq6LB3YNtevDFSAZGlgtLoAc81PjUfiFz36n4KMpwhtAd4he8ToSI3TGyuhyx5xmiWNYZFyw==", + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.23.1.tgz", + "integrity": "sha512-h1k6yS8/pN/NHlMl5+v4XPfikhJulk4G+tKGFIOwURBSFzE8bixw1ebjluLOjfwtLqY0kewfjLSrO6tN2MgIhA==", "cpu": [ "arm64" ], @@ -145,9 +146,9 @@ } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.23.0.tgz", - "integrity": "sha512-XKDVu8IsD0/q3foBzsXGt/KjD/yTKBCIwOHE1XwiXmrRwrX6Hbnd5Eqn/WvDekddK21tfszBSrE/WMaZh+1buQ==", + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.23.1.tgz", + "integrity": "sha512-lK1eJeyk1ZX8UklqFd/3A60UuZ/6UVfGT2LuGo3Wp4/z7eRTRYY+0xOu2kpClP+vMTi9wKOfXi2vjUpO1Ro76g==", "cpu": [ "x64" ], @@ -161,9 +162,9 @@ } }, "node_modules/@esbuild/linux-arm": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.23.0.tgz", - "integrity": "sha512-SEELSTEtOFu5LPykzA395Mc+54RMg1EUgXP+iw2SJ72+ooMwVsgfuwXo5Fn0wXNgWZsTVHwY2cg4Vi/bOD88qw==", + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.23.1.tgz", + "integrity": "sha512-CXXkzgn+dXAPs3WBwE+Kvnrf4WECwBdfjfeYHpMeVxWE0EceB6vhWGShs6wi0IYEqMSIzdOF1XjQ/Mkm5d7ZdQ==", "cpu": [ "arm" ], @@ -177,9 +178,9 @@ } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.23.0.tgz", - "integrity": "sha512-j1t5iG8jE7BhonbsEg5d9qOYcVZv/Rv6tghaXM/Ug9xahM0nX/H2gfu6X6z11QRTMT6+aywOMA8TDkhPo8aCGw==", + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.23.1.tgz", + "integrity": "sha512-/93bf2yxencYDnItMYV/v116zff6UyTjo4EtEQjUBeGiVpMmffDNUyD9UN2zV+V3LRV3/on4xdZ26NKzn6754g==", "cpu": [ "arm64" ], @@ -193,9 +194,9 @@ } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.23.0.tgz", - "integrity": "sha512-P7O5Tkh2NbgIm2R6x1zGJJsnacDzTFcRWZyTTMgFdVit6E98LTxO+v8LCCLWRvPrjdzXHx9FEOA8oAZPyApWUA==", + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.23.1.tgz", + "integrity": "sha512-VTN4EuOHwXEkXzX5nTvVY4s7E/Krz7COC8xkftbbKRYAl96vPiUssGkeMELQMOnLOJ8k3BY1+ZY52tttZnHcXQ==", "cpu": [ "ia32" ], @@ -209,9 +210,9 @@ } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.23.0.tgz", - "integrity": "sha512-InQwepswq6urikQiIC/kkx412fqUZudBO4SYKu0N+tGhXRWUqAx+Q+341tFV6QdBifpjYgUndV1hhMq3WeJi7A==", + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.23.1.tgz", + "integrity": "sha512-Vx09LzEoBa5zDnieH8LSMRToj7ir/Jeq0Gu6qJ/1GcBq9GkfoEAoXvLiW1U9J1qE/Y/Oyaq33w5p2ZWrNNHNEw==", "cpu": [ "loong64" ], @@ -225,9 +226,9 @@ } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.23.0.tgz", - "integrity": "sha512-J9rflLtqdYrxHv2FqXE2i1ELgNjT+JFURt/uDMoPQLcjWQA5wDKgQA4t/dTqGa88ZVECKaD0TctwsUfHbVoi4w==", + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.23.1.tgz", + "integrity": "sha512-nrFzzMQ7W4WRLNUOU5dlWAqa6yVeI0P78WKGUo7lg2HShq/yx+UYkeNSE0SSfSure0SqgnsxPvmAUu/vu0E+3Q==", "cpu": [ "mips64el" ], @@ -241,9 +242,9 @@ } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.23.0.tgz", - "integrity": "sha512-cShCXtEOVc5GxU0fM+dsFD10qZ5UpcQ8AM22bYj0u/yaAykWnqXJDpd77ublcX6vdDsWLuweeuSNZk4yUxZwtw==", + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.23.1.tgz", + "integrity": "sha512-dKN8fgVqd0vUIjxuJI6P/9SSSe/mB9rvA98CSH2sJnlZ/OCZWO1DJvxj8jvKTfYUdGfcq2dDxoKaC6bHuTlgcw==", "cpu": [ "ppc64" ], @@ -257,9 +258,9 @@ } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.23.0.tgz", - "integrity": "sha512-HEtaN7Y5UB4tZPeQmgz/UhzoEyYftbMXrBCUjINGjh3uil+rB/QzzpMshz3cNUxqXN7Vr93zzVtpIDL99t9aRw==", + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.23.1.tgz", + "integrity": "sha512-5AV4Pzp80fhHL83JM6LoA6pTQVWgB1HovMBsLQ9OZWLDqVY8MVobBXNSmAJi//Csh6tcY7e7Lny2Hg1tElMjIA==", "cpu": [ "riscv64" ], @@ -273,9 +274,9 @@ } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.23.0.tgz", - "integrity": "sha512-WDi3+NVAuyjg/Wxi+o5KPqRbZY0QhI9TjrEEm+8dmpY9Xir8+HE/HNx2JoLckhKbFopW0RdO2D72w8trZOV+Wg==", + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.23.1.tgz", + "integrity": "sha512-9ygs73tuFCe6f6m/Tb+9LtYxWR4c9yg7zjt2cYkjDbDpV/xVn+68cQxMXCjUpYwEkze2RcU/rMnfIXNRFmSoDw==", "cpu": [ "s390x" ], @@ -289,9 +290,9 @@ } }, "node_modules/@esbuild/linux-x64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.23.0.tgz", - "integrity": "sha512-a3pMQhUEJkITgAw6e0bWA+F+vFtCciMjW/LPtoj99MhVt+Mfb6bbL9hu2wmTZgNd994qTAEw+U/r6k3qHWWaOQ==", + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.23.1.tgz", + "integrity": "sha512-EV6+ovTsEXCPAp58g2dD68LxoP/wK5pRvgy0J/HxPGB009omFPv3Yet0HiaqvrIrgPTBuC6wCH1LTOY91EO5hQ==", "cpu": [ "x64" ], @@ -305,9 +306,9 @@ } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.23.0.tgz", - "integrity": "sha512-cRK+YDem7lFTs2Q5nEv/HHc4LnrfBCbH5+JHu6wm2eP+d8OZNoSMYgPZJq78vqQ9g+9+nMuIsAO7skzphRXHyw==", + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.23.1.tgz", + "integrity": "sha512-aevEkCNu7KlPRpYLjwmdcuNz6bDFiE7Z8XC4CPqExjTvrHugh28QzUXVOZtiYghciKUacNktqxdpymplil1beA==", "cpu": [ "x64" ], @@ -321,9 +322,9 @@ } }, "node_modules/@esbuild/openbsd-arm64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.23.0.tgz", - "integrity": "sha512-suXjq53gERueVWu0OKxzWqk7NxiUWSUlrxoZK7usiF50C6ipColGR5qie2496iKGYNLhDZkPxBI3erbnYkU0rQ==", + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.23.1.tgz", + "integrity": "sha512-3x37szhLexNA4bXhLrCC/LImN/YtWis6WXr1VESlfVtVeoFJBRINPJ3f0a/6LV8zpikqoUg4hyXw0sFBt5Cr+Q==", "cpu": [ "arm64" ], @@ -337,9 +338,9 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.23.0.tgz", - "integrity": "sha512-6p3nHpby0DM/v15IFKMjAaayFhqnXV52aEmv1whZHX56pdkK+MEaLoQWj+H42ssFarP1PcomVhbsR4pkz09qBg==", + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.23.1.tgz", + "integrity": "sha512-aY2gMmKmPhxfU+0EdnN+XNtGbjfQgwZj43k8G3fyrDM/UdZww6xrWxmDkuz2eCZchqVeABjV5BpildOrUbBTqA==", "cpu": [ "x64" ], @@ -353,9 +354,9 @@ } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.23.0.tgz", - "integrity": "sha512-BFelBGfrBwk6LVrmFzCq1u1dZbG4zy/Kp93w2+y83Q5UGYF1d8sCzeLI9NXjKyujjBBniQa8R8PzLFAUrSM9OA==", + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.23.1.tgz", + "integrity": "sha512-RBRT2gqEl0IKQABT4XTj78tpk9v7ehp+mazn2HbUeZl1YMdaGAQqhapjGTCe7uw7y0frDi4gS0uHzhvpFuI1sA==", "cpu": [ "x64" ], @@ -369,9 +370,9 @@ } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.23.0.tgz", - "integrity": "sha512-lY6AC8p4Cnb7xYHuIxQ6iYPe6MfO2CC43XXKo9nBXDb35krYt7KGhQnOkRGar5psxYkircpCqfbNDB4uJbS2jQ==", + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.23.1.tgz", + "integrity": "sha512-4O+gPR5rEBe2FpKOVyiJ7wNDPA8nGzDuJ6gN4okSA1gEOYZ67N8JPk58tkWtdtPeLz7lBnY6I5L3jdsr3S+A6A==", "cpu": [ "arm64" ], @@ -385,9 +386,9 @@ } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.23.0.tgz", - "integrity": "sha512-7L1bHlOTcO4ByvI7OXVI5pNN6HSu6pUQq9yodga8izeuB1KcT2UkHaH6118QJwopExPn0rMHIseCTx1CRo/uNA==", + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.23.1.tgz", + "integrity": "sha512-BcaL0Vn6QwCwre3Y717nVHZbAa4UBEigzFm6VdsVdT/MbZ38xoj1X9HPkZhbmaBGUD1W8vxAfffbDe8bA6AKnQ==", "cpu": [ "ia32" ], @@ -401,9 +402,9 @@ } }, "node_modules/@esbuild/win32-x64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.23.0.tgz", - "integrity": "sha512-Arm+WgUFLUATuoxCJcahGuk6Yj9Pzxd6l11Zb/2aAuv5kWWvvfhLFo2fni4uSK5vzlUdCGZ/BdV5tH8klj8p8g==", + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.23.1.tgz", + "integrity": "sha512-BHpFFeslkWrXWyUPnbKm+xYYVYruCinGcftSBaa8zoF9hZO4BcSCFUvHVTtzpIY6YzUnYtuEhZ+C9iEXjxnasg==", "cpu": [ "x64" ], @@ -819,6 +820,15 @@ "node": ">=0.4.0" } }, + "node_modules/adm-zip": { + "version": "0.5.16", + "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.16.tgz", + "integrity": "sha512-TGw5yVi4saajsSEgz25grObGHEUaDrniwvA2qwSC060KfqGPdglhvPMA2lPIoxs3PQIItj2iag35fONcQqgUaQ==", + "license": "MIT", + "engines": { + "node": ">=12.0" + } + }, "node_modules/aria-query": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", @@ -923,9 +933,9 @@ "peer": true }, "node_modules/esbuild": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.23.0.tgz", - "integrity": "sha512-1lvV17H2bMYda/WaFb2jLPeHU3zml2k4/yagNMG8Q/YtfMjCwEUZa2eXXMgZTVSL5q1n4H7sQ0X6CdJDqqeCFA==", + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.23.1.tgz", + "integrity": "sha512-VVNz/9Sa0bs5SELtn3f7qhJCDPCF5oMEl5cO9/SSinpE9hbPVvxbd572HH5AKiP7WD8INO53GgfDDhRjkylHEg==", "hasInstallScript": true, "license": "MIT", "bin": { @@ -935,30 +945,30 @@ "node": ">=18" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.23.0", - "@esbuild/android-arm": "0.23.0", - "@esbuild/android-arm64": "0.23.0", - "@esbuild/android-x64": "0.23.0", - "@esbuild/darwin-arm64": "0.23.0", - "@esbuild/darwin-x64": "0.23.0", - "@esbuild/freebsd-arm64": "0.23.0", - "@esbuild/freebsd-x64": "0.23.0", - "@esbuild/linux-arm": "0.23.0", - "@esbuild/linux-arm64": "0.23.0", - "@esbuild/linux-ia32": "0.23.0", - "@esbuild/linux-loong64": "0.23.0", - "@esbuild/linux-mips64el": "0.23.0", - "@esbuild/linux-ppc64": "0.23.0", - "@esbuild/linux-riscv64": "0.23.0", - "@esbuild/linux-s390x": "0.23.0", - "@esbuild/linux-x64": "0.23.0", - "@esbuild/netbsd-x64": "0.23.0", - "@esbuild/openbsd-arm64": "0.23.0", - "@esbuild/openbsd-x64": "0.23.0", - "@esbuild/sunos-x64": "0.23.0", - "@esbuild/win32-arm64": "0.23.0", - "@esbuild/win32-ia32": "0.23.0", - "@esbuild/win32-x64": "0.23.0" + "@esbuild/aix-ppc64": "0.23.1", + "@esbuild/android-arm": "0.23.1", + "@esbuild/android-arm64": "0.23.1", + "@esbuild/android-x64": "0.23.1", + "@esbuild/darwin-arm64": "0.23.1", + "@esbuild/darwin-x64": "0.23.1", + "@esbuild/freebsd-arm64": "0.23.1", + "@esbuild/freebsd-x64": "0.23.1", + "@esbuild/linux-arm": "0.23.1", + "@esbuild/linux-arm64": "0.23.1", + "@esbuild/linux-ia32": "0.23.1", + "@esbuild/linux-loong64": "0.23.1", + "@esbuild/linux-mips64el": "0.23.1", + "@esbuild/linux-ppc64": "0.23.1", + "@esbuild/linux-riscv64": "0.23.1", + "@esbuild/linux-s390x": "0.23.1", + "@esbuild/linux-x64": "0.23.1", + "@esbuild/netbsd-x64": "0.23.1", + "@esbuild/openbsd-arm64": "0.23.1", + "@esbuild/openbsd-x64": "0.23.1", + "@esbuild/sunos-x64": "0.23.1", + "@esbuild/win32-arm64": "0.23.1", + "@esbuild/win32-ia32": "0.23.1", + "@esbuild/win32-x64": "0.23.1" } }, "node_modules/esm-env": { diff --git a/adapter-battleshiper/package.json b/adapter-battleshiper/package.json index 93b3c3f..fd71ab0 100644 --- a/adapter-battleshiper/package.json +++ b/adapter-battleshiper/package.json @@ -9,7 +9,7 @@ "sveltekit", "battleshiper" ], - "version": "0.3.0", + "version": "0.4.0", "author": "Megakuul", "license": "MIT", "private": false, @@ -39,6 +39,7 @@ "@types/aws-lambda": "^8.10.140" }, "dependencies": { - "esbuild": "^0.23.0" + "adm-zip": "^0.5.16", + "esbuild": "^0.23.1" } } diff --git a/api/resource/deleteproject/deleteproject.go b/api/resource/deleteproject/deleteproject.go index 02a4bbe..72668b6 100644 --- a/api/resource/deleteproject/deleteproject.go +++ b/api/resource/deleteproject/deleteproject.go @@ -16,7 +16,7 @@ import ( ) type deleteProjectInput struct { - ProjectId string `json:"project_id"` + ProjectName string `json:"project_name"` } type deleteProjectOutput struct { @@ -73,25 +73,19 @@ func runHandleDeleteProject(request events.APIGatewayV2HTTPRequest, transportCtx } projectCollection := routeCtx.Database.Collection(project.PROJECT_COLLECTION) - - deletedProject := &project.Project{} - err = projectCollection.FindOneAndUpdate(transportCtx, bson.M{"id": deleteProjectInput.ProjectId}, bson.M{ + result, err := projectCollection.UpdateOne(transportCtx, bson.D{ + {Key: "name", Value: deleteProjectInput.ProjectName}, + {Key: "owner_id", Value: userToken.Id}, + {Key: "deleted", Value: false}, + }, bson.M{ "$set": bson.M{ - "deleted": bson.M{ - "$cond": bson.M{ - "if": bson.M{"$eq": bson.A{"$owner_id", userToken.Id}}, - "then": true, - "else": false, - }, - }, + "deleted": true, }, - }).Decode(&deletedProject) + }) if err != nil { - return nil, http.StatusBadRequest, fmt.Errorf("failed to mark project as deleted on database") - } - - if !deletedProject.Deleted { - return nil, http.StatusForbidden, fmt.Errorf("user is not the owner of the project") + return nil, http.StatusInternalServerError, fmt.Errorf("failed to mark project as deleted on database") + } else if result.MatchedCount < 1 { + return nil, http.StatusNotFound, fmt.Errorf("project '%s' not found", deleteProjectInput.ProjectName) } return &deleteProjectOutput{ diff --git a/api/resource/fetchlog/fetchlog.go b/api/resource/fetchlog/fetchlog.go index 4ca9969..a96f9f3 100644 --- a/api/resource/fetchlog/fetchlog.go +++ b/api/resource/fetchlog/fetchlog.go @@ -88,9 +88,10 @@ func runHandleFetchLog(request events.APIGatewayV2HTTPRequest, transportCtx cont specifiedProject := &project.Project{} err = projectCollection.FindOne(transportCtx, - bson.M{ - "owner_id": userToken.Id, - "name": fetchLogInput.ProjectName, + bson.D{ + {Key: "owner_id", Value: userToken.Id}, + {Key: "name", Value: fetchLogInput.ProjectName}, + {Key: "deleted", Value: false}, }, ).Decode(&specifiedProject) if err == mongo.ErrNoDocuments { diff --git a/api/resource/main.go b/api/resource/main.go index 5002826..c257561 100644 --- a/api/resource/main.go +++ b/api/resource/main.go @@ -100,6 +100,7 @@ func run() error { database.SetupIndexes(databaseHandle.Collection(project.PROJECT_COLLECTION), context.TODO(), []database.Index{ {FieldNames: []string{"name"}, SortingOrder: 1, Unique: true}, {FieldNames: []string{"owner_id"}, SortingOrder: 1, Unique: false}, + {FieldNames: []string{"deleted"}, SortingOrder: 1, Unique: false}, }) jwtOptions, err := auth.CreateJwtOptions(awsConfig, context.TODO(), JWT_CREDENTIAL_ARN, 0) diff --git a/api/resource/updatealias/updatealias.go b/api/resource/updatealias/updatealias.go index a80e97c..4a0ee70 100644 --- a/api/resource/updatealias/updatealias.go +++ b/api/resource/updatealias/updatealias.go @@ -95,6 +95,7 @@ func runHandleUpdateAlias(request events.APIGatewayV2HTTPRequest, transportCtx c err = projectCollection.FindOne(transportCtx, bson.D{ {Key: "name", Value: updateAliasInput.ProjectName}, {Key: "owner_id", Value: userDoc.Id}, + {Key: "deleted", Value: false}, }).Decode(&projectDoc) if err == mongo.ErrNoDocuments { return nil, http.StatusNotFound, fmt.Errorf("project does not exist") diff --git a/api/resource/updateproject/updateproject.go b/api/resource/updateproject/updateproject.go index f6e1afe..aa7de09 100644 --- a/api/resource/updateproject/updateproject.go +++ b/api/resource/updateproject/updateproject.go @@ -113,6 +113,7 @@ func runHandleUpdateProject(request events.APIGatewayV2HTTPRequest, transportCtx result, err := projectCollection.UpdateOne(transportCtx, bson.D{ {Key: "name", Value: updateProjectInput.ProjectName}, {Key: "owner_id", Value: userDoc.Id}, + {Key: "deleted", Value: false}, }, bson.M{ "$set": updateSpec, }) diff --git a/pipeline/delete/deleteprojects/deleteprojects.go b/pipeline/delete/deleteprojects/deleteprojects.go new file mode 100644 index 0000000..d878b7e --- /dev/null +++ b/pipeline/delete/deleteprojects/deleteprojects.go @@ -0,0 +1,110 @@ +package deleteprojects + +import ( + "context" + "fmt" + "log" + "strings" + "time" + + "github.com/aws/aws-lambda-go/events" + "github.com/megakuul/battleshiper/lib/model/project" + "github.com/megakuul/battleshiper/pipeline/delete/eventcontext" + "go.mongodb.org/mongo-driver/bson" +) + +func HandleDeleteProjects(eventCtx eventcontext.Context) func(context.Context, events.CloudWatchEvent) error { + return func(ctx context.Context, event events.CloudWatchEvent) error { + err := runHandleDeleteProjects(event, ctx, eventCtx) + if err != nil { + log.Printf("ERROR DELETEPROJECTS: %v\n", err) + return err + } + return nil + } +} + +func runHandleDeleteProjects(request events.CloudWatchEvent, transportCtx context.Context, eventCtx eventcontext.Context) error { + projectCollection := eventCtx.Database.Collection(project.PROJECT_COLLECTION) + + projectDoc := &project.Project{} + err := projectCollection.FindOneAndUpdate(transportCtx, bson.D{ + {Key: "name", Value: deployClaims.Project}, + {Key: "owner_id", Value: deployClaims.UserID}, + }, bson.M{ + // Lock the pipeline, this step is used to ensure only one deployment runs at a time. + // running multiple deployments at the same time should not cause major issues, + // however it can cause weird or unintended behavior for the project. + "$set": bson.M{ + "pipeline_lock": true, + }, + }).Decode(&projectDoc) + if err != nil { + return fmt.Errorf("failed to fetch project from database") + } + if projectDoc.PipelineLock { + return fmt.Errorf("project locked") + } + + // Finish build step + buildResult := project.BuildResult{ + ExecutionIdentifier: deployRequest.Parameters.ExecutionIdentifier, + Timepoint: time.Now().Unix(), + } + if strings.ToUpper(deployRequest.Status) != "SUCCEEDED" { + buildResult.Successful = false + result, err := projectCollection.UpdateByID(transportCtx, projectDoc.MongoID, bson.M{ + "$set": bson.M{ + "last_build_result": buildResult, + "status": fmt.Errorf("BUILD FAILED: %v", err), + }, + }) + if err != nil && result.MatchedCount < 1 { + return fmt.Errorf("failed to update project (last_build_result)") + } + return nil + } else { + buildResult.Successful = true + result, err := projectCollection.UpdateByID(transportCtx, projectDoc.MongoID, bson.M{ + "$set": bson.M{ + "last_build_result": buildResult, + }, + }) + if err != nil && result.MatchedCount < 1 { + return fmt.Errorf("failed to update project (last_build_result)") + } + } + + // Start actual deployment step + deploymentResult := project.DeploymentResult{ + ExecutionIdentifier: deployRequest.Parameters.ExecutionIdentifier, + } + if err := deployProject(transportCtx, eventCtx, projectDoc, deployClaims.UserID, deployRequest.Parameters.ExecutionIdentifier); err != nil { + deploymentResult.Timepoint = time.Now().Unix() + deploymentResult.Successful = false + result, err := projectCollection.UpdateByID(transportCtx, projectDoc.MongoID, bson.M{ + "$set": bson.M{ + "last_deployment_result": deploymentResult, + "status": fmt.Errorf("DEPLOYMENT FAILED: %v", err), + }, + }) + if err != nil && result.MatchedCount < 1 { + return fmt.Errorf("failed to update project (last_deployment_result)") + } + return nil + } else { + deploymentResult.Timepoint = time.Now().Unix() + deploymentResult.Successful = true + result, err := projectCollection.UpdateByID(transportCtx, projectDoc.MongoID, bson.M{ + "$set": bson.M{ + "last_deployment_result": deploymentResult, + "status": "", + }, + }) + if err != nil && result.MatchedCount < 1 { + return fmt.Errorf("failed to update project (last_deployment_result)") + } + } + + return nil +} diff --git a/pipeline/delete/eventcontext/eventcontext.go b/pipeline/delete/eventcontext/eventcontext.go new file mode 100644 index 0000000..64a4b15 --- /dev/null +++ b/pipeline/delete/eventcontext/eventcontext.go @@ -0,0 +1,26 @@ +package eventcontext + +import ( + "github.com/aws/aws-sdk-go-v2/service/cloudformation" + "github.com/aws/aws-sdk-go-v2/service/cloudfrontkeyvaluestore" + "github.com/aws/aws-sdk-go-v2/service/s3" + "go.mongodb.org/mongo-driver/mongo" +) + +type BucketConfiguration struct { + StaticBucketName string +} + +type CloudfrontConfiguration struct { + CacheArn string +} + +// Context provides data to event handlers. +type Context struct { + Database *mongo.Database + S3Client *s3.Client + CloudformationClient *cloudformation.Client + CloudfrontCacheClient *cloudfrontkeyvaluestore.Client + BucketConfiguration *BucketConfiguration + CloudfrontConfiguration *CloudfrontConfiguration +} diff --git a/pipeline/delete/go.mod b/pipeline/delete/go.mod index 50afc0d..eda4623 100644 --- a/pipeline/delete/go.mod +++ b/pipeline/delete/go.mod @@ -1,3 +1,47 @@ -module github.com/megakuul/battleshiper/pipeline/deploy +module github.com/megakuul/battleshiper/pipeline/delete go 1.23.0 + +require ( + github.com/aws/aws-lambda-go v1.47.0 + github.com/aws/aws-sdk-go-v2/config v1.27.33 + github.com/aws/aws-sdk-go-v2/service/cloudformation v1.53.7 + github.com/aws/aws-sdk-go-v2/service/cloudfrontkeyvaluestore v1.6.6 + github.com/aws/aws-sdk-go-v2/service/s3 v1.61.2 + github.com/megakuul/battleshiper/lib/helper v0.1.12 + github.com/megakuul/battleshiper/lib/model v0.2.5 + go.mongodb.org/mongo-driver v1.16.1 +) + +require ( + github.com/aws/aws-sdk-go-v2 v1.30.5 // indirect + github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.4 // indirect + github.com/aws/aws-sdk-go-v2/credentials v1.17.32 // indirect + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.13 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.17 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.17 // indirect + github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 // indirect + github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.17 // indirect + github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs v1.39.0 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.4 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.19 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.19 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.17 // indirect + github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.32.8 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.22.7 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.7 // indirect + github.com/aws/aws-sdk-go-v2/service/sts v1.30.7 // indirect + github.com/aws/smithy-go v1.20.4 // indirect + github.com/golang-jwt/jwt/v5 v5.2.1 // indirect + github.com/golang/snappy v0.0.4 // indirect + github.com/jmespath/go-jmespath v0.4.0 // indirect + github.com/klauspost/compress v1.17.9 // indirect + github.com/montanaflynn/stats v0.7.1 // indirect + github.com/xdg-go/pbkdf2 v1.0.0 // indirect + github.com/xdg-go/scram v1.1.2 // indirect + github.com/xdg-go/stringprep v1.0.4 // indirect + github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect + golang.org/x/crypto v0.27.0 // indirect + golang.org/x/sync v0.8.0 // indirect + golang.org/x/text v0.18.0 // indirect +) diff --git a/pipeline/delete/go.sum b/pipeline/delete/go.sum new file mode 100644 index 0000000..be3e761 --- /dev/null +++ b/pipeline/delete/go.sum @@ -0,0 +1,119 @@ +github.com/aws/aws-lambda-go v1.47.0 h1:0H8s0vumYx/YKs4sE7YM0ktwL2eWse+kfopsRI1sXVI= +github.com/aws/aws-lambda-go v1.47.0/go.mod h1:dpMpZgvWx5vuQJfBt0zqBha60q7Dd7RfgJv23DymV8A= +github.com/aws/aws-sdk-go-v2 v1.30.5 h1:mWSRTwQAb0aLE17dSzztCVJWI9+cRMgqebndjwDyK0g= +github.com/aws/aws-sdk-go-v2 v1.30.5/go.mod h1:CT+ZPWXbYrci8chcARI3OmI/qgd+f6WtuLOoaIA8PR0= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.4 h1:70PVAiL15/aBMh5LThwgXdSQorVr91L127ttckI9QQU= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.4/go.mod h1:/MQxMqci8tlqDH+pjmoLu1i0tbWCUP1hhyMRuFxpQCw= +github.com/aws/aws-sdk-go-v2/config v1.27.33 h1:Nof9o/MsmH4oa0s2q9a0k7tMz5x/Yj5k06lDODWz3BU= +github.com/aws/aws-sdk-go-v2/config v1.27.33/go.mod h1:kEqdYzRb8dd8Sy2pOdEbExTTF5v7ozEXX0McgPE7xks= +github.com/aws/aws-sdk-go-v2/credentials v1.17.32 h1:7Cxhp/BnT2RcGy4VisJ9miUPecY+lyE9I8JvcZofn9I= +github.com/aws/aws-sdk-go-v2/credentials v1.17.32/go.mod h1:P5/QMF3/DCHbXGEGkdbilXHsyTBX5D3HSwcrSc9p20I= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.13 h1:pfQ2sqNpMVK6xz2RbqLEL0GH87JOwSxPV2rzm8Zsb74= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.13/go.mod h1:NG7RXPUlqfsCLLFfi0+IpKN4sCB9D9fw/qTaSB+xRoU= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.17 h1:pI7Bzt0BJtYA0N/JEC6B8fJ4RBrEMi1LBrkMdFYNSnQ= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.17/go.mod h1:Dh5zzJYMtxfIjYW+/evjQ8uj2OyR/ve2KROHGHlSFqE= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.17 h1:Mqr/V5gvrhA2gvgnF42Zh5iMiQNcOYthFYwCyrnuWlc= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.17/go.mod h1:aLJpZlCmjE+V+KtN1q1uyZkfnUWpQGpbsn89XPKyzfU= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 h1:VaRN3TlFdd6KxX1x3ILT5ynH6HvKgqdiXoTxAF4HQcQ= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1/go.mod h1:FbtygfRFze9usAadmnGJNc8KsP346kEe+y2/oyhGAGc= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.17 h1:Roo69qTpfu8OlJ2Tb7pAYVuF0CpuUMB0IYWwYP/4DZM= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.17/go.mod h1:NcWPxQzGM1USQggaTVwz6VpqMZPX1CvDJLDh6jnOCa4= +github.com/aws/aws-sdk-go-v2/service/cloudformation v1.53.7 h1:pWuvZn0cGEybhLxYUZBlUQF8vaIcJ11I/8o8i1QjdZ0= +github.com/aws/aws-sdk-go-v2/service/cloudformation v1.53.7/go.mod h1:TXiuXcbBl1rEAy9xhZi2TBZeWfoRhJ6ymMfepMxJnZk= +github.com/aws/aws-sdk-go-v2/service/cloudfrontkeyvaluestore v1.6.6 h1:RuRzhxGSlxkxEH0I2fc44D27ODljrmPFumrzn9TJTGs= +github.com/aws/aws-sdk-go-v2/service/cloudfrontkeyvaluestore v1.6.6/go.mod h1:B6djS2mK38QoSzZ5SiAKA0VwS5jxGrhWIMRdNt/O19M= +github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs v1.39.0 h1:FL5Gfgg2Cp669y7egTKUH6lVHOwFbNdm2VbCZvmzeho= +github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs v1.39.0/go.mod h1:bDqBjrjbgWKyis9R6mf3NcjoIrgnrBA9L4W724mg7pA= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.4 h1:KypMCbLPPHEmf9DgMGw51jMj77VfGPAN2Kv4cfhlfgI= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.4/go.mod h1:Vz1JQXliGcQktFTN/LN6uGppAIRoLBR2bMvIMP0gOjc= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.19 h1:FLMkfEiRjhgeDTCjjLoc3URo/TBkgeQbocA78lfkzSI= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.19/go.mod h1:Vx+GucNSsdhaxs3aZIKfSUjKVGsxN25nX2SRcdhuw08= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.19 h1:rfprUlsdzgl7ZL2KlXiUAoJnI/VxfHCvDFr2QDFj6u4= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.19/go.mod h1:SCWkEdRq8/7EK60NcvvQ6NXKuTcchAD4ROAsC37VEZE= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.17 h1:u+EfGmksnJc/x5tq3A+OD7LrMbSSR/5TrKLvkdy/fhY= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.17/go.mod h1:VaMx6302JHax2vHJWgRo+5n9zvbacs3bLU/23DNQrTY= +github.com/aws/aws-sdk-go-v2/service/s3 v1.61.2 h1:Kp6PWAlXwP1UvIflkIP6MFZYBNDCa4mFCGtxrpICVOg= +github.com/aws/aws-sdk-go-v2/service/s3 v1.61.2/go.mod h1:5FmD/Dqq57gP+XwaUnd5WFPipAuzrf0HmupX27Gvjvc= +github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.32.8 h1:HNXhQReFG2fbucvPRxDabbIGQf/6dieOfTnzoGPEqXI= +github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.32.8/go.mod h1:BYr9P/rrcLNJ8A36nT15p8tpoVDZ5lroHuMn/njecBw= +github.com/aws/aws-sdk-go-v2/service/sso v1.22.7 h1:pIaGg+08llrP7Q5aiz9ICWbY8cqhTkyy+0SHvfzQpTc= +github.com/aws/aws-sdk-go-v2/service/sso v1.22.7/go.mod h1:eEygMHnTKH/3kNp9Jr1n3PdejuSNcgwLe1dWgQtO0VQ= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.7 h1:/Cfdu0XV3mONYKaOt1Gr0k1KvQzkzPyiKUdlWJqy+J4= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.7/go.mod h1:bCbAxKDqNvkHxRaIMnyVPXPo+OaPRwvmgzMxbz1VKSA= +github.com/aws/aws-sdk-go-v2/service/sts v1.30.7 h1:NKTa1eqZYw8tiHSRGpP0VtTdub/8KNk8sDkNPFaOKDE= +github.com/aws/aws-sdk-go-v2/service/sts v1.30.7/go.mod h1:NXi1dIAGteSaRLqYgarlhP/Ij0cFT+qmCwiJqWh/U5o= +github.com/aws/smithy-go v1.20.4 h1:2HK1zBdPgRbjFOHlfeQZfpC4r72MOb9bZkiFwggKO+4= +github.com/aws/smithy-go v1.20.4/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk= +github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= +github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= +github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= +github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= +github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= +github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= +github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= +github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/megakuul/battleshiper/lib/helper v0.1.12 h1:3WnImGFX9TpJHdQWV8UtZFVA8zYk8XmPeKFVi90L0NU= +github.com/megakuul/battleshiper/lib/helper v0.1.12/go.mod h1:aU4r+wEWDjaTy1PE3PYeR7MEN19tLqxkmFB7WZIzsas= +github.com/megakuul/battleshiper/lib/model v0.2.5 h1:fgP1yYV4gK1LaoHycjDEhaQdCJycJ88qrvHKxSd+mOA= +github.com/megakuul/battleshiper/lib/model v0.2.5/go.mod h1:N2fHQkJOezOs4B9m0/lMLAdhaaVahf5zmarhfHLzUvQ= +github.com/megakuul/battleshiper/pipeline/deploy v0.0.0-20240914182907-6ff6fe596714 h1:zhlU0iseN8jD4wsJjp2T9srf2V4a3Fm/N78reKkmg9I= +github.com/megakuul/battleshiper/pipeline/deploy v0.0.0-20240914182907-6ff6fe596714/go.mod h1:omMJJUb374tU4aQwjT9z2zhbWqMv3f8Dt3Ir5stQsbw= +github.com/montanaflynn/stats v0.7.1 h1:etflOAAHORrCC44V+aR6Ftzort912ZU+YLiSTuV8eaE= +github.com/montanaflynn/stats v0.7.1/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c= +github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= +github.com/xdg-go/scram v1.1.2 h1:FHX5I5B4i4hKRVRBCFRxq1iQRej7WO3hhBuJf+UUySY= +github.com/xdg-go/scram v1.1.2/go.mod h1:RT/sEzTbU5y00aCK8UOx6R7YryM0iF1N2MOmC3kKLN4= +github.com/xdg-go/stringprep v1.0.4 h1:XLI/Ng3O1Atzq0oBs3TWm+5ZVgkq2aqdlvP9JtoZ6c8= +github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM= +github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 h1:ilQV1hzziu+LLM3zUTJ0trRztfwgjqKnBWNtSRkbmwM= +github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78/go.mod h1:aL8wCCfTfSfmXjznFBSZNN13rSJjlIOI1fUNAtF7rmI= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +go.mongodb.org/mongo-driver v1.16.1 h1:rIVLL3q0IHM39dvE+z2ulZLp9ENZKThVfuvN/IiN4l8= +go.mongodb.org/mongo-driver v1.16.1/go.mod h1:oB6AhJQvFQL4LEHyXi6aJzQJtBiTQHiAd83l0GdFaiw= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A= +golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= +golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= +golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= +golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/pipeline/delete/main.go b/pipeline/delete/main.go index 06ab7d0..c043d66 100644 --- a/pipeline/delete/main.go +++ b/pipeline/delete/main.go @@ -1 +1,79 @@ package main + +import ( + "context" + "fmt" + "log" + "os" + "time" + + "github.com/aws/aws-lambda-go/lambda" + "github.com/aws/aws-sdk-go-v2/config" + "github.com/aws/aws-sdk-go-v2/service/cloudformation" + "github.com/aws/aws-sdk-go-v2/service/cloudfrontkeyvaluestore" + "github.com/aws/aws-sdk-go-v2/service/s3" + "github.com/megakuul/battleshiper/lib/helper/database" + "github.com/megakuul/battleshiper/lib/model/project" + "github.com/megakuul/battleshiper/pipeline/delete/deleteprojects" + "github.com/megakuul/battleshiper/pipeline/delete/eventcontext" + "go.mongodb.org/mongo-driver/mongo" +) + +var ( + REGION = os.Getenv("AWS_REGION") + DATABASE_ENDPOINT = os.Getenv("DATABASE_ENDPOINT") + DATABASE_NAME = os.Getenv("DATABASE_NAME") + DATABASE_SECRET_ARN = os.Getenv("DATABASE_SECRET_ARN") + STATIC_BUCKET_NAME = os.Getenv("STATIC_BUCKET_NAME") + CLOUDFRONT_CACHE_ARN = os.Getenv("CLOUDFRONT_CACHE_ARN") +) + +func main() { + if err := run(); err != nil { + log.Printf("ERROR INITIALIZATION: %v\n", err) + os.Exit(1) + } +} + +func run() error { + awsConfig, err := config.LoadDefaultConfig(context.TODO(), config.WithRegion(REGION)) + if err != nil { + return fmt.Errorf("failed to load aws config: %v", err) + } + + s3Client := s3.NewFromConfig(awsConfig) + + cloudformationClient := cloudformation.NewFromConfig(awsConfig) + + cloudfrontClient := cloudfrontkeyvaluestore.NewFromConfig(awsConfig) + + databaseOptions, err := database.CreateDatabaseOptions(awsConfig, context.TODO(), DATABASE_SECRET_ARN, DATABASE_ENDPOINT, DATABASE_NAME) + if err != nil { + return err + } + databaseClient, err := mongo.Connect(context.TODO(), databaseOptions) + if err != nil { + return err + } + defer func() { + ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second) + if err = databaseClient.Disconnect(ctx); err != nil { + log.Printf("ERROR CLEANUP: %v\n", err) + } + cancel() + }() + databaseHandle := databaseClient.Database(DATABASE_NAME) + + database.SetupIndexes(databaseHandle.Collection(project.PROJECT_COLLECTION), context.TODO(), []database.Index{ + {FieldNames: []string{"deleted"}, SortingOrder: 1, Unique: false}, + }) + + lambda.Start(deleteprojects.HandleDeleteProjects(eventcontext.Context{ + Database: databaseHandle, + S3Client: s3Client, + CloudformationClient: cloudformationClient, + CloudfrontCacheClient: cloudfrontClient, + })) + + return nil +} diff --git a/pipeline/deploy/deployproject/analyze.go b/pipeline/deploy/deployproject/analyze.go index c8f871e..03838e8 100644 --- a/pipeline/deploy/deployproject/analyze.go +++ b/pipeline/deploy/deployproject/analyze.go @@ -15,7 +15,7 @@ import ( ) const ( - SERVER_PATH = "server/index.js" + SERVER_PATH = "server/handler.zip" CLIENT_PATH = "client" PRERENDER_PATH = "prerendered" ) @@ -25,8 +25,10 @@ type ObjectDescription struct { // Key relative to the objects logical root // e.g. build_asset_bucket/x/123/client/_app/static/myimage.png = _app/static/myimage.png. RelativeKey string - // Full source bucket path of the object (including key). - SourcePath string + // Source bucket name of the object. + SourceBucket string + // Source bucket key of the object. + SourceKey string } // BuildInformation provides information about the content of the build output. @@ -95,8 +97,9 @@ func analyzeClientObjects(transportCtx context.Context, s3Client *s3.Client, buc } clientObjects = append(clientObjects, ObjectDescription{ - SourcePath: fmt.Sprintf("%s/%s", bucketName, obj.Key), - RelativeKey: strings.TrimPrefix(*obj.Key, clientPrefix), + SourceBucket: bucketName, + SourceKey: *obj.Key, + RelativeKey: strings.TrimPrefix(*obj.Key, clientPrefix), }) } } @@ -131,8 +134,9 @@ func analyzePrerenderObjects(transportCtx context.Context, s3Client *s3.Client, } prerenderObjects = append(prerenderObjects, ObjectDescription{ - SourcePath: fmt.Sprintf("%s/%s", bucketName, obj.Key), - RelativeKey: strings.TrimPrefix(*obj.Key, prerenderPrefix), + SourceBucket: bucketName, + SourceKey: *obj.Key, + RelativeKey: strings.TrimPrefix(*obj.Key, prerenderPrefix), }) } } @@ -161,8 +165,9 @@ func analyzeServerObject(transportCtx context.Context, s3Client *s3.Client, buck } return &ObjectDescription{ - SourcePath: fmt.Sprintf("%s/%s", bucketName, serverKey), - RelativeKey: SERVER_PATH, + SourceBucket: bucketName, + SourceKey: serverKey, + RelativeKey: SERVER_PATH, }, nil } diff --git a/pipeline/deploy/deployproject/dedicated.go b/pipeline/deploy/deployproject/dedicated.go index 86a0080..40fa591 100644 --- a/pipeline/deploy/deployproject/dedicated.go +++ b/pipeline/deploy/deployproject/dedicated.go @@ -9,7 +9,6 @@ import ( cloudformationtypes "github.com/aws/aws-sdk-go-v2/service/cloudformation/types" goform "github.com/awslabs/goformation/v7" goformation "github.com/awslabs/goformation/v7/cloudformation" - "github.com/awslabs/goformation/v7/cloudformation/apigatewayv2" "github.com/awslabs/goformation/v7/cloudformation/iam" "github.com/awslabs/goformation/v7/cloudformation/lambda" "github.com/awslabs/goformation/v7/cloudformation/tags" @@ -41,7 +40,7 @@ func validateStackState(transportCtx context.Context, eventCtx eventcontext.Cont } // createChangeSet loads the current stack, builds a changeset with the new system and pushes the change set to cloudformation. -func createChangeSet(transportCtx context.Context, eventCtx eventcontext.Context, projectDoc *project.Project, execId string) (string, error) { +func createChangeSet(transportCtx context.Context, eventCtx eventcontext.Context, projectDoc *project.Project, execId string, serverAsset ObjectDescription) (string, error) { stackTemplate, err := eventCtx.CloudformationClient.GetTemplate(transportCtx, &cloudformation.GetTemplateInput{ StackName: aws.String(projectDoc.DedicatedInfrastructure.StackName), }) @@ -53,7 +52,7 @@ func createChangeSet(transportCtx context.Context, eventCtx eventcontext.Context return "", fmt.Errorf("failed to parse stack template: %v", err) } - attachServerSystem(stackBody, eventCtx, projectDoc) + attachServerSystem(stackBody, eventCtx, projectDoc, serverAsset.SourceBucket, serverAsset.SourceKey) stackBodyRaw, err := stackBody.JSON() if err != nil { @@ -123,7 +122,7 @@ func executeChangeSet(transportCtx context.Context, eventCtx eventcontext.Contex waiter := cloudformation.NewStackUpdateCompleteWaiter(eventCtx.CloudformationClient) err = waiter.Wait(transportCtx, &cloudformation.DescribeStacksInput{ StackName: aws.String(projectDoc.DedicatedInfrastructure.StackName), - }, eventCtx.DeploymentTimeout) + }, eventCtx.DeploymentConfiguration.Timeout) if err != nil { return fmt.Errorf("failed to wait for update completion: %v", err) } @@ -132,7 +131,10 @@ func executeChangeSet(transportCtx context.Context, eventCtx eventcontext.Contex } // attachServerSystem adds the project server system to the stack. -func attachServerSystem(stackTemplate *goformation.Template, eventCtx eventcontext.Context, projectDoc *project.Project, apiGatewayId string, staticBucketUri string) { +func attachServerSystem(stackTemplate *goformation.Template, eventCtx eventcontext.Context, projectDoc *project.Project, serverBucketName, serverBucketKey string) { + // ServerLogGroup is deployed at initialization (combined with all other log groups) + const SERVER_LOG_GROUP string = "ServerLogGroup" + const SERVER_FUNCTION_ROLE = "ServerFunctionRole" stackTemplate.Resources[SERVER_FUNCTION_ROLE] = &iam.Role{ Tags: []tags.Tag{ @@ -154,39 +156,22 @@ func attachServerSystem(stackTemplate *goformation.Template, eventCtx eventconte } const SERVER_FUNCTION string = "ServerFunction" - stackTemplate.Resources[SERVER_FUNCTION] = &lambda.Function{} - - const API_INTEGRATION_STATIC string = "ApiIntegrationStatic" - stackTemplate.Resources[API_INTEGRATION_STATIC] = &apigatewayv2.Integration{ - ApiId: apiGatewayId, - IntegrationType: "HTTP_PROXY", - IntegrationUri: aws.String(staticBucketUri), - IntegrationMethod: aws.String("GET"), - } - - const API_ROUTE_STATIC string = "ApiRouteStatic" - stackTemplate.Resources[API_ROUTE_STATIC] = &apigatewayv2.Route{ - ApiId: apiGatewayId, - RouteKey: fmt.Sprintf("GET /%s/{page}.html", projectDoc.Name), - Target: aws.String(fmt.Sprintf("integrations/%s", goformation.Ref(API_INTEGRATION_STATIC))), - } - - const API_INTEGRATION_SERVER string = "ApiIntegrationServer" - stackTemplate.Resources[API_INTEGRATION_SERVER] = &apigatewayv2.Integration{ - ApiId: apiGatewayId, - IntegrationType: "AWS_PROXY", - IntegrationMethod: aws.String("ANY"), - IntegrationUri: aws.String(goformation.Sub(fmt.Sprintf( - "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${%s.Arn}/invocations", SERVER_FUNCTION), - )), - PayloadFormatVersion: aws.String("2.0"), - } - - const API_ROUTE_SERVER string = "ApiRouteServer" - stackTemplate.Resources[API_ROUTE_SERVER] = &apigatewayv2.Route{ - ApiId: apiGatewayId, - RouteKey: fmt.Sprintf("ANY /%s/{proxy+}", projectDoc.Name), - Target: aws.String(fmt.Sprintf("integrations/%s", goformation.Ref(API_INTEGRATION_SERVER))), + stackTemplate.Resources[SERVER_FUNCTION] = &lambda.Function{ + FunctionName: aws.String(fmt.Sprintf("%s%s", eventCtx.ProjectConfiguration.ServerNamePrefix, projectDoc.Name)), + Description: aws.String(fmt.Sprintf("Server backend for battleshiper project %s", projectDoc.Name)), + Architectures: []string{"x86_64"}, + Runtime: aws.String(eventCtx.ProjectConfiguration.ServerRuntime), + MemorySize: aws.Int(eventCtx.ProjectConfiguration.ServerMemory), + Timeout: aws.Int(eventCtx.ProjectConfiguration.ServerTimeout), + Role: goformation.GetAtt(SERVER_FUNCTION_ROLE, "Arn"), + Code: &lambda.Function_Code{ + S3Bucket: aws.String(serverBucketName), + S3Key: aws.String(serverBucketKey), + }, + Handler: aws.String("index.handler"), + LoggingConfig: &lambda.Function_LoggingConfig{ + LogGroup: aws.String(SERVER_LOG_GROUP), + LogFormat: aws.String("Text"), + }, } - } diff --git a/pipeline/deploy/deployproject/deployproject.go b/pipeline/deploy/deployproject/deployproject.go index e0bf2d9..b5206f8 100644 --- a/pipeline/deploy/deployproject/deployproject.go +++ b/pipeline/deploy/deployproject/deployproject.go @@ -177,7 +177,7 @@ func deployProject(transportCtx context.Context, eventCtx eventcontext.Context, } cloudLogger.WriteLog("creating stack changeset...") - changeSetName, err := createChangeSet(transportCtx, eventCtx, projectDoc, execId) + changeSetName, err := createChangeSet(transportCtx, eventCtx, projectDoc, execId, buildInformation.ServerObject) if err != nil { cloudLogger.WriteLog(err.Error()) if err := cloudLogger.PushLogs(); err != nil { diff --git a/pipeline/deploy/deployproject/shared.go b/pipeline/deploy/deployproject/shared.go index ab76bd6..0315f6b 100644 --- a/pipeline/deploy/deployproject/shared.go +++ b/pipeline/deploy/deployproject/shared.go @@ -71,7 +71,7 @@ func copyStaticAssets(transportCtx context.Context, eventCtx eventcontext.Contex for _, obj := range assets { _, err := eventCtx.S3Client.CopyObject(transportCtx, &s3.CopyObjectInput{ Bucket: aws.String(bucketName), - CopySource: aws.String(obj.SourcePath), + CopySource: aws.String(fmt.Sprintf("%s/%s", obj.SourceBucket, obj.SourceKey)), Key: aws.String(fmt.Sprintf("%s%s", bucketPrefix, obj.RelativeKey)), }) if err != nil { @@ -93,7 +93,7 @@ func copyStaticPages(transportCtx context.Context, eventCtx eventcontext.Context for _, obj := range pages { _, err := eventCtx.S3Client.CopyObject(transportCtx, &s3.CopyObjectInput{ Bucket: aws.String(bucketName), - CopySource: aws.String(obj.SourcePath), + CopySource: aws.String(fmt.Sprintf("%s/%s", obj.SourceBucket, obj.SourceKey)), Key: aws.String(fmt.Sprintf("%s%s", bucketPrefix, obj.RelativeKey)), }) if err != nil { @@ -123,13 +123,13 @@ func updateStaticPageKeys(transportCtx context.Context, eventCtx eventcontext.Co } storeMetadata, err := eventCtx.CloudfrontCacheClient.DescribeKeyValueStore(transportCtx, &cloudfrontkeyvaluestore.DescribeKeyValueStoreInput{ - KvsARN: aws.String(eventCtx.CloudfrontCacheArn), + KvsARN: aws.String(eventCtx.ProjectConfiguration.CloudfrontCacheArn), }) if err != nil { return fmt.Errorf("failed to describe cdn store: %v", err) } _, err = eventCtx.CloudfrontCacheClient.UpdateKeys(transportCtx, &cloudfrontkeyvaluestore.UpdateKeysInput{ - KvsARN: aws.String(eventCtx.CloudfrontCacheArn), + KvsARN: aws.String(eventCtx.ProjectConfiguration.CloudfrontCacheArn), Puts: addStaticPageKeys, Deletes: deleteStaticPageKeys, IfMatch: storeMetadata.ETag, diff --git a/pipeline/deploy/eventcontext/eventcontext.go b/pipeline/deploy/eventcontext/eventcontext.go index 549e55d..875f4c8 100644 --- a/pipeline/deploy/eventcontext/eventcontext.go +++ b/pipeline/deploy/eventcontext/eventcontext.go @@ -11,14 +11,26 @@ import ( "go.mongodb.org/mongo-driver/mongo" ) +type DeploymentConfiguration struct { + Timeout time.Duration +} + +type ProjectConfiguration struct { + ServerNamePrefix string + ServerRuntime string + ServerMemory int + ServerTimeout int + CloudfrontCacheArn string +} + // Context provides data to event handlers. type Context struct { - Database *mongo.Database - TicketOptions *pipeline.TicketOptions - CloudformationClient *cloudformation.Client - DeploymentTimeout time.Duration - S3Client *s3.Client - CloudwatchClient *cloudwatchlogs.Client - CloudfrontCacheClient *cloudfrontkeyvaluestore.Client - CloudfrontCacheArn string + Database *mongo.Database + TicketOptions *pipeline.TicketOptions + CloudformationClient *cloudformation.Client + S3Client *s3.Client + CloudwatchClient *cloudwatchlogs.Client + CloudfrontCacheClient *cloudfrontkeyvaluestore.Client + DeploymentConfiguration *DeploymentConfiguration + ProjectConfiguration *ProjectConfiguration } diff --git a/pipeline/deploy/main.go b/pipeline/deploy/main.go index 004969d..45835b9 100644 --- a/pipeline/deploy/main.go +++ b/pipeline/deploy/main.go @@ -5,6 +5,7 @@ import ( "fmt" "log" "os" + "strconv" "time" "github.com/aws/aws-lambda-go/lambda" @@ -31,6 +32,10 @@ var ( TICKET_CREDENTIAL_ARN = os.Getenv("TICKET_CREDENTIAL_ARN") DEPLOYMENT_TIMEOUT = os.Getenv("DEPLOYMENT_TIMEOUT") CLOUDFRONT_CACHE_ARN = os.Getenv("CLOUDFRONT_CACHE_ARN") + SERVER_NAME_PREFIX = os.Getenv("SERVER_NAME_PREFIX") + SERVER_RUNTIME = os.Getenv("SERVER_RUNTIME") + SERVER_MEMORY = os.Getenv("SERVER_MEMORY") + SERVER_TIMEOUT = os.Getenv("SERVER_TIMEOUT") ) func main() { @@ -94,15 +99,33 @@ func run() error { return fmt.Errorf("failed to parse DEPLOYMENT_TIMEOUT environment variable") } + serverMemory, err := strconv.Atoi(SERVER_MEMORY) + if err != nil { + return fmt.Errorf("failed to parse SERVER_MEMORY environment variable") + } + + serverTimeout, err := strconv.Atoi(SERVER_TIMEOUT) + if err != nil { + return fmt.Errorf("failed to parse SERVER_TIMEOUT environment variable") + } + lambda.Start(deployproject.HandleDeployProject(eventcontext.Context{ Database: databaseHandle, TicketOptions: ticketOptions, CloudformationClient: cloudformationClient, - DeploymentTimeout: deploymentTimeout, S3Client: s3Client, CloudwatchClient: cloudwatchClient, CloudfrontCacheClient: cloudfrontClient, - CloudfrontCacheArn: CLOUDFRONT_CACHE_ARN, + DeploymentConfiguration: &eventcontext.DeploymentConfiguration{ + Timeout: deploymentTimeout, + }, + ProjectConfiguration: &eventcontext.ProjectConfiguration{ + ServerNamePrefix: SERVER_NAME_PREFIX, + ServerRuntime: SERVER_RUNTIME, + ServerMemory: serverMemory, + ServerTimeout: serverTimeout, + CloudfrontCacheArn: CLOUDFRONT_CACHE_ARN, + }, })) return nil diff --git a/pipeline/init/eventcontext/eventcontext.go b/pipeline/init/eventcontext/eventcontext.go index 860bdcd..c577fb2 100644 --- a/pipeline/init/eventcontext/eventcontext.go +++ b/pipeline/init/eventcontext/eventcontext.go @@ -8,12 +8,17 @@ import ( "go.mongodb.org/mongo-driver/mongo" ) +type DeploymentConfiguration struct { + ServiceRoleArn string + Timeout time.Duration +} + type BucketConfiguration struct { StaticBucketName string BuildAssetBucketName string } -type BuildConfiguration struct { +type ProjectConfiguration struct { EventLogPrefix string BuildLogPrefix string DeployLogPrefix string @@ -31,11 +36,10 @@ type BuildConfiguration struct { // Context provides data to event handlers. type Context struct { - Database *mongo.Database - TicketOptions *pipeline.TicketOptions - CloudformationClient *cloudformation.Client - DeploymentServiceRoleArn string - DeploymentTimeout time.Duration - BucketConfiguration *BucketConfiguration - BuildConfiguration *BuildConfiguration + Database *mongo.Database + TicketOptions *pipeline.TicketOptions + CloudformationClient *cloudformation.Client + DeploymentConfiguration *DeploymentConfiguration + BucketConfiguration *BucketConfiguration + ProjectConfiguration *ProjectConfiguration } diff --git a/pipeline/init/initproject/dedicated.go b/pipeline/init/initproject/dedicated.go index 98393c8..5d22457 100644 --- a/pipeline/init/initproject/dedicated.go +++ b/pipeline/init/initproject/dedicated.go @@ -43,7 +43,7 @@ func createStack(transportCtx context.Context, eventCtx eventcontext.Context, pr _, err = eventCtx.CloudformationClient.CreateStack(transportCtx, &cloudformation.CreateStackInput{ StackName: aws.String(projectDoc.DedicatedInfrastructure.StackName), - RoleARN: aws.String(eventCtx.DeploymentServiceRoleArn), + RoleARN: aws.String(eventCtx.DeploymentConfiguration.ServiceRoleArn), Capabilities: []types.Capability{types.CapabilityCapabilityIam}, TemplateBody: aws.String(string(stackBodyRaw)), }) @@ -75,7 +75,7 @@ func createStack(transportCtx context.Context, eventCtx eventcontext.Context, pr waiter := cloudformation.NewStackCreateCompleteWaiter(eventCtx.CloudformationClient) err = waiter.Wait(transportCtx, &cloudformation.DescribeStacksInput{ StackName: aws.String(projectDoc.DedicatedInfrastructure.StackName), - }, eventCtx.DeploymentTimeout) + }, eventCtx.DeploymentConfiguration.Timeout) if err != nil { return fmt.Errorf("failed to apply cloudformation stack: %v", err) } @@ -103,10 +103,10 @@ func validateInfrastructureConfiguration(projectDoc *project.Project) error { func generateDedicatedInfrastructure(eventCtx eventcontext.Context, projectName string) project.DedicatedInfrastructure { infrastructure := project.DedicatedInfrastructure{} - infrastructure.EventLogGroup = fmt.Sprintf("%s/%s", eventCtx.BuildConfiguration.EventLogPrefix, projectName) - infrastructure.BuildLogGroup = fmt.Sprintf("%s/%s", eventCtx.BuildConfiguration.BuildLogPrefix, projectName) - infrastructure.EventLogGroup = fmt.Sprintf("%s/%s", eventCtx.BuildConfiguration.DeployLogPrefix, projectName) - infrastructure.ServerLogGroup = fmt.Sprintf("%s/%s", eventCtx.BuildConfiguration.ServerLogPrefix, projectName) + infrastructure.EventLogGroup = fmt.Sprintf("%s/%s", eventCtx.ProjectConfiguration.EventLogPrefix, projectName) + infrastructure.BuildLogGroup = fmt.Sprintf("%s/%s", eventCtx.ProjectConfiguration.BuildLogPrefix, projectName) + infrastructure.EventLogGroup = fmt.Sprintf("%s/%s", eventCtx.ProjectConfiguration.DeployLogPrefix, projectName) + infrastructure.ServerLogGroup = fmt.Sprintf("%s/%s", eventCtx.ProjectConfiguration.ServerLogPrefix, projectName) infrastructure.StackName = fmt.Sprintf("battleshiper-project-stack-%s", projectName) @@ -118,19 +118,19 @@ func attachLogSystem(stackTemplate *goformation.Template, eventCtx eventcontext. const EVENT_LOG_GROUP string = "EventLogGroup" stackTemplate.Resources[EVENT_LOG_GROUP] = &logs.LogGroup{ LogGroupName: aws.String(projectDoc.DedicatedInfrastructure.EventLogGroup), - RetentionInDays: aws.Int(eventCtx.BuildConfiguration.LogRetentionDays), + RetentionInDays: aws.Int(eventCtx.ProjectConfiguration.LogRetentionDays), } const DEPLOY_LOG_GROUP string = "DeployLogGroup" stackTemplate.Resources[DEPLOY_LOG_GROUP] = &logs.LogGroup{ LogGroupName: aws.String(projectDoc.DedicatedInfrastructure.DeployLogGroup), - RetentionInDays: aws.Int(eventCtx.BuildConfiguration.LogRetentionDays), + RetentionInDays: aws.Int(eventCtx.ProjectConfiguration.LogRetentionDays), } const SERVER_LOG_GROUP string = "ServerLogGroup" stackTemplate.Resources[SERVER_LOG_GROUP] = &logs.LogGroup{ LogGroupName: aws.String(projectDoc.DedicatedInfrastructure.ServerLogGroup), - RetentionInDays: aws.Int(eventCtx.BuildConfiguration.LogRetentionDays), + RetentionInDays: aws.Int(eventCtx.ProjectConfiguration.LogRetentionDays), } } @@ -153,7 +153,7 @@ func attachBuildSystem(stackTemplate *goformation.Template, eventCtx eventcontex const BUILD_LOG_GROUP string = "BuildLogGroup" stackTemplate.Resources[BUILD_LOG_GROUP] = &logs.LogGroup{ LogGroupName: aws.String(projectDoc.DedicatedInfrastructure.BuildLogGroup), - RetentionInDays: aws.Int(eventCtx.BuildConfiguration.LogRetentionDays), + RetentionInDays: aws.Int(eventCtx.ProjectConfiguration.LogRetentionDays), } const BUILD_JOB_EXEC_ROLE string = "BuildJobExecRole" @@ -233,8 +233,8 @@ func attachBuildSystem(stackTemplate *goformation.Template, eventCtx eventcontex Type: "container", ContainerProperties: &batch.JobDefinition_ContainerProperties{ Image: projectDoc.BuildImage, - Vcpus: aws.Int(eventCtx.BuildConfiguration.BuildJobVCPUS), - Memory: aws.Int(eventCtx.BuildConfiguration.BuildJobMemory), + Vcpus: aws.Int(eventCtx.ProjectConfiguration.BuildJobVCPUS), + Memory: aws.Int(eventCtx.ProjectConfiguration.BuildJobMemory), JobRoleArn: aws.String(goformation.Ref(BUILD_JOB_ROLE)), ExecutionRoleArn: aws.String(goformation.Ref(BUILD_JOB_EXEC_ROLE)), LogConfiguration: &batch.JobDefinition_LogConfiguration{ @@ -261,7 +261,7 @@ func attachBuildSystem(stackTemplate *goformation.Template, eventCtx eventcontex }, }, Timeout: &batch.JobDefinition_Timeout{ - AttemptDurationSeconds: aws.Int(int(eventCtx.BuildConfiguration.BuildJobTimeout.Seconds())), + AttemptDurationSeconds: aws.Int(int(eventCtx.ProjectConfiguration.BuildJobTimeout.Seconds())), }, } @@ -284,7 +284,7 @@ func attachBuildSystem(stackTemplate *goformation.Template, eventCtx eventcontex }, }, ManagedPolicyArns: []string{ - eventCtx.BuildConfiguration.BuildJobQueuePolicyArn, + eventCtx.ProjectConfiguration.BuildJobQueuePolicyArn, }, } @@ -334,21 +334,21 @@ func attachBuildSystem(stackTemplate *goformation.Template, eventCtx eventcontex const BUILD_RULE string = "BuildRule" stackTemplate.Resources[BUILD_RULE] = &events.Rule{ - EventBusName: aws.String(eventCtx.BuildConfiguration.BuildEventbusName), + EventBusName: aws.String(eventCtx.ProjectConfiguration.BuildEventbusName), Name: aws.String(fmt.Sprintf("battleshiper-project-build-rule-%s", projectDoc.Name)), Description: aws.String("triggers the associated build targets"), State: aws.String("ENABLED"), EventPattern: map[string]interface{}{ "source": []string{ - eventCtx.BuildConfiguration.BuildEventSource, + eventCtx.ProjectConfiguration.BuildEventSource, }, "detail-type": []string{ - fmt.Sprintf("%s.%s", eventCtx.BuildConfiguration.BuildEventAction, projectDoc.Name), + fmt.Sprintf("%s.%s", eventCtx.ProjectConfiguration.BuildEventAction, projectDoc.Name), }, }, Targets: []events.Rule_Target{ { - Arn: eventCtx.BuildConfiguration.BuildJobQueueArn, + Arn: eventCtx.ProjectConfiguration.BuildJobQueueArn, Id: "battleshiper-project-build-queue", RoleArn: aws.String(goformation.GetAtt(BUILD_RULE_ROLE, "Arn")), RetryPolicy: &events.Rule_RetryPolicy{ diff --git a/pipeline/init/main.go b/pipeline/init/main.go index e1cdfae..00451a9 100644 --- a/pipeline/init/main.go +++ b/pipeline/init/main.go @@ -112,16 +112,18 @@ func run() error { } lambda.Start(initproject.HandleInitProject(eventcontext.Context{ - Database: databaseHandle, - TicketOptions: ticketOptions, - CloudformationClient: cloudformationClient, - DeploymentServiceRoleArn: DEPLOYMENT_SERVICE_ROLE_ARN, - DeploymentTimeout: deploymentTimeout, + Database: databaseHandle, + TicketOptions: ticketOptions, + CloudformationClient: cloudformationClient, + DeploymentConfiguration: &eventcontext.DeploymentConfiguration{ + ServiceRoleArn: DEPLOYMENT_SERVICE_ROLE_ARN, + Timeout: deploymentTimeout, + }, BucketConfiguration: &eventcontext.BucketConfiguration{ StaticBucketName: STATIC_BUCKET_NAME, BuildAssetBucketName: BUILD_ASSET_BUCKET_NAME, }, - BuildConfiguration: &eventcontext.BuildConfiguration{ + ProjectConfiguration: &eventcontext.ProjectConfiguration{ EventLogPrefix: EVENT_LOG_GROUP_PREFIX, BuildLogPrefix: BUILD_LOG_GROUP_PREFIX, DeployLogPrefix: DEPLOY_LOG_GROUP_PREFIX, diff --git a/router/main.go b/router/main.go index a902dcf..7c1fbfa 100644 --- a/router/main.go +++ b/router/main.go @@ -15,9 +15,9 @@ import ( ) var ( - REGION = os.Getenv("AWS_REGION") - STATIC_BUCKET_NAME = os.Getenv("STATIC_BUCKET_NAME") - SERVER_FUNCTION_PREFIX = os.Getenv("SERVER_FUNCTION_PREFIX") + REGION = os.Getenv("AWS_REGION") + STATIC_BUCKET_NAME = os.Getenv("STATIC_BUCKET_NAME") + SERVER_NAME_PREFIX = os.Getenv("SERVER_NAME_PREFIX") ) func main() { @@ -38,10 +38,10 @@ func run() error { functionClient := function.NewFromConfig(awsConfig) lambda.Start(routerequest.HandleRouteRequest(routecontext.Context{ - S3Client: s3Client, - S3Bucket: STATIC_BUCKET_NAME, - FunctionClient: functionClient, - FunctionPrefix: SERVER_FUNCTION_PREFIX, + S3Client: s3Client, + StaticBucketName: STATIC_BUCKET_NAME, + FunctionClient: functionClient, + ServerNamePrefix: SERVER_NAME_PREFIX, })) return nil diff --git a/router/routecontext/routecontext.go b/router/routecontext/routecontext.go index 0c147e7..e7b441b 100644 --- a/router/routecontext/routecontext.go +++ b/router/routecontext/routecontext.go @@ -7,8 +7,8 @@ import ( // Context provides data to route handlers. type Context struct { - S3Bucket string - S3Client *s3.Client - FunctionPrefix string - FunctionClient *lambda.Client + S3Client *s3.Client + StaticBucketName string + FunctionClient *lambda.Client + ServerNamePrefix string } diff --git a/router/routerequest/routerequest.go b/router/routerequest/routerequest.go index 9dfdf2f..c45c36f 100644 --- a/router/routerequest/routerequest.go +++ b/router/routerequest/routerequest.go @@ -57,7 +57,7 @@ func runHandleRouteRequest(request events.APIGatewayV2HTTPRequest, transportCtx // proxyStatic reads the requested path from the static s3 bucket and returns it as Content-Type text/html. func proxyStatic(request events.APIGatewayV2HTTPRequest, transportCtx context.Context, routeCtx routecontext.Context) (*events.APIGatewayV2HTTPResponse, int, error) { objectOutput, err := routeCtx.S3Client.GetObject(transportCtx, &s3.GetObjectInput{ - Bucket: aws.String(routeCtx.S3Bucket), + Bucket: aws.String(routeCtx.StaticBucketName), Key: aws.String(request.RawPath), }) if err != nil { @@ -89,7 +89,7 @@ func proxyServer(request events.APIGatewayV2HTTPRequest, transportCtx context.Co } result, err := routeCtx.FunctionClient.Invoke(transportCtx, &lambda.InvokeInput{ - FunctionName: aws.String(fmt.Sprintf("%s%s", routeCtx.FunctionPrefix, projectName)), + FunctionName: aws.String(fmt.Sprintf("%s%s", routeCtx.ServerNamePrefix, projectName)), Payload: requestRaw, InvocationType: lambdatypes.InvocationTypeRequestResponse, }) diff --git a/template.yaml b/template.yaml index 0084bf7..e9de936 100644 --- a/template.yaml +++ b/template.yaml @@ -78,7 +78,7 @@ Resources: Variables: AWS_REGION: !Ref AWS::Region STATIC_BUCKET_NAME: !Ref BattleshiperStaticBucket - SERVER_FUNCTION_PREFIX: "battleshiper-project-server-" + SERVER_NAME_PREFIX: "battleshiper-project-server-" LoggingConfig: LogGroup: !Ref BattleshiperRouterLogGroup @@ -721,6 +721,7 @@ Resources: LoggingConfig: LogGroup: !Ref BattleshiperApiLogGroup + # ============================================ # =========== S3 Storage ===================== # ============================================ @@ -823,16 +824,12 @@ Resources: DomainName: !GetAtt BattleshiperStaticBucket.DomainName OriginAccessControlId: !GetAtt BattleshiperCDNOriginAccessControl.Id S3OriginConfig: {} - - Id: "battleshiper-server" - DomainName: !GetAtt BattleshiperRouterApi.ApiEndpoint - CustomOriginConfig: - OriginProtocolPolicy: "https-only" - Id: "battleshiper-api" DomainName: !GetAtt BattleshiperApi.ApiEndpoint CustomOriginConfig: OriginProtocolPolicy: "https-only" DefaultCacheBehavior: - TargetOriginId: "battleshiper-server" + TargetOriginId: "battleshiper-api" AllowedMethods: - GET - HEAD @@ -845,19 +842,6 @@ Resources: CachePolicyId: !Ref BattleshiperCDNServerCachePolicy OriginRequestPolicyId: !Ref BattleshiperCDNServerOriginRequestPolicy CacheBehaviors: - - PathPattern: "/api/*" - TargetOriginId: "battleshiper-api" - AllowedMethods: - - GET - - HEAD - - OPTIONS - - PUT - - PATCH - - POST - - DELETE - ViewerProtocolPolicy: redirect-to-https - CachePolicyId: !Ref BattleshiperCDNServerCachePolicy - OriginRequestPolicyId: !Ref BattleshiperCDNServerOriginRequestPolicy - PathPattern: "/_app/*" TargetOriginId: "battleshiper-static-bucket" AllowedMethods: @@ -1371,7 +1355,10 @@ Resources: TICKET_CREDENTIAL_ARN: !Ref BattleshiperPipelineTicketCredentials DEPLOYMENT_TIMEOUT: "400s" CLOUDFRONT_CACHE_ARN: !GetAtt BattleshiperProjectCDNRouteStore.Arn - SERVER_FUNCTION_PREFIX: "battleshiper-project-server" + SERVER_NAME_PREFIX: "battleshiper-project-server-" + SERVER_RUNTIME: "nodejs20.x" # https://docs.aws.amazon.com/lambda/latest/dg/lambda-runtimes.html#runtimes-supported + SERVER_MEMORY: 128 + SERVER_TIMEOUT: 3 # ideally this should be lower then the timeout of the core router function LoggingConfig: LogGroup: !Ref BattleshiperApiLogGroup @@ -1413,6 +1400,7 @@ Resources: Runtime: provided.al2023 Architectures: - x86_64 + Timeout: 180 VpcConfig: SubnetIds: - !Ref BattleshiperPipelineSubnet1