Add CI quality gate

This commit is contained in:
Mikhail Kilin
2026-05-17 18:55:36 +03:00
parent 2d4c1906d5
commit 51e9cf5c10
13 changed files with 50 additions and 60 deletions

View File

@@ -8,6 +8,14 @@ steps:
- rustup component add rustfmt
- cargo fmt -- --check
- name: check
image: rust:latest
environment:
CARGO_HOME: /tmp/cargo
commands:
- apt-get update -qq && apt-get install -y -qq pkg-config libssl-dev libdbus-1-dev zlib1g-dev > /dev/null 2>&1
- cargo check --all-targets --all-features
- name: clippy
image: rust:latest
environment:
@@ -15,7 +23,7 @@ steps:
commands:
- apt-get update -qq && apt-get install -y -qq pkg-config libssl-dev libdbus-1-dev zlib1g-dev > /dev/null 2>&1
- rustup component add clippy
- cargo clippy -- -D warnings
- cargo clippy --all-targets --all-features -- -D warnings
- name: test
image: rust:latest
@@ -23,4 +31,4 @@ steps:
CARGO_HOME: /tmp/cargo
commands:
- apt-get update -qq && apt-get install -y -qq pkg-config libssl-dev libdbus-1-dev zlib1g-dev > /dev/null 2>&1
- cargo test
- cargo test --all-features

View File

@@ -13,5 +13,6 @@
- Не запускай `cargo run`, `cargo build`, `cargo test`, `cargo check` без прямой команды пользователя.
- Не коммить изменения, пока пользователь не попросит.
- Если пользователь попросил тесты/коммит/план до конца, используй quality gate из [DEVELOPMENT.md](DEVELOPMENT.md).
- После функциональной правки дай короткий ручной сценарий проверки.
- Обновляй [CONTEXT.md](CONTEXT.md), только если изменились статус, риск, архитектурное решение или следующий шаг.

View File

@@ -21,6 +21,20 @@ cargo check
В финальном ответе после изменения укажи, какие cargo-команды не запускались, и дай минимальную ручную проверку.
## Quality Gate
Если пользователь прямо попросил проверить, закоммитить или выполнить план с тестами, используй тот же набор проверок, что и CI:
```bash
cargo fmt -- --check
cargo check --all-targets --all-features
cargo clippy --all-targets --all-features -- -D warnings
cargo test --all-features
git diff --check
```
Перед коммитом не оставляй `*.snap.new` файлы.
## Scope
- Делай одну логическую правку за раз.

View File

@@ -43,9 +43,7 @@ fn benchmark_format_simple_text(c: &mut Criterion) {
let entities = vec![];
c.bench_function("format_simple_text", |b| {
b.iter(|| {
format_text_with_entities(black_box(&text), black_box(&entities), Color::White)
});
b.iter(|| format_text_with_entities(black_box(&text), black_box(&entities), Color::White));
});
}
@@ -53,9 +51,7 @@ fn benchmark_format_markdown_text(c: &mut Criterion) {
let (text, entities) = create_text_with_entities();
c.bench_function("format_markdown_text", |b| {
b.iter(|| {
format_text_with_entities(black_box(&text), black_box(&entities), Color::White)
});
b.iter(|| format_text_with_entities(black_box(&text), black_box(&entities), Color::White));
});
}
@@ -79,9 +75,7 @@ fn benchmark_format_long_text(c: &mut Criterion) {
}
c.bench_function("format_long_text_with_100_entities", |b| {
b.iter(|| {
format_text_with_entities(black_box(&text), black_box(&entities), Color::White)
});
b.iter(|| format_text_with_entities(black_box(&text), black_box(&entities), Color::White));
});
}

View File

@@ -216,11 +216,11 @@ Target files:
Steps:
- [ ] Add CI steps for `cargo check --all-targets --all-features`.
- [ ] Add CI steps for `cargo clippy --all-targets --all-features -- -D warnings`.
- [ ] Add CI steps for `cargo test --all-features`.
- [ ] Document the same commands in `DEVELOPMENT.md` or `AGENT.md`.
- [ ] Keep CI commands aligned with the commands used by agents and humans locally.
- [x] Add CI steps for `cargo check --all-targets --all-features`.
- [x] Add CI steps for `cargo clippy --all-targets --all-features -- -D warnings`.
- [x] Add CI steps for `cargo test --all-features`.
- [x] Document the same commands in `DEVELOPMENT.md` or `AGENT.md`.
- [x] Keep CI commands aligned with the commands used by agents and humans locally.
Acceptance criteria:
@@ -231,13 +231,13 @@ Acceptance criteria:
Before considering the refactor layer complete:
- [ ] `cargo check --all-targets --all-features` passes.
- [ ] `cargo clippy --all-targets --all-features -- -D warnings` passes.
- [ ] `cargo test --all-features` passes.
- [ ] `git diff --check` passes.
- [ ] No unexpected `*.snap.new` files remain.
- [ ] `rg -n "current_chat_messages_mut|chats_mut|folders_mut|pending_user_ids_mut|user_cache_mut" src/tdlib` shows only intentionally contained internal access.
- [ ] `rg -n "unwrap\\(|expect\\(|panic!\\(" src` has no risky production UI or TDLib data-path panics left.
- [x] `cargo check --all-targets --all-features` passes.
- [x] `cargo clippy --all-targets --all-features -- -D warnings` passes.
- [x] `cargo test --all-features` passes.
- [x] `git diff --check` passes.
- [x] No unexpected `*.snap.new` files remain.
- [x] `rg -n "current_chat_messages_mut|chats_mut|folders_mut|pending_user_ids_mut|user_cache_mut" src/tdlib` shows only intentionally contained internal access.
- [x] `rg -n "unwrap\\(|expect\\(|panic!\\(" src` has no risky production UI or TDLib data-path panics left.
## Recommended Commit Order

