Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 74 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,55 @@ jobs:
--file "$app/Contents/Resources/bin/devsy" \
--goos "$MATRIX_GO_OS" --goarch "$MATRIX_GO_ARCH"

- name: install desktop-file-utils
if: matrix.name == 'linux-x64'
run: sudo apt-get install -y desktop-file-utils rpm cpio

- name: verify Linux desktop identity and icons in packages
if: matrix.name == 'linux-x64'
shell: bash
run: |
set -euo pipefail
app_id=sh.devsy.app
work="$RUNNER_TEMP/linux-package-check"
rm -rf "$work"
mkdir -p "$work"

appimage=$(find desktop/release -maxdepth 1 -name '*.AppImage' -print -quit)
deb=$(find desktop/release -maxdepth 1 -name '*.deb' -print -quit)
rpm=$(find desktop/release -maxdepth 1 -name '*.rpm' -print -quit)
for pkg in "$appimage" "$deb" "$rpm"; do
[ -n "$pkg" ] || { echo "::error::missing Linux package in desktop/release"; exit 1; }
done

mkdir "$work/appimage" && (cd "$work/appimage" && chmod +x "$GITHUB_WORKSPACE/$appimage" && "$GITHUB_WORKSPACE/$appimage" --appimage-extract >/dev/null)
mkdir "$work/deb" && dpkg-deb -x "$deb" "$work/deb"
mkdir "$work/rpm" && (cd "$work/rpm" && rpm2cpio "$GITHUB_WORKSPACE/$rpm" | cpio -idm --quiet)

appimage_root="$work/appimage/squashfs-root"
go run ./hack/release_artifacts verify-linux-desktop \
--app-id "$app_id" \
--desktop-file "$appimage_root/$app_id.desktop" \
--icon-root "$appimage_root/usr/share/icons/hicolor" \
--require-file "$appimage_root/resources/app-icon.png" \
--require-file "$appimage_root/devsy-desktop.png"
for root in "$work/deb" "$work/rpm"; do
go run ./hack/release_artifacts verify-linux-desktop \
--app-id "$app_id" \
--desktop-file "$root/usr/share/applications/$app_id.desktop" \
--icon-root "$root/usr/share/icons/hicolor" \
--require-file "$root/opt/Devsy/resources/app-icon.png"
done

desktop-file-validate \
"$appimage_root/$app_id.desktop" \
"$work/deb/usr/share/applications/$app_id.desktop" \
"$work/rpm/usr/share/applications/$app_id.desktop"

# The version step rewrites package.json in CI, so check what shipped.
packaged_name=$(cd desktop && node -e 'process.stdout.write(require("@electron/asar").extractFile(process.argv[1], "package.json"))' "$appimage_root/resources/app.asar" | jq -r .desktopName)
[ "$packaged_name" = "$app_id.desktop" ] || { echo "::error::bundled desktopName is '$packaged_name', expected $app_id.desktop"; exit 1; }

- name: upload desktop artifacts to release
uses: softprops/action-gh-release@efb35369e0ad2afab669f228072c1b0d510eae64 # v3
with:
Expand Down Expand Up @@ -378,6 +427,31 @@ jobs:
cache-key: flatpak-builder-${{ github.sha }}
upload-artifact: true

- uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7
with:
go-version-file: go.mod

- name: verify Flatpak desktop identity and exported icons
run: |
set -euo pipefail
# The pinned image is Freedesktop SDK based, without a distro package manager.
command -v flatpak ostree desktop-file-validate
app_id=sh.devsy.app
work="$RUNNER_TEMP/flatpak-bundle-check"
rm -rf "$work"
mkdir -p "$work"
ostree init --repo="$work/repo" --mode=archive-z2
flatpak build-import-bundle "$work/repo" Devsy.flatpak
ref=$(ostree refs --repo="$work/repo" | grep "^app/$app_id/" | head -n 1)
ostree checkout --repo="$work/repo" --user-mode "$ref" "$work/files"
export_root="$work/files/export/share"
go run ./hack/release_artifacts verify-linux-desktop \
--app-id "$app_id" \
--desktop-file "$export_root/applications/$app_id.desktop" \
--icon-root "$export_root/icons/hicolor"
test -s "$export_root/icons/hicolor/128x128/apps/$app_id.png"
desktop-file-validate "$export_root/applications/$app_id.desktop"

- name: upload flatpak bundle
uses: softprops/action-gh-release@efb35369e0ad2afab669f228072c1b0d510eae64 # v3
with:
Expand Down
6 changes: 6 additions & 0 deletions desktop/electron-builder.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ extraResources:
- "**/*"
- from: resources/image-catalog-seed.json
to: image-catalog-seed.json
# Linux windows read this at runtime; the builder icon directory only feeds
# the desktop entry and package icon theme.
- from: resources/icon.png
to: app-icon.png

mac:
category: public.app-category.developer-tools
Expand Down Expand Up @@ -53,6 +57,8 @@ nsis:

