Skip to content

Guia de Implantação e Atualização Automatizada do GitHub Actions para Aplicativos Electron de Código Aberto

1. Introdução

Este artigo fornece um guia detalhado sobre como usar o GitHub Actions para alcançar construção, publicação e atualizações automáticas de aplicativos Electron por meio do UpgradeLink. Por meio deste guia, você aprenderá como configurar fluxos de trabalho do GitHub Actions para completar o processo de automação total desde o envio de código até as atualizações do aplicativo.

2. Introdução às Ferramentas Core

O UpgradeLink fornece um plugin do GitHub Action para fazer upload de arquivos de atualização gerados por aplicativos Electron para o servidor do UpgradeLink. O UpgradeLink lê os endereços dos arquivos do aplicativo de arquivos JSON, salva os arquivos e cria automaticamente arquivos de versão do aplicativo e estratégias de atualização correspondentes.

2. Projeto de Exemplo com Fluxo de Trabalho Completo

Projeto de exemplo com fluxo de trabalho completo:

3. Descrição do Fluxo de Trabalho

O fluxo de trabalho consiste em três jobs principais:

  1. electron-build: Construir e publicar pacotes de aplicativos Electron para diferentes plataformas e arquiteturas

    • Construção multiplataforma: Suporta macOS, Linux e Windows simultaneamente
    • Extração de versão: Extrair número da versão do aplicativo do resultado da construção do Electron
  2. electron-release: Publicar versões com base nos pacotes construídos por electron-build

    • Gerenciamento de publicação: Criar automaticamente GitHub Release e fazer upload de pacotes de instalação do aplicativo
    • Parâmetros de saída: Saída do número da versão do aplicativo para jobs subsequentes
  3. upgradeLink-upload: Sincronizar informações de atualização com o UpgradeLink

    • Dependência: Aguarda a conclusão dos dois jobs acima
    • Conhecimento de versão: Obter o número da versão do aplicativo por meio de parâmetros de saída
    • Chamadas de API: Usar o UpgradeLink Action para fazer upload dos pacotes de instalação correspondentes para o servidor de atualização

4. Explicação Detalhada dos Passos de Integração

1. Preparação

Primeiro, certifique-se de que:

  • O repositório GitHub foi criado e o código do aplicativo Electron foi enviado
  • Tenha uma conta na plataforma UpgradeLink e obtenha as seguintes credenciais:
  • Configure o endereço do repositório GitHub na configuração do aplicativo electron na plataforma UpgradeLink.

2. Configurar GitHub Secrets

Adicione as seguintes variáveis de ambiente criptografadas em Configurações do Repositório GitHub > Segurança > Secrets and variables > Actions:

Nome do SecretDescrição
UPGRADE_LINK_ACCESS_KEYChave de acesso fornecida pela plataforma UpgradeLink para autenticação de chamada de API
UPGRADE_LINK_ELECTRON_KEYIdentificador único atribuído pela plataforma UpgradeLink para seu aplicativo Electron

