Update golangci-lint to v2.12.2 with canonical config
All checks were successful
Check / check (pull_request) Successful in 3m22s

Bump golangci-lint from v2.10.1 to v2.12.2 in the Dockerfile lint
stage (tag+digest pin) and script/bootstrap release-archive pins
(linux amd64/arm64 sha256s). Replace .golangci.yml with the canonical
v2-layout config so linter settings (lll 88, funlen 80/50, cyclop 15,
dupl 100) actually apply.

Fix all findings surfaced by the new linter and config:

- noctx: use httptest.NewRequestWithContext in all tests
- gosec G710/G703: route app redirects through a path-escaping
  redirectToApp helper; annotate internal log path usage
- goconst: introduce shared constants for template/JSON keys and
  repeated test literals
- lll: wrap lines to the 88-column limit
- dupl: extract shared helpers (generic findAllByAppID in models,
  deleteAppResource in handlers, parsePush in webhook payloads,
  table-driven/helper-based test dedup)
- nolintlint: drop nolint directives made obsolete by the new limits

Record the change in TODO.md; make check is green.
This commit is contained in:
2026-08-07 17:16:57 +00:00
parent 291f85f3ed
commit a4b8ea4402
41 changed files with 1172 additions and 797 deletions

View File

@@ -16,6 +16,12 @@ import (
"sneak.berlin/go/upaas/internal/service/app"
)
// testRepoURL is the default repository URL used across tests.
const testRepoURL = "git@example.com:user/repo.git"
// giteaRepoURL is the gitea repository URL used across tests.
const giteaRepoURL = "git@gitea.example.com:user/repo.git"
func setupTestService(t *testing.T) (*app.Service, func()) {
t.Helper()
@@ -58,7 +64,8 @@ func setupTestService(t *testing.T) (*app.Service, func()) {
}
// deleteItemTestHelper is a generic helper for testing delete operations.
// It creates an app, adds an item, verifies it exists, deletes it, and verifies it's gone.
// It creates an app, adds an item, verifies it exists, deletes it, and
// verifies it's gone.
func deleteItemTestHelper(
t *testing.T,
appName string,
@@ -73,7 +80,7 @@ func deleteItemTestHelper(
createdApp, err := svc.CreateApp(context.Background(), app.CreateAppInput{
Name: appName,
RepoURL: "git@example.com:user/repo.git",
RepoURL: testRepoURL,
})
require.NoError(t, err)
@@ -92,6 +99,35 @@ func deleteItemTestHelper(
assert.Equal(t, 0, count)
}
// runDeleteItemTest adapts typed list/delete callbacks so delete tests for
// different item types can share deleteItemTestHelper.
func runDeleteItemTest[T any](
t *testing.T,
appName string,
addItem func(ctx context.Context, svc *app.Service, appID string) error,
listItems func(ctx context.Context, application *models.App) ([]T, error),
deleteFirst func(ctx context.Context, svc *app.Service, item T) error,
) {
t.Helper()
deleteItemTestHelper(t, appName,
addItem,
func(ctx context.Context, application *models.App) (int, error) {
items, err := listItems(ctx, application)
return len(items), err
},
func(ctx context.Context, svc *app.Service, application *models.App) error {
items, err := listItems(ctx, application)
if err != nil {
return err
}
return deleteFirst(ctx, svc, items[0])
},
)
}
func TestCreateAppWithGeneratedKeys(t *testing.T) {
t.Parallel()
@@ -100,7 +136,7 @@ func TestCreateAppWithGeneratedKeys(t *testing.T) {
input := app.CreateAppInput{
Name: "test-app",
RepoURL: "git@gitea.example.com:user/repo.git",
RepoURL: giteaRepoURL,
Branch: "main",
DockerfilePath: "Dockerfile",
}
@@ -110,7 +146,7 @@ func TestCreateAppWithGeneratedKeys(t *testing.T) {
require.NotNil(t, createdApp)
assert.Equal(t, "test-app", createdApp.Name)
assert.Equal(t, "git@gitea.example.com:user/repo.git", createdApp.RepoURL)
assert.Equal(t, giteaRepoURL, createdApp.RepoURL)
assert.Equal(t, "main", createdApp.Branch)
assert.Equal(t, "Dockerfile", createdApp.DockerfilePath)
assert.NotEmpty(t, createdApp.ID)
@@ -130,7 +166,7 @@ func TestCreateAppDefaults(t *testing.T) {
input := app.CreateAppInput{
Name: "test-app-defaults",
RepoURL: "git@gitea.example.com:user/repo.git",
RepoURL: giteaRepoURL,
}
createdApp, err := svc.CreateApp(context.Background(), input)
@@ -148,7 +184,7 @@ func TestCreateAppOptionalFields(t *testing.T) {
input := app.CreateAppInput{
Name: "test-app-full",
RepoURL: "git@gitea.example.com:user/repo.git",
RepoURL: giteaRepoURL,
Branch: "develop",
DockerNetwork: "my-network",
NtfyTopic: "https://ntfy.sh/my-topic",
@@ -176,7 +212,7 @@ func TestUpdateApp(testingT *testing.T) {
createdApp, err := svc.CreateApp(context.Background(), app.CreateAppInput{
Name: "original-name",
RepoURL: "git@example.com:user/repo.git",
RepoURL: testRepoURL,
})
require.NoError(t, err)
@@ -208,7 +244,7 @@ func TestUpdateApp(testingT *testing.T) {
createdApp, err := svc.CreateApp(context.Background(), app.CreateAppInput{
Name: "test-clear",
RepoURL: "git@example.com:user/repo.git",
RepoURL: testRepoURL,
NtfyTopic: "https://ntfy.sh/topic",
SlackWebhook: "https://slack.com/hook",
})
@@ -216,7 +252,7 @@ func TestUpdateApp(testingT *testing.T) {
err = svc.UpdateApp(context.Background(), createdApp, app.UpdateAppInput{
Name: "test-clear",
RepoURL: "git@example.com:user/repo.git",
RepoURL: testRepoURL,
Branch: "main",
})
require.NoError(t, err)
@@ -240,7 +276,7 @@ func TestDeleteApp(testingT *testing.T) {
createdApp, err := svc.CreateApp(context.Background(), app.CreateAppInput{
Name: "to-delete",
RepoURL: "git@example.com:user/repo.git",
RepoURL: testRepoURL,
})
require.NoError(t, err)
@@ -264,7 +300,7 @@ func TestGetApp(testingT *testing.T) {
created, err := svc.CreateApp(context.Background(), app.CreateAppInput{
Name: "findable-app",
RepoURL: "git@example.com:user/repo.git",
RepoURL: testRepoURL,
})
require.NoError(t, err)
@@ -299,7 +335,7 @@ func TestGetAppByWebhookSecret(testingT *testing.T) {
created, err := svc.CreateApp(context.Background(), app.CreateAppInput{
Name: "webhook-app",
RepoURL: "git@example.com:user/repo.git",
RepoURL: testRepoURL,
})
require.NoError(t, err)
@@ -378,7 +414,7 @@ func TestEnvVarsAddAndRetrieve(t *testing.T) {
createdApp, err := svc.CreateApp(context.Background(), app.CreateAppInput{
Name: "env-test",
RepoURL: "git@example.com:user/repo.git",
RepoURL: testRepoURL,
})
require.NoError(t, err)
@@ -411,29 +447,33 @@ func TestEnvVarsAddAndRetrieve(t *testing.T) {
assert.Equal(t, "secret123", keys["API_KEY"])
}
// addDeletableEnvVar seeds the env var removed in the delete test.
func addDeletableEnvVar(
ctx context.Context, svc *app.Service, appID string,
) error {
return svc.AddEnvVar(ctx, appID, "TO_DELETE", "value")
}
func TestEnvVarsDelete(t *testing.T) {
t.Parallel()
deleteItemTestHelper(t, "env-delete-test",
func(ctx context.Context, svc *app.Service, appID string) error {
return svc.AddEnvVar(ctx, appID, "TO_DELETE", "value")
runDeleteItemTest(t, "env-delete-test", addDeletableEnvVar,
func(ctx context.Context, application *models.App) ([]*models.EnvVar, error) {
return application.GetEnvVars(ctx)
},
func(ctx context.Context, application *models.App) (int, error) {
envVars, err := application.GetEnvVars(ctx)
return len(envVars), err
},
func(ctx context.Context, svc *app.Service, application *models.App) error {
envVars, err := application.GetEnvVars(ctx)
if err != nil {
return err
}
return svc.DeleteEnvVar(ctx, envVars[0].ID)
func(ctx context.Context, svc *app.Service, item *models.EnvVar) error {
return svc.DeleteEnvVar(ctx, item.ID)
},
)
}
// addDeletableLabel seeds the label removed in the delete test.
func addDeletableLabel(
ctx context.Context, svc *app.Service, appID string,
) error {
return svc.AddLabel(ctx, appID, "to.delete", "value")
}
func TestLabels(testingT *testing.T) {
testingT.Parallel()
@@ -445,7 +485,7 @@ func TestLabels(testingT *testing.T) {
createdApp, err := svc.CreateApp(context.Background(), app.CreateAppInput{
Name: "label-test",
RepoURL: "git@example.com:user/repo.git",
RepoURL: testRepoURL,
})
require.NoError(t, err)
@@ -468,22 +508,12 @@ func TestLabels(testingT *testing.T) {
testingT.Run("deletes label", func(t *testing.T) {
t.Parallel()
deleteItemTestHelper(t, "label-delete-test",
func(ctx context.Context, svc *app.Service, appID string) error {
return svc.AddLabel(ctx, appID, "to.delete", "value")
runDeleteItemTest(t, "label-delete-test", addDeletableLabel,
func(ctx context.Context, application *models.App) ([]*models.Label, error) {
return application.GetLabels(ctx)
},
func(ctx context.Context, application *models.App) (int, error) {
labels, err := application.GetLabels(ctx)
return len(labels), err
},
func(ctx context.Context, svc *app.Service, application *models.App) error {
labels, err := application.GetLabels(ctx)
if err != nil {
return err
}
return svc.DeleteLabel(ctx, labels[0].ID)
func(ctx context.Context, svc *app.Service, item *models.Label) error {
return svc.DeleteLabel(ctx, item.ID)
},
)
})
@@ -497,7 +527,7 @@ func TestVolumesAddAndRetrieve(t *testing.T) {
createdApp, err := svc.CreateApp(context.Background(), app.CreateAppInput{
Name: "volume-test",
RepoURL: "git@example.com:user/repo.git",
RepoURL: testRepoURL,
})
require.NoError(t, err)
@@ -547,7 +577,7 @@ func TestVolumesDelete(t *testing.T) {
createdApp, err := svc.CreateApp(context.Background(), app.CreateAppInput{
Name: "volume-delete-test",
RepoURL: "git@example.com:user/repo.git",
RepoURL: testRepoURL,
})
require.NoError(t, err)
@@ -583,7 +613,7 @@ func TestUpdateAppStatus(testingT *testing.T) {
createdApp, err := svc.CreateApp(context.Background(), app.CreateAppInput{
Name: "status-test",
RepoURL: "git@example.com:user/repo.git",
RepoURL: testRepoURL,
})
require.NoError(t, err)
assert.Equal(t, models.AppStatusPending, createdApp.Status)