diff --git a/.gitignore b/.gitignore index 83a749c..db70d42 100644 --- a/.gitignore +++ b/.gitignore @@ -14,6 +14,7 @@ pouch/*.webhapp # electron-builder out/ +electron-builder.yml # Diagnostic reports (https://nodejs.org/api/report.html) report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json diff --git a/kangaroo.config.ts b/kangaroo.config.ts index 6775503..95137ef 100644 --- a/kangaroo.config.ts +++ b/kangaroo.config.ts @@ -2,7 +2,8 @@ import { defineConfig } from "./src/main/defineConfig"; export default defineConfig({ appId: "kangaroo-electron", - productName: "electron.kangaroo.holochain", + productName: "org.holochain.kangaroo-electron", + version: "0.1.0", usePassword: true, bins: { holochain: { diff --git a/package.json b/package.json index cfe049e..5353883 100644 --- a/package.json +++ b/package.json @@ -1,8 +1,7 @@ { - "name": "replace-me", - "productName": "replace-me", - "version": "0.0.1", - "description": "My Electron application description", + "name": "____REPLACE____", + "version": "0.1.0", + "license": "CAL-1.0", "main": "./out/main/index.js", "scripts": { "start": "electron-vite preview", @@ -18,8 +17,6 @@ "build:linux": "yarn build && electron-builder --linux --config", "lint": "eslint --ext .ts,.tsx ." }, - "keywords": [], - "license": "CAL-1.0", "dependencies": { "@electron-toolkit/preload": "^3.0.1", "@electron-toolkit/utils": "^3.0.0", @@ -45,6 +42,7 @@ "electron-vite": "^2.3.0", "eslint": "^8.0.1", "eslint-plugin-import": "^2.25.0", + "js-yaml": "4.1.0", "make-dir-cli": "^3.1.0", "ncp": "^2.0.0", "rimraf": "^5.0.1", diff --git a/scripts/extend-deb-postinst.mjs b/scripts/extend-deb-postinst.mjs new file mode 100644 index 0000000..673baf6 --- /dev/null +++ b/scripts/extend-deb-postinst.mjs @@ -0,0 +1,110 @@ +/** + * This script extends the deb postinst script with the creation of an apparmor profile + * on Ubuntu 24.04 (https://github.com/electron/electron/issues/41066), repackages + * the deb file and then overwrites the latest-linux.yaml file with the new sha256 hash + */ +import yaml from 'js-yaml'; +import fs from 'fs'; +import crypto from 'crypto'; +import child_process from 'child_process'; + +const electronBuilderYaml = yaml.load(fs.readFileSync('electron-builder.yml', 'utf-8')); +const packageJson = JSON.parse(fs.readFileSync('package.json')); +const appId = electronBuilderYaml.appId; +const productName = electronBuilderYaml.productName; +const appVersion = packageJson.version; +const debFileName = `${appId}_${appVersion}_amd64.deb`; +const debFilePath = `dist/${debFileName}`; + +const fileBytesBefore = fs.readFileSync(debFilePath); +const hasher1 = crypto.createHash('sha512'); +hasher1.update(fileBytesBefore); +const sha512_before = hasher1.digest('base64'); +console.log('sha512 before modification: ', sha512_before); +console.log('fileSize before modification: ', fileBytesBefore.length); + +const unpackDirectory = `dist/modified-deb`; +console.log('Unpacking deb file for subsequent modification. This may take a while...'); +child_process.execSync(`dpkg-deb -R ${debFilePath} ${unpackDirectory}`); +console.log('.deb file unpacked.'); + +// Modify the postinst script +const posinstPath = `${unpackDirectory}/DEBIAN/postinst`; +const postinstScript = fs.readFileSync(posinstPath, 'utf-8'); +const postinstScriptModified = postinstScript.replace( + '# SUID chrome-sandbox for Electron 5+', + ` +if [ -e /etc/lsb-release ]; then + + while IFS='=' read -r key value + + do + if [ "$key" == "DISTRIB_RELEASE" ]; then + release_version=$value + fi + done < /etc/lsb-release + + + if [ $release_version == "24.04" ]; then + + # chown the sandbox on Ubuntu 24.04 + chown root '/opt/${productName}/chrome-sandbox' || true + + # add AppArmor profile on Ubuntu 24.04 + profile_content="# This profile allows everything and only exists to give the +# application a name instead of having the label "unconfined" + +abi , +include + +profile ${appId} \\"/opt/${productName}/${appId}\\" flags=(unconfined) { + userns, + + # Site-specific additions and overrides. See local/README for details. + include if exists +}" + + echo "$profile_content" > /etc/apparmor.d/${appId} + + systemctl reload apparmor.service + + fi + +fi + +# SUID chrome-sandbox for Electron 5+ +`, +); + +fs.writeFileSync(posinstPath, postinstScriptModified); + +console.log('Wrote modified postinst script: ', postinstScriptModified); + +// Package modified .deb file +console.log('Re-packaging modified deb file...'); +child_process.execSync(`dpkg-deb -b ${unpackDirectory} ${debFilePath}`); +console.log('Modified deb file packaged.'); + +// Modify sha512 hashes of latest-linux.yaml +const fileBytes = fs.readFileSync(debFilePath); +const hasher = crypto.createHash('sha512'); +hasher.update(fileBytes); +const sha512 = hasher.digest('base64'); + +const latestYaml = yaml.load(fs.readFileSync('dist/latest-linux.yml')); + +console.log('latestYaml before modification:\n', latestYaml); + +const files = latestYaml.files.filter((file) => file.url !== debFileName); +files.push({ + url: debFileName, + sha512, + size: fileBytes.length, +}); + +latestYaml.files = files; + +console.log('\n\nsha512: ', sha512); +console.log('\n\nlatestYaml after modification: ', latestYaml); + +fs.writeFileSync('latest-linux.yml', yaml.dump(latestYaml, { lineWidth: -1 }), 'utf-8'); diff --git a/scripts/fetch-binaries.js b/scripts/fetch-binaries.js index 964e4b2..1c67a58 100644 --- a/scripts/fetch-binaries.js +++ b/scripts/fetch-binaries.js @@ -7,14 +7,8 @@ const childProcess = require('child_process'); tsNode.register(); -// eslint-disable-next-line import/no-unresolved -// import kangarooConfig from '../kangaroo.config.ts'; -// eslint-disable-next-line @typescript-eslint/no-var-requires -// export const kangarooConfig = require('kangaroo.config.ts').default; -// eslint-disable-next-line @typescript-eslint/no-var-requires const kangarooConfig = require(path.join(process.cwd(), 'kangaroo.config.ts')).default; - const binariesDir = path.join('resources', 'bins'); fs.mkdirSync(binariesDir, { recursive: true }); diff --git a/scripts/write-builder-config.js b/scripts/write-builder-config.js new file mode 100644 index 0000000..af0ed2f --- /dev/null +++ b/scripts/write-builder-config.js @@ -0,0 +1,43 @@ +/* eslint-disable @typescript-eslint/no-var-requires */ +const jsYaml = require("js-yaml"); +const fs = require("fs"); +const path = require("path"); +const tsNode = require("ts-node"); + +tsNode.register(); + +const kangarooConfig = require(path.join( + process.cwd(), + "kangaroo.config.ts" +)).default; + +// CHECK THAT NO DEFAULT VALUES ANYMORE +if (kangarooConfig.appId === "kangaroo-electron") + throw new Error( + "The appId field in 'kangaroo.config.ts' is still using the default value. Change it to the appId of your app." + ); +if (kangarooConfig.productName === "org.holochain.kangaroo-electron") + throw new Error( + "The productName field in 'kangaroo.config.ts' is still using the default value. Change it to the productName of your app." + ); + +// Overwrite package.json values +const packageJsonString = fs.readFileSync('package.json', 'utf-8'); +const packageJSON = JSON.parse(packageJsonString); +packageJSON.name = kangarooConfig.appId; +packageJSON.version = kangarooConfig.version; + +fs.writeFileSync('package.json', JSON.stringify(packageJSON, undefined, 2), 'utf-8'); + +const eletronBuilderYml = jsYaml.load( + fs.readFileSync( + path.join(process.cwd(), "templates", "electron-builder-template.yml") + ) +); + +eletronBuilderYml.appId = kangarooConfig.appId; +eletronBuilderYml.productName = kangarooConfig.productName; +eletronBuilderYml.win.executableName = kangarooConfig.appId; + +fs.writeFileSync('electron-builder.yml', jsYaml.dump(eletronBuilderYml), 'utf-8'); + diff --git a/src/main/types.ts b/src/main/types.ts index ebde8fb..2bc10ec 100644 --- a/src/main/types.ts +++ b/src/main/types.ts @@ -6,12 +6,27 @@ export type KangarooConfig = { * the storage location of data. Should not contain whitespaces. * Typically, this is an id in reverse domain notation, like * "org.holochain.kangaroo". + * + * Will also be used as the package name in package.json. */ appId: string, /** - * The name of the app as displayed in places such as the Window bar + * The name of the app as displayed in places such as the Window bar. */ productName: string, + /** + * This version will overwrite the version in package.json. + * **IMPORTANT** Breaking version semver changes here will lead to + * the app using a new, independent conductor. + * + * Examples: + * 0.0.1 -> 0.0.2: Breaking change; + * 0.1.0 -> 0.2.0: Breaking change; + * 0.1.0 -> 0.1.1: *No* breaking change; + * 0.13.0-alpha.0 -> 0.13.0-beta.0: Breaking change; + * 0.13.0-alpha.0 -> 0.13.0-alpha.1: *No* breaking change; + */ + version: string, /** * Whether or not the app should have the user set up a password. */ diff --git a/electron-builder.yml b/templates/electron-builder-template.yml similarity index 87% rename from electron-builder.yml rename to templates/electron-builder-template.yml index dc96393..bebe414 100644 --- a/electron-builder.yml +++ b/templates/electron-builder-template.yml @@ -1,5 +1,5 @@ -appId: electron.kangaroo.test -productName: Holochain Kangaroo Electron +appId: ____REPLACE____ +productName: ____REPLACE____ directories: buildResources: build files: @@ -7,9 +7,8 @@ files: - out asarUnpack: - resources/** -afterSign: scripts/notarize.js win: - executableName: holochain-kangaroo-electron + executableName: ____REPLACE____ nsis: artifactName: ${name}-${version}-setup.${ext} shortcutName: ${productName} @@ -29,7 +28,7 @@ dmg: linux: target: - AppImage - # - deb + - deb # - snap maintainer: electronjs.org category: Utility diff --git a/yarn.lock b/yarn.lock index 82ab1d5..f89433a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2525,7 +2525,7 @@ js-tokens@^4.0.0: resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== -js-yaml@^4.1.0: +js-yaml@4.1.0, js-yaml@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==