Skip to content
Merged
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
4 changes: 2 additions & 2 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,12 @@ jobs:
- name: Checkout
uses: actions/checkout@v4
- name: Install uv
uses: astral-sh/setup-uv@v4
uses: astral-sh/setup-uv@v5

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Consider using a more specific version pin for the astral-sh/setup-uv action to avoid unexpected breakages due to future updates.

uses: astral-sh/setup-uv@v5.0.0

with:
enable-cache: true
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version-file: .python-version
- name: Test
run: uv run invoke test
run: uv run just test
4 changes: 2 additions & 2 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
# https://pre-commit.com/hooks.html

default_language_version:
python: python3.12
python: python3.13
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v5.0.0
rev: 'v5.0.0'
hooks:
- id: check-added-large-files
- id: check-case-conflict
Expand Down
2 changes: 1 addition & 1 deletion .python-version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
3.12
3.13
17 changes: 0 additions & 17 deletions CHANGELOG.md

This file was deleted.

29 changes: 16 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ The template provides a robust foundation for building, testing, packaging, and

This [Cookiecutter](https://cookiecutter.readthedocs.io/) is designed to be a common ground for diverse MLOps environments. Whether you're working with [Kubernetes](https://www.kubeflow.org/), [Vertex AI](https://cloud.google.com/vertex-ai), [Databricks](https://www.databricks.com/), [Azure ML](https://azure.microsoft.com/en-us/products/machine-learning), or [AWS SageMaker](https://aws.amazon.com/sagemaker/), the core principles of using Python packages and Docker images remain consistent.

This template equips you with the essentials for creating, testing, and packaging your AI/ML code, providing a solid base for integration into your chosen MLOps platform. To fully leverage its capabilities within a specific environment, you might need to combine it with external tools like [Airflow](https://airflow.apache.org/) for orchestration or platform-specific SDKs for deployment.
This template equips you with the essentials for creating, testing, and packaging your AI/ML code, providing a solid base for [integration into your chosen MLOps platform](https://fmind.medium.com/stop-building-rigid-ai-ml-pipelines-embrace-reusable-components-for-flexible-mlops-6e165d837110). To fully leverage its capabilities within a specific environment, you might need to combine it with external tools like [Airflow](https://airflow.apache.org/) for orchestration or platform-specific SDKs for deployment.

You have the freedom to structure your `src/` and `tests/` directories according to your preferences. Alternatively, you can draw inspiration from the structure used in the [MLOps Python Package](https://github.com/fmind/mlops-python-package) project for a ready-made implementation.

Expand Down Expand Up @@ -50,8 +50,8 @@ You'll be prompted for the following variables:
- `license`: The license for your project.
- `version`: The initial version of your project.
- `description`: A brief description of your project.
- `python_version`: The Python version to use (e.g., 3.12).
- `mlflow_version`: The MLflow version to use (e.g., 2.19.0).
- `python_version`: The Python version to use (e.g., 3.13).
- `mlflow_version`: The MLflow version to use (e.g., 2.20.3).

2. **Initialize a git repository:**

Expand All @@ -78,30 +78,33 @@ git init

Use the provided Invoke tasks to manage your development workflow:

- `invoke installs`: Install dependencies and pre-commit hooks.
- `invoke formats`: Format your code.
- `invoke checks`: Run code quality, type, security, and test checks.
- `invoke docs`: Generate API documentation.
- `invoke packages`: Build your Python package.
- `invoke projects`: Run MLflow projects.
- `invoke containers`: Build and run your Docker image.
- `uv run just check`: Run code quality, type, security, and test checks.
- `uv run just clean`: Clean up generated files.
- `uv run just commit`: Commit changes to your repository.
- `uv run just doc`: Generate API documentation.
- `uv run just docker`: Build and run your Docker image.
- `uv run just format`: Format your code with Ruff.
- `uv run just install`: Install dependencies, pre-commit hooks, and GitHub rulesets.
- `uv run just mlflow`: Start an Mlflow server.
- `uv run just package`: Build your Python package.
- `uv run just project`: Run the project in the CLI.

## Example Usage

### Running an MLflow Project
### Running the Project Script

After installing dependencies and setting up MLflow:

```bash
invoke projects
uv run just project
```

This will execute the job with the configuration file in your `confs` folder.

### Building and Running Your Docker Image

```bash
invoke containers
invoke docker
```

This builds a Docker image based on your [`Dockerfile`](https://github.com/fmind/cookiecutter-mlops-package/blob/main/%7B%7Bcookiecutter.repository%7D%7D/Dockerfile) and runs it. The `CMD` in the Dockerfile executes your package with the `--help` flag.
Expand Down
1 change: 0 additions & 1 deletion cookiecutter-mlops-package.code-workspace
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
},
"extensions": {
"recommendations": [
"dchanco.vsc-invoke",
"ms-python.python"
]
}
Expand Down
4 changes: 2 additions & 2 deletions cookiecutter.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
"license": "MIT",
"version": "0.1.0",
"description": "TODO",
"python_version": "3.12",
"mlflow_version": "2.19.0",
"python_version": "3.13",
"mlflow_version": "2.20.3",
"__prompts__": {
"user": "GitHub User",
"name": "Project Name",
Expand Down
4 changes: 0 additions & 4 deletions invoke.yaml

This file was deleted.

33 changes: 33 additions & 0 deletions justfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# https://just.systems/man/en/

# REQUIRES

find := require("find")
rm := require("rm")
uv := require("uv")

# DEFAULTS

# display help information
default:
@just --list

# TASKS

# clean the project
clean:
rm -rf .venv/
rm -rf .mypy_cache/
rm -rf .pytest_cache/

# install the project
install:
uv sync --all-groups

# setup the project hooks
hooks:
uv run pre-commit install

# run the project unit tests
test:
uv run pytest tests/
8 changes: 4 additions & 4 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,23 @@

[project]
name = "cookiecutter-mlops-package"
version = "3.0.0"
version = "4.1.0"
description = "Build and deploy Python packages and Docker images for MLOps projects."
authors = [{ name = "Médéric HURIER", email = "github@fmind.dev" }]
readme = "README.md"
requires-python = ">=3.12"
requires-python = ">=3.13"
license = { file = "LICENSE.txt" }

# DEPENDENCIES

[dependency-groups]
dev = [
"commitizen>=4.1.0",
"invoke>=2.2.0",
"pre-commit>=4.0.1",
"pytest>=8.3.4",
"pytest-cookies>=0.7.0",
"pytest-shell-utilities>=1.9.7",
"pytest>=8.3.4",
"rust-just>=1.39.0",
]

# TOOLS
Expand Down
36 changes: 0 additions & 36 deletions tasks.py

This file was deleted.

26 changes: 13 additions & 13 deletions tests/test_cookiecutter.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,15 @@

COMMANDS = [
"git init",
"uv run invoke cleans.reset",
"uv run invoke installs",
"uv run invoke formats",
"uv run invoke checks",
"uv run invoke docs",
"uv run invoke projects",
"uv run invoke packages",
"uv run invoke containers",
"uv run invoke mlflow.doctor",
"uv run just clean",
"uv run just install",
"uv run just format",
"uv run just check",
"uv run just doc",
"uv run just project",
"uv run just package",
"uv run just docker",
"uv run just mlflow-doctor",
]

# %% TESTS
Expand All @@ -26,14 +26,14 @@
def test_project_generation(cookies: Cookies) -> None:
"""Test the generation of the project."""
# given
context = {
context = {
"user": "tester",
"name": "MLOps 123",
"license": "apache-2",
"version": "1.0.0",
"description": "A test project.",
"python_version": "3.12",
"mlflow_version": "2.19.0",
"python_version": "3.13",
"mlflow_version": "2.20.3",
}
repository = context['name'].lower().replace(' ', '-')
package = repository.replace('-', '_')
Expand All @@ -48,8 +48,8 @@ def test_project_generation(cookies: Cookies) -> None:
assert result.context == {
"user": context['user'],
"name": context['name'],
"repository": repository,
"package": package,
"repository": repository,
"license": context['license'],
"version": context['version'],
"description": context['description'],
Expand Down
Loading