chore: padroniza arquitetura Ciberfauna, logo na raiz, hooks de verificação e CI multi-arch no runner ARM
CI / Formatação e clippy (push) Successful in 1m9s
CI / Auditoria de dependências (push) Successful in 12s
CI / Testes (Linux) (push) Successful in 1m34s
Release / Cria a release (push) Successful in 5s
CI / Compila o app desktop (Linux) (push) Successful in 1m36s
Release / CLI (linux-aarch64) (push) Successful in 1m23s
Release / CLI (linux-x86_64) (push) Successful in 1m40s
Release / App desktop (linux-aarch64) (push) Successful in 7m32s
Release / App desktop (linux-x86_64) (push) Failing after 9m5s
Release / App desktop (windows) (push) Failing after 6m20s
CI / Formatação e clippy (push) Successful in 1m9s
CI / Auditoria de dependências (push) Successful in 12s
CI / Testes (Linux) (push) Successful in 1m34s
Release / Cria a release (push) Successful in 5s
CI / Compila o app desktop (Linux) (push) Successful in 1m36s
Release / CLI (linux-aarch64) (push) Successful in 1m23s
Release / CLI (linux-x86_64) (push) Successful in 1m40s
Release / App desktop (linux-aarch64) (push) Successful in 7m32s
Release / App desktop (linux-x86_64) (push) Failing after 9m5s
Release / App desktop (windows) (push) Failing after 6m20s
This commit is contained in:
1 parent
30a086a808
commit
659701b2d4
95 files changed
+2826
-253
No files matched your search
@@ -16,15 +16,15 @@ mkdir -p "$cache/partial"
|
||||
trap 'sudo chown -R "$(id -u):$(id -g)" "$cache" 2>/dev/null || true; rm -f "$cache/lock"' EXIT
|
||||
opts=(-o "Dir::Cache::archives=$cache" -y)
|
||||
|
||||
# 1) com .deb em cache: instala direto, sem nem atualizar o índice do apt
|
||||
if ls "$cache"/*.deb >/dev/null 2>&1 && timeout 300 sudo apt-get "${opts[@]}" install "${pkgs[@]}"; then
|
||||
# 1) com .deb em cache e índice presente: instala direto, sem nem atualizar o índice do apt
|
||||
if [ -z "$(dpkg --print-foreign-architectures)" ] && ls "$cache"/*.deb >/dev/null 2>&1 && ls /var/lib/apt/lists/*Packages* >/dev/null 2>&1 && timeout 300 sudo apt-get "${opts[@]}" install "${pkgs[@]}"; then
|
||||
echo "instalado a partir do cache"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# 2) sem cache (ou incompleto): atualiza e instala, até 3 tentativas com tempo limite
|
||||
# 2) sem cache (ou multiarch / incompleto): atualiza e instala, até 3 tentativas com tempo limite
|
||||
for tentativa in 1 2 3; do
|
||||
if timeout 240 sudo apt-get update && timeout 600 sudo apt-get "${opts[@]}" install "${pkgs[@]}"; then
|
||||
if timeout 240 sudo apt-get update && { [ -z "$(dpkg --print-foreign-architectures)" ] || timeout 600 sudo apt-get "${opts[@]}" upgrade; } && timeout 600 sudo apt-get "${opts[@]}" install "${pkgs[@]}"; then
|
||||
echo "instalado (tentativa $tentativa)"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
+92
-5
@@ -12,15 +12,22 @@
|
||||
set -euo pipefail
|
||||
|
||||
cd "$(dirname "$0")/.."
|
||||
platform=${1:?uso: build-gui.sh <linux|windows|windows-docker>}
|
||||
platform=${1:?uso: build-gui.sh <linux|linux-x86_64|linux-aarch64|windows|windows-docker>}
|
||||
tauri() { npx --yes @tauri-apps/cli@2 "$@"; }
|
||||
|
||||
if [ -z "${TAURI_SIGNING_PRIVATE_KEY:-}" ] && [ -f "$HOME/.tauri/sabia-updater.key" ]; then
|
||||
export TAURI_SIGNING_PRIVATE_KEY="$(cat "$HOME/.tauri/sabia-updater.key")"
|
||||
[ -f "$HOME/.tauri/sabia-updater.pass" ] && export TAURI_SIGNING_PRIVATE_KEY_PASSWORD="$(cat "$HOME/.tauri/sabia-updater.pass")"
|
||||
fi
|
||||
|
||||
if [ "$platform" = windows-docker ]; then
|
||||
docker volume create sabia-cargo >/dev/null
|
||||
docker volume create sabia-rustup >/dev/null
|
||||
mkdir -p dist-gui
|
||||
exec docker run --rm -v "$PWD":/src -v sabia-cargo:/root/.cargo -v sabia-rustup:/root/.rustup \
|
||||
-w /src -e HOST_UID="$(id -u)" -e HOST_GID="$(id -g)" ubuntu:24.04 bash -c '
|
||||
-w /src -e HOST_UID="$(id -u)" -e HOST_GID="$(id -g)" \
|
||||
-e TAURI_SIGNING_PRIVATE_KEY -e TAURI_SIGNING_PRIVATE_KEY_PASSWORD \
|
||||
ubuntu:24.04 bash -c '
|
||||
set -e
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
apt-get update -qq
|
||||
@@ -32,24 +39,104 @@ if [ "$platform" = windows-docker ]; then
|
||||
chown -R "$HOST_UID:$HOST_GID" dist-gui apps/gui/src-tauri/target 2>/dev/null || true'
|
||||
fi
|
||||
|
||||
rm -rf dist-gui
|
||||
mkdir -p dist-gui
|
||||
cd apps/gui/src-tauri
|
||||
|
||||
# Os ícones derivados do original não ficam todos no repositório.
|
||||
[ -f icons/icon.ico ] || tauri icon icons/source.png -o icons
|
||||
|
||||
tauri_blob_cache="$HOME/.cache/tauri"
|
||||
if [ -d /opt/hostedtoolcache ] && [ -w /opt/hostedtoolcache ]; then
|
||||
tauri_blob_cache="/opt/hostedtoolcache/tauri-tools"
|
||||
fi
|
||||
mkdir -p "$tauri_blob_cache" "$HOME/.cache/tauri"
|
||||
|
||||
fetch_cached_tool() {
|
||||
local name=$1 url=$2 patch_elf=${3:-0}
|
||||
local cached="$tauri_blob_cache/$name"
|
||||
if [ ! -s "$cached" ]; then
|
||||
local tmp="$cached.tmp.$$"
|
||||
curl -fsSL "$url" -o "$tmp"
|
||||
if [ "$patch_elf" = 1 ]; then
|
||||
dd if=/dev/zero of="$tmp" bs=1 count=3 seek=8 conv=notrunc 2>/dev/null
|
||||
fi
|
||||
chmod +x "$tmp"
|
||||
mv -f "$tmp" "$cached"
|
||||
fi
|
||||
if [ "$cached" != "$HOME/.cache/tauri/$name" ]; then
|
||||
cp -f "$cached" "$HOME/.cache/tauri/$name"
|
||||
chmod +x "$HOME/.cache/tauri/$name"
|
||||
fi
|
||||
}
|
||||
|
||||
case "$platform" in
|
||||
linux)
|
||||
tauri build --bundles appimage,deb
|
||||
linux|linux-aarch64)
|
||||
bundle="${CARGO_TARGET_DIR:-target}/release/bundle"
|
||||
rm -rf "$bundle/appimage" "$bundle/deb"
|
||||
tauri build --bundles appimage,deb
|
||||
cp "$bundle"/appimage/*.AppImage "$bundle"/deb/*.deb ../../../dist-gui/
|
||||
# O atualizador do Tauri (quando o projeto usa) precisa do .sig ao lado.
|
||||
cp "$bundle"/appimage/*.AppImage.sig ../../../dist-gui/ 2>/dev/null || true
|
||||
;;
|
||||
linux-x86_64)
|
||||
if [ "$(uname -m)" = x86_64 ]; then
|
||||
bundle="${CARGO_TARGET_DIR:-target}/release/bundle"
|
||||
rm -rf "$bundle/appimage" "$bundle/deb"
|
||||
tauri build --bundles appimage,deb
|
||||
else
|
||||
rustup target add x86_64-unknown-linux-gnu >/dev/null
|
||||
mkdir -p /tmp/x86_64-cross-tools "$HOME/.cache/tauri"
|
||||
cat >/tmp/x86_64-cross-tools/ldd <<'EOF'
|
||||
#!/usr/bin/env bash
|
||||
exec qemu-x86_64 /lib64/ld-linux-x86-64.so.2 --list "$@"
|
||||
EOF
|
||||
chmod +x /tmp/x86_64-cross-tools/ldd
|
||||
ln -sf /usr/bin/x86_64-linux-gnu-strip /tmp/x86_64-cross-tools/strip
|
||||
for tool_rel in glib-2.0/gio-querymodules gdk-pixbuf-2.0/gdk-pixbuf-query-loaders libgtk-3-0t64/gtk-query-immodules-3.0 libgtk-3-0/gtk-query-immodules-3.0; do
|
||||
if [ -x "/usr/lib/x86_64-linux-gnu/$tool_rel" ]; then
|
||||
tname=$(basename "$tool_rel")
|
||||
printf '#!/usr/bin/env bash\nexec qemu-x86_64 "/usr/lib/x86_64-linux-gnu/%s" "$@"\n' "$tool_rel" >"/tmp/x86_64-cross-tools/$tname"
|
||||
chmod +x "/tmp/x86_64-cross-tools/$tname"
|
||||
fi
|
||||
done
|
||||
fetch_cached_tool "linuxdeploy-07333c6-aarch64.AppImage" \
|
||||
"https://github.com/tauri-apps/binary-releases/releases/download/linuxdeploy-07333c6/linuxdeploy-aarch64.AppImage" 1
|
||||
fetch_cached_tool "linuxdeploy-plugin-appimage.AppImage" \
|
||||
"https://github.com/linuxdeploy/linuxdeploy-plugin-appimage/releases/download/continuous/linuxdeploy-plugin-appimage-aarch64.AppImage" 1
|
||||
fetch_cached_tool "runtime-x86_64" \
|
||||
"https://github.com/AppImage/type2-runtime/releases/download/continuous/runtime-x86_64" 0
|
||||
cat >"$HOME/.cache/tauri/linuxdeploy-07333c6-x86_64.AppImage" <<'EOF'
|
||||
#!/usr/bin/env bash
|
||||
export ARCH=x86_64
|
||||
export NO_STRIP=true
|
||||
export APPIMAGE_EXTRACT_AND_RUN=1
|
||||
export LDAI_RUNTIME_FILE="$HOME/.cache/tauri/runtime-x86_64"
|
||||
export LD_GTK_LIBRARY_PATH=/usr/lib/x86_64-linux-gnu
|
||||
export DEB_HOST_MULTIARCH=x86_64-linux-gnu
|
||||
export PKG_CONFIG_ALLOW_CROSS=1
|
||||
export PKG_CONFIG_LIBDIR=/usr/lib/x86_64-linux-gnu/pkgconfig:/usr/share/pkgconfig
|
||||
export PATH="/tmp/x86_64-cross-tools:$PATH"
|
||||
exec "$HOME/.cache/tauri/linuxdeploy-07333c6-aarch64.AppImage" "$@"
|
||||
EOF
|
||||
chmod +x "$HOME/.cache/tauri/linuxdeploy-07333c6-x86_64.AppImage"
|
||||
export PKG_CONFIG_ALLOW_CROSS=1
|
||||
export PKG_CONFIG_LIBDIR=/usr/lib/x86_64-linux-gnu/pkgconfig:/usr/share/pkgconfig
|
||||
export CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_LINKER=x86_64-linux-gnu-gcc
|
||||
export CC_x86_64_unknown_linux_gnu=x86_64-linux-gnu-gcc
|
||||
export CXX_x86_64_unknown_linux_gnu=x86_64-linux-gnu-g++
|
||||
bundle="${CARGO_TARGET_DIR:-target}/x86_64-unknown-linux-gnu/release/bundle"
|
||||
rm -rf "$bundle/appimage" "$bundle/deb"
|
||||
tauri build --target x86_64-unknown-linux-gnu --bundles appimage,deb
|
||||
fi
|
||||
cp "$bundle"/appimage/*.AppImage "$bundle"/deb/*.deb ../../../dist-gui/
|
||||
cp "$bundle"/appimage/*.AppImage.sig ../../../dist-gui/ 2>/dev/null || true
|
||||
;;
|
||||
windows)
|
||||
rustup target add x86_64-pc-windows-msvc >/dev/null
|
||||
tauri build --runner cargo-xwin --target x86_64-pc-windows-msvc --bundles nsis
|
||||
bundle="${CARGO_TARGET_DIR:-target}/x86_64-pc-windows-msvc/release/bundle/nsis"
|
||||
rm -rf "$bundle"
|
||||
tauri build --runner cargo-xwin --target x86_64-pc-windows-msvc --bundles nsis
|
||||
cp "$bundle"/*-setup.exe ../../../dist-gui/
|
||||
cp "$bundle"/*-setup.exe.sig ../../../dist-gui/ 2>/dev/null || true
|
||||
;;
|
||||
|
||||
@@ -250,7 +250,7 @@ function rustLabels(source, file) {
|
||||
// ---------------------------------------------------------------- coleta
|
||||
|
||||
const uiFiles = readdirSync(join(root, 'apps/gui/ui'))
|
||||
.filter((f) => f.endsWith('.js') && f !== 'i18n-en.js' && f !== 'paged.polyfill.min.js')
|
||||
.filter((f) => f.endsWith('.js') && f !== 'i18n-en.js' && f !== 'vendor')
|
||||
.map((f) => join(root, 'apps/gui/ui', f));
|
||||
uiFiles.push(join(root, 'apps/gui/ui/index.html'));
|
||||
|
||||
|
||||
Executable
+49
@@ -0,0 +1,49 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Gera, a partir da logo oficial, o ícone base usado pelo Tauri.
|
||||
|
||||
A logo oficial é `logo.png` na raiz do repositório (RGBA, fundo transparente,
|
||||
serve aos temas claro e escuro). Ela não é alterada aqui. Saída:
|
||||
apps/gui/src-tauri/icons/source.png 1024 px, a arte sobre o fundo escuro com cantos arredondados;
|
||||
o CI e `npx @tauri-apps/cli icon` geram o resto dos ícones.
|
||||
|
||||
Uso: python3 scripts/gerar-logo.py
|
||||
"""
|
||||
import os
|
||||
from PIL import Image, ImageDraw
|
||||
|
||||
RAIZ = os.path.join(os.path.dirname(os.path.abspath(__file__)), "..")
|
||||
ICONES = os.path.join(RAIZ, "apps/gui/src-tauri/icons")
|
||||
FUNDO_ICONE = (10, 16, 28) # o azul-noite do fundo da arte original
|
||||
|
||||
|
||||
def recortar_quadrado(im, margem=0.04):
|
||||
"""Recorta no que é visível (opacidade > 16, ignora resquícios) e centraliza num quadrado."""
|
||||
box = im.getchannel("A").point(lambda v: 255 if v > 16 else 0).getbbox()
|
||||
im = im.crop(box)
|
||||
w, h = im.size
|
||||
lado = round(max(w, h) * (1 + 2 * margem))
|
||||
quadro = Image.new("RGBA", (lado, lado), (0, 0, 0, 0))
|
||||
quadro.paste(im, ((lado - w) // 2, (lado - h) // 2), im)
|
||||
return quadro
|
||||
|
||||
|
||||
def main():
|
||||
logo = recortar_quadrado(Image.open(os.path.join(RAIZ, "logo.png")).convert("RGBA"))
|
||||
|
||||
lado = 1024
|
||||
fundo = Image.new("RGBA", (lado, lado), FUNDO_ICONE + (255,))
|
||||
arte = logo.resize((round(lado * 0.82),) * 2, Image.LANCZOS)
|
||||
fundo.paste(arte, ((lado - arte.width) // 2, (lado - arte.height) // 2), arte)
|
||||
mascara = Image.new("L", (lado, lado), 0)
|
||||
ImageDraw.Draw(mascara).rounded_rectangle((0, 0, lado - 1, lado - 1), radius=round(lado * 0.2237), fill=255)
|
||||
icone = Image.new("RGBA", (lado, lado), (0, 0, 0, 0))
|
||||
icone.paste(fundo, (0, 0), mascara)
|
||||
os.makedirs(ICONES, exist_ok=True)
|
||||
destino = os.path.join(ICONES, "source.png")
|
||||
icone.save(destino, optimize=True)
|
||||
os.chmod(destino, 0o644)
|
||||
print("icons/source.png")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Executable
+6
@@ -0,0 +1,6 @@
|
||||
#!/usr/bin/env bash
|
||||
# Liga o hook de pre-push do repositório (roda scripts/verificar.sh antes de cada push).
|
||||
set -euo pipefail
|
||||
cd "$(dirname "$0")/.."
|
||||
git config core.hooksPath .githooks
|
||||
echo "hook ligado: git push passa a rodar scripts/verificar.sh (desligue com: git config --unset core.hooksPath)"
|
||||
@@ -2,7 +2,7 @@
|
||||
# Compila o CLI para uma plataforma e empacota como o atualizador espera:
|
||||
# sabia-<tag>-<plataforma>.tar.gz com um .sha256 ao lado.
|
||||
#
|
||||
# scripts/package-cli.sh v1.0.1 linux-x86_64 x86_64-unknown-linux-gnu
|
||||
# scripts/package-cli.sh v1.0.3 linux-x86_64 x86_64-unknown-linux-gnu
|
||||
#
|
||||
# Plataformas: linux-x86_64 e linux-aarch64. O alvo diferente da máquina de build
|
||||
# usa o linker cruzado correspondente (gcc-x86-64-linux-gnu). Escreve os arquivos
|
||||
|
||||
@@ -16,9 +16,10 @@ id=$(curl -fsS "${auth[@]}" "$API/releases/tags/$tag" | jq -r .id)
|
||||
|
||||
for file in "$@"; do
|
||||
name=$(basename "$file")
|
||||
encoded=$(jq -rn --arg n "$name" '$n|@uri')
|
||||
for old in $(curl -fsS "${auth[@]}" "$API/releases/$id/assets" | jq -r --arg n "$name" '.[] | select(.name == $n) | .id'); do
|
||||
curl -fsS -X DELETE "${auth[@]}" "$API/releases/$id/assets/$old"
|
||||
done
|
||||
curl -fsS -X POST "${auth[@]}" -F "attachment=@$file" "$API/releases/$id/assets?name=$name" >/dev/null
|
||||
curl -fsS -X POST "${auth[@]}" -F "attachment=@$file" "$API/releases/$id/assets?name=$encoded" >/dev/null
|
||||
echo "enviado: $name"
|
||||
done
|
||||
Executable
+67
@@ -0,0 +1,67 @@
|
||||
#!/usr/bin/env bash
|
||||
# Verificação local: roda o mesmo que o CI roda, antes de você dar push.
|
||||
#
|
||||
# scripts/verificar.sh rápido (~1 min): formatação, clippy, tradução, scripts, workflows
|
||||
# scripts/verificar.sh --completo inclui os testes do workspace e o cargo audit
|
||||
#
|
||||
# O CI leva de 5 a 30 minutos por execução e roda em Linux; quase tudo que o faz falhar
|
||||
# aparece aqui em segundos. Se isto passa, o CI só deve revelar o que é próprio dele
|
||||
# (imagens baixadas, apt do runner).
|
||||
set -uo pipefail
|
||||
cd "$(dirname "$0")/.."
|
||||
completo=0
|
||||
[ "${1:-}" = "--completo" ] && completo=1
|
||||
falhas=()
|
||||
passo() { # passo "nome" comando...
|
||||
local nome="$1"; shift
|
||||
printf '\n\033[1m== %s\033[0m\n' "$nome"
|
||||
if "$@"; then printf '\033[32mok\033[0m %s\n' "$nome"; else printf '\033[31mFALHOU\033[0m %s\n' "$nome"; falhas+=("$nome"); fi
|
||||
}
|
||||
|
||||
passo "formatação (cargo fmt)" cargo fmt --all -- --check
|
||||
# as mesmas flags do CI: avisos viram erro, inclusive nos testes
|
||||
passo "clippy (workspace, todos os alvos)" env RUSTFLAGS="-D warnings" cargo clippy --workspace --all-targets
|
||||
passo "cobertura da tradução da interface" node scripts/check-ui-i18n.mjs
|
||||
passo "sintaxe dos scripts bash" bash -c 'for f in scripts/*.sh .githooks/*; do bash -n "$f" || exit 1; done'
|
||||
passo "workflows e templates (YAML válido)" python3 -c "
|
||||
import glob, yaml
|
||||
for f in glob.glob('.gitea/**/*.yml', recursive=True):
|
||||
yaml.safe_load(open(f))
|
||||
"
|
||||
passo "versões consistentes" python3 -c "
|
||||
import json, re, sys
|
||||
from pathlib import Path
|
||||
|
||||
def cargo_version(path):
|
||||
m = re.search(r'^version\s*=\s*\"([^\"]+)\"', Path(path).read_text(), re.M)
|
||||
if not m:
|
||||
sys.exit(f'versão não encontrada em {path}')
|
||||
return m.group(1)
|
||||
|
||||
versoes = [
|
||||
cargo_version('Cargo.toml'),
|
||||
cargo_version('apps/gui/src-tauri/Cargo.toml'),
|
||||
json.load(open('apps/gui/src-tauri/tauri.conf.json'))['version'],
|
||||
]
|
||||
if len(set(versoes)) != 1:
|
||||
sys.exit(f'versões divergentes: Cargo.toml={versoes[0]}, src-tauri={versoes[1]}, tauri.conf={versoes[2]}')
|
||||
print(versoes[0])
|
||||
"
|
||||
if [ -f apps/gui/src-tauri/Cargo.toml ] && pkg-config --exists webkit2gtk-4.1 2>/dev/null; then
|
||||
passo "app desktop (cargo check)" env RUSTFLAGS="" cargo check --manifest-path apps/gui/src-tauri/Cargo.toml
|
||||
else
|
||||
printf '\n(app desktop: pulado, faltam as bibliotecas do WebKitGTK; o CI compila)\n'
|
||||
fi
|
||||
|
||||
if [ "$completo" = 1 ]; then
|
||||
passo "testes (cargo test --workspace)" cargo test --workspace
|
||||
passo "auditoria de dependências (cargo audit)" cargo audit
|
||||
fi
|
||||
|
||||
printf '\n'
|
||||
if [ ${#falhas[@]} -eq 0 ]; then
|
||||
printf '\033[32mtudo certo\033[0m: pode dar push.\n'
|
||||
else
|
||||
printf '\033[31mfalhou:\033[0m %s\n' "${falhas[*]}"
|
||||
exit 1
|
||||
fi
|
||||
Reference in new issue
Block a user