deploy.yml: sync compose+Caddyfile from git, reload caddy after up

This commit is contained in:
lekss361 2026-04-26 13:31:26 +03:00
parent 4f034bd86b
commit 6c4ba1777a
10 changed files with 17 additions and 30 deletions

View file

@ -2,13 +2,9 @@ from pydantic_settings import BaseSettings, SettingsConfigDict
class Settings(BaseSettings): class Settings(BaseSettings):
model_config = SettingsConfigDict( model_config = SettingsConfigDict(env_file=".env", env_file_encoding="utf-8", extra="ignore")
env_file=".env", env_file_encoding="utf-8", extra="ignore"
)
database_url: str = ( database_url: str = "postgresql+psycopg://gendesign:gendesign@localhost:5432/gendesign"
"postgresql+psycopg://gendesign:gendesign@localhost:5432/gendesign"
)
redis_url: str = "redis://localhost:6379/0" redis_url: str = "redis://localhost:6379/0"
cors_origins: list[str] = ["http://localhost:3000"] cors_origins: list[str] = ["http://localhost:3000"]
sentry_dsn: str | None = None sentry_dsn: str | None = None

View file

@ -6,9 +6,7 @@ from sqlalchemy.orm import DeclarativeBase, Session, sessionmaker
from app.core.config import settings from app.core.config import settings
engine = create_engine(settings.database_url, pool_pre_ping=True, future=True) engine = create_engine(settings.database_url, pool_pre_ping=True, future=True)
SessionLocal = sessionmaker( SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine, expire_on_commit=False)
autocommit=False, autoflush=False, bind=engine, expire_on_commit=False
)
class Base(DeclarativeBase): class Base(DeclarativeBase):

View file

@ -12,9 +12,7 @@ class ConceptInput(BaseModel):
housing_class: Literal["econom", "comfort", "business"] = "comfort" housing_class: Literal["econom", "comfort", "business"] = "comfort"
target_floors: int = Field(9, ge=1, le=30) target_floors: int = Field(9, ge=1, le=30)
development_type: Literal["spot", "mid_rise", "high_rise"] = "mid_rise" development_type: Literal["spot", "mid_rise", "high_rise"] = "mid_rise"
land_cost_rub: float | None = Field( land_cost_rub: float | None = Field(None, description="Optional land cost for financial model")
None, description="Optional land cost for financial model"
)
class TEAP(BaseModel): class TEAP(BaseModel):

View file

@ -21,9 +21,7 @@ def generate_stub(payload: ConceptInput) -> list[ConceptVariant]:
density=0.0, density=0.0,
parking_spaces=0, parking_spaces=0,
) )
empty_financial = FinancialModel( empty_financial = FinancialModel(revenue_rub=0.0, cost_rub=0.0, gross_margin_rub=0.0, irr=0.0)
revenue_rub=0.0, cost_rub=0.0, gross_margin_rub=0.0, irr=0.0
)
strategies: list[ConceptVariant] = [] strategies: list[ConceptVariant] = []
for strategy in ("max_area", "max_insolation", "balanced"): for strategy in ("max_area", "max_insolation", "balanced"):
strategies.append( strategies.append(

View file

@ -7,7 +7,5 @@ from celery import Celery
from app.core.config import settings from app.core.config import settings
celery_app = Celery( celery_app = Celery("gendesign", broker=settings.redis_url, backend=settings.redis_url)
"gendesign", broker=settings.redis_url, backend=settings.redis_url
)
celery_app.conf.timezone = "Europe/Moscow" celery_app.conf.timezone = "Europe/Moscow"

View file

@ -8,12 +8,10 @@ export default function ConceptPage() {
<Link href="/"> Home</Link> <Link href="/"> Home</Link>
<h1>Concept (Generative Design)</h1> <h1>Concept (Generative Design)</h1>
<p> <p>
TODO Stage 1a: polygon import (GeoJSON / Leaflet draw) + parameter form + TODO Stage 1a: polygon import (GeoJSON / Leaflet draw) + parameter form
result tabs. + result tabs.
</p>
<p>
TODO Stage 1b: render 3 variants on the map with colored buildings.
</p> </p>
<p>TODO Stage 1b: render 3 variants on the map with colored buildings.</p>
<p> <p>
TODO Stage 1c: TEAP table, financial form, PDF/Excel/DXF download TODO Stage 1c: TEAP table, financial form, PDF/Excel/DXF download
buttons. buttons.

View file

@ -8,7 +8,10 @@ export default function SiteFinderPage() {
<Link href="/"> Home</Link> <Link href="/"> Home</Link>
<h1>Site Finder</h1> <h1>Site Finder</h1>
<p>TODO Stage 2a: load 1000+ Sverdlovsk parcels into PostGIS.</p> <p>TODO Stage 2a: load 1000+ Sverdlovsk parcels into PostGIS.</p>
<p>TODO Stage 2b: map (Mapbox) with color-graded parcels + filters + table + card.</p> <p>
TODO Stage 2b: map (Mapbox) with color-graded parcels + filters + table
+ card.
</p>
<p>TODO Stage 2c: «Compute concept» button calling Generative module.</p> <p>TODO Stage 2c: «Compute concept» button calling Generative module.</p>
</main> </main>
); );

View file

@ -4,7 +4,7 @@ export const API_BASE_URL = process.env.NEXT_PUBLIC_API_BASE_URL ?? "";
export async function apiFetch<T>( export async function apiFetch<T>(
path: string, path: string,
init?: RequestInit init?: RequestInit,
): Promise<T> { ): Promise<T> {
const response = await fetch(`${API_BASE_URL}${path}`, { const response = await fetch(`${API_BASE_URL}${path}`, {
...init, ...init,
@ -14,9 +14,7 @@ export async function apiFetch<T>(
}, },
}); });
if (!response.ok) { if (!response.ok) {
throw new Error( throw new Error(`API error ${response.status}: ${await response.text()}`);
`API error ${response.status}: ${await response.text()}`
);
} }
return response.json() as Promise<T>; return response.json() as Promise<T>;
} }