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
11 changes: 11 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
.venv/
__pycache__/
*.pyc
*.pyo
*.pyd
.Python
.pytest_cache/
.mypy_cache/
.ruff_cache/
.git/
.gitignore
45 changes: 45 additions & 0 deletions .github/workflows/fly-deploy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
name: Deploy to Fly.io

on:
push:
branches:
- main
workflow_dispatch:

concurrency:
group: fly-deploy-${{ github.ref }}
cancel-in-progress: true

jobs:
deploy:
runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Compute app version
id: app_version
run: |
APP_VERSION=$(python - <<'PY'
import tomllib
import os

with open("pyproject.toml", "rb") as f:
data = tomllib.load(f)
base = data["project"]["version"]
parts = base.split(".")
if len(parts) != 3:
raise SystemExit(f"Expected semantic version 'X.Y.Z', got: {base}")
print(f"{parts[0]}.{parts[1]}.{os.environ['GITHUB_RUN_NUMBER']}")
PY
)
echo "value=${APP_VERSION}" >> "$GITHUB_OUTPUT"

- name: Setup flyctl
uses: superfly/flyctl-actions/setup-flyctl@master

- name: Deploy to Fly.io
run: flyctl deploy --remote-only --config fly.toml --build-arg APP_VERSION=${{ steps.app_version.outputs.value }}
env:
FLY_API_TOKEN: ${{ secrets.FLY_API_TOKEN }}
7 changes: 0 additions & 7 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -94,13 +94,6 @@ ipython_config.py
# install all needed dependencies.
#Pipfile.lock

# poetry
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
# This is especially recommended for binary packages to ensure reproducibility, and is more
# commonly ignored for libraries.
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
*.lock

# pdm
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
#pdm.lock
Expand Down
2 changes: 1 addition & 1 deletion .python-version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
3.10
3.14
18 changes: 14 additions & 4 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,11 +1,21 @@
FROM python:3-alpine
FROM python:3.14-slim

WORKDIR /app

COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/

ENV UV_PYTHON_DOWNLOADS=never
ENV UV_LINK_MODE=copy

COPY pyproject.toml uv.lock ./
RUN uv sync --frozen --no-dev --no-install-project

COPY . .
RUN uv sync --frozen --no-dev

RUN pip install --no-cache-dir .
ARG APP_VERSION=dev
ENV APP_VERSION=${APP_VERSION}

EXPOSE 8000
EXPOSE 8080

CMD ["python", "src/main.py"]
CMD ["/app/.venv/bin/python", "src/main.py"]
18 changes: 17 additions & 1 deletion fly.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,22 @@ app = "flet-controls-gallery"
[env]
FLET_SERVER_PORT = "8080"
FLET_FORCE_WEB_SERVER = "true"
FLET_SESSION_TIMEOUT = "600"
MEM_DIAG = "0"
MEM_DIAG_INTERVAL_SEC = "60"
MEM_DIAG_TRACE_INTERVAL_SEC = "300"
MEM_DIAG_TRACE_FRAMES = "10"
MEM_DIAG_TRACE_TOP = "10"
MEM_DIAG_CONTROL_SCAN_MAX_NODES = "15000"
MEM_DIAG_COLLECT_ON_SAMPLE = "1"
MEM_DIAG_CONTROL_SCAN = "1"
MEM_DIAG_GC_OBJECTS = "0"
MEM_DIAG_COLLECT_GEN2_ON_SAMPLE = "1"
MEM_DIAG_TYPE_HIST = "0"
MEM_DIAG_TYPE_HIST_INTERVAL_SEC = "300"
MEM_DIAG_TYPE_HIST_TOP = "30"
MALLOC_ARENA_MAX = "2"
MALLOC_TRIM_THRESHOLD_ = "131072"

