Skip to content
Open
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
39 changes: 39 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
name: CI

on:
pull_request:
branches:
- main

permissions:
contents: read

jobs:
test:
runs-on: ubuntu-latest

steps:
- name: Checkout repository
uses: actions/checkout@v6

- name: Set up Python
uses: actions/setup-python@v7
with:
python-version: "3.13"
cache: pip
cache-dependency-path: ПетрухинОИ/requirements.txt

- name: Install dependencies
working-directory: ./ПетрухинОИ
run: |
python -m pip install --upgrade pip
python -m pip install -r requirements.txt
python -m pip install -e .

- name: Build project
working-directory: ./ПетрухинОИ
run: python -m build

- name: Run tests
working-directory: ./ПетрухинОИ
run: pytest -v
6 changes: 6 additions & 0 deletions ПетрухинОИ/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
.git
.venv
__pycache__
.pytest_cache
dist
build
12 changes: 12 additions & 0 deletions ПетрухинОИ/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
__pycache__/
*.py[cod]
.pytest_cache/
.venv/
venv/
build/
dist/
*.egg-info/
.idea/
.vscode/
.DS_Store
.env
196 changes: 196 additions & 0 deletions ПетрухинОИ/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,196 @@
# Лабораторная работа №106

## Continuous Integration (CI)

**Выполнил:** Олег Петрухин

## Цель

Настроить автоматическую проверку изменений при Pull Request в ветку `main`.

## Проект

Сделан небольшой Python-проект для анализа текста. Программа считает количество символов, слов и уникальных слов, а также определяет самые частые слова.

Для тестирования используется `pytest`.

## CI

В качестве CI используется **GitHub Actions**.

Workflow находится здесь:

```text
.github/workflows/ci.yml
```

В репозитории workflow должен находиться именно в корневом `.github/workflows`, иначе GitHub Actions его не запустит.

Pipeline запускается при Pull Request в `main` и выполняется по шагам:

```text
Checkout
↓
Python
↓
Установка зависимостей
↓
Build
↓
Tests
```

В workflow используются `actions/checkout@v6` и `actions/setup-python@v7`.

## Локальная проверка

Нужны Python 3.11+ и Git.

Проверка:

```bash
python --version
git --version
```

Создание окружения:

### Windows

```powershell
python -m venv .venv
.venv\\Scripts\\activate
```

### Linux/macOS

```bash
python3 -m venv .venv
source .venv/bin/activate
```

Установка зависимостей:

```bash
pip install -r requirements.txt
```

Сборка:

```bash
python -m build
```

Тесты:

```bash
pytest -v
```

## Проверка CI

После создания Pull Request открыть в GitHub:

```text
Actions → CI
```

Для успешного запуска нужен зелёный статус. На скриншоте желательно показать название workflow, Pull Request и шаги установки зависимостей, сборки и тестов.

### Успешный запуск

Сначала оставить код без ошибок, отправить его в ветку PR и дождаться завершения workflow.

**Сюда вставить реальный скриншот успешного запуска GitHub Actions.**

## Проверка ошибки

Чтобы показать работу CI при проблеме, временно изменить в `src/text_analyzer/analyzer.py`:

```python
"words": len(words),
```

на:

```python
"words": len(words) + 1,
```

После этого:

```bash
git add ПетрухинОИ/
git commit -m "Проверка падения тестов"
git push
```

Новый запуск Actions должен завершиться ошибкой на шаге `Run tests`.

**Сюда вставить реальный скриншот failed pipeline.**

После скриншота вернуть правильный код:

```python
"words": len(words),
```

И выполнить:

```bash
git add ПетрухинОИ/
git commit -m "Исправление тестов"
git push
```

Финальная версия PR должна проходить тесты.

## Git и Pull Request

Если используется fork:

```bash
git clone https://github.com/ВАШ_ЛОГИН/Practice106.git
cd Practice106
git checkout -b practice106-petrukhin-oi
```

После копирования проекта:

```bash
git add ПетрухинОИ/
git add .github/workflows/ci.yml
git commit -m "Лабораторная работа №106"
git push -u origin practice106-petrukhin-oi
```

Pull Request создаётся из:

```text
ВАШ_FORK/Practice106
practice106-petrukhin-oi
```

в:

```text
SoftwareEngineering2026/Practice106
main
```

## Вывод

В ходе работы был настроен CI-процесс на GitHub Actions. При Pull Request workflow устанавливает зависимости, собирает проект и запускает тесты. Отдельно проверяется сценарий с ошибкой в коде: тесты перестают проходить, и pipeline завершается с ошибкой. После исправления кода проверка снова проходит успешно.

## Проверка требований

| Требование | Реализация |
|---|---|
| GitHub Actions | `.github/workflows/ci.yml` |
| Pull Request → `main` | `on: pull_request` |
| Установка зависимостей | `pip install -r requirements.txt` |
| Сборка | `python -m build` |
| Тесты | `pytest -v` |
| Ошибочный pipeline | временная ошибка в коде |
| Каталог сдачи | `ПетрухинОИ/` |
| README | `ПетрухинОИ/README.md` |
15 changes: 15 additions & 0 deletions ПетрухинОИ/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
[build-system]
requires = ["setuptools>=68", "wheel"]
build-backend = "setuptools.build_meta"

[project]
name = "petrukhin-text-analyzer"
version = "1.0.0"
description = "Небольшой учебный проект для демонстрации Continuous Integration"
requires-python = ">=3.11"
authors = [
{name = "Олег Петрухин"}
]

[tool.setuptools.packages.find]
where = ["src"]
2 changes: 2 additions & 0 deletions ПетрухинОИ/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
pytest>=8,<9
build>=1,<2
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added ПетрухинОИ/screenshots/ci-failed.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added ПетрухинОИ/screenshots/ci-success.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions ПетрухинОИ/src/text_analyzer/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from .analyzer import analyze_text, normalize_text

__all__ = ["analyze_text", "normalize_text"]
25 changes: 25 additions & 0 deletions ПетрухинОИ/src/text_analyzer/analyzer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import re
from collections import Counter


def normalize_text(text: str) -> str:
if not isinstance(text, str):
raise TypeError("text должен быть строкой")
return text.strip()


def analyze_text(text: str) -> dict:
text = normalize_text(text)

if not text:
raise ValueError("text не должен быть пустым")

words = re.findall(r"[A-Za-zА-Яа-яЁё0-9]+", text.lower())
counter = Counter(words)

return {
"characters": len(text),
"words": len(words),
"unique_words": len(counter),
"top_words": counter.most_common(5),
}
33 changes: 33 additions & 0 deletions ПетрухинОИ/tests/test_analyzer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import pytest

from text_analyzer import analyze_text, normalize_text


def test_normalize_text():
assert normalize_text(" hello ") == "hello"


def test_analyze_text_basic():
result = analyze_text("Hello world hello")

assert result["characters"] == 17
assert result["words"] == 3
assert result["unique_words"] == 2
assert result["top_words"][0] == ("hello", 2)


def test_analyze_text_handles_punctuation():
result = analyze_text("Hello, hello! Python.")

assert result["words"] == 3
assert result["unique_words"] == 2


def test_analyze_text_empty():
with pytest.raises(ValueError):
analyze_text("")


def test_normalize_text_wrong_type():
with pytest.raises(TypeError):
normalize_text(123)