This commit is contained in:
Dmitry 2025-11-21 10:18:15 +03:00
parent 167abca134
commit 8a42e77563
6 changed files with 71 additions and 214 deletions

View file

@ -1,203 +0,0 @@
# Исправление ошибки "Flutter directory is not a clone of the GitHub project"
**Дата**: 19 ноября 2025
**Статус**: ✅ Исправлено
## Проблема
При выполнении CI/CD workflow для web app получали ошибку:
```
Error: The Flutter directory is not a clone of the GitHub project.
The flutter tool requires Git in order to operate properly;
to install Flutter, see the instructions at:
https://flutter.dev/get-started
```
## Причина
Flutter SDK требует наличия Git для своей работы, так как:
1. Flutter проверяет целостность своего SDK через Git
2. Flutter использует Git для управления своими компонентами
3. В некоторых runner'ах Git может не быть установлен по умолчанию
## Решение
Добавлены следующие изменения во все Flutter workflow:
### 1. Полный checkout репозитория
**Было**:
```yaml
- name: Checkout code
uses: actions/checkout@v4
```
**Стало**:
```yaml
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0 # Полная история Git
```
### 2. Явная установка Git
Добавлен новый шаг перед Setup Flutter:
```yaml
- name: Install Git
run: |
sudo apt-get update
sudo apt-get install -y git
```
### 3. Включение кеширования Flutter
**Было**:
```yaml
- name: Setup Flutter
uses: subosito/flutter-action@v2
with:
flutter-version: '3.35.5'
channel: 'stable'
```
**Стало**:
```yaml
- name: Setup Flutter
uses: subosito/flutter-action@v2
with:
flutter-version: '3.35.5'
channel: 'stable'
cache: true # Включено кеширование
```
## Обновленные файлы
1. ✅ `.forgejo/workflows/ci-web.yml` - Web App CI
- Job: `test` - обновлен
- Job: `build` - обновлен
2. ✅ `.forgejo/workflows/ci-mobile.yml` - Mobile App CI
- Все jobs обновлены (3 job'а)
3. ✅ `.forgejo/workflows/code-quality.yml` - Code Quality
- Job обновлен
## Преимущества изменений
### 1. Полная история Git (fetch-depth: 0)
- Позволяет Git командам работать корректно
- Необходимо для некоторых Flutter операций
- Полезно для анализа изменений
### 2. Явная установка Git
- Гарантирует наличие Git в runner
- Избегает зависимости от базового образа
- Работает на разных платформах (GitHub Actions, Forgejo Actions)
### 3. Кеширование Flutter (cache: true)
- Ускоряет установку Flutter SDK
- Экономит время на повторных запусках
- Уменьшает нагрузку на сеть
## Проверка
После применения изменений:
1. **Commit изменения**:
```bash
git add .forgejo/workflows/
git commit -m "fix: Add Git installation for Flutter workflows"
git push origin master
```
2. **Запустить workflow вручную** через Forgejo UI:
- Перейти в Actions
- Выбрать workflow (например, Web App CI)
- Нажать "Run workflow"
3. **Проверить логи**:
- Шаг "Install Git" должен выполниться успешно
- Шаг "Setup Flutter" должен пройти без ошибок
- Шаг "Build web app" должен завершиться успешно
## Альтернативные решения
Если проблема сохраняется, можно попробовать:
### 1. Использовать Docker образ с предустановленным Flutter
```yaml
jobs:
build:
runs-on: ubuntu-latest
container:
image: ghcr.io/cirruslabs/flutter:3.35.5
```
### 2. Установить Flutter вручную
```yaml
- name: Install Flutter manually
run: |
git clone https://github.com/flutter/flutter.git -b stable
echo "$PWD/flutter/bin" >> $GITHUB_PATH
```
### 3. Использовать flutter-action с git-path
```yaml
- name: Setup Flutter
uses: subosito/flutter-action@v2
with:
flutter-version: '3.35.5'
channel: 'stable'
cache: true
git-path: /usr/bin/git
```
## Версия Flutter
Во всех workflow используется **Flutter 3.35.5 stable**, как указано в требованиях.
## Дополнительные настройки
### Если используется self-hosted runner
На self-hosted runner нужно убедиться что Git установлен:
```bash
# На сервере runner'а
ssh root@147.45.152.129
# Проверить Git
git --version
# Если не установлен
sudo apt-get update
sudo apt-get install -y git
```
### Если нужно обновить Flutter на сервере
```bash
# На сервере
cd /path/to/flutter
git fetch
git checkout stable
git pull
flutter doctor
```
## Статус
🟢 **ИСПРАВЛЕНО**
Все Flutter workflow обновлены и должны работать корректно.
---
**Примечание**: Изменения применены ко всем workflow файлам, использующим Flutter, чтобы обеспечить единообразие и избежать подобных проблем в будущем.

View file

@ -11,6 +11,8 @@ on:
- web_v2 - web_v2
- backend - backend
- common - common
schedule:
- cron: '0 */4 * * *'
jobs: jobs:
planning: planning:

View file

@ -19,8 +19,8 @@ This is a language learning application with multiple components:
## Input Sources ## Input Sources
Review these files to understand current state: Review these files to understand current state:
- `tasks.md` - Human-defined tasks and priorities - `ai_docs/agent/tasks.md` - Human-defined tasks and priorities in component directories
- `workflow_state.md` - Current development state and progress - `workflow_state.md` - Current development state and progress in component directories
- `ai_docs/agent/{component}/task_list.json` - Current task list - `ai_docs/agent/{component}/task_list.json` - Current task list
- `ai_docs/agent/{component}/agent_state.json` - Agent execution state - `ai_docs/agent/{component}/agent_state.json` - Agent execution state
- Recent commits - What has been completed recently - Recent commits - What has been completed recently
@ -62,10 +62,10 @@ Each task should have:
- **Small tasks** (1-3 hours): Single feature or bug fix - **PREFERRED SIZE** - **Small tasks** (1-3 hours): Single feature or bug fix - **PREFERRED SIZE**
- **Medium tasks** (4-5 hours): Feature with multiple files - **ACCEPTABLE, but prefer smaller** - **Medium tasks** (4-5 hours): Feature with multiple files - **ACCEPTABLE, but prefer smaller**
- **Large tasks** (6+ hours): **MUST be broken down** into smaller subtasks before adding to task list - **Large tasks** (3+ hours): **MUST be broken down** into smaller subtasks before adding to task list
**Task Decomposition Rules:** **Task Decomposition Rules:**
- If a task exceeds 6 hours, it MUST be split into multiple smaller tasks - If a task exceeds 3 hours, it MUST be split into multiple smaller tasks
- Each subtask should be independently testable and completable - Each subtask should be independently testable and completable
- Subtasks should have clear dependencies between them - Subtasks should have clear dependencies between them
- Aim for tasks that can be completed in 2-4 hours whenever possible - Aim for tasks that can be completed in 2-4 hours whenever possible
@ -170,7 +170,7 @@ When a task in one component depends on another:
- Identify dependencies between tasks - Identify dependencies between tasks
- Determine component ownership - Determine component ownership
- Estimate effort for each task - Estimate effort for each task
- **Break down large tasks** (6+ hours) into smaller subtasks before proceeding - **Break down large tasks** (3+ hours) into smaller subtasks before proceeding
### 3. Prioritization Phase ### 3. Prioritization Phase
@ -204,7 +204,7 @@ Generate `task_list.json` for each component:
"title": "Implement Subscription Service", "title": "Implement Subscription Service",
"priority": "high", "priority": "high",
"status": "pending", "status": "pending",
"estimated_hours": 6, "estimated_hours": 2,
"description": "Create SubscriptionService to handle subscription operations using HttpRepositoryV2. Include methods for fetching plans, purchasing, checking status, and cancelling subscriptions.", "description": "Create SubscriptionService to handle subscription operations using HttpRepositoryV2. Include methods for fetching plans, purchasing, checking status, and cancelling subscriptions.",
"acceptance_criteria": [ "acceptance_criteria": [
"SubscriptionService created with all CRUD methods", "SubscriptionService created with all CRUD methods",
@ -260,8 +260,8 @@ Before finalizing task list:
1. ✅ All tasks have unique IDs 1. ✅ All tasks have unique IDs
2. ✅ Dependencies are valid (tasks exist) 2. ✅ Dependencies are valid (tasks exist)
3. ✅ Priorities are balanced (not all high) 3. ✅ Priorities are balanced (not all high)
4. ✅ **All tasks are small (2-6 hours max)** - large tasks have been broken down 4. ✅ **All tasks are small (1-3 hours max)** - large tasks have been broken down
5. ✅ Estimates are reasonable (2-6 hours preferred, 6-8 hours acceptable only if cannot be split) 5. ✅ Estimates are reasonable (2-3 hours preferred, 3-5 hours acceptable only if cannot be split)
6. ✅ Acceptance criteria are specific 6. ✅ Acceptance criteria are specific
7. ✅ Files to modify are listed 7. ✅ Files to modify are listed
8. ✅ No circular dependencies 8. ✅ No circular dependencies

0
ai_docs/agent/tasks.md Normal file
View file

View file

@ -50,6 +50,9 @@ class AgentOrchestrator:
try: try:
state = self.task_manager.load_state() state = self.task_manager.load_state()
# Reset stale in_progress tasks (tasks that were left in_progress from previous runs)
self.task_manager.reset_stale_in_progress_tasks(state.current_task_id)
# Check iteration limit # Check iteration limit
if state.iteration_count >= self.config.max_iterations: if state.iteration_count >= self.config.max_iterations:
print(f"\n⏹️ Reached maximum iterations ({self.config.max_iterations})") print(f"\n⏹️ Reached maximum iterations ({self.config.max_iterations})")
@ -59,10 +62,37 @@ class AgentOrchestrator:
next_task = self.task_manager.get_next_task() next_task = self.task_manager.get_next_task()
if not next_task: if not next_task:
print("\n✅ All tasks completed!") print("\n✅ All tasks completed or no pending tasks!")
self.task_manager.reset_state()
return 0
# Trigger planning agent to generate new tasks
print("\n🎯 No tasks available, triggering planning agent...")
planning_agent = PlanningAgent(self.config)
planning_result = planning_agent.run()
if planning_result == 0:
print("\n✅ Planning agent completed successfully")
print(" New tasks have been generated. Checking for available tasks...")
# Try to get next task again after planning
next_task = self.task_manager.get_next_task()
if next_task:
print(f"\n📋 Found new task: {next_task.id} - {next_task.title}")
print(" Proceeding to execute the new task...")
# Continue with task execution (don't return, fall through to task execution)
else:
print("\n⚠️ Planning agent completed but no new tasks were generated")
print(" Agent will exit. You may need to manually create tasks.")
self.task_manager.reset_state()
return 0
else:
print("\n⚠️ Planning agent failed")
print(" Agent will exit. You may need to manually trigger planning or create tasks")
self.task_manager.reset_state()
return 0
# At this point we should have a task to execute
# Continue with task execution
print(f"\n{'='*80}") print(f"\n{'='*80}")
print(f"📋 Task: {next_task.id}") print(f"📋 Task: {next_task.id}")
print(f"📝 {next_task.title}") print(f"📝 {next_task.title}")

View file

@ -165,6 +165,7 @@ class TaskManager:
if task_id not in state.completed_tasks: if task_id not in state.completed_tasks:
state.completed_tasks.append(task_id) state.completed_tasks.append(task_id)
state.current_task_id = None state.current_task_id = None
state.status = "idle" # Reset status to allow agent to continue or finish
state.retry_count = 0 state.retry_count = 0
self.save_state(state) self.save_state(state)
@ -244,6 +245,33 @@ class TaskManager:
tasks = self.load_tasks() tasks = self.load_tasks()
return all(task.status in ["completed", "skipped"] for task in tasks) return all(task.status in ["completed", "skipped"] for task in tasks)
def reset_stale_in_progress_tasks(self, current_task_id: Optional[str] = None) -> None:
"""
Reset tasks that are stuck in 'in_progress' status.
These are tasks that were started but never completed (e.g., agent crashed).
Args:
current_task_id: ID of the task that is currently being worked on (don't reset this one)
"""
tasks = self.load_tasks()
state = self.load_state()
reset_count = 0
for task in tasks:
if task.status == "in_progress":
# Don't reset the current task if it's actually being worked on
if task.id == current_task_id and state.status == "in_progress":
continue
# Reset stale in_progress task to pending
task.status = "pending"
reset_count += 1
print(f"⚠️ Resetting stale task {task.id} from 'in_progress' to 'pending'")
if reset_count > 0:
self.save_tasks(tasks)
print(f"✅ Reset {reset_count} stale task(s) to 'pending' status")
class GlobalLock: class GlobalLock:
"""Manages global lock for shared resource access.""" """Manages global lock for shared resource access."""