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.