From 3aed0b5a35f242d1e2550c516e29a497b1b3371f Mon Sep 17 00:00:00 2001 From: develar Date: Thu, 9 Feb 2017 18:19:58 +0100 Subject: [PATCH] feat(snap): custom plugs Close #1226 --- docs/Options.md | 5 +- .../src/options/linuxOptions.ts | 26 ++- .../src/options/macOptions.ts | 5 +- packages/electron-builder/src/targets/snap.ts | 29 ++- .../electron-publisher-s3/src/s3Publisher.ts | 8 +- test/out/linux/__snapshots__/snapTest.js.snap | 203 ++++++++++++++++++ test/src/linux/snapTest.ts | 26 ++- 7 files changed, 278 insertions(+), 24 deletions(-) create mode 100644 test/out/linux/__snapshots__/snapTest.js.snap diff --git a/docs/Options.md b/docs/Options.md index b0fc3af9e73..2f51ccda21b 100644 --- a/docs/Options.md +++ b/docs/Options.md @@ -194,7 +194,7 @@ See [NSIS target notes](https://github.com/electron-userland/electron-builder/wi ### `pkg` macOS Product Archive Options | Name | Description | --- | --- -| scripts |

The scripts directory, relative to build (build resources directory). Defaults to build/pkg-scripts. [Scripting in installer packages](http://macinstallers.blogspot.de/2012/07/scripting-in-installer-packages.html) The scripts can be in any language so long as the files are marked executable and have the appropriate shebang indicating the path to the interpreter.

Scripts are required to be executable (chmod +x file). It is not checked and corrected by electron-builder.

+| scripts |

The scripts directory, relative to build (build resources directory). Defaults to build/pkg-scripts. See [Scripting in installer packages](http://macinstallers.blogspot.de/2012/07/scripting-in-installer-packages.html). The scripts can be in any language so long as the files are marked executable and have the appropriate shebang indicating the path to the interpreter.

Scripts are required to be executable (chmod +x file).

| installLocation | The install location. Defaults to `/Applications`. @@ -246,7 +246,8 @@ To use Squirrel.Windows please install `electron-builder-squirrel-windows` depen | summary | The 78 character long summary. Defaults to [productName](#AppMetadata-productName). | grade |

The quality grade of the snap. It can be either devel (i.e. a development version of the snap, so not to be published to the “stable” or “candidate” channels) or “stable” (i.e. a stable release or release candidate, which can be released to all channels). Defaults to stable.

| assumes | The list of features that must be supported by the core in order for this snap to install. -| stagePackages |

The list of Ubuntu packages to use that are needed to support the app part creation. Like depends for deb. Defaults to ["libnotify4", "libappindicator1", "libxtst6", "libnss3", "libxss1", "fontconfig-config", "gconf2", "libasound2"].

+| stagePackages |

The list of Ubuntu packages to use that are needed to support the app part creation. Like depends for deb. Defaults to ["libnotify4", "libappindicator1", "libxtst6", "libnss3", "libxss1", "fontconfig-config", "gconf2", "libasound2", "pulseaudio"].

If list contains default, it will be replaced to default list, so, ["default", "foo"] can be used to add custom package foo in addition to defaults.

+| plugs |

The list of [plugs](https://snapcraft.io/docs/reference/interfaces). Defaults to ["home", "x11", "unity7", "browser-support", "network", "gsettings", "pulseaudio", "opengl"].

If list contains default, it will be replaced to default list, so, ["default", "foo"] can be used to add custom plug foo in addition to defaults.

| ubuntuAppPlatformContent |

Specify ubuntu-app-platform1 to use [ubuntu-app-platform](https://insights.ubuntu.com/2016/11/17/how-to-create-snap-packages-on-qt-applications/). Snap size will be greatly reduced, but it is not recommended for now because “the snaps must be connected before running uitk-gallery for the first time”.

diff --git a/packages/electron-builder/src/options/linuxOptions.ts b/packages/electron-builder/src/options/linuxOptions.ts index 60181eeeae4..b7e661bd4d9 100644 --- a/packages/electron-builder/src/options/linuxOptions.ts +++ b/packages/electron-builder/src/options/linuxOptions.ts @@ -93,35 +93,45 @@ export interface SnapOptions extends LinuxBuildOptions { /* The type of confinement supported by the snap. Can be either `devmode` (i.e. this snap doesn’t support running under confinement) or `strict` (i.e. full confinement supported via interfaces). Defaults to `strict`. */ - confinement?: "devmode" | "strict" | null + readonly confinement?: "devmode" | "strict" | null /* The 78 character long summary. Defaults to [productName](#AppMetadata-productName). */ - summary?: string | null + readonly summary?: string | null /* The quality grade of the snap. It can be either `devel` (i.e. a development version of the snap, so not to be published to the “stable” or “candidate” channels) or “stable” (i.e. a stable release or release candidate, which can be released to all channels). Defaults to `stable`. */ - grade?: "devel" | "stable" | null + readonly grade?: "devel" | "stable" | null /* The list of features that must be supported by the core in order for this snap to install. */ - assumes?: Array | null + readonly assumes?: Array | null /* The list of Ubuntu packages to use that are needed to support the `app` part creation. Like `depends` for `deb`. - Defaults to `["libnotify4", "libappindicator1", "libxtst6", "libnss3", "libxss1", "fontconfig-config", "gconf2", "libasound2"]`. + Defaults to `["libnotify4", "libappindicator1", "libxtst6", "libnss3", "libxss1", "fontconfig-config", "gconf2", "libasound2", "pulseaudio"]`. + + If list contains `default`, it will be replaced to default list, so, `["default", "foo"]` can be used to add custom package `foo` in addition to defaults. + */ + readonly stagePackages?: Array | null + + /* + The list of [plugs](https://snapcraft.io/docs/reference/interfaces). + Defaults to `["home", "x11", "unity7", "browser-support", "network", "gsettings", "pulseaudio", "opengl"]`. + + If list contains `default`, it will be replaced to default list, so, `["default", "foo"]` can be used to add custom plug `foo` in addition to defaults. */ - stagePackages?: Array | null + readonly plugs?: Array | null /* Specify `ubuntu-app-platform1` to use [ubuntu-app-platform](https://insights.ubuntu.com/2016/11/17/how-to-create-snap-packages-on-qt-applications/). Snap size will be greatly reduced, but it is not recommended for now because "the snaps must be connected before running uitk-gallery for the first time". */ - ubuntuAppPlatformContent?: string | null + readonly ubuntuAppPlatformContent?: string | null } /* @@ -131,5 +141,5 @@ export interface AppImageOptions extends LinuxBuildOptions { /* Whether to include required system libraries (`gconf2`, `libappindicator1`). Defaults to `false`. */ - includeRequiredLib?: boolean | null + readonly includeRequiredLib?: boolean | null } \ No newline at end of file diff --git a/packages/electron-builder/src/options/macOptions.ts b/packages/electron-builder/src/options/macOptions.ts index 56c71ec42c4..fb22828193f 100644 --- a/packages/electron-builder/src/options/macOptions.ts +++ b/packages/electron-builder/src/options/macOptions.ts @@ -66,10 +66,11 @@ export interface MacOptions extends PlatformSpecificBuildOptions { */ export interface PkgOptions { /* - The scripts directory, relative to `build` (build resources directory). Defaults to `build/pkg-scripts`. [Scripting in installer packages](http://macinstallers.blogspot.de/2012/07/scripting-in-installer-packages.html) + The scripts directory, relative to `build` (build resources directory). Defaults to `build/pkg-scripts`. + See [Scripting in installer packages](http://macinstallers.blogspot.de/2012/07/scripting-in-installer-packages.html). The scripts can be in any language so long as the files are marked executable and have the appropriate shebang indicating the path to the interpreter. - Scripts are required to be executable (`chmod +x file`). It is not checked and corrected by electron-builder. + Scripts are required to be executable (`chmod +x file`). */ readonly scripts?: string | null diff --git a/packages/electron-builder/src/targets/snap.ts b/packages/electron-builder/src/targets/snap.ts index 0b15f183804..9b03fc51b87 100644 --- a/packages/electron-builder/src/targets/snap.ts +++ b/packages/electron-builder/src/targets/snap.ts @@ -61,9 +61,7 @@ export default class SnapTarget extends Target { snap.apps = { [snap.name]: { command: `desktop-launch $SNAP/${packager.executableName}`, - plugs: [ - "home", "x11", "unity7", "browser-support", "network", "gsettings", "pulseaudio", "opengl", - ] + plugs: [replaceDefault(options.plugs, ["home", "x11", "unity7", "browser-support", "network", "gsettings", "pulseaudio", "opengl"])] } } @@ -81,10 +79,12 @@ export default class SnapTarget extends Target { // libxss1, libasound2, gconf2 - was "error while loading shared libraries: libXss.so.1" on Xubuntu 16.04 const isUseDocker = process.platform !== "linux" + + const defaultStagePackages = (isUseUbuntuPlatform ? ["libnss3"] : ["libnotify4", "libappindicator1", "libxtst6", "libnss3", "libxss1", "fontconfig-config", "gconf2", "libasound2", "pulseaudio"]) snap.parts = { app: { plugin: "dump", - "stage-packages": options.stagePackages || (isUseUbuntuPlatform ? ["libnss3"] : ["libnotify4", "libappindicator1", "libxtst6", "libnss3", "libxss1", "fontconfig-config", "gconf2", "libasound2"]), + "stage-packages": replaceDefault(options.stagePackages, defaultStagePackages), source: isUseDocker ? `/out/${path.basename(appOutDir)}` : appOutDir, after: isUseUbuntuPlatform ? ["extra", "desktop-ubuntu-app-platform"] : ["desktop-glib-only"] } @@ -97,6 +97,10 @@ export default class SnapTarget extends Target { } } + if (packager.packagerOptions.effectiveOptionComputed != null && await packager.packagerOptions.effectiveOptionComputed(snap)) { + return + } + const snapcraft = path.join(snapDir, "snapcraft.yaml") await writeFile(snapcraft, safeDump(snap, {lineWidth: 160})) @@ -123,4 +127,21 @@ export default class SnapTarget extends Target { } packager.dispatchArtifactCreated(resultFile, this) } +} + +function replaceDefault(inList: Array | n, defaultList: Array): Array { + if (inList == null) { + return defaultList + } + + const index = inList.indexOf("default") + if (index >= 0) { + let list = inList.slice(0, index) + list.push(...defaultList) + if (index != (inList.length - 1)) { + list.push(...inList.slice(index + 1)) + } + inList = list + } + return inList } \ No newline at end of file diff --git a/packages/electron-publisher-s3/src/s3Publisher.ts b/packages/electron-publisher-s3/src/s3Publisher.ts index 04ecf34cb48..6b5a47d7ef0 100644 --- a/packages/electron-publisher-s3/src/s3Publisher.ts +++ b/packages/electron-publisher-s3/src/s3Publisher.ts @@ -1,7 +1,7 @@ import { Publisher, PublishContext } from "electron-builder-publisher" import { S3Options } from "electron-builder-http/out/publishOptions" import { S3 } from "aws-sdk" -import { createReadStream, stat } from "fs-extra-p" +import { stat } from "fs-extra-p" import mime from "mime" import BluebirdPromise from "bluebird-lst-c" import { debug, isEmptyOrSpaces } from "electron-builder-util" @@ -30,13 +30,9 @@ export default class S3Publisher extends Publisher { const fileName = basename(file) const fileStat = await stat(file) return this.context.cancellationToken.trackPromise(new BluebirdPromise((resolve, reject, onCancel) => { - //noinspection JSUnusedLocalSymbols - const fileStream = createReadStream(file) - fileStream.on("error", reject) - const upload = this.s3.upload({ Bucket: this.info.bucket!, - Key: fileName, + Key: (this.info.path == null ? "" : `${this.info.path}/`) + fileName, ACL: this.info.acl || "public-read", Body: this.createReadStreamAndProgressBar(file, fileStat, this.createProgressBar(fileName, fileStat), reject), ContentLength: fileStat.size, diff --git a/test/out/linux/__snapshots__/snapTest.js.snap b/test/out/linux/__snapshots__/snapTest.js.snap new file mode 100644 index 00000000000..509a73e06b8 --- /dev/null +++ b/test/out/linux/__snapshots__/snapTest.js.snap @@ -0,0 +1,203 @@ +exports[`test default stagePackages 1`] = ` +Object { + "apps": Object { + "sep": Object { + "command": "desktop-launch $SNAP/sep", + "plugs": Array [ + Array [ + "home", + "x11", + "unity7", + "browser-support", + "network", + "gsettings", + "pulseaudio", + "opengl", + ], + ], + }, + }, + "confinement": "strict", + "description": "Test Application (test quite “ #378)", + "grade": "stable", + "icon": "setup/gui/icon.png", + "name": "sep", + "parts": Object { + "app": Object { + "after": Array [ + "desktop-glib-only", + ], + "plugin": "dump", + "source": "/out/linux-unpacked", + "stage-packages": Array [ + "libnotify4", + "libappindicator1", + "libxtst6", + "libnss3", + "libxss1", + "fontconfig-config", + "gconf2", + "libasound2", + "pulseaudio", + ], + }, + }, + "summary": "Sep", + "version": "1.1.0", +} +`; + +exports[`test default stagePackages 2`] = ` +Object { + "apps": Object { + "sep": Object { + "command": "desktop-launch $SNAP/sep", + "plugs": Array [ + Array [ + "home", + "x11", + "unity7", + "browser-support", + "network", + "gsettings", + "pulseaudio", + "opengl", + "custom", + ], + ], + }, + }, + "confinement": "strict", + "description": "Test Application (test quite “ #378)", + "grade": "stable", + "icon": "setup/gui/icon.png", + "name": "sep", + "parts": Object { + "app": Object { + "after": Array [ + "desktop-glib-only", + ], + "plugin": "dump", + "source": "/out/linux-unpacked", + "stage-packages": Array [ + "libnotify4", + "libappindicator1", + "libxtst6", + "libnss3", + "libxss1", + "fontconfig-config", + "gconf2", + "libasound2", + "pulseaudio", + "custom", + ], + }, + }, + "summary": "Sep", + "version": "1.1.0", +} +`; + +exports[`test default stagePackages 3`] = ` +Object { + "apps": Object { + "sep": Object { + "command": "desktop-launch $SNAP/sep", + "plugs": Array [ + Array [ + "custom", + "home", + "x11", + "unity7", + "browser-support", + "network", + "gsettings", + "pulseaudio", + "opengl", + ], + ], + }, + }, + "confinement": "strict", + "description": "Test Application (test quite “ #378)", + "grade": "stable", + "icon": "setup/gui/icon.png", + "name": "sep", + "parts": Object { + "app": Object { + "after": Array [ + "desktop-glib-only", + ], + "plugin": "dump", + "source": "/out/linux-unpacked", + "stage-packages": Array [ + "custom", + "libnotify4", + "libappindicator1", + "libxtst6", + "libnss3", + "libxss1", + "fontconfig-config", + "gconf2", + "libasound2", + "pulseaudio", + ], + }, + }, + "summary": "Sep", + "version": "1.1.0", +} +`; + +exports[`test default stagePackages 4`] = ` +Object { + "apps": Object { + "sep": Object { + "command": "desktop-launch $SNAP/sep", + "plugs": Array [ + Array [ + "foo1", + "home", + "x11", + "unity7", + "browser-support", + "network", + "gsettings", + "pulseaudio", + "opengl", + "foo2", + ], + ], + }, + }, + "confinement": "strict", + "description": "Test Application (test quite “ #378)", + "grade": "stable", + "icon": "setup/gui/icon.png", + "name": "sep", + "parts": Object { + "app": Object { + "after": Array [ + "desktop-glib-only", + ], + "plugin": "dump", + "source": "/out/linux-unpacked", + "stage-packages": Array [ + "foo1", + "libnotify4", + "libappindicator1", + "libxtst6", + "libnss3", + "libxss1", + "fontconfig-config", + "gconf2", + "libasound2", + "pulseaudio", + "foo2", + ], + }, + }, + "summary": "Sep", + "version": "1.1.0", +} +`; diff --git a/test/src/linux/snapTest.ts b/test/src/linux/snapTest.ts index c507e17008e..e8c3e1aef03 100644 --- a/test/src/linux/snapTest.ts +++ b/test/src/linux/snapTest.ts @@ -1,8 +1,8 @@ import { Platform } from "electron-builder" -import { app } from "../helpers/packTester" +import { app, assertPack } from "../helpers/packTester" import isCi from "is-ci" -if (!((isCi && process.platform === "linux") || process.env.SNAP_TEST === "true")) { +if (isCi ? process.platform !== "linux" : (process.env.SNAP_TEST == null && process.env.TEST_DIR != null)) { fit("Skip snapTest suite — not Linux CI or env SNAP_TEST not set to true", () => { console.warn("[SKIP] Skip snapTest suite — not Linux CI or env SNAP_TEST not set to true") }) @@ -30,3 +30,25 @@ test("snap", app({ name: "sep", }, })) + +test("default stagePackages", async () => { + for (const p of [["default"], ["default", "custom"], ["custom", "default"], ["foo1", "default", "foo2"]]) { + await assertPack("test-app-one", { + targets: Platform.LINUX.createTarget("snap"), + config: { + productName: "Sep", + snap: { + stagePackages: p, + plugs: p, + } + }, + appMetadata: { + name: "sep", + }, + effectiveOptionComputed: async (snap) => { + expect(snap).toMatchSnapshot() + return true + } + }) + } +})