From 8dbeacb46d2e97f2661591e7507882d7d778097b Mon Sep 17 00:00:00 2001 From: Breadway Date: Sun, 7 Jun 2026 15:59:02 +0800 Subject: [PATCH 01/18] feat: enable ROCm EP for GPU inference, add rocm-runtime system dep Switches ort from load-dynamic to rocm feature so the ROCm execution provider is compiled in. Adds rocm-runtime to bakery system_deps so bakery doctor/install can verify it's present. --- Cargo.lock | 19 ++++--------------- Cargo.toml | 4 ++-- bakery.toml | 2 +- 3 files changed, 7 insertions(+), 18 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 59a39e6..be9fc6a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -314,7 +314,7 @@ dependencies = [ [[package]] name = "breadman" -version = "0.2.0" +version = "0.3.0" dependencies = [ "anyhow", "breadpad-shared", @@ -331,7 +331,7 @@ dependencies = [ [[package]] name = "breadpad" -version = "0.2.0" +version = "0.3.0" dependencies = [ "anyhow", "breadpad-shared", @@ -350,7 +350,7 @@ dependencies = [ [[package]] name = "breadpad-shared" -version = "0.2.0" +version = "0.3.0" dependencies = [ "anyhow", "bread-theme", @@ -376,7 +376,7 @@ dependencies = [ [[package]] name = "breadpad-test" -version = "0.2.0" +version = "0.3.0" dependencies = [ "anyhow", "breadpad-shared", @@ -1862,16 +1862,6 @@ version = "0.2.186" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" -[[package]] -name = "libloading" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "754ca22de805bb5744484a5b151a9e1a8e837d5dc232c2d7d8c2e3492edc8b60" -dependencies = [ - "cfg-if", - "windows-link", -] - [[package]] name = "libredox" version = "0.1.17" @@ -2148,7 +2138,6 @@ version = "2.0.0-rc.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d7de3af33d24a745ffb8fab904b13478438d1cd52868e6f17735ef6e1f8bf133" dependencies = [ - "libloading", "ndarray 0.17.2", "ort-sys", "smallvec", diff --git a/Cargo.toml b/Cargo.toml index 9c26f19..78ae4e0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,7 +8,7 @@ members = [ resolver = "2" [workspace.package] -version = "0.2.0" +version = "0.3.0" edition = "2021" license = "MIT" authors = ["Breadway"] @@ -24,7 +24,7 @@ chrono = { version = "0.4", features = ["serde"] } rrule = "0.12" tokio = { version = "1", features = ["full"] } zbus = { version = "4", default-features = false, features = ["tokio"] } -ort = { version = "2.0.0-rc.12", default-features = false, features = ["std", "ndarray", "tracing", "api-24", "load-dynamic"] } +ort = { version = "2.0.0-rc.12", default-features = false, features = ["std", "ndarray", "tracing", "api-24", "rocm"] } ndarray = "0.16" tokenizers = { version = "0.21", default-features = false, features = ["http", "fancy-regex"] } gtk4 = { version = "0.11", features = ["v4_12"] } diff --git a/bakery.toml b/bakery.toml index e1c028d..2fbc31d 100644 --- a/bakery.toml +++ b/bakery.toml @@ -1,7 +1,7 @@ name = "breadpad" description = "Quick-capture scratchpad and note viewer with AI classification" binaries = ["breadpad", "breadman"] -system_deps = ["gtk4", "gtk4-layer-shell"] +system_deps = ["gtk4", "gtk4-layer-shell", "rocm-runtime"] bread_deps = [] [config] From d7d88284779a0008f9e798fe2d92b07aec010414 Mon Sep 17 00:00:00 2001 From: Breadway Date: Thu, 11 Jun 2026 13:38:35 +0800 Subject: [PATCH 02/18] fix: remove non-existent rocm-runtime dep, add optional_system_deps MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit rocm-runtime is not a real Arch package name. ORT links ONNX Runtime statically and falls back to CPU — ROCm should not block install. Required: gtk4, gtk4-layer-shell only. Optional: rocm-hip-runtime (GPU inference), ollama (AI fallback), hyprland. --- bakery.toml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/bakery.toml b/bakery.toml index 2fbc31d..25e9033 100644 --- a/bakery.toml +++ b/bakery.toml @@ -1,7 +1,8 @@ name = "breadpad" description = "Quick-capture scratchpad and note viewer with AI classification" binaries = ["breadpad", "breadman"] -system_deps = ["gtk4", "gtk4-layer-shell", "rocm-runtime"] +system_deps = ["gtk4", "gtk4-layer-shell"] +optional_system_deps = ["rocm-hip-runtime", "ollama", "hyprland"] bread_deps = [] [config] From bf4586e60898310f2fb5effe7b24c6bc8e1fb41e Mon Sep 17 00:00:00 2001 From: Breadway Date: Thu, 11 Jun 2026 14:21:50 +0800 Subject: [PATCH 03/18] chore: bump version to 0.3.1 --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 78ae4e0..9fdda15 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,7 +8,7 @@ members = [ resolver = "2" [workspace.package] -version = "0.3.0" +version = "0.3.1" edition = "2021" license = "MIT" authors = ["Breadway"] From e21c5c4ad37ee6f69d081d75f200bd926df05fe2 Mon Sep 17 00:00:00 2001 From: Breadway Date: Thu, 11 Jun 2026 14:28:11 +0800 Subject: [PATCH 04/18] chore: update Cargo.lock for v0.3.1 --- Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index be9fc6a..d1d32f2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -314,7 +314,7 @@ dependencies = [ [[package]] name = "breadman" -version = "0.3.0" +version = "0.3.1" dependencies = [ "anyhow", "breadpad-shared", @@ -331,7 +331,7 @@ dependencies = [ [[package]] name = "breadpad" -version = "0.3.0" +version = "0.3.1" dependencies = [ "anyhow", "breadpad-shared", @@ -350,7 +350,7 @@ dependencies = [ [[package]] name = "breadpad-shared" -version = "0.3.0" +version = "0.3.1" dependencies = [ "anyhow", "bread-theme", @@ -376,7 +376,7 @@ dependencies = [ [[package]] name = "breadpad-test" -version = "0.3.0" +version = "0.3.1" dependencies = [ "anyhow", "breadpad-shared", From 596ae90455ff95d6c980d5fe95b31cddd165e01c Mon Sep 17 00:00:00 2001 From: Breadway Date: Thu, 11 Jun 2026 14:53:23 +0800 Subject: [PATCH 05/18] fix: enable load-dynamic ORT feature for breadpad-test ort::init_from requires the load-dynamic feature; breadpad-test calls it to load libonnxruntime.so from a runtime path. --- Cargo.lock | 11 +++++++++++ Cargo.toml | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index d1d32f2..8769946 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1862,6 +1862,16 @@ version = "0.2.186" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" +[[package]] +name = "libloading" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "754ca22de805bb5744484a5b151a9e1a8e837d5dc232c2d7d8c2e3492edc8b60" +dependencies = [ + "cfg-if", + "windows-link", +] + [[package]] name = "libredox" version = "0.1.17" @@ -2138,6 +2148,7 @@ version = "2.0.0-rc.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d7de3af33d24a745ffb8fab904b13478438d1cd52868e6f17735ef6e1f8bf133" dependencies = [ + "libloading", "ndarray 0.17.2", "ort-sys", "smallvec", diff --git a/Cargo.toml b/Cargo.toml index 9fdda15..af2b588 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,7 +24,7 @@ chrono = { version = "0.4", features = ["serde"] } rrule = "0.12" tokio = { version = "1", features = ["full"] } zbus = { version = "4", default-features = false, features = ["tokio"] } -ort = { version = "2.0.0-rc.12", default-features = false, features = ["std", "ndarray", "tracing", "api-24", "rocm"] } +ort = { version = "2.0.0-rc.12", default-features = false, features = ["std", "ndarray", "tracing", "api-24", "rocm", "load-dynamic"] } ndarray = "0.16" tokenizers = { version = "0.21", default-features = false, features = ["http", "fancy-regex"] } gtk4 = { version = "0.11", features = ["v4_12"] } From 659e3da5edc64bc6dd4ac293d3ed2c62865ef6f2 Mon Sep 17 00:00:00 2001 From: Breadway Date: Sat, 13 Jun 2026 12:12:43 +0800 Subject: [PATCH 06/18] Add packaging/arch PKGBUILD and Forgejo Actions workflows - packaging/arch/PKGBUILD: builds and publishes breadpad to [breadway] repo - .forgejo/workflows/mirror.yml: mirrors every push/tag to GitHub - .forgejo/workflows/package.yml: builds on tag, publishes to Forgejo registry Requires FORGEJO_TOKEN and GITHUB_MIRROR_TOKEN secrets in Forgejo. --- .forgejo/workflows/mirror.yml | 20 +++++++++++++++ .forgejo/workflows/package.yml | 46 ++++++++++++++++++++++++++++++++++ packaging/arch/PKGBUILD | 34 +++++++++++++++++++++++++ 3 files changed, 100 insertions(+) create mode 100644 .forgejo/workflows/mirror.yml create mode 100644 .forgejo/workflows/package.yml create mode 100644 packaging/arch/PKGBUILD diff --git a/.forgejo/workflows/mirror.yml b/.forgejo/workflows/mirror.yml new file mode 100644 index 0000000..dbc9c1b --- /dev/null +++ b/.forgejo/workflows/mirror.yml @@ -0,0 +1,20 @@ +name: Mirror to GitHub + +on: + push: + branches: ['**'] + tags: ['**'] + +jobs: + mirror: + runs-on: [self-hosted, hestia] + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Push to GitHub + run: | + git remote add github \ + "https://x-access-token:${{ secrets.GITHUB_MIRROR_TOKEN }}@github.com/Breadway/breadpad.git" + git push github --mirror diff --git a/.forgejo/workflows/package.yml b/.forgejo/workflows/package.yml new file mode 100644 index 0000000..624e210 --- /dev/null +++ b/.forgejo/workflows/package.yml @@ -0,0 +1,46 @@ +name: Build and publish package + +on: + push: + tags: ['v*'] + +jobs: + package: + runs-on: [self-hosted, hestia] + container: + image: archlinux:latest + options: --privileged + + steps: + - uses: actions/checkout@v4 + + - name: Set version + run: echo "VERSION=${GITHUB_REF_NAME#v}" >> $GITHUB_ENV + + - name: Install build dependencies + run: pacman -Syu --noconfirm base-devel git rust cargo gtk4 gtk4-layer-shell + + - name: Create builder user + run: useradd -m builder + + - name: Prepare source + run: | + git archive --format=tar.gz \ + --prefix=breadpad-${VERSION}/ \ + HEAD > packaging/arch/breadpad-${VERSION}.tar.gz + SHA=$(sha256sum packaging/arch/breadpad-${VERSION}.tar.gz | awk '{print $1}') + sed -i "s/^pkgver=.*/pkgver=${VERSION}/" packaging/arch/PKGBUILD + sed -i "s/^sha256sums=.*/sha256sums=('${SHA}')/" packaging/arch/PKGBUILD + cp -r . /home/builder/src + chown -R builder:builder /home/builder/src + + - name: Build package + run: su builder -c "cd /home/builder/src/packaging/arch && makepkg -sf --noconfirm" + + - name: Publish to Forgejo registry + run: | + PKG=$(find /home/builder/src/packaging/arch -name '*.pkg.tar.zst' | head -1) + curl -fsS -X PUT \ + -H "Authorization: token ${{ secrets.FORGEJO_TOKEN }}" \ + --upload-file "${PKG}" \ + "https://git.breadway.dev/api/packages/breadway/arch/push?distrib=breadway" diff --git a/packaging/arch/PKGBUILD b/packaging/arch/PKGBUILD new file mode 100644 index 0000000..f3d29fd --- /dev/null +++ b/packaging/arch/PKGBUILD @@ -0,0 +1,34 @@ +# Maintainer: Breadway + +pkgname=breadpad +pkgver=0.3.1 +pkgrel=1 +pkgdesc="Quick-capture scratchpad and note viewer with AI classification" +arch=('x86_64') +url="https://github.com/Breadway/breadpad" +license=('MIT') +depends=('gtk4' 'gtk4-layer-shell') +optdepends=( + 'ollama: local AI note classification' + 'hyprland: scratchpad window integration' +) +makedepends=('rust' 'cargo') +source=("${pkgname}-${pkgver}.tar.gz") +sha256sums=('SKIP') + +build() { + cd "${srcdir}/${pkgname}-${pkgver}" + cargo build --release --locked +} + +check() { + cd "${srcdir}/${pkgname}-${pkgver}" + cargo test --release --locked --workspace +} + +package() { + cd "${srcdir}/${pkgname}-${pkgver}" + install -Dm755 target/release/breadpad "${pkgdir}/usr/bin/breadpad" + install -Dm755 target/release/breadman "${pkgdir}/usr/bin/breadman" + install -Dm644 LICENSE "${pkgdir}/usr/share/licenses/${pkgname}/LICENSE" +} From ce0b7740d6d969279c30392007e33a7b230865d4 Mon Sep 17 00:00:00 2001 From: Breadway Date: Sat, 13 Jun 2026 16:02:30 +0800 Subject: [PATCH 07/18] Fix Forgejo workflows for the actual server capabilities - package.yml: correct Arch registry upload (octet-stream + binary body), drop --privileged, manual shell clone (archlinux image has no Node), built-in Actions token, --nocheck - mirror.yml: clone --mirror + explicit refs push with --prune --- .forgejo/workflows/mirror.yml | 17 ++++++------ .forgejo/workflows/package.yml | 48 +++++++++++++++------------------- 2 files changed, 30 insertions(+), 35 deletions(-) diff --git a/.forgejo/workflows/mirror.yml b/.forgejo/workflows/mirror.yml index dbc9c1b..2b2a5a5 100644 --- a/.forgejo/workflows/mirror.yml +++ b/.forgejo/workflows/mirror.yml @@ -9,12 +9,13 @@ jobs: mirror: runs-on: [self-hosted, hestia] steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - - name: Push to GitHub + - name: Mirror to GitHub run: | - git remote add github \ - "https://x-access-token:${{ secrets.GITHUB_MIRROR_TOKEN }}@github.com/Breadway/breadpad.git" - git push github --mirror + set -euo pipefail + git clone --mirror "${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}.git" repo.git + cd repo.git + # Mirror only branches and tags (not refs/pull/*, which GitHub rejects); + # --prune deletes GitHub refs that no longer exist on Forgejo. + git push --prune \ + "https://x-access-token:${{ secrets.GITHUB_MIRROR_TOKEN }}@github.com/Breadway/breadpad.git" \ + '+refs/heads/*:refs/heads/*' '+refs/tags/*:refs/tags/*' diff --git a/.forgejo/workflows/package.yml b/.forgejo/workflows/package.yml index 624e210..ef1413d 100644 --- a/.forgejo/workflows/package.yml +++ b/.forgejo/workflows/package.yml @@ -9,38 +9,32 @@ jobs: runs-on: [self-hosted, hestia] container: image: archlinux:latest - options: --privileged - steps: - - uses: actions/checkout@v4 - - - name: Set version - run: echo "VERSION=${GITHUB_REF_NAME#v}" >> $GITHUB_ENV - - - name: Install build dependencies - run: pacman -Syu --noconfirm base-devel git rust cargo gtk4 gtk4-layer-shell - - - name: Create builder user - run: useradd -m builder - - - name: Prepare source + # Note: no actions/checkout — the archlinux image has no Node, which JS + # actions require. Everything runs as shell steps and clones manually. + - name: Build and publish + env: + PUBLISH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | - git archive --format=tar.gz \ - --prefix=breadpad-${VERSION}/ \ - HEAD > packaging/arch/breadpad-${VERSION}.tar.gz + set -euo pipefail + VERSION="${GITHUB_REF_NAME#v}" + pacman -Syu --noconfirm base-devel git rust cargo gtk4 gtk4-layer-shell + useradd -m builder + git config --global --add safe.directory '*' + git clone --branch "${GITHUB_REF_NAME}" --depth 1 \ + "${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}.git" /home/builder/src + cd /home/builder/src + git archive --format=tar.gz --prefix="breadpad-${VERSION}/" HEAD \ + > packaging/arch/breadpad-${VERSION}.tar.gz SHA=$(sha256sum packaging/arch/breadpad-${VERSION}.tar.gz | awk '{print $1}') sed -i "s/^pkgver=.*/pkgver=${VERSION}/" packaging/arch/PKGBUILD sed -i "s/^sha256sums=.*/sha256sums=('${SHA}')/" packaging/arch/PKGBUILD - cp -r . /home/builder/src chown -R builder:builder /home/builder/src - - - name: Build package - run: su builder -c "cd /home/builder/src/packaging/arch && makepkg -sf --noconfirm" - - - name: Publish to Forgejo registry - run: | + # --nocheck: packaging builds the artifact; tests belong in a CI job. + su builder -c "cd /home/builder/src/packaging/arch && makepkg -f --noconfirm --nocheck" PKG=$(find /home/builder/src/packaging/arch -name '*.pkg.tar.zst' | head -1) curl -fsS -X PUT \ - -H "Authorization: token ${{ secrets.FORGEJO_TOKEN }}" \ - --upload-file "${PKG}" \ - "https://git.breadway.dev/api/packages/breadway/arch/push?distrib=breadway" + -H "Authorization: token ${PUBLISH_TOKEN}" \ + -H "Content-Type: application/octet-stream" \ + --data-binary "@${PKG}" \ + "https://git.breadway.dev/api/packages/Breadway/arch/os" From ca95ac06938cb5a0fe42017c1512370e7ff54962 Mon Sep 17 00:00:00 2001 From: Breadway Date: Sat, 13 Jun 2026 16:10:51 +0800 Subject: [PATCH 08/18] Rename mirror secret to MIRROR_TOKEN (GITHUB_ prefix is reserved) Forgejo/gitea rejects user secret names starting with GITHUB_. --- .forgejo/workflows/mirror.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.forgejo/workflows/mirror.yml b/.forgejo/workflows/mirror.yml index 2b2a5a5..cda41f9 100644 --- a/.forgejo/workflows/mirror.yml +++ b/.forgejo/workflows/mirror.yml @@ -17,5 +17,5 @@ jobs: # Mirror only branches and tags (not refs/pull/*, which GitHub rejects); # --prune deletes GitHub refs that no longer exist on Forgejo. git push --prune \ - "https://x-access-token:${{ secrets.GITHUB_MIRROR_TOKEN }}@github.com/Breadway/breadpad.git" \ + "https://x-access-token:${{ secrets.MIRROR_TOKEN }}@github.com/Breadway/breadpad.git" \ '+refs/heads/*:refs/heads/*' '+refs/tags/*:refs/tags/*' From d1aef21998fc2c9a8fd164cb42797d65e322cd01 Mon Sep 17 00:00:00 2001 From: Breadway Date: Sat, 13 Jun 2026 16:14:15 +0800 Subject: [PATCH 09/18] Clone from public URL, not GITHUB_SERVER_URL (resolves to localhost in runner) The Forgejo runner injects GITHUB_SERVER_URL as http://localhost:3002, which is unreachable from inside the job container. Use the public URL instead. --- .forgejo/workflows/mirror.yml | 2 +- .forgejo/workflows/package.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.forgejo/workflows/mirror.yml b/.forgejo/workflows/mirror.yml index cda41f9..e91c97e 100644 --- a/.forgejo/workflows/mirror.yml +++ b/.forgejo/workflows/mirror.yml @@ -12,7 +12,7 @@ jobs: - name: Mirror to GitHub run: | set -euo pipefail - git clone --mirror "${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}.git" repo.git + git clone --mirror "https://git.breadway.dev/${GITHUB_REPOSITORY}.git" repo.git cd repo.git # Mirror only branches and tags (not refs/pull/*, which GitHub rejects); # --prune deletes GitHub refs that no longer exist on Forgejo. diff --git a/.forgejo/workflows/package.yml b/.forgejo/workflows/package.yml index ef1413d..7e36a5a 100644 --- a/.forgejo/workflows/package.yml +++ b/.forgejo/workflows/package.yml @@ -22,7 +22,7 @@ jobs: useradd -m builder git config --global --add safe.directory '*' git clone --branch "${GITHUB_REF_NAME}" --depth 1 \ - "${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}.git" /home/builder/src + "https://git.breadway.dev/${GITHUB_REPOSITORY}.git" /home/builder/src cd /home/builder/src git archive --format=tar.gz --prefix="breadpad-${VERSION}/" HEAD \ > packaging/arch/breadpad-${VERSION}.tar.gz From d4ae2dfed45867795e02b05935704569ee225bd5 Mon Sep 17 00:00:00 2001 From: Breadway Date: Sat, 13 Jun 2026 17:06:56 +0800 Subject: [PATCH 10/18] Disable LTO in PKGBUILD (vendored ring/mlua static libs vs makepkg -flto) --- packaging/arch/PKGBUILD | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packaging/arch/PKGBUILD b/packaging/arch/PKGBUILD index f3d29fd..b815520 100644 --- a/packaging/arch/PKGBUILD +++ b/packaging/arch/PKGBUILD @@ -7,6 +7,10 @@ pkgdesc="Quick-capture scratchpad and note viewer with AI classification" arch=('x86_64') url="https://github.com/Breadway/breadpad" license=('MIT') +# Some Rust deps (ring/mlua) build vendored C/asm into static archives; makepkg's +# default -flto=auto emits GCC LTO bitcode the Rust (lld) link cannot read, +# causing undefined-symbol errors. Disable LTO. +options=(!lto) depends=('gtk4' 'gtk4-layer-shell') optdepends=( 'ollama: local AI note classification' From 9ae815caa2147f663b731c6912c05926e9e38e27 Mon Sep 17 00:00:00 2001 From: Breadway Date: Sat, 13 Jun 2026 22:55:43 +0800 Subject: [PATCH 11/18] Use REGISTRY_TOKEN (scoped write:package) for registry publish --- .forgejo/workflows/package.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.forgejo/workflows/package.yml b/.forgejo/workflows/package.yml index 7e36a5a..fdfdef9 100644 --- a/.forgejo/workflows/package.yml +++ b/.forgejo/workflows/package.yml @@ -14,7 +14,7 @@ jobs: # actions require. Everything runs as shell steps and clones manually. - name: Build and publish env: - PUBLISH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + PUBLISH_TOKEN: ${{ secrets.REGISTRY_TOKEN }} run: | set -euo pipefail VERSION="${GITHUB_REF_NAME#v}" From eab3775de1c082f64e5489dc81694dbcd0b8e04a Mon Sep 17 00:00:00 2001 From: Breadway Date: Sat, 13 Jun 2026 23:00:52 +0800 Subject: [PATCH 12/18] Disable debug package so the main package publishes correctly makepkg's debug split produced a -debug pkg; the upload's head -1 could grab it instead of the main package. !debug yields a single package. --- packaging/arch/PKGBUILD | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/arch/PKGBUILD b/packaging/arch/PKGBUILD index b815520..22511b6 100644 --- a/packaging/arch/PKGBUILD +++ b/packaging/arch/PKGBUILD @@ -10,7 +10,7 @@ license=('MIT') # Some Rust deps (ring/mlua) build vendored C/asm into static archives; makepkg's # default -flto=auto emits GCC LTO bitcode the Rust (lld) link cannot read, # causing undefined-symbol errors. Disable LTO. -options=(!lto) +options=(!lto !debug) depends=('gtk4' 'gtk4-layer-shell') optdepends=( 'ollama: local AI note classification' From 49f6966d9cbecd25aceb9f2510e59d9831dd863c Mon Sep 17 00:00:00 2001 From: Breadway Date: Tue, 16 Jun 2026 16:57:16 +0800 Subject: [PATCH 13/18] theme: build on the shared bread-theme stylesheet build_css() now starts from bread_theme::stylesheet(palette) and appends only breadpad/breadman-specific components. This unifies fonts, palette, and generic widgets with the rest of the ecosystem and fixes the colour mapping (overlay is now color7, matching every other app, not color0). Bump bread-theme to v0.2.6. --- breadpad-shared/Cargo.toml | 2 +- breadpad-shared/src/theme.rs | 105 ++++++++++------------------------- 2 files changed, 31 insertions(+), 76 deletions(-) diff --git a/breadpad-shared/Cargo.toml b/breadpad-shared/Cargo.toml index 610c040..cea30b3 100644 --- a/breadpad-shared/Cargo.toml +++ b/breadpad-shared/Cargo.toml @@ -7,7 +7,7 @@ authors.workspace = true [dependencies] -bread-theme = { git = "https://github.com/Breadway/bread-ecosystem", tag = "v0.1.0" } +bread-theme = { git = "https://github.com/Breadway/bread-ecosystem", tag = "v0.2.6" } anyhow.workspace = true tracing.workspace = true serde.workspace = true diff --git a/breadpad-shared/src/theme.rs b/breadpad-shared/src/theme.rs index adc76dc..857dcfe 100644 --- a/breadpad-shared/src/theme.rs +++ b/breadpad-shared/src/theme.rs @@ -1,31 +1,21 @@ pub use bread_theme::{load_palette, Palette}; -/// Generate the full breadpad CSS string. The base colour variables come from -/// `bread-theme`; the widget rules below are breadpad-specific. +/// Generate the full breadpad/breadman CSS string. The base — `@define-color` +/// palette, fonts, and generic widget styling — comes from the shared +/// `bread_theme::stylesheet`, so breadpad and breadman look identical to the +/// rest of the ecosystem. Only breadpad-specific component rules are appended. pub fn build_css(palette: &Palette, user_css: Option<&str>) -> String { - let mut css = format!( + // Shared ecosystem base (define-colors incl. accent, font, buttons, entries, + // switches, lists, cards, scrollbars). `overlay` here is color7 — consistent + // with every other bread app (breadpad previously mapped it to color0). + let mut css = bread_theme::stylesheet(palette); + + css.push_str( r#" -@define-color bg {bg}; -@define-color fg {fg}; -@define-color red {c1}; -@define-color green {c2}; -@define-color yellow {c3}; -@define-color blue {c4}; -@define-color pink {c5}; -@define-color teal {c6}; -@define-color overlay {c0}; +/* breadpad/breadman-specific components */ +window { border-radius: 8px; } -* {{ - font-family: 'Varela Round', sans-serif; -}} - -window {{ - background-color: @bg; - color: @fg; - border-radius: 8px; -}} - -.popup-entry {{ +.popup-entry { background: @bg; color: @fg; border: 2px solid @blue; @@ -33,80 +23,59 @@ window {{ padding: 12px 16px; font-size: 14px; caret-color: @fg; -}} +} -.popup-entry:focus {{ +.popup-entry:focus { outline: none; border-color: @teal; -}} +} -.type-chip {{ +.type-chip { background: @overlay; color: @fg; border-radius: 999px; padding: 4px 12px; font-size: 12px; margin: 4px; -}} +} -.type-chip.active {{ +.type-chip.active { background: @blue; color: @bg; -}} +} -.confirm-button {{ +.confirm-button { background: @blue; color: @bg; border: none; border-radius: 8px; padding: 8px 16px; font-weight: bold; -}} +} -.note-card {{ +.note-card { background: shade(@bg, 1.1); border-radius: 8px; padding: 12px; margin: 8px; border-left: 3px solid @blue; -}} +} -.note-card:hover {{ +.note-card:hover { background: shade(@bg, 1.2); -}} +} -.search-entry {{ +.search-entry { background: shade(@bg, 1.1); color: @fg; border: 1px solid @overlay; border-radius: 6px; padding: 8px 12px; -}} - -.search-entry:focus {{ - border-color: @blue; - outline: none; -}} -"#, - bg = palette.background, - fg = palette.foreground, - c0 = palette.color0, - c1 = palette.color1, - c2 = palette.color2, - c3 = palette.color3, - c4 = palette.color4, - c5 = palette.color5, - c6 = palette.color6, - ); - - css.push_str(r#" -.dim-label { - color: alpha(@fg, 0.5); - font-size: 12px; } -.sidebar { - background: shade(@bg, 0.93); +.search-entry:focus { + border-color: @blue; + outline: none; } .sidebar-row { @@ -217,20 +186,6 @@ window {{ } .snooze-option:hover { background: shade(@bg, 1.2); } - -entry { - background: shade(@bg, 1.1); - color: @fg; - border: 1px solid @overlay; - border-radius: 6px; - caret-color: @fg; - padding: 5px 10px; -} - -entry:focus { - border-color: @blue; - outline: none; -} "#); if let Some(extra) = user_css { From 08d8956eac73d96e2eb396fb2b58422a98ad89b4 Mon Sep 17 00:00:00 2001 From: Breadway Date: Tue, 16 Jun 2026 17:07:06 +0800 Subject: [PATCH 14/18] docs: add CalDAV calendar-sync walkthrough The [calendar] config keys existed without explanation. Document enabling CalDAV sync end to end: finding the collection URL, creating an app password, the config block, and the best-effort sync behaviour. --- README.md | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/README.md b/README.md index 02ec8a2..b39ea3d 100644 --- a/README.md +++ b/README.md @@ -190,8 +190,41 @@ enabled = true # set false to never call Ollama [reminders] default_morning = "08:00" # what "tomorrow morning" resolves to missed_grace_minutes = 60 # how long after boot to still fire a missed reminder + +[calendar] +enabled = false # turn on CalDAV sync (see below) +url = "" # CalDAV calendar collection URL +username = "" +password = "" # app password / token recommended ``` +### Calendar sync (CalDAV) + +When `[calendar].enabled = true`, reminders and dated notes are pushed to a +CalDAV calendar as events (tracked by `caldav_uid` on each note), so they show +up alongside the rest of your calendar. + +1. Find your calendar's **collection URL**. It's the per-calendar CalDAV path, + not the server root — e.g. Nextcloud: + `https://host/remote.php/dav/calendars///`. +2. Create an **app password** for breadpad (don't use your main password): + Nextcloud → Settings → Security → *Devices & sessions* → "Create new app + password". Most CalDAV servers have an equivalent. +3. Fill in `breadpad.toml` (or BOS Settings → breadpad → Calendar): + + ```toml + [calendar] + enabled = true + url = "https://host/remote.php/dav/calendars/me/breadpad/" + username = "me" + password = "xxxx-xxxx-xxxx-xxxx" + ``` +4. Restart breadpad. New dated/reminder notes sync up; the `caldav_uid` field + links each note to its event so updates and deletes stay in step. + +If the server is unreachable, breadpad logs a warning and keeps the note +locally — sync is best-effort and never blocks capture. + --- ## Usage From dfe19708ba334e9da4c109a0afde39c4cfdc1993 Mon Sep 17 00:00:00 2001 From: Breadway Date: Tue, 16 Jun 2026 18:35:33 +0800 Subject: [PATCH 15/18] Release 0.3.4: shared bread-theme stylesheet (overlay=color7) --- Cargo.lock | 12 ++++++------ Cargo.toml | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8769946..46fa8d0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -304,8 +304,8 @@ dependencies = [ [[package]] name = "bread-theme" -version = "0.1.0" -source = "git+https://github.com/Breadway/bread-ecosystem?tag=v0.1.0#6b5f4f475f66a645b08cb865e6dda8228d23679b" +version = "0.2.3" +source = "git+https://github.com/Breadway/bread-ecosystem?tag=v0.2.6#0c8c5c00e435fedff4f81e36d603424c153519a9" dependencies = [ "dirs 5.0.1", "serde", @@ -314,7 +314,7 @@ dependencies = [ [[package]] name = "breadman" -version = "0.3.1" +version = "0.3.4" dependencies = [ "anyhow", "breadpad-shared", @@ -331,7 +331,7 @@ dependencies = [ [[package]] name = "breadpad" -version = "0.3.1" +version = "0.3.4" dependencies = [ "anyhow", "breadpad-shared", @@ -350,7 +350,7 @@ dependencies = [ [[package]] name = "breadpad-shared" -version = "0.3.1" +version = "0.3.4" dependencies = [ "anyhow", "bread-theme", @@ -376,7 +376,7 @@ dependencies = [ [[package]] name = "breadpad-test" -version = "0.3.1" +version = "0.3.4" dependencies = [ "anyhow", "breadpad-shared", diff --git a/Cargo.toml b/Cargo.toml index af2b588..4092bed 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,7 +8,7 @@ members = [ resolver = "2" [workspace.package] -version = "0.3.1" +version = "0.3.4" edition = "2021" license = "MIT" authors = ["Breadway"] From c30aa2497e49451f3915707fb79be2858408eb87 Mon Sep 17 00:00:00 2001 From: Breadway Date: Wed, 17 Jun 2026 12:42:12 +0800 Subject: [PATCH 16/18] Fix illegible text on light pywal palettes + hot-reload MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use bread-theme 0.2.7's luminance-picked ink (@on-*): type chips on @overlay and selected sidebar rows / confirm buttons on @blue kept @fg or @bg, which vanished when those slots came out light/dark. They now use @on-overlay / @on-accent. Add breadpad_shared::theme::apply_live (wraps bread_theme::gtk::apply_app_css) so breadpad and breadman recolour live on `bread-theme reload` and re-read the user's style.css — replacing the build-once provider. bread-theme bumped to v0.2.7 (gtk feature). --- Cargo.lock | 3 ++- breadman/src/main.rs | 19 +++---------------- breadpad-shared/Cargo.toml | 2 +- breadpad-shared/src/theme.rs | 21 +++++++++++++++++---- breadpad/src/main.rs | 21 ++++----------------- 5 files changed, 27 insertions(+), 39 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 46fa8d0..11b33d9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -305,9 +305,10 @@ dependencies = [ [[package]] name = "bread-theme" version = "0.2.3" -source = "git+https://github.com/Breadway/bread-ecosystem?tag=v0.2.6#0c8c5c00e435fedff4f81e36d603424c153519a9" +source = "git+https://github.com/Breadway/bread-ecosystem?tag=v0.2.7#ea87083c0615fc9141b0ae4c99f833748a0189d1" dependencies = [ "dirs 5.0.1", + "gtk4", "serde", "serde_json", ] diff --git a/breadman/src/main.rs b/breadman/src/main.rs index 0ee89bc..d46557a 100644 --- a/breadman/src/main.rs +++ b/breadman/src/main.rs @@ -4,7 +4,6 @@ use breadpad_shared::{ parser::parse_rule_based, scheduler::Scheduler, store::Store, - theme::{build_css, load_palette}, types::{Note, NoteType, RecurrenceRule}, }; use chrono::Local; @@ -924,19 +923,7 @@ fn show_add_note_window(parent: >k4::ApplicationWindow, state: AppState) { // ── CSS ─────────────────────────────────────────────────────────────────────── fn apply_css(_cfg: &Config) { - let palette = load_palette(); - let user_css = std::fs::read_to_string(breadpad_shared::config::style_css_path()).ok(); - let css = build_css(&palette, user_css.as_deref()); - - let provider = gtk4::CssProvider::new(); - provider.load_from_string(&css); - let Some(display) = gtk4::gdk::Display::default() else { - tracing::warn!("no default display; skipping CSS provider"); - return; - }; - gtk4::style_context_add_provider_for_display( - &display, - &provider, - gtk4::STYLE_PROVIDER_PRIORITY_APPLICATION, - ); + // Hot-reloads on `bread-theme reload` (recolours to the new pywal palette + // and re-reads the user's style.css). See breadpad_shared::theme::apply_live. + breadpad_shared::theme::apply_live(); } diff --git a/breadpad-shared/Cargo.toml b/breadpad-shared/Cargo.toml index cea30b3..52a5b21 100644 --- a/breadpad-shared/Cargo.toml +++ b/breadpad-shared/Cargo.toml @@ -7,7 +7,7 @@ authors.workspace = true [dependencies] -bread-theme = { git = "https://github.com/Breadway/bread-ecosystem", tag = "v0.2.6" } +bread-theme = { git = "https://github.com/Breadway/bread-ecosystem", tag = "v0.2.7", features = ["gtk"] } anyhow.workspace = true tracing.workspace = true serde.workspace = true diff --git a/breadpad-shared/src/theme.rs b/breadpad-shared/src/theme.rs index 857dcfe..cb1139a 100644 --- a/breadpad-shared/src/theme.rs +++ b/breadpad-shared/src/theme.rs @@ -1,5 +1,18 @@ pub use bread_theme::{load_palette, Palette}; +/// Apply breadpad/breadman's stylesheet and keep it live across palette changes. +/// [`build_css`] bundles the shared component sheet with the app's own rules from +/// the current pywal palette; `bread_theme::gtk::apply_app_css` re-runs this +/// whenever `bread-theme reload` rewrites the shared theme file, so the UI +/// recolours in place (and re-reads the user's `style.css` override too). +pub fn apply_live() { + bread_theme::gtk::apply_app_css(|| { + let palette = load_palette(); + let user_css = std::fs::read_to_string(crate::config::style_css_path()).ok(); + build_css(&palette, user_css.as_deref()) + }); +} + /// Generate the full breadpad/breadman CSS string. The base — `@define-color` /// palette, fonts, and generic widget styling — comes from the shared /// `bread_theme::stylesheet`, so breadpad and breadman look identical to the @@ -32,7 +45,7 @@ window { border-radius: 8px; } .type-chip { background: @overlay; - color: @fg; + color: @on-overlay; border-radius: 999px; padding: 4px 12px; font-size: 12px; @@ -41,12 +54,12 @@ window { border-radius: 8px; } .type-chip.active { background: @blue; - color: @bg; + color: @on-accent; } .confirm-button { background: @blue; - color: @bg; + color: @on-accent; border: none; border-radius: 8px; padding: 8px 16px; @@ -90,7 +103,7 @@ window { border-radius: 8px; } .sidebar-row:selected { background: @blue; - color: @bg; + color: @on-accent; font-weight: 500; } diff --git a/breadpad/src/main.rs b/breadpad/src/main.rs index c840557..aa924d0 100644 --- a/breadpad/src/main.rs +++ b/breadpad/src/main.rs @@ -2,10 +2,9 @@ use anyhow::Result; use breadpad_shared::{ calendar::CalDavClient, classifier::Classifier, - config::{style_css_path, Config}, + config::Config, scheduler::Scheduler, store::Store, - theme::{build_css, load_palette}, types::{Note, NoteType}, }; use gtk4::{glib, prelude::*}; @@ -765,19 +764,7 @@ fn save_note_classified( } fn apply_css(_cfg: &Config) { - let palette = load_palette(); - let user_css = std::fs::read_to_string(style_css_path()).ok(); - let css = build_css(&palette, user_css.as_deref()); - - let provider = gtk4::CssProvider::new(); - provider.load_from_string(&css); - let Some(display) = gtk4::gdk::Display::default() else { - tracing::warn!("no default display; skipping CSS provider"); - return; - }; - gtk4::style_context_add_provider_for_display( - &display, - &provider, - gtk4::STYLE_PROVIDER_PRIORITY_APPLICATION, - ); + // Hot-reloads on `bread-theme reload` (recolours to the new pywal palette + // and re-reads the user's style.css). See breadpad_shared::theme::apply_live. + breadpad_shared::theme::apply_live(); } From e0b55e1713661f8fc7f28cff8711ecd2271a6856 Mon Sep 17 00:00:00 2001 From: Breadway Date: Wed, 17 Jun 2026 12:55:57 +0800 Subject: [PATCH 17/18] Bump bread-theme to v0.2.8 (live-reload fix) --- Cargo.lock | 2 +- breadpad-shared/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 11b33d9..756f0c3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -305,7 +305,7 @@ dependencies = [ [[package]] name = "bread-theme" version = "0.2.3" -source = "git+https://github.com/Breadway/bread-ecosystem?tag=v0.2.7#ea87083c0615fc9141b0ae4c99f833748a0189d1" +source = "git+https://github.com/Breadway/bread-ecosystem?tag=v0.2.8#77417d552130281ff787e07d52541eb25e9d533b" dependencies = [ "dirs 5.0.1", "gtk4", diff --git a/breadpad-shared/Cargo.toml b/breadpad-shared/Cargo.toml index 52a5b21..01470f9 100644 --- a/breadpad-shared/Cargo.toml +++ b/breadpad-shared/Cargo.toml @@ -7,7 +7,7 @@ authors.workspace = true [dependencies] -bread-theme = { git = "https://github.com/Breadway/bread-ecosystem", tag = "v0.2.7", features = ["gtk"] } +bread-theme = { git = "https://github.com/Breadway/bread-ecosystem", tag = "v0.2.8", features = ["gtk"] } anyhow.workspace = true tracing.workspace = true serde.workspace = true From df42aba1d32ff85b5d20dbb7f14c22905aacf85b Mon Sep 17 00:00:00 2001 From: Breadway Date: Fri, 19 Jun 2026 08:38:40 +0800 Subject: [PATCH 18/18] CI: use /tmp for ecosystem clone, avoid permissions conflict --- .github/workflows/release.yml | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 8df4368..e492838 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -9,7 +9,7 @@ permissions: env: DL_DIR: /srv/breadway-dl - ECOSYSTEM_DIR: /home/breadway/Projects/bread-ecosystem + ECOSYSTEM_DIR: /tmp/bread-ecosystem-ci jobs: build: @@ -40,12 +40,8 @@ jobs: - name: ensure bread-ecosystem run: | - if [[ -d "${ECOSYSTEM_DIR}/.git" ]]; then - git -C "${ECOSYSTEM_DIR}" pull --ff-only - else - mkdir -p "$(dirname "${ECOSYSTEM_DIR}")" - git clone https://github.com/Breadway/bread-ecosystem.git "${ECOSYSTEM_DIR}" - fi + rm -rf "${ECOSYSTEM_DIR}" + git clone https://github.com/Breadway/bread-ecosystem.git "${ECOSYSTEM_DIR}" - name: regenerate index.json run: bash "${ECOSYSTEM_DIR}/scripts/gen-index.sh"