← Оглавление

0.4 Застава

Знать команды - это одно. Помнить о них каждый раз - совсем другое. У опытного мастера не бывает дня без проверки: не потому что он бдителен, а потому что проверка давно стала частью движения. Ученик пока делает это усилием воли. Усилие воли известно своей ненадёжностью.

Что нужно

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

Нужен ещё один документ - описание того, как вообще попасть в мастерскую. Новый разработчик, клонировавший репозиторий, должен уметь запустить tq без вопросов.

Ритуал

Создай Makefile в корне проекта - рядом с Cargo.toml:

# ==================================================================================== #
# HELPERS
# ==================================================================================== #

## help: print this help message
.PHONY: help
help:
	@echo 'Usage:'
	@sed -n 's/^##//p' ${MAKEFILE_LIST} | column -t -s ':' | sed -e 's/^/ /'

# ==================================================================================== #
# DEVELOPMENT
# ==================================================================================== #

## run: run tq
.PHONY: run
run:
	@cargo run

## build: build debug binary
.PHONY: build
build:
	@cargo build

## check: cargo check + clippy
.PHONY: check
check:
	@cargo check && cargo clippy

## fmt: format code
.PHONY: fmt
fmt:
	@cargo fmt

## test: run tests
.PHONY: test
test:
	@cargo test

# ==================================================================================== #
# QUALITY CONTROL
# ==================================================================================== #

## ci: full check - format, linting and tests
.PHONY: ci
ci:
	@cargo fmt --check && cargo clippy -- -D warnings && cargo test

# ==================================================================================== #
# BUILD
# ==================================================================================== #

## clean: remove build artifacts
.PHONY: clean
clean:
	@cargo clean

Важно: отступы в Makefile - строго символ табуляции. Пробелы вместо табуляции дадут ошибку.

make ci - застава. Именно эта команда решает, закончена ли работа:

make ci
   Compiling tq v0.1.0 (.../tq)
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.38s
     Running unittests src/main.rs (target/debug/deps/tq-...)

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

Тестов пока нет - это изменится к концу первого этапа. make ci не возражает против пустого набора тестов. Он возражает против кода, который не форматирован, не проходит Clippy, или не компилируется.

Теперь README.md. Создай его рядом с Makefile:

# tq

Менеджер задач. Работа в процессе.

## Требования

- [Rust](https://rustup.rs/) - последняя стабильная версия
- `make`

## Быстрый старт

    cargo run
    # или
    make run

## Разработка

    make ci       # форматирование + clippy + тесты
    make fmt      # форматировать код
    make check    # cargo check + clippy
    make test     # тесты
    make clean    # удалить артефакты сборки

Результат

make ci проходит. Застава стоит - незавершённая работа через неё не пройдёт.

Код tq в этой главе не изменился - застава выставлена вокруг уже существующего. Для единообразия он всё же лежит в 0-the-workshop/04-the-gate/.


Lore: как работает наш Makefile

make help не читает никакого отдельного файла с описаниями - он разбирает сам Makefile. Комментарии вида ## target: описание - это не просто комментарии, это данные:

@sed -n 's/^##//p' ${MAKEFILE_LIST} | column -t -s ':' | sed -e 's/^/ /'

${MAKEFILE_LIST} - переменная Make, содержащая имена всех загруженных файлов. Обычно это просто Makefile, но если один Makefile включает другой - sed пройдёт по обоим.

Три шага:

  1. sed -n 's/^##//p' - находит строки, начинающиеся с ##, обрезает префикс и печатает их. Всё остальное игнорируется.

  2. column -t -s ':' - выравнивает вывод в колонки, разбивая по символу :. Поэтому run: run tq и ci: full check - format, linting and tests выстраиваются ровно, независимо от длины имени цели.

  3. sed -e 's/^/ /' - добавляет отступ перед каждой строкой.

.PHONY объявляет цели фиктивными: Make по умолчанию считает цель именем файла и пропускает команду, если файл с таким именем уже существует. run, build, ci - не файлы. Без .PHONY make build мог бы промолчать, обнаружив папку build/ в директории.

@ в начале команды подавляет её вывод в терминал. Без него make run напечатал бы cargo run перед запуском. С ним - только вывод самой команды.


Lore: —check и почему ci не форматирует сам

make fmt запускает cargo fmt - команду, которая исправляет файлы на месте. В make ci стоит cargo fmt --check: она только проверяет и завершается с ошибкой, если форматирование не совпадает с ожидаемым.

Разница принципиальная. Если make ci запускается автоматически - на сервере, в пайплайне - оно не должно менять файлы молча. Ошибка видна; тихое исправление - нет. В локальной работе запусти make fmt, затем снова make ci.