fix(ci): install pipewire headers, and make the Gitea upload diagnosable
OpenSSF Scorecard / Scorecard analysis (push) Waiting to run
CI / Build & test (Node 20) (push) Canceled after 0s
CI / Build & test (Node 24) (push) Canceled after 0s
CI / Build & test (push) Canceled after 0s
CodeQL / Analyze (javascript-typescript) (push) Canceled after 0s
Security / Secret scan (gitleaks) (push) Canceled after 0s
Security / Dependency scan (OSV-Scanner) (push) Canceled after 0s
Security / IaC/config scan (Trivy) (push) Canceled after 0s
Security / License compliance scan (Trivy) (push) Canceled after 0s

Two separate failures on the first run.

Linux could not compile the native module: it needs libpipewire-0.3-dev, which
its README states and the apt list omitted.

Windows built everything, native module verified, then died on the upload with
a bare JSONDecodeError. The cause was curl -sf, which discards the error body,
so a failed release creation surfaced as an empty pipe and no reason at all.
The step now captures status and body and prints them, treats a failed create
as possibly the other matrix job having just created it, and passes
target_commitish so the tag can be created.

Embedded python gave way to jq: a multi-line heredoc inside a YAML literal
block ends the block at the first unindented line, which is how the file became
invalid YAML in the first place.
This commit is contained in:
2026-09-01 15:58:26 -03:00
parent 9f7723d104
commit 9ea399ded5
+57 -29
View File
@@ -43,7 +43,8 @@ jobs:
sudo apt-get install -y \
libx11-dev libxtst-dev libxt-dev \
libxkbcommon-dev libxkbcommon-x11-dev libxkbfile-dev \
libxrandr-dev libxinerama-dev libx11-xcb-dev
libxrandr-dev libxinerama-dev libx11-xcb-dev \
libpipewire-0.3-dev
- name: Setup pnpm
uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5.0.0
@@ -104,36 +105,60 @@ jobs:
GITEA_API: https://git.resenha.website/api/v1/repos/devsyncwrld/backspace
TAG: latest
run: |
set -euo pipefail
set -uo pipefail
if [ -z "${GITEA_TOKEN:-}" ]; then
echo "::error::segredo GITEA_TOKEN não configurado no repositório"
echo "::error::segredo GITEA_TOKEN não configurado"
exit 1
fi
# A release `latest` é recriada a cada publicação: o electron-updater
# busca latest.yml antes de saber qual versão existe, então a URL não
# pode conter número de versão.
ID=$(curl -sf -H "Authorization: token $GITEA_TOKEN" \
"$GITEA_API/releases/tags/$TAG" | python3 -c \
"import json,sys;print(json.load(sys.stdin).get('id',''))" 2>/dev/null || true)
# Sem -f e imprimindo o corpo: a versão anterior usava `curl -sf`, que
# engole a resposta de erro, então uma falha aqui só aparecia como um
# JSONDecodeError sem dizer o motivo.
api() {
local method=$1 path=$2; shift 2
curl -s -w '\n%{http_code}' -X "$method" \
-H "Authorization: token $GITEA_TOKEN" "$GITEA_API$path" "$@"
}
body() { sed '$d' <<<"$1"; }
code() { tail -n1 <<<"$1"; }
# jq em vez de python embutido: um heredoc multilinha dentro de um
# bloco literal de YAML encerra o bloco na primeira linha sem recuo.
json_id() { jq -r '.id // empty'; }
if [ -n "$ID" ]; then
echo "release existente ($ID) — removendo anexos desta plataforma"
curl -sf -H "Authorization: token $GITEA_TOKEN" "$GITEA_API/releases/$ID/assets" \
| python3 -c "import json,sys;[print(a['id'],a['name']) for a in json.load(sys.stdin)]" \
| while read -r aid aname; do
case "$aname" in
*.exe|*.AppImage|*.deb|latest*.yml)
curl -s -o /dev/null -X DELETE -H "Authorization: token $GITEA_TOKEN" \
"$GITEA_API/releases/$ID/assets/$aid" ;;
esac
done
find_release() {
local r; r=$(api GET "/releases/tags/$TAG")
[ "$(code "$r")" = "200" ] && body "$r" | json_id || echo ""
}
ID=$(find_release)
if [ -z "$ID" ]; then
R=$(api POST "/releases" -H 'Content-Type: application/json' \
-d "{\"tag_name\":\"$TAG\",\"name\":\"Última versão\",\"target_commitish\":\"main\",\"body\":\"Instaladores publicados pelo CI.\"}")
if [ "$(code "$R")" = "201" ]; then
ID=$(body "$R" | json_id)
echo "release criada: $ID"
else
echo "criação retornou HTTP $(code "$R"): $(body "$R")"
# O outro job da matriz pode tê-la criado no mesmo instante.
ID=$(find_release)
[ -n "$ID" ] || { echo "::error::não foi possível obter nem criar a release"; exit 1; }
echo "release encontrada após corrida: $ID"
fi
else
ID=$(curl -sf -X POST -H "Authorization: token $GITEA_TOKEN" \
-H 'Content-Type: application/json' \
-d "{\"tag_name\":\"$TAG\",\"name\":\"Última versão\",\"body\":\"Instaladores publicados automaticamente pelo CI.\"}" \
"$GITEA_API/releases" | python3 -c "import json,sys;print(json.load(sys.stdin)['id'])")
echo "release criada: $ID"
echo "release existente: $ID"
fi
# Remove só os anexos que esta plataforma vai repor, para os dois jobs
# não apagarem o trabalho um do outro.
R=$(api GET "/releases/$ID/assets")
if [ "$(code "$R")" = "200" ]; then
body "$R" | jq -r '.[] | "\(.id) \(.name)"' | while read -r aid aname; do
case "$aname" in
${{ runner.os == 'Windows' && '*.exe|latest.yml' || '*.AppImage|*.deb|latest-linux.yml' }})
echo "removendo anexo antigo: $aname"
api DELETE "/releases/$ID/assets/$aid" > /dev/null ;;
esac
done
fi
shopt -s nullglob
@@ -143,10 +168,13 @@ jobs:
packages/desktop/dist-electron/*.deb \
packages/desktop/dist-electron/latest*.yml; do
name=$(basename "$f")
echo "enviando $name"
curl -sf -X POST -H "Authorization: token $GITEA_TOKEN" \
-F "attachment=@$f" "$GITEA_API/releases/$ID/assets?name=$name" > /dev/null
R=$(api POST "/releases/$ID/assets?name=$name" -F "attachment=@$f")
if [ "$(code "$R")" != "201" ]; then
echo "::error::falha ao enviar $name — HTTP $(code "$R"): $(body "$R")"
exit 1
fi
echo "enviado: $name"
sent=$((sent+1))
done
[ "$sent" -gt 0 ] || { echo "::error::nada para enviar — o build não produziu instaladores"; exit 1; }
[ "$sent" -gt 0 ] || { echo "::error::o build não produziu instaladores"; exit 1; }
echo "$sent arquivo(s) publicados"