開源專案 pyqt 軟體自動更新框架

Chenhappy發表於2022-08-13

開源專案地址 github.com/duolabmeng6/qtAutoUpdat...

GithubActions 專案釋出最佳實踐 pyqt軟體自動更新框架 無需伺服器搭建
www.bilibili.com/video/BV1Ud4y1K7r...

提供通用易於配置的 python 應用自動更新程式框架

適用於 pyinstaller 應用的自動更新 支援 pyqt 的應用 或者其他python應用使用

如果是 pyqt5 pyqt6 請自行修改 很簡單 很容易

本演示程式由 Pyside6 構建

由於搜遍了全網都沒有找到一個能用的且方便的 python 軟體自動更新的解決方案

考慮到自動更新的框架原理並不複雜 所以自己動手開始造輪子

以便後續開發的qt應用都能方便的更新迭代

這是一個全網唯一最易用的 python 應用通用全自動更新框架 無需自建伺服器 可跨平臺使用

  • 支援 MacOS 系統應用更新

  • 支援 Window 系統應用更新

  • 無需伺服器

  • 使用 Github 自動構建軟體和釋出軟體

  • 客戶端自動檢查 Github 中釋出的軟體資源並自動更新

  • 使用映象對國內的網路進行最佳化 避免無法下載更新的情況

image-20220724092930449

image-20220724092918002

image-20220724061909904

image-20220724035028662

檔案結構

│  my_app.py
│  my_app_win.spec                window 構建軟體配置
│  my_app_macos.spec            macos 構建軟體配置
│  app.icns                     macos 應用圖示
│  app.ico                      window 應用圖示
│  requirements.txt
│  run_write_version.py        構建時寫出的版本號檔案的指令碼
│  version.py                    版本號檔案 這個檔案構建會被覆蓋無需修改
│  版本描述.md                     釋出應用的描述內容
├─.github
│  └─workflows
│          釋出軟體.yml            自動構建版本號 編譯window軟體和macos軟體 自動釋出 
└─自動更新模組
    │  ui_winUpdate.py            ui介面檔案
    │  winUpdate.ui                qt designer 設計檔案
    │  __init__.py
    │  壓縮包檔案處理.py
    │  檔案下載模組.py
    │  視窗_更新軟體.py            
    │  自動更新模組.py
    │  自動更新讀取版本模組.py

主要複製

  • 自動更新模組/

  • .github/

  • run_write_version

  • version.py

1 作為子模組使用

git submodule add https://github.com/duolabmeng6/qtAutoUpdateApp qtAutoUpdateApp

當然直接下載本專案也是可以的

import qtAutoUpdateApp.自動更新模組 as 自動更新模組
import version
全域性變數_版本號 = version.version
全域性_專案名稱 = "duolabmeng6/QtEasyDesigner"
全域性_應用名稱 = "QtEasyDesigner.app"
全域性_當前版本 = version.version
全域性_官方網址 = "https://github.com/duolabmeng6/QtEasyDesigner"

2 檢查更新的回撥

    def 檢查更新回到回撥函式(self, 資料):
        # print("資料", 資料)
        最新版本號 = 資料['版本號']
        釋出時間 = 資料['釋出時間']
        釋出時間 = 到時間(釋出時間).取日期()
        try:
            最新版本 = f"最新版更新於:{釋出時間}({最新版本號})"
        except:
            pass
            最新版本 = "查詢失敗"
        self.狀態條標籤.setText(f"歡迎使用 Qt視窗設計器(QtEasyDesigner) 當前版本:{全域性變數_版本號} {最新版本}")

    def 更新版本號(self):
        self.檢查更新執行緒 = 自動更新模組.檢查更新執行緒(全域性_專案名稱, self.檢查更新回到回撥函式)
        self.檢查更新執行緒.start()

3 彈出軟體更新視窗

        if self.winUpdate is None:
            self.winUpdate = 自動更新模組.視窗_更新軟體(Github專案名稱=全域性_專案名稱,
                                            應用名稱=全域性_應用名稱,
                                            當前版本號=全域性_當前版本,
                                            官方網址=全域性_官方網址)
        self.winUpdate.show()

4 程式入口加入程式碼

自動化檢測是否能夠執行和一些啟動時的處理

if __name__ == '__main__':
    自動更新模組.初始化()

給自動化流程 測試軟體是否能開啟的

以上4個步驟就是在程式碼中的流程

還需要配置github自動構建的指令碼請自行修改~

配置檔案 自動化編譯指令碼

檔案位於 .github/workflows/釋出軟體.yml

1 構建版本號和變更資訊

  jobs_v:
    name: 構建版本號和變更資訊
    runs-on: ubuntu-latest
    outputs:
      version: ${{ steps.create_version.outputs.tag_name }} # 版本號
      body: ${{ steps.create_version.outputs.body }} # 版本變更內容
    steps:
      - uses: release-drafter/release-drafter@v5
        id: create_version
        with:
          config-name: release-drafter.yml # 配置檔案在 .github/release-drafter.yml
          disable-autolabeler: true # 禁止自動標籤
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
      - name: 檢視變數
        run: |
          echo ${{ format('version={0}', steps.create_version.outputs.tag_name ) }} 

這裡注意 輸出的變數 version 和 body 是版本號和釋出的內容

釋出的內容

檔案位於 .github/release-drafter.yml

