package executor import ( "context" "fmt" "os" "path/filepath" "strings" "deployment-manager/internal/events" "deployment-manager/internal/model" ) func BuildAndPushImage(ctx context.Context, eventChan chan<- *events.Event, repo *model.Repo, workDir string) (string, error) { imageName := generateImageName(repo) // Build command buildCmd := "docker" buildArgs := []string{ "build", "-t", imageName, workDir, } if err := RunCmd(ctx, eventChan, repo.ID, buildCmd, buildArgs...); err != nil { return "", fmt.Errorf("docker build failed: %w", err) } // Push command pushCmd := "docker" pushArgs := []string{ "push", imageName, } if err := RunCmd(ctx, eventChan, repo.ID, pushCmd, pushArgs...); err != nil { return "", fmt.Errorf("docker push failed: %w", err) } return imageName, nil } func generateImageName(repo *model.Repo) string { // Extract repo name from URL for cleaner image names parts := strings.Split(strings.TrimSuffix(repo.RepoURL, ".git"), "/") repoName := parts[len(parts)-1] return fmt.Sprintf("deployment-manager/%s-%d:latest", repoName, repo.ID) } func GetDockerfileContent(repoType model.RepoType) string { switch repoType { case model.TypeNodeJS: return `FROM node:18-alpine WORKDIR /app COPY package*.json ./ RUN npm ci --only=production COPY . . EXPOSE 3000 CMD ["npm", "start"]` case model.TypePython: return `FROM python:3.11-slim WORKDIR /app COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt COPY . . EXPOSE 8000 CMD ["python", "app.py"]` default: return `FROM alpine:latest WORKDIR /app COPY . . CMD ["./app"]` } } func CreateDockerfile(workDir string, repoType model.RepoType) error { dockerfilePath := filepath.Join(workDir, "Dockerfile") content := GetDockerfileContent(repoType) return writeFile(dockerfilePath, content) } func writeFile(path, content string) error { return os.WriteFile(path, []byte(content), 0644) }