Skip to content

Open Source Electron Application GitHub Actions Automated Deployment and Upgrade Guide

1. Introduction

This article provides a detailed guide on how to use GitHub Actions to achieve automated building, publishing, and automatic updates for Electron applications through UpgradeLink. Through this guide, you will learn how to configure GitHub Actions workflows to complete the full automation process from code submission to application updates.

2. Core Tools Introduction

UpgradeLink provides a GitHub Action plugin for uploading Electron application generated update files to the UpgradeLink server. UpgradeLink reads the application file addresses from JSON files, saves the files, and automatically creates application version files and corresponding upgrade strategies.

2. Example Project with Complete Workflow

Example project with complete workflow:

3. Workflow Description

The workflow consists of three main jobs:

  1. electron-build: Build and publish Electron application packages for different platforms and architectures

    • Cross-platform building: Supports macOS, Linux, and Windows simultaneously
    • Version extraction: Extract application version number from Electron build output
  2. electron-release: Release versions based on packages built by electron-build

    • Release management: Automatically create GitHub Release and upload application installation packages
    • Output parameters: Output application version number for subsequent jobs
  3. upgradeLink-upload: Synchronize update information to UpgradeLink

    • Dependency: Waits for the completion of the above two jobs
    • Version awareness: Get application version number through output parameters
    • API calls: Use UpgradeLink Action to upload corresponding installation packages to the upgrade server

4. Integration Steps Detailed Explanation

1. Preparation

First, ensure that:

  • GitHub repository has been created and Electron application code has been uploaded
  • Have an UpgradeLink platform account and obtain the following credentials:
  • Configure the GitHub repository address in the electron application configuration on the UpgradeLink platform.

2. Configure GitHub Secrets

Add the following encrypted environment variables in GitHub repository Settings > Security > Secrets and variables > Actions:

Secret NameDescription
UPGRADE_LINK_ACCESS_KEYAccess key provided by UpgradeLink platform for API call authentication
UPGRADE_LINK_ELECTRON_KEYUnique identifier assigned by UpgradeLink platform for your Electron application

3. Edit electron-demo/.github/workflows/main.yml GitHub Action file, adjust according to your needs.

yaml
name: 'publish'

on:
  push:
    branches:
      - main
    tags:
      - '*.*.*'