3. Edite o arquivo electron-demo/.github/workflows/main.yml do GitHub Action, ajuste de acordo com suas necessidades.

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:
          # Plataforma Linux
          - platform: ubuntu-22.04
            target: x86_64-unknown-linux-gnu
            artifact-name: ubuntu-x86_64
            arch-suffix: x64
            # Definir comando de construção completo incluindo informações do canal
            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"

          # Plataforma 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"

          # Plataforma 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
        # Executar diretamente o comando de construção completo definido na matriz
        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 "Arquivos de publicação mantidos:"
          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 "Arquivos de publicação mantidos:"
          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 "Arquivos de publicação mantidos:"
          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 "Erro: Sufixo de arquitetura incorreto - $ARCH_SUFFIX"
            exit 1
          fi

          # Processar identificadores de plataforma duplicados primeiro
          for file in *.yml; do
            if [ -f "$file" ]; then
              # Substituição fixa -linux-linux para -linux
              if [[ "$file" == *-linux-linux* ]]; then
                new_file="${file//-linux-linux/-linux}"
                mv "$file" "$new_file"
                echo "Substituir identificador duplicado: $file -> $new_file"
                file="$new_file"
              fi

              # Substituição fixa -mac-mac para -mac
              if [[ "$file" == *-mac-mac* ]]; then
                new_file="${file//-mac-mac/-mac}"
                mv "$file" "$new_file"
                echo "Substituir identificador duplicado: $file -> $new_file"
                file="$new_file"
              fi
          
              # Substituição fixa x86_64-x64 para -x64
              if [[ "$file" == *-x86_64-x64* ]]; then
                new_file="${file//x86_64-x64/-x64}"
                mv "$file" "$new_file"
                echo "Substituir identificador duplicado: $file -> $new_file"
                file="$new_file"
              fi

              # Processar sufixo de arquitetura
              if [[ "$file" != *-"$ARCH_SUFFIX".* ]]; then
                filename="${file%.*}"
                extension="${file#$filename}"
                new_filename="${filename}-${ARCH_SUFFIX}${extension}"
                mv "$file" "$new_filename"
                echo "Adicionar sufixo de arquitetura: $file -> $new_filename"
              else
                echo "Arquivo processado: $file"
              fi
            fi
          done

          echo "Lista final de arquivos:"
          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 "Erro: Sufixo de arquitetura incorreto - $ARCH_SUFFIX"
            exit 1
          }
          
          Get-ChildItem -File | ForEach-Object {
            $file = $_
            if ($file.Name -match "-$ARCH_SUFFIX\.[^.]+$") {
              Write-Host "Arquivo já contém sufixo de arquitetura: $($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 "Renomear: $($file.Name) -> $new_filename"
            }
          }
          
          Write-Host "Arquivos após renomeação:"
          Get-ChildItem -File

      - name: Extract version
        id: extract-version
        run: |
          # Priorizar obtenção do número da versão do tag
          if [[ "${{ github.ref }}" == refs/tags/* ]]; then
            VERSION=${{ github.ref_name }}
          else
            # Se não for um push de tag, ler o número da versão do package.json
            VERSION=$(node -p "require('./package.json').version")
            # Ou usar um valor padrão fixo
            # VERSION="dev-$(date +%Y%m%d)"
          fi
          echo "appVersion=$VERSION" >> $GITHUB_OUTPUT
          echo "Versão extraída: $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 "Estrutura de arquivos baixados:"
          tree artifacts
          
          if [ -z "$(find artifacts -type f)" ]; then
            echo "Erro: Nenhum arquivo artifact encontrado"
            exit 1
          fi

      - name: Prepare release files
        run: |
          mkdir -p release-files
          find artifacts -type f -exec cp {} release-files/ \;
          echo "Arquivos preparados para publicação:"
          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:
     # Depender de ambos electron-build e electron-release para garantir acesso à saída do electron-build
     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 }}  # Chave ACCESS_KEY
           electron-key: ${{ secrets.UPGRADE_LINK_ELECTRON_KEY }}    # ELECTRON_KEY identificador único do aplicativo electron
           github-token: ${{ secrets.GITHUB_TOKEN }}
           version: ${{ needs.electron-build.outputs.appVersion }}
           prompt-upgrade-content: 'Conteúdo do prompt de atualização'

5. Problemas Comuns e Soluções

1. Problemas de Assinatura

2. Solução de Problemas de Falha de Construção

  • Verificar logs do GitHub Actions para informações específicas de erro
  • Confirmar que todas as dependências estão corretamente instaladas, especialmente dependências do sistema para a plataforma Linux
  • Garantir compatibilidade de versão do Node.js
  • Verificar se o identificador do aplicativo no console do UpgradeLink corresponde à configuração
  • Confirmar se os arquivos corretos de pacote de instalação são gerados nos GitHub Releases

6. Resumo

Por meio da configuração acima, você pode alcançar automação total dos processos de construção, publicação e atualização de aplicativos Electron. Sempre que o código for enviado para o branch especificado, o GitHub Actions completará automaticamente o seguinte trabalho:

  1. Detectar alterações no código
  2. Construir aplicativo Electron em ambientes multiplataforma
  3. Criar GitHub Release e fazer upload de pacotes de instalação
  4. Extrair número da versão do aplicativo
  5. Sincronizar informações de atualização com a plataforma UpgradeLink
  6. Usuários finais receberão notificações de atualização do aplicativo por meio do UpgradeLink

Este fluxo de trabalho automatizado melhora muito a eficiência do desenvolvimento, reduz erros de operação manual e permite que desenvolvedores se concentrem mais no desenvolvimento de recursos do aplicativo.

toolsetlink@163.com