From 5d8ed375d6bf0e9ddfc700344c97d98738fe283b Mon Sep 17 00:00:00 2001 From: Akis Kesoglou Date: Wed, 1 Nov 2023 14:07:46 +0200 Subject: [PATCH] Run on CI --- .github/actions/publish/action.yml | 113 ++++++++++++++--------------- .github/actions/test/action.yml | 32 ++++++-- afterSignHook.js | 25 ------- dev-app-update.yml | 4 - forge.config.ts | 69 ++++++++---------- package.json | 45 ++++++++++-- 6 files changed, 150 insertions(+), 138 deletions(-) delete mode 100644 afterSignHook.js delete mode 100644 dev-app-update.yml diff --git a/.github/actions/publish/action.yml b/.github/actions/publish/action.yml index 6f5c73d5980..b82fe58cd97 100644 --- a/.github/actions/publish/action.yml +++ b/.github/actions/publish/action.yml @@ -48,19 +48,49 @@ runs: node-version: ${{ inputs.NODE_VERSION }} cache: npm - - name: Install yq + - name: Install host dependencies + if: runner.os == 'Linux' shell: bash --noprofile --norc -eo pipefail -x {0} - run: choco install yq + run: | + set -ea + sudo apt-get update + sudo apt-get install -y --no-install-recommends fakeroot dpkg rpm + + - name: Install host dependencies if: runner.os == 'Windows' + shell: bash --noprofile --norc -eo pipefail -x {0} + run: choco install yq # https://www.electron.build/code-signing.html - # https://github.com/Apple-Actions/import-codesign-certs + # https://dev.to/rwwagner90/signing-electron-apps-with-github-actions-4cof - name: Import Apple code signing certificate if: runner.os == 'macOS' - uses: apple-actions/import-codesign-certs@v1 - with: - p12-file-base64: ${{ fromJSON(inputs.secrets).APPLE_SIGNING }} - p12-password: ${{ fromJSON(inputs.secrets).APPLE_SIGNING_PASSWORD }} + shell: bash --noprofile --norc -eo pipefail -x {0} + run: | + KEY_CHAIN=build.keychain + CERTIFICATE_P12=certificate.p12 + + # Recreate the certificate from the secure environment variable + echo $CERTIFICATE_P12_B64 | base64 --decode > $CERTIFICATE_P12 + + #create a keychain + security create-keychain -p actions $KEY_CHAIN + + # Make the keychain the default so identities are found + security default-keychain -s $KEY_CHAIN + + # Unlock the keychain + security unlock-keychain -p actions $KEY_CHAIN + + security import $CERTIFICATE_P12 -k $KEY_CHAIN -P $CERTIFICATE_PASSWORD -T /usr/bin/codesign + + security set-key-partition-list -S apple-tool:,apple: -s -k actions $KEY_CHAIN + + # remove certs + rm -fr *.p12 + env: + CERTIFICATE_P12_B64: ${{ fromJSON(inputs.secrets).APPLE_SIGNING }} + CERTIFICATE_PASSWORD: ${{ fromJSON(inputs.secrets).APPLE_SIGNING_PASSWORD }} - name: Import Windows code signing certificate if: runner.os == 'Windows' @@ -81,10 +111,6 @@ runs: WINDOWS_CERTIFICATE: ${{ fromJSON(inputs.secrets).WINDOWS_SIGNING }} WINDOWS_CERTIFICATE_PASSWORD: ${{ fromJSON(inputs.secrets).WINDOWS_SIGNING_PASSWORD }} - # ... or refactor (e.g.) https://github.com/samuelmeuli/action-electron-builder - # https://github.com/product-os/scripts/tree/master/electron - # https://github.com/product-os/scripts/tree/master/shared - # https://github.com/product-os/balena-concourse/blob/master/pipelines/github-events/template.yml - name: Package release id: package_release shell: bash --noprofile --norc -eo pipefail -x {0} @@ -94,76 +120,47 @@ runs: [[ '${{ inputs.VERBOSE }}' =~ on|On|Yes|yes|true|True ]] && set -x runner_os="$(echo "${RUNNER_OS}" | tr '[:upper:]' '[:lower:]')" - runner_arch="$(echo "${RUNNER_ARCH}" | tr '[:upper:]' '[:lower:]')" - ELECTRON_BUILDER_ARCHITECTURE="${runner_arch}" APPLICATION_VERSION="$(jq -r '.version' package.json)" - ARCHITECTURE_FLAGS="--${ELECTRON_BUILDER_ARCHITECTURE}" - if [[ $runner_os =~ linux ]]; then - ELECTRON_BUILDER_OS='--linux' - TARGETS="$(yq e .linux.target[] electron-builder.yml)" + if [[ $RUNNER_OS =~ linux ]]; then + BUILD_PLATFORM='linux' + BUILD_ARCH='x64' elif [[ $runner_os =~ darwin|macos|osx ]]; then - CSC_KEY_PASSWORD=${{ fromJSON(inputs.secrets).APPLE_SIGNING_PASSWORD }} - CSC_KEYCHAIN=signing_temp - CSC_LINK=${{ fromJSON(inputs.secrets).APPLE_SIGNING }} - ELECTRON_BUILDER_OS='--mac' - TARGETS="$(yq e .mac.target[] electron-builder.yml)" + BUILD_PLATFORM='darwin' + BUILD_ARCH='x64,arm64' elif [[ $runner_os =~ windows|win ]]; then - ARCHITECTURE_FLAGS="--ia32 ${ARCHITECTURE_FLAGS}" - CSC_KEY_PASSWORD=${{ fromJSON(inputs.secrets).WINDOWS_SIGNING_PASSWORD }} - CSC_LINK=${{ fromJSON(inputs.secrets).WINDOWS_SIGNING }} - ELECTRON_BUILDER_OS='--win' - TARGETS="$(yq e .win.target[] electron-builder.yml)" + BUILD_PLATFORM='win32' + BUILD_ARCH="ia32,x64" else - exit 1 + echo "ERROR: unexpected runner OS: ${runner_os}" + exit 1 fi - npm link electron-builder - - for target in ${TARGETS}; do - electron-builder ${ELECTRON_BUILDER_OS} ${target} ${ARCHITECTURE_FLAGS} \ - --c.extraMetadata.analytics.sentry.token='https://739bbcfc0ba4481481138d3fc831136d@o95242.ingest.sentry.io/4504451487301632' \ - --c.extraMetadata.analytics.amplitude.token='balena-etcher' \ - --c.extraMetadata.packageType="${target}" - - find dist -type f -maxdepth 1 - done + npm run make -- --platform="${BUILD_PLATFORM}" --arch="${BUILD_ARCH}" echo "version=${APPLICATION_VERSION}" >> $GITHUB_OUTPUT env: - # Apple notarization (afterSignHook.js) + # Apple notarization XCODE_APP_LOADER_EMAIL: ${{ inputs.XCODE_APP_LOADER_EMAIL }} XCODE_APP_LOADER_PASSWORD: ${{ fromJSON(inputs.secrets).XCODE_APP_LOADER_PASSWORD }} + XCODE_APP_LOADER_TEAM_ID: ${{ fromJSON(inputs.secrets).XCODE_APP_LOADER_TEAM_ID }} + # Windows signing + WINDOWS_SIGNING: ${{ fromJSON(inputs.secrets).WINDOWS_SIGNING }} + WINDOWS_SIGNING_PASSWORD: ${{ fromJSON(inputs.secrets).WINDOWS_SIGNING_PASSWORD }} # https://github.blog/2020-08-03-github-actions-improvements-for-fork-and-pull-request-workflows/#improvements-for-public-repository-forks # https://docs.github.com/en/actions/managing-workflow-runs/approving-workflow-runs-from-public-forks#about-workflow-runs-from-public-forks CSC_FOR_PULL_REQUEST: true - # https://www.electron.build/auto-update.html#staged-rollouts - - name: Configure staged rollout(s) - shell: bash --noprofile --norc -eo pipefail -x {0} - run: | - set -ea - - [[ '${{ inputs.VERBOSE }}' =~ on|On|Yes|yes|true|True ]] && set -x - - percentage="$(cat < repo.yml | yq e .triggerNotification.stagingPercentage)" - - find dist -type f -maxdepth 1 \ - -name "latest*.yml" \ - -exec yq -i e .version=\"${{ steps.package_release.outputs.version }}\" {} \; - - find dist -type f -maxdepth 1 \ - -name "latest*.yml" \ - -exec yq -i e .stagingPercentage=\"$percentage\" {} \; - - name: Upload artifacts uses: actions/upload-artifact@v3 with: name: gh-release-${{ github.event.pull_request.head.sha || github.event.head_commit.id }} - path: dist + path: | + out/**/*.{deb,rpm,dmg,zip} + out/**/*Setup.exe retention-days: 1 diff --git a/.github/actions/test/action.yml b/.github/actions/test/action.yml index 36ddce23339..a48d6baeabb 100644 --- a/.github/actions/test/action.yml +++ b/.github/actions/test/action.yml @@ -28,23 +28,43 @@ runs: node-version: ${{ inputs.NODE_VERSION }} cache: npm - - name: Test release + - name: Install host dependencies + if: runner.os == 'Linux' shell: bash --noprofile --norc -eo pipefail -x {0} run: | set -ea + sudo apt-get update + sudo apt-get install -y --no-install-recommends xvfb libudev-dev + cat < package.json | jq -r '.hostDependencies[][]' - | \ + xargs -L1 echo | sed 's/|//g' | xargs -L1 \ + sudo apt-get --ignore-missing install || true - [[ '${{ inputs.VERBOSE }}' =~ on|On|Yes|yes|true|True ]] && set -x + - name: Install host dependencies + if: runner.os == 'Windows' + shell: bash --noprofile --norc -eo pipefail -x {0} + run: npx node-gyp install - runner_os="$(echo "${RUNNER_OS}" | tr '[:upper:]' '[:lower:]')" + - name: Install host dependencies + if: runner.os == 'macOS' + # FIXME: Python 3.12 dropped distutils that node-gyp depends upon. + # This is a temporary workaround to make the job use Python 3.11 until + # node-gyp catches up. + uses: actions/setup-python@d27e3f3d7c64b4bbf8e4abfb9b63b83e846e0435 # v4 + with: + python-version: '3.11' - npm run flowzone-preinstall-${runner_os} + - name: Test release + shell: bash --noprofile --norc -eo pipefail -x {0} + run: | + set -ea + runner_os="$(echo "${RUNNER_OS}" | tr '[:upper:]' '[:lower:]')" npm ci npm run package npm run test-${runner_os} - env: # https://www.electronjs.org/docs/latest/api/environment-variables - ELECTRON_NO_ATTACH_CONSOLE: true + ELECTRON_NO_ATTACH_CONSOLE: 'true' + ELECTRON_SKIP_NOTARIZATION: 'true' - name: Compress custom source if: runner.os != 'Windows' diff --git a/afterSignHook.js b/afterSignHook.js deleted file mode 100644 index f11464426bb..00000000000 --- a/afterSignHook.js +++ /dev/null @@ -1,25 +0,0 @@ -'use strict' - -const { notarize } = require('electron-notarize') -const { ELECTRON_SKIP_NOTARIZATION } = process.env - -async function main(context) { - const { electronPlatformName, appOutDir } = context - if (electronPlatformName !== 'darwin' || ELECTRON_SKIP_NOTARIZATION === 'true') { - return - } - - const appName = context.packager.appInfo.productFilename - const appleId = process.env.XCODE_APP_LOADER_EMAIL || 'accounts+apple@balena.io' - const appleIdPassword = process.env.XCODE_APP_LOADER_PASSWORD - - // https://github.com/electron/notarize/blob/main/README.md - await notarize({ - appBundleId: 'io.balena.etcher', - appPath: `${appOutDir}/${appName}.app`, - appleId, - appleIdPassword - }) -} - -exports.default = main diff --git a/dev-app-update.yml b/dev-app-update.yml deleted file mode 100644 index 41f675986c2..00000000000 --- a/dev-app-update.yml +++ /dev/null @@ -1,4 +0,0 @@ -owner: balena-io -repo: etcher -provider: github -updaterCacheDirName: balena-etcher-updater diff --git a/forge.config.ts b/forge.config.ts index 42972fc3175..0cf462c9e5f 100644 --- a/forge.config.ts +++ b/forge.config.ts @@ -11,11 +11,37 @@ import { ResourcePlugin } from 'electron-forge-resource-plugin'; import { mainConfig, rendererConfig } from './webpack.config'; +const { hostDependencies } = require('./package.json'); + const LONG_DESCRIPTION = `balenaEtcher is a powerful OS image flasher built with web technologies to ensure flashing an SDCard or USB drive is a pleasant and safe experience. It protects you from accidentally writing to your hard-drives, ensures every byte of data was written correctly and much more.`; +let osxSigningConfig: any = {}; +let winSigningConfig: any = {}; + +if (process.env.NODE_ENV !== 'development' && process.env.ELECTRON_SKIP_NOTARIZATION !== 'true') { + osxSigningConfig.osxSign = { + optionsForFile: () => ({ + entitlements: './entitlements.mac.plist', + hardenedRuntime: true, + }), + }; + + osxSigningConfig.osxNotarize = { + tool: 'notarytool', + appleId: process.env.XCODE_APP_LOADER_EMAIL, + appleIdPassword: process.env.XCODE_APP_LOADER_PASSWORD, + teamId: process.env.XCODE_APP_LOADER_TEAM_ID, + }; + + winSigningConfig = { + certificateFile: process.env.WINDOWS_SIGNING, + certificatePassword: process.env.WINDOWS_SIGNING_PASSWORD + } +} + const config: ForgeConfig = { packagerConfig: { asar: true, @@ -27,15 +53,14 @@ const config: ForgeConfig = { protocols: [ { name: 'etcher', schemes: ['etcher']}, ], - - // osxSign: {}, - // osxNotarize: {}, + ...osxSigningConfig, }, rebuildConfig: {}, makers: [ new MakerZIP(), new MakerSquirrel({ setupIcon: 'assets/icon.ico', + ...winSigningConfig, }), new MakerDMG({ background: './assets/dmg/background.tiff', @@ -87,43 +112,7 @@ const config: ForgeConfig = { scripts: { postinst: './after-install.tpl', }, - depends: [ - 'gconf-service', - 'gconf2', - 'libasound2', - 'libatk1.0-0', - 'libc6', - 'libcairo2', - 'libcups2', - 'libdbus-1-3', - 'libexpat1', - 'libfontconfig1', - 'libfreetype6', - 'libgbm1', - 'libgcc1', - 'libgconf-2-4', - 'libgdk-pixbuf2.0-0', - 'libglib2.0-0', - 'libgtk-3-0', - 'liblzma5', - 'libnotify4', - 'libnspr4', - 'libnss3', - 'libpango1.0-0 | libpango-1.0-0', - 'libstdc++6', - 'libx11-6', - 'libxcomposite1', - 'libxcursor1', - 'libxdamage1', - 'libxext6', - 'libxfixes3', - 'libxi6', - 'libxrandr2', - 'libxrender1', - 'libxss1', - 'libxtst6', - 'polkit-1-auth-agent | policykit-1-gnome | polkit-kde-1', - ], + depends: hostDependencies['debian'], } }), ], diff --git a/package.json b/package.json index b971304c692..67802ce2527 100644 --- a/package.json +++ b/package.json @@ -14,14 +14,9 @@ "url": "git@github.com:balena-io/etcher.git" }, "scripts": { - "flowzone-preinstall-linux": "sudo apt-get update && sudo apt-get install -y xvfb libudev-dev && cat < electron-builder.yml | yq e .deb.depends[] - | xargs -L1 echo | sed 's/|//g' | xargs -L1 sudo apt-get --ignore-missing install || true", - "flowzone-preinstall-macos": "true", - "flowzone-preinstall-windows": "npx node-gyp install", - "flowzone-preinstall": "npm run flowzone-preinstall-linux", "lint-css": "prettier --write lib/**/*.css", "lint-ts": "balena-lint --fix --typescript typings lib tests webpack.config.ts", "lint": "npm run lint-ts && npm run lint-css", - "start": "electron-forge start", "test-gui": "electron-mocha --recursive --reporter spec --window-config tests/gui/window-config.json --require ts-node/register/transpile-only --require-main tests/gui/allow-renderer-process-reuse.ts --full-trace --no-sandbox --renderer tests/gui/**/*.ts", "test-shared": "electron-mocha --recursive --reporter spec --require ts-node/register/transpile-only --require-main tests/gui/allow-renderer-process-reuse.ts --full-trace --no-sandbox tests/shared/**/*.ts", "test-windows": "npm run lint && npm run test-gui && npm run test-shared", @@ -29,6 +24,7 @@ "test-linux": "npm run lint && xvfb-run --auto-servernum npm run test-gui && xvfb-run --auto-servernum npm run test-shared", "test": "echo npm run test-{linux,windows,macos}", "package": "electron-forge package", + "start": "electron-forge start", "make": "electron-forge make" }, "husky": { @@ -126,6 +122,45 @@ "typescript": "4.4.4", "url-loader": "4.1.1" }, + "hostDependencies": { + "debian": [ + "gconf-service", + "gconf2", + "libasound2", + "libatk1.0-0", + "libc6", + "libcairo2", + "libcups2", + "libdbus-1-3", + "libexpat1", + "libfontconfig1", + "libfreetype6", + "libgbm1", + "libgcc1", + "libgconf-2-4", + "libgdk-pixbuf2.0-0", + "libglib2.0-0", + "libgtk-3-0", + "liblzma5", + "libnotify4", + "libnspr4", + "libnss3", + "libpango1.0-0 | libpango-1.0-0", + "libstdc++6", + "libx11-6", + "libxcomposite1", + "libxcursor1", + "libxdamage1", + "libxext6", + "libxfixes3", + "libxi6", + "libxrandr2", + "libxrender1", + "libxss1", + "libxtst6", + "polkit-1-auth-agent | policykit-1-gnome | polkit-kde-1" + ] + }, "engines": { "node": ">=18 <20" },