Skip to content

chore(snap): migrate snap generation from app-builder-bin to JS #8892

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 39 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
7161ff0
tmp save
mmaietta Feb 23, 2025
fa3a7f8
everything builds
mmaietta Feb 23, 2025
3fb49c9
convert to SnapBuilderOptions
mmaietta Feb 23, 2025
35f363d
everything builds
mmaietta Feb 23, 2025
cc6bf7e
add more helpers
mmaietta Feb 23, 2025
5cf634e
cleanup
mmaietta Feb 23, 2025
78eacf3
snap tests pass
mmaietta Feb 23, 2025
5dbbb3e
cleanup?
mmaietta Feb 23, 2025
d76121e
Merge commit 'e4d51475676819fc1c92f43b954171b1154d3290' into snap-js-…
mmaietta Feb 23, 2025
16b347e
clean up part 1
mmaietta Feb 23, 2025
cbb2a27
cleanup 3
mmaietta Feb 23, 2025
742a0fc
cleanup 4
mmaietta Feb 23, 2025
6ee53b0
cleanup 5
mmaietta Feb 23, 2025
2a68308
Merge branch 'master' into snap-js-migration
mmaietta Feb 23, 2025
aff2805
move snap tests to macos so that we can install snapcraft and multipass
mmaietta Feb 23, 2025
3f79884
move back to linux runner
mmaietta Feb 23, 2025
0be7bbd
test running snaptest on ubuntu runner?
mmaietta Feb 24, 2025
4690ae4
add sudo
mmaietta Feb 24, 2025
5a9c9c3
run in band
mmaietta Feb 24, 2025
8bdb942
multipass parallel?
mmaietta Feb 24, 2025
58051ac
only skip multipass tests
mmaietta Feb 24, 2025
db11629
update snapshots
mmaietta Feb 24, 2025
5eb372b
run all tests and update snapshots
mmaietta Feb 24, 2025
e7e3468
Merge branch 'master' into snap-js-migration
mmaietta Feb 25, 2025
34fcff6
cleanup
mmaietta Feb 25, 2025
0d7981c
add snapHeavyTest to GH runner
mmaietta Feb 25, 2025
3409ede
guess we cant run snapHeavyTest on GH runner due to multipass being u…
mmaietta Feb 25, 2025
873106f
Create empty-files-itch.md
mmaietta Feb 25, 2025
f30c812
Merge branch 'master' into snap-js-migration
mmaietta Feb 25, 2025
249790b
Merge commit '67b6f71f85798dba4ce51dfb2cd012e04cd391db' into snap-js-…
mmaietta Feb 25, 2025
00158e7
pr feedback
mmaietta Feb 26, 2025
de61d2a
Merge branch 'master' into snap-js-migration
mmaietta Feb 26, 2025
44325b9
convert `chmod -R` to `await chmod`
mmaietta Feb 26, 2025
8197563
update warning message
mmaietta Feb 27, 2025
ac96cb8
move templates to `template` dir
mmaietta Feb 27, 2025
fde0731
read files instead of byte string and refactor
mmaietta Feb 27, 2025
5cd59d4
add more snapshots because why not
mmaietta Feb 28, 2025
f0a9c3b
Merge branch 'master' into snap-js-migration
mmaietta Mar 3, 2025
aef891c
Merge branch 'master' into snap-js-migration
beyondkmp Mar 5, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .changeset/empty-files-itch.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"app-builder-lib": patch
"builder-util": patch
"electron-publish": patch
---

chore(snap): migrate snap generation from app-builder-bin to JS
27 changes: 26 additions & 1 deletion .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ jobs:
matrix:
testFiles:
- ArtifactPublisherTest,BuildTest,ExtraBuildTest,RepoSlugTest,binDownloadTest,configurationValidationTest,filenameUtilTest,filesTest,globTest,ignoreTest,macroExpanderTest,mainEntryTest,urlUtilTest,extraMetadataTest,linuxArchiveTest,linuxPackagerTest,HoistedNodeModuleTest,MemoLazyTest,HoistTest
- snapTest,debTest,fpmTest,protonTest
- debTest,fpmTest,protonTest
- winPackagerTest,winCodeSignTest,webInstallerTest
- oneClickInstallerTest,assistedInstallerTest
steps:
Expand Down Expand Up @@ -219,3 +219,28 @@ jobs:
env:
TEST_FILES: ${{ matrix.testFiles }}
FORCE_COLOR: 1

