Skip to content

Commit dbaadbe

Browse files
authored
Merge pull request #3 from trobz/feat/service-support
feat: add service support template files
2 parents d176c59 + 510600e commit dbaadbe

8 files changed

Lines changed: 150 additions & 7 deletions

copier.yaml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,23 @@ project_description:
2121
type: str
2222
help: Your project description
2323

24+
project_type:
25+
type: str
26+
choices:
27+
- cli
28+
- service
29+
default: cli
30+
help: Type of the project
31+
32+
service_framework:
33+
type: str
34+
choices:
35+
- fastapi
36+
- flask
37+
default: fastapi
38+
when: "{{ project_type == 'service' }}"
39+
help: Web framework to use
40+
2441
repository_namespace:
2542
type: str
2643
help: Your repository namespace

template/.gitignore

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -147,8 +147,9 @@ activemq-data/
147147
# SageMath parsed files
148148
*.sage.py
149149

150-
# Environments
151-
.env
150+
# env files (can opt-in for committing if needed)
151+
.env*
152+
!.env.example
152153
.envrc
153154
.venv
154155
env/
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,21 @@ check: ## Run code quality tools.
1313
@echo "🚀 Static type checking: Running ty"
1414
@uv run ty check
1515

16+
.PHONY: release-dry
17+
release-dry: ## Simulate the release process and show the next version
18+
@echo "🚀 Simulating release process..."
19+
@uv run semantic-release --noop version --print
20+
21+
.PHONY: release-stable
22+
release-stable: ## Prepare project for stable 1.0.0 release (disables 0.x.x versions)
23+
@echo "🚀 Preparing for stable release..."
24+
@sed -i 's/allow_zero_version = true/allow_zero_version = false/' pyproject.toml
25+
@echo "Updated pyproject.toml: allow_zero_version = false"
26+
@echo "Next steps:"
27+
@echo " 1. git add pyproject.toml"
28+
@echo " 2. git commit -m 'chore: prepare for stable 1.0.0 release'"
29+
@echo " 3. Push to main - the next feat/fix commit will trigger 1.0.0"
30+
1631
.PHONY: test
1732
test: ## Test the code with pytest
1833
@echo "🚀 Testing code: Running pytest"
@@ -35,3 +50,10 @@ help:
3550
[[print(f'\033[36m{m[0]:<20}\033[0m {m[1]}') for m in re.findall(r'^([a-zA-Z_-]+):.*?## (.*)$$', open(makefile).read(), re.M)] for makefile in ('$(MAKEFILE_LIST)').strip().split()]"
3651
3752
.DEFAULT_GOAL := help
53+
54+
{% if project_type == 'service' %}
55+
.PHONY: serve
56+
serve: ## Run the service
57+
@echo "🚀 Running service"
58+
@uv run python -m {{package_name}}.main
59+
{% endif %}

template/pyproject.toml.jinja

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "{{ project_name }}"
3-
version = "0.0.1"
3+
version = "0.0.0"
44
description = "{{ project_description }}"
55
authors = [{name = "{{ author_username }}", email = "{{ author_email }}"}]
66
requires-python = ">=3.10"
@@ -9,21 +9,34 @@ license = "AGPL-3.0"
99
license-files = ["LICENSE"]
1010

1111
dependencies = [
12-
"typer>=0.20"
12+
{%- if project_type == 'cli' %}
13+
"typer>=0.20",
14+
{%- elif project_type == 'service' %}
15+
{%- if service_framework == 'fastapi' %}
16+
"fastapi>=0.110.0",
17+
{%- elif service_framework == 'flask' %}
18+
"flask>=3.0.0",
19+
{%- endif %}
20+
"uvicorn>=0.27.0",
21+
"pydantic-settings>=2.2.0",
22+
{%- endif %}
1323
]
1424

1525
[project.urls]
1626
Repository = "https://github.com/trobz/{{project_name}}"
1727

28+
{%- if project_type == 'cli' %}
1829
[project.scripts]
1930
{{ project_name }} = "{{ package_name }}.main:app"
31+
{%- endif %}
2032

2133
[dependency-groups]
2234
dev = [
2335
"pre-commit>=2.20.0",
2436
"ty>=0.0.1a16",
2537
"ruff>=0.11.5",
2638
"pytest>=7.2.0",
39+
"python-semantic-release>=10.5.3",
2740
]
2841

2942
[tool.pytest.ini_options]
@@ -55,6 +68,18 @@ build_command = """
5568
uv build
5669
"""
5770
71+
# Commit parser - this should be at the top level
72+
commit_parser = "conventional"
73+
74+
# Allow 0.x.x versions (prevents jumping straight to 1.0.0)
75+
allow_zero_version = true
76+
77+
# Don't do major version bumps when in 0.x.x
78+
major_on_zero = false
79+
80+
# Tag format
81+
tag_format = "v{version}"
82+
5883
[tool.semantic_release.changelog]
5984
exclude_commit_patterns = [
6085
'''chore(?:\([^)]*?\))?: .+''',
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
ENVIRONMENT=local
2+
DEBUG=false
3+
4+
SERVER_HOST=0.0.0.0
5+
SERVER_PORT=8000

template/{{package_name}}/main.py

Lines changed: 0 additions & 3 deletions
This file was deleted.
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
{% if project_type == 'cli' -%}
2+
import typer
3+
4+
app = typer.Typer()
5+
6+
7+
@app.command()
8+
def hello(name: str):
9+
print(f"Hello {name}")
10+
11+
12+
if __name__ == "__main__":
13+
app()
14+
15+
{%- elif project_type == 'service' -%}
16+
{%- if service_framework == 'fastapi' -%}
17+
from fastapi import FastAPI
18+
from .settings import settings
19+
import uvicorn
20+
21+
app = FastAPI(title="{{ project_name }}")
22+
23+
24+
@app.get("/")
25+
def read_root():
26+
return {"Hello": "World", "env": settings.environment}
27+
28+
@app.get("/health")
29+
def health_check():
30+
return {"status": "ok"}
31+
32+
33+
if __name__ == "__main__":
34+
uvicorn.run(
35+
"{{ package_name }}.main:app",
36+
host=settings.server_host,
37+
port=settings.server_port,
38+
reload=settings.debug,
39+
)
40+
41+
{%- elif service_framework == 'flask' -%}
42+
from flask import Flask
43+
from .settings import settings
44+
45+
app = Flask(__name__)
46+
47+
48+
@app.route("/")
49+
def hello_world():
50+
return {"Hello": "World", "env": settings.environment}
51+
52+
@app.route("/health")
53+
def health_check():
54+
return {"status": "ok"}
55+
56+
57+
if __name__ == "__main__":
58+
# For development only. Use a production WSGI server for deployment.
59+
app.run(host=settings.server_host, port=settings.server_port, debug=settings.debug)
60+
{%- endif -%}
61+
{%- endif -%}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
from pydantic_settings import BaseSettings, SettingsConfigDict
2+
3+
4+
class Settings(BaseSettings):
5+
model_config = SettingsConfigDict(
6+
env_file=(".env.local", ".env"), env_ignore_empty=True, extra="ignore"
7+
)
8+
9+
environment: str = "local"
10+
debug: bool = False
11+
server_host: str = "0.0.0.0"
12+
server_port: int = 8000
13+
14+
15+
settings = Settings()

0 commit comments

Comments
 (0)