Skip to content

Руководство по автоматизированному развертыванию и обновлению Electron-приложений с помощью GitHub Actions

1. Введение

В этой статье представлено подробное руководство о том, как использовать GitHub Actions для достижения автоматизированной сборки, публикации и автоматических обновлений Electron-приложений через UpgradeLink. С помощью этого руководства вы узнаете, как настроить рабочие процессы GitHub Actions для завершения полного автоматизированного процесса от отправки кода до обновления приложения.

2. Введение в основные инструменты

UpgradeLink предоставляет плагин GitHub Action для загрузки сгенерированных файлов обновления Electron-приложений на сервер UpgradeLink. UpgradeLink читает адреса файлов приложения из JSON-файлов, сохраняет файлы и автоматически создает файлы версий приложения и соответствующие стратегии обновления.

2. Пример проекта с полным рабочим процессом

Пример проекта с полным рабочим процессом:

3. Описание рабочего процесса

Рабочий процесс состоит из трех основных заданий:

  1. electron-build: Сборка и публикация пакетов Electron-приложений для разных платформ и архитектур

    • Кроссплатформенная сборка: Поддерживает одновременно macOS, Linux и Windows
    • Извлечение версии: Извлечение номера версии приложения из выходных данных сборки Electron
  2. electron-release: Выпуск версий на основе пакетов, собранных electron-build

    • Управление выпусками: Автоматическое создание GitHub Release и загрузка установочных пакетов приложения
    • Параметры вывода: Вывод номера версии приложения для последующих заданий
  3. upgradeLink-upload: Синхронизация информации об обновлении с UpgradeLink

    • Зависимость: Ожидание завершения двух вышеупомянутых заданий
    • Учет версии: Получение номера версии приложения через параметры вывода
    • Вызовы API: Использование UpgradeLink Action для загрузки соответствующих установочных пакетов на сервер обновления

4. Подробное объяснение шагов интеграции

1. Подготовка

Сначала убедитесь, что:

  • Репозиторий GitHub создан и код Electron-приложения загружен
  • У вас есть аккаунт платформы UpgradeLink и получены следующие учетные данные:
  • На платформе UpgradeLink в конфигурации Electron-приложения настроен адрес репозитория GitHub.

2. Настройка GitHub Secrets

Добавьте следующие зашифрованные переменные среды в настройках репозитория GitHub > Security > Secrets and variables > Actions:

Название секретаОписание
UPGRADE_LINK_ACCESS_KEYКлюч доступа, предоставленный платформой UpgradeLink для аутентификации вызовов API
UPGRADE_LINK_ELECTRON_KEYУникальный идентификатор, присвоенный платформой UpgradeLink для вашего Electron-приложения

3. Отредактируйте файл GitHub Action electron-demo/.github/workflows/main.yml, скорректируйте в соответствии с вашими потребностями.

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: ubuntu-22.04
            target: x86_64-unknown-linux-gnu
            artifact-name: ubuntu-x86_64
            arch-suffix: x64
            # Прямое определение полной команды сборки с информацией о канале
            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: 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: 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
        # Прямое выполнение полной команды сборки, определенной в матрице
        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. Распространенные проблемы и их решения

1. Проблемы с подписью

2. Устранение неполадок при сбое сборки

  • Проверьте журналы GitHub Actions на наличие конкретной информации об ошибке
  • Убедитесь, что все зависимости правильно установлены, особенно системные зависимости для платформы Linux
  • Обеспечьте совместимость версии Node.js
  • Проверьте, соответствует ли идентификатор приложения в консоли UpgradeLink конфигурации
  • Убедитесь, что в GitHub Releases генерируются правильные файлы установочных пакетов

6. Резюме

С помощью вышеуказанной конфигурации вы можете достичь полной автоматизации процессов сборки, публикации и обновления Electron-приложений. Каждый раз, когда код отправляется в указанную ветку, GitHub Actions автоматически выполнит следующую работу:

  1. Обнаружение изменений в коде
  2. Сборка Electron-приложения в средах с несколькими платформами
  3. Создание GitHub Release и загрузка установочных пакетов
  4. Извлечение номера версии приложения
  5. Синхронизация информации об обновлении с платформой UpgradeLink
  6. Конечные пользователи получат уведомления об обновлении приложения через UpgradeLink

Этот автоматизированный рабочий процесс значительно повышает эффективность разработки, уменьшает ошибки при ручных операциях и позволяет разработчикам сосредоточиться больше на разработке функциональных возможностей приложения.

toolsetlink@163.com