Build Electron and NWJS packages #2022
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # 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 without suffix (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? Nightly will only publish on the main branch. Artefacts will appear under the workflow run. For release, a draft release with corresponding tag must exist. | |
| required: false | |
| options: | |
| - release | |
| - nightly | |
| - artefacts | |
| default: 'artefacts' | |
| build_platform: | |
| description: Which platform(s) to build for? | |
| type: choice | |
| required: false | |
| options: | |
| - all | |
| - linux | |
| - macos | |
| - windows | |
| - win7 | |
| - win11 | |
| default: 'all' | |
| win11packages: | |
| description: For Windows 11 builds, select which packages to build | |
| type: choice | |
| required: false | |
| options: | |
| - all | |
| - nsisweb | |
| - appx | |
| default: 'all' | |
| sign: | |
| description: Do you wish to sign the Windows packages? | |
| type: choice | |
| required: false | |
| options: | |
| - true | |
| - false | |
| default: 'false' | |
| publish_to: | |
| description: Publish to GitHub releases or AWS S3? | |
| type: choice | |
| required: false | |
| options: | |
| - github | |
| - aws | |
| default: 'github' | |
| env: | |
| INPUT_VERSION: ${{ github.event.inputs.version }} | |
| INPUT_TARGET: ${{ github.event.inputs.target }} | |
| CRON_LAUNCHED: ${{ github.event.schedule }} | |
| INPUT_SIGN: ${{ github.event.inputs.sign || 'false' }} | |
| BUILD_PLATFORM: ${{ github.event.inputs.build_platform || 'all' }} | |
| WIN11_PACKAGES: ${{ github.event.inputs.win11packages }} | |
| PUBLISH_TO: ${{ github.event.inputs.publish_to }} | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| ESIGNER_USERNAME: ${{ secrets.ESIGNER_USER_USERNAME }} | |
| ESIGNER_PASSWORD: ${{ secrets.ESIGNER_USER_PASSWORD }} | |
| ESIGNER_TOTP_SECRET: ${{ secrets.ESIGNER_USER_TOTP_SECRET }} | |
| MASTER_KEY_FILE: "C:\\Users\\runneradmin\\eSignerCKA\\master.key" | |
| INSTALL_DIR: C:\Users\runneradmin\eSignerCKA | |
| SSH_KEY: ${{ secrets.KIWIXJSPWA_FILE_UPLOAD_KEY }} | |
| REF_NAME: ${{ github.ref_name }} | |
| jobs: | |
| Release_Linux: | |
| if: github.event.inputs.build_platform == 'all' || github.event.inputs.build_platform == 'linux' || github.event.inputs.build_platform == '' | |
| 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 | |
| if [[ $CRON_LAUNCHED = true ]]; then | |
| packagedFileGeneric=$(sed -E 's/_[0-9-]+(\.zim)/\1/' <<<"$packagedFile") | |
| echo -e "\nDownloading https://download.kiwix.org/zim/$packagedFileGeneric" | |
| 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 | |
| echo -e "\nDownloading https://mirror.download.kiwix.org/zim/$flavour/$packagedFile" | |
| 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: Configure publish target (GitHub or AWS S3) | |
| run: | | |
| if [[ "$PUBLISH_TO" == "aws" ]]; then | |
| echo "Configuring electron-builder to publish to AWS S3..." | |
| if [[ -n "$INPUT_VERSION" ]]; then | |
| VERSION=$(echo "$INPUT_VERSION" | sed -E 's/^v?([0-9]+\.[0-9]+\.[0-9]+).*/\1/') | |
| echo "Extracted version from INPUT_VERSION: $VERSION" | |
| else | |
| echo "No INPUT_VERSION provided, reading version from init.js..." | |
| VERSION=$(grep 'params\[.appVersion' www/js/init.js | sed -E "s/[^[:digit:]]+([^\"']+).*/\1/" | sed -E 's/^([0-9]+\.[0-9]+\.[0-9]+).*/\1/') | |
| echo "Extracted version from init.js: $VERSION" | |
| fi | |
| if [[ -z "$VERSION" ]]; then | |
| echo "ERROR: Could not determine version number" | |
| exit 1 | |
| fi | |
| node -e " | |
| const fs = require('fs'); | |
| const pkg = JSON.parse(fs.readFileSync('./package.json', 'utf8')); | |
| const s3Config = { | |
| provider: 's3', | |
| bucket: 'org-kiwix-download.branded-apps', | |
| endpoint: 'https://s3.eu-west-2.wasabisys.com', | |
| path: 'WikiMed/v${VERSION}/', | |
| acl: 'public-read' | |
| }; | |
| if (pkg.build.linux) pkg.build.linux.publish = [s3Config]; | |
| fs.writeFileSync('./package.json', JSON.stringify(pkg, null, 2)); | |
| console.log('S3 path configured as:', s3Config.path); | |
| " | |
| echo "Builds will upload to: s3://org-kiwix-download.branded-apps/WikiMed/v${VERSION}/" | |
| else | |
| echo "Using default GitHub publish configuration" | |
| fi | |
| - name: Build and publish 64bit | |
| env: | |
| USE_HARD_LINKS: false | |
| AWS_ACCESS_KEY_ID: ${{ secrets.S3_ACCESS_KEY }} | |
| AWS_SECRET_ACCESS_KEY: ${{ secrets.S3_SECRET_KEY }} | |
| 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 "Copying package.json to dist" | |
| cp ./package.json ./dist/package.json | |
| echo "Installing dependencies in dist" | |
| cd dist && npm install && cd .. | |
| PUBLISH_FLAG="never" | |
| if [[ "$PUBLISH_TO" == "aws" ]]; then | |
| PUBLISH_FLAG="always" | |
| fi | |
| 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 --publish $PUBLISH_FLAG --projectDir dist | |
| else | |
| npx electron-builder --linux AppImage:x64 AppImage:arm64 deb:x64 --publish $PUBLISH_FLAG --projectDir dist | |
| fi | |
| - name: Build and publish 32bit | |
| env: | |
| USE_HARD_LINKS: false | |
| AWS_ACCESS_KEY_ID: ${{ secrets.S3_ACCESS_KEY }} | |
| AWS_SECRET_ACCESS_KEY: ${{ secrets.S3_SECRET_KEY }} | |
| 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 .. | |
| PUBLISH_FLAG="never" | |
| if [[ "$PUBLISH_TO" == "aws" ]]; then | |
| PUBLISH_FLAG="always" | |
| fi | |
| echo "Building 32bit packages for ref_name=$REF_NAME..." | |
| if [[ $REF_NAME = "main" ]]; then | |
| npx electron-builder --linux AppImage:ia32 deb:ia32 rpm:ia32 --publish $PUBLISH_FLAG --projectDir dist | |
| else | |
| npx electron-builder --linux AppImage:ia32 --publish $PUBLISH_FLAG --projectDir dist | |
| fi | |
| - name: Upload packages to Kiwix | |
| if: github.ref_name == 'main' && github.event.inputs.target != 'artefacts' && github.event.inputs.publish_to != 'aws' | |
| 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_macOS: | |
| if: github.event.inputs.build_platform == 'all' || github.event.inputs.build_platform == 'macos' || github.event.inputs.build_platform == '' | |
| runs-on: macos-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 (BSD sed syntax for macOS) | |
| 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 | |
| if [[ $CRON_LAUNCHED = true ]]; then | |
| packagedFileGeneric=$(sed -E 's/_[0-9-]+(\.zim)/\1/' <<<"$packagedFile") | |
| echo -e "\nDownloading https://download.kiwix.org/zim/$packagedFileGeneric" | |
| 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 | |
| echo -e "\nDownloading https://mirror.download.kiwix.org/zim/$flavour/$packagedFile" | |
| 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: Configure publish target (GitHub or AWS S3) | |
| run: | | |
| if [[ "$PUBLISH_TO" == "aws" ]]; then | |
| echo "Configuring electron-builder to publish to AWS S3..." | |
| if [[ -n "$INPUT_VERSION" ]]; then | |
| VERSION=$(echo "$INPUT_VERSION" | sed -E 's/^v?([0-9]+\.[0-9]+\.[0-9]+).*/\1/') | |
| echo "Extracted version from INPUT_VERSION: $VERSION" | |
| else | |
| echo "No INPUT_VERSION provided, reading version from init.js..." | |
| VERSION=$(grep 'params\[.appVersion' www/js/init.js | sed -E "s/[^[:digit:]]+([^\"']+).*/\1/" | sed -E 's/^([0-9]+\.[0-9]+\.[0-9]+).*/\1/') | |
| echo "Extracted version from init.js: $VERSION" | |
| fi | |
| if [[ -z "$VERSION" ]]; then | |
| echo "ERROR: Could not determine version number" | |
| exit 1 | |
| fi | |
| echo "S3_VERSION=$VERSION" >> $GITHUB_ENV | |
| node -e " | |
| const fs = require('fs'); | |
| const pkg = JSON.parse(fs.readFileSync('./package.json', 'utf8')); | |
| const s3Config = { | |
| provider: 's3', | |
| bucket: 'org-kiwix-download.branded-apps', | |
| endpoint: 'https://s3.eu-west-2.wasabisys.com', | |
| path: 'WikiMed/v${VERSION}/', | |
| acl: 'public-read' | |
| }; | |
| if (pkg.build.mac) pkg.build.mac.publish = [s3Config]; | |
| fs.writeFileSync('./package.json', JSON.stringify(pkg, null, 2)); | |
| " | |
| echo "S3 publish configuration injected into package.json" | |
| echo "Builds will upload to: s3://org-kiwix-download.branded-apps/WikiMed/v${VERSION}/" | |
| else | |
| echo "Using default GitHub publish configuration" | |
| fi | |
| - name: Build macOS packages (High Sierra/Mojave compatible) | |
| env: | |
| USE_HARD_LINKS: false | |
| run: | | |
| # Save the original Electron version (just the version string, no quotes) | |
| ORIGINAL_ELECTRON_VERSION=$(grep -m1 '"electron":' ./package.json | sed -E 's/.*"electron"[^"]*"([^"]+)".*/\1/') | |
| echo "Original Electron version: $ORIGINAL_ELECTRON_VERSION" | |
| echo "ORIGINAL_ELECTRON_VERSION=$ORIGINAL_ELECTRON_VERSION" >> $GITHUB_ENV | |
| echo "Changing Electron version to exactly 26.6.10 (last to support macOS 10.13+) in ./package.json" | |
| sed -i '' -E 's/"electron"[[:space:]]*:[[:space:]]*"[^"]+"/"electron": "26.6.10"/' ./package.json | |
| echo "Verifying package.json has exact version (no ^ or ~):" | |
| grep '"electron":' ./package.json | |
| echo "Copying the package.json to dist" | |
| cp ./package.json ./dist/package.json | |
| cp ./package-lock.json ./dist/package-lock.json | |
| echo "Removing old Electron and installing exactly 26.6.10 in root and dist" | |
| npm uninstall electron && npm install electron@26.6.10 --save-exact --save-dev | |
| cd dist && npm install electron@26.6.10 --save-exact --save-dev && cd .. | |
| echo "Verifying installed Electron version..." | |
| npx electron --version | |
| echo "Building macOS packages for High Sierra/Mojave..." | |
| if [[ $REF_NAME = "main" ]]; then | |
| npx electron-builder --mac zip:x64 --publish never --projectDir dist | |
| else | |
| npx electron-builder --mac zip:x64 --publish never --projectDir dist | |
| fi | |
| echo "Renaming High Sierra package..." | |
| cd dist/bld/Electron | |
| for file in *.zip; do | |
| if [[ -f "$file" ]] && [[ "$file" =~ -mac\.zip$ ]]; then | |
| newname="${file/-mac.zip/-macOS-HighSierra.zip}" | |
| mv "$file" "$newname" | |
| echo "Renamed High Sierra build: $file -> $newname" | |
| if [[ -f "${file}.blockmap" ]]; then | |
| mv "${file}.blockmap" "${newname}.blockmap" | |
| fi | |
| fi | |
| done | |
| # echo "Removing blockmap files (autoupdate not supported for renamed packages)..." | |
| # rm -f *.blockmap | |
| cd ../../.. | |
| echo "Restoring original Electron version: $ORIGINAL_ELECTRON_VERSION" | |
| sed -i '' -E "s/\"electron\"[[:space:]]*:[[:space:]]*\"[^\"]+\"/\"electron\": \"$ORIGINAL_ELECTRON_VERSION\"/" ./package.json | |
| echo "Verifying restoration:" | |
| grep '"electron":' ./package.json | |
| - name: Build macOS packages (modern) | |
| env: | |
| USE_HARD_LINKS: false | |
| run: | | |
| echo "Reinstalling dependencies with modern Electron version in root and dist" | |
| cp ./package.json ./dist/package.json | |
| cp ./package-lock.json ./dist/package-lock.json | |
| npm install | |
| cd dist && npm uninstall electron && npm install electron --save-dev && cd .. | |
| echo "Verifying Electron versions before building..." | |
| echo "Checking package.json electron entry:" | |
| grep '"electron":' ./package.json | |
| echo "Root Electron version:" | |
| npx electron --version | |
| echo "Dist Electron version:" | |
| cd dist && npx electron --version && cd .. | |
| EXPECTED_VERSION=$(grep -m1 '"electron":' ./package.json | sed -E 's/.*"electron"[^"]*"([^"]+)".*/\1/' | sed -E 's/^[\^~]//') | |
| echo "DEBUG: Extracted EXPECTED_VERSION='$EXPECTED_VERSION'" | |
| ACTUAL_VERSION=$(cd dist && npx electron --version | sed 's/^v//') | |
| echo "Expected: $EXPECTED_VERSION, Actual in dist: $ACTUAL_VERSION" | |
| if [[ "$ACTUAL_VERSION" != "$EXPECTED_VERSION" ]]; then | |
| echo "ERROR: Electron version mismatch! Expected $EXPECTED_VERSION but got $ACTUAL_VERSION" | |
| else | |
| echo "✓ Electron versions verified successfully" | |
| fi | |
| echo "Building modern macOS packages for ref_name=$REF_NAME..." | |
| npx electron-builder --mac zip:x64 zip:arm64 --publish never --projectDir dist | |
| echo "Renaming modern macOS packages to avoid conflicts..." | |
| cd dist/bld/Electron | |
| for file in *.zip; do | |
| if [[ -f "$file" ]]; then | |
| newname="" | |
| if [[ "$file" =~ -arm64-mac\.zip$ ]]; then | |
| # Rename the ARM64 build | |
| newname="${file/-arm64-mac.zip/-macOS-arm64.zip}" | |
| elif [[ "$file" =~ -mac\.zip$ ]]; then | |
| # This is the x64 modern build, rename it to indicate architecture | |
| newname="${file/-mac.zip/-macOS-x64.zip}" | |
| fi | |
| if [[ -n "$newname" ]]; then | |
| mv "$file" "$newname" | |
| echo "Renamed build: $file -> $newname" | |
| if [[ -f "${file}.blockmap" ]]; then | |
| mv "${file}.blockmap" "${newname}.blockmap" | |
| fi | |
| fi | |
| fi | |
| done | |
| # echo "Removing blockmap files (autoupdate not supported for renamed packages)..." | |
| # rm -f *.blockmap | |
| cd ../../.. | |
| - name: Smoke test Electron app | |
| run: | | |
| echo "Extracting macOS app for testing..." | |
| cd dist/bld/Electron | |
| # Find the first zip file (prefer x64 if available) | |
| ZIP_FILE=$(ls -1 *.zip | head -1) | |
| echo "Found zip file: $ZIP_FILE" | |
| # Extract the zip file | |
| unzip -q "$ZIP_FILE" | |
| # Find the .app bundle | |
| APP_BUNDLE=$(find . -name "*.app" -type d | head -1) | |
| echo "Found app bundle: $APP_BUNDLE" | |
| if [ -z "$APP_BUNDLE" ]; then | |
| echo "Error: No .app bundle found!" | |
| exit 1 | |
| fi | |
| # Remove quarantine attribute (required for CI) | |
| xattr -dr com.apple.quarantine "$APP_BUNDLE" || true | |
| # Test basic app launch (verify it can start without crashing) | |
| echo "Testing app launch..." | |
| # Determine the executable name based on the app bundle name | |
| APP_NAME=$(basename "$APP_BUNDLE" .app) | |
| EXECUTABLE_PATH="$APP_BUNDLE/Contents/MacOS/$APP_NAME" | |
| echo "Using executable: $EXECUTABLE_PATH" | |
| # Verify executable exists | |
| if [ ! -f "$EXECUTABLE_PATH" ]; then | |
| echo "Error: Executable not found at $EXECUTABLE_PATH" | |
| ls -la "$APP_BUNDLE/Contents/MacOS/" | |
| exit 1 | |
| fi | |
| "$EXECUTABLE_PATH" \ | |
| --disable-gpu-sandbox \ | |
| --no-sandbox \ | |
| --disable-web-security \ | |
| --disable-dev-shm-usage \ | |
| --no-first-run \ | |
| --disable-default-apps & | |
| APP_PID=$! | |
| echo "Started app with PID: $APP_PID" | |
| # Wait for app to start and check if process is running | |
| sleep 8 | |
| if kill -0 $APP_PID 2>/dev/null; then | |
| echo "✅ App process is running successfully" | |
| # Check if app is responsive by looking at process details | |
| echo "Process details:" | |
| ps -p $APP_PID -o pid,ppid,time,command || true | |
| echo "App is running and responsive" | |
| # Kill app gracefully | |
| kill -TERM $APP_PID 2>/dev/null || true | |
| sleep 3 | |
| # Force kill if still running | |
| if kill -0 $APP_PID 2>/dev/null; then | |
| echo "Force killing app..." | |
| kill -KILL $APP_PID 2>/dev/null || true | |
| fi | |
| echo "✅ App launched and terminated successfully" | |
| else | |
| echo "❌ App process failed to start or crashed immediately" | |
| exit 1 | |
| fi | |
| echo "Smoke test completed successfully" | |
| - name: Upload macOS builds to S3 | |
| if: env.PUBLISH_TO == 'aws' | |
| env: | |
| AWS_ACCESS_KEY_ID: ${{ secrets.S3_ACCESS_KEY }} | |
| AWS_SECRET_ACCESS_KEY: ${{ secrets.S3_SECRET_KEY }} | |
| run: | | |
| which aws || pip3 install awscli --quiet | |
| ENDPOINT="https://s3.eu-west-2.wasabisys.com" | |
| S3_PATH="s3://org-kiwix-download.branded-apps/WikiMed/v${S3_VERSION}" | |
| echo "Uploading macOS builds to $S3_PATH ..." | |
| for file in dist/bld/Electron/*.zip; do | |
| if [[ -f "$file" ]]; then | |
| filename=$(basename "$file") | |
| echo "Uploading $filename..." | |
| aws s3 cp "$file" "$S3_PATH/$filename" --endpoint-url "$ENDPOINT" --no-progress | |
| fi | |
| done | |
| echo "macOS upload complete." | |
| - name: Publish packages to GitHub | |
| if: github.event.inputs.target == 'release' && github.event.inputs.publish_to != 'aws' | |
| run: | | |
| chmod +x ./scripts/publish_macos_packages_to_github.sh | |
| ./scripts/publish_macos_packages_to_github.sh | |
| - name: Upload packages to Kiwix | |
| if: github.ref_name == 'main' && github.event.inputs.target != 'artefacts' && github.event.inputs.publish_to != 'aws' | |
| run: | | |
| echo "$SSH_KEY" > ./scripts/ssh_key | |
| chmod 600 ./scripts/ssh_key | |
| chmod +x ./scripts/publish_macos_packages_to_kiwix.sh | |
| ./scripts/publish_macos_packages_to_kiwix.sh | |
| - name: Archive build artefacts | |
| if: github.event.inputs.target == 'artefacts' | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: kiwix-js-electron_macos | |
| path: | | |
| dist/bld/Electron/*.zip | |
| Release_Windows: | |
| if: github.event.inputs.build_platform == 'all' || github.event.inputs.build_platform == 'windows' || github.event.inputs.build_platform == 'win7' || github.event.inputs.build_platform == 'win11' || github.event.inputs.build_platform == '' | |
| runs-on: windows-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-node@v4 | |
| - name: Find and set signtool.exe path | |
| if: github.event.inputs.sign == 'true' | |
| shell: powershell | |
| run: | | |
| # Find the latest available Windows SDK version with signtool | |
| $sdkPath = "C:\Program Files (x86)\Windows Kits\10\bin" | |
| if (Test-Path $sdkPath) { | |
| $latestSdk = Get-ChildItem $sdkPath -Directory | | |
| Where-Object { $_.Name -match '^\d+\.\d+\.\d+\.\d+$' } | | |
| Sort-Object Name -Descending | | |
| Select-Object -First 1 | |
| if ($latestSdk) { | |
| $signtoolPath = Join-Path $latestSdk.FullName "x86\signtool.exe" | |
| if (Test-Path $signtoolPath) { | |
| echo "Found signtool at: $signtoolPath" | |
| echo "SIGNTOOL_PATH=$signtoolPath" >> $env:GITHUB_ENV | |
| } else { | |
| # Try x64 version | |
| $signtoolPath = Join-Path $latestSdk.FullName "x64\signtool.exe" | |
| if (Test-Path $signtoolPath) { | |
| echo "Found signtool at: $signtoolPath" | |
| echo "SIGNTOOL_PATH=$signtoolPath" >> $env:GITHUB_ENV | |
| } else { | |
| echo "ERROR: signtool.exe not found in SDK version $($latestSdk.Name)" | |
| exit 1 | |
| } | |
| } | |
| } else { | |
| echo "ERROR: No Windows SDK found at $sdkPath" | |
| exit 1 | |
| } | |
| } else { | |
| echo "ERROR: Windows SDK path does not exist: $sdkPath" | |
| exit 1 | |
| } | |
| - 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 | |
| if ($CRON_LAUNCHED) { | |
| $packagedFileGeneric = $packagedFile -replace '_[0-9-]+(\.zim)', '$1' | |
| Write-Host "`nDownloading https://download.kiwix.org/zim/$packagedFileGeneric" | |
| Invoke-WebRequest "https://download.kiwix.org/zim/$packagedFileGeneric" -OutFile "archives\$packagedFile" | |
| } else { | |
| $flavour = $packagedFile -replace '^([^_]+)_.+$', '$1' | |
| if ($flavour -eq 'mdwiki') { | |
| $flavour = 'other' | |
| } | |
| Write-Host "`nDownloading https://mirror.download.kiwix.org/zim/$flavour/$packagedFile" | |
| 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: Install and configure eSigner CKA and Windows SDK | |
| if: github.event.inputs.sign == 'true' | |
| env: | |
| ESIGNER_URL: https://github.com/SSLcom/eSignerCKA/releases/download/v1.0.7/SSL.COM-eSigner-CKA_1.0.7.zip | |
| run: | | |
| Set-StrictMode -Version 'Latest' | |
| # Download and Unzip eSignerCKA Setup | |
| Invoke-WebRequest -OutFile eSigner_CKA_Setup.zip "$env:ESIGNER_URL" | |
| Expand-Archive -Force eSigner_CKA_Setup.zip | |
| Remove-Item eSigner_CKA_Setup.zip | |
| Move-Item -Destination “eSigner_CKA_Installer.exe” -Path “eSigner_CKA_*\*.exe” | |
| # Install eSignerCKA | |
| New-Item -ItemType Directory -Force -Path ${{ env.INSTALL_DIR }} | |
| ./eSigner_CKA_Installer.exe /CURRENTUSER /VERYSILENT /SUPPRESSMSGBOXES /DIR=”${{ env.INSTALL_DIR }}” | Out-Null | |
| # Disable logger | |
| $LogConfig = Get-Content -Path ${{ env.INSTALL_DIR }}/log4net.config | |
| $LogConfig[0] = '<log4net threshold="OFF">' | |
| $LogConfig | Set-Content -Path ${{ env.INSTALL_DIR }}/log4net.config | |
| # Configure | |
| ${{ env.INSTALL_DIR }}/eSignerCKATool.exe config -mode product -user "${{ env.ESIGNER_USERNAME }}" -pass "${{ env.ESIGNER_PASSWORD }}" -totp "${{ env.ESIGNER_TOTP_SECRET }}" -key "${{ env.MASTER_KEY_FILE }}" -r | |
| ${{ env.INSTALL_DIR }}/eSignerCKATool.exe unload | |
| ${{ env.INSTALL_DIR }}/eSignerCKATool.exe load | |
| # Find certificate | |
| $CodeSigningCert = Get-ChildItem Cert:\CurrentUser\My -CodeSigningCert | Select-Object -First 1 | |
| echo Certificate: $CodeSigningCert | |
| # Extract thumbprint and subject name | |
| $Thumbprint = $CodeSigningCert.Thumbprint | |
| $SubjectName = ($CodeSigningCert.Subject -replace ", ?", "`n" | ConvertFrom-StringData).CN | |
| ls -l ${{ env.MASTER_KEY_FILE }} | |
| echo "ED_SIGNTOOL_THUMBPRINT=$Thumbprint" >> $env:GITHUB_ENV | |
| echo "ED_SIGNTOOL_SUBJECT_NAME=$SubjectName" >> $env:GITHUB_ENV | |
| - name: Configure publish target (GitHub or AWS S3) | |
| shell: powershell | |
| run: | | |
| $PUBLISH_TO = $Env:PUBLISH_TO | |
| $INPUT_VERSION = $Env:INPUT_VERSION | |
| if ($PUBLISH_TO -eq 'aws') { | |
| echo "Configuring electron-builder to publish to AWS S3..." | |
| $VERSION = $INPUT_VERSION -replace '^v([0-9.]+).*', '$1' | |
| $packageJson = Get-Content -Raw ./package.json | ConvertFrom-Json | |
| # Replace GitHub publish config with S3 config in win, mac, and linux sections | |
| $s3Config = @{ | |
| provider = "s3" | |
| bucket = "org-kiwix-download.branded-apps" | |
| endpoint = "https://s3.eu-west-2.wasabisys.com" | |
| path = "WikiMed/v$VERSION/" | |
| acl = "public-read" | |
| } | |
| $packageJson.build.win.publish = @($s3Config) | |
| if ($packageJson.build.PSObject.Properties.Name -contains 'mac') { | |
| $packageJson.build.mac.publish = @($s3Config) | |
| } | |
| if ($packageJson.build.PSObject.Properties.Name -contains 'linux') { | |
| $packageJson.build.linux.publish = @($s3Config) | |
| } | |
| # Configure nsis-web appPackageUrl to point to S3 | |
| $s3BaseUrl = "https://s3.eu-west-2.wasabisys.com/org-kiwix-download.branded-apps/WikiMed/v$VERSION" | |
| if ($packageJson.build.PSObject.Properties.Name -contains 'nsisWeb') { | |
| $packageJson.build.PSObject.Properties.Remove('nsisWeb') | |
| } | |
| $packageJson.build | Add-Member -MemberType NoteProperty -Name 'nsisWeb' -Value ([PSCustomObject]@{ | |
| appPackageUrl = $s3BaseUrl | |
| }) | |
| $packageJson | ConvertTo-Json -Depth 100 | Set-Content ./package.json | |
| echo "S3 publish configuration injected into package.json" | |
| echo "nsis-web appPackageUrl set to: $s3BaseUrl" | |
| echo "Builds will upload to: s3://org-kiwix-download.branded-apps/WikiMed/v$VERSION/" | |
| } else { | |
| echo "Using default GitHub publish configuration" | |
| } | |
| - name: Run electron builder for Win 7/8/8.1 | |
| if: github.event.inputs.build_platform != 'win11' | |
| shell: powershell | |
| env: | |
| AWS_ACCESS_KEY_ID: ${{ secrets.S3_ACCESS_KEY }} | |
| AWS_SECRET_ACCESS_KEY: ${{ secrets.S3_SECRET_KEY }} | |
| run: | | |
| $GITHUB_TOKEN = $Env:GITHUB_TOKEN | |
| $INPUT_VERSION = $Env:INPUT_VERSION | |
| $INPUT_TARGET = $Env:INPUT_TARGET | |
| $CRON_LAUNCHED = $Env:CRON_LAUNCHED | |
| $INPUT_SIGN = !$CRON_LAUNCHED -and [System.Convert]::ToBoolean($Env:INPUT_SIGN) | |
| 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 "Copying the package.json to dist" | |
| cp ./package.json ./dist/package.json | |
| cp ./package-lock.json ./dist/package-lock.json | |
| echo "Installing dependencies in root and dist" | |
| npm install; cd dist; npm install; cd .. | |
| echo "Installed Electron version:$(npx electron --version)" | |
| # Check if this is WikiMed (NSIS Setup too large to sign) | |
| $packageName = (Get-Content ./package.json | ConvertFrom-Json).name | |
| $isWikiMed = $packageName -match 'wikimed' | |
| if ($isWikiMed) { | |
| # WikiMed: build unpacked dir + zip (NSIS Setup exe too large for signtool) | |
| echo "Building Windows 7+ unpacked app (no NSIS installer - package too large for signing)..." | |
| if ($INPUT_SIGN) { | |
| npx electron-builder build --win dir:ia32 --publish never --projectDir dist | |
| } else { | |
| echo "********************" | |
| echo "*** DEV: Packages are NOT signed, as requested! ***" | |
| echo "********************" | |
| npx electron-builder build --config ../scripts/electronBuilder.cjs --win dir:ia32 --publish never --projectDir dist | |
| } | |
| # Create portable zip with launcher scripts | |
| $unpacked = "dist/bld/Electron/win-ia32-unpacked" | |
| $foldername = "kiwix-js-pwa-win32-ia32" | |
| $productName = (Get-Content ./package.json | ConvertFrom-Json).productName | |
| $zipDir = "dist/bld/Electron/$foldername" | |
| if (Test-Path $zipDir) { rm -r $zipDir } | |
| mkdir $zipDir | |
| cp -r "$unpacked\*" $zipDir | |
| # Create launcher scripts | |
| $executable = (ls "$unpacked/*.exe" | Select-Object -First 1).Name | |
| $launcherStub = "dist/bld/Electron/Start $productName" | |
| $batch = "@cd `"$foldername`"`r`n@start `"$productName`" `"$executable`"`r`n" | |
| $batch > "$launcherStub.bat" | |
| $WshShell = New-Object -ComObject WScript.Shell | |
| $Shortcut = $WshShell.CreateShortcut("$launcherStub.lnk") | |
| $Shortcut.TargetPath = '%windir%\explorer.exe' | |
| $Shortcut.Arguments = "$foldername\$executable" | |
| $Shortcut.IconLocation = '%windir%\explorer.exe,12' | |
| $Shortcut.Save() | |
| $safeName = $productName -replace '\s', '-' | |
| $zipName = "$safeName-Win7-$INPUT_VERSION_E.zip" | |
| $zipPath = "dist/bld/Electron/$zipName" | |
| echo "Compressing to $zipPath..." | |
| # Use 7z instead of Compress-Archive (which has a 2GB stream limit) | |
| 7z a -tzip $zipPath "$launcherStub.bat" "$launcherStub.lnk" $zipDir | |
| # Upload to S3 if configured | |
| if ($Env:PUBLISH_TO -eq 'aws') { | |
| $VERSION = $Env:INPUT_VERSION -replace '^v([0-9.]+).*', '$1' | |
| $s3Path = "s3://org-kiwix-download.branded-apps/WikiMed/v$VERSION/$zipName" | |
| echo "Uploading $zipName to S3..." | |
| aws s3 cp $zipPath $s3Path --endpoint-url "https://s3.eu-west-2.wasabisys.com" --no-progress | |
| } | |
| ls ./dist/bld/Electron/ | |
| if ($Env:INPUT_TARGET -ne 'artefacts' -and $Env:PUBLISH_TO -ne 'aws') { | |
| & ./scripts/Publish-ElectronPackages.ps1 -githubonly -portableonly | |
| } | |
| } else { | |
| # Non-WikiMed: build standard NSIS Setup installer | |
| echo "Building Windows 7+ 32bit NSIS package..." | |
| if ($INPUT_SIGN) { | |
| npm run dist-win-nsis | |
| } else { | |
| echo "********************" | |
| echo "*** DEV: Build will appear to sign, but packages are NOT actually signed, as requested! ***" | |
| echo "********************" | |
| npm run dist-win-nsis-skipsigning | |
| } | |
| 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" | |
| } | |
| mv "dist/bld/Electron/latest.yml" "dist/bld/Electron/latest-win7.yml" | |
| ls ./dist/bld/Electron/ | |
| if ($INPUT_TARGET -ne 'artefacts') { | |
| & ./scripts/Publish-ElectronPackages.ps1 -githubonly | |
| } | |
| } | |
| ./scripts/Rewrite-DraftReleaseTag.ps1 | |
| - name: Run electron builder for Win 10/11 | |
| if: github.event.inputs.build_platform != 'win7' | |
| shell: powershell | |
| env: | |
| AWS_ACCESS_KEY_ID: ${{ secrets.S3_ACCESS_KEY }} | |
| AWS_SECRET_ACCESS_KEY: ${{ secrets.S3_SECRET_KEY }} | |
| run: | | |
| $GITHUB_TOKEN = $Env:GITHUB_TOKEN | |
| $INPUT_VERSION = $Env:INPUT_VERSION | |
| $INPUT_TARGET = $Env:INPUT_TARGET | |
| $CRON_LAUNCHED = $Env:CRON_LAUNCHED | |
| $INPUT_SIGN = !$CRON_LAUNCHED -and [System.Convert]::ToBoolean($Env:INPUT_SIGN) | |
| $ORIGINAL_ELECTRON_VERSION = $Env:ORIGINAL_ELECTRON_VERSION | |
| if (![string]::IsNullOrEmpty($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 | |
| } else { | |
| echo "Using Electron version defined in 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 "Copying the rewritten package.json to dist" | |
| cp ./package.json ./dist/package.json | |
| cp ./package-lock.json ./dist/package-lock.json | |
| echo "Installing dependencies in root and dist" | |
| npm install; cd dist; npm install; cd .. | |
| echo "Installed Electron version:$(npx electron --version)" | |
| $PUBLISH_TO = $Env:PUBLISH_TO | |
| $WIN11_PACKAGES = $Env:WIN11_PACKAGES | |
| echo "Building Windows packages (sign=$INPUT_SIGN, publish_to=$PUBLISH_TO, packages=$WIN11_PACKAGES)..." | |
| if (!$INPUT_SIGN) { | |
| echo "********************" | |
| echo "*** DEV: Packages are NOT signed, as requested! ***" | |
| echo "********************" | |
| } | |
| # Determine phase 1 build targets based on app type | |
| # WikiMed: skip NSIS Setup (too large for signtool) and portable (too large to self-extract) | |
| # Wikivoyage: skip portable (too large to self-extract) but keep NSIS Setup | |
| # Kiwix JS Electron: build all targets | |
| $packageName = (Get-Content ./package.json | ConvertFrom-Json).name | |
| $phase1Targets = @() | |
| if ($packageName -notmatch 'wikimed') { $phase1Targets += 'NSIS:ia32' } | |
| if ($packageName -notmatch 'wikimed|wikivoyage') { $phase1Targets += 'portable:ia32' } | |
| $phase1Targets += 'appx' | |
| $PHASE1_TARGETS = $phase1Targets -join ' ' | |
| echo "Phase 1 build targets: $PHASE1_TARGETS" | |
| # Build and publish to configured target (GitHub or S3) | |
| # The publish target was configured in package.json by the previous step | |
| # For AWS publishing, use --publish always to override the onTagOrDraft policy | |
| if ($PUBLISH_TO -eq 'aws') { | |
| # AWS S3 publishing - use --publish always | |
| switch ($WIN11_PACKAGES) { | |
| 'nsisweb' { | |
| if (!$INPUT_SIGN) { | |
| npx electron-builder build --config ../scripts/electronBuilder.cjs --win nsis-web --ia32 --x64 --arm64 --publish always --projectDir dist | |
| } else { | |
| npx electron-builder build --win nsis-web --ia32 --x64 --arm64 --publish always --projectDir dist | |
| } | |
| } | |
| 'appx' { | |
| if (!$INPUT_SIGN) { | |
| npx electron-builder build --config ../scripts/electronBuilder.cjs --win appx --publish always --projectDir dist | |
| } else { | |
| npx electron-builder build --win appx --publish always --projectDir dist | |
| } | |
| } | |
| default { | |
| if (!$INPUT_SIGN) { | |
| npx electron-builder build --config ../scripts/electronBuilder.cjs --win $PHASE1_TARGETS --publish always --projectDir dist | |
| node scripts/delete-latest-yml.js | |
| npx electron-builder build --config ../scripts/electronBuilder.cjs --win nsis-web --ia32 --x64 --arm64 --publish always --projectDir dist | |
| } else { | |
| npx electron-builder build --win $PHASE1_TARGETS --publish always --projectDir dist | |
| node scripts/delete-latest-yml.js | |
| npx electron-builder build --win nsis-web --ia32 --x64 --arm64 --publish always --projectDir dist | |
| } | |
| } | |
| } | |
| } else { | |
| # GitHub publishing - use default onTagOrDraft policy | |
| switch ($WIN11_PACKAGES) { | |
| 'nsisweb' { | |
| if (!$INPUT_SIGN) { | |
| npx electron-builder build --config ../scripts/electronBuilder.cjs --win nsis-web --ia32 --x64 --arm64 --projectDir dist | |
| } else { | |
| npx electron-builder build --win nsis-web --ia32 --x64 --arm64 --projectDir dist | |
| } | |
| } | |
| 'appx' { | |
| if (!$INPUT_SIGN) { | |
| npx electron-builder build --config ../scripts/electronBuilder.cjs --win appx --projectDir dist | |
| } else { | |
| npx electron-builder build --win appx --projectDir dist | |
| } | |
| } | |
| default { | |
| if (!$INPUT_SIGN) { | |
| npx electron-builder build --config ../scripts/electronBuilder.cjs --win $PHASE1_TARGETS --projectDir dist | |
| node scripts/delete-latest-yml.js | |
| npx electron-builder build --config ../scripts/electronBuilder.cjs --win nsis-web --ia32 --x64 --arm64 --projectDir dist | |
| } else { | |
| npx electron-builder build --win $PHASE1_TARGETS --projectDir dist | |
| node scripts/delete-latest-yml.js | |
| npx electron-builder build --win nsis-web --ia32 --x64 --arm64 --projectDir dist | |
| } | |
| } | |
| } | |
| } | |
| ./scripts/Rewrite-DraftReleaseTag.ps1 | |
| - name: Build portable Electron app | |
| if: github.event.inputs.build_platform != 'win7' && github.event.inputs.win11packages != 'nsisweb' && github.event.inputs.win11packages != 'appx' | |
| env: | |
| AWS_ACCESS_KEY_ID: ${{ secrets.S3_ACCESS_KEY }} | |
| AWS_SECRET_ACCESS_KEY: ${{ secrets.S3_SECRET_KEY }} | |
| 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 | |
| # Upload portable zip to S3 if configured | |
| if ($Env:PUBLISH_TO -eq 'aws') { | |
| $VERSION = $Env:INPUT_VERSION -replace '^v([0-9.]+).*', '$1' | |
| $s3Base = "s3://org-kiwix-download.branded-apps/WikiMed/v$VERSION" | |
| $zipFiles = Get-ChildItem "dist/bld/Electron/*.zip" | |
| foreach ($zip in $zipFiles) { | |
| # Skip the Win7 zip (already uploaded in the Win7 step) | |
| if ($zip.Name -notmatch 'Win7') { | |
| echo "Uploading $($zip.Name) to S3..." | |
| aws s3 cp $zip.FullName "$s3Base/$($zip.Name)" --endpoint-url "https://s3.eu-west-2.wasabisys.com" --no-progress | |
| } | |
| } | |
| } | |
| } | |
| - name: Publish packages | |
| if: github.event.inputs.build_platform != 'win7' && github.event.inputs.target != 'artefacts' && github.event.inputs.publish_to != 'aws' | |
| run: | | |
| $SSH_KEY = $Env:SSH_KEY | |
| $keyfile = ".\scripts\ssh_key" | |
| # Write SSH key with Unix line endings (LF only, no BOM) | |
| [System.IO.File]::WriteAllText($keyfile, $SSH_KEY + "`n", [System.Text.UTF8Encoding]::new($false)) | |
| $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 { | |
| echo "DEV: Note that only nightly builds launched from main will be published to the Kiwix server..." | |
| ./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' && (github.event.inputs.build_platform == 'all' || github.event.inputs.build_platform == '') | |
| 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 | |
| if ($CRON_LAUNCHED) { | |
| $packagedFileGeneric = $packagedFile -replace '_[0-9-]+(\.zim)', '$1' | |
| Write-Host "`nDownloading https://download.kiwix.org/zim/$packagedFileGeneric" | |
| Invoke-WebRequest "https://download.kiwix.org/zim/$packagedFileGeneric" -OutFile "archives\$packagedFile" | |
| } else { | |
| $flavour = $packagedFile -replace '^([^_]+)_.+$', '$1' | |
| if ($flavour -eq 'mdwiki') { | |
| $flavour = 'other' | |
| } | |
| Write-Host "`nDownloading https://mirror.download.kiwix.org/zim/$flavour/$packagedFile" | |
| 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 | |
| - name: Publish | |
| if: github.event.inputs.target != 'artefacts' | |
| run: | | |
| $SSH_KEY = $Env:SSH_KEY | |
| $keyfile = ".\scripts\ssh_key" | |
| # Write SSH key with Unix line endings (LF only, no BOM) | |
| [System.IO.File]::WriteAllText($keyfile, $SSH_KEY + "`n", [System.Text.UTF8Encoding]::new($false)) | |
| $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 | |
| } else { | |
| echo "DEV: Note that this is a manual test build from branch $Env:REF_NAME" | |
| ./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 |