From 2593a1f241aefbdfb0d98c4c64eeee944ba676ee Mon Sep 17 00:00:00 2001 From: Mike Maietta Date: Sat, 2 Nov 2024 16:30:08 -0700 Subject: [PATCH 1/5] chore: migrate documentation site from Netlify app to GHA w/ docker image (#8629) --- .../{docker-deploy.yml => deploy-docker.yml} | 0 .github/workflows/deploy-netlify.yml | 49 ++++++++++++++++++ .github/workflows/pr-netlify.yml | 50 +++++++++++++++++++ .../{semantic-pr.yml => pr-semantic.yml} | 0 mkdocs-dockerfile | 7 +-- 5 files changed, 101 insertions(+), 5 deletions(-) rename .github/workflows/{docker-deploy.yml => deploy-docker.yml} (100%) create mode 100644 .github/workflows/deploy-netlify.yml create mode 100644 .github/workflows/pr-netlify.yml rename .github/workflows/{semantic-pr.yml => pr-semantic.yml} (100%) diff --git a/.github/workflows/docker-deploy.yml b/.github/workflows/deploy-docker.yml similarity index 100% rename from .github/workflows/docker-deploy.yml rename to .github/workflows/deploy-docker.yml diff --git a/.github/workflows/deploy-netlify.yml b/.github/workflows/deploy-netlify.yml new file mode 100644 index 00000000000..422ed844020 --- /dev/null +++ b/.github/workflows/deploy-netlify.yml @@ -0,0 +1,49 @@ +name: 'Netlify Deploy - Release' + +on: + release: + types: ['published'] + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +permissions: + contents: read + statuses: write + +jobs: + deploy: + name: 'Deploy Release' + runs-on: ubuntu-latest + + steps: + - name: Checkout code repository + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4 + + - name: Install deps and audit + uses: ./.github/actions/pnpm + + - name: Build typdoc site + run: pnpm docs:all + + - uses: jsmrcaga/action-netlify-deploy@v2.3.0 + with: + NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }} + NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }} + NETLIFY_DEPLOY_MESSAGE: "Prod deploy v${{ github.ref }}" + NETLIFY_DEPLOY_TO_PROD: true + install_command: "echo Skipping installing the dependencies" + build_command: "echo Skipping building the web files" + debug: true + build_directory: "site" + monorepo_package: "electron-builder" + + # Creates a status check with link to preview + - name: Set Status check on commit + uses: guibranco/github-status-action-v2@v1.1.13 + with: + authToken: ${{ secrets.GITHUB_TOKEN }} + state: success + context: Netlify Documentation Site preview + description: Production - Click "details" + target_url: ${{ env.NETLIFY_PREVIEW_URL }} + sha: ${{github.event.pull_request.head.sha || github.sha}} \ No newline at end of file diff --git a/.github/workflows/pr-netlify.yml b/.github/workflows/pr-netlify.yml new file mode 100644 index 00000000000..973060ec630 --- /dev/null +++ b/.github/workflows/pr-netlify.yml @@ -0,0 +1,50 @@ +name: 'Netlify Deploy - PR' + +on: + pull_request: + types: ['opened', 'edited', 'synchronize'] + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +permissions: + contents: read + statuses: write + +jobs: + deploy: + name: 'Deploy PR' + runs-on: ubuntu-latest + + steps: + - name: Checkout code repository + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4 + + - name: Install deps and audit + uses: ./.github/actions/pnpm + + - name: Build typdoc site + run: pnpm docs:all + + # Sets the branch name as environment variable + - uses: nelonoel/branch-name@v1.0.1 + - uses: jsmrcaga/action-netlify-deploy@v2.3.0 + with: + NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }} + NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }} + deploy_alias: ${{ env.BRANCH_NAME }} + install_command: "echo Skipping installing the dependencies" + build_command: "echo Skipping building the web files" + debug: true + build_directory: "site" + monorepo_package: "electron-builder" + + # Creates a status check with link to preview + - name: Set Status check on commit + uses: guibranco/github-status-action-v2@v1.1.13 + with: + authToken: ${{ secrets.GITHUB_TOKEN }} + state: success + context: Netlify Documentation Site preview + description: Development - Click "details" + target_url: ${{ env.NETLIFY_PREVIEW_URL }} + sha: ${{github.event.pull_request.head.sha || github.sha}} \ No newline at end of file diff --git a/.github/workflows/semantic-pr.yml b/.github/workflows/pr-semantic.yml similarity index 100% rename from .github/workflows/semantic-pr.yml rename to .github/workflows/pr-semantic.yml diff --git a/mkdocs-dockerfile b/mkdocs-dockerfile index 689caaf2b58..d8f8c1153e7 100644 --- a/mkdocs-dockerfile +++ b/mkdocs-dockerfile @@ -1,5 +1,2 @@ -FROM squidfunk/mkdocs-material -RUN pip install mkdocs-include-markdown-plugin -RUN pip install pymdown-extensions -RUN pip install pygments -RUN pip install markdown-include +FROM squidfunk/mkdocs-material:9.5 +RUN pip install mkdocs-include-markdown-plugin pymdown-extensions pygments markdown-include From b06c5effd35051c6b953696aec90b68a67456bed Mon Sep 17 00:00:00 2001 From: Mike Maietta Date: Sat, 2 Nov 2024 17:43:42 -0700 Subject: [PATCH 2/5] chore(docs): fixing indentation of typedoc and TOC depth/padding (#8657) --- mkdocs.yml | 3 +++ pages/appimage.md | 2 +- pages/appx.md | 2 +- pages/auto-update.md | 2 +- pages/configuration.md | 10 ++++++---- pages/contents.md | 4 ++-- pages/dmg.md | 2 +- pages/linux.md | 6 +++--- pages/mac.md | 4 ++-- pages/mas.md | 2 +- pages/msi-wrapped.md | 2 +- pages/msi.md | 2 +- pages/nsis.md | 2 +- pages/pkg.md | 2 +- pages/publish.md | 20 +++++++------------- pages/snap.md | 2 +- pages/squirrel-windows.md | 2 +- pages/stylesheets/autowidth.css | 2 +- pages/tutorials/adding-electron-fuses.md | 2 +- pages/win.md | 2 +- typedoc.config.js | 2 -- 21 files changed, 37 insertions(+), 40 deletions(-) diff --git a/mkdocs.yml b/mkdocs.yml index aa719e9b6ed..6ab914d6e4a 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -68,9 +68,12 @@ markdown_extensions: - pymdownx.tilde - toc: permalink: true + toc_depth: 5 - markdown_include.include: base_path : './docs/' encoding : 'utf-8' + # headingOffset : 2 + inheritHeadingDepth : true plugins: - search diff --git a/pages/appimage.md b/pages/appimage.md index e1801cef698..4bf98a20c65 100644 --- a/pages/appimage.md +++ b/pages/appimage.md @@ -5,4 +5,4 @@ The top-level [appImage](configuration.md#appImage) key contains set of options ## Configuration -{!./app-builder-lib.Interface.AppImageOptions.md!} + {!./app-builder-lib.Interface.AppImageOptions.md!} diff --git a/pages/appx.md b/pages/appx.md index a3eedcf7751..bdfaf662f03 100644 --- a/pages/appx.md +++ b/pages/appx.md @@ -52,4 +52,4 @@ If you use self-signed certificate, you need to add it to "Trusted People". See ## Configuration -{!./app-builder-lib.Interface.AppXOptions.md!} \ No newline at end of file + {!./app-builder-lib.Interface.AppXOptions.md!} \ No newline at end of file diff --git a/pages/auto-update.md b/pages/auto-update.md index c706df9a75c..bf835357c1f 100644 --- a/pages/auto-update.md +++ b/pages/auto-update.md @@ -213,4 +213,4 @@ Emitted on progress. ## UpdateInfo -{!./electron-updater.Interface.UpdateInfo.md!} + {!./electron-updater.Interface.UpdateInfo.md!} diff --git a/pages/configuration.md b/pages/configuration.md index f25f88ef54d..edae45353bc 100644 --- a/pages/configuration.md +++ b/pages/configuration.md @@ -36,7 +36,7 @@ Env file `electron-builder.env` in the current dir ([example](https://github.com ### Common Configuration -{!./app-builder-lib.Interface.CommonConfiguration.md!} + {!./app-builder-lib.Interface.CommonConfiguration.md!} --- @@ -46,12 +46,12 @@ Following options can be set also per platform (top-level keys [mac](mac.md), [l ## Base Configuration -{!./app-builder-lib.Interface.PlatformSpecificBuildOptions.md!} + {!./app-builder-lib.Interface.PlatformSpecificBuildOptions.md!} ## Metadata Some standard fields should be defined in the `package.json`. -{!./app-builder-lib.Interface.Metadata.md!} + {!./app-builder-lib.Interface.Metadata.md!} ## Proton Native @@ -61,4 +61,6 @@ Currently, only macOS and Linux supported. ## Build Version Management `CFBundleVersion` (macOS) and `FileVersion` (Windows) will be set automatically to `version.build_number` on CI server (Travis, AppVeyor, CircleCI and Bamboo supported). -{!./hooks.md!} +## Build Hooks + + {!./hooks.md!} diff --git a/pages/contents.md b/pages/contents.md index 23eee2b797e..92594abec0a 100644 --- a/pages/contents.md +++ b/pages/contents.md @@ -1,7 +1,7 @@ ## File Contents -#{!./app-builder-lib.Interface.FilesBuildOptions.md!} + {!./app-builder-lib.Interface.FilesBuildOptions.md!} ## FileSet Configuration -#{!./app-builder-lib.Interface.FileSet.md!} \ No newline at end of file + {!./app-builder-lib.Interface.FileSet.md!} \ No newline at end of file diff --git a/pages/dmg.md b/pages/dmg.md index 2e52345e1cd..fa65fbb90a1 100644 --- a/pages/dmg.md +++ b/pages/dmg.md @@ -20,4 +20,4 @@ The contain file should have the following format: ## Configuration -{!./app-builder-lib.Interface.DmgOptions.md!} \ No newline at end of file + {!./app-builder-lib.Interface.DmgOptions.md!} \ No newline at end of file diff --git a/pages/linux.md b/pages/linux.md index a4ee09c7ea8..40e62db148d 100644 --- a/pages/linux.md +++ b/pages/linux.md @@ -2,13 +2,13 @@ The top-level [linux](configuration.md#linux) key contains set of options instru ## Base Linux Configuration -{!./app-builder-lib.Interface.LinuxConfiguration.md!} + {!./app-builder-lib.Interface.LinuxConfiguration.md!} ## Debian Package Options The top-level [deb](configuration.md#deb) key contains set of options instructing electron-builder on how it should build Debian package. -{!./app-builder-lib.Interface.DebOptions.md!} + {!./app-builder-lib.Interface.DebOptions.md!} All [LinuxTargetSpecificOptions](linux.md#linuxtargetspecificoptions-apk-freebsd-pacman-p5p-and-rpm-options) can be also specified in the `deb` to customize Debian package. @@ -16,5 +16,5 @@ All [LinuxTargetSpecificOptions](linux.md#linuxtargetspecificoptions-apk-freebsd The top-level `apk`, `freebsd`, `pacman`, `p5p` and `rpm` keys contains set of options instructing electron-builder on how it should build corresponding Linux target. -{!./app-builder-lib.Interface.LinuxTargetSpecificOptions.md!} + {!./app-builder-lib.Interface.LinuxTargetSpecificOptions.md!} diff --git a/pages/mac.md b/pages/mac.md index 761c8be3717..e1753a1f506 100644 --- a/pages/mac.md +++ b/pages/mac.md @@ -2,8 +2,8 @@ The top-level [mac](configuration.md#mac) key contains set of options instructin ## Configuration -{!./app-builder-lib.Interface.MacConfiguration.md!} + {!./app-builder-lib.Interface.MacConfiguration.md!} ## Notarize Configuration -{!./app-builder-lib.Interface.NotarizeNotaryOptions.md!} + {!./app-builder-lib.Interface.NotarizeNotaryOptions.md!} diff --git a/pages/mas.md b/pages/mas.md index d931f85d593..eb19e364b6b 100644 --- a/pages/mas.md +++ b/pages/mas.md @@ -3,5 +3,5 @@ Inherits [macOS options](mac.md). ## Configuration -{!./app-builder-lib.Interface.MasConfiguration.md!} + {!./app-builder-lib.Interface.MasConfiguration.md!} diff --git a/pages/msi-wrapped.md b/pages/msi-wrapped.md index 8fce0f85fa4..4d1ac83d9bc 100644 --- a/pages/msi-wrapped.md +++ b/pages/msi-wrapped.md @@ -1,3 +1,3 @@ ## Configuration -{!./app-builder-lib.Interface.MsiWrappedOptions.md!} \ No newline at end of file + {!./app-builder-lib.Interface.MsiWrappedOptions.md!} \ No newline at end of file diff --git a/pages/msi.md b/pages/msi.md index 92f9e2aac05..0bd4738a414 100644 --- a/pages/msi.md +++ b/pages/msi.md @@ -1,3 +1,3 @@ ## Configuration -{!./app-builder-lib.Interface.MsiOptions.md!} \ No newline at end of file + {!./app-builder-lib.Interface.MsiOptions.md!} \ No newline at end of file diff --git a/pages/nsis.md b/pages/nsis.md index b2cbb3da2f9..f37572a8b8c 100644 --- a/pages/nsis.md +++ b/pages/nsis.md @@ -151,4 +151,4 @@ For portable app, following environment variables are available: ## Configuration -{!./app-builder-lib.Interface.NsisOptions.md!} + {!./app-builder-lib.Interface.NsisOptions.md!} diff --git a/pages/pkg.md b/pages/pkg.md index 48ca56ceedf..9775f5b9616 100644 --- a/pages/pkg.md +++ b/pages/pkg.md @@ -2,4 +2,4 @@ The top-level [pkg](configuration.md#pkg) key contains set of options instructin ## Configuration -{!./app-builder-lib.Interface.PkgOptions.md!} \ No newline at end of file + {!./app-builder-lib.Interface.PkgOptions.md!} \ No newline at end of file diff --git a/pages/publish.md b/pages/publish.md index 5d7a1b4fb45..d48327c6348 100644 --- a/pages/publish.md +++ b/pages/publish.md @@ -117,29 +117,23 @@ Detected automatically using: # Publishers ## Bitbucket -{!./builder-util-runtime.Interface.BitbucketOptions.md!} + {!./builder-util-runtime.Interface.BitbucketOptions.md!} ## Github - -{!./builder-util-runtime.Interface.GithubOptions.md!} + {!./builder-util-runtime.Interface.GithubOptions.md!} ## Keygen - -{!./builder-util-runtime.Interface.KeygenOptions.md!} + {!./builder-util-runtime.Interface.KeygenOptions.md!} ## S3 - -{!./builder-util-runtime.Interface.S3Options.md!} + {!./builder-util-runtime.Interface.S3Options.md!} ## Snap Store - -{!./builder-util-runtime.Interface.SnapStoreOptions.md!} + {!./builder-util-runtime.Interface.SnapStoreOptions.md!} ## Spaces - -{!./builder-util-runtime.Interface.SpacesOptions.md!} + {!./builder-util-runtime.Interface.SpacesOptions.md!} ## BYO Generic (create-your-own) - (And maybe submit it upstream in a PR!) -{!./builder-util-runtime.Interface.GenericServerOptions.md!} \ No newline at end of file + {!./builder-util-runtime.Interface.GenericServerOptions.md!} \ No newline at end of file diff --git a/pages/snap.md b/pages/snap.md index c312f072e09..32dd1de4cc6 100644 --- a/pages/snap.md +++ b/pages/snap.md @@ -2,4 +2,4 @@ The top-level [snap](configuration.md#snap) key contains set of options instruct ## Configuration -{!./app-builder-lib.Interface.SnapOptions.md!} \ No newline at end of file + {!./app-builder-lib.Interface.SnapOptions.md!} \ No newline at end of file diff --git a/pages/squirrel-windows.md b/pages/squirrel-windows.md index e28a6747988..415e6144a46 100644 --- a/pages/squirrel-windows.md +++ b/pages/squirrel-windows.md @@ -9,4 +9,4 @@ Your app must be able to handle Squirrel.Windows startup events that occur durin ## Configuration -{!./app-builder-lib.Interface.SquirrelWindowsOptions.md!} \ No newline at end of file + {!./app-builder-lib.Interface.SquirrelWindowsOptions.md!} \ No newline at end of file diff --git a/pages/stylesheets/autowidth.css b/pages/stylesheets/autowidth.css index b736eb732b4..b128fe66cf1 100644 --- a/pages/stylesheets/autowidth.css +++ b/pages/stylesheets/autowidth.css @@ -7,4 +7,4 @@ } /* Hide TOC elements less than h3 */ -.md-nav--secondary .md-nav__list .md-nav__list .md-nav__list { display: none } \ No newline at end of file +/* .md-nav--secondary .md-nav__list .md-nav__list .md-nav__list { display: none } */ \ No newline at end of file diff --git a/pages/tutorials/adding-electron-fuses.md b/pages/tutorials/adding-electron-fuses.md index 6c5b9415deb..73f3ad73c66 100644 --- a/pages/tutorials/adding-electron-fuses.md +++ b/pages/tutorials/adding-electron-fuses.md @@ -56,4 +56,4 @@ npx @electron/fuses read --app /Applications/Foo.app ``` ## Typedoc -{!./app-builder-lib.Interface.FuseOptionsV1.md!} \ No newline at end of file + {!./app-builder-lib.Interface.FuseOptionsV1.md!} \ No newline at end of file diff --git a/pages/win.md b/pages/win.md index 1cfb658bf67..79057412111 100644 --- a/pages/win.md +++ b/pages/win.md @@ -94,4 +94,4 @@ VirtualBox is not supported by electron-builder for now, so, you need to setup b ## Configuration -{!./app-builder-lib.Interface.WindowsConfiguration.md!} + {!./app-builder-lib.Interface.WindowsConfiguration.md!} diff --git a/typedoc.config.js b/typedoc.config.js index be7f08a8f85..ed46f65bed0 100644 --- a/typedoc.config.js +++ b/typedoc.config.js @@ -49,7 +49,5 @@ module.exports = { private: false, inherited: false, external: false, - "@alpha": false, - "@beta": false, }, } From df07101305b24a62731f6b4359228c508c5c76c7 Mon Sep 17 00:00:00 2001 From: Alex Kozack Date: Mon, 4 Nov 2024 17:59:31 +0200 Subject: [PATCH 3/5] docs: update vite-electron-builder boilerplate description (#8658) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 7cb491884d0..02534c6cabb 100644 --- a/README.md +++ b/README.md @@ -193,7 +193,7 @@ builder.build({ * [electron-boilerplate](https://github.com/szwacz/electron-boilerplate) A minimalistic yet comprehensive boilerplate application. * [Vue CLI 3 plugin for Electron](https://nklayman.github.io/vue-cli-plugin-electron-builder) A Vue CLI 3 plugin for Electron with no required configuration. * [electron-vue-vite](https://github.com/caoxiemeihao/electron-vue-vite) A real simple Electron + Vue3 + Vite5 boilerplate. -* [vite-electron-builder](https://github.com/cawa-93/vite-electron-builder) Secure boilerplate for Electron app based on Vite. TypeScript + Vue/React/Angular/Svelte/Vanilla +* [vite-electron-builder](https://github.com/cawa-93/vite-electron-builder) Secure boilerplate for Electron app based on Vite. Supports multiple frameworks. ## Debug From fb26f6ae32503df46523f5e986ce40f3e3f8dfff Mon Sep 17 00:00:00 2001 From: Mike Maietta Date: Tue, 5 Nov 2024 10:17:32 -0800 Subject: [PATCH 4/5] fix: docker build script unable to build node 18 image (#8665) --- .changeset/tame-buckets-drum.md | 5 +++++ docker/build.sh | 6 ++++-- 2 files changed, 9 insertions(+), 2 deletions(-) create mode 100644 .changeset/tame-buckets-drum.md diff --git a/.changeset/tame-buckets-drum.md b/.changeset/tame-buckets-drum.md new file mode 100644 index 00000000000..55a45c2a0a8 --- /dev/null +++ b/.changeset/tame-buckets-drum.md @@ -0,0 +1,5 @@ +--- + +--- + +chore: minor semver update to node in docker images diff --git a/docker/build.sh b/docker/build.sh index 25c2dd10239..1fb0c451093 100755 --- a/docker/build.sh +++ b/docker/build.sh @@ -9,14 +9,16 @@ docker build -t electronuserland/builder:base -t "electronuserland/builder:base- ## NOTE: Order the latest to oldest versions. The most recent node LTS should be tagged as the latest image # Node 20 -docker build --build-arg NODE_VERSION=20.15.1 --build-arg IMAGE_VERSION=base-$DATE -t electronuserland/builder:20 -t "electronuserland/builder:20-$DATE" -t electronuserland/builder:latest docker/node +docker build --build-arg NODE_VERSION=20.18.0 --build-arg IMAGE_VERSION=base-$DATE -t electronuserland/builder:20 -t "electronuserland/builder:20-$DATE" -t electronuserland/builder:latest docker/node docker build --build-arg IMAGE_VERSION=20-$DATE -t electronuserland/builder:20-wine -t "electronuserland/builder:20-wine-$DATE" -t electronuserland/builder:wine docker/wine docker build --build-arg IMAGE_VERSION=20-wine-$DATE -t electronuserland/builder:20-wine-mono -t "electronuserland/builder:20-wine-mono-$DATE" -t electronuserland/builder:wine-mono docker/wine-mono docker build --build-arg IMAGE_VERSION=20-wine-$DATE -t electronuserland/builder:20-wine-chrome -t "electronuserland/builder:20-wine-chrome-$DATE" -t electronuserland/builder:wine-chrome docker/wine-chrome # Node 18 -docker build --build-arg NODE_VERSION=18.18.2 --build-arg IMAGE_VERSION=18-$DATE -t electronuserland/builder:18-wine -t "electronuserland/builder:18-wine-$DATE" docker/wine +docker build --build-arg NODE_VERSION=18.20.4 --build-arg IMAGE_VERSION=base-$DATE -t electronuserland/builder:18 -t "electronuserland/builder:18-$DATE" docker/node + +docker build --build-arg IMAGE_VERSION=18-$DATE -t electronuserland/builder:18-wine -t "electronuserland/builder:18-wine-$DATE" docker/wine docker build --build-arg IMAGE_VERSION=18-wine-$DATE -t electronuserland/builder:18-wine-mono -t "electronuserland/builder:18-wine-mono-$DATE" docker/wine-mono docker build --build-arg IMAGE_VERSION=18-wine-$DATE -t electronuserland/builder:18-wine-chrome -t "electronuserland/builder:18-wine-chrome-$DATE" docker/wine-chrome From 88cc0b06dba22139721fd1e04f6a1cf2d447edbd Mon Sep 17 00:00:00 2001 From: Mike Maietta Date: Tue, 5 Nov 2024 10:38:48 -0800 Subject: [PATCH 5/5] feat: add AppArmor profile to FPM targets to pair with `afterInstall` and `afterRemove` template scripts (#8636) --- .changeset/mighty-forks-pump.md | 5 +++ packages/app-builder-lib/scheme.json | 18 ++++++++++ .../src/options/linuxOptions.ts | 10 ++++++ .../app-builder-lib/src/targets/FpmTarget.ts | 34 ++++++++++++------ .../templates/linux/after-install.tpl | 27 ++++++++++++++ .../templates/linux/after-remove.tpl | 7 ++++ .../templates/linux/apparmor-profile.tpl | 9 +++++ test/snapshots/PublishManagerTest.js.snap | 1 + test/snapshots/linux/debTest.js.snap | 35 +++++++++++++++++++ 9 files changed, 135 insertions(+), 11 deletions(-) create mode 100644 .changeset/mighty-forks-pump.md create mode 100644 packages/app-builder-lib/templates/linux/apparmor-profile.tpl diff --git a/.changeset/mighty-forks-pump.md b/.changeset/mighty-forks-pump.md new file mode 100644 index 00000000000..8feb9f0494b --- /dev/null +++ b/.changeset/mighty-forks-pump.md @@ -0,0 +1,5 @@ +--- +"app-builder-lib": minor +--- + +feat: add support for AppArmor with template profile and configuration property diff --git a/packages/app-builder-lib/scheme.json b/packages/app-builder-lib/scheme.json index 9a438419de4..8021f5a9fea 100644 --- a/packages/app-builder-lib/scheme.json +++ b/packages/app-builder-lib/scheme.json @@ -519,12 +519,21 @@ "additionalProperties": false, "properties": { "afterInstall": { + "description": "File path to script to be passed to FPM for `--after-install` arg.", "type": [ "null", "string" ] }, "afterRemove": { + "description": "File path to script to be passed to FPM for `--after-remove` arg.", + "type": [ + "null", + "string" + ] + }, + "appArmorProfile": { + "description": "File path to custom AppArmor profile (Ubuntu 24+)", "type": [ "null", "string" @@ -2050,12 +2059,21 @@ "additionalProperties": false, "properties": { "afterInstall": { + "description": "File path to script to be passed to FPM for `--after-install` arg.", "type": [ "null", "string" ] }, "afterRemove": { + "description": "File path to script to be passed to FPM for `--after-remove` arg.", + "type": [ + "null", + "string" + ] + }, + "appArmorProfile": { + "description": "File path to custom AppArmor profile (Ubuntu 24+)", "type": [ "null", "string" diff --git a/packages/app-builder-lib/src/options/linuxOptions.ts b/packages/app-builder-lib/src/options/linuxOptions.ts index 77e4882cb36..8157174c20f 100644 --- a/packages/app-builder-lib/src/options/linuxOptions.ts +++ b/packages/app-builder-lib/src/options/linuxOptions.ts @@ -122,8 +122,18 @@ export interface LinuxTargetSpecificOptions extends CommonLinuxOptions, TargetSp readonly vendor?: string | null readonly maintainer?: string | null + /** + * File path to script to be passed to FPM for `--after-install` arg. + */ readonly afterInstall?: string | null + /** + * File path to script to be passed to FPM for `--after-remove` arg. + */ readonly afterRemove?: string | null + /** + * File path to custom AppArmor profile (Ubuntu 24+) + */ + readonly appArmorProfile?: string | null /** * *Advanced only* The [fpm](https://fpm.readthedocs.io/en/latest/cli-reference.html) options. diff --git a/packages/app-builder-lib/src/targets/FpmTarget.ts b/packages/app-builder-lib/src/targets/FpmTarget.ts index 46baf32e8c6..2ad603bc5a8 100644 --- a/packages/app-builder-lib/src/targets/FpmTarget.ts +++ b/packages/app-builder-lib/src/targets/FpmTarget.ts @@ -1,6 +1,6 @@ import { Arch, executeAppBuilder, getArchSuffix, log, TmpDir, toLinuxArchString, use, serializeToYaml, asArray } from "builder-util" import { unlinkIfExists } from "builder-util" -import { outputFile, stat } from "fs-extra" +import { copyFile, outputFile, stat } from "fs-extra" import { mkdir, readFile } from "fs/promises" import * as path from "path" import { smarten } from "../appInfo" @@ -26,10 +26,16 @@ interface FpmOptions { url: string } +interface ScriptFiles { + afterRemove: string + afterInstall: string + appArmor: string +} + export default class FpmTarget extends Target { readonly options: LinuxTargetSpecificOptions = { ...this.packager.platformSpecificBuildOptions, ...(this.packager.config as any)[this.name] } - private readonly scriptFiles: Promise> + private readonly scriptFiles: Promise constructor( name: string, @@ -42,7 +48,7 @@ export default class FpmTarget extends Target { this.scriptFiles = this.createScripts() } - private async createScripts(): Promise> { + private async createScripts(): Promise { const defaultTemplatesDir = getTemplatePath("linux") const packager = this.packager @@ -61,10 +67,11 @@ export default class FpmTarget extends Target { return path.resolve(packager.projectDir, value) } - return await Promise.all([ - writeConfigFile(packager.info.tempDirManager, getResource(this.options.afterInstall, "after-install.tpl"), templateOptions), - writeConfigFile(packager.info.tempDirManager, getResource(this.options.afterRemove, "after-remove.tpl"), templateOptions), - ]) + return { + afterInstall: await writeConfigFile(packager.info.tempDirManager, getResource(this.options.afterInstall, "after-install.tpl"), templateOptions), + afterRemove: await writeConfigFile(packager.info.tempDirManager, getResource(this.options.afterRemove, "after-remove.tpl"), templateOptions), + appArmor: await writeConfigFile(packager.info.tempDirManager, getResource(this.options.appArmorProfile, "apparmor-profile.tpl"), templateOptions), + } } checkOptions(): Promise { @@ -130,13 +137,13 @@ export default class FpmTarget extends Target { if (packager.packagerOptions.prepackaged != null) { await mkdir(this.outDir, { recursive: true }) } + const linuxDistType = packager.packagerOptions.prepackaged || path.join(this.outDir, `linux${getArchSuffix(arch)}-unpacked`) + const resourceDir = packager.getResourcesDir(linuxDistType) const publishConfig = this.supportsAutoUpdate(target) ? await getAppUpdatePublishConfiguration(packager, arch, false /* in any case validation will be done on publish */) : null if (publishConfig != null) { - const linuxDistType = this.packager.packagerOptions.prepackaged || path.join(this.outDir, `linux${getArchSuffix(arch)}-unpacked`) - const resourceDir = packager.getResourcesDir(linuxDistType) log.info({ resourceDir: log.filePath(resourceDir) }, `adding autoupdate files for: ${target}. (Beta feature)`) await outputFile(path.join(resourceDir, "app-update.yml"), serializeToYaml(publishConfig)) // Extra file needed for auto-updater to detect installation method @@ -144,6 +151,11 @@ export default class FpmTarget extends Target { } const scripts = await this.scriptFiles + + // Install AppArmor support for ubuntu 24+ + // https://github.com/electron-userland/electron-builder/issues/8635 + await copyFile(scripts.appArmor, path.join(resourceDir, "apparmor-profile")) + const appInfo = packager.appInfo const options = this.options const synopsis = options.synopsis @@ -151,9 +163,9 @@ export default class FpmTarget extends Target { "--architecture", toLinuxArchString(arch, target), "--after-install", - scripts[0], + scripts.afterInstall, "--after-remove", - scripts[1], + scripts.afterRemove, "--description", smarten(target === "rpm" ? this.helper.getDescription(options) : `${synopsis || ""}\n ${this.helper.getDescription(options)}`), "--version", diff --git a/packages/app-builder-lib/templates/linux/after-install.tpl b/packages/app-builder-lib/templates/linux/after-install.tpl index 0c9b9459062..7433249abf7 100644 --- a/packages/app-builder-lib/templates/linux/after-install.tpl +++ b/packages/app-builder-lib/templates/linux/after-install.tpl @@ -25,3 +25,30 @@ fi if hash update-desktop-database 2>/dev/null; then update-desktop-database /usr/share/applications || true fi + +# Install apparmor profile. (Ubuntu 24+) +# First check if the version of AppArmor running on the device supports our profile. +# This is in order to keep backwards compatibility with Ubuntu 22.04 which does not support abi/4.0. +# In that case, we just skip installing the profile since the app runs fine without it on 22.04. +# +# Those apparmor_parser flags are akin to performing a dry run of loading a profile. +# https://wiki.debian.org/AppArmor/HowToUse#Dumping_profiles +# +# Unfortunately, at the moment AppArmor doesn't have a good story for backwards compatibility. +# https://askubuntu.com/questions/1517272/writing-a-backwards-compatible-apparmor-profile +APPARMOR_PROFILE_SOURCE='/opt/${sanitizedProductName}/resources/apparmor-profile' +APPARMOR_PROFILE_TARGET='/etc/apparmor.d/${executable}' +if test -d "/etc/apparmor.d"; then + if apparmor_parser --skip-kernel-load --debug "$APPARMOR_PROFILE_SOURCE" > /dev/null 2>&1; then + cp -f "$APPARMOR_PROFILE_SOURCE" "$APPARMOR_PROFILE_TARGET" + + if hash apparmor_parser 2>/dev/null; then + # Extra flags taken from dh_apparmor: + # > By using '-W -T' we ensure that any abstraction updates are also pulled in. + # https://wiki.debian.org/AppArmor/Contribute/FirstTimeProfileImport + apparmor_parser --replace --write-cache --skip-read-cache "$APPARMOR_PROFILE_TARGET" + fi + else + echo "Skipping the installation of the AppArmor profile as this version of AppArmor does not seem to support the bundled profile" + fi +fi \ No newline at end of file diff --git a/packages/app-builder-lib/templates/linux/after-remove.tpl b/packages/app-builder-lib/templates/linux/after-remove.tpl index a3004ebbd0e..19b3decabe1 100644 --- a/packages/app-builder-lib/templates/linux/after-remove.tpl +++ b/packages/app-builder-lib/templates/linux/after-remove.tpl @@ -6,3 +6,10 @@ if type update-alternatives >/dev/null 2>&1; then else rm -f '/usr/bin/${executable}' fi + +APPARMOR_PROFILE_DEST='/etc/apparmor.d/${executable}' + +# Remove apparmor profile. +if [ -f "$APPARMOR_PROFILE_DEST" ]; then + rm -f "$APPARMOR_PROFILE_DEST" +fi \ No newline at end of file diff --git a/packages/app-builder-lib/templates/linux/apparmor-profile.tpl b/packages/app-builder-lib/templates/linux/apparmor-profile.tpl new file mode 100644 index 00000000000..3769b7963b8 --- /dev/null +++ b/packages/app-builder-lib/templates/linux/apparmor-profile.tpl @@ -0,0 +1,9 @@ +abi , +include + +profile ${executable} "/opt/${sanitizedProductName}/${executable}" flags=(unconfined) { + userns, + + # Site-specific additions and overrides. See local/README for details. + include if exists +} \ No newline at end of file diff --git a/test/snapshots/PublishManagerTest.js.snap b/test/snapshots/PublishManagerTest.js.snap index 0c0ec7ad561..c453041e114 100644 --- a/test/snapshots/PublishManagerTest.js.snap +++ b/test/snapshots/PublishManagerTest.js.snap @@ -58,6 +58,7 @@ exports[`custom provider 2`] = ` "/opt/Test App ßW/resources/", "/opt/Test App ßW/resources/app-update.yml", "/opt/Test App ßW/resources/app.asar", + "/opt/Test App ßW/resources/apparmor-profile", "/opt/Test App ßW/resources/package-type", "/usr/share/applications/", "/usr/share/applications/testapp.desktop", diff --git a/test/snapshots/linux/debTest.js.snap b/test/snapshots/linux/debTest.js.snap index 600e070cbae..71bb7417e37 100644 --- a/test/snapshots/linux/debTest.js.snap +++ b/test/snapshots/linux/debTest.js.snap @@ -41,6 +41,7 @@ exports[`arm 2`] = ` "/usr/share/", "/opt/Test App ßW/resources/", "/opt/Test App ßW/resources/app.asar", + "/opt/Test App ßW/resources/apparmor-profile", "/usr/share/applications/", "/usr/share/applications/testapp.desktop", "/usr/share/doc/", @@ -115,6 +116,7 @@ exports[`arm 5`] = ` "/usr/share/", "/opt/Test App ßW/resources/", "/opt/Test App ßW/resources/app.asar", + "/opt/Test App ßW/resources/apparmor-profile", "/usr/share/applications/", "/usr/share/applications/testapp.desktop", "/usr/share/doc/", @@ -200,6 +202,7 @@ exports[`custom depends 2`] = ` "/usr/share/", "/opt/Test App ßW/resources/", "/opt/Test App ßW/resources/app.asar", + "/opt/Test App ßW/resources/apparmor-profile", "/usr/share/applications/", "/usr/share/applications/Boo.desktop", "/usr/share/doc/", @@ -285,6 +288,7 @@ exports[`deb 2`] = ` "/usr/share/", "/opt/Test App ßW/resources/", "/opt/Test App ßW/resources/app.asar", + "/opt/Test App ßW/resources/apparmor-profile", "/usr/share/applications/", "/usr/share/applications/testapp.desktop", "/usr/share/doc/", @@ -370,6 +374,7 @@ exports[`deb file associations 2`] = ` "/usr/share/", "/opt/Test App ßW/resources/", "/opt/Test App ßW/resources/app.asar", + "/opt/Test App ßW/resources/apparmor-profile", "/usr/share/applications/", "/usr/share/applications/testapp.desktop", "/usr/share/doc/", @@ -469,6 +474,7 @@ exports[`executable path in postinst script 2`] = ` "/usr/share/", "/opt/foo/resources/", "/opt/foo/resources/app.asar", + "/opt/foo/resources/apparmor-profile", "/usr/share/applications/", "/usr/share/applications/Boo.desktop", "/usr/share/doc/", @@ -544,6 +550,33 @@ fi if hash update-desktop-database 2>/dev/null; then update-desktop-database /usr/share/applications || true +fi + +# Install apparmor profile. (Ubuntu 24+) +# First check if the version of AppArmor running on the device supports our profile. +# This is in order to keep backwards compatibility with Ubuntu 22.04 which does not support abi/4.0. +# In that case, we just skip installing the profile since the app runs fine without it on 22.04. +# +# Those apparmor_parser flags are akin to performing a dry run of loading a profile. +# https://wiki.debian.org/AppArmor/HowToUse#Dumping_profiles +# +# Unfortunately, at the moment AppArmor doesn't have a good story for backwards compatibility. +# https://askubuntu.com/questions/1517272/writing-a-backwards-compatible-apparmor-profile +APPARMOR_PROFILE_SOURCE='/opt/foo/resources/apparmor-profile' +APPARMOR_PROFILE_TARGET='/etc/apparmor.d/Boo' +if test -d "/etc/apparmor.d"; then + if apparmor_parser --skip-kernel-load --debug "$APPARMOR_PROFILE_SOURCE" > /dev/null 2>&1; then + cp -f "$APPARMOR_PROFILE_SOURCE" "$APPARMOR_PROFILE_TARGET" + + if hash apparmor_parser 2>/dev/null; then + # Extra flags taken from dh_apparmor: + # > By using '-W -T' we ensure that any abstraction updates are also pulled in. + # https://wiki.debian.org/AppArmor/Contribute/FirstTimeProfileImport + apparmor_parser --replace --write-cache --skip-read-cache "$APPARMOR_PROFILE_TARGET" + fi + else + echo "Skipping the installation of the AppArmor profile as this version of AppArmor does not seem to support the bundled profile" + fi fi" `; @@ -597,6 +630,7 @@ exports[`no quotes for safe exec name 3`] = ` "/usr/share/", "/opt/foo/resources/", "/opt/foo/resources/app.asar", + "/opt/foo/resources/apparmor-profile", "/usr/share/applications/", "/usr/share/applications/Boo.desktop", "/usr/share/doc/", @@ -682,6 +716,7 @@ exports[`top-level exec name 2`] = ` "/usr/share/", "/opt/foo/resources/", "/opt/foo/resources/app.asar", + "/opt/foo/resources/apparmor-profile", "/usr/share/applications/", "/usr/share/applications/Boo.desktop", "/usr/share/doc/",