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
30 changes: 30 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ name: CI
on:
push:
branches: [ main, dev, '**-connector', '**-connection-pull' ]
tags:
- 'v*'
pull_request:
branches: [ main, dev ]

Expand Down Expand Up @@ -44,3 +46,31 @@ jobs:

- name: Analyze code
run: flutter analyze

# Release smoke build: same tag also runs release.yml (artifacts). This job
# gates tags on a real linux release compile after tests + analyze.
build-linux-release:
name: Build Linux (release)
needs: [test, analyze]
if: startsWith(github.ref, 'refs/tags/v')
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Install Linux dependencies
run: |
sudo apt-get update
sudo apt-get install -y clang cmake ninja-build pkg-config libgtk-3-dev

- name: Setup Flutter
uses: subosito/flutter-action@v2
with:
flutter-version: '3.38.5'
channel: 'stable'
cache: true

- name: Get dependencies
run: flutter pub get

- name: Build Linux (release)
run: flutter build linux --release
98 changes: 79 additions & 19 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -1,14 +1,21 @@
# Сборка релизов и публикация в GitHub Releases.
# Запуск: создайте и запушьте тег, например v0.1.0:
# git tag v0.1.0
# git push origin v0.1.0
# Release: сборка артефактов → единая публикация с git-cliff и SHA256SUMS.
# Триггер: git tag v0.1.0 && git push origin v0.1.0
#
# Рекомендуемые коммиты: Conventional Commits (feat:, fix:, …) — см. cliff.toml

name: Release

on:
push:
tags:
- 'v*' # v0.1.0, v1.0.0, etc.
- 'v*'

permissions:
contents: write

concurrency:
group: release-${{ github.ref }}
cancel-in-progress: false

jobs:
build-windows:
Expand Down Expand Up @@ -36,16 +43,11 @@ jobs:
$dir = "build\windows\x64\runner\Release"
Compress-Archive -Path "$dir\*" -DestinationPath "Querya-Desktop-$tag-windows.zip"

- name: Create Release and upload Windows
uses: softprops/action-gh-release@v2
- uses: actions/upload-artifact@v4
with:
tag_name: ${{ github.ref_name }}
name: Release ${{ github.ref_name }}
generate_release_notes: true
files: Querya-Desktop-${{ github.ref_name }}-windows.zip
allow_updates: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
name: bundle-windows
path: Querya-Desktop-${{ github.ref_name }}-windows.zip
if-no-files-found: error

build-linux:
name: Build Linux
Expand Down Expand Up @@ -74,15 +76,73 @@ jobs:
- name: Zip Linux artifact
run: |
cd build/linux/x64/release/bundle
zip -r ../../../../../../Querya-Desktop-${{ github.ref_name }}-linux.zip .
zip -r "${GITHUB_WORKSPACE}/Querya-Desktop-${{ github.ref_name }}-linux.zip" .

- uses: actions/upload-artifact@v4
with:
name: bundle-linux
path: Querya-Desktop-${{ github.ref_name }}-linux.zip
if-no-files-found: error

publish:
name: Publish GitHub Release
needs: [build-windows, build-linux]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0

- uses: taiki-e/install-action@v2
with:
tool: git-cliff@2.11.0

- uses: actions/download-artifact@v4
with:
path: artifacts
pattern: bundle-*
merge-multiple: true

- name: Layout distribution files
run: |
set -euo pipefail
mkdir -p dist
find artifacts -name '*.zip' -exec mv -t dist/ {} +
test "$(find dist -name '*.zip' | wc -l)" -eq 2
cd dist
sha256sum *.zip | tee SHA256SUMS.txt

- name: Generate changelog (git-cliff + GitHub API)
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITHUB_REPO: ${{ github.repository }}
run: |
set -euo pipefail
TAG="${{ github.ref_name }}"
# Текст страницы релиза: без глобального header из cliff.toml
git-cliff --latest \
--config cliff.toml \
--strip header \
--github-token "$GITHUB_TOKEN" \
--github-repo "$GITHUB_REPO" \
-o release-body.md
# Вложение: полный фрагмент с header (удобно архивировать / копировать в docs)
git-cliff --latest \
--config cliff.toml \
--github-token "$GITHUB_TOKEN" \
--github-repo "$GITHUB_REPO" \
-o "CHANGELOG-${TAG}.md"

