File size: 7,447 Bytes
e56d042
 
 
 
 
 
 
 
 
 
 
 
 
2073b3f
 
 
 
 
 
 
 
 
e56d042
 
 
 
 
 
 
 
2073b3f
 
 
 
 
 
 
 
 
 
 
 
eea2be5
 
 
 
 
2073b3f
 
 
 
 
 
 
 
 
 
 
e56d042
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2073b3f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
eea2be5
2073b3f
 
 
eea2be5
2073b3f
 
 
0f8f2c1
2073b3f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
0f8f2c1
 
 
 
2073b3f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
eea2be5
2073b3f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
# Load .env if present so Make sees every KEY=value in it, both as $(VAR)
# inside the Makefile and as an environment variable exported to recipes.
# Precedence (highest β†’ lowest):
#   1. CLI:           make run POOL_SIZE=16
#   2. Shell env:     POOL_SIZE=16 make run
#   3. .env file:     AWS_RL_ENV_POOL_SIZE=16 in ./.env
#   4. Makefile default (via ?=)
# Create one by copying the template:  cp .env.example .env
ifneq (,$(wildcard ./.env))
    include .env
    export
endif

# Project settings
PROJECT_NAME := openenv-aws_rl_env
PYTHON := python3
UV := uv
DOCKER_IMAGE := aws-rl-env
DOCKER_TAG := latest
SERVER_HOST := 0.0.0.0
SERVER_PORT := 8000

# Parallel MiniStack pool (used by `make run`).
#   POOL_SIZE=1           β†’ single MiniStack on MINISTACK_BASE_PORT (legacy behavior)
#   POOL_SIZE>1           β†’ N MiniStacks on MINISTACK_BASE_PORT..BASE_PORT+N-1,
#                           server exposes N concurrent WebSocket sessions
# Override from CLI: `make run POOL_SIZE=8` or `POOL_SIZE=8 make run`.
POOL_SIZE ?= $(or $(AWS_RL_ENV_POOL_SIZE),1)
MINISTACK_BASE_PORT ?= $(or $(AWS_RL_ENV_MINISTACK_BASE_PORT),4566)

.DEFAULT_GOAL := help

# ──────────────────────────────────────────────
# Setup & Dependencies
# ──────────────────────────────────────────────

.PHONY: install
install: ## Install project dependencies
	$(UV) sync --frozen

.PHONY: install-dev
install-dev: ## Install project with dev dependencies
	$(UV) sync --frozen --extra dev


.PHONY: install-all
install-all: ## Install project with all dependencies (dev + training)
	$(UV) sync --frozen --all-extras

.PHONY: lock
lock: ## Update the lockfile
	$(UV) lock

# ──────────────────────────────────────────────
# Development
# ──────────────────────────────────────────────

.PHONY: run
run: ## Run MiniStack pool + FastAPI server. Env: POOL_SIZE (default 1), MINISTACK_BASE_PORT (default 4566)
	@echo "==> Starting $(POOL_SIZE) MiniStack(s) on ports $(MINISTACK_BASE_PORT)..$$(($(MINISTACK_BASE_PORT) + $(POOL_SIZE) - 1))"
	@for i in $$(seq 0 $$(($(POOL_SIZE) - 1))); do \
		port=$$(($(MINISTACK_BASE_PORT) + $$i)); \
		echo "    MiniStack :$$port"; \
		GATEWAY_PORT=$$port ministack -d; \
	done
	@sleep 2
	@echo "==> FastAPI server on $(SERVER_HOST):$(SERVER_PORT) (POOL_SIZE=$(POOL_SIZE))"
	AWS_RL_ENV_POOL_SIZE=$(POOL_SIZE) \
	AWS_RL_ENV_MINISTACK_BASE_PORT=$(MINISTACK_BASE_PORT) \
	$(UV) run uvicorn server.app:app --host $(SERVER_HOST) --port $(SERVER_PORT) --reload

.PHONY: run-stop
run-stop: ## Stop every MiniStack started by `make run` (uses current POOL_SIZE + MINISTACK_BASE_PORT)
	@for i in $$(seq 0 $$(($(POOL_SIZE) - 1))); do \
		port=$$(($(MINISTACK_BASE_PORT) + $$i)); \
		echo "    stopping MiniStack :$$port"; \
		GATEWAY_PORT=$$port ministack --stop || true; \
	done