linux:
icon: resources/icons
# Names the desktop entry after appId so it matches Electron's desktopName.
syncDesktopName: true
category: Development
artifactName: Devsy_${os}_${arch}.${ext}
target:
Expand Down
2 changes: 1 addition & 1 deletion desktop/flatpak/Devsy.desktop
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@ Icon=sh.devsy.app
Terminal=false
Type=Application
Categories=Development;
StartupWMClass=Devsy
StartupWMClass=sh.devsy.app
11 changes: 10 additions & 1 deletion desktop/flatpak/sh.devsy.app.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,10 @@ modules:
- cp -r opt/Devsy /app/devsy
# Install the CLI binary
- install -Dm755 opt/Devsy/resources/bin/devsy /app/bin/devsy
# Install desktop file, icon, and wrapper
# Install desktop file, exported icons, and wrapper
- install -Dm644 Devsy.desktop /app/share/applications/sh.devsy.app.desktop
- install -Dm644 icon-32.png /app/share/icons/hicolor/32x32/apps/sh.devsy.app.png
- install -Dm644 icon-128.png /app/share/icons/hicolor/128x128/apps/sh.devsy.app.png
- install -Dm755 devsy-wrapper /app/bin/devsy-wrapper
sources:
- type: file
Expand All @@ -44,3 +46,10 @@ modules:
path: Devsy.desktop
- type: file
path: devsy-wrapper
# Flatpak exports only icons up to 512x512 from share/icons/hicolor.
- type: file
path: ../resources/icons/32x32.png
dest-filename: icon-32.png
- type: file
path: ../resources/icons/128x128.png
dest-filename: icon-128.png
1 change: 1 addition & 0 deletions desktop/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"name": "devsy-desktop",
"version": "0.1.0",
"desktopName": "sh.devsy.app.desktop",
"private": true,
"homepage": "https://devsy.sh",
"author": {
Expand Down
33 changes: 33 additions & 0 deletions desktop/src/main/__tests__/app-settings.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ describe("normalizeAppSettings", () => {
trayNotifications: "all",
desktopLogLevel: "info",
cliCaptureLogLevel: "info",
appImageIntegrationPromptDismissed: false,
})
})

Expand All @@ -43,6 +44,7 @@ describe("normalizeAppSettings", () => {
trayNotifications: "failures",
desktopLogLevel: "info",
cliCaptureLogLevel: "info",
appImageIntegrationPromptDismissed: false,
})
})

Expand Down Expand Up @@ -79,13 +81,15 @@ describe("patchAppSettings", () => {
trayNotifications: "all" as const,
desktopLogLevel: "info" as const,
cliCaptureLogLevel: "info" as const,
appImageIntegrationPromptDismissed: false,
}
expect(patchAppSettings(current, { runAtStartup: false })).toEqual({
runAtStartup: false,
openToTrayOnStartup: false,
trayNotifications: "all",
desktopLogLevel: "info",
cliCaptureLogLevel: "info",
appImageIntegrationPromptDismissed: false,
})
})

Expand All @@ -96,13 +100,15 @@ describe("patchAppSettings", () => {
trayNotifications: "off" as const,
desktopLogLevel: "info" as const,
cliCaptureLogLevel: "info" as const,
appImageIntegrationPromptDismissed: false,
}
expect(patchAppSettings(current, { openToTrayOnStartup: true })).toEqual({
runAtStartup: true,
openToTrayOnStartup: true,
trayNotifications: "off",
desktopLogLevel: "info",
cliCaptureLogLevel: "info",
appImageIntegrationPromptDismissed: false,
})
})
})
Expand Down Expand Up @@ -169,6 +175,7 @@ describe("AppSettingsStore", () => {
trayNotifications: "off",
desktopLogLevel: "info",
cliCaptureLogLevel: "info",
appImageIntegrationPromptDismissed: false,
})
})

Expand All @@ -186,6 +193,7 @@ describe("AppSettingsStore", () => {
trayNotifications: "failures",
desktopLogLevel: "info",
cliCaptureLogLevel: "info",
appImageIntegrationPromptDismissed: false,
})
})

Expand Down Expand Up @@ -215,3 +223,28 @@ describe("AppSettingsStore", () => {
expect(calls).toBe(1)
})
})

describe("appImageIntegrationPromptDismissed", () => {
it("persists a dismissed prompt and defaults to not dismissed", () => {
expect(normalizeAppSettings({}).appImageIntegrationPromptDismissed).toBe(
false,
)
expect(
normalizeAppSettings({ appImageIntegrationPromptDismissed: true })
.appImageIntegrationPromptDismissed,
).toBe(true)
expect(
normalizeAppSettings({ appImageIntegrationPromptDismissed: "yes" })
.appImageIntegrationPromptDismissed,
).toBe(false)
})

it("accepts only a boolean from the renderer", () => {
expect(
sanitizeAppSettingsPatch({ appImageIntegrationPromptDismissed: true }),
).toEqual({ appImageIntegrationPromptDismissed: true })
expect(() =>
sanitizeAppSettingsPatch({ appImageIntegrationPromptDismissed: 1 }),
).toThrow("appImageIntegrationPromptDismissed must be boolean")
})
})
31 changes: 31 additions & 0 deletions desktop/src/main/__tests__/linux-desktop-identity.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// @vitest-environment node
import { join } from "node:path"
import { describe, expect, it } from "vitest"
import {
linuxWindowIcon,
PACKAGED_ICON_FILE,
} from "../linux-desktop-identity.js"

const context = {
isPackaged: true,
resourcesPath: "/opt/Devsy/resources",
appPath: "/work/desktop",
}

describe("linuxWindowIcon", () => {
it("uses the icon shipped in resources when packaged", () => {
expect(linuxWindowIcon({ ...context, platform: "linux" })).toBe(
join("/opt/Devsy/resources", PACKAGED_ICON_FILE),
)
})

it("uses the source tree icon in development", () => {
expect(
linuxWindowIcon({ ...context, platform: "linux", isPackaged: false }),
).toBe(join("/work/desktop", "resources", "icon.png"))
})

it.each(["darwin", "win32"] as const)("sets no icon on %s", (platform) => {
expect(linuxWindowIcon({ ...context, platform })).toBeUndefined()
})
})
Loading
Loading