# 多平台打包

# 整体流程

  • 修改electron-builder配置文件

    • 检查 是否有漏掉的文件
    • 检查 是否关闭了nortarize
  • 修改package.json-添加repo信息(建议)

  • 配置github actions

    • 如何测试(如何手动触发)
    • 如何配置secrets
    • 如何配置多环境
  • 配置mac的证书与nortarize:

    • p12证书

    • 个人API证书 + 密钥id + issue_id

      打开:https://appstoreconnect.apple.com/access/api

  • AutoUpdated

    • 不能设置tag参数
    • 私人仓库如何进行更新

# 前置准备

# 创建仓库

申请用户Github Token(权限是repo):

image-20220222140528463

需要在github仓库里面配置密钥:

image-20220222135716251

注意:

  • 名称不要随意修改;
  • 特别是GH_TOKEN这个必须是这个变量名称,存放上面申请的用户的token。

# 配置文件

name: Release
on:
  push:
    # 这里是触发条件
    branches:
      - main
      - master
    paths-ignore:
      - "**.md"
      - "**.spec.js"
      - ".idea"
      - ".gitignore"
      - ".github/**"
      - "!.github/workflows/release.yml"
  # Allows you to run this workflow manually from the Actions tab
  workflow_dispatch:

concurrency:
  group: release-${{ github.ref }}
  cancel-in-progress: true

defaults:
  run:
    shell: "bash"

jobs:
  # 形成github草稿
  draft:
    runs-on: ubuntu-latest
    outputs:
      release-note: ${{ steps.release-note.outputs.release-note }}
      version: ${{ steps.version.outputs.build-version }}

    steps:
      - uses: actions/checkout@v2
        with:
          fetch-depth: 0

      - uses: actions/setup-node@v2
        with:
          node-version: 14

      - name: Get last git tag
        id: tag
        run: echo "::set-output name=last-tag::$(git describe --tags --abbrev=0 || git rev-list --max-parents=0 ${{github.ref}})"

      # 产生日志
      - name: Generate release notes
        uses: ./.github/actions/release-notes
        id: release-note
        with:
          from: ${{ steps.tag.outputs.last-tag }}
          to: ${{ github.ref }}
          include-commit-body: true
          include-abbreviated-commit: true

      # 从当前的日期获取构建号
      - name: Get version from current date
        id: version
        run: echo "::set-output name=build-version::$(node -e "try{console.log(require('./electron-builder.config.js').extraMetadata.version)}catch(e){console.error(e);process.exit(1)}")"

      - name: Waiting on All checks
        uses: lewagon/wait-on-check-action@v0.2
        with:
          ref: ${{ github.ref }}
          repo-token: ${{ secrets.GH_TOKEN }}
          running-workflow-name: "draft"

      # 删除过期的Draft草稿
      - name: Delete outdated drafts
        uses: hugo19941994/delete-draft-releases@v1.0.0
        env:
          GITHUB_TOKEN: ${{ secrets.GH_TOKEN }}

      - name: Create Release Draft
        uses: softprops/action-gh-release@v1
        env:
          GITHUB_TOKEN: ${{ secrets.GH_TOKEN }}
        with:
          prerelease: true
          draft: true
          tag_name: v${{ steps.version.outputs.build-version }}
          name: v${{ steps.version.outputs.build-version }}
          body: ${{ steps.release-note.outputs.release-note }}

  upload_artifacts:
    needs: [draft]

    strategy:
      matrix:
        os: [windows-latest, macos-latest, ubuntu-latest]
    #    To compile the application for different platforms, use:
    #    os: [ macos-latest, ubuntu-latest, windows-latest ]

    runs-on: ${{ matrix.os }}

    steps:
      - uses: actions/checkout@v2

      - uses: actions/setup-node@v2
        with:
          node-version: 16 # Need for npm >=7.7
          cache: "npm"

      - name: Install dependencies
        run: npm ci

      # The easiest way to transfer release notes to a compiled application is create `release-notes.md` in the build resources.
      # See https://github.com/electron-userland/electron-builder/issues/1511#issuecomment-310160119
      - name: Prepare release notes
        env:
          RELEASE_NOTE: ${{ needs.draft.outputs.release-note }}
        run: echo "$RELEASE_NOTE" >> ./buildResources/release-notes.md

      - name: Prepare for app notarization
        if: startsWith(matrix.os, 'macos')
        # Import Apple API key for app notarization on macOS
        run: |
          mkdir -p ~/private_keys/
          echo '${{ secrets.api_key }}' > ~/private_keys/AuthKey_${{ secrets.api_key_id }}.p8

      # Compile app and upload artifacts
      - name: Compile & release Electron app
        uses: samuelmeuli/action-electron-builder@v1
        env:
          VITE_APP_VERSION: ${{ needs.draft.outputs.version }}
          # macOS notarization API key
          API_KEY_ID: ${{ secrets.api_key_id }}
          API_KEY_ISSUER_ID: ${{ secrets.api_key_issuer_id }}
        with:
          build_script_name: build
          args: --config electron-builder.config.js

          # GitHub token, automatically provided to the action
          # (No need to define this secret in the repo settings)
          github_token: ${{ secrets.GH_TOKEN }}

          # If the commit is tagged with a version (e.g. "v1.0.0"),
          # release the app after building
          release: true

          # Sometimes the build may fail due to a connection problem with Apple, GitHub, etc. servers.
          # This option will restart the build as many attempts as possible
          max_attempts: 3

          # Code Signing params

          # Base64-encoded code signing certificate for Windows
          # windows_certs: ''

          # Password for decrypting `windows_certs`
          # windows_certs_password: ''

          # Base64-encoded code signing certificate for macOS
          mac_certs: ${{ secrets.mac_certs }}

          # Password for decrypting `mac_certs`
          mac_certs_password: ${{ secrets.mac_certs_password }}

