9fadfbc37a2cc266fba1885a61efa6d00a347709
66
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
9fadfbc37a |
Make the AppImage updatable, and drop the deb and rpm
Secret Scan / scan (push) Successful in 4s
Build App (Preview) / compute-version (pull_request) Successful in 4s
Secret Scan / scan (pull_request) Successful in 3s
Build App (Preview) / create-release (pull_request) Successful in 2s
Build App (Preview) / build-macos (pull_request) Successful in 2m43s
Build App (Preview) / build-windows (pull_request) Successful in 4m51s
Build App (Preview) / build-linux (pull_request) Successful in 5m19s
Build App (Preview) / prune-previews (pull_request) Successful in 1s
An AppImage manager can adopt the current build but never update it: the image carries no update information, which is the string that tells such a tool where to look for a newer one. It also carries no AppStream metadata, so a manager has nothing to show but a filename — appimagetool has been warning about that on every build — and linuxdeploy leaves `Categories=` empty, which files the app nowhere in a desktop menu. All three are fixed while the image is already unpacked for the wayland fix, so the cost is a few lines rather than a second pass. `unbundle-wayland-client.sh` is now `finalize-appimage.sh`, since it does more than unbundle. The update URL is a **fixed** `linux-latest` tag on the GitHub mirror, which is where updates are pulled from — deliberately not `releases/latest`. `latest` follows whichever release is newest, and the Gitea-to-GitHub backfill creates one GitHub release per Gitea tag, including the `-win` and `-mac` tags that carry no AppImage. A URL that can resolve to a release with no AppImage in it fails on users' machines and nowhere else. The output is named for that tag too, and that is not cosmetic: zsync records a *relative* filename which a client resolves against the .zsync URL it fetched, so a versioned name would send every client after the build it already has. Verified by reading the generated header — `Filename: Triple-C_x86_64 .AppImage` — and the image's own `.upd_info` section, which is where the tag actually lives. My first guard checked the .zsync for the tag and failed correctly, which is how that distinction got found rather than shipped. Range requests were confirmed against the mirror before building on them: 206 with a correct content-range, so updates are real deltas rather than an 85 MB re-download. The .deb and .rpm go. They are two more artifacts to build, publish and keep working for an audience already served by the one file that runs on every distribution, and neither could ever self-update — which is now the difference that matters. Older releases keep theirs. The Linux job passes `--bundles appimage` rather than changing `tauri.conf.json`, so macOS and Windows are untouched. Verified against the real 0.4.19 artifact: it repacks, the AppStream file and filled-in Categories land inside the image, the update string resolves to the fixed tag, and the wayland fallback still holds. Both publisher failure paths refuse rather than half-publishing — no token, and missing artifacts. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011YPqHpjV4EL6RNEwrRKqQm |
||
|
|
a3bdf6f4da |
Let the host's libwayland-client win in the AppImage
Secret Scan / scan (push) Successful in 3s
Build App (Preview) / compute-version (pull_request) Successful in 3s
Secret Scan / scan (pull_request) Successful in 3s
Build App (Preview) / create-release (pull_request) Successful in 1s
Build App (Preview) / build-macos (pull_request) Successful in 2m52s
Build App (Preview) / build-linux (pull_request) Successful in 5m20s
Build App (Preview) / build-windows (pull_request) Successful in 5m21s
Build App (Preview) / prune-previews (pull_request) Successful in 1s
The AppImage came up blank on CachyOS with `Could not create default EGL display: EGL_BAD_PARAMETER. Aborting...`, and the DMA-BUF workaround already in `main.rs` did not help — verified by finding the flag compiled into the shipped 0.4.19 binary, where it runs unconditionally on Linux. It is a different fault with the same error text. linuxdeploy bundles `libwayland-client.so.0` as a GTK dependency and `AppRun.wrapped` puts the bundled directory ahead of the host's, so the host's Mesa resolves against our copy. `libEGL_mesa.so.0` — the driver libglvnd's `libEGL.so.1` dlopens — has a hard DT_NEEDED on that library, so when its symbols will not resolve the driver never loads, glvnd is left with none, and `eglGetDisplay` reports no display. That is why `GDK_BACKEND=x11` does not dodge it, and why the symptom is a bad-parameter error rather than a link failure. Bisected on the reporter's machine against the released artifact — removing `libwayland-client.so.0` from the AppDir cleared the abort, while removing `libwayland-egl` or `libepoxy` did not. The bundled copy (Ubuntu 22.04, wayland 1.20) is missing eleven symbols their wayland 1.26 exports, including `wl_proxy_get_display`, `wl_proxy_get_queue`, `wl_display_create_queue_with_name` and `wl_fixes_interface`. Bundling a newer wayland would defer this, not fix it: the floor is set by the host's Mesa, which updates independently of our releases, so any version we pick is one release away from being too old again. This is a host-coupled library like libGL and libdrm — the only correct version is the host's. So the copy is demoted rather than deleted. It moves off the loader path into `usr/lib/wayland-fallback`, and a hook adds that directory back only when the host has no libwayland-client of its own — so a host without one still starts. The ordering is safe because `AppRun.wrapped` appends the inherited LD_LIBRARY_PATH after its own entries, making the hook a fallback and never an override. AppRun sources hooks by name rather than globbing, so it is patched to source this one. X11-only hosts are unaffected: libwayland-client is a package dependency of Mesa and GTK, so it is present even on a machine with no display server at all — confirmed on a headless container with neither DISPLAY nor WAYLAND_DISPLAY set. And the AppImage already runs as an X11 client everywhere, since linuxdeploy's own hook forces GDK_BACKEND=x11. Verified against the real 0.4.19 artifact rather than a synthetic AppDir: it repacks, the binary and AppRun survive, and both hook branches were exercised — host-has-it leaves LD_LIBRARY_PATH untouched, and a debian:12-slim container with no wayland at all engages the fallback. The comment in `main.rs` quoted this exact error as one the DMA-BUF flag fixes. That claim sent this investigation down the wrong path first, so it is corrected rather than left to do it again. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011YPqHpjV4EL6RNEwrRKqQm |
||
|
|
7a5c0c1f13 |
Retire the Arch package, document AppImage desktop integration
The `triple-c-bin` package was never on the AUR, so installing it meant
downloading a file and running `pacman -U` — the same gesture as making an
AppImage executable, for a second artifact to keep building. And being
`workflow_dispatch`-only it reached 1 release in 28 (only v0.4.16 has a
`.pkg.tar.zst`), while HOW-TO-USE.md told Arch and CachyOS users to download
it from every release. A distribution channel that is absent 27 times out of
28 is worse than not promising one.
`packaging/arch/` and `.gitea/workflows/publish-arch-package.yml` are
preserved whole on `hold/arch-packaging`, the same way the disk panel and
drag-out work were held rather than deleted. What would make an Arch package
worth having is an AUR account and its SSH key as a repo secret — both
one-time manual steps that never happened; the workflow's own header already
said as much about its AUR push step.
This also closes the gap that prompted the review: nothing validated the
PKGBUILD until someone manually dispatched the workflow, making it the only
packaging path with no CI coverage. Removing it removes the untested surface
rather than adding a job to test something nobody installs.
In its place, `scripts/install-appimage.sh` does what a package manager's
install hooks would. An AppImage carries a `.desktop` entry and icons inside
itself, but nothing on the host reads them, so it never appears in the app
launcher. The script extracts the bundled icons into the user's icon theme
and writes a launcher entry — no sudo, nothing outside `~/.local/share`, and
the AppImage itself is never copied or moved.
Two details it gets right on purpose:
* The `Exec` line is rewritten, not copied. The bundled entry says
`Exec=triple-c`, which resolves only inside the running AppImage's own
mount — a verbatim copy gives a launcher entry that starts nothing.
* Extraction uses `--appimage-extract`, which needs no FUSE, so the script
works on a machine where *running* the AppImage would first need
`fuse2` installed. That requirement is now documented too: Arch and
CachyOS do not ship FUSE 2 by default.
Verified against the real artifact — the AppImage from this repo's own
preview-3a49a67 release: 4 icon sizes install, `desktop-file-validate` passes
with no warnings, `--uninstall` leaves nothing behind, and shellcheck is
clean.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ApLYH6ybHwQFkMCtKuHrrV
|
||
|
|
f2cfc0be8f |
Also attach the Arch package to the matching Gitea release
The workflow only ever uploaded to the GitHub release — the Gitea release for the same version (the plain, unsuffixed vX.Y.Z tag build-app.yml's Linux job creates, which already holds the .deb/.rpm/.AppImage) never got it, so it looked missing to anyone checking releases on Gitea instead of GitHub. New step mirrors build-app.yml's own Gitea upload step exactly: same get-or-create-by-tag, delete-existing-asset, upload-as-octet-stream shape, same REGISTRY_TOKEN secret. Verified the read side (release lookup, asset listing) against the real v0.4.16 release before writing this — resolves to the correct release id and correctly finds no existing asset yet. |
||
|
|
3c8296843f |
Skip AUR for now — attach the built Arch package to the GitHub release
Publishing to the AUR needs a maintainer AUR account and its SSH key registered as a secret here, neither of which exists yet. Rather than leave the workflow permanently failing at that last step, it now stops short of AUR and instead uploads the built .pkg.tar.zst to the same GitHub release it built from, as a plain downloadable asset (`pacman -U` to install). The AUR-push step is still in this file's git history if that setup happens later. Renamed publish-aur-package.yml -> publish-arch-package.yml to match. The render/validate steps are unchanged; new here is capturing the exact built package filename from inside the build container (makepkg is the only thing that actually knows it) and an upload step that follows the same create-or-reuse-release, strip-upload_url, POST-octet-stream pattern build-app.yml and backfill-releases.yml already use for GitHub assets, plus a delete-existing-asset-first step so a re-dispatch for an already-packaged version replaces rather than 422s. Verified with a real Docker run end to end: rendered a real PKGBUILD, built a real (synthetic) .deb through makepkg + namcap in an archlinux container, confirmed the container exits 0, and confirmed the exact package filename it captures (triple-c-bin-<version>-1-x86_64.pkg.tar.zst) round-trips out via docker cp intact. |
||
|
|
6dcdeb89cb |
Fix PKGBUILD render silently no-op'ing on every AUR publish run
The "Render PKGBUILD" step's Python heredoc built its old_source match
string via an f-string, escaping literal braces as `${{pkgver}}` — which
put that exact four-character sequence directly in this workflow file's
own YAML text. Gitea Actions scans a run: block for `${{ ... }}` and tries
to evaluate whatever's inside as one of its own expressions before the
shell ever sees the script; "pkgver" isn't a valid expression context, so
every run has been failing that interpolation and emptying the step
instead of raising anything visible there. The next step's `makepkg` then
failed with "PKGBUILD does not exist" — the actual point of failure was
one step earlier and unrelated to AUR credentials.
Rebuilt the same match string with a "$" variable and plain concatenation
so the file's own text never contains the trigger sequence. Verified by
extracting the exact heredoc and running it standalone against the real
PKGBUILD template — renders identically to the intended output.
|
||
|
|
b3d07bda09 |
Fix real workflow bugs a review found: dead bind mount, blind error gate
A review found the "Validate with makepkg and namcap" step's bind mount
(docker run -v "$PWD/rendered:/work") would very likely fail on Gitea's
own act_runner: a containerized job's $PWD isn't a path the daemon's host
can resolve, so the mount would silently attach an empty directory
instead of failing loudly — the same class of problem noted elsewhere for
this exact environment. Switched to docker create + docker cp (in and
back out) + docker start -a, the pattern already validated locally, which
works regardless of where the daemon actually lives.
Also found and fixed, most severe first:
- The namcap error gate (`grep -q "^[a-zA-Z0-9_-]*bin E:"`) only matched
one of namcap's two line shapes for reporting an error
("triple-c-bin E: ...") and missed the other ("PKGBUILD
(triple-c-bin) E: ...") entirely — confirmed by reproducing both against
a real namcap run. The PKGBUILD-level half of the safety net was dead.
Replaced with a plain `grep -q " E: "`, confirmed to match both real
shapes (and a split-package variant) and nothing else.
- package()'s `ar x "Triple-C_${pkgver}_amd64.deb"` named the asset
literally, defeating the whole point of the resolve step discovering
the real filename from the release instead of assuming a pattern — a
future Tauri bundler naming change would still break here with an
opaque error. Changed to `ar x ./*_amd64.deb`, which `source=()` already
guarantees matches exactly one file.
- `pacman -Sy` before installing packages is the canonical Arch partial-
upgrade footgun; changed to `pacman -Syu --noconfirm --needed`.
- `${{ inputs.version }}` was interpolated directly into a shell step
instead of routed through `env:`, unlike every other step in the file.
- `git push origin master` assumes the local branch name after cloning a
brand-new (not-yet-created) AUR repo's empty state is `master`, which
depends on the runner's own `init.defaultBranch` if the server sends no
symref. `git push origin HEAD:master` is unambiguous either way.
- The private key was written with a plain redirect then chmod'd after,
leaving a window where it's world-readable; now created at its final
mode first via `install -m 600 /dev/null`. Added `-o IdentitiesOnly=yes`
so a runner ssh-agent can't offer a different key first.
- Added GH_PAT auth to the api.github.com calls, matching every other
workflow in this repo, to avoid the unauthenticated 60/hour rate limit.
- Fixed two comments: the `options` comment credited `!debug` for
suppressing the empty debug-package directory, when it's actually
`!strip` doing that (verified in a real build); and documented in the
README that a hand-edit made directly in the AUR repo is silently
reverted by the next dispatch, since every run renders fresh from this
repo's template.
All of the above re-verified with the same real end-to-end methodology as
the original commit: real makepkg build, real namcap lint (clean), and
the exact updated docker create/cp/start sequence run against a live
container.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FGjXq6fqtAFHdbhk4f3PfZ
|
||
|
|
e025a7441a |
Add a native Arch/CachyOS package via its own AUR publish workflow
Part of triple-c#34's third ask ("I would like to also have an
Arch/CachyOS native version as well"), addressed separately from the
Wayland crash fix (fix/wayland-webkit-egl-crash) since it's an unrelated
feature, not a bug.
packaging/arch/PKGBUILD is a "-bin" AUR package repackaging the same .deb
build-app.yml already produces — no Rust/Node toolchain needed to install
it, and the user gets exactly the binary the project ships and tests.
Verified end to end against a real release (v0.4.14) rather than going by
Tauri's generic docs: downloaded the actual .deb, ldd'd the actual binary
to ground-truth `depends` (dropped `pango` and `libayatana-appindicator`
from an earlier draft — the first is already pulled in transitively by
gtk3, the second was never linked at all since this app has no tray icon
or menu), and ran a real makepkg/namcap/pacman -U cycle. namcap caught a
real issue this way (missing license file under
/usr/share/licenses/triple-c-bin/), now fixed by fetching LICENSE
alongside the .deb.
.gitea/workflows/publish-aur-package.yml does the actual publishing:
given a version (or "latest"), it finds that release's real Linux asset
on GitHub, downloads it, computes real checksums, renders the PKGBUILD
template, validates the result with makepkg and namcap inside a real
Arch container, and pushes to AUR. workflow_dispatch only, deliberately —
the same reasoning that killed sync-release.yml in triple-c#32 (releases
are assembled by build-app.yml across three separate platform jobs, so
there's no single automatic event that fires only once the Linux .deb
this needs actually exists) applies here too.
Requires a repo secret this workflow cannot set up itself:
AUR_SSH_PRIVATE_KEY, from an AUR account that has already created (or
been given co-maintainer access to) triple-c-bin — both one-time manual
steps on aur.archlinux.org. Until that secret exists, the workflow fails
loudly at the push step rather than silently doing nothing. See
packaging/arch/README.md for the full maintenance flow.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FGjXq6fqtAFHdbhk4f3PfZ
|
||
|
|
945883bb9d |
Actually offer a preview the release it precedes, and fix two more gaps
Secret Scan / scan (push) Successful in 4s
Build App (Preview) / compute-version (pull_request) Successful in 3s
Secret Scan / scan (pull_request) Successful in 4s
Build App (Preview) / create-release (pull_request) Successful in 1s
Build App (Preview) / build-macos (pull_request) Successful in 2m39s
Build App (Preview) / build-windows (pull_request) Successful in 4m50s
Build App (Preview) / build-linux (pull_request) Successful in 7m25s
Build App (Preview) / prune-previews (pull_request) Successful in 6s
An Opus review of the previous commit found its headline claim didn't hold: a preview and the release it precedes compute to the identical numeric version by construction, but check_for_updates compared with a strict `>` against the bare CARGO_PKG_VERSION (never the suffixed display string), so `(0,4,13) > (0,4,13)` is false and the release was never offered. Plain semver ordering doesn't make a `-preview.<sha>` suffix sort below the same numeric release on its own here, since the comparison never sees the suffix at all. pick_update now takes is_preview_build, derived from whether TRIPLE_C_BUILD_SUFFIX was baked in, and relaxes that one comparison to `>=` — so "a release exists at my own number" reads as an update. A production build still requires strictly newer. Also: ported build-app.yml's `git tag --points-at HEAD` guard into the preview version computation. Without it, workflow_dispatch (which this workflow allows on main, not just PR builds) run on a commit a release was already cut from would compute one past that release — reintroducing "preview outranks production" through the manual-dispatch door. And corrected two comments that claimed the prerelease filter was currently a no-op: backfill-releases.yml mirrors every Gitea release to GitHub unfiltered, prerelease flag included, so it's real defence-in-depth against a dispatched backfill leaking a preview release, not a no-op. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FGjXq6fqtAFHdbhk4f3PfZ |
||
|
|
b71e15c2c0 |
Make preview versions monotonic and distinguishable from production
Secret Scan / scan (push) Successful in 6s
Build App (Preview) / compute-version (pull_request) Successful in 3s
Secret Scan / scan (pull_request) Successful in 3s
Build App (Preview) / create-release (pull_request) Successful in 1s
Build App (Preview) / build-macos (pull_request) Successful in 2m41s
Build App (Preview) / build-windows (pull_request) Successful in 4m51s
Build App (Preview) / build-linux (pull_request) Successful in 6m26s
Build App (Preview) / prune-previews (pull_request) Successful in 4s
build-app-preview.yml computed its patch number as `git rev-list --count <latest tag>..HEAD` — the exact formula build-app.yml itself documents as broken and replaced (#26): a distance from whichever tag sorts highest, not a counter, so it resets to zero on every release and previews went backwards (0.4.62 -> 0.4.0) the moment one landed. Ported the same "one past the highest patch already used" computation build-app.yml uses for real releases, reading the same tags (including -mac/-win suffixes), so a preview built right before a release now computes the exact number that release is about to take — semver already orders `0.4.12-preview.<sha> < 0.4.12`, so a preview user is offered the release the moment it ships instead of being silently pinned forever. The installed preview's reported version was also indistinguishable from production: the bundle's own version field strips the `-preview.<sha>` suffix before touching tauri.conf.json/Cargo.toml/package.json, since the Windows MSI's ProductVersion has no room for one. Rather than risk that (unverifiable without an actual Windows build), preview builds now bake the suffix into the binary separately via a TRIPLE_C_BUILD_SUFFIX build-time env var, and get_app_version() appends it when present — a production build sets nothing, so this is a no-op there. Also: added `prerelease` to `GitHubRelease` and filter on it in check_for_updates (currently a no-op against real data — nothing mirrored to GitHub is ever prerelease:true — but the updater is no longer structurally incapable of enforcing a channel split if one is ever made explicit). And deleted sync-release.yml: workflow_dispatch-only, reading gitea.event.release.* fields a manual dispatch never populates, so it could never have actually run; build-app.yml's inline mirror already does the same job. Refactored check_for_updates' filtering into a pure, testable pick_update helper (this file had no tests before), and added tests for it and the new get_app_version suffix handling. Fixes #32. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FGjXq6fqtAFHdbhk4f3PfZ |
||
|
|
68b73a9102 |
Refuse a commit that adds something shaped like a credential
Secret Scan / scan (push) Successful in 4s
Build App (Preview) / compute-version (pull_request) Successful in 4s
Secret Scan / scan (pull_request) Successful in 5s
Build App (Preview) / create-release (pull_request) Successful in 2s
Build App (Preview) / build-macos (pull_request) Successful in 2m34s
Build App (Preview) / prune-previews (pull_request) Canceled after 0s
Build App (Preview) / build-linux (pull_request) Canceled after 3m23s
Build App (Preview) / build-windows (pull_request) Canceled after 3m26s
The companion to the fixture removal. A site-admin token sat in a test file for
92 commits and fourteen days on a public mirror, past five audit rounds and two
independent reviews, because all of them read the code under change and this was
not under change. A grep would have caught it the first day.
`scripts/scan-secrets.sh` is that grep, in three rules:
* vendor-prefixed credentials — `ghp_`, `github_pat_`, `glpat-`, `xox*-`,
`sk-`, `AKIA`/`ASIA`, `ya29.`, `AIza`, `npm_`, `dckr_pat_`. Shape alone
identifies these, so there is no context to get wrong.
* `BEGIN … PRIVATE KEY` blocks.
* an opaque literal assigned to a secret-shaped name — the rule that would
have caught this one.
The third rule needs **both** halves, and that is what makes it usable rather
than another disabled check. Measured before writing it: an entropy-only rule
flags 317 literals in this tree, and name-proximity alone flags four, three of
which are `secure::get_project_secret(&id, "aws-secret-access-key")` — a
keychain *key name* sitting next to the word `secret`. Requiring the literal
itself to be hex or base64 with no word structure is what excludes those.
Validated rather than asserted:
* **0 false positives** across every tracked file.
* **Catches the real incident** — `--range 9b2f4fe~1..9b2f4fe` is refused.
* Twelve shaped cases pass and fail as intended, including a sha256 in an
`assert_eq!`, a git sha in a comment and the new dummy fixture, none of
which trip it.
* The hook was proved to block an actual `git commit`, not just to exist.
Two halves, because each covers the other's gap:
* `.githooks/pre-commit`, enabled per clone by `npm run hooks`. Git will not
let a repository set its own hooks path — cloning would then be enough to
run its code — so this is opt-in everywhere and `--no-verify` skips it.
* `Secret Scan`, which nobody can bypass. It carries **no `paths:` filter** on
purpose: the leak lived in `app/**` and `build.yml` only runs for
`container/**`, so a path-filtered scan would have missed the very thing it
exists for. It scans the whole tracked tree rather than a range, because a
wrong range fails *open* and the full pass takes 0.5s.
Also fixed while here: `core.hooksPath` in this clone pointed at
`/workspace/.git/hooks`, a directory that does not exist — so git hooks were
disabled outright and anything dropped in `.git/hooks` would have been ignored
in silence. A hook that never runs is worse than no hook, because the checklist
says it is there.
`--tracked` skips binaries. Feeding a blob to grep gets "binary file matches"
instead of the line, so a genuine finding inside one would arrive as a sentence
nobody can act on.
A line ending `pragma: allowlist secret` is skipped — wordy on purpose, so it
reads as a claim and leaves something greppable.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LHL9ty7arp8FHwvE77ne7y
|
||
|
|
3741e0fef5 |
Number releases by the highest one already published, not by drift
The Linux release upload failed with a bare "exitcode '1'" and no output. The cause was not the upload: compute-version handed it a version that had already been released three days earlier. The patch number was `git rev-list --count <highest tag>..HEAD` — how far HEAD has drifted from whichever tag sorts highest, which resets to zero every time a tag is cut. It is not a counter, and the published history is what the old formula returned at each point: v0.4.0 -> 3 commits -> v0.4.3 looked fine v0.4.3 -> 4 commits -> v0.4.4 fine by luck, 4 > 3 v0.4.4 -> 2 commits -> v0.4.2 went backwards v0.4.4 -> 6 commits -> v0.4.6 jumped, skipping .5 v0.4.6 -> 3 commits -> v0.4.3 already taken So the line published 0.4.0, 0.4.3, 0.4.4, 0.4.2, 0.4.6 in that order, never used 0.4.1 or 0.4.5, and then came back round to 0.4.3. The patch is now one past the highest already used. Suffixed tags count towards that: create-tag is skipped whenever a platform job fails, so a run can publish v0.4.7-mac and never create the plain v0.4.7, and reading only unsuffixed tags would hand the same number out twice. A commit that is already tagged reuses its own tag, so re-running a build does not mint a version. Reusing a number was doing real damage, not just failing. macOS and Windows delete-then-upload each asset, so they took the duplicate in their stride and rewrote v0.4.3-mac and v0.4.3-win — public since Aug 11 — with today's binaries. Linux is the only platform that failed, and failing was the correct outcome; its v0.4.3 assets are the only ones still original. Linux also gets the idempotent get-or-create the other two already had, plus `set -euo pipefail` and `-fsS`. Its `curl -s` with no `-f` is why a 409 produced no diagnostic at all: the HTTP error was swallowed, the id grep came back empty, and the step died without ever printing why. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
ab747ce53d |
Say what "open in container" is doing, and land on the pane doing it
Build App (Preview) / compute-version (pull_request) Successful in 4s
Build App (Preview) / create-release (pull_request) Successful in 1s
Build App (Preview) / build-macos (pull_request) Successful in 2m40s
Build App (Preview) / build-linux (pull_request) Successful in 5m33s
Build App (Preview) / build-windows (pull_request) Successful in 5m40s
Build App (Preview) / prune-previews (pull_request) Successful in 1s
Opening a page is a container probe, a browser launch, a page load and often a viewer start — several seconds during which the only feedback was the click itself. Worse from a terminal, where the result appears in a pane the user is not looking at. So: the backend emits progress on the existing `container-progress` channel at each step, the Browser tab renders that line whenever it is set — the progress belongs to the project, not to whoever pressed the button, which is what lets a terminal-initiated open report anywhere at all — and the terminal's "In container" now selects the project's Browser tab before starting, so the line has somewhere to appear. Selecting a sub-tab from outside needed a route: `ProjectHome` keeps it in local state, so `openProjectHomeTab` parks a request in the store and the pane consumes it once. Consumed once, so it cannot fight the user's own clicking afterwards. Preview releases now prune themselves to the newest KEEP_PREVIEWS (2), in a job that runs only if all three platforms published — a half-finished run must not evict a good older build. The cleanup workflow's manual sweep stays as the backstop. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
5bd80a05bc |
One build per push: previews carry the PR check
Build App (Preview) / compute-version (pull_request) Successful in 3s
Build App (Preview) / create-release (pull_request) Successful in 1s
Build App (Preview) / build-macos (pull_request) Successful in 2m44s
Build App (Preview) / build-windows (pull_request) Successful in 5m27s
Build App (Preview) / build-linux (pull_request) Successful in 5m36s
Every push to the PR started two workflows on the same commit. build-app.yml ran on pull_request and compiled all three platforms — then published nothing, because every publishing step in it is gated on `gitea.event_name == 'push'`. build-app-preview.yml compiled the same three and published them. Six OS builds per push, half of them unreachable. So the PR trigger moves to the preview workflow, which was already doing the identical compilation and has something to show for it. build-app.yml is now push-to-main and manual dispatch only: releases. Two things a pull_request event changes, handled rather than inherited: `gitea.sha` can be the merge ref — not the commit anyone is testing, and not something to hang a tag on — so the release's target comes from `git rev-parse HEAD` in the checkout; and `gitea.ref_name` is the PR number, so the release body uses `gitea.head_ref` when there is one. The cost is one prerelease per PR commit touching app/**, which the existing Cleanup Old Releases sweep already prunes. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
5b18ce804f |
Start the 0.4 line, and give previews the version they are previewing
Build App / compute-version (pull_request) Successful in 5s
Build App / build-macos (pull_request) Successful in 2m34s
Build App / build-windows (pull_request) Successful in 5m17s
Build App / build-linux (pull_request) Successful in 5m23s
Build App / create-tag (pull_request) Skipped
Build App / sync-to-github (pull_request) Skipped
Two version problems, one of them mine. **Previews claimed x.y.0.** The preview workflow hard-coded the patch number, so every preview installer reported 0.3.0 whatever it contained, while the real build computes the patch from tags. It now runs the same computation, so a preview is labelled with the version the release it previews would carry. **A new minor line started at the wrong number.** `compute-version`'s fallback for "no tag matches this line yet" counted every commit in the repository — fine as a bootstrap, wrong the moment a minor version is bumped: the first 0.4 build would have been 0.4.234. A line nobody has tagged is a new line, and a new line starts at .0. With those fixed, VERSION moves to 0.4 — tab reordering, the browser pop-out, opening pages in the container's browser and the Playwright install fix are more than a patch bump. The next release is v0.4.0; today's HEAD would have been 0.3.90 on the old line. `app/package.json`, `package-lock.json`, `tauri.conf.json` and `Cargo.toml` follow to 0.4.0. CI patches all four per build, so they are the dev-time defaults rather than the source of truth — but a local `tauri dev` shows them, so they should not still say 0.3. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
63f3c54b95 |
Publish preview builds as a prerelease instead of workflow artifacts
Build App / compute-version (pull_request) Successful in 4s
Build App / build-macos (pull_request) Successful in 2m33s
Build App / build-windows (pull_request) Successful in 5m20s
Build App / build-linux (pull_request) Successful in 5m30s
Build App / create-tag (pull_request) Skipped
Build App / sync-to-github (pull_request) Skipped
Workflow artifacts do not work on this Gitea, in two different ways:
* upload-artifact@v4 cannot run at all. @actions/artifact v2's isGhes()
treats any GITHUB_SERVER_URL that is not github.com / *.ghe.com /
*.localhost as GitHub Enterprise Server and throws before making a
single request. act_runner sets it to this instance, so all three
platforms died with GHESNotSupportedError — after paying for the
whole Tauri build (run #265).
* @v3 uploads succeed and the files are downloadable by direct URL,
but Gitea does not *list* them: /api/v1/…/runs/<id>/artifacts returns
total_count 0 and the run page shows nothing (verified on run #267).
A build nobody can find is not a build.
So previews publish the way every other workflow here does: curl to the
releases API. One prerelease per preview, tagged `preview-<sha>`, with
all three platforms' bundles as assets — visible on the Releases page
with stable links.
The release is created in a job the three builds depend on rather than
get-or-created in each. They run concurrently, so per-job creation races
on one tag: the loser gets a 409, and the id parse then yields empty
while the step still reports success — the failure build-app.yml's
macOS job was hardened against after it happened for real. One creator
removes the race instead of handling it.
Asset upload keeps that hardening: delete-then-upload so a re-dispatch
replaces rather than 409s, --http1.1 and retries for the mid-stream
drops the macOS runner has produced (curl exit 92, exit 28), and an
explicit failure when a platform produced no bundles at all.
The `preview-` prefix is load-bearing: cleanup-releases.yml keeps recent
`v<x>.<y>.<z>` releases and separately deletes every release whose tag
does not start with `v[0-9]`, so previews are pruned by the cleanup
already in use and never crowd the real release list. sync-release.yml
is dispatch-only, so none of this reaches GitHub.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
||
|
|
1207a21aae |
Pin the preview build's uploads to upload-artifact@v3
Build App / compute-version (pull_request) Successful in 5s
Build App / build-macos (pull_request) Successful in 2m32s
Build App / build-windows (pull_request) Successful in 5m20s
Build App / build-linux (pull_request) Successful in 5m32s
Build App / create-tag (pull_request) Skipped
Build App / sync-to-github (pull_request) Skipped
Run #265 — this workflow's first ever run — built the app on all three platforms and then lost every bundle at the upload step: GHESNotSupportedError: @actions/artifact v2.0.0+, upload-artifact@v4+ and download-artifact@v4+ are not currently supported on GHES. v4 bundles @actions/artifact v2, whose isGhes() treats any GITHUB_SERVER_URL that is not github.com, *.ghe.com or *.localhost as GitHub Enterprise Server and throws before making a single request. act_runner sets that variable to this Gitea instance, so v4 cannot work here on any runner or any OS — and it fails *after* the whole Tauri build has been paid for. v3 uses the v1 artifact API, which Gitea implements. Both options this workflow relies on, `if-no-files-found: error` and `retention-days`, exist in v3. The other workflows never hit this because they publish by curling the Gitea releases API instead. Noted at the top of the file, with the isGhes rule, so the pin is not "upgraded" back. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
2c014fd752 |
CI: create the WOW64 junctions in the workflow instead of by hand
Build App / compute-version (pull_request) Successful in 6s
Build App / build-macos (pull_request) Successful in 2m29s
Build App / build-windows (pull_request) Successful in 5m52s
Build App / build-linux (pull_request) Successful in 6m12s
Build App / create-tag (pull_request) Skipped
Build App / sync-to-github (pull_request) Skipped
The Windows fix was the only part of it living outside git — two junctions created by hand on the build VM. Rebuild that VM, add a second Windows runner, or reset the SYSTEM profile and Windows builds break again with an error that points nowhere near the cause. Tauri downloads candle.exe, light.exe and makensis.exe, and all three are 32-bit. A runner running as SYSTEM has %LOCALAPPDATA% under C:\Windows\System32\config\systemprofile, and WOW64 redirection serves 32-bit processes reading System32 from SysWOW64, where those directories do not exist. The bundlers cannot see their own folder: candle exits 0x80131700, makensis reports "Unable to start child process, error 0x2", and Tauri surfaces neither — only "failed to run candle.exe". The job now junctions the SysWOW64 view onto the System32 originals when it detects a profile inside System32, and skips entirely otherwise, so a runner running as a normal user is unaffected. Idempotent, and written with goto rather than nested blocks to avoid the delayed-expansion trap that already bit the MSVC step. Verified rather than assumed: the hand-made junctions were deleted from the build VM before this was pushed, so this run has to recreate them. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
0aa8315514 |
CI: restore the MSI now that the 32-bit bundlers can resolve their paths
Build App / compute-version (pull_request) Successful in 3s
Build Container / build-container (pull_request) Successful in 32s
Build App / build-macos (pull_request) Successful in 2m26s
Build App / build-windows (pull_request) Successful in 4m51s
Build App / build-linux (pull_request) Successful in 6m11s
Build App / create-tag (pull_request) Skipped
Build App / sync-to-github (pull_request) Skipped
Dropping the MSI did not help: makensis.exe is 32-bit like candle.exe
and failed the same way ("Unable to start child process, error 0x2").
The cause was WOW64 redirection sending 32-bit processes reading
C:\Windows\System32 to SysWOW64, where the toolset directory does not
exist.
The build VM now carries junctions from the SysWOW64 view of
systemprofile\AppData\Local\tauri and systemprofile\.cache to the
System32 originals. Verified on the runner: candle.exe reports WiX
3.14.1.8722 and makensis reports v3.11, both exiting 0 from the path
that previously failed.
Both targets build again, so the .msi comes back. Artifact collection
fails if either installer is missing.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
||
|
|
fdc161fd9c |
CI: build NSIS only on Windows, dropping the MSI target
Build App / compute-version (pull_request) Successful in 17s
Build Container / build-container (pull_request) Successful in 1m22s
Build App / build-macos (pull_request) Successful in 2m22s
Build App / build-windows (pull_request) Failing after 4m41s
Build App / build-linux (pull_request) Successful in 5m51s
Build App / create-tag (pull_request) Skipped
Build App / sync-to-github (pull_request) Skipped
WiX's candle.exe/light.exe are 32-bit. On a SYSTEM-run runner Tauri caches WiX under C:\Windows\system32\config\systemprofile\..., and WOW64 redirection sends 32-bit processes to SysWOW64 where that directory does not exist, so candle exits 0x80131700. Tauri aborts the whole bundle on one target's failure, so the MSI was suppressing the NSIS installer too and Windows produced no artifact at all. NSIS is what the project already relies on for Windows upgrades. Drops the .NET 3.5 gate, which existed only for WiX; keeps the MSVC step, which is what makes the app link. Artifact collection now fails when no installer is produced rather than tolerating an empty directory. To restore the MSI, run the runner as a normal user and set --bundles msi,nsis. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
763af91042 |
Revert: LOCALAPPDATA override does not move Tauri's WiX cache
Build App / compute-version (pull_request) Successful in 3s
Build Container / build-container (pull_request) Successful in 32s
Build App / build-macos (pull_request) Successful in 2m23s
Build App / build-windows (pull_request) Failing after 4m35s
Build App / build-linux (pull_request) Successful in 5m6s
Build App / create-tag (pull_request) Skipped
Build App / sync-to-github (pull_request) Skipped
Rust's `dirs` crate resolves LOCALAPPDATA on Windows through SHGetKnownFolderPath, which reads the process token rather than the environment, so the override changed nothing and 32-bit candle.exe still hit WOW64 redirection under the SYSTEM profile. Removing it rather than leaving a plausible-looking non-fix in the workflow. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
03384409e7 |
CI: keep the WiX toolset out of System32 so 32-bit candle.exe can run
Build App / compute-version (pull_request) Successful in 13s
Build Container / build-container (pull_request) Successful in 44s
Build App / build-macos (pull_request) Successful in 2m24s
Build App / build-windows (pull_request) Failing after 4m39s
Build App / build-linux (pull_request) Successful in 6m44s
Build App / create-tag (pull_request) Skipped
Build App / sync-to-github (pull_request) Skipped
WiX's candle.exe/light.exe are 32-bit. A SYSTEM-run runner has %LOCALAPPDATA% under C:\Windows\system32\config\systemprofile, where Tauri caches the WiX toolset — and WOW64 redirection sends 32-bit processes reading System32 to SysWOW64, which has no such directory. The CLR then fails to start with 0x80131700 and Tauri reports only "failed to run candle.exe". Verified: the same binary and identity exits 0 from C:\wixtest and 0x80131700 from the systemprofile path. Pointing LOCALAPPDATA outside System32 avoids redirection, needs no stored credential, and is a no-op for runners already running as a normal user. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
c6bb7fdf1d |
CI: fix the MSVC exit-code check and verify .NET 3.5 before bundling
Build App / compute-version (pull_request) Successful in 6s
Build Container / build-container (pull_request) Successful in 1m48s
Build App / build-windows (pull_request) Failing after 5m14s
Build App / build-linux (pull_request) Successful in 6m2s
Build App / build-macos (pull_request) Successful in 2m24s
Build App / create-tag (pull_request) Skipped
Build App / sync-to-github (pull_request) Skipped
%VSEXIT% and %ERRORLEVEL% inside a parenthesised cmd block are substituted at parse time, not run time, so the installer's real exit code was never read. Uses delayed expansion now. Also checks for the .NET 3.5 runtime before building: WiX candle.exe needs it, and Tauri aborts the whole bundle when the MSI target fails, which silently suppresses the NSIS installer too. Fails early with the exact dism command rather than at bundle time. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
ca0f944712 |
CI: install MSVC build tools on Windows runners that lack them
Build App / compute-version (pull_request) Successful in 4s
Build Container / build-container (pull_request) Successful in 30s
Build App / build-linux (pull_request) Successful in 5m24s
Build App / build-windows (pull_request) Failing after 15m29s
Build App / build-macos (pull_request) Successful in 2m24s
Build App / create-tag (pull_request) Skipped
Build App / sync-to-github (pull_request) Skipped
build-windows failed on this PR with "linker `link.exe` not found", while build-linux and build-container passed — the code was fine, the runner environment was not. The job installs Rust and Node conditionally but assumed the MSVC C++ toolchain was hand-provisioned. A runner without it registers normally, advertises windows-latest, accepts the job, downloads the entire crate graph and only then fails at link time. That also means a bare runner coming online turns a job that would have queued for a capable machine into a failed build. Installs the VC++ workload when vswhere cannot find it, matching the existing conditional Rust and Node steps. rustc locates MSVC through vswhere and the registry rather than PATH, so no dev-shell activation is needed. Installer exit 3010 (success, reboot pending) is treated as success. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
997e1ab3a9 |
Fix Windows release upload: idempotent get-or-create + fail-loud
Build App / compute-version (pull_request) Successful in 9s
Build App / build-macos (pull_request) Successful in 2m36s
Build App / build-windows (pull_request) Successful in 2m50s
Build App / build-linux (pull_request) Successful in 6m26s
Build App / create-tag (pull_request) Has been skipped
Build App / sync-to-github (pull_request) Has been skipped
The cmd-batch upload step POSTed to /releases unconditionally. On a
re-run the v{VERSION}-win tag already exists, so Gitea returns 409, the
findstr id parse yields an empty RELEASE_ID, and uploads go to a
malformed .../releases//assets URL -- all silently swallowed by cmd and
`curl -s`, so the step reported success while attaching no assets.
Rewrite in PowerShell mirroring the macOS job: look the release up by
tag first and create only on 404, throw if the id can't be resolved,
delete same-named assets left over from partial runs before re-upload,
and fail loudly (ErrorActionPreference=Stop, curl.exe -fsS with retries,
$LASTEXITCODE check).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
||
|
|
4588bdf40c |
Make macOS release upload idempotent across re-runs
Build App / compute-version (push) Successful in 2s
Build App / build-macos (push) Successful in 2m25s
Build App / build-windows (push) Successful in 4m42s
Build App / build-linux (push) Successful in 8m54s
Build App / create-tag (push) Successful in 3s
Build App / sync-to-github (push) Successful in 10s
Previous fix only addressed the network flake; a re-run after any upload failure still tripped over the leftover release record. The naive POST /releases got 409 from Gitea, the grep-pipe parser yielded an empty RELEASE_ID, and pipefail aborted with an opaque exit 1. Now: - Look up the release by tag first; reuse on 200, create on 404, fail loudly on anything else. - Validate RELEASE_ID is non-empty and surface the response body if parsing fails. - Before uploading each asset, check whether the release already has an asset with that name (from a partial prior run) and DELETE it so the POST is replace-not-conflict. - Set -euo pipefail explicitly so the script's failure modes are predictable rather than dependent on the runner's default flags. Network hardening from the previous commit (HTTP/1.1, retries, -f) is preserved. Linux and Windows blocks unchanged. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
b607cf3681 |
Harden macOS release upload against curl exit 92
Build App / compute-version (push) Successful in 3s
Build App / build-windows (push) Successful in 4m5s
Build App / build-linux (push) Successful in 9m53s
Build App / build-macos (push) Failing after 2m30s
Build App / create-tag (push) Has been skipped
Build App / sync-to-github (push) Has been skipped
macOS upload has been intermittently failing with curl exit 92
("HTTP/2 stream not closed cleanly") for several releases (v0.3.12,
v0.3.10, v0.3.1 all landed with empty asset arrays despite the per-tag
release record being created). It is not a size issue — Linux uploads
the 81MB AppImage on the same Gitea instance without trouble while the
Mac dmg is only 13.6MB.
Adds `--http1.1` to sidestep HTTP/2 stream multiplexing flakes on the
macOS runner, `-f` so HTTP errors no longer fail silently under `-s`,
and `--retry 5 --retry-all-errors --retry-delay 5 --max-time 600` to
absorb transient drops. Linux and Windows blocks unchanged; an inline
note in the YAML calls out where to mirror this if those start
failing.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
5360f22b65 |
Make preview build workflow manual-only
Trigger is workflow_dispatch exclusively so builds happen only when explicitly requested from the Actions UI, not on every branch push. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
0316234329 |
Add preview build workflow for non-main branches
Mirrors build-app.yml's three-platform matrix (Linux/macOS/Windows) but uploads the bundles as workflow artifacts instead of creating Gitea releases or syncing to GitHub, so feature branches can be smoke-tested without cluttering the release streams. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
d60124f1bd |
Fix CI: harden version computation and Dockerfile apt retries
Build App / compute-version (push) Successful in 3s
Build App / build-macos (push) Successful in 2m44s
Build App / build-windows (push) Successful in 5m18s
Build App / build-linux (push) Successful in 46m30s
Build App / create-tag (push) Successful in 2s
Build App / sync-to-github (push) Successful in 11s
Build Container / build-container (push) Failing after 3m14s
Two fixes for the v0.3.x initial build failures: 1. **Compute Version step**: When no tags match v0.3.*, `grep` returns exit 1 which under `pipefail` killed the step before the empty-tag fallback could run. Added `|| true` to the pipeline so the fallback (`git rev-list --count HEAD`) runs correctly on first 0.3.x build. 2. **Dockerfile apt-get update**: Transient archive.ubuntu.com mirror sync failures (stale Packages.gz with mismatched hash) broke the GitHub CLI install step. Added a shell retry loop (5 attempts with 10s sleep, clearing /var/lib/apt/lists/* between retries) to both the main system packages step and the GitHub CLI step, plus Acquire::Retries=3 on the other apt-get update calls for transient network failures. Also includes the Cargo.lock 0.2.0 → 0.3.0 rev that went with the previous version bump commit. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> |
||
|
|
532de77927 |
Add speech-to-text feature using Faster Whisper container
Build App / compute-version (pull_request) Successful in 3s
Build App / build-macos (pull_request) Successful in 2m28s
Build STT Container / build-stt-container (pull_request) Successful in 3m18s
Build App / build-windows (pull_request) Successful in 4m40s
Build App / build-linux (pull_request) Failing after 1m46s
Build App / create-tag (pull_request) Has been skipped
Build App / sync-to-github (pull_request) Has been skipped
Adds a mic button to the terminal UI that captures speech, transcribes it via a Faster Whisper sidecar container, and injects the text into the terminal input. Includes settings panel for model selection (tiny/small/medium), port config, and container lifecycle management. - stt-container/: Dockerfile + FastAPI server for Whisper transcription - Rust backend: STT container management, transcribe_audio IPC command - Frontend: useSTT hook, SttButton, SttSettings, WAV encoder - CI: Gitea Actions workflow for multi-arch STT image builds Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> |
||
|
|
8301fd3690 |
Add workflow to clean up old releases
Manual workflow that deletes old Gitea and GitHub releases, keeping only the N most recent versions. Defaults to dry-run mode for safe preview before deletion. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> |
||
|
|
bab1df1c57 |
Switch distribution from Gitea to GitHub/GHCR
Build App / compute-version (push) Successful in 6s
Build Container / build-container (push) Successful in 1m44s
Build App / build-macos (push) Successful in 2m21s
Build App / build-windows (push) Successful in 3m30s
Build App / build-linux (push) Successful in 4m52s
Build App / create-tag (push) Successful in 3s
Build App / sync-to-github (push) Successful in 10s
Work VPN blocks repo.anhonesthost.net, breaking update checks and image pulls. Move all user-facing distribution to GitHub (releases API) and GHCR (container images) while keeping Gitea as the source of truth for development and CI. - CI: push container images to GHCR alongside Gitea registry - App updates: switch releases API to api.github.com, filter by asset filename instead of tag suffix for unified releases - Image updates: switch registry to ghcr.io with anonymous token auth - Container pull: point REGISTRY_IMAGE to ghcr.io/shadowdao/triple-c-sandbox - Rename GiteaRelease/GiteaAsset structs to GitHubRelease/GitHubAsset Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> |
||
|
|
beae0942a1 |
Add dynamic versioning with VERSION file and tag-based patch counting
Build App / compute-version (push) Successful in 3s
Build App / build-macos (push) Successful in 2m19s
Build App / build-windows (push) Successful in 3m22s
Build App / build-linux (push) Successful in 6m14s
Build App / create-tag (push) Successful in 8s
Build App / sync-to-github (push) Successful in 10s
- Create VERSION file (currently `0.2`) as the single source of truth for major.minor
- Add compute-version job that reads VERSION and counts commits since the last
matching v{major.minor}.N tag to derive the patch number
- Patch resets automatically when VERSION is bumped (no matching tags exist yet)
- Add create-tag job that tags the repo after all platform builds succeed,
so subsequent builds count from the new tag
- All platform jobs now consume the shared version instead of computing their own
- VERSION file changes trigger the build workflow
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
||
|
|
6b49981b3a |
Update build workflow version from 0.1.x to 0.2.x
The computed build version was hardcoded as 0.1.${COMMIT_COUNT} across all
three platform jobs (Linux, macOS, Windows), producing 0.1.x releases even
though the source files were bumped to 0.2.0.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
||
|
|
b7585420ef |
Reconcile project statuses against Docker on startup, update docs and CI
Build App / build-macos (push) Successful in 2m40s
Build App / build-windows (push) Successful in 4m12s
Build App / build-linux (push) Successful in 5m4s
Build Container / build-container (push) Successful in 2m41s
Build App / sync-to-github (push) Successful in 10s
- Add reconcile_project_statuses command that checks actual Docker container state on startup, preserving Running status for containers that are genuinely still running and resetting stale statuses to Stopped - Add is_container_running helper using Docker inspect API - Frontend calls reconciliation after Docker is confirmed available - Update TECHNICAL.md project structure, auth modes, and file listings to match current codebase - Update README.md and HOW-TO-USE.md with MCP servers, Mission Control, file manager, bash shells, clipboard/audio shims, and progress modal docs - Add workflow file self-triggers to CI path filters for build-app.yml and build.yml - Install Mission Control skills to ~/.claude/skills/ in entrypoint Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> |
||
|
|
574fca633a |
fix: sync build artifacts to GitHub instead of empty source archives
Move GitHub release sync into build-app.yml as a final sync-to-github job that runs after all 3 platform builds complete. This eliminates the race condition where sync-release.yml triggered before artifacts were uploaded to Gitea. The old sync-release.yml is changed to manual-only. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> |
||
|
|
d642cc64de |
fix: use browser_download_url for Gitea asset downloads
The API endpoint /releases/assets/{id} returns JSON metadata, not the
binary file. Use the browser_download_url from the asset object instead.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
||
|
|
4f41f0d98b |
feat: add Gitea actions to sync releases to GitHub
Add two new workflows: - sync-release.yml: automatically mirrors releases (with assets) to GitHub when published on Gitea - backfill-releases.yml: manual workflow to bulk-sync all existing Gitea releases to GitHub Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> |
||
|
|
c9dc232fc4 |
fix: remove Node.js from actual path location on Act runner
The Act runner has Node 18 at /opt/acttoolcache/node/18.20.3/x64/bin/, not at /usr/local/bin/. Use $(dirname "$(which node)") to find and remove the actual binary location before installing Node 22. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> |
||
|
|
2d4fce935f |
fix: remove old Node.js before installing v22 on Linux runner
The Act runner has Node 18 at /usr/local/bin/node which takes precedence over the apt-installed /usr/bin/node. Even after running nodesource setup and apt-get install, the old Node 18 binary remained in the PATH. Now removes old binaries and uses hash -r to force path re-lookup. Also removes package-lock.json before npm install to ensure correct platform-specific bindings. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> |
||
|
|
e739f6aaff |
fix: check Node.js version, not just presence, in CI
The Act runner has Node.js v18 pre-installed, so the check `command -v node` passes and skips installing v22. Node 18 is too old for dependencies like vitest, jsdom, and tailwindcss/oxide. Now checks the major version and upgrades if < 22. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> |
||
|
|
550159fc63 |
Fix native binding error: use npm install instead of npm ci
@tailwindcss/oxide has platform-specific native bindings. The package-lock.json was generated on a different platform, so npm ci installs the wrong native binary. Switching to rm -rf node_modules + npm install lets npm resolve the correct platform-specific optional dependency (e.g., @tailwindcss/oxide-linux-x64-gnu on Linux, oxide-darwin-arm64 on macOS). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> |
||
|
|
e3c874bc75 |
Fix cargo PATH: use explicit export in every step that needs it
The Gitea Act runner's Docker container does not reliably support $GITHUB_PATH or sourcing ~/.cargo/env across steps. Both mechanisms failed because the runner spawns a fresh shell for each step. Adopted the same pattern that already works for the Windows job: explicitly set PATH at the top of every step that calls cargo or npx tauri. This is the most portable approach across all runner environments (Act Docker containers, bare metal macOS, Windows). Build history shows Linux succeeded through run#46 (JS-based actions) and failed from run#49 onward (shell-based installs). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> |
||
|
|
6cae0e7feb |
Source cargo env before using rustup in install step
GITHUB_PATH only takes effect in subsequent steps, but rustup/rustc/cargo are called within the same step. Adding `. "$HOME/.cargo/env"` immediately after install puts cargo/rustup in PATH for the remainder of the step. Fixed in both Linux and macOS jobs. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> |
||
|
|
601a2db3cf |
Move Node.js install before checkout in Linux build
The Gitea Linux runner also lacks Node.js, causing actions/checkout@v4 (a JS action) to fail with "node: executable file not found in PATH". Same fix as the macOS job: install Node.js via shell before any JS-based actions run. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> |
||
|
|
b795e27251 |
Fix Linux build PATH and add ARM64 container support
Linux app build: cargo was not in PATH for subsequent steps after shell-based install. Fixed by adding $HOME/.cargo/bin to GITHUB_PATH (persists across steps) and setting it in the job-level env. Also removed the now-unnecessary per-step PATH override in the macOS job. Container build: added QEMU setup and platforms: linux/amd64,linux/arm64 to produce a multi-arch manifest. The Dockerfile already uses arch-aware commands (dpkg --print-architecture, uname -m) so it builds natively on both architectures. This fixes the "no matching manifest for linux/arm64/v8" error on Apple Silicon Macs. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> |
||
|
|
19d4cbce27 |
Use shell-based check-before-install for all build jobs
Replace JS-based GitHub Actions (dtolnay/rust-toolchain, actions/setup-node) in the Linux job with shell commands that check if Rust and Node.js are already present before installing. All three jobs (Linux, macOS, Windows) now use the same pattern: skip installation if the tool is already available on the runner. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> |
||
|
|
946ea03956 |
Fix macOS CI build and add macOS build instructions
The macOS Gitea runner lacks Node.js, causing actions/checkout@v4 (a JS action) to fail with "Cannot find: node in PATH". Fixed by installing Node.js via Homebrew before checkout and replacing all JS-based actions (setup-node, rust-toolchain, rust-cache) with shell equivalents. Also adds macOS section to BUILDING.md covering Xcode CLI tools, universal binary targets, and Gatekeeper bypass instructions. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> |
||
|
|
ba4cb4176d |
Add macOS build job to app build workflow
Builds a universal binary (aarch64 + x86_64) targeting both Apple Silicon and Intel Macs. Produces .dmg and .app.tar.gz artifacts, uploaded to a separate Gitea release tagged with -mac suffix. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> |