fix(ci): resilient large git push to updates feed (1.0.8)
Release / release (push) Failing after 6m13s
Release / release (push) Failing after 6m13s
http.postBuffer 2GiB, disable low-speed abort, retry push; docs for nginx/Gitea limits. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -360,6 +360,24 @@ git push origin v1.0.1
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## Если `git push` в `updates` падает: `remote end hung up` / таймаут
|
||||||
|
|
||||||
|
Один коммит с **Windows + два AppImage** может быть **сотни МБ** — HTTPS-push иногда рвётся из‑за лимита буфера Git или таймаута **nginx / reverse proxy** перед Gitea.
|
||||||
|
|
||||||
|
**В репозитории с кодом** скрипт `scripts/sync-update-feed.mjs` уже выставляет в клоне feed-репо:
|
||||||
|
|
||||||
|
- `http.postBuffer` **2 GiB**;
|
||||||
|
- отключение «медленной передачи» (`http.lowSpeedLimit` / `http.lowSpeedTime`);
|
||||||
|
- до **3** повторов `git push` с паузой 20 с (переменная **`DND_GIT_PUSH_RETRIES`**, максимум 5).
|
||||||
|
|
||||||
|
Если ошибка сохраняется — на **сервере** (nginx и т.п.) проверьте, например:
|
||||||
|
|
||||||
|
- `client_max_body_size` — не меньше размера push (или `0` для безлимита, если политика безопасности позволяет);
|
||||||
|
- `proxy_read_timeout` / `proxy_send_timeout` — **несколько минут** и больше для больших загрузок;
|
||||||
|
- лимиты самого **Gitea** (`[repository.upload]`, `APP_MAX_FILE_SIZE` в зависимости от версии) — в документации вашей сборки Gitea.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Поведение приложения
|
## Поведение приложения
|
||||||
|
|
||||||
- Проверка только в **собранной** установке (`app.isPackaged`).
|
- Проверка только в **собранной** установке (`app.isPackaged`).
|
||||||
|
|||||||
Generated
+2
-2
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "DndGamePlayer",
|
"name": "DndGamePlayer",
|
||||||
"version": "1.0.7",
|
"version": "1.0.8",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "DndGamePlayer",
|
"name": "DndGamePlayer",
|
||||||
"version": "1.0.7",
|
"version": "1.0.8",
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "DndGamePlayer",
|
"name": "DndGamePlayer",
|
||||||
"version": "1.0.7",
|
"version": "1.0.8",
|
||||||
"description": "DNDGamePlayer — редактор и проигрыватель игр",
|
"description": "DNDGamePlayer — редактор и проигрыватель игр",
|
||||||
"main": "dist/main/index.cjs",
|
"main": "dist/main/index.cjs",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
* ARTIFACT_MAC — каталог с файлами macOS
|
* ARTIFACT_MAC — каталог с файлами macOS
|
||||||
* ARTIFACT_LINUX — каталог с файлами Linux (AppImage и т.д.)
|
* ARTIFACT_LINUX — каталог с файлами Linux (AppImage и т.д.)
|
||||||
* GIT_COMMIT_TAG — опционально, для сообщения коммита
|
* GIT_COMMIT_TAG — опционально, для сообщения коммита
|
||||||
|
* DND_GIT_PUSH_RETRIES — опционально, число попыток git push (1–5, по умолчанию 3)
|
||||||
*/
|
*/
|
||||||
import { execFileSync } from 'node:child_process';
|
import { execFileSync } from 'node:child_process';
|
||||||
import fs from 'node:fs';
|
import fs from 'node:fs';
|
||||||
@@ -56,6 +57,43 @@ function runGit(args, cwd) {
|
|||||||
execFileSync('git', args, { cwd, stdio: 'inherit' });
|
execFileSync('git', args, { cwd, stdio: 'inherit' });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Большие AppImage + exe в одном push: без этого Git по умолчанию может оборвать HTTPS (postBuffer / stall). */
|
||||||
|
function configureGitHttpForLargePush(cwd) {
|
||||||
|
// 2 GiB — достаточно для пачки артефактов; на старых Git при необходимости поднять на сервере лимиты nginx/Gitea.
|
||||||
|
runGit(['config', 'http.postBuffer', '2147483648'], cwd);
|
||||||
|
runGit(['config', 'http.lowSpeedLimit', '0'], cwd);
|
||||||
|
runGit(['config', 'http.lowSpeedTime', '0'], cwd);
|
||||||
|
}
|
||||||
|
|
||||||
|
function sleepSyncSeconds(seconds) {
|
||||||
|
try {
|
||||||
|
execFileSync('sleep', [String(seconds)], { stdio: 'ignore' });
|
||||||
|
} catch {
|
||||||
|
const end = Date.now() + seconds * 1000;
|
||||||
|
while (Date.now() < end) {
|
||||||
|
/* fallback без утилиты sleep */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function pushUpdatesBranch(work) {
|
||||||
|
const retries = Math.max(1, Math.min(5, Number.parseInt(process.env.DND_GIT_PUSH_RETRIES || '3', 10) || 3));
|
||||||
|
let lastError;
|
||||||
|
for (let attempt = 1; attempt <= retries; attempt += 1) {
|
||||||
|
try {
|
||||||
|
runGit(['push', '-u', 'origin', 'updates'], work);
|
||||||
|
return;
|
||||||
|
} catch (err) {
|
||||||
|
lastError = err;
|
||||||
|
console.warn(`[sync-update-feed] git push failed (attempt ${attempt}/${retries})`);
|
||||||
|
if (attempt < retries) {
|
||||||
|
sleepSyncSeconds(20);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw lastError;
|
||||||
|
}
|
||||||
|
|
||||||
function main() {
|
function main() {
|
||||||
const server = mustEnv('DND_UPDATES_SERVER').replace(/\/+$/u, '');
|
const server = mustEnv('DND_UPDATES_SERVER').replace(/\/+$/u, '');
|
||||||
const updatesRepo = mustEnv('UPDATES_REPO');
|
const updatesRepo = mustEnv('UPDATES_REPO');
|
||||||
@@ -80,6 +118,7 @@ function main() {
|
|||||||
|
|
||||||
runGit(['config', 'user.email', 'ci@gitea-actions.local'], work);
|
runGit(['config', 'user.email', 'ci@gitea-actions.local'], work);
|
||||||
runGit(['config', 'user.name', 'gitea-actions'], work);
|
runGit(['config', 'user.name', 'gitea-actions'], work);
|
||||||
|
configureGitHttpForLargePush(work);
|
||||||
|
|
||||||
const copied =
|
const copied =
|
||||||
copyFlatReleaseFiles(winDir, work) +
|
copyFlatReleaseFiles(winDir, work) +
|
||||||
@@ -96,7 +135,7 @@ function main() {
|
|||||||
const st = execFileSync('git', ['status', '--porcelain'], { cwd: work }).toString().trim();
|
const st = execFileSync('git', ['status', '--porcelain'], { cwd: work }).toString().trim();
|
||||||
if (st) {
|
if (st) {
|
||||||
runGit(['commit', '-m', `update feed ${tag}`], work);
|
runGit(['commit', '-m', `update feed ${tag}`], work);
|
||||||
runGit(['push', '-u', 'origin', 'updates'], work);
|
pushUpdatesBranch(work);
|
||||||
} else {
|
} else {
|
||||||
console.warn('[sync-update-feed] nothing to commit (identical artifacts?)');
|
console.warn('[sync-update-feed] nothing to commit (identical artifacts?)');
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user