[experimental]
allowed_public_ports = []
Expand Down Expand Up @@ -36,4 +52,4 @@ app = "flet-controls-gallery"
grace_period = "1s"
interval = "15s"
restart_limit = 0
timeout = "2s"
timeout = "2s"
7 changes: 4 additions & 3 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name = "gallery"
version = "0.1.0"
description = ""
readme = "README.md"
requires-python = ">=3.10"
requires-python = ">=3.14"
authors = [
{ name = "Flet developer", email = "you@example.com" }
]
Expand All @@ -12,6 +12,7 @@ dependencies = [
"flet-audio",
"flet-video",
"flet",
"flet-web",
"objgraph"
]

Expand All @@ -27,6 +28,6 @@ path = "src"

[dependency-groups]
dev = [
"flet[all]",
"flet-cli",
"flet-desktop",
]

7 changes: 6 additions & 1 deletion src/components/app.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import flet as ft

from components.app_bar import AppBar
from components.diagnostics_view import DiagnosticsView
from components.gallery_view import GalleryView
from contexts.route import RouteContext, RouteContextValue
from contexts.theme import ThemeContext, ThemeContextValue
Expand Down Expand Up @@ -74,7 +75,11 @@ def update_theme():
lambda: ft.View(
route="/",
appbar=AppBar(),
controls=[GalleryView(gallery)],
controls=[
DiagnosticsView(key="diagnostics-view")
if app.route == "/__diag"
else GalleryView(gallery, key="gallery-view")
],
),
),
)
36 changes: 34 additions & 2 deletions src/components/app_bar.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,34 @@
import platform

import flet as ft
import flet.version

from utils.app_version import get_app_version


@ft.component
def AppBar():
def show_about_dialog():
ft.context.page.show_dialog(
ft.AlertDialog(
title=ft.Text("About Gallery"),
content=ft.Column(
tight=True,
controls=[
ft.Text(f"Gallery version: {get_app_version()}"),
ft.Text(f"Flet version: {flet.version.flet_version}"),
ft.Text(f"Flutter version: {flet.version.flutter_version}"),
ft.Text(f"Python version: {platform.python_version()}"),
],
),
actions=[
ft.TextButton(
"Close", on_click=lambda _: ft.context.page.pop_dialog()
)
],
)
)

return ft.AppBar(
title=ft.Row(
[
Expand All @@ -14,8 +39,15 @@ def AppBar():
center_title=True,
# bgcolor=ft.Colors.INVERSE_PRIMARY,
actions=[
ft.Container(
padding=10, content=ft.Text(f"Version: {flet.version.flet_version}")
ft.PopupMenuButton(
icon=ft.Icons.MORE_VERT,
tooltip="Menu",
items=[
ft.PopupMenuItem(
content="About",
on_click=show_about_dialog,
)
],
),
],
)
50 changes: 50 additions & 0 deletions src/components/diagnostics_view.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import json

import flet as ft

from diagnostics import diagnostics


@ft.component
def DiagnosticsView() -> ft.Control:
last_dump, set_last_dump = ft.use_state("No diagnostics dump requested yet.")

print("Rendering DiagnosticsView")

def dump_now(_):
payload = diagnostics.dump_now(reason="hidden_route_button")
set_last_dump(json.dumps(payload, indent=2, default=str))

return ft.Column(
expand=True,
controls=[
ft.Text("Memory Diagnostics"),
ft.Text(
"Hidden route for on-demand mem diagnostics. Triggering a dump logs JSON via memdiag logger.",
color=ft.Colors.ON_SURFACE_VARIANT,
),
ft.Row(
controls=[
ft.Button(
"Dump diagnostics now",
icon=ft.Icons.BUG_REPORT,
on_click=dump_now,
),
ft.OutlinedButton(
"Back to gallery",
icon=ft.Icons.ARROW_BACK,
on_click=lambda _: ft.context.page.go("/"),
),
]
),
ft.TextField(
value=last_dump,
multiline=True,
min_lines=14,
max_lines=24,
read_only=True,
expand=True,
text_style=ft.TextStyle(font_family="Roboto Mono", size=12),
),
],
)
Loading