Compare commits
6 Commits
fix/module
...
dca05a8e9d
| Author | SHA1 | Date | |
|---|---|---|---|
| dca05a8e9d | |||
| e858fea056 | |||
| 90a4264691 | |||
| a94ba0d8a0 | |||
| 7253c64c78 | |||
| b074b8fe47 |
@@ -6,8 +6,9 @@ services:
|
|||||||
- "8080:8080"
|
- "8080:8080"
|
||||||
volumes:
|
volumes:
|
||||||
- /var/run/docker.sock:/var/run/docker.sock
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
- upaas-data:/var/lib/upaas
|
- ${HOST_DATA_DIR:-./data}:/var/lib/upaas
|
||||||
# environment:
|
environment:
|
||||||
|
- UPAAS_HOST_DATA_DIR=${HOST_DATA_DIR:-./data}
|
||||||
# Optional: uncomment to enable debug logging
|
# Optional: uncomment to enable debug logging
|
||||||
# - DEBUG=true
|
# - DEBUG=true
|
||||||
# Optional: Sentry error reporting
|
# Optional: Sentry error reporting
|
||||||
@@ -15,6 +16,3 @@ services:
|
|||||||
# Optional: Prometheus metrics auth
|
# Optional: Prometheus metrics auth
|
||||||
# - METRICS_USERNAME=prometheus
|
# - METRICS_USERNAME=prometheus
|
||||||
# - METRICS_PASSWORD=secret
|
# - METRICS_PASSWORD=secret
|
||||||
|
|
||||||
volumes:
|
|
||||||
upaas-data:
|
|
||||||
|
|||||||
@@ -113,9 +113,9 @@ func (d *Database) applyMigration(ctx context.Context, filename string) error {
|
|||||||
return fmt.Errorf("failed to record migration: %w", err)
|
return fmt.Errorf("failed to record migration: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
commitErr := transaction.Commit()
|
err = transaction.Commit()
|
||||||
if commitErr != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to commit migration: %w", commitErr)
|
return fmt.Errorf("failed to commit migration: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ func (h *Handlers) HandleAppCreate() http.HandlerFunc { //nolint:funlen // valid
|
|||||||
nameErr := validateAppName(name)
|
nameErr := validateAppName(name)
|
||||||
if nameErr != nil {
|
if nameErr != nil {
|
||||||
data["Error"] = "Invalid app name: " + nameErr.Error()
|
data["Error"] = "Invalid app name: " + nameErr.Error()
|
||||||
_ = tmpl.ExecuteTemplate(writer, "app_new.html", data)
|
h.renderTemplate(writer, tmpl, "app_new.html", data)
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -228,7 +228,7 @@ func (h *Handlers) HandleAppUpdate() http.HandlerFunc { //nolint:funlen // valid
|
|||||||
"App": application,
|
"App": application,
|
||||||
"Error": "Invalid app name: " + nameErr.Error(),
|
"Error": "Invalid app name: " + nameErr.Error(),
|
||||||
}, request)
|
}, request)
|
||||||
_ = tmpl.ExecuteTemplate(writer, "app_edit.html", data)
|
h.renderTemplate(writer, tmpl, "app_edit.html", data)
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -239,7 +239,7 @@ func (h *Handlers) HandleAppUpdate() http.HandlerFunc { //nolint:funlen // valid
|
|||||||
"App": application,
|
"App": application,
|
||||||
"Error": "Invalid repository URL: " + repoURLErr.Error(),
|
"Error": "Invalid repository URL: " + repoURLErr.Error(),
|
||||||
}, request)
|
}, request)
|
||||||
_ = tmpl.ExecuteTemplate(writer, "app_edit.html", data)
|
h.renderTemplate(writer, tmpl, "app_edit.html", data)
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import (
|
|||||||
"database/sql"
|
"database/sql"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.eeqj.de/sneak/upaas/internal/database"
|
"git.eeqj.de/sneak/upaas/internal/database"
|
||||||
@@ -76,7 +77,11 @@ func (d *Deployment) Reload(ctx context.Context) error {
|
|||||||
return d.scan(row)
|
return d.scan(row)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// maxLogSize is the maximum size of deployment logs stored in the database (1MB).
|
||||||
|
const maxLogSize = 1 << 20
|
||||||
|
|
||||||
// AppendLog appends a log line to the deployment logs.
|
// AppendLog appends a log line to the deployment logs.
|
||||||
|
// If the total log size exceeds maxLogSize, the oldest lines are truncated.
|
||||||
func (d *Deployment) AppendLog(ctx context.Context, line string) error {
|
func (d *Deployment) AppendLog(ctx context.Context, line string) error {
|
||||||
var currentLogs string
|
var currentLogs string
|
||||||
|
|
||||||
@@ -84,7 +89,22 @@ func (d *Deployment) AppendLog(ctx context.Context, line string) error {
|
|||||||
currentLogs = d.Logs.String
|
currentLogs = d.Logs.String
|
||||||
}
|
}
|
||||||
|
|
||||||
d.Logs = sql.NullString{String: currentLogs + line + "\n", Valid: true}
|
newLogs := currentLogs + line + "\n"
|
||||||
|
|
||||||
|
if len(newLogs) > maxLogSize {
|
||||||
|
// Keep the most recent logs that fit within the limit.
|
||||||
|
// Find a newline after the truncation point to avoid partial lines.
|
||||||
|
truncateAt := len(newLogs) - maxLogSize
|
||||||
|
idx := strings.Index(newLogs[truncateAt:], "\n")
|
||||||
|
|
||||||
|
if idx >= 0 {
|
||||||
|
newLogs = "[earlier logs truncated]\n" + newLogs[truncateAt+idx+1:]
|
||||||
|
} else {
|
||||||
|
newLogs = "[earlier logs truncated]\n" + newLogs[truncateAt:]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
d.Logs = sql.NullString{String: newLogs, Valid: true}
|
||||||
|
|
||||||
return d.Save(ctx)
|
return d.Save(ctx)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -251,8 +251,8 @@ func New(lc fx.Lifecycle, params ServiceParams) (*Service, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetBuildDir returns the build directory path for an app.
|
// GetBuildDir returns the build directory path for an app.
|
||||||
func (svc *Service) GetBuildDir(appID string) string {
|
func (svc *Service) GetBuildDir(appName string) string {
|
||||||
return filepath.Join(svc.config.DataDir, "builds", appID)
|
return filepath.Join(svc.config.DataDir, "builds", appName)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetLogFilePath returns the path to the log file for a deployment.
|
// GetLogFilePath returns the path to the log file for a deployment.
|
||||||
@@ -484,7 +484,7 @@ func (svc *Service) runBuildAndDeploy(
|
|||||||
svc.notify.NotifyBuildSuccess(bgCtx, app, deployment)
|
svc.notify.NotifyBuildSuccess(bgCtx, app, deployment)
|
||||||
|
|
||||||
// Deploy phase with timeout
|
// Deploy phase with timeout
|
||||||
err = svc.deployContainerWithTimeout(deployCtx, app, deployment, imageID)
|
err = svc.deployContainerWithTimeout(deployCtx, app, deployment)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
cancelErr := svc.checkCancelled(deployCtx, bgCtx, app, deployment, imageID)
|
cancelErr := svc.checkCancelled(deployCtx, bgCtx, app, deployment, imageID)
|
||||||
if cancelErr != nil {
|
if cancelErr != nil {
|
||||||
@@ -541,7 +541,6 @@ func (svc *Service) deployContainerWithTimeout(
|
|||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
app *models.App,
|
app *models.App,
|
||||||
deployment *models.Deployment,
|
deployment *models.Deployment,
|
||||||
imageID string,
|
|
||||||
) error {
|
) error {
|
||||||
deployCtx, cancel := context.WithTimeout(ctx, deployTimeout)
|
deployCtx, cancel := context.WithTimeout(ctx, deployTimeout)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
@@ -555,7 +554,7 @@ func (svc *Service) deployContainerWithTimeout(
|
|||||||
svc.removeOldContainer(deployCtx, app, deployment)
|
svc.removeOldContainer(deployCtx, app, deployment)
|
||||||
|
|
||||||
// Create and start the new container
|
// Create and start the new container
|
||||||
_, err = svc.createAndStartContainer(deployCtx, app, deployment, imageID)
|
_, err = svc.createAndStartContainer(deployCtx, app, deployment)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(deployCtx.Err(), context.DeadlineExceeded) {
|
if errors.Is(deployCtx.Err(), context.DeadlineExceeded) {
|
||||||
timeoutErr := fmt.Errorf("%w after %v", ErrDeployTimeout, deployTimeout)
|
timeoutErr := fmt.Errorf("%w after %v", ErrDeployTimeout, deployTimeout)
|
||||||
@@ -1018,7 +1017,6 @@ func (svc *Service) createAndStartContainer(
|
|||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
app *models.App,
|
app *models.App,
|
||||||
deployment *models.Deployment,
|
deployment *models.Deployment,
|
||||||
_ string,
|
|
||||||
) (string, error) {
|
) (string, error) {
|
||||||
containerOpts, err := svc.buildContainerOptions(ctx, app, deployment.ID)
|
containerOpts, err := svc.buildContainerOptions(ctx, app, deployment.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
Reference in New Issue
Block a user