2022-03-08 16:49:08 +00:00
/ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2024-12-02 10:49:37 +00:00
* Copyright ( C ) 2024 Red Hat , Inc .
2022-04-14 12:29:32 +00:00
*
2022-03-08 16:49:08 +00:00
* Licensed under the Apache License , Version 2.0 ( the "License" ) ;
* you may not use this file except in compliance with the License .
* You may obtain a copy of the License at
2022-04-14 12:29:32 +00:00
*
2022-03-08 16:49:08 +00:00
* http : //www.apache.org/licenses/LICENSE-2.0
2022-04-14 12:29:32 +00:00
*
2022-03-08 16:49:08 +00:00
* Unless required by applicable law or agreed to in writing , software
* distributed under the License is distributed on an "AS IS" BASIS ,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND , either express or implied .
* See the License for the specific language governing permissions and
* limitations under the License .
*
* SPDX - License - Identifier : Apache - 2.0
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /
2025-12-08 10:17:51 +00:00
const { exec , execFile } = require ( 'child_process' ) ;
2022-08-18 09:20:41 +00:00
const Arch = require ( 'builder-util' ) . Arch ;
2024-01-02 15:35:23 +00:00
const path = require ( 'path' ) ;
const { flipFuses , FuseVersion , FuseV1Options } = require ( '@electron/fuses' ) ;
2025-11-27 08:52:48 +00:00
const product = require ( './product.json' ) ;
2025-12-08 10:17:51 +00:00
const fs = require ( 'node:fs' ) ;
2022-03-08 16:49:08 +00:00
if ( process . env . VITE _APP _VERSION === undefined ) {
2022-04-14 12:29:32 +00:00
const now = new Date ( ) ;
process . env . VITE _APP _VERSION = ` ${ now . getUTCFullYear ( ) - 2000 } . ${ now . getUTCMonth ( ) + 1 } . ${ now . getUTCDate ( ) } - ${
now . getUTCHours ( ) * 60 + now . getUTCMinutes ( )
} ` ;
2022-03-08 16:49:08 +00:00
}
2023-01-10 20:56:02 +00:00
let macosArches = [ 'x64' , 'arm64' , 'universal' ] ;
let artifactNameSuffix = '' ;
if ( process . env . AIRGAP _DOWNLOAD ) {
artifactNameSuffix = '-airgap' ;
2024-04-25 21:49:11 +00:00
// Create dedicated but not universal builds for airgap as it's > 2GB for macOS
macosArches = [ 'x64' , 'arm64' ] ;
2023-01-10 20:56:02 +00:00
}
2024-01-02 15:35:23 +00:00
async function addElectronFuses ( context ) {
const { electronPlatformName , arch } = context ;
const ext = {
darwin : '.app' ,
win32 : '.exe' ,
linux : [ '' ] ,
} [ electronPlatformName ] ;
const IS _LINUX = context . electronPlatformName === 'linux' ;
const executableName = IS _LINUX
? context . packager . appInfo . productFilename . toLowerCase ( ) . replace ( '-dev' , '' ) . replace ( ' ' , '-' )
: context . packager . appInfo . productFilename ; // .toLowerCase() to accomodate Linux file named `name` but productFileName is `Name` -- Replaces '-dev' because on Linux the executable name is `name` even for the DEV builds
const electronBinaryPath = path . join ( context . appOutDir , ` ${ executableName } ${ ext } ` ) ;
2024-05-07 12:54:13 +00:00
let electronEnableInspect = false ;
if ( process . env . ELECTRON _ENABLE _INSPECT === 'true' ) {
electronEnableInspect = true ;
}
2024-01-02 15:35:23 +00:00
await flipFuses ( electronBinaryPath , {
version : FuseVersion . V1 ,
[ FuseV1Options . RunAsNode ] : false ,
[ FuseV1Options . EnableNodeOptionsEnvironmentVariable ] : false ,
2024-05-07 12:54:13 +00:00
[ FuseV1Options . EnableNodeCliInspectArguments ] : electronEnableInspect ,
2024-01-02 15:35:23 +00:00
} ) ;
}
2025-12-08 10:17:51 +00:00
/ * *
* This function will start the script that will bundle the extensions # remote from the ` product.json `
* to the extensions - extra folder
*
* @ remarks it should be called in the beforePack to populate the folder extensions - extra before electron builder pack them
* /
2026-01-07 16:26:56 +00:00
async function packageRemoteExtensions ( context ) {
2025-12-08 10:17:51 +00:00
const downloadScript = path . join ( 'packages' , 'main' , 'dist' , 'download-remote-extensions.cjs' ) ;
if ( ! fs . existsSync ( downloadScript ) ) {
console . warn ( ` ${ downloadScript } not found, skipping remote extension download ` ) ;
return ;
}
const destination = path . resolve ( './extensions-extra' ) ;
2026-01-07 16:26:56 +00:00
await new Promise ( ( resolve , reject ) => {
2025-12-15 16:29:33 +00:00
execFile (
'node' ,
[ downloadScript , ` --output= ${ destination } ` ] ,
{ maxBuffer : 10 * 1024 * 1024 } , // use 10MB else default size is too small and we get stdout maxBuffer length exceeded
( error , stdout , stderr ) => {
console . log ( stdout ) ;
console . log ( stderr ) ;
if ( error ) {
reject ( error ) ;
} else {
resolve ( ) ;
}
} ,
) ;
2025-12-08 10:17:51 +00:00
} ) ;
2026-01-07 16:26:56 +00:00
context . packager . config . extraResources . push ( './extensions-extra/**' ) ;
2025-12-08 10:17:51 +00:00
}
2022-03-08 16:49:08 +00:00
/ * *
* @ type { import ( 'electron-builder' ) . Configuration }
* @ see https : //www.electron.build/configuration/configuration
* /
const config = {
2025-11-27 08:52:48 +00:00
productName : product . name ,
appId : product . appId ,
2022-03-08 16:49:08 +00:00
directories : {
output : 'dist' ,
buildResources : 'buildResources' ,
} ,
2022-10-14 07:49:50 +00:00
buildDependenciesFromSource : false ,
npmRebuild : false ,
2024-09-23 08:12:38 +00:00
beforePack : async context => {
2024-10-22 00:57:37 +00:00
const DEFAULT _ASSETS = [ ] ;
2025-09-17 14:16:21 +00:00
const PODMAN _EXTENSION _ASSETS = 'extensions/podman/packages/extension/assets' ;
2024-08-12 14:11:31 +00:00
context . packager . config . extraResources = DEFAULT _ASSETS ;
2022-08-18 09:20:41 +00:00
2025-12-08 10:17:51 +00:00
// download & package remote extensions
2026-01-07 16:26:56 +00:00
await packageRemoteExtensions ( context ) ;
2025-12-08 10:17:51 +00:00
2025-11-27 16:08:28 +00:00
// include product.json
context . packager . config . extraResources . push ( {
from : 'product.json' ,
to : 'product.json' ,
} ) ;
2022-08-18 09:20:41 +00:00
// universal build, add both pkg files
// this is hack to avoid issue https://github.com/electron/universal/issues/36
2024-09-23 08:12:38 +00:00
if (
context . appOutDir . endsWith ( 'mac-universal-x64-temp' ) ||
context . appOutDir . endsWith ( 'mac-universal-arm64-temp' )
) {
context . packager . config . extraResources = DEFAULT _ASSETS ;
2025-09-17 14:16:21 +00:00
context . packager . config . extraResources . push ( ` ${ PODMAN _EXTENSION _ASSETS } /podman-installer-macos-universal*.pkg ` ) ;
2022-08-18 09:20:41 +00:00
return ;
}
2024-09-23 08:12:38 +00:00
if ( context . arch === Arch . arm64 && context . electronPlatformName === 'darwin' ) {
2025-09-17 14:16:21 +00:00
context . packager . config . extraResources . push ( ` ${ PODMAN _EXTENSION _ASSETS } /podman-installer-macos-aarch64-*.pkg ` ) ;
context . packager . config . extraResources . push ( ` ${ PODMAN _EXTENSION _ASSETS } /podman-image-arm64.zst ` ) ;
2022-08-18 09:20:41 +00:00
}
2024-09-23 08:12:38 +00:00
if ( context . arch === Arch . x64 && context . electronPlatformName === 'darwin' ) {
2025-09-17 14:16:21 +00:00
context . packager . config . extraResources . push ( ` ${ PODMAN _EXTENSION _ASSETS } /podman-installer-macos-amd64-*.pkg ` ) ;
context . packager . config . extraResources . push ( ` ${ PODMAN _EXTENSION _ASSETS } /podman-image-x64.zst ` ) ;
2022-08-18 09:20:41 +00:00
}
2023-08-23 15:28:54 +00:00
if ( context . electronPlatformName === 'win32' ) {
// add the win-ca package
context . packager . config . extraResources . push ( {
from : 'node_modules/win-ca/lib/roots.exe' ,
to : 'win-ca/roots.exe' ,
} ) ;
// add podman installer
2025-09-17 14:16:21 +00:00
if ( context . arch === Arch . x64 ) {
2026-01-16 12:59:49 +00:00
context . packager . config . extraResources . push ( ` ${ PODMAN _EXTENSION _ASSETS } /podman-installer-windows-amd64.msi ` ) ;
2025-09-17 14:16:21 +00:00
context . packager . config . extraResources . push ( ` ${ PODMAN _EXTENSION _ASSETS } /podman-image-x64.zst ` ) ;
}
if ( context . arch === Arch . arm64 ) {
2026-01-16 12:59:49 +00:00
context . packager . config . extraResources . push ( ` ${ PODMAN _EXTENSION _ASSETS } /podman-installer-windows-arm64.msi ` ) ;
2025-09-17 14:16:21 +00:00
context . packager . config . extraResources . push ( ` ${ PODMAN _EXTENSION _ASSETS } /podman-image-arm64.zst ` ) ;
}
2022-08-18 09:20:41 +00:00
}
} ,
2024-01-02 15:35:23 +00:00
afterPack : async context => {
await addElectronFuses ( context ) ;
} ,
2026-01-07 16:26:56 +00:00
files : [ 'packages/**/dist/**' , 'extensions/**/builtin/*.cdix/**' , 'packages/main/src/assets/**' ] ,
2022-03-10 12:46:55 +00:00
portable : {
2025-11-27 08:52:48 +00:00
artifactName : ` ${ product . artifactName } ${ artifactNameSuffix } - \$ {version}- \$ {arch}. \$ {ext} ` ,
2022-03-10 12:46:55 +00:00
} ,
nsis : {
2025-11-27 08:52:48 +00:00
artifactName : ` ${ product . artifactName } ${ artifactNameSuffix } - \$ {version}-setup- \$ {arch}. \$ {ext} ` ,
2025-06-27 20:39:56 +00:00
oneClick : false ,
2025-11-01 04:52:01 +00:00
include : 'buildResources/installer.nsh' ,
2022-03-10 12:46:55 +00:00
} ,
2022-03-10 12:21:59 +00:00
win : {
2023-08-23 08:24:38 +00:00
target : [
{
target : 'portable' ,
arch : [ 'x64' , 'arm64' ] ,
} ,
{
target : 'nsis' ,
arch : [ 'x64' , 'arm64' ] ,
} ,
] ,
2025-06-02 09:26:53 +00:00
/ * *
2025-07-08 14:28:59 +00:00
* Use Azure Keyvault to sign the Windows binaries ( using Digicert timestamp server and not Azure Trusted Signing ) .
2025-06-02 09:26:53 +00:00
* /
signtoolOptions : {
2025-07-08 14:28:59 +00:00
sign : configuration => azureKeyvaultSign ( configuration . path ) ,
2025-06-02 09:26:53 +00:00
} ,
2022-03-10 12:21:59 +00:00
} ,
2022-05-03 07:31:23 +00:00
flatpak : {
license : 'LICENSE' ,
finishArgs : [
'--socket=wayland' ,
'--socket=x11' ,
'--share=ipc' ,
// Open GL
'--device=dri' ,
// Read/write home directory access
'--filesystem=home' ,
2026-01-21 16:04:59 +00:00
// Read-only access to /usr and /etc for managed-configuration support.
// Flatpak sandboxes these directories, so we can't use --filesystem=/usr/share/podman-desktop:ro directly.
// host-os:ro only exposes /usr and parts of /etc (not the full filesystem).
// See: https://github.com/flatpak/flatpak/issues/5575
// See: https://man7.org/linux/man-pages/man5/flatpak-metadata.5.html (host-os section)
'--filesystem=host-os:ro' ,
2022-05-03 07:31:23 +00:00
// Read podman socket
2022-11-18 09:02:34 +00:00
'--filesystem=xdg-run/podman:create' ,
2025-03-13 09:36:02 +00:00
// Read/write containers directory access (ability to save the application preferences)
'--filesystem=xdg-run/containers:create' ,
2022-11-23 19:06:54 +00:00
// Read docker socket
'--filesystem=/run/docker.sock' ,
2022-05-03 07:31:23 +00:00
// Allow communication with network
'--share=network' ,
// System notifications with libnotify
'--talk-name=org.freedesktop.Notifications' ,
2025-04-01 16:10:19 +00:00
// Allow safeStorage access to keyring to encrypt/decrypt file used to store sensitive information
// In Gnome Desktop Environment
'--talk-name=org.freedesktop.secrets' ,
// In KDE Desktop Environment
'--talk-name=org.kde.kwalletd6' ,
2025-06-09 22:02:36 +00:00
// Allow registration and management of system tray icons and their associated
// notifications in KDE Desktop Environment
'--talk-name=org.kde.StatusNotifierWatcher' ,
// Allow to interact with Flatpak system to execute commands outside the application's sandbox
'--talk-name=org.freedesktop.Flatpak' ,
2026-01-21 16:04:59 +00:00
// required to fix cursor scaling on wayland https://github.com/electron/electron/issues/19810 when the user uses --socket=wayland in their flatpak run
'--env=XCURSOR_PATH=/run/host/user-share/icons:/run/host/share/icons' ,
2025-10-14 05:48:01 +00:00
'--env=XDG_SESSION_TYPE=x11' ,
2022-05-03 07:31:23 +00:00
] ,
2022-07-18 15:11:37 +00:00
useWaylandFlags : 'false' ,
2025-11-27 08:52:48 +00:00
artifactName : ` ${ product . artifactName } - \$ {version}. \$ {ext} ` ,
2025-11-01 22:11:11 +00:00
runtimeVersion : '25.08' ,
2022-05-03 07:31:23 +00:00
branch : 'main' ,
2022-07-20 08:33:11 +00:00
files : [
[ '.flatpak-appdata.xml' , '/share/metainfo/io.podman_desktop.PodmanDesktop.metainfo.xml' ] ,
2022-07-20 09:15:41 +00:00
[ 'buildResources/icon-512x512.png' , '/share/icons/hicolor/512x512/apps/io.podman_desktop.PodmanDesktop.png' ] ,
2022-07-20 08:33:11 +00:00
] ,
2022-05-03 07:31:23 +00:00
} ,
2022-03-10 12:21:59 +00:00
linux : {
2023-09-19 13:03:31 +00:00
category : 'Development' ,
2022-05-03 07:31:23 +00:00
icon : './buildResources/icon-512x512.png' ,
2025-12-12 09:40:14 +00:00
executableName : product . artifactName ,
2025-12-12 14:41:44 +00:00
artifactName : ` ${ product . artifactName } ${ artifactNameSuffix } - \$ {version}- \$ {arch}. \$ {ext} ` ,
2025-04-22 07:26:11 +00:00
target : [ 'flatpak' , { target : 'tar.gz' , arch : [ 'x64' , 'arm64' ] } ] ,
2022-03-10 12:21:59 +00:00
} ,
2022-03-09 13:56:05 +00:00
mac : {
2025-11-27 08:52:48 +00:00
artifactName : ` ${ product . artifactName } ${ artifactNameSuffix } - \$ {version}- \$ {arch}. \$ {ext} ` ,
2022-03-23 13:08:00 +00:00
hardenedRuntime : true ,
entitlements : './node_modules/electron-builder-notarize/entitlements.mac.inherit.plist' ,
2026-02-11 15:17:35 +00:00
x64ArchFiles : 'Contents/Resources/app.asar.unpacked/**/*.node' ,
2022-03-09 13:56:05 +00:00
target : {
target : 'default' ,
2023-01-10 20:56:02 +00:00
arch : macosArches ,
2022-03-09 13:56:05 +00:00
} ,
} ,
2022-03-08 16:49:08 +00:00
dmg : {
2026-02-11 15:17:35 +00:00
background : 'buildResources/dmg-background.png' ,
2025-05-08 14:44:08 +00:00
window : {
width : 540 ,
height : 380 ,
} ,
2022-03-08 16:49:08 +00:00
contents : [
{
x : 410 ,
2025-05-08 14:44:08 +00:00
y : 166 ,
2022-04-14 12:29:32 +00:00
type : 'link' ,
path : '/Applications' ,
2022-03-08 16:49:08 +00:00
} ,
{
x : 130 ,
2025-05-08 14:44:08 +00:00
y : 166 ,
2022-04-14 12:29:32 +00:00
type : 'file' ,
2022-03-08 16:49:08 +00:00
} ,
] ,
} ,
2023-06-05 08:55:58 +00:00
protocols : {
2025-11-27 08:52:48 +00:00
name : product . name ,
schemes : [ product . urlProtocol ] ,
2024-09-23 08:12:38 +00:00
role : 'Editor' ,
2023-06-05 08:55:58 +00:00
} ,
2022-10-26 06:35:05 +00:00
publish : {
provider : 'github' ,
timeout : 10000 ,
2024-09-23 08:12:38 +00:00
} ,
2022-03-10 15:33:40 +00:00
/ * e x t r a M e t a d a t a : {
2022-03-08 16:49:08 +00:00
version : process . env . VITE _APP _VERSION ,
2022-03-10 15:33:40 +00:00
} , * /
2022-03-08 16:49:08 +00:00
} ;
2023-01-10 20:56:02 +00:00
// do not publish auto-update files for airgap mode
if ( process . env . AIRGAP _DOWNLOAD ) {
config . publish = {
publishAutoUpdate : false ,
2024-09-23 08:12:38 +00:00
provider : 'github' ,
2023-01-10 20:56:02 +00:00
} ;
}
2025-06-02 09:26:53 +00:00
/ * *
2025-07-08 14:28:59 +00:00
* Use a keyvault instance that has a certificate to sign the Windows binaries .
2025-06-02 09:26:53 +00:00
* @ param filePath
* @ return { Promise < void > }
* /
2025-07-08 14:28:59 +00:00
const azureKeyvaultSign = filePath => {
2022-08-09 13:02:27 +00:00
if ( ! process . env . AZURE _KEY _VAULT _URL ) {
console . log ( 'Skipping code signing, no environment variables set for that.' ) ;
return Promise . resolve ( ) ;
}
return new Promise ( ( resolve , reject ) => {
const {
AZURE _KEY _VAULT _TENANT _ID ,
AZURE _KEY _VAULT _CLIENT _ID ,
AZURE _KEY _VAULT _SECRET ,
AZURE _KEY _VAULT _URL ,
AZURE _KEY _VAULT _CERTIFICATE ,
} = process . env ;
// eslint-disable-next-line no-console
console . log ( 'Signing file' , filePath ) ;
const command = ` AzureSignTool sign -kvu ${ AZURE _KEY _VAULT _URL } -kvi ${ AZURE _KEY _VAULT _CLIENT _ID } -kvt ${ AZURE _KEY _VAULT _TENANT _ID } -kvs ${ AZURE _KEY _VAULT _SECRET } -kvc ${ AZURE _KEY _VAULT _CERTIFICATE } -tr http://timestamp.digicert.com -v ' ${ filePath } ' ` ;
exec ( command , { shell : 'powershell.exe' } , ( e , stdout , stderr ) => {
if ( e instanceof Error ) {
console . log ( e ) ;
reject ( e ) ;
return ;
}
if ( stderr ) {
reject ( new Error ( stderr ) ) ;
return ;
}
if ( stdout . indexOf ( 'Signing completed successfully' ) > - 1 ) {
// eslint-disable-next-line no-console
console . log ( stdout ) ;
resolve ( ) ;
} else {
reject ( new Error ( stdout ) ) ;
}
} ) ;
} ) ;
} ;
2022-03-08 16:49:08 +00:00
module . exports = config ;