Add server-side app name validation (closes #37) #49
No reviewers
Labels
No Milestone
No project
No Assignees
2 Participants
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: sneak/upaas#49
Loading…
Reference in New Issue
Block a user
No description provided.
Delete Branch ":fix/server-side-app-name-validation"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Adds server-side validation for app names in both
HandleAppCreateandHandleAppUpdate, matching the client-side HTML pattern[a-z0-9-]+.Validation Rules
Changes
internal/handlers/app_name_validation.go—validateAppName()with sentinel errorsinternal/handlers/app_name_validation_test.go— 22 test cases covering valid names, length limits, invalid characters, path traversal, unicode, etc.internal/handlers/app.go— validation added toHandleAppCreateandHandleAppUpdateTest Results
All tests pass. Lint clean (only pre-existing
testpackageissue intail_validation_test.go).Closes #37
Test Results\n```\n# git.eeqj.de/sneak/upaas/internal/service/webhook.test
=== RUN TestHashWebhookSecret
=== PAUSE TestHashWebhookSecret
=== CONT TestHashWebhookSecret
--- PASS: TestHashWebhookSecret (0.00s)
PASS
ok git.eeqj.de/sneak/upaas/internal/database (cached) coverage: 1.6% of statements
--- PASS: TestValidBranchRegex (0.00s)
--- PASS: TestValidCommitSHARegex (0.00s)
--- PASS: TestCloneRepoRejectsInjection (0.00s)
--- PASS: TestCloneRepoRejectsInjection/shell_injection_in_branch (0.00s)
--- PASS: TestCloneRepoRejectsInjection/injection_in_commitSHA (0.00s)
--- PASS: TestCloneRepoRejectsInjection/valid_branch_no_SHA_passes_validation_(hit_NotConnected) (0.00s)
--- PASS: TestCloneRepoRejectsInjection/short_SHA_rejected (0.00s)
--- PASS: TestCloneRepoRejectsInjection/command_substitution_in_branch (0.00s)
--- PASS: TestCloneRepoRejectsInjection/backtick_injection_in_branch (0.00s)
--- PASS: TestCloneRepoRejectsInjection/valid_inputs_pass_validation_(hit_NotConnected) (0.00s)
PASS
ok git.eeqj.de/sneak/upaas/internal/docker (cached) coverage: 2.8% of statements
=== RUN TestHandleWebhookRejectsOversizedBody
=== PAUSE TestHandleWebhookRejectsOversizedBody
=== RUN TestHandleWebhookReturns404ForUnknownSecret
=== PAUSE TestHandleWebhookReturns404ForUnknownSecret
=== RUN TestHandleWebhookProcessesValidWebhook
=== PAUSE TestHandleWebhookProcessesValidWebhook
=== CONT TestHandleWebhookReturns404ForUnknownSecret
=== CONT TestHandleWebhookRejectsOversizedBody
=== CONT TestHandleWebhookProcessesValidWebhook
{"time":"2026-02-15T22:05:54.950155-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/database.(*Database).connect","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/database/database.go","line":155},"msg":"database connected","path":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/TestHandleWebhookReturns404ForUnknownSecret3971019389/001/upaas.db"}
--- PASS: TestSanitizeTail (0.00s)
--- PASS: TestSanitizeTail/empty_uses_default (0.00s)
--- PASS: TestSanitizeTail/all_keyword_uses_default (0.00s)
--- PASS: TestSanitizeTail/non-numeric_uses_default (0.00s)
--- PASS: TestSanitizeTail/valid_max_boundary (0.00s)
--- PASS: TestSanitizeTail/negative_uses_default (0.00s)
--- PASS: TestSanitizeTail/zero_uses_default (0.00s)
--- PASS: TestSanitizeTail/valid_small_number (0.00s)
--- PASS: TestSanitizeTail/one_is_valid (0.00s)
--- PASS: TestSanitizeTail/exceeds_max_clamped (0.00s)
--- PASS: TestSanitizeTail/very_large_clamped (0.00s)
--- PASS: TestSanitizeTail/float_uses_default (0.00s)
--- PASS: TestParsePortValues (0.00s)
--- PASS: TestParsePortValues/both_ports_above_65535 (0.00s)
--- PASS: TestParsePortValues/host_port_above_65535 (0.00s)
--- PASS: TestParsePortValues/container_port_above_65535 (0.00s)
--- PASS: TestParsePortValues/valid_ports (0.00s)
--- PASS: TestParsePortValues/non-numeric (0.00s)
--- PASS: TestParsePortValues/port_65535 (0.00s)
--- PASS: TestParsePortValues/negative_port (0.00s)
--- PASS: TestParsePortValues/zero_port (0.00s)
--- PASS: TestParsePortValues/port_1 (0.00s)
--- PASS: TestValidateAppName (0.00s)
--- PASS: TestValidateAppName/valid_simple (0.00s)
--- PASS: TestValidateAppName/special_chars (0.00s)
--- PASS: TestValidateAppName/unicode (0.00s)
--- PASS: TestValidateAppName/dot (0.00s)
--- PASS: TestValidateAppName/slash (0.00s)
--- PASS: TestValidateAppName/empty (0.00s)
--- PASS: TestValidateAppName/starts_with_hyphen (0.00s)
--- PASS: TestValidateAppName/valid_with_hyphen (0.00s)
--- PASS: TestValidateAppName/uppercase (0.00s)
--- PASS: TestValidateAppName/path_traversal (0.00s)
--- PASS: TestValidateAppName/valid_complex (0.00s)
--- PASS: TestValidateAppName/too_long (0.00s)
--- PASS: TestValidateAppName/valid_two_chars (0.00s)
--- PASS: TestValidateAppName/valid_all_numbers (0.00s)
--- PASS: TestValidateAppName/64_chars (0.00s)
--- PASS: TestValidateAppName/exactly_63_chars (0.00s)
--- PASS: TestValidateAppName/spaces (0.00s)
--- PASS: TestValidateAppName/single_char (0.00s)
--- PASS: TestValidateAppName/ends_with_hyphen (0.00s)
--- PASS: TestValidateAppName/valid_with_numbers (0.00s)
--- PASS: TestValidateAppName/underscore (0.00s)
{"time":"2026-02-15T22:05:54.954288-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/database.(*Database).connect","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/database/database.go","line":155},"msg":"database connected","path":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/TestHandleWebhookRejectsOversizedBody309039733/001/upaas.db"}
{"time":"2026-02-15T22:05:54.955083-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/database.(*Database).connect","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/database/database.go","line":155},"msg":"database connected","path":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/TestHandleWebhookProcessesValidWebhook891577419/001/upaas.db"}
{"time":"2026-02-15T22:05:54.984448-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/database.(*Database).migrate","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/database/migrations.go","line":62},"msg":"migration applied","migration":"005_add_webhook_secret_hash.sql"}
{"time":"2026-02-15T22:05:54.985924-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/database.(*Database).migrate","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/database/migrations.go","line":62},"msg":"migration applied","migration":"005_add_webhook_secret_hash.sql"}
{"time":"2026-02-15T22:05:54.986311-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/database.(*Database).migrate","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/database/migrations.go","line":62},"msg":"migration applied","migration":"005_add_webhook_secret_hash.sql"}
{"time":"2026-02-15T22:05:54.986794-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/database.(*Database).migrate","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/database/migrations.go","line":62},"msg":"migration applied","migration":"005_add_webhook_secret_hash.sql"}
{"time":"2026-02-15T22:05:54.98815-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/database.(*Database).migrate","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/database/migrations.go","line":62},"msg":"migration applied","migration":"005_add_webhook_secret_hash.sql"}
{"time":"2026-02-15T22:05:54.988177-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/database.(*Database).migrate","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/database/migrations.go","line":62},"msg":"migration applied","migration":"005_add_webhook_secret_hash.sql"}
{"time":"2026-02-15T22:05:54.988213-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/database.(*Database).migrate","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/database/migrations.go","line":62},"msg":"migration applied","migration":"005_add_webhook_secret_hash.sql"}
{"time":"2026-02-15T22:05:54.989159-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/database.(*Database).migrate","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/database/migrations.go","line":62},"msg":"migration applied","migration":"005_add_webhook_secret_hash.sql"}
{"time":"2026-02-15T22:05:54.989695-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/database.(*Database).migrate","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/database/migrations.go","line":62},"msg":"migration applied","migration":"005_add_webhook_secret_hash.sql"}
--- PASS: TestHandleWebhookReturns404ForUnknownSecret (0.04s)
{"time":"2026-02-15T22:05:54.990459-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/database.(*Database).migrate","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/database/migrations.go","line":62},"msg":"migration applied","migration":"005_add_webhook_secret_hash.sql"}
{"time":"2026-02-15T22:05:54.990626-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/database.(*Database).migrate","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/database/migrations.go","line":62},"msg":"migration applied","migration":"005_add_webhook_secret_hash.sql"}
{"time":"2026-02-15T22:05:54.990783-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/database.(*Database).migrate","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/database/migrations.go","line":62},"msg":"migration applied","migration":"005_add_webhook_secret_hash.sql"}
{"time":"2026-02-15T22:05:54.99231-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/database.(*Database).migrate","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/database/migrations.go","line":62},"msg":"migration applied","migration":"005_add_webhook_secret_hash.sql"}
{"time":"2026-02-15T22:05:54.992322-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/database.(*Database).migrate","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/database/migrations.go","line":62},"msg":"migration applied","migration":"005_add_webhook_secret_hash.sql"}
{"time":"2026-02-15T22:05:54.99231-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/database.(*Database).migrate","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/database/migrations.go","line":62},"msg":"migration applied","migration":"005_add_webhook_secret_hash.sql"}
--- PASS: TestHandleSetupPOSTRejectsMismatchedPasswords (0.05s)
--- PASS: TestHandleSetupPOSTRejectsShortPassword (0.05s)
{"time":"2026-02-15T22:05:54.992533-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/database.(*Database).migrate","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/database/migrations.go","line":62},"msg":"migration applied","migration":"005_add_webhook_secret_hash.sql"}
{"time":"2026-02-15T22:05:54.99254-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/database.(*Database).migrate","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/database/migrations.go","line":62},"msg":"migration applied","migration":"005_add_webhook_secret_hash.sql"}
--- PASS: TestHandleSetupPOSTRejectsEmptyUsername (0.05s)
--- PASS: TestHandleSetupGET (0.00s)
--- PASS: TestHandleSetupGET/renders_setup_page (0.04s)
{"time":"2026-02-15T22:05:54.992798-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/database.(*Database).migrate","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/database/migrations.go","line":62},"msg":"migration applied","migration":"005_add_webhook_secret_hash.sql"}
--- PASS: TestHandleHealthCheck (0.00s)
--- PASS: TestHandleHealthCheck/returns_health_check_response (0.04s)
--- PASS: TestHandleAppNew (0.00s)
--- PASS: TestHandleAppNew/renders_new_app_form (0.04s)
{"time":"2026-02-15T22:05:54.993398-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/service/app.(*Service).CreateApp","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/service/app/app.go","line":108},"msg":"app created","id":"01KHJGWCDG110Z2AJZWNNA43DX","name":"webhook-test-app"}
--- PASS: TestHandleLoginGET (0.00s)
--- PASS: TestHandleLoginGET/renders_login_page (0.04s)
--- PASS: TestHandleDashboard (0.00s)
--- PASS: TestHandleDashboard/renders_dashboard_with_app_list (0.04s)
{"time":"2026-02-15T22:05:54.993861-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/service/webhook.(*Service).HandleWebhook","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/service/webhook/webhook.go","line":82},"msg":"processing webhook","app":"webhook-test-app","event":"push"}
{"time":"2026-02-15T22:05:54.994236-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/service/webhook.(*Service).HandleWebhook","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/service/webhook/webhook.go","line":117},"msg":"webhook event recorded","app":"webhook-test-app","branch":"main","matched":true,"commit":"abc123"}
--- PASS: TestDeletePortOwnershipVerification (0.05s)
{"time":"2026-02-15T22:05:54.995584-08:00","level":"ERROR","source":{"function":"git.eeqj.de/sneak/upaas/internal/service/deploy.(*Service).failDeployment","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/service/deploy/deploy.go","line":954},"msg":"deployment failed","app":"webhook-test-app","error":"failed to clone repo: invalid commit SHA: "abc123""}
--- PASS: TestDeleteVolumeOwnershipVerification (0.05s)
--- PASS: TestDeleteLabelOwnershipVerification (0.05s)
--- PASS: TestDeleteEnvVarOwnershipVerification (0.05s)
{"time":"2026-02-15T22:05:54.996188-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/service/deploy.(*Service).writeLogsToFile","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/service/deploy/deploy.go","line":991},"msg":"wrote deployment logs to file","path":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/TestHandleWebhookProcessesValidWebhook891577419/001/logs/inference.local/webhook-test-app/webhook-test-app_abc123_20260216T060554Z.log.txt"}
{"time":"2026-02-15T22:05:54.996429-08:00","level":"ERROR","source":{"function":"git.eeqj.de/sneak/upaas/internal/service/webhook.(*Service).triggerDeployment.func1","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/service/webhook/webhook.go","line":148},"msg":"deployment failed","error":"failed to clone repo: invalid commit SHA: "abc123"","app":"webhook-test-app"}
{"time":"2026-02-15T22:05:54.997233-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/service/webhook.(*Service).HandleWebhook","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/service/webhook/webhook.go","line":82},"msg":"processing webhook","app":"oversize-test-app","event":"push"}
{"time":"2026-02-15T22:05:54.99728-08:00","level":"WARN","source":{"function":"git.eeqj.de/sneak/upaas/internal/service/webhook.(*Service).HandleWebhook","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/service/webhook/webhook.go","line":89},"msg":"failed to parse webhook payload","error":"invalid character 'x' looking for beginning of value"}
{"time":"2026-02-15T22:05:55.000178-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/service/webhook.(*Service).HandleWebhook","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/service/webhook/webhook.go","line":117},"msg":"webhook event recorded","app":"oversize-test-app","branch":"","matched":false,"commit":""}
--- PASS: TestHandleWebhookRejectsOversizedBody (0.05s)
--- PASS: TestHandleSetupPOSTCreatesUserAndRedirects (0.15s)
--- PASS: TestHandleWebhookProcessesValidWebhook (0.15s)
--- PASS: TestHandleLoginPOSTRejectsInvalidCredentials (0.25s)
--- PASS: TestHandleLoginPOSTAuthenticatesValidCredentials (0.25s)
PASS
ok git.eeqj.de/sneak/upaas/internal/handlers (cached) coverage: 23.1% of statements
--- PASS: TestLoginRateLimitAllowsUpToBurst (0.00s)
--- PASS: TestLoginRateLimitIsolatesIPs (0.00s)
--- PASS: TestLoginRateLimitReturns429Body (0.00s)
--- PASS: TestIPLimiterEvictsStaleEntries (0.00s)
--- PASS: TestRealIP (0.00s)
--- PASS: TestRealIP/X-Forwarded-For_used_when_no_X-Real-IP (0.00s)
--- PASS: TestRealIP/empty_X-Real-IP_falls_through_to_XFF (0.00s)
--- PASS: TestRealIP/falls_back_to_RemoteAddr (0.00s)
--- PASS: TestRealIP/X-Real-IP_with_whitespace (0.00s)
--- PASS: TestRealIP/X-Forwarded-For_with_whitespace (0.00s)
--- PASS: TestRealIP/X-Real-IP_takes_priority (0.00s)
--- PASS: TestRealIP/RemoteAddr_without_port (0.00s)
--- PASS: TestRealIP/X-Forwarded-For_single_IP (0.00s)
PASS
ok git.eeqj.de/sneak/upaas/internal/middleware (cached) coverage: 47.1% of statements
=== RUN TestAppFindByWebhookSecret
=== PAUSE TestAppFindByWebhookSecret
=== RUN TestWebhookEventCRUD
=== PAUSE TestWebhookEventCRUD
=== RUN TestAppGetWebhookEvents
=== PAUSE TestAppGetWebhookEvents
=== CONT TestAppGetWebhookEvents
=== CONT TestAppFindByWebhookSecret
=== CONT TestWebhookEventCRUD
=== RUN TestWebhookEventCRUD/creates_and_finds_webhook_events
=== PAUSE TestWebhookEventCRUD/creates_and_finds_webhook_events
=== CONT TestWebhookEventCRUD/creates_and_finds_webhook_events
{"time":"2026-02-15T22:03:31.394221-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/database.(*Database).connect","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/database/database.go","line":155},"msg":"database connected","path":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/TestAppFindByWebhookSecret125405549/001/upaas.db"}
{"time":"2026-02-15T22:03:31.394989-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/database.(*Database).connect","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/database/database.go","line":155},"msg":"database connected","path":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/TestAppGetWebhookEvents3272892269/001/upaas.db"}
{"time":"2026-02-15T22:03:31.407834-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/database.(*Database).connect","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/database/database.go","line":155},"msg":"database connected","path":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/TestWebhookEventCRUDcreates_and_finds_webhook_events3805417030/001/upaas.db"}
{"time":"2026-02-15T22:03:31.448032-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/database.(*Database).migrate","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/database/migrations.go","line":62},"msg":"migration applied","migration":"005_add_webhook_secret_hash.sql"}
{"time":"2026-02-15T22:03:31.448454-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/database.(*Database).migrate","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/database/migrations.go","line":62},"msg":"migration applied","migration":"005_add_webhook_secret_hash.sql"}
--- PASS: TestUserFindByUsernameNotFound (0.07s)
{"time":"2026-02-15T22:03:31.449682-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/database.(*Database).migrate","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/database/migrations.go","line":62},"msg":"migration applied","migration":"005_add_webhook_secret_hash.sql"}
--- PASS: TestUserUpdate (0.07s)
{"time":"2026-02-15T22:03:31.452617-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/database.(*Database).migrate","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/database/migrations.go","line":62},"msg":"migration applied","migration":"005_add_webhook_secret_hash.sql"}
{"time":"2026-02-15T22:03:31.45328-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/database.(*Database).migrate","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/database/migrations.go","line":62},"msg":"migration applied","migration":"005_add_webhook_secret_hash.sql"}
--- PASS: TestAppFindByWebhookSecret (0.07s)
{"time":"2026-02-15T22:03:31.456092-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/database.(*Database).migrate","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/database/migrations.go","line":62},"msg":"migration applied","migration":"005_add_webhook_secret_hash.sql"}
{"time":"2026-02-15T22:03:31.456628-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/database.(*Database).migrate","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/database/migrations.go","line":62},"msg":"migration applied","migration":"005_add_webhook_secret_hash.sql"}
{"time":"2026-02-15T22:03:31.457018-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/database.(*Database).migrate","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/database/migrations.go","line":62},"msg":"migration applied","migration":"005_add_webhook_secret_hash.sql"}
--- PASS: TestDeploymentCreateAndFind (0.07s)
--- PASS: TestDeploymentMarkFinished (0.08s)
--- PASS: TestWebhookEventCRUD (0.00s)
--- PASS: TestWebhookEventCRUD/creates_and_finds_webhook_events (0.07s)
{"time":"2026-02-15T22:03:31.459657-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/database.(*Database).migrate","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/database/migrations.go","line":62},"msg":"migration applied","migration":"005_add_webhook_secret_hash.sql"}
{"time":"2026-02-15T22:03:31.459931-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/database.(*Database).migrate","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/database/migrations.go","line":62},"msg":"migration applied","migration":"005_add_webhook_secret_hash.sql"}
{"time":"2026-02-15T22:03:31.460332-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/database.(*Database).migrate","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/database/migrations.go","line":62},"msg":"migration applied","migration":"005_add_webhook_secret_hash.sql"}
{"time":"2026-02-15T22:03:31.460638-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/database.(*Database).migrate","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/database/migrations.go","line":62},"msg":"migration applied","migration":"005_add_webhook_secret_hash.sql"}
{"time":"2026-02-15T22:03:31.460769-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/database.(*Database).migrate","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/database/migrations.go","line":62},"msg":"migration applied","migration":"005_add_webhook_secret_hash.sql"}
{"time":"2026-02-15T22:03:31.460935-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/database.(*Database).migrate","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/database/migrations.go","line":62},"msg":"migration applied","migration":"005_add_webhook_secret_hash.sql"}
{"time":"2026-02-15T22:03:31.461136-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/database.(*Database).migrate","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/database/migrations.go","line":62},"msg":"migration applied","migration":"005_add_webhook_secret_hash.sql"}
--- PASS: TestVolumeCRUD (0.00s)
--- PASS: TestVolumeCRUD/creates_and_finds_volumes (0.07s)
--- PASS: TestAllApps (0.00s)
--- PASS: TestAllApps/returns_apps_ordered_by_name (0.07s)
--- PASS: TestAllApps/returns_empty_list_when_no_apps (0.07s)
{"time":"2026-02-15T22:03:31.462301-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/database.(*Database).migrate","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/database/migrations.go","line":62},"msg":"migration applied","migration":"005_add_webhook_secret_hash.sql"}
{"time":"2026-02-15T22:03:31.462413-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/database.(*Database).migrate","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/database/migrations.go","line":62},"msg":"migration applied","migration":"005_add_webhook_secret_hash.sql"}
--- PASS: TestDeploymentFindByAppID (0.08s)
{"time":"2026-02-15T22:03:31.46377-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/database.(*Database).migrate","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/database/migrations.go","line":62},"msg":"migration applied","migration":"005_add_webhook_secret_hash.sql"}
{"time":"2026-02-15T22:03:31.463853-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/database.(*Database).migrate","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/database/migrations.go","line":62},"msg":"migration applied","migration":"005_add_webhook_secret_hash.sql"}
{"time":"2026-02-15T22:03:31.46404-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/database.(*Database).migrate","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/database/migrations.go","line":62},"msg":"migration applied","migration":"005_add_webhook_secret_hash.sql"}
{"time":"2026-02-15T22:03:31.464795-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/database.(*Database).migrate","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/database/migrations.go","line":62},"msg":"migration applied","migration":"005_add_webhook_secret_hash.sql"}
--- PASS: TestLabelCRUD (0.00s)
--- PASS: TestLabelCRUD/creates_and_finds_labels (0.08s)
--- PASS: TestUserCreateAndFind (0.08s)
--- PASS: TestAppGetVolumes (0.08s)
{"time":"2026-02-15T22:03:31.465194-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/database.(*Database).migrate","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/database/migrations.go","line":62},"msg":"migration applied","migration":"005_add_webhook_secret_hash.sql"}
{"time":"2026-02-15T22:03:31.465239-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/database.(*Database).migrate","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/database/migrations.go","line":62},"msg":"migration applied","migration":"005_add_webhook_secret_hash.sql"}
--- PASS: TestAppGetEnvVars (0.08s)
--- PASS: TestDeploymentAppendLog (0.08s)
{"time":"2026-02-15T22:03:31.465544-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/database.(*Database).migrate","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/database/migrations.go","line":62},"msg":"migration applied","migration":"005_add_webhook_secret_hash.sql"}
--- PASS: TestAppGetWebhookEvents (0.08s)
{"time":"2026-02-15T22:03:31.46605-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/database.(*Database).migrate","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/database/migrations.go","line":62},"msg":"migration applied","migration":"005_add_webhook_secret_hash.sql"}
{"time":"2026-02-15T22:03:31.466478-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/database.(*Database).migrate","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/database/migrations.go","line":62},"msg":"migration applied","migration":"005_add_webhook_secret_hash.sql"}
{"time":"2026-02-15T22:03:31.46656-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/database.(*Database).migrate","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/database/migrations.go","line":62},"msg":"migration applied","migration":"005_add_webhook_secret_hash.sql"}
{"time":"2026-02-15T22:03:31.466678-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/database.(*Database).migrate","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/database/migrations.go","line":62},"msg":"migration applied","migration":"005_add_webhook_secret_hash.sql"}
--- PASS: TestUserDelete (0.08s)
--- PASS: TestAppUpdate (0.08s)
{"time":"2026-02-15T22:03:31.467806-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/database.(*Database).migrate","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/database/migrations.go","line":62},"msg":"migration applied","migration":"005_add_webhook_secret_hash.sql"}
--- PASS: TestAppGetLabels (0.08s)
--- PASS: TestAppGetDeployments (0.08s)
--- PASS: TestAppCreateAndFind (0.09s)
--- PASS: TestUserExists (0.00s)
--- PASS: TestUserExists/returns_false_when_no_users (0.08s)
--- PASS: TestUserExists/returns_true_when_user_exists (0.09s)
--- PASS: TestEnvVarCRUD (0.00s)
--- PASS: TestEnvVarCRUD/creates_and_finds_env_vars (0.08s)
--- PASS: TestEnvVarCRUD/deletes_env_var (0.08s)
--- PASS: TestUserFindByUsername (0.09s)
--- PASS: TestDeploymentFindLatest (0.08s)
--- PASS: TestAppDelete (0.09s)
--- PASS: TestCascadeDelete (0.00s)
--- PASS: TestCascadeDelete/deleting_app_cascades_to_related_records (0.08s)
PASS
ok git.eeqj.de/sneak/upaas/internal/models (cached) coverage: 53.1% of statements
=== RUN TestGetAppByWebhookSecret
=== PAUSE TestGetAppByWebhookSecret
=== CONT TestGetAppByWebhookSecret
=== RUN TestGetAppByWebhookSecret/finds_app_by_webhook_secret
=== PAUSE TestGetAppByWebhookSecret/finds_app_by_webhook_secret
=== RUN TestGetAppByWebhookSecret/returns_nil_for_invalid_secret
=== RUN TestDeleteApp/deletes_app_and_returns_nil_on_lookup
=== PAUSE TestDeleteApp/deletes_app_and_returns_nil_on_lookup
=== PAUSE TestGetAppByWebhookSecret/returns_nil_for_invalid_secret
=== CONT TestDeleteApp/deletes_app_and_returns_nil_on_lookup
=== CONT TestGetAppByWebhookSecret/returns_nil_for_invalid_secret
=== CONT TestGetAppByWebhookSecret/finds_app_by_webhook_secret
{"time":"2026-02-15T22:03:32.07014-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/database.(*Database).connect","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/database/database.go","line":155},"msg":"database connected","path":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/TestDeleteAppdeletes_app_and_returns_nil_on_lookup3054339973/001/upaas.db"}
{"time":"2026-02-15T22:03:32.072112-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/database.(*Database).connect","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/database/database.go","line":155},"msg":"database connected","path":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/TestGetAppByWebhookSecretfinds_app_by_webhook_secret2226392366/001/upaas.db"}
{"time":"2026-02-15T22:03:32.083052-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/database.(*Database).connect","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/database/database.go","line":155},"msg":"database connected","path":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/TestGetAppByWebhookSecretreturns_nil_for_invalid_secret2545745244/001/upaas.db"}
{"time":"2026-02-15T22:03:32.133116-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/database.(*Database).migrate","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/database/migrations.go","line":62},"msg":"migration applied","migration":"005_add_webhook_secret_hash.sql"}
{"time":"2026-02-15T22:03:32.134251-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/database.(*Database).migrate","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/database/migrations.go","line":62},"msg":"migration applied","migration":"005_add_webhook_secret_hash.sql"}
{"time":"2026-02-15T22:03:32.138121-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/database.(*Database).migrate","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/database/migrations.go","line":62},"msg":"migration applied","migration":"005_add_webhook_secret_hash.sql"}
{"time":"2026-02-15T22:03:32.139424-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/database.(*Database).migrate","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/database/migrations.go","line":62},"msg":"migration applied","migration":"005_add_webhook_secret_hash.sql"}
{"time":"2026-02-15T22:03:32.141847-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/database.(*Database).migrate","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/database/migrations.go","line":62},"msg":"migration applied","migration":"005_add_webhook_secret_hash.sql"}
--- PASS: TestEnvVarsAddAndRetrieve (0.08s)
{"time":"2026-02-15T22:03:32.143253-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/database.(*Database).migrate","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/database/migrations.go","line":62},"msg":"migration applied","migration":"005_add_webhook_secret_hash.sql"}
--- PASS: TestCreateAppOptionalFields (0.08s)
--- PASS: TestEnvVarsDelete (0.08s)
--- PASS: TestVolumesAddAndRetrieve (0.08s)
{"time":"2026-02-15T22:03:32.144851-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/database.(*Database).migrate","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/database/migrations.go","line":62},"msg":"migration applied","migration":"005_add_webhook_secret_hash.sql"}
{"time":"2026-02-15T22:03:32.14516-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/database.(*Database).migrate","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/database/migrations.go","line":62},"msg":"migration applied","migration":"005_add_webhook_secret_hash.sql"}
{"time":"2026-02-15T22:03:32.145664-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/database.(*Database).migrate","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/database/migrations.go","line":62},"msg":"migration applied","migration":"005_add_webhook_secret_hash.sql"}
{"time":"2026-02-15T22:03:32.145939-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/database.(*Database).migrate","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/database/migrations.go","line":62},"msg":"migration applied","migration":"005_add_webhook_secret_hash.sql"}
{"time":"2026-02-15T22:03:32.145966-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/database.(*Database).migrate","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/database/migrations.go","line":62},"msg":"migration applied","migration":"005_add_webhook_secret_hash.sql"}
{"time":"2026-02-15T22:03:32.145939-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/database.(*Database).migrate","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/database/migrations.go","line":62},"msg":"migration applied","migration":"005_add_webhook_secret_hash.sql"}
{"time":"2026-02-15T22:03:32.146972-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/database.(*Database).migrate","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/database/migrations.go","line":62},"msg":"migration applied","migration":"005_add_webhook_secret_hash.sql"}
--- PASS: TestUpdateAppStatus (0.00s)
--- PASS: TestUpdateAppStatus/updates_app_status (0.08s)
--- PASS: TestCreateAppWithGeneratedKeys (0.09s)
--- PASS: TestVolumesDelete (0.09s)
{"time":"2026-02-15T22:03:32.149259-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/database.(*Database).migrate","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/database/migrations.go","line":62},"msg":"migration applied","migration":"005_add_webhook_secret_hash.sql"}
{"time":"2026-02-15T22:03:32.149214-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/database.(*Database).migrate","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/database/migrations.go","line":62},"msg":"migration applied","migration":"005_add_webhook_secret_hash.sql"}
--- PASS: TestLabels (0.00s)
--- PASS: TestLabels/deletes_label (0.08s)
--- PASS: TestLabels/adds_and_retrieves_labels (0.08s)
{"time":"2026-02-15T22:03:32.149806-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/database.(*Database).migrate","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/database/migrations.go","line":62},"msg":"migration applied","migration":"005_add_webhook_secret_hash.sql"}
{"time":"2026-02-15T22:03:32.150129-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/database.(*Database).migrate","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/database/migrations.go","line":62},"msg":"migration applied","migration":"005_add_webhook_secret_hash.sql"}
{"time":"2026-02-15T22:03:32.151394-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/database.(*Database).migrate","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/database/migrations.go","line":62},"msg":"migration applied","migration":"005_add_webhook_secret_hash.sql"}
--- PASS: TestUpdateApp (0.00s)
--- PASS: TestUpdateApp/clears_optional_fields_when_empty (0.08s)
--- PASS: TestUpdateApp/updates_app_fields (0.09s)
{"time":"2026-02-15T22:03:32.15261-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/database.(*Database).migrate","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/database/migrations.go","line":62},"msg":"migration applied","migration":"005_add_webhook_secret_hash.sql"}
--- PASS: TestCreateAppDefaults (0.09s)
{"time":"2026-02-15T22:03:32.152889-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/service/app.(*Service).CreateApp","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/service/app/app.go","line":108},"msg":"app created","id":"01KHJGR0XRTHBA7RW7CPKFHT12","name":"webhook-app"}
--- PASS: TestGetApp (0.00s)
--- PASS: TestGetApp/returns_nil_for_non-existent_app (0.08s)
--- PASS: TestGetApp/finds_existing_app (0.09s)
--- PASS: TestGetAppByWebhookSecret (0.00s)
--- PASS: TestGetAppByWebhookSecret/returns_nil_for_invalid_secret (0.09s)
--- PASS: TestGetAppByWebhookSecret/finds_app_by_webhook_secret (0.08s)
--- PASS: TestListApps (0.00s)
--- PASS: TestListApps/returns_empty_list_when_no_apps (0.08s)
--- PASS: TestListApps/returns_all_apps_ordered_by_name (0.09s)
--- PASS: TestDeleteApp (0.00s)
--- PASS: TestDeleteApp/deletes_app_and_returns_nil_on_lookup (0.09s)
PASS
ok git.eeqj.de/sneak/upaas/internal/service/app (cached) coverage: 82.8% of statements
=== RUN TestSessionCookieSecureFlag
=== PAUSE TestSessionCookieSecureFlag
=== CONT TestSessionCookieSecureFlag
=== RUN TestSessionCookieSecureFlag/secure_flag_is_true_when_debug_is_false
=== PAUSE TestSessionCookieSecureFlag/secure_flag_is_true_when_debug_is_false
=== CONT TestSessionCookieSecureFlag/secure_flag_is_true_when_debug_is_false
{"time":"2026-02-15T22:03:31.879203-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/database.(*Database).connect","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/database/database.go","line":155},"msg":"database connected","path":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/TestSessionCookieSecureFlagsecure_flag_is_true_when_debug_is_fa3724651782/001/upaas.db"}
{"time":"2026-02-15T22:03:31.905892-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/database.(*Database).migrate","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/database/migrations.go","line":62},"msg":"migration applied","migration":"005_add_webhook_secret_hash.sql"}
{"time":"2026-02-15T22:03:31.907254-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/database.(*Database).migrate","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/database/migrations.go","line":62},"msg":"migration applied","migration":"005_add_webhook_secret_hash.sql"}
{"time":"2026-02-15T22:03:31.907743-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/database.(*Database).migrate","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/database/migrations.go","line":62},"msg":"migration applied","migration":"005_add_webhook_secret_hash.sql"}
{"time":"2026-02-15T22:03:31.907876-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/database.(*Database).migrate","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/database/migrations.go","line":62},"msg":"migration applied","migration":"005_add_webhook_secret_hash.sql"}
{"time":"2026-02-15T22:03:31.912461-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/database.(*Database).migrate","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/database/migrations.go","line":62},"msg":"migration applied","migration":"005_add_webhook_secret_hash.sql"}
{"time":"2026-02-15T22:03:31.912566-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/database.(*Database).migrate","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/database/migrations.go","line":62},"msg":"migration applied","migration":"005_add_webhook_secret_hash.sql"}
{"time":"2026-02-15T22:03:31.913688-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/database.(*Database).migrate","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/database/migrations.go","line":62},"msg":"migration applied","migration":"005_add_webhook_secret_hash.sql"}
{"time":"2026-02-15T22:03:31.970865-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/database.(*Database).migrate","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/database/migrations.go","line":62},"msg":"migration applied","migration":"005_add_webhook_secret_hash.sql"}
{"time":"2026-02-15T22:03:31.975042-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/database.(*Database).migrate","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/database/migrations.go","line":62},"msg":"migration applied","migration":"005_add_webhook_secret_hash.sql"}
{"time":"2026-02-15T22:03:31.987333-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/database.(*Database).migrate","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/database/migrations.go","line":62},"msg":"migration applied","migration":"005_add_webhook_secret_hash.sql"}
{"time":"2026-02-15T22:03:32.017781-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/database.(*Database).migrate","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/database/migrations.go","line":62},"msg":"migration applied","migration":"005_add_webhook_secret_hash.sql"}
{"time":"2026-02-15T22:03:32.019502-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/database.(*Database).migrate","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/database/migrations.go","line":62},"msg":"migration applied","migration":"005_add_webhook_secret_hash.sql"}
--- PASS: TestIsSetupRequired (0.00s)
--- PASS: TestIsSetupRequired/returns_true_when_no_users_exist (0.14s)
{"time":"2026-02-15T22:03:32.087105-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/database.(*Database).migrate","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/database/migrations.go","line":62},"msg":"migration applied","migration":"005_add_webhook_secret_hash.sql"}
{"time":"2026-02-15T22:03:32.160244-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/database.(*Database).migrate","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/database/migrations.go","line":62},"msg":"migration applied","migration":"005_add_webhook_secret_hash.sql"}
--- PASS: TestCreateUserRaceCondition (0.00s)
--- PASS: TestCreateUserRaceCondition/concurrent_setup_requests_create_only_one_user (0.49s)
--- PASS: TestHashPassword (0.00s)
--- PASS: TestHashPassword/hashes_password_successfully (0.29s)
--- PASS: TestHashPassword/produces_different_hashes_for_same_password (0.53s)
--- PASS: TestSessionCookieSecureFlag (0.00s)
--- PASS: TestSessionCookieSecureFlag/secure_flag_is_true_when_debug_is_false (0.54s)
--- PASS: TestAuthenticate (0.00s)
--- PASS: TestAuthenticate/rejects_unknown_user (0.10s)
--- PASS: TestAuthenticate/rejects_invalid_password (0.52s)
--- PASS: TestAuthenticate/authenticates_valid_credentials (0.56s)
--- PASS: TestVerifyPassword (0.00s)
--- PASS: TestVerifyPassword/rejects_invalid_hash_format (0.21s)
--- PASS: TestVerifyPassword/verifies_correct_password (0.53s)
--- PASS: TestVerifyPassword/rejects_empty_password (0.54s)
--- PASS: TestVerifyPassword/rejects_incorrect_password (0.57s)
--- PASS: TestCreateUser (0.00s)
--- PASS: TestCreateUser/creates_user_successfully (0.48s)
--- PASS: TestCreateUser/rejects_duplicate_user (0.63s)
PASS
ok git.eeqj.de/sneak/upaas/internal/service/auth (cached) coverage: 62.7% of statements
=== RUN TestHandleWebhookMatchingBranch
=== PAUSE TestHandleWebhookMatchingBranch
=== RUN TestHandleWebhookNonMatchingBranch
=== PAUSE TestHandleWebhookNonMatchingBranch
=== RUN TestHandleWebhookInvalidJSON
=== PAUSE TestHandleWebhookInvalidJSON
=== RUN TestHandleWebhookEmptyPayload
=== PAUSE TestHandleWebhookEmptyPayload
=== CONT TestHandleWebhookInvalidJSON
=== CONT TestHandleWebhookMatchingBranch
=== CONT TestHandleWebhookEmptyPayload
=== CONT TestHandleWebhookNonMatchingBranch
--- PASS: TestGiteaPushPayloadParsing (0.00s)
--- PASS: TestGiteaPushPayloadParsing/parses_full_payload (0.00s)
{"time":"2026-02-15T22:03:31.713665-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/database.(*Database).connect","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/database/database.go","line":155},"msg":"database connected","path":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/TestHandleWebhookEmptyPayload883134231/001/upaas.db"}
{"time":"2026-02-15T22:03:31.713443-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/database.(*Database).connect","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/database/database.go","line":155},"msg":"database connected","path":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/TestHandleWebhookMatchingBranch4062815577/001/upaas.db"}
{"time":"2026-02-15T22:03:31.713567-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/database.(*Database).connect","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/database/database.go","line":155},"msg":"database connected","path":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/TestHandleWebhookInvalidJSON2145582442/001/upaas.db"}
{"time":"2026-02-15T22:03:31.713507-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/database.(*Database).connect","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/database/database.go","line":155},"msg":"database connected","path":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/TestHandleWebhookNonMatchingBranch1190593892/001/upaas.db"}
{"time":"2026-02-15T22:03:31.732483-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/database.(*Database).migrate","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/database/migrations.go","line":62},"msg":"migration applied","migration":"005_add_webhook_secret_hash.sql"}
{"time":"2026-02-15T22:03:31.733056-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/service/webhook.(*Service).HandleWebhook","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/service/webhook/webhook.go","line":82},"msg":"processing webhook","app":"test-app","event":"push"}
{"time":"2026-02-15T22:03:31.733359-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/service/webhook.(*Service).HandleWebhook","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/service/webhook/webhook.go","line":117},"msg":"webhook event recorded","app":"test-app","branch":"main","matched":true,"commit":""}
{"time":"2026-02-15T22:03:31.735292-08:00","level":"ERROR","source":{"function":"git.eeqj.de/sneak/upaas/internal/service/webhook.(*Service).triggerDeployment.func1","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/service/webhook/webhook.go","line":148},"msg":"deployment failed","error":"failed to clone repo: docker client not connected","app":"test-app"}
{"time":"2026-02-15T22:03:31.738857-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/database.(*Database).migrate","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/database/migrations.go","line":62},"msg":"migration applied","migration":"005_add_webhook_secret_hash.sql"}
{"time":"2026-02-15T22:03:31.739166-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/service/webhook.(*Service).HandleWebhook","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/service/webhook/webhook.go","line":82},"msg":"processing webhook","app":"test-app","event":"push"}
{"time":"2026-02-15T22:03:31.739417-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/database.(*Database).migrate","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/database/migrations.go","line":62},"msg":"migration applied","migration":"005_add_webhook_secret_hash.sql"}
{"time":"2026-02-15T22:03:31.73945-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/service/webhook.(*Service).HandleWebhook","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/service/webhook/webhook.go","line":117},"msg":"webhook event recorded","app":"test-app","branch":"feature/new-feature","matched":true,"commit":""}
{"time":"2026-02-15T22:03:31.739955-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/database.(*Database).migrate","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/database/migrations.go","line":62},"msg":"migration applied","migration":"005_add_webhook_secret_hash.sql"}
{"time":"2026-02-15T22:03:31.740045-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/database.(*Database).migrate","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/database/migrations.go","line":62},"msg":"migration applied","migration":"005_add_webhook_secret_hash.sql"}
{"time":"2026-02-15T22:03:31.740062-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/database.(*Database).migrate","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/database/migrations.go","line":62},"msg":"migration applied","migration":"005_add_webhook_secret_hash.sql"}
{"time":"2026-02-15T22:03:31.740073-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/database.(*Database).migrate","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/database/migrations.go","line":62},"msg":"migration applied","migration":"005_add_webhook_secret_hash.sql"}
--- PASS: TestSetupTestService (0.00s)
--- PASS: TestSetupTestService/creates_working_test_service (0.03s)
{"time":"2026-02-15T22:03:31.740147-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/database.(*Database).migrate","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/database/migrations.go","line":62},"msg":"migration applied","migration":"005_add_webhook_secret_hash.sql"}
{"time":"2026-02-15T22:03:31.740504-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/service/webhook.(*Service).HandleWebhook","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/service/webhook/webhook.go","line":82},"msg":"processing webhook","app":"test-app","event":"push"}
{"time":"2026-02-15T22:03:31.740542-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/service/webhook.(*Service).HandleWebhook","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/service/webhook/webhook.go","line":82},"msg":"processing webhook","app":"test-app","event":"push"}
{"time":"2026-02-15T22:03:31.740576-08:00","level":"WARN","source":{"function":"git.eeqj.de/sneak/upaas/internal/service/webhook.(*Service).HandleWebhook","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/service/webhook/webhook.go","line":89},"msg":"failed to parse webhook payload","error":"invalid character 'i' looking for beginning of object key string"}
{"time":"2026-02-15T22:03:31.740602-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/service/webhook.(*Service).HandleWebhook","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/service/webhook/webhook.go","line":82},"msg":"processing webhook","app":"test-app","event":"push"}
{"time":"2026-02-15T22:03:31.740754-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/database.(*Database).migrate","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/database/migrations.go","line":62},"msg":"migration applied","migration":"005_add_webhook_secret_hash.sql"}
{"time":"2026-02-15T22:03:31.740765-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/service/webhook.(*Service).HandleWebhook","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/service/webhook/webhook.go","line":82},"msg":"processing webhook","app":"test-app","event":"push"}
{"time":"2026-02-15T22:03:31.740794-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/service/webhook.(*Service).HandleWebhook","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/service/webhook/webhook.go","line":82},"msg":"processing webhook","app":"test-app","event":"push"}
{"time":"2026-02-15T22:03:31.740809-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/service/webhook.(*Service).HandleWebhook","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/service/webhook/webhook.go","line":117},"msg":"webhook event recorded","app":"test-app","branch":"develop","matched":false,"commit":"def789ghi012"}
{"time":"2026-02-15T22:03:31.740823-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/service/webhook.(*Service).HandleWebhook","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/service/webhook/webhook.go","line":117},"msg":"webhook event recorded","app":"test-app","branch":"","matched":false,"commit":""}
{"time":"2026-02-15T22:03:31.740881-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/database.(*Database).migrate","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/database/migrations.go","line":62},"msg":"migration applied","migration":"005_add_webhook_secret_hash.sql"}
{"time":"2026-02-15T22:03:31.740934-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/database.(*Database).migrate","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/database/migrations.go","line":62},"msg":"migration applied","migration":"005_add_webhook_secret_hash.sql"}
{"time":"2026-02-15T22:03:31.740943-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/service/webhook.(*Service).HandleWebhook","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/service/webhook/webhook.go","line":117},"msg":"webhook event recorded","app":"test-app","branch":"","matched":true,"commit":""}
{"time":"2026-02-15T22:03:31.741279-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/service/webhook.(*Service).HandleWebhook","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/service/webhook/webhook.go","line":117},"msg":"webhook event recorded","app":"test-app","branch":"","matched":false,"commit":""}
{"time":"2026-02-15T22:03:31.741356-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/service/webhook.(*Service).HandleWebhook","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/service/webhook/webhook.go","line":117},"msg":"webhook event recorded","app":"test-app","branch":"","matched":true,"commit":""}
{"time":"2026-02-15T22:03:31.741405-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/service/webhook.(*Service).HandleWebhook","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/service/webhook/webhook.go","line":82},"msg":"processing webhook","app":"test-app","event":"push"}
--- PASS: TestHandleWebhookInvalidJSON (0.03s)
{"time":"2026-02-15T22:03:31.741561-08:00","level":"ERROR","source":{"function":"git.eeqj.de/sneak/upaas/internal/service/webhook.(*Service).triggerDeployment.func1","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/service/webhook/webhook.go","line":148},"msg":"deployment failed","error":"failed to clone repo: docker client not connected","app":"test-app"}
--- PASS: TestHandleWebhookNonMatchingBranch (0.03s)
{"time":"2026-02-15T22:03:31.741711-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/service/webhook.(*Service).HandleWebhook","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/service/webhook/webhook.go","line":117},"msg":"webhook event recorded","app":"test-app","branch":"develop","matched":true,"commit":""}
{"time":"2026-02-15T22:03:31.741719-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/service/webhook.(*Service).HandleWebhook","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/service/webhook/webhook.go","line":82},"msg":"processing webhook","app":"test-app","event":"push"}
{"time":"2026-02-15T22:03:31.741722-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/service/webhook.(*Service).HandleWebhook","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/service/webhook/webhook.go","line":82},"msg":"processing webhook","app":"test-app","event":"push"}
{"time":"2026-02-15T22:03:31.74188-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/service/webhook.(*Service).HandleWebhook","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/service/webhook/webhook.go","line":117},"msg":"webhook event recorded","app":"test-app","branch":"main","matched":true,"commit":""}
--- PASS: TestHandleWebhookEmptyPayload (0.03s)
{"time":"2026-02-15T22:03:31.742285-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/service/webhook.(*Service).HandleWebhook","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/service/webhook/webhook.go","line":117},"msg":"webhook event recorded","app":"test-app","branch":"main","matched":true,"commit":"abc123def456"}
{"time":"2026-02-15T22:03:31.743405-08:00","level":"ERROR","source":{"function":"git.eeqj.de/sneak/upaas/internal/service/webhook.(*Service).triggerDeployment.func1","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/service/webhook/webhook.go","line":148},"msg":"deployment failed","error":"failed to clone repo: invalid branch name: ""","app":"test-app"}
{"time":"2026-02-15T22:03:31.743648-08:00","level":"ERROR","source":{"function":"git.eeqj.de/sneak/upaas/internal/service/webhook.(*Service).triggerDeployment.func1","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/service/webhook/webhook.go","line":148},"msg":"deployment failed","error":"failed to clone repo: invalid branch name: ""","app":"test-app"}
{"time":"2026-02-15T22:03:31.743884-08:00","level":"ERROR","source":{"function":"git.eeqj.de/sneak/upaas/internal/service/webhook.(*Service).triggerDeployment.func1","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/service/webhook/webhook.go","line":148},"msg":"deployment failed","error":"failed to clone repo: docker client not connected","app":"test-app"}
{"time":"2026-02-15T22:03:31.744016-08:00","level":"ERROR","source":{"function":"git.eeqj.de/sneak/upaas/internal/service/webhook.(*Service).triggerDeployment.func1","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/service/webhook/webhook.go","line":148},"msg":"deployment failed","error":"failed to clone repo: docker client not connected","app":"test-app"}
{"time":"2026-02-15T22:03:31.744053-08:00","level":"INFO","source":{"function":"git.eeqj.de/sneak/upaas/internal/service/deploy.(*Service).writeLogsToFile","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/service/deploy/deploy.go","line":991},"msg":"wrote deployment logs to file","path":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/TestHandleWebhookMatchingBranch4062815577/001/logs/inference.local/test-app/test-app_abc123def456_20260216T060331Z.log.txt"}
{"time":"2026-02-15T22:03:31.744196-08:00","level":"ERROR","source":{"function":"git.eeqj.de/sneak/upaas/internal/service/webhook.(*Service).triggerDeployment.func1","file":"/var/folders/nq/wq3c5mv50nb4fnymxft9ggv40000gn/T/tmp.6IkV5n3z0a/internal/service/webhook/webhook.go","line":148},"msg":"deployment failed","error":"failed to clone repo: invalid commit SHA: "abc123def456"","app":"test-app"}
--- PASS: TestExtractBranch (0.00s)
--- PASS: TestExtractBranch/returns_raw_ref_if_no_prefix (0.13s)
--- PASS: TestExtractBranch/extracts_feature_branch (0.13s)
--- PASS: TestExtractBranch/handles_partial_prefix (0.13s)
--- PASS: TestExtractBranch/handles_empty_ref (0.13s)
--- PASS: TestExtractBranch/extracts_develop_branch (0.13s)
--- PASS: TestExtractBranch/extracts_main_branch (0.13s)
--- PASS: TestHandleWebhookMatchingBranch (0.13s)
PASS
ok git.eeqj.de/sneak/upaas/internal/service/webhook (cached) coverage: 93.3% of statements
--- PASS: TestValidatePrivateKey (0.00s)
--- PASS: TestValidatePrivateKey/rejects_empty_key (0.00s)
--- PASS: TestValidatePrivateKey/rejects_invalid_key (0.00s)
--- PASS: TestValidatePrivateKey/validates_generated_key (0.01s)
--- PASS: TestGenerateKeyPair (0.00s)
--- PASS: TestGenerateKeyPair/generates_valid_key_pair (0.01s)
--- PASS: TestGenerateKeyPair/generates_unique_keys_each_time (0.01s)
PASS
ok git.eeqj.de/sneak/upaas/internal/ssh (cached) coverage: 78.6% of statements\n
\n\n## Lint Results\n\ninternal/handlers/tail_validation_test.go:1:9: package should behandlers_testinstead ofhandlers(testpackage)package handlers
^
1 issues:
testpackageissue intail_validation_test.gois pre-existing and unrelated to this PR.