Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
5ab2a9c
Merge remote-tracking branch 'upstream/master'
farfromrefug Apr 7, 2026
1eb44bb
Merge remote-tracking branch 'origin/master'
farfromrefug Apr 13, 2026
40a9050
fix: tray icon click toggle window state instead of always showing
farfromrefug Apr 15, 2026
7fe68a3
fix: linux tray icon fix
farfromrefug Apr 15, 2026
ea0b70b
Merge remote-tracking branch 'upstream/master'
farfromrefug Apr 15, 2026
02fd208
Merge remote-tracking branch 'upstream/master'
farfromrefug Apr 15, 2026
1bb1baa
feat: implement auto-update for macOS/Windows/Linux with deb build sc…
Copilot Apr 20, 2026
b057f8d
fix: address code review feedback - constants, robocopy comment, isdigit
Copilot Apr 20, 2026
0d60211
chore: working on updater
farfromrefug Apr 20, 2026
fbe8fdb
feat: macOS restart, daily update check, consistent button style, red…
Copilot Apr 20, 2026
84c0769
fix: address code review feedback - derived interval constant, jq for…
Copilot Apr 20, 2026
ff99622
Merge remote-tracking branch 'origin/copilot/implement-auto-update-fe…
farfromrefug Apr 20, 2026
14f699c
chore: updater check
farfromrefug Apr 20, 2026
83bae11
chore: working deb/update
farfromrefug Apr 21, 2026
c06018e
fix: deb restart now relaunches app; enable UPX on Linux/Windows builds
Copilot Apr 21, 2026
312f9ef
fix: remove extra blank lines in updater.py (code review)
Copilot Apr 21, 2026
7aff134
chore: upx not working on linux yet
farfromrefug Apr 21, 2026
bb0d9b0
chore: bump version to 3.5.4 [skip ci]
github-actions[bot] Apr 21, 2026
b568a1a
chore: bump version to 3.5.5 [skip ci]
github-actions[bot] Apr 21, 2026
f5aa20d
Update build_deb.sh
farfromrefug Apr 21, 2026
1d995bf
Update version.py
farfromrefug Apr 21, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 82 additions & 0 deletions .github/release-drafter.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
# .github/release-drafter.yml
#
# Configuration for release-drafter/release-drafter.
# Generates release notes from merged PRs (with contributors) and conventional
# commits that are not part of a merged PR.

name-template: 'Mouser $RESOLVED_VERSION'
tag-template: 'v$RESOLVED_VERSION'

# ── Category mapping (by PR label) ────────────────────────────────────────────
categories:
- title: '🚀 Features'
labels:
- 'feature'
- 'enhancement'
- 'feat'
- title: '🐛 Bug Fixes'
labels:
- 'bug'
- 'bugfix'
- 'fix'
- title: '📝 Documentation'
labels:
- 'documentation'
- 'docs'
- title: '⚡ Performance'
labels:
- 'performance'
- 'perf'
- title: '🔧 Maintenance'
labels:
- 'chore'
- 'maintenance'
- 'refactor'
- 'ci'
- 'build'
- title: '🔒 Security'
labels:
- 'security'

# ── Autolabeler: map conventional-commit prefixes in PR titles to labels ──────
autolabeler:
- label: 'feature'
title:
- '/^feat(\(.+\))?:/i'
- label: 'fix'
title:
- '/^fix(\(.+\))?:/i'
- label: 'docs'
title:
- '/^docs(\(.+\))?:/i'
- label: 'perf'
title:
- '/^perf(\(.+\))?:/i'
- label: 'chore'
title:
- '/^(chore|refactor|ci|build|style|test)(\(.+\))?:/i'

# ── Version resolver (used when release-drafter is kept as a draft) ───────────
version-resolver:
major:
labels: ['major', 'breaking']
minor:
labels: ['minor', 'feature', 'enhancement', 'feat']
patch:
labels: ['patch', 'bug', 'bugfix', 'fix', 'chore']
default: patch

# ── Templates ─────────────────────────────────────────────────────────────────
change-template: '- $TITLE @$AUTHOR (#$NUMBER)'
change-title-escapes: '\<*_&'

template: |
## What's Changed

$CHANGES

$CONTRIBUTORS

**Full Changelog**: $PREVIOUS_TAG...$TAG

no-changes-template: 'No significant changes in this release.'
241 changes: 214 additions & 27 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,119 @@ on:
push:
tags: ["v*"]
workflow_dispatch:
inputs:
bump:
description: 'Version bump type (ignored when triggered by a tag push)'
required: true
type: choice
options: [none, patch, minor, major]
default: patch
release_on_github:
description: 'Create / update GitHub release (false = build artifacts only)'
required: true
type: boolean
default: true

# One release pipeline per tag to prevent duplicate runs.
concurrency:
group: release-${{ github.ref_name }}
cancel-in-progress: false

permissions:
contents: write

