Compare commits
8 commits
Author | SHA1 | Date | |
---|---|---|---|
c8c69a39b4 | |||
807d4d0585 | |||
cd5f999cda | |||
3452a924f9 | |||
86b4b50b99 | |||
46da0c049b | |||
c820fb9421 | |||
7dfed6af6c |
4 changed files with 167 additions and 18 deletions
144
.forgejo/workflows/build_all.yaml
Normal file
144
.forgejo/workflows/build_all.yaml
Normal file
|
@ -0,0 +1,144 @@
|
||||||
|
name: Build all artifacts and make release
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
build:
|
||||||
|
description: 'Select build type'
|
||||||
|
required: true
|
||||||
|
default: 'all'
|
||||||
|
type: choice
|
||||||
|
options:
|
||||||
|
- all
|
||||||
|
- mac
|
||||||
|
- windows
|
||||||
|
- linux
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-macos:
|
||||||
|
if: ${{ github.event.inputs.build == 'all' || github.event.inputs.build == 'mac' }}
|
||||||
|
runs-on: macos-latest
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Download universal2 Python
|
||||||
|
run: |
|
||||||
|
curl -o python.pkg https://www.python.org/ftp/python/3.12.4/python-3.12.4-macos11.pkg
|
||||||
|
- name: Install Python
|
||||||
|
run: |
|
||||||
|
sudo installer -pkg python.pkg -target /
|
||||||
|
- name: Add Python to PATH
|
||||||
|
run: |
|
||||||
|
echo "/Library/Frameworks/Python.framework/Versions/3.12/bin" >> $GITHUB_PATH
|
||||||
|
- name: Verify Python installation
|
||||||
|
run: |
|
||||||
|
python3 --version
|
||||||
|
pip3 --version
|
||||||
|
- name: Install dependencies
|
||||||
|
run: |
|
||||||
|
pip3 install --upgrade pip
|
||||||
|
pip3 install pyinstaller
|
||||||
|
pip3 install --no-cache cffi --no-binary :all:
|
||||||
|
pip3 install --no-cache charset_normalizer --no-binary :all:
|
||||||
|
pip3 install -U --pre -f https://wxpython.org/Phoenix/snapshot-builds/ wxPython
|
||||||
|
pip3 install -r requirements.txt
|
||||||
|
- name: Build with PyInstaller
|
||||||
|
run: |
|
||||||
|
pyinstaller BTClockOTA-universal.spec
|
||||||
|
- name: Zip the app bundle
|
||||||
|
run: |
|
||||||
|
cd dist
|
||||||
|
zip -r BTClockOTA-macos-universal2.zip BTClockOTA.app
|
||||||
|
- name: Create DMG
|
||||||
|
run: |
|
||||||
|
mkdir dmg_temp
|
||||||
|
cp -R dist/BTClockOTA.app dmg_temp/
|
||||||
|
# Create the DMG file
|
||||||
|
hdiutil create -volname "BTClockOTA" -srcfolder dmg_temp -ov -format UDZO "dist/BTClockOTA-universal.dmg"
|
||||||
|
- name: Archive artifacts
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: macos-artifacts
|
||||||
|
path: |
|
||||||
|
dist/*
|
||||||
|
!dist/BTClockOTA.app
|
||||||
|
build-windows:
|
||||||
|
if: ${{ github.event.inputs.build == 'all' || github.event.inputs.build == 'windows' }}
|
||||||
|
runs-on: docker-amd64
|
||||||
|
container:
|
||||||
|
image: batonogov/pyinstaller-windows:latest
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Build with PyInstaller
|
||||||
|
run: |
|
||||||
|
python -m PyInstaller $SPECFILE
|
||||||
|
- name: Archive artifacts
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: windows-artifacts
|
||||||
|
path: dist/
|
||||||
|
build-linux:
|
||||||
|
if: ${{ github.event.inputs.build == 'all' || github.event.inputs.build == 'linux' }}
|
||||||
|
runs-on: docker-amd64
|
||||||
|
container:
|
||||||
|
image: ghcr.io/btclock/pyinstaller-wxpython-linux:latest
|
||||||
|
credentials:
|
||||||
|
username: dsbaars
|
||||||
|
password: ${{ secrets.GH_TOKEN }}
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Build with PyInstaller
|
||||||
|
run: |
|
||||||
|
python -m PyInstaller $SPECFILE &&
|
||||||
|
mv dist/BTClockOTA dist/BTClockOTA-linux-amd64
|
||||||
|
- name: Archive artifacts
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: linux-artifacts
|
||||||
|
path: dist/
|
||||||
|
release:
|
||||||
|
needs: [build-macos, build-windows, build-linux]
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Get current block
|
||||||
|
id: getBlockHeight
|
||||||
|
run: echo "blockHeight=$(curl -s https://mempool.space/api/blocks/tip/height)" >> $GITHUB_OUTPUT
|
||||||
|
- name: Get Windows Artifacts
|
||||||
|
if: ${{ always() }}
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: windows-artifacts
|
||||||
|
path: windows
|
||||||
|
- name: Get macOS Artifacts
|
||||||
|
if: ${{ always() }}
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: macos-artifacts
|
||||||
|
path: macos
|
||||||
|
- name: Get Linux Artifacts
|
||||||
|
if: ${{ always() }}
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: linux-artifacts
|
||||||
|
path: linux
|
||||||
|
- name: Create release
|
||||||
|
uses: ncipollo/release-action@v1
|
||||||
|
with:
|
||||||
|
tag: ${{ steps.getBlockHeight.outputs.blockHeight }}
|
||||||
|
commit: main
|
||||||
|
name: release-${{ steps.getBlockHeight.outputs.blockHeight }}
|
||||||
|
artifacts: "macos/**/*.dmg,macos/**/*.zip,windows/**/*.exe,linux/*"
|
||||||
|
allowUpdates: true
|
||||||
|
makeLatest: true
|
|
@ -93,18 +93,26 @@ class FwUpdater:
|
||||||
address, os.path.abspath(local_filename), FLASH))
|
address, os.path.abspath(local_filename), FLASH))
|
||||||
thread.start()
|
thread.start()
|
||||||
|
|
||||||
def start_fs_update(self, release_name, address):
|
def start_fs_update(self, release_name, address, hw_rev):
|
||||||
|
hw_rev_to_model = {
|
||||||
|
"REV_B_EPD_2_13": "littlefs_8MB",
|
||||||
|
"REV_V8_EPD_2_13": "littlefs_16MB",
|
||||||
|
"REV_A_EPD_2_9": "littlefs_4MB"
|
||||||
|
}
|
||||||
|
|
||||||
# Path to the firmware file
|
# Path to the firmware file
|
||||||
local_filename = f"{get_app_data_folder()}/{release_name}_littlefs.bin"
|
local_filename = f"{get_app_data_folder()}/{release_name}_{hw_rev_to_model.get(hw_rev, "littlefs_4MB")}.bin"
|
||||||
|
|
||||||
self.updatingName = address
|
self.updatingName = address
|
||||||
self.currentlyUpdating = True
|
self.currentlyUpdating = True
|
||||||
|
|
||||||
if self.event_cb is not None:
|
if self.event_cb is not None:
|
||||||
self.event_cb("Starting WebUI update")
|
self.event_cb(f"Starting WebUI update {local_filename}")
|
||||||
|
|
||||||
if os.path.exists(os.path.abspath(local_filename)):
|
if os.path.exists(os.path.abspath(local_filename)):
|
||||||
thread = Thread(target=self.run_fs_update, args=(
|
thread = Thread(target=self.run_fs_update, args=(
|
||||||
address, os.path.abspath(local_filename), SPIFFS))
|
address, os.path.abspath(local_filename), SPIFFS))
|
||||||
thread.start()
|
thread.start()
|
||||||
|
else:
|
||||||
|
if self.event_cb is not None:
|
||||||
|
self.event_cb(f"Firmware file not found: {local_filename}")
|
||||||
|
|
|
@ -80,6 +80,7 @@ class ActionButtonPanel(wx.Panel):
|
||||||
selected_index = self.device_list.GetFirstSelected()
|
selected_index = self.device_list.GetFirstSelected()
|
||||||
if selected_index != -1:
|
if selected_index != -1:
|
||||||
service_name = self.device_list.GetItemText(selected_index, 0)
|
service_name = self.device_list.GetItemText(selected_index, 0)
|
||||||
|
hw_rev = self.device_list.GetItemText(selected_index, 3)
|
||||||
info = self.listener.services.get(service_name)
|
info = self.listener.services.get(service_name)
|
||||||
if self.currentlyUpdating:
|
if self.currentlyUpdating:
|
||||||
wx.MessageBox("Please wait, already updating",
|
wx.MessageBox("Please wait, already updating",
|
||||||
|
@ -89,7 +90,7 @@ class ActionButtonPanel(wx.Panel):
|
||||||
if info:
|
if info:
|
||||||
address = info.parsed_addresses(
|
address = info.parsed_addresses(
|
||||||
)[0] if info.parsed_addresses() else "N/A"
|
)[0] if info.parsed_addresses() else "N/A"
|
||||||
self.parent_frame.fw_updater.start_fs_update(self.parent_frame.releaseChecker.release_name, address)
|
self.parent_frame.fw_updater.start_fs_update(self.parent_frame.releaseChecker.release_name, address, hw_rev)
|
||||||
else:
|
else:
|
||||||
wx.MessageBox(
|
wx.MessageBox(
|
||||||
"No service information available for selected device", "Error", wx.ICON_ERROR)
|
"No service information available for selected device", "Error", wx.ICON_ERROR)
|
||||||
|
|
|
@ -11,6 +11,7 @@ from app.utils import get_app_data_folder, keep_latest_versions
|
||||||
CACHE_FILE = get_app_data_folder() + '/cache.json'
|
CACHE_FILE = get_app_data_folder() + '/cache.json'
|
||||||
CACHE_DURATION = timedelta(minutes=30)
|
CACHE_DURATION = timedelta(minutes=30)
|
||||||
|
|
||||||
|
LATEST_RELEASE_ENDPOINT = "https://git.btclock.dev/api/v1/repos/btclock/btclock_v3/tags"
|
||||||
|
|
||||||
class ReleaseChecker:
|
class ReleaseChecker:
|
||||||
'''Release Checker for firmware updates'''
|
'''Release Checker for firmware updates'''
|
||||||
|
@ -42,7 +43,8 @@ class ReleaseChecker:
|
||||||
if 'latest_release' in cache and (now - datetime.fromisoformat(cache['latest_release']['timestamp'])) < CACHE_DURATION:
|
if 'latest_release' in cache and (now - datetime.fromisoformat(cache['latest_release']['timestamp'])) < CACHE_DURATION:
|
||||||
latest_release = cache['latest_release']['data']
|
latest_release = cache['latest_release']['data']
|
||||||
else:
|
else:
|
||||||
url = f"https://api.github.com/repos/{repo}/releases/latest"
|
# url = f"https://api.github.com/repos/{repo}/releases/latest"
|
||||||
|
url = f"https://git.btclock.dev/api/v1/repos/{repo}/releases/latest"
|
||||||
try:
|
try:
|
||||||
response = requests.get(url)
|
response = requests.get(url)
|
||||||
response.raise_for_status()
|
response.raise_for_status()
|
||||||
|
@ -63,7 +65,7 @@ class ReleaseChecker:
|
||||||
"lolin_s3_mini_29epd_firmware.bin",
|
"lolin_s3_mini_29epd_firmware.bin",
|
||||||
"btclock_v8_213epd_firmware.bin",
|
"btclock_v8_213epd_firmware.bin",
|
||||||
"btclock_rev_b_213epd_firmware.bin",
|
"btclock_rev_b_213epd_firmware.bin",
|
||||||
"littlefs.bin"]
|
"littlefs_4MB.bin", "littlefs_8MB.bin", "littlefs_16MB.bin"]
|
||||||
|
|
||||||
asset_urls = [asset['browser_download_url']
|
asset_urls = [asset['browser_download_url']
|
||||||
for asset in latest_release['assets'] if asset['name'] in filenames_to_download]
|
for asset in latest_release['assets'] if asset['name'] in filenames_to_download]
|
||||||
|
@ -72,8 +74,9 @@ class ReleaseChecker:
|
||||||
for asset_url in asset_urls:
|
for asset_url in asset_urls:
|
||||||
self.download_file(asset_url, release_name)
|
self.download_file(asset_url, release_name)
|
||||||
|
|
||||||
ref_url = f"https://api.github.com/repos/{
|
ref_url = f"https://git.btclock.dev/api/v1/repos/{repo}/tags/{release_name}"
|
||||||
repo}/git/ref/tags/{release_name}"
|
#ref_url = f"https://api.github.com/repos/{
|
||||||
|
# repo}/git/ref/tags/{release_name}"
|
||||||
if ref_url in cache and (now - datetime.fromisoformat(cache[ref_url]['timestamp'])) < CACHE_DURATION:
|
if ref_url in cache and (now - datetime.fromisoformat(cache[ref_url]['timestamp'])) < CACHE_DURATION:
|
||||||
commit_hash = cache[ref_url]['data']
|
commit_hash = cache[ref_url]['data']
|
||||||
|
|
||||||
|
@ -81,15 +84,8 @@ class ReleaseChecker:
|
||||||
response = requests.get(ref_url)
|
response = requests.get(ref_url)
|
||||||
response.raise_for_status()
|
response.raise_for_status()
|
||||||
ref_info = response.json()
|
ref_info = response.json()
|
||||||
if ref_info["object"]["type"] == "commit":
|
commit_hash = ref_info["commit"]["sha"]
|
||||||
commit_hash = ref_info["object"]["sha"]
|
|
||||||
else:
|
|
||||||
tag_url = f"https://api.github.com/repos/{
|
|
||||||
repo}/git/tags/{ref_info['object']['sha']}"
|
|
||||||
response = requests.get(tag_url)
|
|
||||||
response.raise_for_status()
|
|
||||||
tag_info = response.json()
|
|
||||||
commit_hash = tag_info["object"]["sha"]
|
|
||||||
cache[ref_url] = {
|
cache[ref_url] = {
|
||||||
'data': commit_hash,
|
'data': commit_hash,
|
||||||
'timestamp': now.isoformat()
|
'timestamp': now.isoformat()
|
||||||
|
|
Loading…
Add table
Reference in a new issue