diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 366a6b4de3..cff6983cc0 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -232,17 +232,32 @@ jobs: shell: pwsh run: | $vswhere = "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe" - $installPath = & $vswhere -products * -latest -property installationPath - $setupExe = "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\setup.exe" - $proc = Start-Process -FilePath $setupExe ` - -ArgumentList "modify", "--installPath", "`"$installPath`"", "--add", ` - "Microsoft.VisualStudio.Component.VC.Tools.x86.x64.Spectre", "--quiet", "--norestart" ` - -Wait -PassThru -NoNewWindow - if ($null -eq $proc -or $proc.ExitCode -ne 0) { - $code = if ($null -ne $proc) { $proc.ExitCode } else { 1 } - Write-Error "Visual Studio Installer failed with exit code $code" - exit $code - } + $installPath = & $vswhere -products * -latest -property installationPath + $setupExe = "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\setup.exe" + $proc = Start-Process -FilePath $setupExe ` + -ArgumentList "modify", "--installPath", "`"$installPath`"", "--add", ` + "Microsoft.VisualStudio.Component.VC.Tools.x86.x64.Spectre", "--quiet", "--norestart" ` + -Wait -PassThru -NoNewWindow + if ($null -eq $proc -or $proc.ExitCode -ne 0) { + $code = if ($null -ne $proc) { $proc.ExitCode } else { 1 } + Write-Error "Visual Studio Installer failed with exit code $code" + exit $code + } + + - name: Install ImageMagick + if: matrix.platform == 'linux' + shell: bash + run: | + if ! command -v magick >/dev/null 2>&1 && ! command -v convert >/dev/null 2>&1; then + sudo apt-get update + sudo apt-get install -y imagemagick + fi + + if command -v magick >/dev/null 2>&1; then + magick -version + else + convert -version + fi - name: Build desktop artifact shell: bash diff --git a/scripts/build-desktop-artifact.ts b/scripts/build-desktop-artifact.ts index 74e8bed0cb..2963fa2c4b 100644 --- a/scripts/build-desktop-artifact.ts +++ b/scripts/build-desktop-artifact.ts @@ -25,6 +25,8 @@ import { import { Command, Flag } from "effect/unstable/cli"; import { ChildProcess, ChildProcessSpawner } from "effect/unstable/process"; +const LINUX_ICON_SIZES = [16, 22, 24, 32, 48, 64, 128, 256, 512] as const; + const BuildPlatform = Schema.Literals(["mac", "linux", "win"]); const BuildArch = Schema.Literals(["arm64", "x64", "universal"]); @@ -419,7 +421,7 @@ function stageMacIcons(stageResourcesDir: string, sourcePng: string, verbose: bo }); } -function stageLinuxIcons(stageResourcesDir: string, sourcePng: string) { +function stageLinuxIcons(stageResourcesDir: string, sourcePng: string, verbose: boolean) { return Effect.gen(function* () { const fs = yield* FileSystem.FileSystem; const path = yield* Path.Path; @@ -431,9 +433,48 @@ function stageLinuxIcons(stageResourcesDir: string, sourcePng: string) { const iconPath = path.join(stageResourcesDir, "icon.png"); yield* fs.copyFile(sourcePng, iconPath); + + const iconsDir = path.join(stageResourcesDir, "icons"); + yield* fs.makeDirectory(iconsDir, { recursive: true }); + for (const iconSize of LINUX_ICON_SIZES) { + yield* stageLinuxIconSize( + sourcePng, + path.join(iconsDir, `${iconSize}x${iconSize}.png`), + iconSize, + verbose, + ); + } }); } +function stageLinuxIconSize( + sourcePng: string, + targetPng: string, + iconSize: number, + verbose: boolean, +) { + const resize = (command: string) => + runCommand( + ChildProcess.make(command, [sourcePng, "-resize", `${iconSize}x${iconSize}`, targetPng], { + ...commandOutputOptions(verbose), + }), + ); + + return resize("magick").pipe( + Effect.catch(() => + resize("convert").pipe( + Effect.mapError( + () => + new BuildScriptError({ + message: + "ImageMagick is required to generate Linux desktop icon sizes. Install ImageMagick so either `magick` or `convert` is available.", + }), + ), + ), + ), + ); +} + function stageWindowsIcons(stageResourcesDir: string, sourceIco: string) { return Effect.gen(function* () { const fs = yield* FileSystem.FileSystem; @@ -599,7 +640,7 @@ const createBuildConfig = Effect.fn("createBuildConfig")(function* ( buildConfig.linux = { target: [target], executableName: "t3code", - icon: "icon.png", + icon: "icons", category: "Development", desktop: { entry: { @@ -638,7 +679,7 @@ const assertPlatformBuildResources = Effect.fn("assertPlatformBuildResources")(f } if (platform === "linux") { - yield* stageLinuxIcons(stageResourcesDir, iconAssets.linuxIconPng); + yield* stageLinuxIcons(stageResourcesDir, iconAssets.linuxIconPng, verbose); return; }