name-template: 'v$RESOLVED_VERSION'
tag-template: 'v$RESOLVED_VERSION'
categories:
  - title: '? 新功能'
    labels:
      - '新功能'
  - title: '? Bug 修復'
    labels:
      - 'bug'
  - title: '? 日常維護'
    label: '日常維護'
change-template: '- $TITLE @$AUTHOR (#$NUMBER)'
change-title-escapes: '\<*_&'
version-resolver:
  major:
    labels:
      - 'major'
  minor:
    labels:
      - 'minor'
  patch:
    labels:
      - 'patch'
  default: patch
template: |
  # 自動更新程式
  * 更新了自動構建
  * 自動獲取版本
  * 自動下載
  * 自動替換

  $CHANGES
no-changes-template: |
  快下載體驗~

注意這裡的 labels 是需要 pull 打標籤才會生成的

template 為釋出的內容 其中 $CHANGES 是版本之間的變更 也是透過 pull 才會顯示的

pull 打標籤

image-20220727234218324

釋出版本時就會顯示

image-20220727234345559

標籤的配置

github.com/duolabmeng6/learn_actio...

注意一點 描述的內容必須刪除 否則構建時會報錯 版本變更將無法生產 刪除即正常

image-20220727234457303

2 構建window軟體

  jobs_window:
    needs: jobs_v
    name: 構建window軟體
    runs-on: windows-2022
    env:
      version: ${{ needs.jobs_v.outputs.version }}
      body: ${{ needs.jobs_v.outputs.body }}
    steps:
      - uses: actions/checkout@v3
        with:
          submodules: recursive
      - name: 讀入環境資訊
        run: |
          echo ${{ format('version {0}', env.version ) }} # 版本號
      - name: 編譯環境設定 Python 3.9.13
        uses: actions/setup-python@v4
        with:
          python-version: "3.9.13"
          architecture: "x64"
          cache: 'pip'
      - name: 下載依賴檔案
        run: pip install -r requirements.txt
      - name: 編譯exe
        run: |
          python run_write_version.py
          pyinstaller --noconfirm --onefile --windowed --icon "app.ico" "my_app.py"
      - name: 測試執行情況
        uses: GuillaumeFalourd/assert-command-line-output@v2
        with:
          command_line: ./dist/my_app.exe test
          contains: app run success
          expected_result: PASSED
      - name: 上傳產物
        uses: actions/upload-artifact@v3
        with:
          name: window
          path: ./dist/*.exe

3 構建macos軟體

  jobs_macos:
    needs: jobs_v
    name: 構建macos軟體
    runs-on: macos-12
    env:
      version: ${{ needs.jobs_v.outputs.version }}
      body: ${{ needs.jobs_v.outputs.body }}
    steps:
      - uses: actions/checkout@v3
        with:
          submodules: recursive
      - name: 讀入環境資訊
        run: |
          echo ${{ format('version {0}', env.version ) }}
      - name: 編譯環境設定 Python 3.9.13
        uses: actions/setup-python@v4
        with:
          python-version: "3.9.13"
          architecture: "x64"
          cache: 'pip'
      - name: 下載依賴檔案
        run: pip install -r requirements.txt
      - name: 編譯 MacOS.app
        run: |
          python run_write_version.py
          pyinstaller my_app_macos.spec
      - name: 測試執行情況
        uses: GuillaumeFalourd/assert-command-line-output@v2
        with:
          command_line: ./dist/my_app.app/Contents/MacOS/my_app test
          contains: app run success
          expected_result: PASSED
      - name: 建立壓縮包
        run: |
          cd ./dist
          zip -r ./my_app_MacOS.zip ./my_app.app
      - name: 上傳產物
        uses: actions/upload-artifact@v3
        with:
          name: macos
          path: ./dist/*.zip

4 釋出版本

  jobs4:
    needs: [ jobs_v,jobs_window,jobs_macos ]
    name: 釋出版本
    runs-on: ubuntu-latest
    env:
      version: ${{ needs.jobs_v.outputs.version }}
      body: ${{ needs.jobs_v.outputs.body }}
    steps:
      - name: 下載產物
        id: download
        uses: actions/download-artifact@v3
        with:
          path: ./
      - name: 讀入環境資訊
        run: |
          echo ${{ format('version {0}', env.version ) }}
          echo ${{steps.download.outputs.download-path}}
          ls -R

      - name: 釋出檔案
        uses: ncipollo/release-action@v1
        with:
          token: ${{ secrets.GITHUB_TOKEN }}
          allowUpdates: true # 覆蓋檔案
          #draft: true # 草稿 自己可見 版本號會保持一樣 預設是自動釋出 latest
          #prerelease: true # 預釋出 別人可以看到 版本號會繼續加
          tag: ${{ env.version }} # 版本號 v0.1.0
          body: ${{ env.body }} # 輸出的內容
          artifacts: "window/*.exe,macos/*.zip"

image-20220727234826096

image-20220727234856303

image-20220727234933101

pull 打標籤

image-20220727235347546

Sparkle

github.com/sparkle-project/Sparkle

Sparkle 需要使用 xcode 進行版本管理 十分麻煩當然也可以使用

思路

將 pyinstaller 構建好的應用內建在 xcode 程式碼中呼叫 就可以使用他進行更新

需要配置 秘鑰 各種亂七八糟的事情..不利於自動化

我認為這種操作本末倒置..雖然他的更新機制很棒~但是使用極其麻煩且需要自行配置伺服器

本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章