init
This commit is contained in:
101
internal/executor/docker.go
Normal file
101
internal/executor/docker.go
Normal file
@@ -0,0 +1,101 @@
|
||||
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)
|
||||
}
|
||||
34
internal/executor/exec.go
Normal file
34
internal/executor/exec.go
Normal file
@@ -0,0 +1,34 @@
|
||||
package executor
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"context"
|
||||
"os/exec"
|
||||
|
||||
"deployment-manager/internal/events"
|
||||
)
|
||||
|
||||
func RunCmd(ctx context.Context, eventChan chan<- *events.Event, repoID int64, cmd string, args ...string) error {
|
||||
c := exec.CommandContext(ctx, cmd, args...)
|
||||
|
||||
stdout, _ := c.StdoutPipe()
|
||||
stderr, _ := c.StderrPipe()
|
||||
|
||||
if err := c.Start(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
go stream(stdout, eventChan, repoID, "stdout")
|
||||
go stream(stderr, eventChan, repoID, "stderr")
|
||||
|
||||
return c.Wait()
|
||||
}
|
||||
|
||||
func stream(r interface{ Read([]byte) (int, error) }, eventChan chan<- *events.Event, repoID int64, streamType string) {
|
||||
scanner := bufio.NewScanner(r)
|
||||
for scanner.Scan() {
|
||||
event := events.NewLogEvent(repoID, scanner.Text())
|
||||
event.Data["stream"] = streamType
|
||||
eventChan <- event
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user