Add CI quality gate
This commit is contained in:
@@ -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
|
||||
|
||||
1
AGENT.md
1
AGENT.md
@@ -13,5 +13,6 @@
|
||||
|
||||
- Не запускай `cargo run`, `cargo build`, `cargo test`, `cargo check` без прямой команды пользователя.
|
||||
- Не коммить изменения, пока пользователь не попросит.
|
||||
- Если пользователь попросил тесты/коммит/план до конца, используй quality gate из [DEVELOPMENT.md](DEVELOPMENT.md).
|
||||
- После функциональной правки дай короткий ручной сценарий проверки.
|
||||
- Обновляй [CONTEXT.md](CONTEXT.md), только если изменились статус, риск, архитектурное решение или следующий шаг.
|
||||
|
||||
@@ -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
|
||||
|
||||
- Делай одну логическую правку за раз.
|
||||
|
||||
@@ -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));
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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!(
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user