Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
name: CI

on:
push:
branches: [main, master]
pull_request:

permissions:
contents: read

jobs:
check:
runs-on: ubuntu-latest
env:
# Tests and the renderer build do not need the Electron binary.
ELECTRON_SKIP_BINARY_DOWNLOAD: '1'
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: npm
- run: npm ci
- run: npm run lint
- name: Typecheck
run: npx tsc -p tsconfig.node.json --noEmit && npx tsc -p tsconfig.json --noEmit
- name: Catalog
run: node scripts/verify-catalog.cjs --no-links && node scripts/generate-winget-map.cjs --verify
- name: Tests
run: |
node scripts/smoke.cjs
node scripts/test-download.cjs
node scripts/test-resilience.cjs
node scripts/test-app-full.cjs
- name: Build main + renderer
run: mkdir -p dist-electron && npx tsc -p tsconfig.node.json && npx vite build
36 changes: 36 additions & 0 deletions .github/workflows/refresh-installers.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
name: Refresh installers

# Pull the latest installer URLs and hashes from the winget manifests and
# propose them as a PR, so pinned downloads do not go stale between releases.
on:
schedule:
- cron: '17 5 * * 1'
workflow_dispatch:

permissions:
contents: write
pull-requests: write

jobs:
refresh:
runs-on: ubuntu-latest
env:
ELECTRON_SKIP_BINARY_DOWNLOAD: '1'
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: npm
- run: npm ci
- run: npm run catalog:installers
- run: node scripts/smoke.cjs
- uses: peter-evans/create-pull-request@v7
with:
branch: chore/refresh-installers
commit-message: Refresh installers.json from winget manifests
title: Refresh installers.json from winget manifests
body: |
Weekly `npm run catalog:installers`: latest installer URLs, SHA256 and switches
from cdn.winget.microsoft.com. Review version jumps and changed install types.
delete-branch: true
33 changes: 33 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Changelog

## 1.2.5

### Установка
- Ссылки на установщики больше не хранятся в каталоге вручную: `data/installers.json` генерируется из официальных манифестов winget (`npm run catalog:installers`) — актуальная версия, URL, SHA256 и ключи тихой установки.
- Перед запуском установщика сверяется SHA256 из манифеста; при несовпадении или сбое загрузки программа ставится через winget.
- Тип файла определяется по содержимому (EXE / MSI): HTML-страница вместо установщика больше не запускается. Исправлена установка Edge (MSI сохранялся как `.exe`).
- Загрузки только по HTTPS, в том числе после перенаправлений.
- Исправлены 10 неверных winget Id (HWMonitor ставил HWiNFO); генератор сверяет название пакета с каталогом.
- FileZilla и RustDesk, которых нет в winget, ставятся через Chocolatey; Teams, ImageGlass и Rufus — через winget.
- Коды MSI «нужна перезагрузка» (3010 / 1641) и коды успеха из манифестов считаются успешной установкой.

### Рекомендации
- Лента «Для вас» на главной и ранжированная вкладка «Рекомендуем» с причиной на каждой карточке («Вместе с Visual Studio Code»).
- В карточке программы — «Часто ставят вместе» и «Альтернативы» (`data/related.json`).
- Пока ничего не установлено, показывается выбор редакции.

### Безопасность
- Окно приложения работает в песочнице (`sandbox: true`), запрещены новые окна и переходы со страницы приложения.
- `openExternal` открывает только ссылки `http(s)`.
- Внешний каталог проверяется перед использованием.
- Удалён отладочный логгер, который в сборке писал файл и отправлял события на localhost.

### Разработка
- Рабочая конфигурация ESLint (typescript-eslint, react-hooks).
- CI на GitHub Actions и еженедельный PR с обновлением `installers.json`.
- `npm run build` работает в свежем клоне.
- Исходники промо-роликов в `promo/`.

## 1.2.0

Первая публичная версия: курируемый каталог, Scoop / winget / Chocolatey, очередь установок, профили, RU / EN.
41 changes: 34 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,28 +12,30 @@
|---|---|
| Платформа | Windows x64 |
| Стек | Electron · React · TypeScript · Vite |
| Версия | 1.2.0 |
| Версия | 1.2.5 |
| Дистрибутив | Portable `.exe` (~70 МБ) |

---

## Возможности

