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
3 changes: 3 additions & 0 deletions .github/workflows/cd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ jobs:
echo "bot_token: ${{ secrets.BOT_TOKEN }}" > deploy/prod/ttt/secrets.yaml
echo "payments_token: ${{ secrets.PAYMENTS_TOKEN }}" >> deploy/prod/ttt/secrets.yaml
echo "gemini_api_key: ${{ secrets.GEMINI_API_KEY }}" >> deploy/prod/ttt/secrets.yaml
echo "sentry_dsn: ${{ secrets.SENTRY_DSN }}" >> deploy/prod/ttt/secrets.yaml

- name: deploy
run: bash ./deploy/prod/deploy.sh
Expand All @@ -29,3 +30,5 @@ jobs:
NATS_TOKEN: ${{ secrets.NATS_TOKEN }}

GEMINI_URL: ${{ secrets.GEMINI_URL }}

GRAFANA_ADMIN_PASSWORD: ${{ secrets.GRAFANA_ADMIN_PASSWORD }}
3 changes: 3 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ jobs:
echo "bot_token: ${{ secrets.BOT_TOKEN }}" > deploy/dev/ttt/secrets.yaml
echo "payments_token: ${{ secrets.PAYMENTS_TOKEN }}" >> deploy/dev/ttt/secrets.yaml
echo "gemini_api_key: ${{ secrets.GEMINI_API_KEY }}" >> deploy/dev/ttt/secrets.yaml
echo "sentry_dsn: ${{ secrets.SENTRY_DSN }}" >> deploy/dev/ttt/secrets.yaml

- name: ruff
run: docker compose -f deploy/dev/docker-compose.yaml run ttt ruff check src tests
Expand All @@ -27,6 +28,7 @@ jobs:
echo "bot_token: ${{ secrets.BOT_TOKEN }}" > deploy/dev/ttt/secrets.yaml
echo "payments_token: ${{ secrets.PAYMENTS_TOKEN }}" >> deploy/dev/ttt/secrets.yaml
echo "gemini_api_key: ${{ secrets.GEMINI_API_KEY }}" >> deploy/dev/ttt/secrets.yaml
echo "sentry_dsn: ${{ secrets.SENTRY_DSN }}" >> deploy/dev/ttt/secrets.yaml

- name: mypy
run: docker compose -f deploy/dev/docker-compose.yaml run ttt mypy src tests
Expand All @@ -41,6 +43,7 @@ jobs:
echo "bot_token: ${{ secrets.BOT_TOKEN }}" > deploy/dev/ttt/secrets.yaml
echo "payments_token: ${{ secrets.PAYMENTS_TOKEN }}" >> deploy/dev/ttt/secrets.yaml
echo "gemini_api_key: ${{ secrets.GEMINI_API_KEY }}" >> deploy/dev/ttt/secrets.yaml
echo "sentry_dsn: ${{ secrets.SENTRY_DSN }}" >> deploy/dev/ttt/secrets.yaml

- name: pytest
run: docker compose -f deploy/dev/docker-compose.yaml run ttt pytest tests --cov --cov-report=xml
Expand Down
17 changes: 11 additions & 6 deletions deploy/dev/docker-compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ name: ttt

services:
ttt:
image: ttt:dev
build:
context: ../../
dockerfile: deploy/dev/ttt/Dockerfile
Expand All @@ -26,7 +27,7 @@ services:
TTT_POSTGRES_POOL_TIMEOUT_SECONDS: 30
TTT_POSTGRES_POOL_RECYCLE_SECONDS: 1800
TTT_POSTGRES_POOL_PRE_PING: false
TTT_POSTGRES_ECHO: true
TTT_POSTGRES_ECHO: false

TTT_REDIS_URL: redis://redis:6379/0
TTT_REDIS_POOL_SIZE: 16
Expand Down Expand Up @@ -54,7 +55,7 @@ services:
POSTGRES_PASSWORD: root
healthcheck:
test: pg_isready -d root -U root
start_period: 1m
start_period: 2m
start_interval: 1s
interval: 5s

