Skip to content

Commit

Permalink
Merge pull request #165 from iongion/fix-flatpak-prepare-publish
Browse files Browse the repository at this point in the history
Fix flatpak
  • Loading branch information
iongion authored Sep 24, 2024
2 parents 343ea63 + a48dc27 commit b44813b
Show file tree
Hide file tree
Showing 20 changed files with 234 additions and 136 deletions.
17 changes: 17 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,23 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## 5.2.4 - 2024-09-24

## Fixed

- WSL - Support for multiple distributions even with automatic connections
- Flatpak - Unable to set icon and connect properly
- Linux - Proper icons and logos in all cases for all packages
- Window Close issues

## Changed

- Reduced timeouts to fail faster
- Improved flatpak build process to be able to publish to flathub
- Updated deps

## Changed

## 5.2.3 - 2024-09-20

## Changed
Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
5.2.3
5.2.4
28 changes: 17 additions & 11 deletions electron-builder-config.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -63,33 +63,37 @@ const config = {
},
publish: null,
flatpak: {
// Debug using: flatpak run --command=sh --devel --filesystem=$(pwd) container_desktop.iongion.github.io
// flatpak run -v container_desktop.iongion.github.io
// flatpak info container_desktop.iongion.github.io
base: "org.electronjs.Electron2.BaseApp",
baseVersion: "24.08",
branch: "main",
category: "Development",
runtime: "org.freedesktop.Platform",
runtimeVersion: "24.08",
license: "LICENSE",
// collection: "org.flathub.Stable",
sdk: "org.freedesktop.Sdk",
useWaylandFlags: true,
finishArgs: [
"--share=network",
"--share=ipc",
"--socket=x11",
"--socket=wayland",
"--socket=pulseaudio",
// "--socket=x11",
"--socket=fallback-x11",
"--socket=pulseaudio", // Is this really needed ?
"--socket=session-bus",
"--socket=system-bus",
"--socket=ssh-auth",
"--device=dri",
"--device=kvm",
"--device=shm",
"--filesystem=host",
"--filesystem=host-os",
"--filesystem=host-etc",
"--filesystem=home",
"--filesystem=/tmp",
"--filesystem=xdg-run/bash",
"--filesystem=xdg-run/nc",
"--filesystem=xdg-run/socat",
"--filesystem=xdg-run/which",
"--filesystem=xdg-run/where",
"--filesystem=xdg-run/ssh",
"--filesystem=/run/user",
"--filesystem=xdg-config",
"--filesystem=xdg-run/podman",
"--filesystem=xdg-run/docker",
"--talk-name=org.freedesktop.Notifications"
Expand Down Expand Up @@ -131,7 +135,9 @@ const config = {
displayName
},
linux: {
icon: "icons/appIcon.svg",
executableName: "container-desktop",
maintainer: process.env.PUBLISHER || pkg.author,
icon: "icons/appIcon.icns",
target: ["deb", "pacman", "rpm", "flatpak", "AppImage"],
category: "Development;System;Utility",
extraResources: ["support/templates"],
Expand Down
14 changes: 7 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
{
"name": "container-desktop",
"title": "Container Desktop",
"version": "5.2.3",
"version": "5.2.4",
"author": "Ionut Stoica <stoica.ionut@gmail.com>",
"description": "Container Desktop",
"main": "build/main-5.2.3.mjs",
"main": "build/main-5.2.4.mjs",
"homepage": "./",
"type": "module",
"scripts": {
Expand Down Expand Up @@ -79,15 +79,15 @@
"@electron/packager": "^18.3.5",
"@hookform/devtools": "^4.3.1",
"@types/electron": "^1.6.10",
"@types/node": "^22.5.5",
"@types/node": "^22.6.1",
"@types/react": "^18.3.8",
"@types/react-dom": "^18.3.0",
"@types/react-helmet": "^6.1.11",
"@types/react-router-dom": "^5.3.3",
"@types/uuid": "10.0.0",
"@typescript-eslint/eslint-plugin": "^8.6.0",
"@typescript-eslint/parser": "^8.6.0",
"@vercel/ncc": "^0.38.1",
"@typescript-eslint/eslint-plugin": "^8.7.0",
"@typescript-eslint/parser": "^8.7.0",
"@vercel/ncc": "^0.38.2",
"@vitejs/plugin-react": "^4.3.1",
"autoprefixer": "^10.4.20",
"cross-env": "^7.0.3",
Expand All @@ -112,7 +112,7 @@
"svgo": "^3.3.2",
"tslib": "^2.7.0",
"typescript": "^5.6.2",
"vite": "^5.4.6",
"vite": "^5.4.7",
"vite-plugin-checker": "^0.8.0",
"vite-plugin-ejs": "^1.7.0",
"vite-plugin-static-copy": "^1.0.6",
Expand Down
31 changes: 27 additions & 4 deletions src/container-client/Api.clients.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
Connection,
Container,
ContainerEngine,
ContainerEngineHost,
ContainerImage,
ContainerImageHistory,
ContainerImageMount,
Expand Down Expand Up @@ -205,17 +206,39 @@ export function isOk(res: AxiosResponse) {
return res.status >= 200 && res.status < 300;
}

export function getApiConfig(api: EngineConnectorApiSettings, scope?: string) {
console.debug("Constructing api configuration", { api, scope });
export async function getApiConfig(api: EngineConnectorApiSettings, scope: string | undefined, host: ContainerEngineHost) {
console.debug("Constructing api configuration", { api, scope, host });
const baseURL = api.baseURL || "";
const socketPath = `${api.connection?.uri || ""}`.replace("npipe://", "").replace("unix://", "");
let socketPath = `${api.connection?.uri || ""}`.replace("npipe://", "").replace("unix://", "");
if (await Platform.isFlatpak()) {
if (
[
// Tests for flatpak
ContainerEngineHost.PODMAN_NATIVE,
ContainerEngineHost.DOCKER_NATIVE,
ContainerEngineHost.PODMAN_VIRTUALIZED_VENDOR,
ContainerEngineHost.DOCKER_VIRTUALIZED_VENDOR,
ContainerEngineHost.PODMAN_REMOTE,
ContainerEngineHost.DOCKER_REMOTE
].includes(host)
) {
//
if (socketPath.startsWith("/run/user")) {
socketPath = await Path.join("/var", socketPath);
} else {
socketPath = await Path.join("/var/run/host", socketPath);
}
console.debug("(flatpak) environment detected - mapped socket path to", socketPath);
}
}
const config: ApiDriverConfig = {
timeout: 60000,
socketPath,
baseURL,
headers: {
Accept: "application/json",
"Content-Type": "application/json"
"Content-Type": "application/json",
"User-Agent": `Container Desktop ${import.meta.env.PROJECT_VERSION}`
}
};
// logger.debug("API configuration", config);
Expand Down
8 changes: 5 additions & 3 deletions src/container-client/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@ async function read() {
async function write(config?: GlobalUserSettings) {
const configPath = await getUserSettingsPath();
try {
const baseDir = await Path.dirname(configPath);
const baseDirExits = await FS.isFilePresent(baseDir);
if (!baseDirExits) {
await FS.mkdir(baseDir, { recursive: true });
}
await FS.writeTextFile(configPath, JSON.stringify(config, null, 2));
} catch (error: any) {
console.error("Unable to write config", { error, config });
Expand All @@ -41,9 +46,6 @@ export async function update(values: Partial<GlobalUserSettings>) {
}

export class UserConfiguration {
constructor() {
console.debug("User configuration has been instantiated");
}
async getStoragePath() {
const dataPath = await Platform.getUserDataPath();
return dataPath;
Expand Down
4 changes: 2 additions & 2 deletions src/container-client/runner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,13 @@ export class Runner {
trace: `Staring the api`
});
this.logger = createLogger("container-client.api.Runner");
this.logger.debug(">> Starting API - guard configuration");
this.logger.debug(">> Starting API - guard configuration", { starter });
if (!starter || !starter?.path) {
this.logger.error("<< Starting API - Starter program not configured");
return false;
}
const clientOpts = {
retry: { count: 10, wait: 10000 },
retry: { count: 10, wait: 5000 },
checkStatus: async () => {
this.logger.debug(">> Starting API - Checking API status - checking if running");
const result = await this.client.isApiRunning();
Expand Down
31 changes: 20 additions & 11 deletions src/container-client/runtimes/abstract/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -170,19 +170,28 @@ export abstract class AbstractContainerEngineHostClient implements ContainerEngi
const controllerProgram = await this.findHostProgram({ name: this.CONTROLLER, path: "" }, settings);
settings.controller = controllerProgram;
settings.controller.scope = existingScope;
const defaultScope = await this.getControllerDefaultScope(settings);
this.logger.warn(this.id, "Default scope is", defaultScope);
if (defaultScope) {
settings.controller.scope = defaultScope.Name;
if (defaultScope.Usable) {
const scopeProgram = await this.findScopeProgram({ name: this.PROGRAM, path: "" }, settings);
settings.program = scopeProgram;
if (isEmpty(existingScope)) {
const defaultScope = await this.getControllerDefaultScope(settings);
this.logger.warn(this.id, "Default scope is", defaultScope);
if (defaultScope) {
settings.controller.scope = defaultScope.Name;
if (defaultScope.Usable) {
const scopeProgram = await this.findScopeProgram({ name: this.PROGRAM, path: "" }, settings);
settings.program = scopeProgram;
} else {
this.logger.warn(this.id, "Default scope is not usable - program will not be detected");
}
// API connection
} else {
this.logger.warn(this.id, "Default scope is not usable - program will not be detected");
this.logger.error(this.id, "No default scope found - program will not be detected");
}
// API connection
} else {
this.logger.error(this.id, "No default scope found - program will not be detected");
try {
const scopeProgram = await this.findScopeProgram({ name: this.PROGRAM, path: "" }, settings);
settings.program = scopeProgram;
} catch (error: any) {
this.logger.error(this.id, "Unable to get scope program", error);
}
}
} else {
const hostProgram = await this.findHostProgram({ name: this.PROGRAM, path: "" }, settings);
Expand Down Expand Up @@ -287,7 +296,7 @@ export abstract class AbstractContainerEngineHostClient implements ContainerEngi
trace: `Performing api health check`
});
try {
const response = await driver.request({ method: "GET", url: "/_ping", timeout: 10000 });
const response = await driver.request({ method: "GET", url: "/_ping", timeout: 5000 });
result.success = response?.data === "OK";
result.details = result.success ? "Api is reachable" : response?.data;
if (!result.success) {
Expand Down
22 changes: 19 additions & 3 deletions src/container-client/runtimes/podman/native.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,16 +56,32 @@ export class PodmanContainerEngineHostClientNative extends PodmanAbstractContain
}
const settings = customSettings || (await this.getSettings());
const programPath = settings.program.path || settings.program.name || "";
if (settings.api.connection.uri) {
const baseDir = await Path.dirname(settings.api.connection.uri);
const socketPath = `${settings.api.connection.uri || ""}`.replace("unix://", "");
if (socketPath) {
const baseDir = await Path.dirname(socketPath);
// CHANGE: I don't know why podman does not create the base-dir of the listening socket
if (await Platform.isFlatpak()) {
if (baseDir.startsWith("/run/user")) {
const hostBaseDir = await Path.join("/var", baseDir);
this.logger.debug(this.id, "(flatpak) Ensuring socket base dir exists in host", hostBaseDir);
await FS.mkdir(hostBaseDir, { recursive: true });
} else {
const hostBaseDir = await Path.join("/var/run/host", baseDir);
this.logger.debug(this.id, "(flatpak) Ensuring socket base dir exists in host", hostBaseDir);
await FS.mkdir(hostBaseDir, { recursive: true });
}
}
this.logger.debug(this.id, "Ensuring socket base dir exists", baseDir);
const baseExists = await FS.isFilePresent(baseDir);
if (!baseExists) {
this.logger.debug(this.id, "Creating socket base dir", baseDir);
await FS.mkdir(baseDir, { recursive: true });
}
}
this.logger.debug(this.id, "Starting API", { programPath, socketPath });
const started = await this.runner.startApi(opts, {
path: programPath,
args: ["system", "service", "--time=0", `unix://${settings.api.connection.uri}`, "--log-level=debug"]
args: ["system", "service", "--time=0", `unix://${socketPath}`, "--log-level=debug"]
});
this.apiStarted = started;
this.logger.debug("Start API complete", started);
Expand Down
1 change: 0 additions & 1 deletion src/container-client/runtimes/podman/ssh.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ export class PodmanContainerEngineHostClientSSH extends AbstractContainerEngineH
} catch (error: any) {
this.logger.warn(this.id, "Unable to get system info", error);
}
// Inspect machine system info for relay path
return {
uri,
relay
Expand Down
5 changes: 1 addition & 4 deletions src/container-client/runtimes/podman/vendor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,7 @@ export class PodmanContainerEngineHostClientVirtualizedVendor extends PodmanAbst
relay: ""
};
}
const NATIVE_PODMAN_SOCKET_PATH = (await Platform.isFlatpak())
? await Path.join("/tmp", PODMAN_API_SOCKET)
: await Path.join(await userConfiguration.getStoragePath(), PODMAN_API_SOCKET);
let uri = NATIVE_PODMAN_SOCKET_PATH;
let uri = await Path.join(await userConfiguration.getStoragePath(), PODMAN_API_SOCKET);
if (this.osType === OperatingSystem.Windows) {
uri = getWindowsPipePath(scope!);
} else {
Expand Down
15 changes: 11 additions & 4 deletions src/container-client/runtimes/podman/wsl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,12 +54,13 @@ export class PodmanContainerEngineHostClientVirtualizedWSL extends AbstractConta
return true;
}
this.logger.warn(this.id, ">> Starting API - starting system service");
const settings = customSettings || (await this.getSettings());
const settings = customSettings || (await this.getSettings()) || {};
this.logger.debug(this.id, ">> Starting API", settings, opts);
const args = ["system", "service", "--time=0", `unix://${settings.api.connection.relay}`, "--log-level=debug"];
const { program, controller } = settings;
let launcherPath = "";
let launcherArgs = [...args];
const scope = settings?.controller?.scope || "";
if (this.isScoped()) {
launcherPath = controller?.path || controller?.name || "";
const programPath = program.path || program.name;
Expand All @@ -68,8 +69,13 @@ export class PodmanContainerEngineHostClientVirtualizedWSL extends AbstractConta
// Bug on WSL - podman is unable to create the base directory for the unix socket
if (settings.api.connection.relay) {
const baseDir = await Path.dirname(settings.api.connection.relay);
this.logger.warn("Ensuring relay base directory", settings.api.connection.relay);
await this.runScopeCommand("mkdir", ["-p", baseDir], controller?.scope || "");
this.logger.error("Ensuring relay base directory", settings.api.connection.relay);
const created = await this.runScopeCommand("mkdir", ["-p", baseDir], scope || "");
if (created.success) {
this.logger.debug(this.id, "Base directory created", baseDir);
} else {
this.logger.warn("Base directory not created", baseDir, { result: created });
}
} else {
this.logger.warn("No relay path - base dir not ensured");
}
Expand All @@ -79,9 +85,10 @@ export class PodmanContainerEngineHostClientVirtualizedWSL extends AbstractConta
} else {
launcherPath = program.path || program.name;
}
this.logger.debug(this.id, ">> Starting API", settings, opts, { launcherPath, launcherArgs });
const started: any = await this.runner.startApi(opts, {
path: launcherPath,
args: launcherArgs
args: ["--distribution", scope, "--exec", "bash", "-l", "-c", "$@", "--"].concat(launcherArgs)
});
this.apiStarted = started;
this.logger.debug(this.id, "<< Starting API completed", started);
Expand Down
Loading

0 comments on commit b44813b

Please sign in to comment.