jobs:
  electron-build:
    outputs:
      appVersion: ${{ steps.extract-version.outputs.appVersion }}
    permissions:
      contents: write
    strategy:
      fail-fast: false
      matrix:
        include:
          # Linux platform
          - platform: ubuntu-22.04
            target: x86_64-unknown-linux-gnu
            artifact-name: ubuntu-x86_64
            arch-suffix: x64
            # Directly define complete build command including channel information
            build-command: "yarn electron-builder --linux --x64 --publish always --config.publish.channel=latest-linux"

          - platform: ubuntu-22.04
            target: aarch64-unknown-linux-gnu
            artifact-name: ubuntu-aarch64
            arch-suffix: arm64
            build-command: "yarn electron-builder --linux --arm64 --publish always --config.publish.channel=latest-linux"

          # macOS platform
          - platform: macos-latest
            target: aarch64-apple-darwin
            artifact-name: macos-arm64
            arch-suffix: arm64
            build-command: "yarn electron-builder --mac --arm64 --publish always --config.publish.channel=latest-mac"

          - platform: macos-latest
            target: x86_64-apple-darwin
            artifact-name: macos-x64
            arch-suffix: x64
            build-command: "yarn electron-builder --mac --x64 --publish always --config.publish.channel=latest-mac"

          # Windows platform
          - platform: windows-latest
            target: x86_64-pc-windows-msvc
            artifact-name: windows-x64
            arch-suffix: x64
            build-command: "yarn electron-builder --win --x64 --publish always --config.publish.channel=latest-win"

    runs-on: ${{ matrix.platform }}
    steps:
      - uses: actions/checkout@v4

      - name: setup node
        uses: actions/setup-node@v4
        with:
          node-version: lts/*
          cache: 'yarn'

      - name: Install dependencies with yarn
        run: yarn install

      - name: List installed dependencies
        run: yarn list

      - name: install dependencies (ubuntu only)
        if: startsWith(matrix.platform, 'ubuntu')
        run: |
          sudo apt-get update
          sudo apt-get install -y libwebkit2gtk-4.1-dev libappindicator3-dev librsvg2-dev patchelf xdg-utils

      - name: install dependencies (macos only)
        if: matrix.platform == 'macos-latest'
        run: |
          brew install automake autoconf libtool

      - name: install frontend dependencies
        run: yarn install

      - name: Install rimraf
        run: yarn add rimraf --dev

      - name: Build Electron App
        # Directly execute the complete build command defined in the matrix
        run: ${{ matrix.build-command }}
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

      - name: Cleanup Artifacts for Linux
        if: startsWith(matrix.platform, 'ubuntu')
        run: |
          mkdir -p dist-temp
          find dist -maxdepth 1 -type f \( -name "*.AppImage" -o -name "*.yml" -o -name "*.zip" \) -exec cp {} dist-temp/ \;
          rm -rf dist
          mv dist-temp dist
          echo "保留的发布文件:"
          ls -la dist

      - name: Cleanup Artifacts for macOS
        if: matrix.platform == 'macos-latest'
        run: |
          mkdir -p dist-temp
          find dist -maxdepth 1 -type f \( -name "*.dmg" -o -name "*.pkg" -o -name "*.zip" -o -name "*.yml" \) -exec cp {} dist-temp/ \;
          rm -rf dist
          mv dist-temp dist
          echo "保留的发布文件:"
          ls -la dist

      - name: Cleanup Artifacts for Windows
        if: matrix.platform == 'windows-latest'
        run: |
          New-Item -ItemType Directory -Path dist-temp -Force | Out-Null
          Get-ChildItem -Path dist -File | Where-Object {
              $_.Name -like "*.exe" -or $_.Name -like "*.msi" -or $_.Name -like "*.zip" -or $_.Name -like "*.yml"
          } | Copy-Item -Destination dist-temp/
          Remove-Item -Path dist -Recurse -Force
          Rename-Item -Path dist-temp -NewName dist
          Write-Host "保留的发布文件:"
          Get-ChildItem -Path dist

      - name: Rename files with architecture suffix (Linux/macOS)
        if: startsWith(matrix.platform, 'ubuntu') || matrix.platform == 'macos-latest'
        run: |
          cd dist

          ARCH_SUFFIX="${{ matrix.arch-suffix }}"

          if [ "$ARCH_SUFFIX" != "x64" ] && [ "$ARCH_SUFFIX" != "arm64" ]; then
            echo "错误: 架构后缀不正确 - $ARCH_SUFFIX"
            exit 1
          fi

          # Process duplicate platform identifiers first
          for file in *.yml; do
            if [ -f "$file" ]; then
              # Fixed replacement -linux-linux to -linux
              if [[ "$file" == *-linux-linux* ]]; then
                new_file="${file//-linux-linux/-linux}"
                mv "$file" "$new_file"
                echo "替换重复标识: $file -> $new_file"
                file="$new_file"
              fi

              # Fixed replacement -mac-mac to -mac
              if [[ "$file" == *-mac-mac* ]]; then
                new_file="${file//-mac-mac/-mac}"
                mv "$file" "$new_file"
                echo "替换重复标识: $file -> $new_file"
                file="$new_file"
              fi
          
              # Fixed replacement x86_64-x64 to -x64
              if [[ "$file" == *-x86_64-x64* ]]; then
                new_file="${file//x86_64-x64/-x64}"
                mv "$file" "$new_file"
                echo "替换重复标识: $file -> $new_file"
                file="$new_file"
              fi

              # Process architecture suffix
              if [[ "$file" != *-"$ARCH_SUFFIX".* ]]; then
                filename="${file%.*}"
                extension="${file#$filename}"
                new_filename="${filename}-${ARCH_SUFFIX}${extension}"
                mv "$file" "$new_filename"
                echo "添加架构后缀: $file -> $new_filename"
              else
                echo "文件已处理完成: $file"
              fi
            fi
          done

          echo "最终文件列表:"
          ls -l

      - name: Rename files with architecture suffix (Windows)
        if: matrix.platform == 'windows-latest'
        run: |
          cd dist
          
          $ARCH_SUFFIX = "${{ matrix.arch-suffix }}"
          if ($ARCH_SUFFIX -ne "x64" -and $ARCH_SUFFIX -ne "arm64") {
            Write-Error "错误: 架构后缀不正确 - $ARCH_SUFFIX"
            exit 1
          }
          
          Get-ChildItem -File | ForEach-Object {
            $file = $_
            if ($file.Name -match "-$ARCH_SUFFIX\.[^.]+$") {
              Write-Host "文件已包含架构后缀: $($file.Name)"
            } else {
              $filename = $file.BaseName
              $extension = $file.Extension
              $new_filename = "$filename-$ARCH_SUFFIX$extension"
              Rename-Item -Path $file.FullName -NewName $new_filename
              Write-Host "重命名: $($file.Name) -> $new_filename"
            }
          }
          
          Write-Host "重命名后的文件:"
          Get-ChildItem -File

      - name: Extract version
        id: extract-version
        run: |
          # Prioritize getting version number from tag
          if [[ "${{ github.ref }}" == refs/tags/* ]]; then
            VERSION=${{ github.ref_name }}
          else
            # If not a tag push, read version number from package.json
            VERSION=$(node -p "require('./package.json').version")
            # Or use a fixed default value
            # VERSION="dev-$(date +%Y%m%d)"
          fi
          echo "appVersion=$VERSION" >> $GITHUB_OUTPUT
          echo "Extracted version: $VERSION"
        shell: bash

      - name: Upload artifacts
        uses: actions/upload-artifact@v4.0.0
        with:
          name: ${{ matrix.artifact-name }}
          path: dist/*
          if-no-files-found: error

  electron-release:
    needs: electron-build
    runs-on: ubuntu-22.04
    permissions:
      contents: write
    steps:
      - name: Download all artifacts
        uses: actions/download-artifact@v4
        with:
          path: artifacts
          merge-multiple: false

      - name: Verify artifact files
        run: |
          echo "下载的文件结构:"
          tree artifacts
          
          if [ -z "$(find artifacts -type f)" ]; then
            echo "错误: 没有找到任何artifact文件"
            exit 1
          fi

      - name: Prepare release files
        run: |
          mkdir -p release-files
          find artifacts -type f -exec cp {} release-files/ \;
          echo "准备发布的文件:"
          ls -l release-files

      - name: Create GitHub Release
        uses: softprops/action-gh-release@v1
        with:
          tag_name: ${{ needs.electron-build.outputs.appVersion }}
          name: Release ${{ needs.electron-build.outputs.appVersion }}
          files: release-files/*
          draft: false
          prerelease: false
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
yaml
  upgradeLink-upload:
     # Depend on both electron-build and electron-release to ensure access to electron-build output
     needs: [ electron-build, electron-release ]
     permissions:
       contents: write
     runs-on: ubuntu-latest
     steps:
       - name: Send a request to UpgradeLink
         uses: toolsetlink/upgradelink-action-electron@v1.0.1
         with:
           source-url: 'https://github.com/toolsetlink/electron-demo/releases/download/${{ needs.electron-build.outputs.appVersion }}'
           access-key: ${{ secrets.UPGRADE_LINK_ACCESS_KEY }}  # ACCESS_KEY key
           electron-key: ${{ secrets.UPGRADE_LINK_ELECTRON_KEY }}    # ELECTRON_KEY electron application unique identifier
           github-token: ${{ secrets.GITHUB_TOKEN }}
           version: ${{ needs.electron-build.outputs.appVersion }}
           prompt-upgrade-content: 'Upgrade prompt content'

5. Common Issues and Solutions

1. Signature Issues

2. Build Failure Troubleshooting

  • Check GitHub Actions logs for specific error information
  • Confirm all dependencies are correctly installed, especially system dependencies for Linux platform
  • Ensure Node.js version compatibility
  • Check if the application identifier in the UpgradeLink console matches the configuration
  • Confirm if correct installation package files are generated in GitHub Releases

6. Summary

Through the above configuration, you can achieve full automation of Electron application building, publishing, and update processes. Whenever code is pushed to the specified branch, GitHub Actions will automatically complete the following work:

  1. Detect code changes
  2. Build Electron application in multi-platform environments
  3. Create GitHub Release and upload installation packages
  4. Extract application version number
  5. Synchronize update information to the UpgradeLink platform
  6. End users will receive application update notifications through UpgradeLink

This automated workflow greatly improves development efficiency, reduces manual operation errors, and allows developers to focus more on application feature development.

toolsetlink@163.com