- **Курируемый каталог** — витрина с иконками, описаниями и прямыми ссылками на установщики
- **Курируемый каталог** — витрина с иконками и описаниями; ссылки на установщики не хранятся вручную, а берутся из манифестов winget
- **Все пакеты** — индекс Scoop / winget / Chocolatey на отдельной вкладке
- **Очередь установок** — один install за раз, с прогрессом
- **Избранное, профили, рекомендации** — быстрый старт наборами программ
- **Персональные рекомендации** — лента «Для вас» по установленному и избранному, «Часто ставят вместе» и «Альтернативы» в карточке программы
- **Избранное и профили** — быстрый старт наборами программ
- **RU / EN** — переключение языка в интерфейсе
- **Кастомный title bar** — без системного меню File / Edit / View
- **Очередь с отменой** — можно отменить загрузку/установку, повторить или убрать ошибку
- **Понятные ошибки** — 404, блокировка CDN/региона, сеть, таймаут (RU/EN)
- **Offline-first** — каталог работает сразу, runtime и метаданные догружаются в фоне
- **Проверка установщиков** — только HTTPS, SHA256 из манифеста winget сверяется до запуска, тип файла определяется по содержимому

## Провайдеры

| Провайдер | ID | Права | Описание |
|-----------|-----|-------|----------|
| **Каталог GetBox** | `catalog` | Не нужны | Курируемый offline-каталог + прямая загрузка installer |
| **Каталог GetBox** | `catalog` | Не нужны | Курируемый offline-каталог; установщик качается напрямую по манифесту winget, при сбое — через winget |
| **Scoop** | `scoop` | Не нужны | Изолированный Scoop в `runtime\scoop\` |
| **winget** | `winget` | Не нужны* | Системный winget / App Installer |
| **Chocolatey** | `chocolatey` | UAC 1× | Опционально: кнопка «Разрешить установку» при первом запуске |
Expand All @@ -49,7 +51,7 @@
Соберите portable-сборку или возьмите готовый артефакт из [Releases](../../releases) (если опубликованы):

```text
release/GetBox-1.2.0-portable.exe
release/GetBox-1.2.5-portable.exe
```

Runtime не упакован внутрь exe — он ставится при первом запуске в `%LOCALAPPDATA%`, поэтому файл остаётся относительно лёгким.
Expand Down Expand Up @@ -82,7 +84,7 @@ npm run electron:dev
npm run dist
```

Результат: `release/GetBox-1.2.0-portable.exe`.
Результат: `release/GetBox-1.2.5-portable.exe`.

### Скрипты

Expand All @@ -95,14 +97,39 @@ npm run dist
| `npm run prewarm` | Предзагрузка метаданных (CLI) |
| `npm test` | Проверка каталога + smoke |
| `npm run verify:catalog` | Только проверка `data/catalog.json` |
| `npm run catalog:installers` | Обновить `data/installers.json` из манифестов winget (Node 22.5+); `-- --check` только проверяет |
| `npm run lint` | ESLint |

### Откуда берутся установщики

В `data/catalog.json` только витрина: название, описание, категория, иконка. Как ставить программу, решает `data/installers.json`, сгенерированный `npm run catalog:installers` из официального индекса winget (`cdn.winget.microsoft.com`, тот же источник, что у клиента winget):

- **прямая загрузка** (113 программ) — URL, SHA256, тип и ключи тихой установки из манифеста. GetBox качает только по HTTPS, сверяет SHA256 и лишь потом запускает; при любом сбое ставит через winget;
- **только winget** — у программы есть лишь MSIX / portable-сборка (Teams, ImageGlass, Rufus);
- **другой менеджер** — записи вида `{ "provider": "chocolatey", "packageId": "filezilla" }` для программ, которых нет в winget. Их скрипт не трогает.

Связь «программа → winget Id» — в `data/winget-map.json`. Скрипт сверяет название пакета с каталогом и не даст подставить чужую программу из-за опечатки в Id.

Добавили программу: допишите её в `catalog.json` и `winget-overrides.json`, затем `npm run winget:map` и `npm run catalog:installers`.

Раз в неделю workflow `refresh-installers.yml` запускает этот скрипт и открывает PR с новыми версиями. Чтобы он мог создавать PR, в настройках репозитория включите *Settings → Actions → General → Allow GitHub Actions to create and approve pull requests*.

### Рекомендации

`src/recommend.ts` ранжирует программы каталога по тому, что у пользователя установлено и в избранном:

- **связки** из `data/related.json` и профили — «ставят вместе с …»;
- **альтернативы** — если браузер или менеджер паролей уже есть, остальные из группы опускаются в ленте;
- доля установленного по категориям и выбор редакции (`picks.json`, `recommended`).

Пока у пользователя ничего нет, лента показывает выбор редакции. В карточке программы — блоки «Часто ставят вместе» и «Альтернативы».

## Структура репозитория

```text
electron/ Main process, провайдеры, bootstrap, IPC, очередь установок
src/ React UI (витрина, очередь, настройки, i18n)
data/ Каталог, категории, профили, иконки, logo.svg
data/ Каталог, installers.json, related.json, категории, профили, иконки
scripts/ Иконки приложения, verify-catalog, smoke
release/ Артефакты electron-builder (в git обычно не коммитятся)
```
Expand Down
Loading
Loading