- name: Upload to Release (Linux)
- name: Create GitHub Release
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ github.ref_name }}
name: Release ${{ github.ref_name }}
generate_release_notes: true
files: Querya-Desktop-${{ github.ref_name }}-linux.zip
allow_updates: true
body_path: release-body.md
fail_on_unmatched_files: true
files: |
dist/*.zip
dist/SHA256SUMS.txt
CHANGELOG-${{ github.ref_name }}.md
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
84 changes: 84 additions & 0 deletions cliff.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
# git-cliff — https://git-cliff.org/docs/configuration
# Conventional Commits: https://www.conventionalcommits.org/
#
# Явный remote: SSH origin (`git@github.com:…`) без этого даёт пустые ссылки в changelog.
# Форки могут переопределить секцию или задать GITHUB_REPO при генерации.

[remote.github]
owner = "QueryaHub"
repo = "Querya-Desktop"

[changelog]
header = """
# Changelog

Release history. Commit messages should follow [Conventional Commits](https://www.conventionalcommits.org/) (`feat:`, `fix:`, `docs:`, …) so entries group correctly.

"""
body = """
{%- macro commit_url(id) -%}
https://github.com/{{ remote.github.owner }}/{{ remote.github.repo }}/commit/{{ id }}
{%- endmacro -%}

{% macro print_commit(commit) -%}
- {% if commit.scope %}**{{ commit.scope }}:** {% endif %}\
{% if commit.breaking %}[**breaking**] {% endif %}\
{{ commit.message | upper_first | trim }} — \
[`{{ commit.id | truncate(length=7, end="") }}`]({{ self::commit_url(id=commit.id) }})
{%- endmacro %}

{% if version %}
## [{{ version }}] — {{ timestamp | date(format="%Y-%m-%d") }}
{% if previous.version %}
[Compare {{ previous.version }}…{{ version }}](https://github.com/{{ remote.github.owner }}/{{ remote.github.repo }}/compare/{{ previous.version }}..{{ version }})
{% endif %}
{% else %}
## [unreleased]
{% endif %}

{% for group, commits in commits | group_by(attribute="group") %}
### {{ group }}
{% for commit in commits -%}
{{ self::print_commit(commit=commit) }}
{% endfor %}
{% endfor %}
{%- if github %}
{%- set newbies = github.contributors | filter(attribute="is_first_time", value=true) %}
{%- if newbies | length != 0 %}

### New contributors
{% for c in newbies -%}
- @{{ c.username }}{% if c.pr_number %} ([#{{ c.pr_number }}](https://github.com/{{ remote.github.owner }}/{{ remote.github.repo }}/pull/{{ c.pr_number }})){% endif %}
{% endfor %}
{%- endif %}
{%- endif %}
"""
footer = """
"""
trim = true

[git]
conventional_commits = true
# Включать и неконвенциональные коммиты (попадут в «Прочее»).
filter_unconventional = false
split_commits = false
commit_parsers = [
{ message = "^feat", group = "Features" },
{ message = "^fix", group = "Bug Fixes" },
{ message = "^doc", group = "Documentation" },
{ message = "^perf", group = "Performance" },
{ message = "^refactor", group = "Refactor" },
{ message = "^style", group = "Styling" },
{ message = "^test", group = "Tests" },
{ message = "^build", group = "Build" },
{ message = "^ci", group = "CI" },
{ message = "^chore", group = "Chore" },
{ message = "^revert", group = "Revert" },
{ message = ".*", group = "Other" },
]
protect_breaking_commits = true
filter_commits = false
tag_pattern = "v[0-9].*"
skip_tags = "beta|alpha|rc"
topo_order = false
sort_commits = "newest"
95 changes: 95 additions & 0 deletions docs/tags-and-releases.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
# Теги и релизы

Кратко: как помечать версии в Git и что при этом делает CI.

## Зачем теги

- **Версия в Git** — неизменяемая метка на коммите (`v0.2.0` всегда указывает на один и тот же снимок кода).
- **Автосборка** — при пуше тега вида `v*` запускается workflow **Release** (см. `.github/workflows/release.yml`): сборки Linux и Windows, checksums, GitHub Release с текстом из [git-cliff](https://git-cliff.org/) и вложениями.

Теги **не заменяют** обычные коммиты в `main` / `dev`: сначала коммиты попадают в нужную ветку, затем на выбранный коммит вешается тег.

## Имя тега

- Используйте префикс **`v`** и семантическую версию, например: `v0.1.0`, `v1.2.3`.
- В CI и [cliff.toml](../cliff.toml) ожидаются теги, попадающие под шаблон **`v*`** (например `v0.1.0`). Теги вроде `1.0.0` без `v` workflow **не** подхватит.
- Предрелизные суффиксы в имени тега возможны, но в `cliff.toml` для changelog **пропускаются** паттерны вроде `beta`, `alpha`, `rc` в `skip_tags` — ориентируйтесь на обычные релизные теги `v1.0.0`.

## Создать и отправить тег

Убедитесь, что нужный коммит уже в удалённом репозитории (или запушьте ветку, затем тег).

**Тег на текущий коммит:**

```bash
git checkout main # или dev — как принято у вас
git pull
git tag v0.2.0
git push origin v0.2.0
```

**Тег на конкретный коммит:**

```bash
git tag v0.2.0 abc1234
git push origin v0.2.0
```

**Удалить тег** (осторожно, если релиз уже опубликован):

```bash
git tag -d v0.2.0
git push origin :refs/tags/v0.2.0
```

На GitHub вручную: **Releases → Draft** не заменяет пуш тега; для автоматизации ориентируйтесь на `git push origin <tag>`.

## Что появится в GitHub после пуша тега

1. Запускается workflow **Release**.
2. Собираются артефакты **Windows** и **Linux** (zip).
3. Генерируется **`SHA256SUMS.txt`** для проверки архивов.
4. Формируется описание релиза и файл **`CHANGELOG-<тег>.md`** через **git-cliff** (группировка по Conventional Commits, при наличии токена — данные с GitHub API).
5. Создаётся или обновляется **GitHub Release** с телом из changelog и вложениями (zip + checksums + markdown).

Отдельно при пуше тега `v*` может выполняться **CI** из `.github/workflows/ci.yml` (тесты, анализ, при необходимости сборка Linux).

## Коммиты и changelog

Чтобы разделы релиза (Features, Bug Fixes и т.д.) выглядели аккуратно, сообщения коммитов лучше вести в стиле [Conventional Commits](https://www.conventionalcommits.org/), например:

- `feat(connections): …`
- `fix(postgres): …`
- `docs: …`

Остальные сообщения не пропадают: они попадают в группу **Other** (см. [cliff.toml](../cliff.toml)).

## Версия в приложении

Номер в **Git-теге** и поле **`version`** в [pubspec.yaml](../pubspec.yaml) — разные сущности. Для согласованности перед релизом обычно обновляют `pubspec.yaml`, коммитят, затем вешают тег на этот коммит (или наоборот — по договорённости в команде).

## Где смотреть настройки

| Файл | Назначение |
|------|------------|
| [.github/workflows/release.yml](../.github/workflows/release.yml) | Триггер по тегам `v*`, сборка, релиз |
| [.github/workflows/ci.yml](../.github/workflows/ci.yml) | CI при пуше веток и тегов `v*` |
| [cliff.toml](../cliff.toml) | Правила changelog (группы, теги, remote) |

## Локальная проверка changelog (опционально)

Установите [git-cliff](https://git-cliff.org/docs/installation), в корне репозитория:

```bash
git-cliff --latest --strip header
```

Для расширенного контекста (PR, контрибьюторы) нужен токен GitHub:

```bash
export GITHUB_TOKEN=ghp_...
export GITHUB_REPO=QueryaHub/Querya-Desktop
git-cliff --latest --github-token "$GITHUB_TOKEN" --github-repo "$GITHUB_REPO" --strip header
```

(В форке подставьте свой `owner/repo`.)
Loading