env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
MOUSER_VERSION: ${{ startsWith(github.ref, 'refs/tags/') && github.ref_name || '' }}
MOUSER_GIT_COMMIT: ${{ github.sha }}
MOUSER_GIT_DIRTY: "false"

jobs:
# ── Determine version ────────────────────────────────────────────────────────
# Skip tag-push events that this workflow itself creates (loop prevention).
prepare:
if: >-
github.event_name == 'workflow_dispatch' ||
(github.event_name == 'push' && github.actor != 'github-actions[bot]')
runs-on: ubuntu-latest
outputs:
version: ${{ steps.ver.outputs.version }}
tag: ${{ steps.ver.outputs.tag }}
should_release: ${{ steps.ver.outputs.should_release }}
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
# Use a PAT or the default token — PAT required only if branch protection
# prevents github-actions[bot] from pushing to the default branch.
token: ${{ secrets.GITHUB_TOKEN }}

- name: Compute version (and bump if requested)
id: ver
shell: bash
run: |
# ── Read current version from version.py ──────────────────────────
CURRENT=$(python3 - <<'PY'
with open("core/version.py") as f:
for line in f:
if "_DEFAULT_APP_VERSION" in line and "=" in line:
v = line.split("=", 1)[1].strip().strip('"').strip("'")
print(v)
break
PY
)
echo "Current version in version.py: ${CURRENT}"

if [[ "${{ github.event_name }}" == "push" ]]; then
# ── Tag-push path: use the tag (strip leading 'v') ───────────────
TAG="${{ github.ref_name }}"
VERSION="${TAG#v}"
SHOULD_RELEASE="true"
else
# ── workflow_dispatch path ────────────────────────────────────────
BUMP="${{ inputs.bump }}"
SHOULD_RELEASE="${{ inputs.release_on_github }}"

if [[ "$BUMP" != "none" ]]; then
IFS='.' read -r MAJOR MINOR PATCH <<< "$CURRENT"
case "$BUMP" in
major) MAJOR=$((MAJOR+1)); MINOR=0; PATCH=0 ;;
minor) MINOR=$((MINOR+1)); PATCH=0 ;;
patch) PATCH=$((PATCH+1)) ;;
esac
VERSION="${MAJOR}.${MINOR}.${PATCH}"

# Update version.py in-place
sed -i "s/_DEFAULT_APP_VERSION = \"${CURRENT}\"/_DEFAULT_APP_VERSION = \"${VERSION}\"/" core/version.py
echo "Bumped version.py: ${CURRENT} → ${VERSION}"

git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git add core/version.py
git commit -m "chore: bump version to ${VERSION} [skip ci]"
git push origin HEAD
else
VERSION="$CURRENT"
fi

TAG="v${VERSION}"

# Push the tag so release-drafter can resolve the correct commit range
# and so the release step can reference it. The resulting push:tags event
# is skipped above because actor == github-actions[bot].
if [[ "$SHOULD_RELEASE" == "true" ]]; then
git tag "$TAG" || true # no-op if it already exists
git push origin "$TAG" || true
fi
fi

echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
echo "tag=${TAG}" >> "$GITHUB_OUTPUT"
echo "should_release=${SHOULD_RELEASE}" >> "$GITHUB_OUTPUT"

# ── Platform builds (all depend on prepare) ──────────────────────────────────
build-windows:
needs: prepare
runs-on: windows-latest
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
MOUSER_VERSION: ${{ needs.prepare.outputs.version }}
MOUSER_GIT_COMMIT: ${{ github.sha }}
MOUSER_GIT_DIRTY: "false"
steps:
- uses: actions/checkout@v6

Expand All @@ -27,6 +127,9 @@ jobs:
- name: Install dependencies
run: pip install -r requirements.txt

- name: Install UPX
run: choco install upx --no-progress -y

- name: Build with PyInstaller
run: pyinstaller Mouser.spec --noconfirm

Expand All @@ -39,6 +142,7 @@ jobs:
path: Mouser-Windows.zip

build-macos:
needs: prepare
name: build-macos (${{ matrix.name }})
strategy:
fail-fast: false
Expand All @@ -57,6 +161,11 @@ jobs:
artifact_name: Mouser-macOS-intel
archive_name: Mouser-macOS-intel.zip
runs-on: ${{ matrix.runner }}
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
MOUSER_VERSION: ${{ needs.prepare.outputs.version }}
MOUSER_GIT_COMMIT: ${{ github.sha }}
MOUSER_GIT_DIRTY: "false"
steps:
- uses: actions/checkout@v6

Expand Down Expand Up @@ -84,7 +193,13 @@ jobs:
path: ${{ matrix.archive_name }}

build-linux:
needs: prepare
runs-on: ubuntu-latest
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
MOUSER_VERSION: ${{ needs.prepare.outputs.version }}
MOUSER_GIT_COMMIT: ${{ github.sha }}
MOUSER_GIT_DIRTY: "false"
steps:
- uses: actions/checkout@v6