# 打包测试

  • 使用eslint + typescript的脚本进行全项目测试;
  • 安装依赖:npm i --package-lock-only,用于去产生package-lock.json,方便线上的CI/CD打包环境。
  • 最后就是compile打包
  • 申请Github Token,配置项目,新增Secrets
  • 然后上传代码,测试Github actions,添加release-notes。

# 自动化更新

设置自动化更新的功能,修改packages/main/src/index.ts

// 是否需要进行通知更新
const checkUpdate = async (flag = false) => {
  // 私有仓库:
  // autoUpdater.setFeedURL({
  //   provider: 'github',
  //   repo: 'repo',
  //   owner: 'owner',
  //   private: true,
  //   token: '<personal-access-token>'
  // })

  sendStatusToWindow('Start Checkding')

  flag ? autoUpdater.checkForUpdatesAndNotify() : autoUpdater.checkForUpdates()

  autoUpdater.on('checking-for-update', () => {
    sendStatusToWindow('Checking for update...')
  })
  autoUpdater.on('update-available', (info) => {
    const str = JSON.stringify(info)
    log.info(info)
    sendStatusToWindow('Update available.' + str)
  })
  autoUpdater.on('update-not-available', (info) => {
    const str = JSON.stringify(info)
    log.info(info)
    sendStatusToWindow('Update not available.' + str)
  })
  autoUpdater.on('error', (err) => {
    const str = JSON.stringify(err)
    sendStatusToWindow('Error in auto-updater. ' + str)
  })
  autoUpdater.on('download-progress', (progressObj) => {
    let log_message = 'Download speed: ' + progressObj.bytesPerSecond
    log_message = log_message + ' - Downloaded ' + progressObj.percent + '%'
    log_message = log_message + ' (' + progressObj.transferred + '/' + progressObj.total + ')'
    sendStatusToWindow(log_message)
  })
  autoUpdater.on('update-downloaded', (info) => {
    log.info(info)
    sendStatusToWindow('Update downloaded')
  })
}


// 添加一个检查更新的菜单
const template: MenuItemConstructorOptions[] = [
  { role: 'appMenu' },
  { role: 'fileMenu' },
  { role: 'editMenu' },
  { role: 'viewMenu' },
  { role: 'windowMenu' },
  {
    role: 'help',
    submenu: [
      {
        label: '查看帮助',
        click: async () => {
          await shell.openExternal('https://front-end.toimc.com')
        }
      },
      {
        label: '检查更新',
        click: async () => {
          checkUpdate()
        }
      }
    ]
  }
]

# 常见错误

  • 有一些tags不是自动生成的:

image-20211121193959489

删除本地的tag

git tag -d [tag-name]

删除远程tag

git push -d origin [tag-name]