Clone and CI Quickstart

This quickstart is for people who already have a Python project on GitHub and want to run it locally or configure a simple CI workflow.

It focuses on the practical path:

clone repository → sync environment → run checks → configure CI

For a quick guide to creating a new project from scratch, see:

docs/quickstart_uv.md

What this quickstart covers

This chapter shows how to:

  • clone a project from GitHub,
  • install uv,
  • synchronize the local environment,
  • run tests,
  • run Ruff,
  • understand uv sync,
  • understand uv sync --locked,
  • configure a basic GitHub Actions workflow.

1. Clone the repository

Clone the project:

git clone https://github.com/your-username/your-project.git
cd your-project

For this guide, the repository is:

git clone https://github.com/michalmaj/modern-python-project-guide.git
cd modern-python-project-guide

Expected result

You should now be inside the cloned repository directory.

Check the current repository state:

git status

A clean clone should usually show:

working tree clean

2. Install uv

If uv is not installed yet, install it first.

macOS and Linux

curl -LsSf https://astral.sh/uv/install.sh | sh

Windows PowerShell

powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"

Check the installation:

uv --version

3. Check important project files

A project managed with uv usually contains:

pyproject.toml
uv.lock
.python-version

pyproject.toml

This file describes the project.

It may contain:

  • project metadata,
  • runtime dependencies,
  • development dependencies,
  • tool configuration.

uv.lock

This file stores exact resolved dependency versions.

It should be committed to Git.

.python-version

This file stores the Python version used by the project.

It helps uv install and use the correct Python version.

Expected result

A project managed with uv should usually contain:

pyproject.toml
uv.lock
.python-version

If one of these files is missing, check the project documentation.

Not every repository uses the same setup, but this guide relies on these files.

This repository also contains mkdocs.yml and docs/index.md for its optional documentation-site view.

4. Sync the local environment

After cloning a project, run:

uv sync

Expected result

The local environment should be created or updated.

You should usually see:

.venv/

This directory is local to your machine.

It should stay ignored by Git.

This creates or updates the local virtual environment.

The environment is usually created in:

.venv/

Do not commit .venv/ to Git.

5. What does uv sync do?

uv sync synchronizes the local environment with the project.

It uses:

pyproject.toml
uv.lock

In practice, this means:

  • creating .venv/ if needed,
  • installing the current project in editable mode,
  • installing project dependencies,
  • installing development dependencies included by default,
  • making the local environment match the project configuration.

For most local development work, this is the command to run after cloning or pulling new changes:

uv sync

Install the repository's fast commit hooks once in this clone:

uv run pre-commit install

The hooks check changed files before Git creates a commit. They do not replace the complete checks below or the CI workflow.

6. Run local checks

Run tests with coverage:

uv run pytest --cov=text_toolkit --cov-report=term-missing

Run Ruff linting:

uv run ruff check .

Check formatting:

uv run ruff format --check .

Lint Markdown:

uv run rumdl check .

Build the documentation site:

uv run mkdocs build --strict

Run type checking:

uv run mypy

A useful local check sequence is:

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

If formatting fails, run:

uv run ruff format .

Then repeat:

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

Expected result

If the project is set up correctly:

  • Ruff linting should pass,
  • Ruff formatting check should pass,
  • Markdown linting should pass,
  • documentation site build should pass,
  • pytest and coverage reporting should pass,
  • mypy should report no issues.

If one command fails, read the error message before changing anything.

The error usually tells you what needs to be fixed.

7. When to run uv sync again

Run:

uv sync

after:

  • cloning the repository,
  • pulling changes that modify pyproject.toml,
  • pulling changes that modify uv.lock,
  • switching to a branch with different dependencies,
  • adding or removing dependencies.

If dependencies did not change, running uv sync again is usually harmless.

8. Adding a new dependency locally

Add a runtime dependency with:

uv add package-name

Example:

uv add rich

Add a development dependency with:

uv add --group dev package-name

Examples:

uv add --group dev pytest
uv add --group dev ruff

After adding a dependency, commit both:

pyproject.toml
uv.lock

9. uv sync vs uv sync --locked

Use this locally most of the time:

uv sync

Use this in this project's CI:

uv sync --locked --group dev

The difference is important.

uv sync

uv sync synchronizes the environment and may update the lockfile if needed.

This is useful during normal development.

uv sync --locked

uv sync --locked requires the existing uv.lock file to be up to date.

It should fail if the lockfile needs to be changed.

This is useful in CI because CI should not silently update project files.

CI should verify what is already committed.

10. Basic GitHub Actions workflow

Create:

.github/workflows/ci.yml

Example workflow:

name: CI

on:
  push:
    branches: ["main"]
  pull_request:
    branches: ["main"]

jobs:
  quality:
    name: Quality checks
    runs-on: ubuntu-latest

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

      - name: Install uv
        uses: astral-sh/setup-uv@v8.1.0

      - name: Set up Python
        run: uv python install

      - name: Install dependencies
        run: uv sync --locked --group dev

      - name: Run Ruff linting
        run: uv run ruff check .

      - name: Check formatting
        run: uv run ruff format --check .

      - name: Lint Markdown
        run: uv run rumdl check .

      - name: Build documentation site
        run: uv run mkdocs build --strict

      - name: Run tests with coverage
        run: uv run pytest --cov=text_toolkit --cov-report=term-missing

      - name: Run type checking
        run: uv run mypy

      - name: Build distributions
        run: uv build --no-sources

This workflow runs on:

  • pull requests targeting main,
  • pushes to main.

Expected result

After this workflow is committed and pushed to GitHub, pull requests should show a CI check.

A successful run means that GitHub was able to:

  • install uv,
  • install the requested Python version,
  • sync dependencies from the lockfile,
  • run Ruff linting,
  • check formatting,
  • run tests,
  • run type checking,
  • build a wheel and source distribution.

A green CI check does not replace review.

It only confirms that the automated checks passed.

11. Why CI uses the same commands

The CI workflow should run the same checks that developers run locally:

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-sources

This makes the workflow easier to understand.

A developer can run the same checks before opening a pull request.

12. What green CI means

A green CI check means:

  • dependencies installed successfully,
  • Ruff linting passed,
  • formatting check passed,
  • Markdown linting passed,
  • documentation site build passed,
  • tests and coverage reporting passed,
  • type checking passed,
  • package distributions built successfully.

It does not mean the pull request is automatically good.

A human review is still needed for:

  • clarity,
  • design,
  • documentation quality,
  • project direction,
  • maintainability.

13. Common clone problems

uv is not found

Check whether uv is installed:

uv --version

If the command fails, install uv and restart the terminal.

Python version is missing

Run:

uv python install

This uses the Python version requested by the project.

Tests cannot import the package

Check whether pyproject.toml contains a build system and pytest configuration similar to:

[build-system]
requires = ["uv_build>=0.12.19,<0.13"]
build-backend = "uv_build"

[tool.pytest.ini_options]
testpaths = ["tests"]

Then run:

uv sync
uv run pytest

CI fails but local checks pass

Possible reasons:

  • uncommitted local files,
  • missing changes in uv.lock,
  • different Python version,
  • platform-specific behavior,
  • stale branch.

Check:

git status
uv sync
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-sources

Quick command summary

For a freshly cloned project:

git clone https://github.com/your-username/your-project.git
cd your-project

uv sync
uv run pre-commit install

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-sources

For CI:

uv python install
uv sync --locked --group dev
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-sources

Rule of thumb

After cloning a project, run:

uv sync

Before opening a pull request, run:

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

In CI, use:

uv sync --locked --group dev

Local development may update the environment.

CI should verify the committed project state.