From 48ace110f85352ede0cabccbd6c607afb3d6d2de Mon Sep 17 00:00:00 2001 From: Allen Houchins <32207388+allenhouchins@users.noreply.github.com> Date: Tue, 26 May 2026 15:37:28 -0500 Subject: [PATCH] Add BlueJ as a Windows FMA (#46222) Add BlueJ as a maintained Windows app: new winget input manifest (ee/maintained-apps/inputs/winget/bluej.json), PowerShell install and uninstall scripts (ee/maintained-apps/inputs/winget/scripts/bluej_install.ps1 and bluej_uninstall.ps1), and output metadata (ee/maintained-apps/outputs/bluej/windows.json). Also update apps index (ee/maintained-apps/outputs/apps.json) to include BlueJ. The install script passes ALLUSERS=2 so the per-user WiX MSI installs per-machine when run elevated; the uninstall script finds related product codes for the app's upgrade code and uninstalls each with a timeout. The outputs include version 5.5.0, installer URL, checksum, and embedded script refs. --- ee/maintained-apps/inputs/winget/bluej.json | 12 +++++++++ .../inputs/winget/scripts/bluej_install.ps1 | 20 +++++++++++++++ .../inputs/winget/scripts/bluej_uninstall.ps1 | 24 ++++++++++++++++++ ee/maintained-apps/outputs/apps.json | 7 +++++ ee/maintained-apps/outputs/bluej/windows.json | 22 ++++++++++++++++ .../SoftwarePage/components/icons/Bluej.tsx | 14 ++++++++++ .../SoftwarePage/components/icons/index.ts | 2 ++ .../assets/images/app-icon-bluej-60x60@2x.png | Bin 0 -> 10906 bytes 8 files changed, 101 insertions(+) create mode 100644 ee/maintained-apps/inputs/winget/bluej.json create mode 100644 ee/maintained-apps/inputs/winget/scripts/bluej_install.ps1 create mode 100644 ee/maintained-apps/inputs/winget/scripts/bluej_uninstall.ps1 create mode 100644 ee/maintained-apps/outputs/bluej/windows.json create mode 100644 frontend/pages/SoftwarePage/components/icons/Bluej.tsx create mode 100644 website/assets/images/app-icon-bluej-60x60@2x.png diff --git a/ee/maintained-apps/inputs/winget/bluej.json b/ee/maintained-apps/inputs/winget/bluej.json new file mode 100644 index 0000000000..73a5837327 --- /dev/null +++ b/ee/maintained-apps/inputs/winget/bluej.json @@ -0,0 +1,12 @@ +{ + "name": "BlueJ", + "slug": "bluej/windows", + "package_identifier": "BlueJTeam.BlueJ", + "unique_identifier": "BlueJ", + "install_script_path": "ee/maintained-apps/inputs/winget/scripts/bluej_install.ps1", + "uninstall_script_path": "ee/maintained-apps/inputs/winget/scripts/bluej_uninstall.ps1", + "installer_arch": "x64", + "installer_type": "msi", + "installer_scope": "user", + "default_categories": ["Developer tools"] +} diff --git a/ee/maintained-apps/inputs/winget/scripts/bluej_install.ps1 b/ee/maintained-apps/inputs/winget/scripts/bluej_install.ps1 new file mode 100644 index 0000000000..7f01579adb --- /dev/null +++ b/ee/maintained-apps/inputs/winget/scripts/bluej_install.ps1 @@ -0,0 +1,20 @@ +# BlueJ ships a per-user WiX MSI. Fleet runs installs elevated (SYSTEM), so we +# pass ALLUSERS=2 — the same switch winget uses — which resolves to a per-machine +# install (into %ProgramFiles%\BlueJ) when run elevated. + +$logFile = "${env:TEMP}/fleet-install-software.log" + +try { + +$installProcess = Start-Process msiexec.exe ` + -ArgumentList "/quiet /norestart /lv ${logFile} /i `"${env:INSTALLER_PATH}`" ALLUSERS=2" ` + -PassThru -Verb RunAs -Wait + +Get-Content $logFile -Tail 500 + +Exit $installProcess.ExitCode + +} catch { + Write-Host "Error: $_" + Exit 1 +} diff --git a/ee/maintained-apps/inputs/winget/scripts/bluej_uninstall.ps1 b/ee/maintained-apps/inputs/winget/scripts/bluej_uninstall.ps1 new file mode 100644 index 0000000000..2806ec4b46 --- /dev/null +++ b/ee/maintained-apps/inputs/winget/scripts/bluej_uninstall.ps1 @@ -0,0 +1,24 @@ +# Fleet uninstalls app by finding all related product codes for the specified upgrade code +$inst = New-Object -ComObject "WindowsInstaller.Installer" +$timeoutSeconds = 300 # 5 minute timeout per product + +foreach ($product_code in $inst.RelatedProducts('{F4B4357E-6101-4CB1-8E38-3D4F3AFB4BE2}')) { + $process = Start-Process msiexec -ArgumentList @("/quiet", "/x", $product_code, "/norestart") -PassThru + + # Wait for process with timeout + $completed = $process.WaitForExit($timeoutSeconds * 1000) + + if (-not $completed) { + Stop-Process -Id $process.Id -Force -ErrorAction SilentlyContinue + Exit 1603 # ERROR_UNINSTALL_FAILURE + } + + # If the uninstall failed, bail + if ($process.ExitCode -ne 0) { + Write-Output "Uninstall for $($product_code) exited $($process.ExitCode)" + Exit $process.ExitCode + } +} + +# All uninstalls succeeded; exit success +Exit 0 diff --git a/ee/maintained-apps/outputs/apps.json b/ee/maintained-apps/outputs/apps.json index 9ee7a24dcd..1e67daf7c4 100644 --- a/ee/maintained-apps/outputs/apps.json +++ b/ee/maintained-apps/outputs/apps.json @@ -288,6 +288,13 @@ "unique_identifier": "Blender", "description": "Blender is a 3D creation suite." }, + { + "name": "BlueJ", + "slug": "bluej/windows", + "platform": "windows", + "unique_identifier": "BlueJ", + "description": "BlueJ is a free Java development environment designed for beginners." + }, { "name": "Box Drive", "slug": "box-drive/darwin", diff --git a/ee/maintained-apps/outputs/bluej/windows.json b/ee/maintained-apps/outputs/bluej/windows.json new file mode 100644 index 0000000000..1e1e2e42c9 --- /dev/null +++ b/ee/maintained-apps/outputs/bluej/windows.json @@ -0,0 +1,22 @@ +{ + "versions": [ + { + "version": "5.5.0", + "queries": { + "exists": "SELECT 1 FROM programs WHERE name = 'BlueJ' AND publisher = 'BlueJ Team';", + "patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM programs WHERE name = 'BlueJ' AND publisher = 'BlueJ Team' AND version_compare(version, '5.5.0') < 0);" + }, + "installer_url": "https://github.com/k-pet-group/BlueJ-Greenfoot/releases/download/BLUEJ-RELEASE-5.5.0/BlueJ-windows-5.5.0.msi", + "install_script_ref": "29a9338f", + "uninstall_script_ref": "d85b3e22", + "sha256": "697404b7f704235878861bd4133e24480e17e74942f0a9d31db08ddfe4ee21c0", + "default_categories": [ + "Developer tools" + ] + } + ], + "refs": { + "29a9338f": "# BlueJ ships a per-user WiX MSI. Fleet runs installs elevated (SYSTEM), so we\n# pass ALLUSERS=2 — the same switch winget uses — which resolves to a per-machine\n# install (into %ProgramFiles%\\BlueJ) when run elevated.\n\n$logFile = \"${env:TEMP}/fleet-install-software.log\"\n\ntry {\n\n$installProcess = Start-Process msiexec.exe `\n -ArgumentList \"/quiet /norestart /lv ${logFile} /i `\"${env:INSTALLER_PATH}`\" ALLUSERS=2\" `\n -PassThru -Verb RunAs -Wait\n\nGet-Content $logFile -Tail 500\n\nExit $installProcess.ExitCode\n\n} catch {\n Write-Host \"Error: $_\"\n Exit 1\n}\n", + "d85b3e22": "# Fleet uninstalls app by finding all related product codes for the specified upgrade code\n$inst = New-Object -ComObject \"WindowsInstaller.Installer\"\n$timeoutSeconds = 300 # 5 minute timeout per product\n\nforeach ($product_code in $inst.RelatedProducts('{F4B4357E-6101-4CB1-8E38-3D4F3AFB4BE2}')) {\n $process = Start-Process msiexec -ArgumentList @(\"/quiet\", \"/x\", $product_code, \"/norestart\") -PassThru\n\n # Wait for process with timeout\n $completed = $process.WaitForExit($timeoutSeconds * 1000)\n\n if (-not $completed) {\n Stop-Process -Id $process.Id -Force -ErrorAction SilentlyContinue\n Exit 1603 # ERROR_UNINSTALL_FAILURE\n }\n\n # If the uninstall failed, bail\n if ($process.ExitCode -ne 0) {\n Write-Output \"Uninstall for $($product_code) exited $($process.ExitCode)\"\n Exit $process.ExitCode\n }\n}\n\n# All uninstalls succeeded; exit success\nExit 0\n" + } +} diff --git a/frontend/pages/SoftwarePage/components/icons/Bluej.tsx b/frontend/pages/SoftwarePage/components/icons/Bluej.tsx new file mode 100644 index 0000000000..1892a4ab5c --- /dev/null +++ b/frontend/pages/SoftwarePage/components/icons/Bluej.tsx @@ -0,0 +1,14 @@ +import * as React from "react"; + +import type { SVGProps } from "react"; + +const Bluej = (props: SVGProps) => ( + + + +); +export default Bluej; diff --git a/frontend/pages/SoftwarePage/components/icons/index.ts b/frontend/pages/SoftwarePage/components/icons/index.ts index 87b0388b0b..0dedbdc167 100644 --- a/frontend/pages/SoftwarePage/components/icons/index.ts +++ b/frontend/pages/SoftwarePage/components/icons/index.ts @@ -7,6 +7,7 @@ import { matchLoosePrefixToKey } from "utilities/strings/stringUtils"; import Backblaze from "./Backblaze"; import BetterDisplay from "./BetterDisplay"; +import Bluej from "./Bluej"; import Cavalry from "./Cavalry"; import Charles from "./Charles"; import ConnectFonts from "./ConnectFonts"; @@ -303,6 +304,7 @@ export const SOFTWARE_NAME_TO_ICON_MAP = { "beyond compare": BeyondCompare, bitwarden: Bitwarden, blender: Blender, + bluej: Bluej, box: Box, brave: Brave, bruno: Bruno, diff --git a/website/assets/images/app-icon-bluej-60x60@2x.png b/website/assets/images/app-icon-bluej-60x60@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..15727adee630fbfa2a907bc23b6cd25350a2167d GIT binary patch literal 10906 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 JEoB=1{{WrfO3?rS literal 0 HcmV?d00001