ci.yml's four jobs (lint, tests, audit, gui check) still used
runs-on: ubuntu-latest. Since the Gitea runners were relabeled (see
the previous ci(release) commit), that alias now resolves only to
hostinger-runner — the single native amd64 machine release.yml routes
the x86_64 build legs to. Every CI push was piling onto that one
runner alongside the release jobs, and it could not keep up: run 73
(triggered by the previous commit) shows 'Set up job' taking 15m22s
and then every following step failing in 0s, including deterministic
ones like cargo fmt --check that have nothing to do with runner
architecture.
Pins all four ci.yml jobs to linux-arm64 (the two oracle-runner
replicas), matching the explicit-label convention release.yml already
uses, and freeing hostinger-runner to do only what it was provisioned
for.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VAyr8d7HuAdUGB6aA5xmDD
Two changes to release.yml, kept together since they touch the same
jobs:
1. Drops the 'updater' job ('Build latest.json'): the desktop app no
longer reads a Tauri-updater manifest (see the previous commit), so
nothing consumes it any more. Also drops the now-unused
GUARA_TAURI_SIGNING_PRIVATE_KEY(_PASSWORD) secrets from the 'gui'
job's env and the header comment documenting them.
2. Routes the linux-x86_64 leg of the cli and gui matrices to the new
native x86_64 Gitea Actions runner (hostinger-runner, label
linux-amd64) instead of cross-compiling it from an aarch64 host
(oracle-runner/-b, label linux-arm64):
- matrix.include gets an explicit runner field per platform;
runs-on: ${{ matrix.runner }} picks it per job. windows also
pinned to linux-amd64 explicitly rather than relying on the
ubuntu-latest alias, since that alias now points at whichever
runner is tagged for it and is no longer a safe stand-in for
"the aarch64 host" (it briefly meant exactly that, then got
relabeled to the x86_64 runner — pinning explicit labels avoids
depending on that alias at all).
- The "Platform cross-linker" step (gcc-x86-64-linux-gnu) only
runs when NOT on the native amd64 runner, since a native build
needs no cross-linker.
- scripts/build-gui.sh and scripts/package-cli.sh are intentionally
left untouched: both already branch on `uname -m` and take the
simple native path when run on x86_64. The existing cross-compile
path (qemu wrappers, the ELF launcher that survives
tauri-bundler's dd patch) stays in place as a dormant fallback in
case the single amd64 runner is ever unavailable — deliberately
kept, not deleted.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VAyr8d7HuAdUGB6aA5xmDD
Replaces the signed tauri-plugin-updater (latest.json manifest, minisign
key pair) with the same simple mechanism Sabiá already uses: query the
Gitea Releases API directly, download the matching platform archive,
verify its SHA-256 checksum, and swap the binary in place. The CI job
that built the old latest.json manifest is removed in the next commit,
alongside an unrelated runner-routing change to the same workflow file.
- New guara-core::update module (check/apply), ported from
sabia-core::update and adapted to Guará's own release asset naming
(guara-<tag>-<platform>.tar.gz, matching scripts/package-cli.sh).
- New Engine::update_check / Engine::update_apply, wired into the RPC
service for the browser UI.
- New CLI subcommand: "guara update" (check) and "guara update --apply"
(download, verify, replace), mirroring "sabia update".
- GUI: replaced the Tauri plugin-updater flow (download_and_install,
update-progress events, in-app restart) with a call to the new
update_check/update_apply commands. The desktop app can no longer
self-install in one click — it now points the user to the Releases
page, same as Sabiá's desktop app already does.
- Removed tauri-plugin-updater, createUpdaterArtifacts and the
updater.pubkey config, the signing-key loading in build-gui.sh, the
CI step testing the old latest.json generator, and the now-unused
make-latest-json.py/test_make_latest_json.py scripts.
- Documented the break for existing installs in CHANGELOG.md /
CHANGELOG.pt-BR.md: versions up to 1.3.2 won't find this release
automatically and need one manual download.
Trade-off accepted knowingly: SHA-256 verifies integrity against
Gitea's own API but, unlike the retired signed mechanism, does not
protect against a compromised Gitea server independently of it. This
is Lucas's own self-hosted instance, not a third-party mirror.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VAyr8d7HuAdUGB6aA5xmDD
Completes the English-only standardization for code, comments, scripts
and CI templates (UI/CLI-facing strings stay bilingual pt-BR/en,
untouched). Covers the remaining crates/, apps/gui/ui/ and
apps/gui/src-tauri/ comments, .gitea/ workflow and template comments,
.githooks/ hooks, and the scripts/ source comments for the files
already renamed in a prior commit (check.sh, generate-logo.py,
install-hooks.sh).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VAyr8d7HuAdUGB6aA5xmDD
On the aarch64 Gitea runner, tauri-bundler's prepare_tools step runs
'dd ... seek=8 conv=notrunc' on the cached linuxdeploy-x86_64 binary to
hide it from AppImage integration tools. That zeroed bytes 8-10 of the
file; our cached binary there was a bash wrapper script, so the dd wrote
into the middle of its shebang/interpreter line, corrupting it, and the
bundler's subsequent spawn failed with ENOENT ('failed to bundle
project: No such file or directory').
Replace the shell wrapper with a small native ELF launcher compiled with
cc: bytes 8-10 of an ELF header are EI_PAD padding, unused by the
loader, so the same dd leaves it executable. The launcher sets the same
environment the old wrapper did and execs the real aarch64 linuxdeploy
binary. Also cache AppRun-x86_64 explicitly so the bundler does not need
to fetch it itself mid-build.
Verified locally: compiled a minimal ELF binary, ran the same dd
command against it, confirmed it still executes (the shebang-script
equivalent does not).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VAyr8d7HuAdUGB6aA5xmDD
The updater reads latest.json from Gitea, built by scripts/make-latest-json.py
against the Gitea API (no gh CLI). Release workflow builds the Linux CLI and
the Linux+Windows desktop app, signs the updater artifacts and attaches
everything to the release.
Needs the repo secrets TAURI_SIGNING_PRIVATE_KEY and
TAURI_SIGNING_PRIVATE_KEY_PASSWORD, which I could not set (secret-store writes
are reserved for the user) - set them from ~/.tauri/guara-updater.key and
.pass before pushing a tag.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The Gitea CI has one Linux runner; the GUI's Windows package is cross-compiled
from it, but there is no path to a macOS build without Apple hardware and a
developer account.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Notes come from the matching CHANGELOG.md section. The macOS and Windows
binaries the old release workflow built need runners this Gitea does not have.
The CI also ignores .wolf, .claude and the release files.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Linux-only runner, so the Windows and macOS legs and GitHub's audit action are
gone. The Rust toolchain, cargo registry and target directories live on the
runner's persistent toolcache volume. release.yml stays under .github and is
not run by Gitea.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Só a logo nova: o guará com o anel laranja, uma arte transparente para os dois temas, no app, no
favicon, nos ícones e no README. Sem mudança de comportamento.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
O autor gerou a logo já sem fundo; ela passa a ser a arte oficial, usada em qualquer tema, e não é
mais alterada. scripts/processar-logo.py (que tirava o fundo) e a arte original com fundo saem;
scripts/gerar-logo.py só deriva guara-s.png (barra lateral e favicon) e o ícone do app, e os ícones
do Tauri são regenerados.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
A variante clara tinha artefatos; a arte escura recortada serve aos dois temas. Saem a troca de
variante por tema, os arquivos -light e a fonte clara; os arquivos escuros viram guara.png e
guara-s.png e o script, o app, o servidor do guara ui e o README usam só eles.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
A arte do usuário (assets/logo/*-fonte.png) passa a ser a logo do projeto. scripts/processar-logo.py
tira o fundo (só o que toca a borda e os bolsões internos, com a faixa da borda refeita pela cor
real do desenho, sem halo) e gera as variantes clara e escura (768 e 128 px) e o ícone do app. O app
escolhe a variante pelo tema (barra lateral, topo e tela inicial), o favicon e o servidor do guara ui
passam a PNG, os ícones do Tauri são regenerados e o README usa <picture> para claro e escuro. A logo
SVG antiga e o gerador dela saem.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
scripts/verificar.sh roda em segundos o mesmo que o CI roda (fmt, clippy -D warnings no workspace
inteiro, tradução, scripts, workflows) e, com --completo, os testes e o cargo audit. O hook de
pre-push (scripts/instalar-hooks.sh) a roda antes de cada push. O CI deixa de rodar em mudanças
só de documentação.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
O apt roda como root e deixa arquivos ilegíveis para o usuário do runner; o actions/cache
falhava com 'tar failed with exit code 2' e nunca salvava, então o cache dos .deb não valia.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Versões, changelog e roadmap: atualização pelo próprio app, assinaturas Ed25519, QCOW2 e VMDK
diferenciais, DMG com LZFSE, imagens de referência no CI dos três sistemas e o teste de exclusão
real do XFS (que rebaixa o XFS para 🟡).
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
O passo de ferramentas das imagens de teste levou 13 minutos num dia de espelho lento (803 s
no último run da main), como o do Tauri. scripts/apt-install.sh vira genérico (pasta de cache e
pacotes por argumento) e passa a servir aos dois.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Ao abrir, o app consulta o latest.json da release no GitHub; havendo versão nova, um cartão
oferece Atualizar agora: baixa, confere a assinatura com a chave pública embutida, instala e
reabre (AppImage substituído no lugar; Windows e macOS pelo instalador). Instalação por .deb ou
.rpm só avisa. Configurações ganha a opção de desligar a consulta e o botão Verificar agora.
A release assina os pacotes com a chave guardada no ambiente 'release' do GitHub (só tags v*) e
o latest.json é montado de uma vez por scripts/make-latest-json.py, depois que todos os jobs
de empacotamento terminam.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
O passo do apt levou 22 e 28 minutos em duas execuções de um dia de espelho lento (o normal é
uns 35 s). O script usa os .deb em cache sem nem atualizar o índice e, sem cache, tenta até 3 vezes
com tempo limite por tentativa. Vale para o CI e para o job do app desktop da release.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
No CI, com um XFS apagado pelo kernel, a recuperação por metadados não acha nada (o kernel zera
o inode e as extensões); o carving recupera o conteúdo de arquivos com estrutura reconhecível.
O teste de nome e pasta fica ignorado até o Guará ler o diário, e o roadmap e a documentação
passam a dizer isso em vez de marcar o XFS como validado.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
scripts/make-xfs-real-deletion.sh (precisa de root) monta uma imagem XFS por loop, grava
arquivos, apaga alguns e desmonta, deixando o hash de cada um em expected.tsv. O teste confere
que cada arquivo apagado volta pelo nome, na pasta certa e com o conteúdo original, e que os que
ficaram não aparecem como apagados. O CI do Linux gera a imagem com sudo e exige o teste.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Os testes com imagens reais (BitLocker, FileVault 2, dfvfs, AFF4, discos virtuais) só rodavam
na máquina de quem baixava as imagens; no CI eram pulados em silêncio. Agora o script de
download roda nos três sistemas, com cache pela versão do script.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>