Update golangci-lint to v2.12.2 with canonical config (#187)
All checks were successful
Check / check (push) Successful in 4s
All checks were successful
Check / check (push) Successful in 4s
Bumps golangci-lint from v2.10.1 to v2.12.2 everywhere it is pinned and installs the canonical `.golangci.yml`, then fixes every finding the new linter surfaces so `make check` is green. ## Version pins - `Dockerfile` lint stage: `golangci/golangci-lint:v2.12.2` (Debian-based), tag plus digest pin - `script/bootstrap`: `GOLANGCI_LINT_VERSION=2.12.2` with updated `linux-amd64`/`linux-arm64` release-archive sha256 pins ## Config `.golangci.yml` replaced with the canonical config. Material change: the old file declared `version: "2"` but kept settings under the legacy top-level `linters-settings` key, which golangci-lint v2 ignores — so the intended thresholds (`lll` 88, `funlen` 80/50, `cyclop` 15, `dupl` 100) were not being applied. The canonical file moves them under `linters.settings` and drops `issues.exclude-use-default`. ## Lint fixes (216 findings) - `lll` (96): wrapped lines to the 88-column limit - `noctx` (46): `httptest.NewRequestWithContext` with `t.Context()` throughout the tests - `goconst` (24): shared constants for template/JSON keys in `internal/handlers` and repeated test literals - `gosec` (23): app-page redirects now go through a `redirectToApp` helper that path-escapes the app ID (G710 open redirect); `http.ServeFile` of the internally derived deployment log path annotated like the adjacent `os.Stat` (G703) - `dupl` (22): extracted a generic `findAllByAppID` in `internal/models`, a `deleteAppResource` helper in `internal/handlers`, a shared `parsePush` in `internal/service/webhook`, and table-driven/helper-based dedup in tests - `nolintlint` (5): removed `//nolint:funlen` directives made obsolete by the new limits (plus one more that became obsolete after refactoring) - `nilerr` (3, surfaced during fixing): resource-delete lookups now propagate the find error to the caller No behavior changes intended; all tests pass and `make check` is green. Note: golangci-lint v2.12 warns that `gomodguard` is deprecated in favor of `gomodguard_v2` — a future canonical-config update should address this centrally. Co-authored-by: sneak <sneak@sneak.berlin> Reviewed-on: #187 Co-authored-by: clawbot <clawbot@noreply.example.org> Co-committed-by: clawbot <clawbot@noreply.example.org>
This commit was merged in pull request #187.
This commit is contained in:
@@ -66,7 +66,8 @@ const logFilePermissions = 0o640
|
||||
// logTimestampFormat is the format for log file timestamps.
|
||||
const logTimestampFormat = "20060102T150405Z"
|
||||
|
||||
// logFileShortSHALength is the number of characters to use for commit SHA in log filenames.
|
||||
// logFileShortSHALength is the number of characters to use for commit SHA
|
||||
// in log filenames.
|
||||
const logFileShortSHALength = 12
|
||||
|
||||
// dockerLogMessage represents a Docker build log message.
|
||||
@@ -87,7 +88,10 @@ type deploymentLogWriter struct {
|
||||
flushCtx context.Context //nolint:containedctx // needed for async flush goroutine
|
||||
}
|
||||
|
||||
func newDeploymentLogWriter(ctx context.Context, deployment *models.Deployment) *deploymentLogWriter {
|
||||
func newDeploymentLogWriter(
|
||||
ctx context.Context,
|
||||
deployment *models.Deployment,
|
||||
) *deploymentLogWriter {
|
||||
w := &deploymentLogWriter{
|
||||
deployment: deployment,
|
||||
done: make(chan struct{}),
|
||||
@@ -257,7 +261,10 @@ func (svc *Service) GetBuildDir(appName string) string {
|
||||
|
||||
// GetLogFilePath returns the path to the log file for a deployment.
|
||||
// Returns empty string if the path cannot be determined.
|
||||
func (svc *Service) GetLogFilePath(app *models.App, deployment *models.Deployment) string {
|
||||
func (svc *Service) GetLogFilePath(
|
||||
app *models.App,
|
||||
deployment *models.Deployment,
|
||||
) string {
|
||||
hostname, err := os.Hostname()
|
||||
if err != nil {
|
||||
hostname = "unknown"
|
||||
@@ -275,7 +282,8 @@ func (svc *Service) GetLogFilePath(app *models.App, deployment *models.Deploymen
|
||||
// Use started_at timestamp
|
||||
timestamp := deployment.StartedAt.UTC().Format(logTimestampFormat)
|
||||
|
||||
// Build filename: appname_sha_timestamp.log.txt (or appname_timestamp.log.txt if no SHA)
|
||||
// Build filename: appname_sha_timestamp.log.txt
|
||||
// (or appname_timestamp.log.txt if no SHA)
|
||||
var filename string
|
||||
if sha != "" {
|
||||
filename = fmt.Sprintf("%s_%s_%s.log.txt", app.Name, sha, timestamp)
|
||||
@@ -308,7 +316,8 @@ func (svc *Service) CancelDeploy(appID string) bool {
|
||||
|
||||
// Deploy deploys an app. If cancelExisting is true (e.g. webhook-triggered),
|
||||
// any in-progress deploy for the same app will be cancelled before starting.
|
||||
// If cancelExisting is false and a deploy is in progress, ErrDeploymentInProgress is returned.
|
||||
// If cancelExisting is false and a deploy is in progress,
|
||||
// ErrDeploymentInProgress is returned.
|
||||
func (svc *Service) Deploy(
|
||||
ctx context.Context,
|
||||
app *models.App,
|
||||
@@ -342,7 +351,8 @@ func (svc *Service) Deploy(
|
||||
// Fetch webhook event and create deployment record
|
||||
webhookEvent := svc.fetchWebhookEvent(deployCtx, webhookEventID)
|
||||
|
||||
// Use a background context for DB operations that must complete regardless of cancellation
|
||||
// Use a background context for DB operations that must complete
|
||||
// regardless of cancellation
|
||||
bgCtx := context.WithoutCancel(deployCtx)
|
||||
|
||||
deployment, err := svc.createDeploymentRecord(bgCtx, app, webhookEventID, webhookEvent)
|
||||
@@ -401,7 +411,10 @@ func (svc *Service) createRollbackDeployment(
|
||||
return nil, fmt.Errorf("failed to create rollback deployment: %w", saveErr)
|
||||
}
|
||||
|
||||
_ = deployment.AppendLog(ctx, "Rolling back to previous image: "+app.PreviousImageID.String)
|
||||
_ = deployment.AppendLog(
|
||||
ctx,
|
||||
"Rolling back to previous image: "+app.PreviousImageID.String,
|
||||
)
|
||||
|
||||
return deployment, nil
|
||||
}
|
||||
@@ -417,7 +430,11 @@ func (svc *Service) executeRollback(
|
||||
|
||||
svc.removeOldContainer(ctx, app, deployment)
|
||||
|
||||
rollbackOpts, err := svc.buildContainerOptions(ctx, app, docker.ImageID(previousImageID))
|
||||
rollbackOpts, err := svc.buildContainerOptions(
|
||||
ctx,
|
||||
app,
|
||||
docker.ImageID(previousImageID),
|
||||
)
|
||||
if err != nil {
|
||||
svc.failDeployment(bgCtx, app, deployment, err)
|
||||
|
||||
@@ -426,7 +443,12 @@ func (svc *Service) executeRollback(
|
||||
|
||||
containerID, err := svc.docker.CreateContainer(ctx, rollbackOpts)
|
||||
if err != nil {
|
||||
svc.failDeployment(bgCtx, app, deployment, fmt.Errorf("failed to create rollback container: %w", err))
|
||||
svc.failDeployment(
|
||||
bgCtx,
|
||||
app,
|
||||
deployment,
|
||||
fmt.Errorf("failed to create rollback container: %w", err),
|
||||
)
|
||||
|
||||
return fmt.Errorf("failed to create rollback container: %w", err)
|
||||
}
|
||||
@@ -436,7 +458,12 @@ func (svc *Service) executeRollback(
|
||||
|
||||
startErr := svc.docker.StartContainer(ctx, containerID)
|
||||
if startErr != nil {
|
||||
svc.failDeployment(bgCtx, app, deployment, fmt.Errorf("failed to start rollback container: %w", startErr))
|
||||
svc.failDeployment(
|
||||
bgCtx,
|
||||
app,
|
||||
deployment,
|
||||
fmt.Errorf("failed to start rollback container: %w", startErr),
|
||||
)
|
||||
|
||||
return fmt.Errorf("failed to start rollback container: %w", startErr)
|
||||
}
|
||||
@@ -695,7 +722,11 @@ func (svc *Service) cleanupCancelledDeploy(
|
||||
if removeErr != nil {
|
||||
svc.log.Error("failed to remove image from cancelled deploy",
|
||||
"error", removeErr, "app", app.Name, "image", imageID)
|
||||
_ = deployment.AppendLog(ctx, "WARNING: failed to clean up image "+imageID.String()+": "+removeErr.Error())
|
||||
_ = deployment.AppendLog(
|
||||
ctx,
|
||||
"WARNING: failed to clean up image "+
|
||||
imageID.String()+": "+removeErr.Error(),
|
||||
)
|
||||
} else {
|
||||
svc.log.Info("cleaned up image from cancelled deploy",
|
||||
"app", app.Name, "image", imageID)
|
||||
@@ -870,14 +901,24 @@ func (svc *Service) cloneRepository(
|
||||
|
||||
err := os.MkdirAll(appBuildsDir, buildsDirPermissions)
|
||||
if err != nil {
|
||||
svc.failDeployment(ctx, app, deployment, fmt.Errorf("failed to create builds dir: %w", err))
|
||||
svc.failDeployment(
|
||||
ctx,
|
||||
app,
|
||||
deployment,
|
||||
fmt.Errorf("failed to create builds dir: %w", err),
|
||||
)
|
||||
|
||||
return "", nil, fmt.Errorf("failed to create builds dir: %w", err)
|
||||
}
|
||||
|
||||
buildDir, err := os.MkdirTemp(appBuildsDir, fmt.Sprintf("%d-*", deployment.ID))
|
||||
if err != nil {
|
||||
svc.failDeployment(ctx, app, deployment, fmt.Errorf("failed to create temp dir: %w", err))
|
||||
svc.failDeployment(
|
||||
ctx,
|
||||
app,
|
||||
deployment,
|
||||
fmt.Errorf("failed to create temp dir: %w", err),
|
||||
)
|
||||
|
||||
return "", nil, fmt.Errorf("failed to create temp dir: %w", err)
|
||||
}
|
||||
@@ -908,7 +949,12 @@ func (svc *Service) cloneRepository(
|
||||
)
|
||||
if cloneErr != nil {
|
||||
cleanup()
|
||||
svc.failDeployment(ctx, app, deployment, fmt.Errorf("failed to clone repo: %w", cloneErr))
|
||||
svc.failDeployment(
|
||||
ctx,
|
||||
app,
|
||||
deployment,
|
||||
fmt.Errorf("failed to clone repo: %w", cloneErr),
|
||||
)
|
||||
|
||||
return "", nil, fmt.Errorf("failed to clone repo: %w", cloneErr)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user