Expand Down Expand Up @@ -97,10 +98,14 @@ services:
command: ["bash", "/mnt/add_streams.sh"]

volumes:
backend-data: null
postgres-data: null
redis-data: null
nats-data: null
backend-data:
name: "ttt-dev-postgres-backend-data"
postgres-data:
name: "ttt-dev-postgres-postgres-data"
redis-data:
name: "ttt-dev-postgres-redis-data"
nats-data:
name: "ttt-dev-postgres-nats-data"

secrets:
secrets:
Expand Down
2 changes: 2 additions & 0 deletions deploy/prod/.env.template
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,5 @@ POSTGRES_REPLICA_PASSWORD=replica
NATS_TOKEN=nats

GEMINI_URL=https://my-gemini.vercel.app

GRAFANA_ADMIN_PASSWORD=grafana
47 changes: 47 additions & 0 deletions deploy/prod/alloy/config.alloy
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// This component is responsible for disovering new containers within the docker environment
discovery.docker "getting_started" {
host = "unix:///var/run/docker.sock"
refresh_interval = "5s"
}

// This component is responsible for relabeling the discovered containers
discovery.relabel "getting_started" {
targets = []

rule {
source_labels = ["__meta_docker_container_name"]
regex = "/(.*)"
target_label = "container"
}
}

// This component is responsible for collecting logs from the discovered containers
loki.source.docker "getting_started" {
host = "unix:///var/run/docker.sock"
targets = discovery.docker.getting_started.targets
forward_to = [loki.process.getting_started.receiver]
relabel_rules = discovery.relabel.getting_started.rules
refresh_interval = "5s"
}

// This component is responsible for processing the logs (In this case adding static labels)
loki.process "getting_started" {
stage.static_labels {
values = {
env = "production",
}
}
forward_to = [loki.write.getting_started.receiver]
}

// This component is responsible for writing the logs to Loki
loki.write "getting_started" {
endpoint {
url = "http://loki:3100/loki/api/v1/push"
}
}

// Enables the ability to view logs in the Alloy UI in realtime
livedebugging {
enabled = true
}
63 changes: 60 additions & 3 deletions deploy/prod/docker-compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ name: ttt

services:
ttt:
image: ttt:prod
build:
context: ../../
dockerfile: deploy/prod/ttt/Dockerfile
Expand All @@ -26,7 +27,7 @@ services:
TTT_POSTGRES_POOL_TIMEOUT_SECONDS: 45
TTT_POSTGRES_POOL_RECYCLE_SECONDS: 1800
TTT_POSTGRES_POOL_PRE_PING: false
TTT_POSTGRES_ECHO: true
TTT_POSTGRES_ECHO: false

TTT_REDIS_URL: redis://:${REDIS_PASSWORD}@redis:6379/0
TTT_REDIS_POOL_SIZE: 16
Expand Down Expand Up @@ -86,7 +87,7 @@ services:
mem_limit: 30mb
healthcheck:
test: pg_isready -d ttt -U ttt
start_period: 1m
start_period: 2m
start_interval: 1s
interval: 5s

Expand Down Expand Up @@ -116,7 +117,7 @@ services:
mem_limit: 30mb
healthcheck:
test: pg_isready -d ttt -U ttt
start_period: 1m
start_period: 2m
start_interval: 1s
interval: 5s

Expand Down Expand Up @@ -154,6 +155,57 @@ services:
entrypoint: [""]
command: ["bash", "/mnt/add_streams.sh"]

alloy:
image: grafana/alloy:v1.10.0
container_name: ttt-alloy
volumes:
- ./alloy/config.alloy:/etc/alloy/config.alloy
- /var/run/docker.sock:/var/run/docker.sock
networks:
- loki
command: run --server.http.listen-addr=0.0.0.0:12345 --storage.path=/var/lib/alloy/data /etc/alloy/config.alloy
depends_on:
- loki

loki:
image: grafana/loki:3.4.5
container_name: ttt-loki
environment:
TZ: ${SYSTEM_TIMEZONE:-Europe/Moscow}
volumes:
- loki-data:/loki
- ./loki/loki-config.yaml:/etc/loki/local-config.yaml
networks:
- loki
command: -config.file=/etc/loki/local-config.yaml