# ──────────────────────────────────────────────
# Code Quality
# ──────────────────────────────────────────────

.PHONY: format
format: ## Format code with ruff
	$(UV) run ruff format .

.PHONY: lint
lint: ## Lint code with ruff
	$(UV) run ruff check .

.PHONY: lint-fix
lint-fix: ## Lint and auto-fix code with ruff
	$(UV) run ruff check --fix .

.PHONY: typecheck
typecheck: ## Run type checking with mypy
	$(UV) run mypy

.PHONY: check
check: lint typecheck

# ──────────────────────────────────────────────
# Docker
# ──────────────────────────────────────────────

.PHONY: docker-build
docker-build: ## Build Docker image
	docker build -t $(DOCKER_IMAGE):$(DOCKER_TAG) .

.PHONY: docker-run
docker-run: ## Run Docker container
	docker run --rm --name $(DOCKER_IMAGE) -p $(SERVER_PORT):8000 $(DOCKER_IMAGE):$(DOCKER_TAG)

.PHONY: docker-run-dev
docker-run-dev: ## Run Docker container in dev mode with live reload
	docker run --rm --name $(DOCKER_IMAGE) -p $(SERVER_PORT):8000 -v $(PWD):/app/env -v /app/env/.venv -e DEV_MODE=1 $(DOCKER_IMAGE):$(DOCKER_TAG)

.PHONY: docker-run-detach
docker-run-detach: ## Run Docker container in background
	docker run -d --rm --name $(DOCKER_IMAGE) -p $(SERVER_PORT):8000 -v $(PWD):/app/env -v /app/env/.venv -e DEV_MODE=1 $(DOCKER_IMAGE):$(DOCKER_TAG)

.PHONY: docker-stop
docker-stop: ## Stop the running Docker container
	docker stop $(DOCKER_IMAGE)

.PHONY: docker-logs
docker-logs: ## Tail logs from the running Docker container
	docker logs -f $(DOCKER_IMAGE)

.PHONY: docker-shell
docker-shell: ## Open a shell in the running Docker container
	docker exec -it $(DOCKER_IMAGE) /bin/bash

.PHONY: docker-clean
docker-clean: ## Stop and remove all running containers for this image
	@docker ps -q --filter ancestor=$(DOCKER_IMAGE):$(DOCKER_TAG) | xargs -r docker rm -f

.PHONY: docker-test
docker-test: ## Run tests inside the running Docker container
	docker exec $(DOCKER_IMAGE) python -m pytest env/tests -v

.PHONY: docker-health
docker-health: ## Check health of the running container
	@curl -sf http://localhost:$(SERVER_PORT)/health && echo " OK" || echo " FAIL"

# ──────────────────────────────────────────────
# OpenEnv
# ──────────────────────────────────────────────

.PHONY: openenv-validate
openenv-validate: ## Validate the OpenEnv configuration
	openenv validate

.PHONY: openenv-build
openenv-build: ## Build the environment using OpenEnv CLI
	openenv build

.PHONY: openenv-push
openenv-push: ## Push the environment to Hugging Face Spaces
	openenv push

# ──────────────────────────────────────────────
# Cleanup
# ──────────────────────────────────────────────

.PHONY: clean
clean: ## Remove build artifacts and caches
	rm -rf build/ dist/ *.egg-info .eggs/
	rm -rf aws_infra/*.egg-info aws_infra/build/ aws_infra/dist/
	rm -rf .pytest_cache/ .mypy_cache/ .ruff_cache/
	rm -rf htmlcov/ .coverage coverage.xml
	find . -type d -name __pycache__ -exec rm -rf {} + 2>/dev/null || true
	find . -type f -name '*.pyc' -delete 2>/dev/null || true

.PHONY: clean-all
clean-all: clean ## Remove all artifacts including venv
	rm -rf .venv/

# ──────────────────────────────────────────────
# Help
# ──────────────────────────────────────────────

.PHONY: help
help: ## Show this help message
	@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | \
		awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-20s\033[0m %s\n", $$1, $$2}'