test-snap:
runs-on: ubuntu-22.04
timeout-minutes: 20
steps:
- name: Checkout code repository
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4

- name: Setup Tests
uses: ./.github/actions/pretest
with:
cache-path: ~/.cache/electron
cache-key: v-23.3.10-snap-electron

- name: Install snapcraft
run: |
sudo apt-get update -yq
sudo apt-get install snapcraft

- name: Test
run: |
pnpm ci:test
env:
TEST_FILES: snapTest
FORCE_COLOR: 1
1 change: 1 addition & 0 deletions packages/app-builder-lib/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"templates",
"scheme.json",
"certs/root_certs.keychain"

],
"repository": {
"type": "git",
Expand Down
4 changes: 2 additions & 2 deletions packages/app-builder-lib/src/binDownload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export function getBinFromCustomLoc(name: string, version: string, binariesLocUr
return getBin(dirName, binariesLocUrl, checksum)
}

export function getBinFromUrl(name: string, version: string, checksum: string): Promise<string> {
export function getBinFromUrl(name: string, version: string, checksum: string, fileName = `${name}-${version}`): Promise<string> {
const dirName = `${name}-${version}`
let url: string
if (process.env.ELECTRON_BUILDER_BINARIES_DOWNLOAD_OVERRIDE_URL) {
Expand All @@ -34,7 +34,7 @@ export function getBinFromUrl(name: string, version: string, checksum: string):
process.env.npm_package_config_electron_builder_binaries_custom_dir ||
process.env.ELECTRON_BUILDER_BINARIES_CUSTOM_DIR ||
dirName
const urlSuffix = dirName + ".7z"
const urlSuffix = fileName + ".7z"
url = `${baseUrl}${middleUrl}/${urlSuffix}`
}

Expand Down
4 changes: 2 additions & 2 deletions packages/app-builder-lib/src/linuxPackager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import AppImageTarget from "./targets/AppImageTarget"
import FlatpakTarget from "./targets/FlatpakTarget"
import FpmTarget from "./targets/FpmTarget"
import { LinuxTargetHelper } from "./targets/LinuxTargetHelper"
import SnapTarget from "./targets/snap"
import SnapTarget from "./targets/snap/snap"
import { createCommonTarget } from "./targets/targetFactory"

export class LinuxPackager extends PlatformPackager<LinuxConfiguration> {
Expand Down Expand Up @@ -44,7 +44,7 @@ export class LinuxPackager extends PlatformPackager<LinuxConfiguration> {
case "appimage":
return require("./targets/AppImageTarget").default
case "snap":
return require("./targets/snap").default
return require("./targets/snap/snap").default
case "flatpak":
return require("./targets/FlatpakTarget").default
case "deb":
Expand Down
36 changes: 36 additions & 0 deletions packages/app-builder-lib/src/targets/snap/linuxTools.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { isEmptyOrSpaces } from "builder-util"
import { getBinFromUrl } from "../../binDownload"
import * as os from "os"
import * as path from "path"
import { Lazy } from "lazy-val"

const appImageToolDir = new Lazy<string>(() => getBinFromUrl("appimage", "12.0.1", "3el6RUh6XoYJCI/ZOApyb0LLU/gSxDntVZ46R6+JNEANzfSo7/TfrzCRp5KlDo35c24r3ZOP7nnw4RqHwkMRLw=="))

function getAppImageToolBin(toolDir: string): string {
return process.platform === "darwin" ? path.join(toolDir, "darwin") : path.join(toolDir, `linux-${goArchToArchSuffix()}`)
}

function goArchToArchSuffix(): string {
const arch = os.arch()
switch (arch) {
case "arm":
return "arm32"
default:
return arch
}
}

async function getLinuxTool(name: string): Promise<string> {
const toolDir = await appImageToolDir.value
return path.join(getAppImageToolBin(toolDir), name)
}

export async function getMksquashfs(): Promise<string> {
if (process.env.USE_SYSTEM_MKSQUASHFS) {
return "mksquashfs"
}
if (!isEmptyOrSpaces(process.env.MKSQUASHFS_PATH)) {
return process.env.MKSQUASHFS_PATH
}
return getLinuxTool("mksquashfs")
}
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
import { replaceDefault as _replaceDefault, Arch, deepAssign, executeAppBuilder, InvalidConfigurationError, log, serializeToYaml, toLinuxArchString } from "builder-util"
import { replaceDefault as _replaceDefault, Arch, deepAssign, InvalidConfigurationError, log, serializeToYaml, toLinuxArchString } from "builder-util"
import { asArray, Nullish, SnapStoreOptions } from "builder-util-runtime"
import { outputFile, readFile } from "fs-extra"
import { load } from "js-yaml"
import * as path from "path"
import * as semver from "semver"
import { Configuration } from "../configuration"
import { Publish, Target } from "../core"
import { LinuxPackager } from "../linuxPackager"
import { PlugDescriptor, SnapOptions } from "../options/SnapOptions"
import { getTemplatePath } from "../util/pathManager"
import { LinuxTargetHelper } from "./LinuxTargetHelper"
import { createStageDirPath } from "./targetUtil"
import { Configuration } from "../../configuration"
import { Publish, Target } from "../../core"
import { LinuxPackager } from "../../linuxPackager"
import { PlugDescriptor, SnapOptions } from "../../options/SnapOptions"
import { getTemplatePath } from "../../util/pathManager"
import { LinuxTargetHelper } from "../LinuxTargetHelper"
import { createStageDirPath } from "../targetUtil"
import { SnapBuilderOptions, createSnap } from "./snapBuilder"

const defaultPlugs = ["desktop", "desktop-legacy", "home", "x11", "wayland", "unity7", "browser-support", "network", "gsettings", "audio-playback", "pulseaudio", "opengl"]

Expand Down Expand Up @@ -190,14 +191,20 @@ export default class SnapTarget extends Target {

const stageDir = await createStageDirPath(this, packager, arch)
const snapArch = toLinuxArchString(arch, "snap")
const args = ["snap", "--app", appOutDir, "--stage", stageDir, "--arch", snapArch, "--output", artifactPath, "--executable", this.packager.executableName]
const args: SnapBuilderOptions = {
appDir: appOutDir,
stageDir: stageDir,
arch: snapArch,
output: artifactPath,
executableName: this.packager.executableName,
}

await this.helper.icons
if (this.helper.maxIconPath != null) {
if (!this.isUseTemplateApp) {
snap.icon = "snap/gui/icon.png"
}
args.push("--icon", this.helper.maxIconPath)
args.icon = this.helper.maxIconPath
}

// snapcraft.yaml inside a snap directory
Expand All @@ -215,15 +222,15 @@ export default class SnapTarget extends Target {
extraAppArgs.push(noSandboxArg)
}
if (this.isUseTemplateApp) {
args.push("--exclude", "chrome-sandbox")
args.excludedAppFiles = ["chrome-sandbox"]
}
}
if (extraAppArgs.length > 0) {
args.push("--extraAppArgs=" + extraAppArgs.join(" "))
args.extraAppArgs = extraAppArgs
}

if (snap.compression != null) {
args.push("--compression", snap.compression)
args.compression = snap.compression
}

if (this.isUseTemplateApp) {
Expand All @@ -234,22 +241,28 @@ export default class SnapTarget extends Target {
}
}

if (packager.packagerOptions.effectiveOptionComputed != null && (await packager.packagerOptions.effectiveOptionComputed({ snap, desktopFile, args }))) {
if (this.isUseTemplateApp) {
args.template = { templateUrl: `electron4:${snapArch}` }
}

// snapshot tests verify `args`, but we need to extract the dynamic/temp paths from the object first
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const { appDir, icon, output, stageDir: _stageDir, ...argsForSnapshotTests } = args
if (
packager.packagerOptions.effectiveOptionComputed != null &&
(await packager.packagerOptions.effectiveOptionComputed({ snap, desktopFile, args: { argsForSnapshotTests, isUseTemplateApp: this.isUseTemplateApp } }))
) {
return
}

await outputFile(path.join(snapMetaDir, this.isUseTemplateApp ? "snap.yaml" : "snapcraft.yaml"), serializeToYaml(snap))

const hooksDir = await packager.getResource(options.hooks, "snap-hooks")
if (hooksDir != null) {
args.push("--hooks", hooksDir)
}

if (this.isUseTemplateApp) {
args.push("--template-url", `electron4:${snapArch}`)
args.hooksDir = hooksDir
}

await executeAppBuilder(args)
await createSnap(args)

const publishConfig = findSnapPublishConfig(this.packager.config)

Expand Down
Loading