Core infrastructure: - Uber fx dependency injection - Chi router with middleware stack - SQLite database with embedded migrations - Embedded templates and static assets - Structured logging with slog Features implemented: - Authentication (login, logout, session management, argon2id hashing) - App management (create, edit, delete, list) - Deployment pipeline (clone, build, deploy, health check) - Webhook processing for Gitea - Notifications (ntfy, Slack) - Environment variables, labels, volumes per app - SSH key generation for deploy keys Server startup: - Server.Run() starts HTTP server on configured port - Server.Shutdown() for graceful shutdown - SetupRoutes() wires all handlers with chi router
802 lines
18 KiB
Go
802 lines
18 KiB
Go
package models_test
|
|
|
|
import (
|
|
"context"
|
|
"database/sql"
|
|
"strconv"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
"go.uber.org/fx"
|
|
|
|
"git.eeqj.de/sneak/upaas/internal/config"
|
|
"git.eeqj.de/sneak/upaas/internal/database"
|
|
"git.eeqj.de/sneak/upaas/internal/globals"
|
|
"git.eeqj.de/sneak/upaas/internal/logger"
|
|
"git.eeqj.de/sneak/upaas/internal/models"
|
|
)
|
|
|
|
// Test constants to satisfy goconst linter.
|
|
const (
|
|
testHash = "hash"
|
|
testBranch = "main"
|
|
testValue = "value"
|
|
testEventType = "push"
|
|
)
|
|
|
|
func setupTestDB(t *testing.T) (*database.Database, func()) {
|
|
t.Helper()
|
|
|
|
tmpDir := t.TempDir()
|
|
|
|
globals.SetAppname("upaas-test")
|
|
globals.SetVersion("test")
|
|
|
|
globalVars, err := globals.New(fx.Lifecycle(nil))
|
|
require.NoError(t, err)
|
|
|
|
logr, err := logger.New(fx.Lifecycle(nil), logger.Params{
|
|
Globals: globalVars,
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
cfg := &config.Config{
|
|
Port: 8080,
|
|
DataDir: tmpDir,
|
|
SessionSecret: "test-secret-key-at-least-32-chars",
|
|
}
|
|
|
|
testDB, err := database.New(fx.Lifecycle(nil), database.Params{
|
|
Logger: logr,
|
|
Config: cfg,
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
// t.TempDir() automatically cleans up after test
|
|
cleanup := func() {}
|
|
|
|
return testDB, cleanup
|
|
}
|
|
|
|
// User Tests.
|
|
|
|
func TestUserCreateAndFind(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
testDB, cleanup := setupTestDB(t)
|
|
defer cleanup()
|
|
|
|
user := models.NewUser(testDB)
|
|
user.Username = "testuser"
|
|
user.PasswordHash = "hashed_password"
|
|
|
|
err := user.Save(context.Background())
|
|
require.NoError(t, err)
|
|
assert.NotZero(t, user.ID)
|
|
assert.NotZero(t, user.CreatedAt)
|
|
|
|
found, err := models.FindUser(context.Background(), testDB, user.ID)
|
|
require.NoError(t, err)
|
|
require.NotNil(t, found)
|
|
assert.Equal(t, "testuser", found.Username)
|
|
}
|
|
|
|
func TestUserUpdate(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
testDB, cleanup := setupTestDB(t)
|
|
defer cleanup()
|
|
|
|
user := models.NewUser(testDB)
|
|
user.Username = "original"
|
|
user.PasswordHash = "hash1"
|
|
|
|
err := user.Save(context.Background())
|
|
require.NoError(t, err)
|
|
|
|
user.Username = "updated"
|
|
user.PasswordHash = "hash2"
|
|
|
|
err = user.Save(context.Background())
|
|
require.NoError(t, err)
|
|
|
|
found, err := models.FindUser(context.Background(), testDB, user.ID)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, "updated", found.Username)
|
|
assert.Equal(t, "hash2", found.PasswordHash)
|
|
}
|
|
|
|
func TestUserDelete(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
testDB, cleanup := setupTestDB(t)
|
|
defer cleanup()
|
|
|
|
user := models.NewUser(testDB)
|
|
user.Username = "todelete"
|
|
user.PasswordHash = testHash
|
|
|
|
err := user.Save(context.Background())
|
|
require.NoError(t, err)
|
|
|
|
err = user.Delete(context.Background())
|
|
require.NoError(t, err)
|
|
|
|
found, err := models.FindUser(context.Background(), testDB, user.ID)
|
|
require.NoError(t, err)
|
|
assert.Nil(t, found)
|
|
}
|
|
|
|
func TestUserFindByUsername(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
testDB, cleanup := setupTestDB(t)
|
|
defer cleanup()
|
|
|
|
user := models.NewUser(testDB)
|
|
user.Username = "findme"
|
|
user.PasswordHash = testHash
|
|
|
|
err := user.Save(context.Background())
|
|
require.NoError(t, err)
|
|
|
|
found, err := models.FindUserByUsername(
|
|
context.Background(), testDB, "findme",
|
|
)
|
|
require.NoError(t, err)
|
|
require.NotNil(t, found)
|
|
assert.Equal(t, user.ID, found.ID)
|
|
}
|
|
|
|
func TestUserFindByUsernameNotFound(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
testDB, cleanup := setupTestDB(t)
|
|
defer cleanup()
|
|
|
|
found, err := models.FindUserByUsername(
|
|
context.Background(), testDB, "nonexistent",
|
|
)
|
|
require.NoError(t, err)
|
|
assert.Nil(t, found)
|
|
}
|
|
|
|
func TestUserExists(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
t.Run("returns false when no users", func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
testDB, cleanup := setupTestDB(t)
|
|
defer cleanup()
|
|
|
|
exists, err := models.UserExists(context.Background(), testDB)
|
|
require.NoError(t, err)
|
|
assert.False(t, exists)
|
|
})
|
|
|
|
t.Run("returns true when user exists", func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
testDB, cleanup := setupTestDB(t)
|
|
defer cleanup()
|
|
|
|
user := models.NewUser(testDB)
|
|
user.Username = "admin"
|
|
user.PasswordHash = testHash
|
|
|
|
err := user.Save(context.Background())
|
|
require.NoError(t, err)
|
|
|
|
exists, err := models.UserExists(context.Background(), testDB)
|
|
require.NoError(t, err)
|
|
assert.True(t, exists)
|
|
})
|
|
}
|
|
|
|
// App Tests.
|
|
|
|
func TestAppCreateAndFind(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
testDB, cleanup := setupTestDB(t)
|
|
defer cleanup()
|
|
|
|
app := createTestApp(t, testDB)
|
|
assert.NotZero(t, app.CreatedAt)
|
|
|
|
found, err := models.FindApp(context.Background(), testDB, app.ID)
|
|
require.NoError(t, err)
|
|
require.NotNil(t, found)
|
|
assert.Equal(t, "test-app", found.Name)
|
|
assert.Equal(t, models.AppStatusPending, found.Status)
|
|
}
|
|
|
|
func TestAppUpdate(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
testDB, cleanup := setupTestDB(t)
|
|
defer cleanup()
|
|
|
|
app := createTestApp(t, testDB)
|
|
|
|
app.Name = "updated"
|
|
app.Status = models.AppStatusRunning
|
|
app.ContainerID = sql.NullString{String: "container123", Valid: true}
|
|
|
|
err := app.Save(context.Background())
|
|
require.NoError(t, err)
|
|
|
|
found, err := models.FindApp(context.Background(), testDB, app.ID)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, "updated", found.Name)
|
|
assert.Equal(t, models.AppStatusRunning, found.Status)
|
|
assert.Equal(t, "container123", found.ContainerID.String)
|
|
}
|
|
|
|
func TestAppDelete(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
testDB, cleanup := setupTestDB(t)
|
|
defer cleanup()
|
|
|
|
app := createTestApp(t, testDB)
|
|
|
|
err := app.Delete(context.Background())
|
|
require.NoError(t, err)
|
|
|
|
found, err := models.FindApp(context.Background(), testDB, app.ID)
|
|
require.NoError(t, err)
|
|
assert.Nil(t, found)
|
|
}
|
|
|
|
func TestAppFindByWebhookSecret(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
testDB, cleanup := setupTestDB(t)
|
|
defer cleanup()
|
|
|
|
app := createTestApp(t, testDB)
|
|
|
|
found, err := models.FindAppByWebhookSecret(
|
|
context.Background(), testDB, app.WebhookSecret,
|
|
)
|
|
require.NoError(t, err)
|
|
require.NotNil(t, found)
|
|
assert.Equal(t, app.ID, found.ID)
|
|
}
|
|
|
|
func TestAllApps(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
t.Run("returns empty list when no apps", func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
testDB, cleanup := setupTestDB(t)
|
|
defer cleanup()
|
|
|
|
apps, err := models.AllApps(context.Background(), testDB)
|
|
require.NoError(t, err)
|
|
assert.Empty(t, apps)
|
|
})
|
|
|
|
t.Run("returns apps ordered by name", func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
testDB, cleanup := setupTestDB(t)
|
|
defer cleanup()
|
|
|
|
names := []string{"zebra", "alpha", "mike"}
|
|
|
|
for idx, name := range names {
|
|
app := models.NewApp(testDB)
|
|
app.ID = name + "-id"
|
|
app.Name = name
|
|
app.RepoURL = "git@example.com:user/" + name + ".git"
|
|
app.Branch = testBranch
|
|
app.DockerfilePath = "Dockerfile"
|
|
app.WebhookSecret = "secret-" + strconv.Itoa(idx)
|
|
app.SSHPrivateKey = "private"
|
|
app.SSHPublicKey = "public"
|
|
|
|
err := app.Save(context.Background())
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
apps, err := models.AllApps(context.Background(), testDB)
|
|
require.NoError(t, err)
|
|
require.Len(t, apps, 3)
|
|
|
|
assert.Equal(t, "alpha", apps[0].Name)
|
|
assert.Equal(t, "mike", apps[1].Name)
|
|
assert.Equal(t, "zebra", apps[2].Name)
|
|
})
|
|
}
|
|
|
|
// EnvVar Tests.
|
|
|
|
func TestEnvVarCRUD(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
t.Run("creates and finds env vars", func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
testDB, cleanup := setupTestDB(t)
|
|
defer cleanup()
|
|
|
|
// Create app first.
|
|
app := createTestApp(t, testDB)
|
|
|
|
envVar := models.NewEnvVar(testDB)
|
|
envVar.AppID = app.ID
|
|
envVar.Key = "DATABASE_URL"
|
|
envVar.Value = "postgres://localhost/db"
|
|
|
|
err := envVar.Save(context.Background())
|
|
require.NoError(t, err)
|
|
assert.NotZero(t, envVar.ID)
|
|
|
|
envVars, err := models.FindEnvVarsByAppID(
|
|
context.Background(), testDB, app.ID,
|
|
)
|
|
require.NoError(t, err)
|
|
require.Len(t, envVars, 1)
|
|
assert.Equal(t, "DATABASE_URL", envVars[0].Key)
|
|
})
|
|
|
|
t.Run("deletes env var", func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
testDB, cleanup := setupTestDB(t)
|
|
defer cleanup()
|
|
|
|
app := createTestApp(t, testDB)
|
|
|
|
envVar := models.NewEnvVar(testDB)
|
|
envVar.AppID = app.ID
|
|
envVar.Key = "TO_DELETE"
|
|
envVar.Value = testValue
|
|
|
|
err := envVar.Save(context.Background())
|
|
require.NoError(t, err)
|
|
|
|
err = envVar.Delete(context.Background())
|
|
require.NoError(t, err)
|
|
|
|
envVars, err := models.FindEnvVarsByAppID(
|
|
context.Background(), testDB, app.ID,
|
|
)
|
|
require.NoError(t, err)
|
|
assert.Empty(t, envVars)
|
|
})
|
|
}
|
|
|
|
// Label Tests.
|
|
|
|
func TestLabelCRUD(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
t.Run("creates and finds labels", func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
testDB, cleanup := setupTestDB(t)
|
|
defer cleanup()
|
|
|
|
app := createTestApp(t, testDB)
|
|
|
|
label := models.NewLabel(testDB)
|
|
label.AppID = app.ID
|
|
label.Key = "traefik.enable"
|
|
label.Value = "true"
|
|
|
|
err := label.Save(context.Background())
|
|
require.NoError(t, err)
|
|
assert.NotZero(t, label.ID)
|
|
|
|
labels, err := models.FindLabelsByAppID(
|
|
context.Background(), testDB, app.ID,
|
|
)
|
|
require.NoError(t, err)
|
|
require.Len(t, labels, 1)
|
|
assert.Equal(t, "traefik.enable", labels[0].Key)
|
|
})
|
|
}
|
|
|
|
// Volume Tests.
|
|
|
|
func TestVolumeCRUD(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
t.Run("creates and finds volumes", func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
testDB, cleanup := setupTestDB(t)
|
|
defer cleanup()
|
|
|
|
app := createTestApp(t, testDB)
|
|
|
|
volume := models.NewVolume(testDB)
|
|
volume.AppID = app.ID
|
|
volume.HostPath = "/data/app"
|
|
volume.ContainerPath = "/app/data"
|
|
volume.ReadOnly = true
|
|
|
|
err := volume.Save(context.Background())
|
|
require.NoError(t, err)
|
|
assert.NotZero(t, volume.ID)
|
|
|
|
volumes, err := models.FindVolumesByAppID(
|
|
context.Background(), testDB, app.ID,
|
|
)
|
|
require.NoError(t, err)
|
|
require.Len(t, volumes, 1)
|
|
assert.Equal(t, "/data/app", volumes[0].HostPath)
|
|
assert.True(t, volumes[0].ReadOnly)
|
|
})
|
|
}
|
|
|
|
// WebhookEvent Tests.
|
|
|
|
func TestWebhookEventCRUD(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
t.Run("creates and finds webhook events", func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
testDB, cleanup := setupTestDB(t)
|
|
defer cleanup()
|
|
|
|
app := createTestApp(t, testDB)
|
|
|
|
event := models.NewWebhookEvent(testDB)
|
|
event.AppID = app.ID
|
|
event.EventType = testEventType
|
|
event.Branch = testBranch
|
|
event.CommitSHA = sql.NullString{String: "abc123", Valid: true}
|
|
event.Matched = true
|
|
|
|
err := event.Save(context.Background())
|
|
require.NoError(t, err)
|
|
assert.NotZero(t, event.ID)
|
|
|
|
events, err := models.FindWebhookEventsByAppID(
|
|
context.Background(), testDB, app.ID, 10,
|
|
)
|
|
require.NoError(t, err)
|
|
require.Len(t, events, 1)
|
|
assert.Equal(t, "push", events[0].EventType)
|
|
assert.True(t, events[0].Matched)
|
|
})
|
|
}
|
|
|
|
// Deployment Tests.
|
|
|
|
func TestDeploymentCreateAndFind(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
testDB, cleanup := setupTestDB(t)
|
|
defer cleanup()
|
|
|
|
app := createTestApp(t, testDB)
|
|
|
|
deployment := models.NewDeployment(testDB)
|
|
deployment.AppID = app.ID
|
|
deployment.CommitSHA = sql.NullString{String: "abc123def456", Valid: true}
|
|
deployment.Status = models.DeploymentStatusBuilding
|
|
|
|
err := deployment.Save(context.Background())
|
|
require.NoError(t, err)
|
|
assert.NotZero(t, deployment.ID)
|
|
assert.NotZero(t, deployment.StartedAt)
|
|
|
|
found, err := models.FindDeployment(context.Background(), testDB, deployment.ID)
|
|
require.NoError(t, err)
|
|
require.NotNil(t, found)
|
|
assert.Equal(t, models.DeploymentStatusBuilding, found.Status)
|
|
}
|
|
|
|
func TestDeploymentAppendLog(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
testDB, cleanup := setupTestDB(t)
|
|
defer cleanup()
|
|
|
|
app := createTestApp(t, testDB)
|
|
|
|
deployment := models.NewDeployment(testDB)
|
|
deployment.AppID = app.ID
|
|
deployment.Status = models.DeploymentStatusBuilding
|
|
|
|
err := deployment.Save(context.Background())
|
|
require.NoError(t, err)
|
|
|
|
err = deployment.AppendLog(context.Background(), "Building image...")
|
|
require.NoError(t, err)
|
|
|
|
err = deployment.AppendLog(context.Background(), "Image built successfully")
|
|
require.NoError(t, err)
|
|
|
|
found, err := models.FindDeployment(context.Background(), testDB, deployment.ID)
|
|
require.NoError(t, err)
|
|
assert.Contains(t, found.Logs.String, "Building image...")
|
|
assert.Contains(t, found.Logs.String, "Image built successfully")
|
|
}
|
|
|
|
func TestDeploymentMarkFinished(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
testDB, cleanup := setupTestDB(t)
|
|
defer cleanup()
|
|
|
|
app := createTestApp(t, testDB)
|
|
|
|
deployment := models.NewDeployment(testDB)
|
|
deployment.AppID = app.ID
|
|
deployment.Status = models.DeploymentStatusBuilding
|
|
|
|
err := deployment.Save(context.Background())
|
|
require.NoError(t, err)
|
|
|
|
err = deployment.MarkFinished(context.Background(), models.DeploymentStatusSuccess)
|
|
require.NoError(t, err)
|
|
|
|
found, err := models.FindDeployment(context.Background(), testDB, deployment.ID)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, models.DeploymentStatusSuccess, found.Status)
|
|
assert.True(t, found.FinishedAt.Valid)
|
|
}
|
|
|
|
func TestDeploymentFindByAppID(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
testDB, cleanup := setupTestDB(t)
|
|
defer cleanup()
|
|
|
|
app := createTestApp(t, testDB)
|
|
|
|
for idx := range 5 {
|
|
deploy := models.NewDeployment(testDB)
|
|
deploy.AppID = app.ID
|
|
deploy.Status = models.DeploymentStatusSuccess
|
|
deploy.CommitSHA = sql.NullString{
|
|
String: "commit" + strconv.Itoa(idx),
|
|
Valid: true,
|
|
}
|
|
|
|
err := deploy.Save(context.Background())
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
deployments, err := models.FindDeploymentsByAppID(context.Background(), testDB, app.ID, 3)
|
|
require.NoError(t, err)
|
|
assert.Len(t, deployments, 3)
|
|
}
|
|
|
|
func TestDeploymentFindLatest(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
testDB, cleanup := setupTestDB(t)
|
|
defer cleanup()
|
|
|
|
app := createTestApp(t, testDB)
|
|
|
|
for idx := range 3 {
|
|
deploy := models.NewDeployment(testDB)
|
|
deploy.AppID = app.ID
|
|
deploy.CommitSHA = sql.NullString{
|
|
String: "commit" + strconv.Itoa(idx),
|
|
Valid: true,
|
|
}
|
|
deploy.Status = models.DeploymentStatusSuccess
|
|
|
|
err := deploy.Save(context.Background())
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
latest, err := models.LatestDeploymentForApp(context.Background(), testDB, app.ID)
|
|
require.NoError(t, err)
|
|
require.NotNil(t, latest)
|
|
assert.Equal(t, "commit2", latest.CommitSHA.String)
|
|
}
|
|
|
|
// App Helper Methods Tests.
|
|
|
|
func TestAppGetEnvVars(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
testDB, cleanup := setupTestDB(t)
|
|
defer cleanup()
|
|
|
|
app := createTestApp(t, testDB)
|
|
|
|
env1 := models.NewEnvVar(testDB)
|
|
env1.AppID = app.ID
|
|
env1.Key = "KEY1"
|
|
env1.Value = "value1"
|
|
_ = env1.Save(context.Background())
|
|
|
|
env2 := models.NewEnvVar(testDB)
|
|
env2.AppID = app.ID
|
|
env2.Key = "KEY2"
|
|
env2.Value = "value2"
|
|
_ = env2.Save(context.Background())
|
|
|
|
envVars, err := app.GetEnvVars(context.Background())
|
|
require.NoError(t, err)
|
|
assert.Len(t, envVars, 2)
|
|
}
|
|
|
|
func TestAppGetLabels(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
testDB, cleanup := setupTestDB(t)
|
|
defer cleanup()
|
|
|
|
app := createTestApp(t, testDB)
|
|
|
|
label := models.NewLabel(testDB)
|
|
label.AppID = app.ID
|
|
label.Key = "label.key"
|
|
label.Value = "label.value"
|
|
_ = label.Save(context.Background())
|
|
|
|
labels, err := app.GetLabels(context.Background())
|
|
require.NoError(t, err)
|
|
assert.Len(t, labels, 1)
|
|
}
|
|
|
|
func TestAppGetVolumes(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
testDB, cleanup := setupTestDB(t)
|
|
defer cleanup()
|
|
|
|
app := createTestApp(t, testDB)
|
|
|
|
vol := models.NewVolume(testDB)
|
|
vol.AppID = app.ID
|
|
vol.HostPath = "/host"
|
|
vol.ContainerPath = "/container"
|
|
_ = vol.Save(context.Background())
|
|
|
|
volumes, err := app.GetVolumes(context.Background())
|
|
require.NoError(t, err)
|
|
assert.Len(t, volumes, 1)
|
|
}
|
|
|
|
func TestAppGetDeployments(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
testDB, cleanup := setupTestDB(t)
|
|
defer cleanup()
|
|
|
|
app := createTestApp(t, testDB)
|
|
|
|
deploy := models.NewDeployment(testDB)
|
|
deploy.AppID = app.ID
|
|
deploy.Status = models.DeploymentStatusSuccess
|
|
_ = deploy.Save(context.Background())
|
|
|
|
deployments, err := app.GetDeployments(context.Background(), 10)
|
|
require.NoError(t, err)
|
|
assert.Len(t, deployments, 1)
|
|
}
|
|
|
|
func TestAppGetWebhookEvents(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
testDB, cleanup := setupTestDB(t)
|
|
defer cleanup()
|
|
|
|
app := createTestApp(t, testDB)
|
|
|
|
event := models.NewWebhookEvent(testDB)
|
|
event.AppID = app.ID
|
|
event.EventType = testEventType
|
|
event.Branch = testBranch
|
|
event.Matched = true
|
|
_ = event.Save(context.Background())
|
|
|
|
events, err := app.GetWebhookEvents(context.Background(), 10)
|
|
require.NoError(t, err)
|
|
assert.Len(t, events, 1)
|
|
}
|
|
|
|
// Cascade Delete Tests.
|
|
|
|
//nolint:funlen // Test function with many assertions - acceptable for integration tests
|
|
func TestCascadeDelete(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
t.Run("deleting app cascades to related records", func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
testDB, cleanup := setupTestDB(t)
|
|
defer cleanup()
|
|
|
|
app := createTestApp(t, testDB)
|
|
|
|
// Create related records.
|
|
env := models.NewEnvVar(testDB)
|
|
env.AppID = app.ID
|
|
env.Key = "KEY"
|
|
env.Value = "value"
|
|
_ = env.Save(context.Background())
|
|
|
|
label := models.NewLabel(testDB)
|
|
label.AppID = app.ID
|
|
label.Key = "key"
|
|
label.Value = "value"
|
|
_ = label.Save(context.Background())
|
|
|
|
vol := models.NewVolume(testDB)
|
|
vol.AppID = app.ID
|
|
vol.HostPath = "/host"
|
|
vol.ContainerPath = "/container"
|
|
_ = vol.Save(context.Background())
|
|
|
|
event := models.NewWebhookEvent(testDB)
|
|
event.AppID = app.ID
|
|
event.EventType = testEventType
|
|
event.Branch = testBranch
|
|
event.Matched = true
|
|
_ = event.Save(context.Background())
|
|
|
|
deploy := models.NewDeployment(testDB)
|
|
deploy.AppID = app.ID
|
|
deploy.Status = models.DeploymentStatusSuccess
|
|
_ = deploy.Save(context.Background())
|
|
|
|
// Delete app.
|
|
err := app.Delete(context.Background())
|
|
require.NoError(t, err)
|
|
|
|
// Verify cascades.
|
|
envVars, _ := models.FindEnvVarsByAppID(
|
|
context.Background(), testDB, app.ID,
|
|
)
|
|
assert.Empty(t, envVars)
|
|
|
|
labels, _ := models.FindLabelsByAppID(
|
|
context.Background(), testDB, app.ID,
|
|
)
|
|
assert.Empty(t, labels)
|
|
|
|
volumes, _ := models.FindVolumesByAppID(
|
|
context.Background(), testDB, app.ID,
|
|
)
|
|
assert.Empty(t, volumes)
|
|
|
|
events, _ := models.FindWebhookEventsByAppID(
|
|
context.Background(), testDB, app.ID, 10,
|
|
)
|
|
assert.Empty(t, events)
|
|
|
|
deployments, _ := models.FindDeploymentsByAppID(
|
|
context.Background(), testDB, app.ID, 10,
|
|
)
|
|
assert.Empty(t, deployments)
|
|
})
|
|
}
|
|
|
|
// Helper function to create a test app.
|
|
func createTestApp(t *testing.T, testDB *database.Database) *models.App {
|
|
t.Helper()
|
|
|
|
app := models.NewApp(testDB)
|
|
app.ID = "test-app-" + t.Name()
|
|
app.Name = "test-app"
|
|
app.RepoURL = "git@example.com:user/repo.git"
|
|
app.Branch = testBranch
|
|
app.DockerfilePath = "Dockerfile"
|
|
app.WebhookSecret = "secret-" + t.Name()
|
|
app.SSHPrivateKey = "private"
|
|
app.SSHPublicKey = "public"
|
|
|
|
err := app.Save(context.Background())
|
|
require.NoError(t, err)
|
|
|
|
return app
|
|
}
|