Skip to content

Build Electron and NWJS packages #1149

Build Electron and NWJS packages

Build Electron and NWJS packages #1149

# Workflow to build Electron and (if not a packaged app) NWJS packages
name: Build Electron and NWJS packages
on:
schedule:
# Nightly run at 03:39 UTC
- cron: '39 03 * * *'
workflow_dispatch:
inputs:
version:
description: Specific version to build like v9.9.9 (if empty, builds version in package.json)
required: false
default: ''
target:
type: choice
description: Do you wish to build for "release", "nightly", or "artefacts" for testing? Artefacts will appear under the workflow run.
required: false
options:
- release
- nightly
- artefacts
default: 'artefacts'
env:
INPUT_VERSION: ${{ github.event.inputs.version }}
INPUT_TARGET: ${{ github.event.inputs.target }}
CRON_LAUNCHED: ${{ github.event.schedule }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
CSC_LINK: ${{ secrets.CSC_LINK }}
CSC_KEY_PASSWORD: ${{ secrets.CSC_KEY_PASSWORD }}
SSH_KEY: ${{ secrets.SSH_KEY }}
REF_NAME: ${{ github.ref_name }}
jobs:
Release_Linux:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
- name: Install dependencies
run: npm install
- name: Rewrite app version number and file name
run: |
chmod +x ./scripts/rewrite_app_version_number.sh
./scripts/rewrite_app_version_number.sh
# Replace -app in archive name for Electron apps
sed -i -E 's/(mdwiki[^-]+)-app_/\1_/g' ./www/js/init.js
- name: Build production code
run: npm run build-min
- name: Download archive if needed
run: |
echo "Changing to the dist directory"
cd dist && pwd
# Get archive name
packagedFile=$(grep -m1 'params\[.packagedFile' www/js/init.js | sed -E "s/^.+'([^']+\.zim)'.+/\1/")
# If packagedFile doesn't match a zim file, we don't need to download anything, so exit
if [[ ! $packagedFile =~ \.zim$ ]]; then
echo -e "\nNo zim file to download.\n"
exit 0
fi
# If file doesn't exist in FS, download it
if [ ! -f "archives/$packagedFile" ]; then
# Generalize the name if cron_launched and download it
echo -e "\nDownloading https://download.kiwix.org/zim/$packagedFile"
if [[ $CRON_LAUNCHED = true ]]; then
packagedFileGeneric=$(sed -E 's/_[0-9-]+(\.zim)/\1/' <<<"$packagedFile")
wget -nv "https://download.kiwix.org/zim/$packagedFileGeneric" -O "archives/$packagedFile"
else
flavour=$(sed -E 's/^([^_]+)_.+$/\1/' <<<"$packagedFile")
if [[ $flavour = "mdwiki" ]]; then
flavour='other'
fi
wget -nv "https://mirror.download.kiwix.org/zim/$flavour/$packagedFile" -O "archives/$packagedFile"
fi
fi
ls archives
if [ -f "archives/$packagedFile" ]; then
echo -e "\nFile $packagedFile now available in 'archives'.\n"
else
echo -e "\nError! We could not obtain the requested archive $packagedFile!\n"
exit 1
fi
- name: Build and publish 64bit
env:
USE_HARD_LINKS: false
run: |
# echo "Setting the module type to one supported by Electron in ./package.json"
# sed -i -E 's/("type":\s+)"module"/\1"commonjs"/' ./package.json
echo "Installing dependencies in dist"
cd dist && npm install && cd ..
echo "Building 64bit packages for ref_name=$REF_NAME..."
if [[ $REF_NAME = "main" ]]; then
npx electron-builder --linux AppImage:x64 AppImage:arm64 deb:x64 rpm:x64 --projectDir dist
else
npx electron-builder --linux AppImage:x64 AppImage:arm64 deb:x64 --projectDir dist
fi
- name: Build and pulblish 32bit
env:
USE_HARD_LINKS: false
run: |
echo "Changing Electron version to latest that supports 32bit Linux (18.3.15) in ./dist/package.json"
sed -i -E 's/("electron":\s")[^"]+/\118.3.15/' ./dist/package.json
echo "Installing dependencies in dist"
cd dist && npm install && cd ..
echo "Building 32bit packages for ref_name=$REF_NAME..."
if [[ $REF_NAME = "main" ]]; then
npx electron-builder --linux AppImage:ia32 deb:ia32 rpm:ia32 --projectDir dist
else
npx electron-builder --linux AppImage:ia32 --projectDir dist
fi
- name: Upload packages to Kiwix
if: github.ref_name == 'main' && github.event.inputs.target != 'artefacts'
run: |
echo "$SSH_KEY" > ./scripts/ssh_key
chmod 600 ./scripts/ssh_key
chmod +x ./scripts/publish_linux_packages_to_kiwix.sh
./scripts/publish_linux_packages_to_kiwix.sh
- name: Archive build artefacts
if: github.event.inputs.target == 'artefacts'
uses: actions/upload-artifact@v4
with:
name: kiwix-js-electron_linux
path: |
dist/bld/Electron/*.AppImage
dist/bld/Electron/*.deb
dist/bld/Electron/*.rpm
Release_Windows:
runs-on: windows-latest
env:
SIGNTOOL_PATH: "C:\\Program Files (x86)\\Windows Kits\\10\\bin\\10.0.22000.0\\x64\\signtool.exe"
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
- name: Install dependencies
run: npm install
- name: Rewrite app version number and file name
run: |
$INPUT_VERSION = $Env:INPUT_VERSION
$INPUT_TARGET = $Env:INPUT_TARGET
$CRON_LAUNCHED = $Env:CRON_LAUNCHED
./scripts/Rewrite-AppVersion.ps1
# Replace -app in archive name for Electron apps
(Get-Content ./www/js/init.js) -replace '(mdwiki[^-]+)-app_', '$1_' | Set-Content -encoding 'utf8BOM' ./www/js/init.js
- name: Build production code
run: npm run build-min
- name: Download archive if needed
run: |
echo "Changing to the dist directory"
cd dist && pwd
$packagedFile = (Select-String 'packagedFile' "www\js\init.js" -List) -ireplace "^.+'([^']+\.zim)'.+", '$1'
# If packagedFile doesn't match a zim file, we don't need to download anything, so exit
if ($packagedFile -and ! ($packagedFile -match '\.zim$')) {
Write-Host "`nNo zim file to download.`n"
exit 0
}
if ($packagedFile -and ! (Test-Path "archives\$packagedFile" -PathType Leaf)) {
# File not in archives, so generalize the name (if nightly) and download it
Write-Host "`nDownloading https://download.kiwix.org/zim/$packagedFile"
if ($CRON_LAUNCHED) {
$packagedFileGeneric = $packagedFile -replace '_[0-9-]+(\.zim)', '$1'
Invoke-WebRequest "https://download.kiwix.org/zim/$packagedFileGeneric" -OutFile "archives\$packagedFile"
} else {
$flavour = $packagedFile -replace '^([^_]+)_.+$', '$1'
if ($flavour -eq 'mdwiki') {
$flavour = 'other'
}
Invoke-WebRequest "https://mirror.download.kiwix.org/zim/$flavour/$packagedFile" -OutFile "archives\$packagedFile"
}
}
ls archives
if ($packagedFile -and (Test-Path "archives\$packagedFile" -PathType Leaf)) {
Write-Host "`nFile $packagedFile now available in 'archives'.`n" -ForegroundColor Green
} else {
Write-Host "`nError! We could not obtain the requested archive $packagedFile!`n" -ForegroundColor Red
exit 1
}
- name: Run electron builder for Win 7/8/8.1
shell: pwsh
run: |
$GITHUB_TOKEN = $Env:GITHUB_TOKEN
$INPUT_VERSION = $Env:INPUT_VERSION
$INPUT_TARGET = $Env:INPUT_TARGET
$CRON_LAUNCHED = $Env:CRON_LAUNCHED
if (-not ($Env:CRON_LAUNCHED -or ($Env:INPUT_TARGET -eq 'nightly'))) {
$INPUT_VERSION_E = $INPUT_VERSION -replace '^v([0-9.]+).*', '$1-E'
} else {
$INPUT_VERSION_E = $INPUT_VERSION -replace '^v', ''
}
./scripts/Rewrite-DraftReleaseTag.ps1
$ORIGINAL_ELECTRON_VERSION = (Get-Content ./package.json | sls '"electron":') -replace '.*"electron"\s*:\s*"(.*)".*', '$1'
echo "ORIGINAL_ELECTRON_VERSION=$ORIGINAL_ELECTRON_VERSION" | Out-File $Env:GITHUB_ENV -Encoding utf8 -Append
echo "Setting the Electron version to the latest supporting Windows 7/8/8.1 (=22.3.25)"
(Get-Content ./package.json) -replace '("electron":\s+)"[\d.]+[\w\d-.]*?"', '$1"22.3.25"' | Set-Content ./package.json
echo "Installing dependencies in root and dist"
npm install && cd dist && npm install && cd ..
echo "Installed Electron version:$(npx electron --version)"
echo "Building Windows 7+ 32bit NSIS package..."
npm run dist-win-nsis
echo "Renaming Windows 7+ executable"
$files = @("Kiwix JS Electron", "WikiMed by Kiwix", "Wikivoyage by Kiwix")
foreach ($file in $files) {
mv "dist/bld/Electron/$file Setup*.exe" "dist/bld/Electron/$file Win7 Setup $INPUT_VERSION_E.exe"
mv "dist/bld/Electron/$file Setup*.exe.blockmap" "dist/bld/Electron/$file Win7 Setup $INPUT_VERSION_E.exe.blockmap"
}
ls ./dist/bld/Electron/
# DEV: We did not use electron-builder to publish because we needed to change the filenames, so we need to publish to GitHub here
if ($INPUT_TARGET -ne 'artefacts') {
& ./scripts/Publish-ElectronPackages.ps1 -githubonly
}
./scripts/Rewrite-DraftReleaseTag.ps1
- name: Run electron builder for Win 10/11
shell: pwsh
run: |
$GITHUB_TOKEN = $Env:GITHUB_TOKEN
$INPUT_VERSION = $Env:INPUT_VERSION
$INPUT_TARGET = $Env:INPUT_TARGET
$CRON_LAUNCHED = $Env:CRON_LAUNCHED
$ORIGINAL_ELECTRON_VERSION = $Env:ORIGINAL_ELECTRON_VERSION
echo "Restoring original Electron version: $ORIGINAL_ELECTRON_VERSION"
(Get-Content ./package.json) -replace '("electron":\s+)"[\d.]+[\w\d-.]*?"', ('$1"' + $ORIGINAL_ELECTRON_VERSION + '"') | Set-Content ./package.json
./scripts/Rewrite-DraftReleaseTag.ps1
# Set the module type to one supported by Electron
# (Get-Content ./package.json) -replace '("type":\s+)"module"', '$1"commonjs"' | Set-Content ./package.json
echo "Installing dependencies in root and dist"
npm install && cd dist && npm install && cd ..
echo "Installed Electron version:$(npx electron --version)"
echo "Building Windows packages..."
npm run publish
./scripts/Rewrite-DraftReleaseTag.ps1
- name: Build portable Electron app
run: |
if (-not ($Env:CRON_LAUNCHED -or ($Env:INPUT_TARGET -eq 'nightly'))) {
$GITHUB_TOKEN = $Env:GITHUB_TOKEN
$INPUT_VERSION_E = $Env:INPUT_VERSION -replace '^(v[0-9.]+).*', '$1E'
if ($Env:INPUT_VERSION -match '-Wiki[\w]+') {
$INPUT_VERSION_E += $matches[0]
}
# To ensure there is enough disk space, we can delete the archive that is no longer needed
rm -r dist/archives
./scripts/Create-DraftRelease -buildonly -tag_name $INPUT_VERSION_E -portableonly -nobundle -wingetprompt N -nobranchcheck
}
- name: Publish packages
if: github.event.inputs.target != 'artefacts'
run: |
$SSH_KEY = $Env:SSH_KEY
echo "$SSH_KEY" > .\scripts\ssh_key
$GITHUB_TOKEN = $Env:GITHUB_TOKEN
$INPUT_VERSION = $Env:INPUT_VERSION
$INPUT_TARGET = $Env:INPUT_TARGET
$CRON_LAUNCHED = $Env:CRON_LAUNCHED
if ($Env:REF_NAME -eq "main") {
./scripts/Publish-ElectronPackages.ps1 -portableonly
} else {
./scripts/Publish-ElectronPackages.ps1 -portableonly -githubonly
}
- name: Archive build artefacts
if: github.event.inputs.target == 'artefacts'
uses: actions/upload-artifact@v4
with:
name: kiwix-js-electron_windows
path: |
dist/bld/Electron/*.exe
dist/bld/Electron/*.appx
dist/bld/Electron/*.zip
dist/bld/Electron/nsis-web/*.exe
dist/bld/Electron/nsis-web/*.nsis.7z
Release_NWJS:
if: github.ref_name == 'main'
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
- name: Install dependencies
run: npm install
- name: Build production code
run: npm run build-min
- name: Select NWJS app
run: |
ren package.json package.json.electron
ren package.json.nwjs package.json
- name: Rewrite app version number
run: |
$INPUT_VERSION = $Env:INPUT_VERSION
$INPUT_TARGET = $Env:INPUT_TARGET
$CRON_LAUNCHED = $Env:CRON_LAUNCHED
./scripts/Rewrite-AppVersion.ps1
cp package.json dist/package.json
- name: Download archive if needed
run: |
echo "Changing to the dist directory"
cd dist && pwd
$packagedFile = (Select-String 'packagedFile' "www\js\init.js" -List) -ireplace "^.+'([^']+\.zim)'.+", '$1'
# If packagedFile doesn't match a zim file, we don't need to download anything, so exit
if ($packagedFile -and ! ($packagedFile -match '\.zim$')) {
Write-Host "`nNo zim file to download.`n"
exit 0
}
if ($packagedFile -and ! (Test-Path "archives\$packagedFile" -PathType Leaf)) {
# File not in archives, so generalize the name (if nightly) and download it
Write-Host "`nDownloading https://download.kiwix.org/zim/$packagedFile"
if ($CRON_LAUNCHED) {
$packagedFileGeneric = $packagedFile -replace '_[0-9-]+(\.zim)', '$1'
Invoke-WebRequest "https://download.kiwix.org/zim/$packagedFileGeneric" -OutFile "archives\$packagedFile"
} else {
$flavour = $packagedFile -replace '^([^_]+)_.+$', '$1'
if ($flavour -eq 'mdwiki') {
$flavour = 'other'
}
Invoke-WebRequest "https://mirror.download.kiwix.org/zim/$flavour/$packagedFile" -OutFile "archives\$packagedFile"
}
}
ls archives
if ($packagedFile -and (Test-Path "archives\$packagedFile" -PathType Leaf)) {
Write-Host "`nFile $packagedFile now available in 'archives'.`n" -ForegroundColor Green
} else {
Write-Host "`nError! We could not obtain the requested archive $packagedFile!`n" -ForegroundColor Red
exit 1
}
- name: Build NWJS app
run: ./scripts/Build-NWJS.ps1 -only32bit
- name: Publish
if: github.event.inputs.target != 'artefacts'
run: |
$SSH_KEY = $Env:SSH_KEY
echo "$SSH_KEY" > .\scripts\ssh_key
$GITHUB_TOKEN = $Env:GITHUB_TOKEN
$INPUT_VERSION = $Env:INPUT_VERSION
$INPUT_TARGET = $Env:INPUT_TARGET
$CRON_LAUNCHED = $Env:CRON_LAUNCHED
./scripts/Publish-ElectronPackages.ps1
- name: Archive build artefacts
if: github.event.inputs.target == 'artefacts'
uses: actions/upload-artifact@v4
with:
name: kiwix-js-nwjs_windows
path: dist/bld/nwjs/*.zip