View File

@@ -33,17 +33,12 @@ pub fn acquire_lock(account_name: &str) -> Result<File, String> {
// Ensure parent directory exists
if let Some(parent) = lock_path.parent() {
fs::create_dir_all(parent).map_err(|e| {
format!(
"Не удалось создать директорию для lock-файла: {}",
e
)
})?;
fs::create_dir_all(parent)
.map_err(|e| format!("Не удалось создать директорию для lock-файла: {}", e))?;
}
let file = File::create(&lock_path).map_err(|e| {
format!("Не удалось создать lock-файл {}: {}", lock_path.display(), e)
})?;
let file = File::create(&lock_path)
.map_err(|e| format!("Не удалось создать lock-файл {}: {}", lock_path.display(), e))?;
file.try_lock_exclusive().map_err(|_| {
format!(

View File

@@ -74,4 +74,3 @@ pub async fn select_folder<T: TdClientTrait>(app: &mut App<T>, folder_idx: usize
app.chat_list_state.select(Some(0));
}
}

View File

@@ -21,10 +21,7 @@ pub mod modal;
pub mod profile;
pub mod search;
pub use chat_loader::{
process_chat_init_events,
process_pending_chat_init,
};
pub use chat_loader::{process_chat_init_events, process_pending_chat_init};
pub use clipboard::*;
pub use global::*;
pub use profile::get_available_actions_count;

View File

@@ -56,12 +56,7 @@ pub fn render<T: TdClientTrait>(f: &mut Frame, area: Rect, app: &App<T>) {
if idx > 0 {
lines.push(Line::from(""));
}
lines.extend(render_message_item(
msg,
idx == selected_index,
content_width,
3,
));
lines.extend(render_message_item(msg, idx == selected_index, content_width, 3));
}
if lines.is_empty() {

View File

@@ -80,12 +80,7 @@ pub fn render<T: TdClientTrait>(f: &mut Frame, area: Rect, app: &App<T>) {
if idx > 0 {
lines.push(Line::from(""));
}
lines.extend(render_message_item(
msg,
idx == selected_index,
content_width,
2,
));
lines.extend(render_message_item(msg, idx == selected_index, content_width, 2));
}
}

View File

@@ -1,6 +1,6 @@
use chrono::{DateTime, Local, NaiveDate, Utc};
#[cfg(test)]
use chrono::FixedOffset;
use chrono::{DateTime, Local, NaiveDate, Utc};
use std::time::{SystemTime, UNIX_EPOCH};
pub trait LocalTimeSource {

View File

@@ -56,7 +56,6 @@ fn snapshot_chat_with_unread_count() {
#[test]
fn test_incoming_message_shows_unread_badge() {
// Создаём чат БЕЗ непрочитанных сообщений
let chat = TestChatBuilder::new("Friend", 999)
.unread_count(0)
@@ -485,7 +484,6 @@ fn snapshot_chat_search_mode() {
#[test]
fn snapshot_chat_with_online_status() {
let chat = TestChatBuilder::new("Alice", 123)
.last_message("Hey there!")
.build();

View File

@@ -144,19 +144,13 @@ impl TestAppBuilder {
/// Добавить сообщение для чата
pub fn with_message(mut self, chat_id: i64, message: MessageInfo) -> Self {
self.messages
.entry(chat_id)
.or_default()
.push(message);
self.messages.entry(chat_id).or_default().push(message);
self
}
/// Добавить несколько сообщений для чата
pub fn with_messages(mut self, chat_id: i64, messages: Vec<MessageInfo>) -> Self {
self.messages
.entry(chat_id)
.or_default()
.extend(messages);
self.messages.entry(chat_id).or_default().extend(messages);
self
}