GitHub Actions is used in this project to run automated checks.
These checks are part of continuous integration, often shortened to CI.
Continuous integration means that important project checks run automatically when changes are pushed or proposed in a pull request.
In this guide, CI runs:
- linting,
- formatting checks,
- tests,
- distribution builds.
The goal is simple:
A pull request should not be merged if the basic project checks are failing.
Running checks locally is important.
However, local checks depend on the developer remembering to run them.
CI gives the project an additional safety net.
It helps answer questions such as:
- Does the project work on a clean machine?
- Did the tests pass outside the developer's local environment?
- Is the formatting still consistent?
- Did the pull request break the main branch expectations?
CI does not replace careful review.
It supports review by checking repetitive things automatically.
The CI workflow should run the same checks that developers run locally.
In this project, the local checks are:
uv run ruff check .
uv run ruff format --check .
uv run rumdl check .
uv run mkdocs build --strict
uv run pytest --cov=text_toolkit --cov-report=term-missing
uv run mypy
uv build --no-sourcesThe GitHub Actions workflow runs the same commands.
This is important because local development and CI should not behave like two unrelated systems.
A developer should be able to run the same checks locally before opening a pull request.
GitHub Actions workflows are stored in:
.github/workflows/
This project uses:
.github/workflows/ci.yml
The workflow is named:
name: CIThis name appears in the GitHub Actions interface and in pull request checks.
The workflow runs on:
on:
push:
branches: ["main"]
pull_request:
branches: ["main"]This means CI runs when:
- code is pushed to
main, - a pull request targets
main.
Running CI on pull requests helps catch problems before merging.
Running CI on main helps confirm that the main branch remains healthy after merges.
The workflow defines one job:
jobs:
quality:
name: Quality checks
runs-on: ubuntu-latestThe job runs on a GitHub-hosted Ubuntu runner.
This gives the project a clean environment for every CI run.
The first step checks out the repository:
- name: Checkout repository
uses: actions/checkout@v6Without this step, the workflow would not have access to the project files.
The workflow installs uv:
- name: Install uv
uses: astral-sh/setup-uv@v8.1.0This makes the uv command available in the CI environment.
The project uses uv locally, so CI should use it too.
The workflow installs Python:
- name: Set up Python
run: uv python installThe project contains a .python-version file, so uv knows which Python version should be used.
This keeps local development and CI aligned.
The workflow installs dependencies with:
- name: Install dependencies
run: uv sync --locked --group devThe --locked option tells uv to use the existing lockfile.
This is important in CI because the workflow should check the project using the dependency versions recorded in uv.lock.
The --group dev option installs development dependencies such as:
pytest,pytest-cov,mkdocs,mypy,ruff,rumdl.
These tools are needed for checks, but they are not runtime dependencies of the package.
The workflow runs Ruff linting:
- name: Run Ruff linting
run: uv run ruff check .This checks the project for selected linting issues.
Examples include:
- unused imports,
- import ordering,
- suspicious code patterns,
- syntax modernization suggestions.
The workflow checks formatting:
- name: Check formatting
run: uv run ruff format --check .This does not modify files.
It only verifies whether files are already formatted correctly.
If formatting is wrong, the command fails.
The developer can fix formatting locally with:
uv run ruff format .The workflow checks Markdown structure and consistency:
- name: Lint Markdown
run: uv run rumdl check .The command uses the [tool.rumdl] configuration in pyproject.toml. It does
not replace the pytest check for local documentation links or human review.
The workflow builds the MkDocs site with strict validation:
- name: Build documentation site
run: uv run mkdocs build --strictThe step validates navigation and rendering without publishing the generated
site. The site/ output directory remains an ignored local artifact.
Publishing is handled by the separate .github/workflows/pages.yml workflow
after relevant changes reach main. Pull requests never receive deployment
permissions. See Publishing with GitHub Pages
for the build, artifact, environment, and permission flow.
The workflow runs tests and prints a coverage report:
- name: Run tests with coverage
run: uv run pytest --cov=text_toolkit --cov-report=term-missingThis verifies the behavior of the example package while measuring statement and branch coverage. The terminal report shows missing source lines, but the project does not fail the workflow based on a coverage percentage.
At this stage, the tests check:
- whitespace normalization,
- word counting,
- character counting.
The workflow runs mypy after the tests:
- name: Run type checking
run: uv run mypyThe command reads [tool.mypy] from pyproject.toml and checks the configured
src/ and tests/ directories in strict mode.
Running the same command locally and in CI prevents type-checking results from depending on a developer remembering an extra manual step.
The workflow builds the package distributions:
- name: Build distributions
run: uv build --no-sourcesThis creates a wheel and source distribution. The command verifies that the package metadata and included files are sufficient for a standard build.
The workflow does not publish or upload the generated files.
This project currently uses one job called quality.
That is enough for the current stage.
The job is simple and readable.
Later, a larger project might split checks into separate jobs, for example:
- linting,
- type checking,
- tests,
- documentation,
- packaging.
However, splitting too early would make the workflow more complex without much benefit.
Caching can make CI faster.
However, this guide starts with a minimal workflow.
A beginner should first understand:
- what the workflow does,
- when it runs,
- how dependencies are installed,
- how checks are executed.
Caching can be added later as an optimization.
The first version should prioritize clarity.
A green CI check means that the automated checks passed.
It does not mean the pull request is automatically good.
It means the pull request passed the basic mechanical checks.
For this project, that also means the documentation site, wheel, and source distribution were built successfully.
A human review is still needed for questions such as:
- Is the change useful?
- Is the design clear?
- Is the documentation understandable?
- Is the code easy to maintain?
- Does the change fit the project direction?
CI should protect the main branch.
A good CI workflow should be:
- easy to understand,
- easy to run locally in similar form,
- strict enough to catch common mistakes,
- simple enough that beginners can read it.
The goal is not to create a complicated automation system.
The goal is to make every pull request safer.