From 21fb7df25380813fa606c26d6531e236213f365e Mon Sep 17 00:00:00 2001 From: m4rc3l05 <15786310+M4RC3L05@users.noreply.github.com> Date: Tue, 1 Oct 2024 21:50:01 +0100 Subject: [PATCH] Improve build Signed-off-by: m4rc3l05 <15786310+M4RC3L05@users.noreply.github.com> --- .github/workflows/release.yaml | 2 +- .gitignore | 9 +--- deno.json | 12 ++---- scripts/build.ts | 54 ++++++++++++++++++++++++ scripts/{public-to-json.ts => bundle.ts} | 32 +++++++------- scripts/embed.ts | 17 ++++++++ scripts/generate-builds.ts | 34 --------------- src/main.ts | 2 +- 8 files changed, 95 insertions(+), 67 deletions(-) create mode 100755 scripts/build.ts rename scripts/{public-to-json.ts => bundle.ts} (75%) create mode 100755 scripts/embed.ts delete mode 100755 scripts/generate-builds.ts diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index cb1d6a5..9bfc776 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -25,7 +25,7 @@ jobs: run: deno task deps - name: build - run: ./scripts/generate-builds.ts + run: ./scripts/bundle.ts && ./scripts/embed.ts && ./scripts/build.ts - name: release uses: ncipollo/release-action@v1 diff --git a/.gitignore b/.gitignore index 77a587d..bcd40be 100644 --- a/.gitignore +++ b/.gitignore @@ -1,12 +1,5 @@ .bin/* !.bin/git-hooks -!.bin/.gitkeep -!.bin/public-to-json.ts -share -lib -include data -src/public.json -*.dll -.cache .env +embed.json diff --git a/deno.json b/deno.json index cc94f95..82c8fb9 100644 --- a/deno.json +++ b/deno.json @@ -3,13 +3,8 @@ "version": "4.5.3", "exports": "./src/main.ts", "tasks": { - "run": "./scripts/public-to-json.ts && deno run --allow-env=ENV --allow-net=127.0.0.1 --cached-only src/main.ts", - "compile": "./scripts/public-to-json.ts && deno compile --allow-env=ENV --allow-net=127.0.0.1 --unstable-ffi --include ./src/public.json --cached-only --env=.env -o ./.bin/denotag ./src/main.ts", - "compile:x86_64-pc-windows-msvc": "./scripts/public-to-json.ts && deno compile --allow-env=ENV --allow-net=127.0.0.1 --unstable-ffi --include ./src/public.json --cached-only --env=.env -o ./.bin/denotag.exe --target=x86_64-pc-windows-msvc ./src/main.ts", - "compile:x86_64-apple-darwin": "./scripts/public-to-json.ts && deno compile --allow-env=ENV --allow-net=127.0.0.1 --unstable-ffi --include ./src/public.json --cached-only --env=.env -o ./.bin/denotag --target=x86_64-apple-darwin ./src/main.ts", - "compile:aarch64-apple-darwin": "./scripts/public-to-json.ts && deno compile --allow-env=ENV --allow-net=127.0.0.1 --unstable-ffi --include ./src/public.json --cached-only --env=.env -o ./.bin/denotag --target=aarch64-apple-darwin ./src/main.ts", - "compile:x86_64-unknown-linux-gnu": "./scripts/public-to-json.ts && deno compile --allow-env=ENV --allow-net=127.0.0.1 --unstable-ffi --include ./src/public.json --cached-only --env=.env -o ./.bin/denotag --target=x86_64-unknown-linux-gnu ./src/main.ts", - "compile:aarch64-unknown-linux-gnu": "./scripts/public-to-json.ts && deno compile --allow-env=ENV --allow-net=127.0.0.1 --unstable-ffi --include ./src/public.json --cached-only --env=.env -o ./.bin/denotag --target=aarch64-unknown-linux-gnu ./src/main.ts", + "run": "./scripts/bundle.ts && ./scripts/embed.ts && deno run --allow-env=ENV --allow-net=127.0.0.1 --cached-only src/main.ts", + "compile": "./scripts/bundle.ts && ./scripts/embed.ts && deno compile --allow-env=ENV --allow-net=127.0.0.1 --cached-only --env=.env -o ./.bin/denotag ./src/main.ts", "deps:lock": "deno cache --frozen=false src/**/*.ts src/**/*.tsx", "deps": "deno cache --reload src/**/*.ts src/**/*.tsx" }, @@ -18,12 +13,13 @@ "jsx": "react-jsx" }, "lint": { + "exclude": ["embed.json"], "rules": { "include": ["verbatim-module-syntax"] } }, "fmt": { - "exclude": ["./src/public.json"] + "exclude": ["embed.json"] }, "imports": { "@mjackson/multipart-parser": "jsr:@mjackson/multipart-parser@0.6.2", diff --git a/scripts/build.ts b/scripts/build.ts new file mode 100755 index 0000000..f73772e --- /dev/null +++ b/scripts/build.ts @@ -0,0 +1,54 @@ +#!/usr/bin/env -S deno run -A --no-lock + +import $ from "jsr:@david/dax@0.42.0"; +import { basename, resolve } from "@std/path"; + +const rootDir = resolve(import.meta.dirname!, "../"); +const binDir = resolve(rootDir, ".bin"); +const binName = "denotag" as const; + +const targets = [ + "x86_64-pc-windows-msvc", + "x86_64-apple-darwin", + "aarch64-apple-darwin", + "x86_64-unknown-linux-gnu", + "aarch64-unknown-linux-gnu", +] as const; + +for (const file of Deno.readDirSync("./.bin")) { + if ( + file.name.match(/.*\.(zip|tar\.gz)(\.sha256)?$/) || + targets.some((target) => file.name.includes(target)) + ) { + Deno.removeSync(resolve(binDir, file.name), { recursive: true }); + } +} + +const buildFor = async (target: typeof targets[number]) => { + const finalBinDir = resolve(binDir, `${binName}-${target}`); + const finalBinName = target.includes("windows") ? `${binName}.exe` : binName; + const finalCompressName = target.includes("windows") + ? `${basename(finalBinDir)}.zip` + : `${basename(finalBinDir)}.tar.gz`; + const finalCompressPath = resolve(binDir, finalCompressName); + const checksumName = `${finalCompressName}.sha256`; + const checksumPath = resolve(binDir, checksumName); + const finalBinPath = resolve(finalBinDir, finalBinName); + const compressCmd = target.includes("windows") + ? `zip -j ${finalCompressPath} ${finalBinPath}` + : `tar -czvf ${finalCompressPath} -C ${finalBinDir} ${finalBinName}`; + const scriptPath = resolve(rootDir, "src", "main.ts"); + + await $`deno compile --allow-env=ENV --allow-net=127.0.0.1 --cached-only --env=${ + $.path(resolve(rootDir, ".env")) + } --target=${target} --output ${$.path(finalBinPath)} ${$.path(scriptPath)}`; + await $.raw`${compressCmd}`; + await $`cd ${$.path(binDir)} && sha256sum ${finalCompressName} > ${ + $.path(checksumPath) + }`; + await Deno.remove(finalBinDir, { recursive: true }); +}; + +await $`echo "ENV=production" > ${$.path(resolve(rootDir, ".env"))}`; + +await Promise.all(targets.map(buildFor)); diff --git a/scripts/public-to-json.ts b/scripts/bundle.ts similarity index 75% rename from scripts/public-to-json.ts rename to scripts/bundle.ts index 4ebda5b..d88abfc 100755 --- a/scripts/public-to-json.ts +++ b/scripts/bundle.ts @@ -4,9 +4,9 @@ import { build, type Plugin, stop } from "npm:esbuild@0.23.1"; import { denoPlugins } from "jsr:@luca/esbuild-deno-loader@0.10.3"; import { resolve } from "@std/path"; -let htmlFile = Deno.readTextFileSync( - new URL("../src/public/index.html", import.meta.url), -); +const rootDir = resolve(import.meta.dirname!, "../"); +const dataDir = resolve(rootDir, "data"); +const bundleFilePath = resolve(dataDir, "index.html"); const [jsCode, cssCode] = await Promise.all([ build({ @@ -17,11 +17,11 @@ const [jsCode, cssCode] = await Promise.all([ }, }, entryPoints: [ - resolve(import.meta.dirname!, "../src/public/src/main.tsx"), + resolve(rootDir, "src/public/src/main.tsx"), ], plugins: denoPlugins({ - configPath: resolve(import.meta.dirname!, "../deno.json"), - lockPath: resolve(import.meta.dirname!, "../deno.lock"), + configPath: resolve(rootDir, "deno.json"), + lockPath: resolve(rootDir, "deno.lock"), }), define: { NODE_ENV: "production", @@ -39,7 +39,7 @@ const [jsCode, cssCode] = await Promise.all([ build({ bundle: true, entryPoints: [ - resolve(import.meta.dirname!, "../src/public/css/main.css"), + resolve(rootDir, "src/public/css/main.css"), ], plugins: [ { @@ -69,6 +69,8 @@ const [jsCode, cssCode] = await Promise.all([ }), ]); +let htmlFile = Deno.readTextFileSync(resolve(rootDir, "src/public/index.html")); + htmlFile = htmlFile.replace( "{{ CssItems }}", cssCode.outputFiles.filter(({ path }) => path.endsWith(".css")).map(( @@ -86,16 +88,16 @@ htmlFile = htmlFile.replace( ); try { - Deno.statSync("./src/public.json"); - Deno.removeSync("./src/public.json"); + Deno.mkdirSync(dataDir); // deno-lint-ignore no-empty } catch {} -Deno.writeTextFileSync( - "./src/public.json", - JSON.stringify({ - "index.html": Array.from(new TextEncoder().encode(htmlFile)), - }), -); +try { + Deno.statSync(bundleFilePath); + Deno.removeSync(bundleFilePath); + // deno-lint-ignore no-empty +} catch {} + +Deno.writeTextFileSync(bundleFilePath, htmlFile); await stop(); diff --git a/scripts/embed.ts b/scripts/embed.ts new file mode 100755 index 0000000..a876d0f --- /dev/null +++ b/scripts/embed.ts @@ -0,0 +1,17 @@ +#!/usr/bin/env -S deno run -A --no-lock + +import { resolve } from "jsr:@std/path@1.0.6"; + +const rootDir = resolve(import.meta.dirname!, "../"); +const dataDir = resolve(rootDir, "data"); +const embedFilePath = resolve(rootDir, "embed.json"); + +const embed: Record = {}; + +for (const file of Deno.readDirSync(dataDir)) { + if (file.name !== "index.html") continue; + + embed[file.name] = Array.from(Deno.readFileSync(resolve(dataDir, file.name))); +} + +Deno.writeTextFileSync(embedFilePath, JSON.stringify(embed)); diff --git a/scripts/generate-builds.ts b/scripts/generate-builds.ts deleted file mode 100755 index 84c6a93..0000000 --- a/scripts/generate-builds.ts +++ /dev/null @@ -1,34 +0,0 @@ -#!/usr/bin/env -S deno run -A --no-lock - -import $ from "jsr:@david/dax@0.42.0"; -import deno from "../deno.json" with { type: "json" }; - -const targets = Object.keys(deno.tasks) - .filter((key) => key.includes("compile:")) - .map((key) => key.replace("compile:", "")); - -for (const file of Deno.readDirSync("./.bin")) { - if (file.name.match(/.*\.(zip|tar\.gz)(\.sha256)?$/)) { - Deno.removeSync(`./.bin/${file.name}`); - } -} - -await $`echo "ENV=production" > .env`; - -for (const target of targets) { - const binPath = target.includes("windows") - ? `./.bin/denotag-${target}.zip` - : `./.bin/denotag-${target}.tar.gz`; - const archiveCmd = target.includes("windows") - ? `zip -j ${binPath} ./.bin/denotag.exe` - : `tar -czvf ${binPath} -C ./.bin denotag`; - - await $`echo "==> Generating binary for ${target}"`; - await $`deno task compile:${target}`; - await $.raw`${archiveCmd}`; - await $`cd ./.bin/ && sha256sum ${$.path(binPath).basename()} > ./${ - $.path(binPath).basename() - }.sha256`; - - await $`echo`; -} diff --git a/src/main.ts b/src/main.ts index 0a41626..00987f7 100644 --- a/src/main.ts +++ b/src/main.ts @@ -45,7 +45,7 @@ const tag = new Command() throw new Error(`Permission to read/write to "${dir}" not granted.`); } - const embed = await import("./public.json", { with: { type: "json" } }) + const embed = await import("./../embed.json", { with: { type: "json" } }) .then(({ default: main }) => main); const ui = Uint8Array.from(embed["index.html"]);