grafana:
image: grafana/grafana:12.0.2-ubuntu
container_name: ttt-grafana
environment:
- GF_PATHS_PROVISIONING=/etc/grafana/provisioning
- GF_FEATURE_TOGGLES_ENABLE=grafanaManagedRecordingRules

- GF_AUTH_ANONYMOUS_ENABLED=false
- GF_AUTH_BASIC_ENABLED=true

- GF_SECURITY_FORCE_PASSWORD_CHANGE=true
- GF_SECURITY_DISABLE_INITIAL_ADMIN_CREATION=false
- GF_SECURITY_ADMIN_USER=admin
- GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_ADMIN_PASSWORD}
- GF_SECURITY_MIN_PASSWORD_LENGTH=4

- GF_USERS_ALLOW_SIGN_UP=false

- TZ=${SYSTEM_TIMEZONE:-Europe/Moscow}
ports:
- 3000:3000
volumes:
- grafana-data:/var/lib/grafana
- ./grafana/provisioning/datasources:/etc/grafana/provisioning/datasources
networks:
- loki

volumes:
postgres-replica1-data:
name: "ttt-prod-postgres-replica1-data"
Expand All @@ -163,11 +215,16 @@ volumes:
name: "ttt-prod-redis-data"
nats-data:
name: "ttt-prod-nats-data"
loki-data:
name: "ttt-prod-loki-data"
grafana-data:
name: "ttt-prod-grafana-data"

networks:
postgres: null
redis: null
nats: null
loki: null

secrets:
secrets:
Expand Down
11 changes: 11 additions & 0 deletions deploy/prod/grafana/provisioning/datasources/loki.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
apiVersion: 1
datasources:
- name: Loki
type: loki
access: proxy
orgId: 1
url: http://loki:3100
basicAuth: false
isDefault: true
version: 1
editable: true
61 changes: 61 additions & 0 deletions deploy/prod/loki/loki-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
auth_enabled: false

server:
http_listen_port: 3100
grpc_listen_port: 9096
log_level: info
grpc_server_max_concurrent_streams: 1000

common:
instance_addr: 127.0.0.1
path_prefix: /tmp/loki
storage:
filesystem:
chunks_directory: /tmp/loki/chunks
rules_directory: /tmp/loki/rules
replication_factor: 1
ring:
kvstore:
store: inmemory

query_range:
results_cache:
cache:
embedded_cache:
enabled: true
max_size_mb: 100

limits_config:
metric_aggregation_enabled: true
allow_structured_metadata: true
volume_enabled: true
retention_period: 24h # 24h

schema_config:
configs:
- from: 2020-10-24
store: tsdb
object_store: filesystem
schema: v13
index:
prefix: index_
period: 24h

pattern_ingester:
enabled: true
metric_aggregation:
loki_address: localhost:3100

ruler:
enable_alertmanager_discovery: true
enable_api: true


frontend:
encoding: protobuf


compactor:
working_directory: /tmp/loki/retention
delete_request_store: filesystem
retention_enabled: true
4 changes: 3 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ dependencies = [
"aiogram==3.20.0.post0",
"nats-py[nkeys]==2.10.0",
"openai==1.97.0",
"structlog==25.4.0",
"structlog-sentry==2.2.1",
]

[dependency-groups]
Expand All @@ -32,7 +34,7 @@ dev = [
"pytest-cov==6.1.1",
"pytest-asyncio==1.0.0",
"dirty-equals==0.9.0",
"watchfiles==1.1.0",
"better-exceptions==0.3.3",
]

[project.urls]
Expand Down
5 changes: 4 additions & 1 deletion src/ttt/application/game/common/ports/game_ai_gateway.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,8 @@
class GameAiGateway(ABC):
@abstractmethod
async def next_move_cell_number_int(
self, game: Game, ai_id: UUID, /,
self,
game: Game,
ai_id: UUID,
/,
) -> int | None: ...
Loading