diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 786ba12..b0c51b8 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -144,38 +144,48 @@ jobs: run: npm run test - name: Build Windows (exe) + run: npm run build env: MODE: production - run: | - npm run build:installer - - - name: Sign Windows Build (exe) - uses: sslcom/esigner-codesign@develop - if: ${{github.ref == 'refs/heads/main'}} + + # Download 'SSLcom/esigner-codesign' to a folder called 'esigner-codesign' in the root of the project + - name: Checkout esigner-codesign repository (Windows) + uses: actions/checkout@v3 with: - command: sign - username: ${{ secrets.ES_USERNAME }} - password: ${{ secrets.ES_PASSWORD }} - credential_id: ${{ secrets.CREDENTIAL_ID }} - totp_secret: ${{ secrets.ES_TOTP_SECRET }} - file_path: ${GITHUB_WORKSPACE}/dist/Install Decentraland.exe - output_path: ${GITHUB_WORKSPACE}/dist/signed - malware_block: false - environment_name: PROD - signing_method: v2 - - - name: Replace signed exe - if: ${{github.ref == 'refs/heads/main'}} - run: | - Copy-Item -Path "${env:GITHUB_WORKSPACE}\dist\signed\Install Decentraland.exe" -Destination "${env:GITHUB_WORKSPACE}\dist\Install Decentraland.exe" -Force + repository: 'SSLcom/esigner-codesign' + path: esigner-codesign - - name: Publish Windows (exe) - if: ${{github.ref == 'refs/heads/main'}} + - name: Publish + # I use this action because it is capable of retrying multiple times if there are any issues with the distribution server + uses: nick-fields/retry@v3 + with: + timeout_minutes: 15 + max_attempts: 6 + retry_wait_seconds: 15 + retry_on: error + shell: 'bash' + command: npx electron-builder --config electron-builder.cjs --publish always env: - GITHUB_TOKEN: ${{secrets.github_token}} - EP_PRE_RELEASE: true - run: | - npm run publishonly + # Code Signing params + # See https://www.electron.build/code-signing + CSC_LINK: ${{ secrets.MACOS_CSC_LINK }} + CSC_KEY_PASSWORD: ${{ secrets.MACOS_CSC_KEY_PASSWORD }} + # Publishing artifacts + GH_TOKEN: ${{ secrets.github_token }} # GitHub token, automatically provided (No need to define this secret in the repo settings) + EP_PRE_RELEASE: true # Publish as pre-release + # The following are the parameters required by the esigner-codesign action to work, we must explicitly pass in even the optional ones since we're not using the action directly, but from the checked out repo + CODE_SIGN_SCRIPT_PATH: "${{ github.workspace }}\\esigner-codesign\\dist\\index.js" + INPUT_COMMAND: 'sign' + INPUT_FILE_PATH: "${{ github.workspace }}\\dist\\Decentraland Launcher-win-x64.exe" + INPUT_OVERRIDE: 'true' + INPUT_MALWARE_BLOCK: 'false' + INPUT_CLEAN_LOGS: 'false' + INPUT_JVM_MAX_MEMORY: '1024M' + INPUT_ENVIRONMENT_NAME: 'PROD' + INPUT_USERNAME: ${{ secrets.ES_USERNAME }} + INPUT_PASSWORD: ${{ secrets.ES_PASSWORD }} + INPUT_TOTP_SECRET: ${{ secrets.ES_TOTP_SECRET }} + INPUT_CREDENTIAL_ID: ${{ secrets.WINDOWS_CREDENTIAL_ID_SIGNER }} - name: Upload artifacts exe env: diff --git a/electron-builder.cjs b/electron-builder.cjs new file mode 100644 index 0000000..67b84bf --- /dev/null +++ b/electron-builder.cjs @@ -0,0 +1,126 @@ +const { execSync } = require('child_process') + +const config = { + appId: 'decentraland.desktop.launcher', + productName: 'Decentraland', + extends: null, + artifactName: 'Decentraland.${ext}', + compression: 'maximum', + files: ['dist/**/*', 'public/**/*', 'public/systray/iOS/**/*', 'public/systray/Windows/**/*'], + protocols: [ + { + name: 'Decentraland Desktop App', + schemes: ['dcl'] + } + ], + directories: { + buildResources: 'assets' + }, + win: { + publisherName: 'Decentraland Foundation', + icon: 'public/app-icon.png', + target: ['nsis'], + verifyUpdateCodeSignature: false, + signAndEditExecutable: true, + signingHashAlgorithms: ['sha256'], + rfc3161TimeStampServer: 'http://ts.ssl.com', + timeStampServer: 'http://ts.ssl.com' + }, + nsis: { + oneClick: false, + shortcutName: 'Decentraland', + artifactName: 'Install Decentraland.${ext}', + installerIcon: 'public/installer-icon.ico', + allowToChangeInstallationDirectory: true, + deleteAppDataOnUninstall: true, + perMachine: true, + include: 'electron/installer.nsh' + }, + appx: { + applicationId: 'com.decentraland.launcher', + identityName: 'DecentralandFoundation.Decentraland', + publisherDisplayName: 'Decentraland Foundation', + publisher: 'CN=546D5DDE-76D5-4F9D-99D8-07C3235EC3A0' + }, + linux: { + icon: 'public/app-icon.png', + target: ['AppImage'] + }, + appImage: { + artifactName: 'Decentraland.${ext}' + }, + mac: { + icon: 'public/app-icon.png', + target: ['dmg', 'zip'], + hardenedRuntime: true, + entitlements: 'entitlements.mac.plist', + extendInfo: { + NSMicrophoneUsageDescription: 'Need microphone access to use voice chat in the application' + } + }, + dmg: { + icon: 'public/installer-icon.icns', + artifactName: 'Decentraland.${ext}' + }, + publish: { + provider: 'github', + owner: 'decentraland', + repo: 'explorer-desktop-launcher', + private: false + } +} + +// Sign Windows .exe +if (process.env.CODE_SIGN_SCRIPT_PATH) { + config.win.sign = (configuration) => { + console.log('Requested signing for ', configuration.path) + + // Only proceed if the installer .exe file is in the configuration path - skip signing everything else + if (!configuration.path.endsWith('Install Decentraland.exe')) { + console.log('This is not the installer .exe, skip signing') + return true + } + + const scriptPath = process.env.CODE_SIGN_SCRIPT_PATH + + try { + // Execute the sign script synchronously + process.env.INPUT_COMMAND = 'sign' // override the INPUT_COMMAND, it is already set in the "env" of the GitHub Action step, but for some reason it gets overwritten with 'npx electron-builder ...' so we must set it to 'sign' + process.env.INPUT_FILE_PATH = configuration.path // set the file path to the installer .exe + const env = { + command: process.env.INPUT_COMMAND, + username: process.env.INPUT_USERNAME, + password: process.env.INPUT_PASSWORD, + credential_id: process.env.INPUT_CREDENTIAL_ID, + totp_secret: process.env.INPUT_TOTP_SECRET, + file_path: process.env.INPUT_FILE_PATH, + output_path: process.env.INPUT_OUTPUT_PATH, + malware_block: process.env.INPUT_MALWARE_BLOCK, + override: process.env.INPUT_OVERRIDE, + clean_logs: process.env.INPUT_CLEAN_LOGS, + environment_name: process.env.INPUT_ENVIRONMENT_NAME, + jvm_max_memory: process.env.INPUT_JVM_MAX_MEMORY + } + console.log('env:', JSON.stringify(env, null, 2)) + const output = execSync(`node "${scriptPath}"`, { + env: { ...process.env, ...env } + }).toString() + console.log(`Script output: ${output}`) + } catch (error) { + console.error(`Error executing script: ${error.message}`) + if (error.stdout) { + console.log(`Script stdout: ${error.stdout.toString()}`) + } + if (error.stderr) { + console.error(`Script stderr: ${error.stderr.toString()}`) + } + return false + } + + return true // Return true at the end of successful signing + } + + config.win.signingHashAlgorithms = ['sha256'] +} + +module.exports = config diff --git a/package-lock.json b/package-lock.json index 9581b2c..9a06685 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "explorer-desktop-launcher", - "version": "0.1.56", + "version": "0.1.59", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "explorer-desktop-launcher", - "version": "0.1.56", + "version": "0.1.59", "hasInstallScript": true, "dependencies": { "axios": "^1.7.7", @@ -15495,4 +15495,4 @@ } } } -} +} \ No newline at end of file diff --git a/package.json b/package.json index ee7ca41..09d5d46 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "explorer-desktop-launcher", - "version": "0.1.58", + "version": "0.1.59", "author": "decentraland", "description": "Decentraland Desktop Launcher", "homepage": ".", @@ -40,98 +40,12 @@ "start:dev": "npm run build && electron . --developer-mode", "start:local": "npm run build && electron . --custom-url http://localhost:3000/?", "build": "rm -rf dist && vite build --config vite.config.main.ts && vite build --config vite.config.preload.ts", - "build:installer": "npm run build && electron-builder --publish never", - "build:appx": "npm run build && electron-builder --windows appx --publish never", - "publish": "npm run build && electron-builder --publish always", - "publishonly": "electron-builder --publish always", + "build:installer": "npm run build && electron-builder --config electron-builder.cjs --publish never", + "build:appx": "npm run build && electron-builder --config electron-builder.cjs --windows appx --publish never", + "publish": "npm run build && electron-builder --config electron-builder.cjs --publish always", "publish:appx": "npm run build && electron-builder --windows appx --publish always", "test": "vitest run" }, - "build": { - "appId": "decentraland.desktop.launcher", - "productName": "Decentraland", - "extends": null, - "artifactName": "Decentraland.${ext}", - "compression": "maximum", - "files": [ - "dist/**/*", - "public/**/*", - "public/systray/iOS/**/*", - "public/systray/Windows/**/*" - ], - "protocols": [ - { - "name": "Decentraland Desktop App", - "schemes": [ - "dcl" - ] - } - ], - "directories": { - "buildResources": "assets" - }, - "win": { - "publisherName": "Decentraland Foundation", - "icon": "public/app-icon.png", - "target": [ - "nsis" - ], - "verifyUpdateCodeSignature": false, - "signAndEditExecutable": true, - "signingHashAlgorithms": [ - "sha256" - ], - "rfc3161TimeStampServer": "http://ts.ssl.com", - "timeStampServer": "http://ts.ssl.com" - }, - "nsis": { - "oneClick": false, - "shortcutName": "Decentraland", - "artifactName": "Install Decentraland.${ext}", - "installerIcon": "public/installer-icon.ico", - "allowToChangeInstallationDirectory": true, - "deleteAppDataOnUninstall": true, - "perMachine": true, - "include": "electron/installer.nsh" - }, - "appx": { - "applicationId": "com.decentraland.launcher", - "identityName": "DecentralandFoundation.Decentraland", - "publisherDisplayName": "Decentraland Foundation", - "publisher": "CN=546D5DDE-76D5-4F9D-99D8-07C3235EC3A0" - }, - "linux": { - "icon": "public/app-icon.png", - "target": [ - "AppImage" - ] - }, - "appImage": { - "artifactName": "Decentraland.${ext}" - }, - "mac": { - "icon": "public/app-icon.png", - "target": [ - "dmg", - "zip" - ], - "hardenedRuntime": true, - "entitlements": "entitlements.mac.plist", - "extendInfo": { - "NSMicrophoneUsageDescription": "Need microphone access to use voice chat in the application" - } - }, - "dmg": { - "icon": "public/installer-icon.icns", - "artifactName": "Decentraland.${ext}" - }, - "publish": { - "provider": "github", - "owner": "decentraland", - "repo": "explorer-desktop-launcher", - "private": false - } - }, "browserslist": { "production": [ ">0.2%", @@ -144,4 +58,4 @@ "last 1 safari version" ] } -} +} \ No newline at end of file