feat: add pg-query example + upload.go supports requirements.txt

- examples/pg-query/handler.py: Python function querying PostgreSQL invocations table
- examples/pg-query/requirements.txt: psycopg2-binary==2.9.9
- examples/pg-query/main.tf: terraform config for sless_function + sless_trigger
- internal/api/handler/upload.go: generateDockerfile() now accepts hasRequirements bool
  - scans zip for requirements.txt at upload time
  - adds RUN pip install --no-cache-dir to Dockerfile when requirements.txt present
- doc/progress.md: updated status for pg-query e2e task
This commit is contained in:
“Naeel”
2026-03-07 10:30:50 +04:00
parent dc7542148e
commit 4e59d79884
5 changed files with 124 additions and 3 deletions
+19 -2
View File
@@ -40,12 +40,18 @@ func runtimeBaseImage(runtime string) (string, error) {
// generateDockerfile генерирует Dockerfile для kaniko.
// Базовый образ содержит HTTP-обёртку (server.py).
// Пользовательский код копируется в /app/function/ поверх базового образа.
func generateDockerfile(runtime string) ([]byte, error) {
// Если в zip есть requirements.txt — добавляем pip install (для python runtime).
func generateDockerfile(runtime string, hasRequirements bool) ([]byte, error) {
baseImage, err := runtimeBaseImage(runtime)
if err != nil {
return nil, err
}
content := fmt.Sprintf("FROM %s\nCOPY . /app/function/\n", baseImage)
// pip install только для python runtime и только если requirements.txt есть в zip.
// Делаем это ПОСЛЕ COPY чтобы воспользоваться кешем слоёв Docker при повторных сборках.
if hasRequirements && runtime == "python3.11" {
content += "RUN pip install --no-cache-dir -r /app/function/requirements.txt\n"
}
return []byte(content), nil
}
@@ -145,8 +151,19 @@ func (h *Handler) UploadCode(w http.ResponseWriter, r *http.Request) {
return
}
// Проверяем есть ли requirements.txt в zip (для python runtime — pip install)
hasRequirements := false
if zr, err := zip.NewReader(bytes.NewReader(zipData), int64(len(zipData))); err == nil {
for _, f := range zr.File {
if f.Name == "requirements.txt" {
hasRequirements = true
break
}
}
}
// Генерируем Dockerfile под runtime функции
dockerfileContent, err := generateDockerfile(fn.Spec.Runtime)
dockerfileContent, err := generateDockerfile(fn.Spec.Runtime, hasRequirements)
if err != nil {
writeJSON(w, http.StatusBadRequest, errResp(err.Error()))
return