Expand All @@ -93,49 +208,121 @@ jobs:
python-version: "3.12"

- name: Install system dependencies
run: sudo apt-get update && sudo apt-get install -y libhidapi-dev
run: sudo apt-get update && sudo apt-get install -y libhidapi-dev dpkg-dev imagemagick upx-ucl

- name: Install dependencies
run: pip install -r requirements.txt

- name: Build with PyInstaller
run: pyinstaller Mouser-linux.spec --noconfirm

- name: Create archive
- name: Create zip archive
run: cd dist && zip -r -y ../Mouser-Linux.zip Mouser

- name: Build .deb package
run: |
chmod +x build_deb.sh
./build_deb.sh

- uses: actions/upload-artifact@v7
with:
name: Mouser-Linux
path: Mouser-Linux.zip

- uses: actions/upload-artifact@v7
with:
name: Mouser-Linux-deb
path: dist/Mouser-Linux.deb

# ── Create GitHub release (conditional) ──────────────────────────────────────
release:
if: startsWith(github.ref, 'refs/tags/')
needs: [build-windows, build-macos, build-linux]
if: needs.prepare.outputs.should_release == 'true'
needs: [prepare, build-windows, build-macos, build-linux]
runs-on: ubuntu-latest
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0

- uses: actions/download-artifact@v8

- name: Generate latest.json
shell: bash
run: |
VERSION="${{ needs.prepare.outputs.version }}"
TAG="${{ needs.prepare.outputs.tag }}"
REPO="${{ github.repository }}"
BASE_URL="https://github.com/${REPO}/releases/download/latest"
# Build JSON with jq to avoid shell-variable injection in Python
jq -n \
--arg version "$VERSION" \
--arg date "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
--arg win "${BASE_URL}/Mouser-Windows.zip" \
--arg mac_arm "${BASE_URL}/Mouser-macOS.zip" \
--arg mac_x64 "${BASE_URL}/Mouser-macOS-intel.zip" \
--arg linux_deb "${BASE_URL}/Mouser-Linux.deb" \
--arg linux_zip "${BASE_URL}/Mouser-Linux.zip" \
'{
version: $version,
date: $date,
downloads: {
"windows-x64": $win,
"macos-arm64": $mac_arm,
"macos-x86_64": $mac_x64,
"linux-deb": $linux_deb,
"linux-zip": $linux_zip
}
}' | tee latest.json

# Generate release notes from merged PRs (with contributors) and any
# conventional commits that are not part of a merged PR.
- name: Generate changelog
id: changelog
uses: release-drafter/release-drafter@v6
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
config-name: release-drafter.yml
tag: ${{ needs.prepare.outputs.tag }}
name: "Mouser ${{ needs.prepare.outputs.tag }}"
# publish=false: only draft so we can read the body; we publish via gh below
publish: false
disable-autolabeler: true

- name: Create or update GitHub Release
env:
GH_TOKEN: ${{ github.token }}
shell: bash
run: |
if gh release view "${{ github.ref_name }}" --repo "${{ github.repository }}" > /dev/null 2>&1; then
# Release already exists — just upload the assets
gh release upload "${{ github.ref_name }}" \
--repo "${{ github.repository }}" \
--clobber \
Mouser-Windows/Mouser-Windows.zip \
Mouser-macOS/Mouser-macOS.zip \
Mouser-macOS-intel/Mouser-macOS-intel.zip \
Mouser-Linux/Mouser-Linux.zip
TAG="${{ needs.prepare.outputs.tag }}"
REPO="${{ github.repository }}"
NOTES_FILE="$(mktemp)"
cat > "$NOTES_FILE" <<'NOTES'
${{ steps.changelog.outputs.body }}
NOTES

ASSETS=(
"Mouser-Windows/Mouser-Windows.zip"
"Mouser-macOS/Mouser-macOS.zip"
"Mouser-macOS-intel/Mouser-macOS-intel.zip"
"Mouser-Linux/Mouser-Linux.zip"
"Mouser-Linux-deb/Mouser-Linux.deb"
"latest.json"
)

if gh release view "$TAG" --repo "$REPO" > /dev/null 2>&1; then
gh release upload "$TAG" --repo "$REPO" --clobber "${ASSETS[@]}"
gh release edit "$TAG" --repo "$REPO" \
--title "Mouser ${TAG}" \
--notes-file "$NOTES_FILE" \
--draft=false
else
gh release create "${{ github.ref_name }}" \
--repo "${{ github.repository }}" \
--title "Mouser ${{ github.ref_name }}" \
--generate-notes \
Mouser-Windows/Mouser-Windows.zip \
Mouser-macOS/Mouser-macOS.zip \
Mouser-macOS-intel/Mouser-macOS-intel.zip \
Mouser-Linux/Mouser-Linux.zip
gh release create "$TAG" \
--repo "$REPO" \
--title "Mouser ${TAG}" \
--notes-file "$NOTES_FILE" \
"${ASSETS[@]}"
fi

Loading
Loading