Skip to content

fix(lint): clear golangci-lint debt in files untouched by open PRs#1276

Closed
cristim wants to merge 27 commits into
mainfrom
fix/leftover-lint
Closed

fix(lint): clear golangci-lint debt in files untouched by open PRs#1276
cristim wants to merge 27 commits into
mainfrom
fix/leftover-lint

Conversation

@cristim

@cristim cristim commented Jun 20, 2026

Copy link
Copy Markdown
Member

Summary

Clears ~1454 leftover golangci-lint issues (godot/misspell/fieldalignment/gocritic/bodyclose/noctx/errcheck/etc.) across 217 files that no open PR touches. Assembled from 8 disjoint per-package fix branches (leftover-lint/g1..g8), each targeting a non-overlapping set of packages.

  • Remaining lint debt lives in files owned by the ~96 open PRs, which fold their own lint fixes; together they bring the repo to golangci-lint zero and green the Lint CI job
  • No behavior change beyond improved error-handling and struct field order (fieldalignment)
  • All module test suites pass (root: 5476, providers/aws: 813, providers/azure: 696, providers/gcp: 259, pkg: 443)
  • Verified: zero leftover-lint files remain with lint issues; all 97 files with residual issues are PR-owned only

Test plan

  • go build ./... passes on root module and all 4 sub-modules (providers/aws, providers/azure, providers/gcp, pkg)
  • go test ./... passes on root module and all 4 sub-modules
  • golangci-lint run (v2.10.1) on root: residual issues only in PR-owned files (confirmed via cross-check against leftover-lint-issues.txt)
  • golangci-lint run on each sub-module: same result - zero leftover files remain unclean

Summary by CodeRabbit

  • Bug Fixes

    • Improved sanity-command exit codes and tightened flag bounds validation for clearer PASS/FAIL reporting.
    • Improved transaction rollback handling so rollback issues are surfaced instead of being silently ignored.
    • Hardened exchange, recommendations, and email workflows for more consistent, predictable failure handling.
  • New Features

    • Upcoming-purchase API responses now optionally include created_by_user_id.
  • Documentation

    • Refreshed user-facing wording for clearer, consistent messaging.

@cristim cristim added triaged Item has been triaged priority/p1 Next up; this sprint type/chore Maintenance / non-user-visible labels Jun 20, 2026
@cristim

cristim commented Jun 20, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jun 20, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Important

Review skipped

Too many files!

This PR contains 423 files, which is 123 over the limit of 300.

To get a review, narrow the scope:
• coderabbit review --type committed # exclude uncommitted changes
• coderabbit review --dir # limit to a subdirectory
• coderabbit review --base # compare against a closer base

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: c8b1d2e7-fee6-4a2e-99b4-29de899427a7

📥 Commits

Reviewing files that changed from the base of the PR and between d484c9d and 3b8f854.

📒 Files selected for processing (423)
  • .golangci.yml
  • ci_cd_sanity_tests/cmd/azure_sanity/main.go
  • ci_cd_sanity_tests/cmd/ri-exchange/main.go
  • ci_cd_sanity_tests/cmd/sanity/main.go
  • ci_cd_sanity_tests/pkg/sanity/aws/aws.go
  • ci_cd_sanity_tests/pkg/sanity/azure/azure.go
  • ci_cd_sanity_tests/pkg/sanity/azure/azure_test.go
  • ci_cd_sanity_tests/pkg/sanity/report/report.go
  • cmd/cleanup-lambda/main.go
  • cmd/configure_azure.go
  • cmd/configure_gcp.go
  • cmd/configure_test.go
  • cmd/helpers.go
  • cmd/lambda/main.go
  • cmd/lambda/main_test.go
  • cmd/main.go
  • cmd/main_test.go
  • cmd/multi_service.go
  • cmd/multi_service_coverage_test.go
  • cmd/multi_service_csv.go
  • cmd/multi_service_csv_test.go
  • cmd/multi_service_engine_versions.go
  • cmd/multi_service_engine_versions_paginate_test.go
  • cmd/multi_service_filters_test.go
  • cmd/multi_service_helpers.go
  • cmd/multi_service_helpers_test.go
  • cmd/multi_service_stats.go
  • cmd/multi_service_stats_helpers.go
  • cmd/multi_service_stats_test.go
  • cmd/multi_service_test.go
  • cmd/multi_service_test_common_test.go
  • cmd/rekey/main.go
  • cmd/secrets_store.go
  • cmd/server/main.go
  • cmd/validators.go
  • cmd/validators_test.go
  • internal/accounts/org_discovery.go
  • internal/accounts/org_discovery_extra_test.go
  • internal/accounts/org_discovery_test.go
  • internal/analytics/collector.go
  • internal/analytics/collector_test.go
  • internal/analytics/interfaces.go
  • internal/analytics/postgres_analytics.go
  • internal/analytics/postgres_analytics_db_test.go
  • internal/analytics/postgres_analytics_integration_test.go
  • internal/analytics/postgres_analytics_mock_test.go
  • internal/analytics/postgres_analytics_pgxmock_test.go
  • internal/analytics/postgres_analytics_test.go
  • internal/api/coverage_extras_test.go
  • internal/api/coverage_gaps_test.go
  • internal/api/db_rate_limiter.go
  • internal/api/db_rate_limiter_integration_test.go
  • internal/api/exchange_lookup.go
  • internal/api/exchange_lookup_test.go
  • internal/api/handler.go
  • internal/api/handler_accounts.go
  • internal/api/handler_accounts_external_id_test.go
  • internal/api/handler_accounts_router_test.go
  • internal/api/handler_accounts_test.go
  • internal/api/handler_analytics.go
  • internal/api/handler_analytics_test.go
  • internal/api/handler_apikeys.go
  • internal/api/handler_apikeys_test.go
  • internal/api/handler_auth.go
  • internal/api/handler_auth_test.go
  • internal/api/handler_commitment_options.go
  • internal/api/handler_commitment_options_test.go
  • internal/api/handler_config.go
  • internal/api/handler_config_test.go
  • internal/api/handler_coverage_test.go
  • internal/api/handler_dashboard.go
  • internal/api/handler_dashboard_test.go
  • internal/api/handler_docs.go
  • internal/api/handler_docs_test.go
  • internal/api/handler_federation.go
  • internal/api/handler_federation_test.go
  • internal/api/handler_groups.go
  • internal/api/handler_history.go
  • internal/api/handler_history_test.go
  • internal/api/handler_inventory.go
  • internal/api/handler_inventory_test.go
  • internal/api/handler_per_account_perms_test.go
  • internal/api/handler_plans.go
  • internal/api/handler_plans_test.go
  • internal/api/handler_purchases.go
  • internal/api/handler_purchases_guards_test.go
  • internal/api/handler_purchases_revoke.go
  • internal/api/handler_purchases_revoke_test.go
  • internal/api/handler_purchases_test.go
  • internal/api/handler_recommendations.go
  • internal/api/handler_recommendations_refresh.go
  • internal/api/handler_recommendations_test.go
  • internal/api/handler_registrations.go
  • internal/api/handler_registrations_autoenable_test.go
  • internal/api/handler_registrations_recipients_test.go
  • internal/api/handler_ri_exchange.go
  • internal/api/handler_ri_exchange_integration_test.go
  • internal/api/handler_ri_exchange_test.go
  • internal/api/handler_router.go
  • internal/api/handler_router_test.go
  • internal/api/handler_security_test.go
  • internal/api/handler_test.go
  • internal/api/handler_users.go
  • internal/api/handler_users_test.go
  • internal/api/handler_version.go
  • internal/api/handler_version_test.go
  • internal/api/health.go
  • internal/api/inmemory_rate_limiter.go
  • internal/api/middleware.go
  • internal/api/middleware_test.go
  • internal/api/mocks_test.go
  • internal/api/rate_limiter.go
  • internal/api/ri_utilization_cache.go
  • internal/api/ri_utilization_cache_test.go
  • internal/api/router.go
  • internal/api/router_660_permission_flips_test.go
  • internal/api/router_auth_test.go
  • internal/api/router_authuser_test.go
  • internal/api/router_handlers_test.go
  • internal/api/scoping.go
  • internal/api/types.go
  • internal/api/types_apikeys.go
  • internal/api/validation.go
  • internal/api/validation_test.go
  • internal/auth/errors.go
  • internal/auth/interfaces.go
  • internal/auth/service.go
  • internal/auth/service_api.go
  • internal/auth/service_api_test.go
  • internal/auth/service_apikeys.go
  • internal/auth/service_apikeys_api.go
  • internal/auth/service_group.go
  • internal/auth/service_helpers.go
  • internal/auth/service_lockout_test.go
  • internal/auth/service_mfa.go
  • internal/auth/service_password.go
  • internal/auth/service_test.go
  • internal/auth/service_user.go
  • internal/auth/service_user_test.go
  • internal/auth/store_postgres.go
  • internal/auth/test_helpers.go
  • internal/auth/types.go
  • internal/commitmentopts/probe.go
  • internal/commitmentopts/probe_azure.go
  • internal/commitmentopts/probe_test.go
  • internal/commitmentopts/service.go
  • internal/commitmentopts/service_test.go
  • internal/commitmentopts/types.go
  • internal/config/constants.go
  • internal/config/defaults.go
  • internal/config/defaults_test.go
  • internal/config/interfaces.go
  • internal/config/recommendation_overrides.go
  • internal/config/recommendation_overrides_test.go
  • internal/config/resolver.go
  • internal/config/resolver_test.go
  • internal/config/store_postgres.go
  • internal/config/store_postgres_additional_test.go
  • internal/config/store_postgres_cloud_accounts_test.go
  • internal/config/store_postgres_comprehensive_test.go
  • internal/config/store_postgres_db_test.go
  • internal/config/store_postgres_increment_step_test.go
  • internal/config/store_postgres_mock_test.go
  • internal/config/store_postgres_pgxmock_test.go
  • internal/config/store_postgres_recommendations.go
  • internal/config/store_postgres_recommendations_test.go
  • internal/config/store_postgres_registrations.go
  • internal/config/store_postgres_savings_filter_test.go
  • internal/config/store_postgres_test.go
  • internal/config/store_postgres_unit_test.go
  • internal/config/types.go
  • internal/config/types_test.go
  • internal/config/validation.go
  • internal/config/validation_test.go
  • internal/credentials/cipher.go
  • internal/credentials/resolver.go
  • internal/credentials/resolver_test.go
  • internal/database/config.go
  • internal/database/config_test.go
  • internal/database/connection.go
  • internal/database/connection_test.go
  • internal/database/coverage_extra_test.go
  • internal/database/open_from_env.go
  • internal/database/postgres/migrations/000053_executions_account_fk_restrict_test.go
  • internal/database/postgres/migrations/000065_enforce_min_one_admin_test.go
  • internal/database/postgres/migrations/ensure_admin_user_test.go
  • internal/database/postgres/migrations/helpers_test.go
  • internal/database/postgres/migrations/migrate.go
  • internal/database/postgres/migrations/migrate_security_test.go
  • internal/database/postgres/migrations/migration_transactional_test.go
  • internal/database/postgres/migrations/split_savingsplans_test.go
  • internal/database/postgres/testhelpers/postgres.go
  • internal/database/security_test.go
  • internal/deploy/coverage_extra_test.go
  • internal/deploy/docker.go
  • internal/deploy/docker_test.go
  • internal/deploy/frontend.go
  • internal/deploy/mocks.go
  • internal/deploy/profiles.go
  • internal/deploy/types.go
  • internal/email/coverage_extra_test.go
  • internal/email/coverage_test.go
  • internal/email/factory.go
  • internal/email/factory_test.go
  • internal/email/interfaces.go
  • internal/email/nop_sender.go
  • internal/email/nop_sender_test.go
  • internal/email/sender.go
  • internal/email/sender_test.go
  • internal/email/smtp_sender.go
  • internal/email/smtp_sender_test.go
  • internal/email/smtp_server_test.go
  • internal/email/template_renderers.go
  • internal/email/template_renderers_test.go
  • internal/email/templates.go
  • internal/email/templates_test.go
  • internal/execution/executor.go
  • internal/execution/fanout.go
  • internal/execution/fanout_test.go
  • internal/mocks/email.go
  • internal/mocks/secretsmanager.go
  • internal/mocks/ses.go
  • internal/mocks/sns.go
  • internal/mocks/stores.go
  • internal/oidc/aws_signer.go
  • internal/oidc/aws_signer_test.go
  • internal/oidc/azure_factory_test.go
  • internal/oidc/azure_signer.go
  • internal/oidc/factory.go
  • internal/oidc/gcp_signer.go
  • internal/oidc/issuer_cache.go
  • internal/oidc/jwks.go
  • internal/oidc/lambda_issuer.go
  • internal/oidc/lambda_issuer_test.go
  • internal/oidc/signer_test.go
  • internal/purchase/approvals.go
  • internal/purchase/approvals_test.go
  • internal/purchase/coverage_extra_test.go
  • internal/purchase/execution.go
  • internal/purchase/execution_test.go
  • internal/purchase/finalize_revocations.go
  • internal/purchase/manager.go
  • internal/purchase/manager_test.go
  • internal/purchase/messages_test.go
  • internal/purchase/mocks_test.go
  • internal/purchase/money_path_regression_test.go
  • internal/purchase/notifications.go
  • internal/purchase/notifications_test.go
  • internal/purchase/reaper.go
  • internal/purchase/reaper_test.go
  • internal/purchase/scheduled_fire.go
  • internal/purchase/scheduled_fire_test.go
  • internal/reporter/reporter.go
  • internal/runtime/runtime.go
  • internal/scheduler/permission_log_test.go
  • internal/scheduler/scheduler.go
  • internal/scheduler/scheduler_overrides_test.go
  • internal/scheduler/scheduler_suppressions_test.go
  • internal/scheduler/scheduler_test.go
  • internal/secrets/aws_resolver.go
  • internal/secrets/aws_resolver_coverage_test.go
  • internal/secrets/aws_resolver_test.go
  • internal/secrets/azure_resolver.go
  • internal/secrets/azure_resolver_coverage_test.go
  • internal/secrets/azure_resolver_test.go
  • internal/secrets/constructor_error_test.go
  • internal/secrets/env_resolver.go
  • internal/secrets/env_resolver_coverage_test.go
  • internal/secrets/env_resolver_test.go
  • internal/secrets/gcp_resolver.go
  • internal/secrets/gcp_resolver_coverage_test.go
  • internal/secrets/gcp_resolver_grpc_test.go
  • internal/secrets/gcp_resolver_test.go
  • internal/secrets/resolver.go
  • internal/secrets/resolver_coverage_test.go
  • internal/secrets/resolver_test.go
  • internal/server/analytics_collect.go
  • internal/server/app.go
  • internal/server/app_coverage_test.go
  • internal/server/app_test.go
  • internal/server/handler.go
  • internal/server/handler_coverage_test.go
  • internal/server/handler_ri_exchange.go
  • internal/server/handler_ri_exchange_test.go
  • internal/server/handler_test.go
  • internal/server/health.go
  • internal/server/health_test.go
  • internal/server/http.go
  • internal/server/http_test.go
  • internal/server/integration_test.go
  • internal/server/interfaces.go
  • internal/server/lambda.go
  • internal/server/lambda_test.go
  • internal/server/scheduledauth/config.go
  • internal/server/scheduledauth/integration_test.go
  • internal/server/scheduledauth/validator.go
  • internal/server/scheduledauth/validator_test.go
  • internal/server/static.go
  • internal/server/static_test.go
  • internal/server/test_helpers_test.go
  • internal/testutil/mocks.go
  • internal/testutil/postgres.go
  • internal/testutil/testutil.go
  • pkg/common/audit.go
  • pkg/common/audit_test.go
  • pkg/common/engine.go
  • pkg/common/identifiers.go
  • pkg/common/matches.go
  • pkg/common/matches_test.go
  • pkg/common/reservation_name.go
  • pkg/common/reservation_name_test.go
  • pkg/common/service_details_codec.go
  • pkg/common/service_details_codec_test.go
  • pkg/common/tokens.go
  • pkg/common/types.go
  • pkg/common/types_test.go
  • pkg/concurrency/concurrency.go
  • pkg/concurrency/concurrency_test.go
  • pkg/config/config_test.go
  • pkg/config/load.go
  • pkg/config/types.go
  • pkg/errors/errors.go
  • pkg/exchange/auto.go
  • pkg/exchange/auto_test.go
  • pkg/exchange/exchange.go
  • pkg/exchange/exchange_test.go
  • pkg/exchange/fail_loud_test.go
  • pkg/exchange/multi_target_test.go
  • pkg/exchange/reshape.go
  • pkg/exchange/reshape_crossfamily_test.go
  • pkg/exchange/reshape_test.go
  • pkg/logging/logger.go
  • pkg/provider/credentials.go
  • pkg/provider/credentials_test.go
  • pkg/provider/factory.go
  • pkg/provider/factory_interface.go
  • pkg/provider/factory_test.go
  • pkg/provider/interface.go
  • pkg/provider/registry.go
  • pkg/provider/registry_test.go
  • pkg/retry/exponential.go
  • pkg/retry/exponential_test.go
  • pkg/scorer/scorer.go
  • providers/aws/internal/purchasecfg/config.go
  • providers/aws/internal/purchasecfg/config_test.go
  • providers/aws/internal/tagging/purchase_tags.go
  • providers/aws/internal/tagging/purchase_tags_test.go
  • providers/aws/provider.go
  • providers/aws/provider_test.go
  • providers/aws/recommendations/client.go
  • providers/aws/recommendations/client_test.go
  • providers/aws/recommendations/converters_test.go
  • providers/aws/recommendations/expiry.go
  • providers/aws/recommendations/family_nu.go
  • providers/aws/recommendations/parser_services.go
  • providers/aws/recommendations/parser_services_test.go
  • providers/aws/recommendations/parser_sp_test.go
  • providers/aws/recommendations/ratelimiter.go
  • providers/aws/recommendations/ratelimiter_test.go
  • providers/aws/recommendations/usage_history.go
  • providers/aws/service_client.go
  • providers/aws/service_client_test.go
  • providers/aws/services/ec2/client.go
  • providers/aws/services/ec2/client_test.go
  • providers/aws/services/elasticache/client.go
  • providers/aws/services/elasticache/client_test.go
  • providers/aws/services/memorydb/client.go
  • providers/aws/services/memorydb/client_test.go
  • providers/aws/services/opensearch/client.go
  • providers/aws/services/opensearch/client_test.go
  • providers/aws/services/rds/client.go
  • providers/aws/services/rds/client_test.go
  • providers/aws/services/redshift/client.go
  • providers/aws/services/redshift/client_test.go
  • providers/aws/services/savingsplans/client.go
  • providers/aws/services/savingsplans/client_test.go
  • providers/azure/internal/pricing/retail_prices.go
  • providers/azure/internal/pricing/retail_prices_test.go
  • providers/azure/internal/recommendations/converter.go
  • providers/azure/internal/recommendations/converter_test.go
  • providers/azure/mocks/azure_mocks.go
  • providers/azure/provider.go
  • providers/azure/provider_test.go
  • providers/azure/recommendations.go
  • providers/azure/recommendations_test.go
  • providers/azure/ri_utilization_test.go
  • providers/azure/services.go
  • providers/azure/services/cache/client.go
  • providers/azure/services/cache/client_test.go
  • providers/azure/services/compute/client.go
  • providers/azure/services/compute/client_test.go
  • providers/azure/services/compute/exchange.go
  • providers/azure/services/compute/exchange_test.go
  • providers/azure/services/cosmosdb/client.go
  • providers/azure/services/cosmosdb/client_test.go
  • providers/azure/services/database/client.go
  • providers/azure/services/database/client_test.go
  • providers/azure/services/internal/reservations/displayname.go
  • providers/azure/services/internal/reservations/displayname_test.go
  • providers/azure/services/internal/reservations/purchase.go
  • providers/azure/services/internal/reservations/purchase_test.go
  • providers/azure/services/managedredis/client.go
  • providers/azure/services/managedredis/client_test.go
  • providers/azure/services/savingsplans/client.go
  • providers/azure/services/savingsplans/client_test.go
  • providers/azure/services/search/client.go
  • providers/azure/services/search/client_test.go
  • providers/azure/services/synapse/client.go
  • providers/azure/services/synapse/client_test.go
  • providers/azure/services_test.go
  • providers/gcp/permission_errors_test.go
  • providers/gcp/provider.go
  • providers/gcp/provider_test.go
  • providers/gcp/recommendations.go
  • providers/gcp/recommendations_test.go
  • providers/gcp/services/cloudsql/client.go
  • providers/gcp/services/cloudsql/client_test.go
  • providers/gcp/services/cloudstorage/client.go
  • providers/gcp/services/cloudstorage/client_test.go
  • providers/gcp/services/computeengine/client.go
  • providers/gcp/services/computeengine/client_test.go
  • providers/gcp/services/memorystore/client.go
  • providers/gcp/services/memorystore/client_test.go

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

The PR updates many APIs to use pointer-based configs, filters, records, and notification payloads. It also reshapes exchange, analytics, and email types, adds run()-based CLI exits, adjusts database/migration handling, and updates many tests, mocks, and comments to match the new contracts.

Changes

Cross-cutting contract and flow updates

Layer / File(s) Summary
Exchange, common types, and audit/reservation helpers
pkg/exchange/*, pkg/common/*
Replaces exchange request/response/client types, adds pointer-based quote/execute flows, renames exchange record/mode types, and updates audit, reservation-name, recommendation-scaling, and shared type definitions for pointer inputs and nil-safe behavior.
Config, analytics, commitment options, and AWS config plumbing
internal/config/*, internal/analytics/*, internal/commitmentopts/*, internal/accounts/org_discovery.go, providers/aws/internal/purchasecfg/config.go
Switches store/filter/config interfaces and callers to pointers, renames config-setting types, refactors analytics store/query contracts, changes commitment-option probers to *aws.Config, and updates related validation/default helpers.
Email system and mocks
internal/email/*, internal/mocks/email.go, internal/mocks/ses.go, internal/mocks/sns.go, internal/mocks/stores.go, internal/email/*_test.go
Moves sender/rendering APIs and mocks to pointer payloads, updates SMTP/factory constructors, refactors message building, and aligns sender/store test doubles with the new method signatures and safer mock return handling.
API handlers, router, and DTOs
internal/api/*
Refactors handler flows to use explicit error assignment, pointer-based request plumbing, updated route/helper return shapes, reordered DTO fields, and revised purchase/RI exchange, docs, version, security, scoping, and commitment-option behavior.
Database, migrations, and connection handling
internal/database/*, internal/database/postgres/migrations/*
Adds pointer-based transaction/config handling, safer type checks, improved rollback/close handling, TLS-aware migration DSN building, updated DB config tags, and related test coverage.
CLI entrypoints and multi-service tooling
ci_cd_sanity_tests/cmd/*, cmd/*
Introduces run() wrappers for command exits, adds flag-range validation, refactors multi-service CSV/report/purchase flows toward pointer inputs, and updates helper/test wiring for the new request shapes.
Auth, struct reordering, and comment normalization
internal/auth/*, internal/deploy/*, various comment-only files
Updates auth service user/password/session/key types and mock helpers; normalizes struct field ordering in auth, deploy, and other types; applies spelling normalization across the codebase.

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~120 minutes

Possibly related PRs

  • LeanerCloud/CUDly#1049: Direct overlap with the analytics collector/store contract changes and pointer-based QuerySavings flow.
  • LeanerCloud/CUDly#79: Direct overlap with exchange lookup / recommendation-to-offering plumbing in the API layer.
  • LeanerCloud/CUDly#1042: Direct overlap with RI-exchange handler pointer-based request type changes.

Suggested labels

triaged, priority/p1, severity/medium, urgency/this-sprint, impact/internal, effort/xl, type/chore

Poem

🐇 I hopped through pointers, neat and sly,
Past emails, exchanges, and configs high.
With run() paths and nil-safe streams,
The burrow hums with tidy dreams.
Canceled to canceled, bounds held tight—
Moonlit code feels soft and right.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 68.78% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the PR’s main goal: removing golangci-lint debt across unaffected files.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/leftover-lint

Comment @coderabbitai help to get the list of available commands.

@coderabbitai

coderabbitai Bot commented Jun 20, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@cristim

cristim commented Jun 21, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jun 21, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 7

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
cmd/multi_service.go (1)

260-266: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Honor cfg.DryRun in CSV execution mode.

Line 262 computes CSV isDryRun from !cfg.ActualPurchase only, so --purchase --dry-run=true can still execute real purchases in this path. Align it with the non-CSV safety gate.

💡 Suggested fix
-	isDryRun := !cfg.ActualPurchase
+	isDryRun := !cfg.ActualPurchase || cfg.DryRun

Based on learnings: “real purchases must only occur when dry-run is explicitly disabled … verify that cfg.DryRun is actually respected in every path (CSV mode vs other modes).”

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cmd/multi_service.go` around lines 260 - 266, The isDryRun calculation in the
runToolFromCSV function only considers cfg.ActualPurchase but ignores
cfg.DryRun, allowing real purchases to execute even when dry-run is explicitly
enabled. Update the isDryRun assignment to check both cfg.DryRun and
cfg.ActualPurchase together, ensuring that isDryRun is true when either the
dry-run flag is true OR actual purchase is disabled. This aligns the CSV
execution path with the safety gate used in non-CSV modes.

Source: Learnings

internal/email/smtp_sender.go (1)

44-58: ⚠️ Potential issue | 🟠 Major

Guard NewSMTPSender against nil input and stop mutating caller-owned config.

Line 45 dereferences cfg without a nil check, so NewSMTPSender(nil) panics. Lines 53-58 mutate the caller's config in place (cfg.Port, cfg.UseTLS), introducing a side effect that changes the caller's struct unexpectedly.

🔧 Proposed fix
 func NewSMTPSender(cfg *SMTPConfig) (*SMTPSender, error) {
-	if cfg.Host == "" {
+	if cfg == nil {
+		return nil, fmt.Errorf("SMTP config is required")
+	}
+	local := *cfg
+
+	if local.Host == "" {
 		return nil, fmt.Errorf("SMTP host is required")
 	}
-	if cfg.FromEmail == "" {
+	if local.FromEmail == "" {
 		return nil, fmt.Errorf("from email is required")
 	}
 
 	// Set defaults
-	if cfg.Port == 0 {
-		cfg.Port = 587 // Default to TLS port
+	if local.Port == 0 {
+		local.Port = 587 // Default to TLS port
 	}
-	if !cfg.UseTLS && cfg.Port == 587 {
-		cfg.UseTLS = true // Enable TLS for port 587 by default
+	if !local.UseTLS && local.Port == 587 {
+		local.UseTLS = true // Enable TLS for port 587 by default
 	}
 
-	notifyEmail := cfg.NotifyEmail
+	notifyEmail := local.NotifyEmail
 	if notifyEmail == "" {
-		notifyEmail = cfg.FromEmail
+		notifyEmail = local.FromEmail
 	}
 
 	return &SMTPSender{
-		host:          cfg.Host,
-		port:          cfg.Port,
-		username:      cfg.Username,
-		password:      cfg.Password,
-		fromEmail:     cfg.FromEmail,
-		fromName:      cfg.FromName,
+		host:          local.Host,
+		port:          local.Port,
+		username:      local.Username,
+		password:      local.Password,
+		fromEmail:     local.FromEmail,
+		fromName:      local.FromName,
 		notifyEmail:   notifyEmail,
-		useTLS:        cfg.UseTLS,
-		allowInsecure: cfg.AllowInsecure,
+		useTLS:        local.UseTLS,
+		allowInsecure: local.AllowInsecure,
 	}, nil
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/email/smtp_sender.go` around lines 44 - 58, The NewSMTPSender
function has two issues: it dereferences cfg without checking for nil first
(causing a panic on nil input), and it mutates the caller's config struct by
directly modifying cfg.Port and cfg.UseTLS, which is an unexpected side effect.
Fix this by adding a nil check for cfg at the beginning of NewSMTPSender before
any dereference, and instead of modifying cfg directly, create a copy of the
config values and apply defaults to the copy, then pass those values (not the
mutated cfg) to the SMTPSender struct initialization.
🧹 Nitpick comments (2)
internal/api/handler_inventory_test.go (1)

451-451: ⚡ Quick win

Keep ListRecommendations argument assertions strict in these tests.

Using mock.Anything here drops verification that the handler still sends the expected empty recommendation filter. Prefer matching &config.RecommendationFilter{} (or mock.MatchedBy) so future filter regressions fail fast.

Also applies to: 654-654

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/api/handler_inventory_test.go` at line 451, Replace the
`mock.Anything` argument in the `mockScheduler.On("ListRecommendations", ctx,
mock.Anything)` calls with a strict matcher that verifies the expected argument
being passed (either `&config.RecommendationFilter{}` or use `mock.MatchedBy`
with a matching function). This ensures the handler is passing the correct
recommendation filter and prevents future regressions. Apply this change to both
occurrences of the ListRecommendations mock setup.
internal/api/handler_per_account_perms_test.go (1)

841-842: ⚡ Quick win

Avoid mock.Anything for recommendation-filter arguments in permission tests.

These tests are validating scoped vs admin visibility; keeping explicit filter expectations (empty pointer filter shape) protects that API contract and catches accidental filter changes.

Also applies to: 912-913

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/api/handler_per_account_perms_test.go` around lines 841 - 842, The
mock setup for ListRecommendations is using mock.Anything for the
recommendation-filter argument, which is too loose for permission validation
tests that verify scoped vs admin visibility. Replace mock.Anything with an
explicit expectation of the filter argument (empty pointer filter shape) in the
ListRecommendations mock calls to properly validate the API contract. This
change should be applied to all occurrences of this pattern, including the ones
at lines 841-842 and 912-913.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@internal/accounts/org_discovery.go`:
- Around line 33-34: The function DiscoverOrgAccounts accepts a pointer
parameter cfg of type *aws.Config and dereferences it unconditionally on the
line where it calls discoverWithClient, which will cause a panic if cfg is nil.
Add a nil guard check at the beginning of the DiscoverOrgAccounts function that
validates cfg is not nil before attempting to dereference it, and return an
appropriate error if the check fails.

In `@internal/api/handler_purchases.go`:
- Around line 381-383: The error handling logic in the cancel execution handler
is incorrectly mapping non-conflict errors to a 409 status code. The condition
checks if the error is NOT ErrExecutionNotInExpectedStatus and returns a 409,
but this is backwards—a 409 should only be used when the error IS
ErrExecutionNotInExpectedStatus (a true status conflict). Invert the condition
so that when the error IS ErrExecutionNotInExpectedStatus, return a 409
conflict, and for all other errors like transient DB failures, return an
appropriate 5xx error instead using a suitable NewServerError or similar
mechanism. This ensures that true status conflicts are properly distinguished
from unexpected backend failures.

In `@internal/api/handler_ri_exchange_test.go`:
- Around line 287-292: In the mockStore.On("GetRIExchangeRecord") fixture that
creates the RIExchangeRecord with Status "canceled", change the spelling from
"canceled" to "cancelled" to align with the consistent spelling convention used
throughout the RI exchange database contract and other test fixtures in this
file.

In `@internal/config/interfaces.go`:
- Around line 86-103: The comments for CancelExecutionAtomic and
CancelScheduledExecutionAtomic methods contain contradictory information about
which statuses they handle. The CancelExecutionAtomic method comment suggests it
supports the scheduled status for Gmail-style pre-fire delay revoke, but the
CancelScheduledExecutionAtomic method comment states that the pending/notified
set intentionally is not extended from CancelExecutionAtomic, implying
CancelExecutionAtomic does not handle scheduled status. Clarify and align both
method comments to document the exact set of statuses each method accepts (for
CancelExecutionAtomic, confirm whether it accepts scheduled, pending, notified,
or some combination) and ensure CancelScheduledExecutionAtomic clearly explains
how its status handling differs from CancelExecutionAtomic. The documented state
model must match the actual implementation contract.

In `@internal/config/store_postgres_savings_filter_test.go`:
- Around line 216-220: The subtest name in the t.Run call at line 216 states
"MinSavingsPct zero is never pushed into SQL" but the test creates a
RecommendationFilter with MinSavingsPct set to 30, not zero. Update the subtest
name to accurately reflect the actual input value being tested (30 instead of
zero) so the test description matches the test implementation.

In `@internal/database/postgres/migrations/migrate.go`:
- Around line 545-547: The buildMigrateDSN function currently infers sslmode
only from whether TLSConfig is nil, which causes stricter SSL modes like
verify-ca and verify-full to be downgraded to require. To fix this, modify the
buildMigrateDSN function signature to accept the original SSLMode string as a
parameter in addition to the pgxpool.Config, then use that SSLMode value
directly when constructing the DSN instead of inferring it from TLSConfig.
Update all three call sites (newMigratorWithRecovery, MigrateToVersion, and
GetMigrationVersion) to pass the appropriate SSL mode value when calling
buildMigrateDSN.

In `@internal/email/factory.go`:
- Around line 208-209: The NewSenderWithConfig function takes a pointer
parameter cfg of type FactoryConfig but directly accesses cfg.Provider in the
switch statement without first validating that cfg is not nil, which will cause
a panic if a nil pointer is passed. Add an explicit nil check at the very
beginning of the NewSenderWithConfig function that returns an appropriate error
if cfg is nil, allowing the function to fail gracefully instead of panicking.

---

Outside diff comments:
In `@cmd/multi_service.go`:
- Around line 260-266: The isDryRun calculation in the runToolFromCSV function
only considers cfg.ActualPurchase but ignores cfg.DryRun, allowing real
purchases to execute even when dry-run is explicitly enabled. Update the
isDryRun assignment to check both cfg.DryRun and cfg.ActualPurchase together,
ensuring that isDryRun is true when either the dry-run flag is true OR actual
purchase is disabled. This aligns the CSV execution path with the safety gate
used in non-CSV modes.

In `@internal/email/smtp_sender.go`:
- Around line 44-58: The NewSMTPSender function has two issues: it dereferences
cfg without checking for nil first (causing a panic on nil input), and it
mutates the caller's config struct by directly modifying cfg.Port and
cfg.UseTLS, which is an unexpected side effect. Fix this by adding a nil check
for cfg at the beginning of NewSMTPSender before any dereference, and instead of
modifying cfg directly, create a copy of the config values and apply defaults to
the copy, then pass those values (not the mutated cfg) to the SMTPSender struct
initialization.

---

Nitpick comments:
In `@internal/api/handler_inventory_test.go`:
- Line 451: Replace the `mock.Anything` argument in the
`mockScheduler.On("ListRecommendations", ctx, mock.Anything)` calls with a
strict matcher that verifies the expected argument being passed (either
`&config.RecommendationFilter{}` or use `mock.MatchedBy` with a matching
function). This ensures the handler is passing the correct recommendation filter
and prevents future regressions. Apply this change to both occurrences of the
ListRecommendations mock setup.

In `@internal/api/handler_per_account_perms_test.go`:
- Around line 841-842: The mock setup for ListRecommendations is using
mock.Anything for the recommendation-filter argument, which is too loose for
permission validation tests that verify scoped vs admin visibility. Replace
mock.Anything with an explicit expectation of the filter argument (empty pointer
filter shape) in the ListRecommendations mock calls to properly validate the API
contract. This change should be applied to all occurrences of this pattern,
including the ones at lines 841-842 and 912-913.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 38a40bc6-7b20-4dad-b513-ca701ca76a79

📥 Commits

Reviewing files that changed from the base of the PR and between 451a70f and 87b00d6.

📒 Files selected for processing (300)
  • ci_cd_sanity_tests/cmd/azure_sanity/main.go
  • ci_cd_sanity_tests/cmd/ri-exchange/main.go
  • ci_cd_sanity_tests/cmd/sanity/main.go
  • ci_cd_sanity_tests/pkg/sanity/aws/aws.go
  • ci_cd_sanity_tests/pkg/sanity/azure/azure.go
  • ci_cd_sanity_tests/pkg/sanity/azure/azure_test.go
  • ci_cd_sanity_tests/pkg/sanity/report/report.go
  • cmd/cleanup-lambda/main.go
  • cmd/helpers.go
  • cmd/lambda/main.go
  • cmd/lambda/main_test.go
  • cmd/main.go
  • cmd/multi_service.go
  • cmd/multi_service_coverage_test.go
  • cmd/multi_service_csv.go
  • cmd/multi_service_csv_test.go
  • cmd/multi_service_engine_versions.go
  • cmd/multi_service_engine_versions_paginate_test.go
  • cmd/multi_service_helpers.go
  • cmd/multi_service_helpers_test.go
  • cmd/multi_service_stats.go
  • cmd/multi_service_stats_helpers.go
  • cmd/multi_service_stats_test.go
  • cmd/multi_service_test.go
  • cmd/multi_service_test_common_test.go
  • cmd/rekey/main.go
  • cmd/secrets_store.go
  • cmd/server/main.go
  • cmd/validators.go
  • cmd/validators_test.go
  • internal/accounts/org_discovery.go
  • internal/accounts/org_discovery_extra_test.go
  • internal/accounts/org_discovery_test.go
  • internal/analytics/collector.go
  • internal/analytics/collector_test.go
  • internal/analytics/interfaces.go
  • internal/analytics/postgres_analytics.go
  • internal/analytics/postgres_analytics_db_test.go
  • internal/analytics/postgres_analytics_integration_test.go
  • internal/analytics/postgres_analytics_mock_test.go
  • internal/analytics/postgres_analytics_pgxmock_test.go
  • internal/analytics/postgres_analytics_test.go
  • internal/api/coverage_extras_test.go
  • internal/api/coverage_gaps_test.go
  • internal/api/db_rate_limiter.go
  • internal/api/db_rate_limiter_integration_test.go
  • internal/api/exchange_lookup.go
  • internal/api/exchange_lookup_test.go
  • internal/api/handler.go
  • internal/api/handler_accounts.go
  • internal/api/handler_accounts_external_id_test.go
  • internal/api/handler_accounts_router_test.go
  • internal/api/handler_accounts_test.go
  • internal/api/handler_analytics.go
  • internal/api/handler_analytics_test.go
  • internal/api/handler_apikeys.go
  • internal/api/handler_auth.go
  • internal/api/handler_auth_test.go
  • internal/api/handler_commitment_options.go
  • internal/api/handler_commitment_options_test.go
  • internal/api/handler_config.go
  • internal/api/handler_config_test.go
  • internal/api/handler_coverage_test.go
  • internal/api/handler_dashboard.go
  • internal/api/handler_dashboard_test.go
  • internal/api/handler_docs.go
  • internal/api/handler_docs_test.go
  • internal/api/handler_federation.go
  • internal/api/handler_federation_test.go
  • internal/api/handler_groups.go
  • internal/api/handler_history.go
  • internal/api/handler_history_test.go
  • internal/api/handler_inventory.go
  • internal/api/handler_inventory_test.go
  • internal/api/handler_per_account_perms_test.go
  • internal/api/handler_plans.go
  • internal/api/handler_plans_test.go
  • internal/api/handler_purchases.go
  • internal/api/handler_purchases_guards_test.go
  • internal/api/handler_purchases_revoke.go
  • internal/api/handler_purchases_revoke_test.go
  • internal/api/handler_purchases_test.go
  • internal/api/handler_recommendations.go
  • internal/api/handler_recommendations_test.go
  • internal/api/handler_registrations.go
  • internal/api/handler_registrations_autoenable_test.go
  • internal/api/handler_registrations_recipients_test.go
  • internal/api/handler_ri_exchange.go
  • internal/api/handler_ri_exchange_integration_test.go
  • internal/api/handler_ri_exchange_test.go
  • internal/api/handler_router.go
  • internal/api/handler_router_test.go
  • internal/api/handler_security_test.go
  • internal/api/handler_test.go
  • internal/api/handler_users.go
  • internal/api/handler_users_test.go
  • internal/api/handler_version.go
  • internal/api/handler_version_test.go
  • internal/api/health.go
  • internal/api/inmemory_rate_limiter.go
  • internal/api/middleware.go
  • internal/api/middleware_test.go
  • internal/api/mocks_test.go
  • internal/api/rate_limiter.go
  • internal/api/ri_utilization_cache.go
  • internal/api/ri_utilization_cache_test.go
  • internal/api/router.go
  • internal/api/router_660_permission_flips_test.go
  • internal/api/router_authuser_test.go
  • internal/api/router_handlers_test.go
  • internal/api/scoping.go
  • internal/api/types.go
  • internal/api/types_apikeys.go
  • internal/api/validation_test.go
  • internal/auth/errors.go
  • internal/auth/interfaces.go
  • internal/auth/service.go
  • internal/auth/service_api.go
  • internal/auth/service_apikeys_api.go
  • internal/auth/service_helpers.go
  • internal/auth/service_lockout_test.go
  • internal/auth/service_password.go
  • internal/auth/service_user.go
  • internal/auth/service_user_test.go
  • internal/auth/test_helpers.go
  • internal/auth/types.go
  • internal/commitmentopts/probe.go
  • internal/commitmentopts/probe_azure.go
  • internal/commitmentopts/probe_test.go
  • internal/commitmentopts/service.go
  • internal/commitmentopts/service_test.go
  • internal/commitmentopts/types.go
  • internal/config/constants.go
  • internal/config/defaults.go
  • internal/config/defaults_test.go
  • internal/config/interfaces.go
  • internal/config/recommendation_overrides.go
  • internal/config/recommendation_overrides_test.go
  • internal/config/resolver.go
  • internal/config/resolver_test.go
  • internal/config/store_postgres.go
  • internal/config/store_postgres_additional_test.go
  • internal/config/store_postgres_cloud_accounts_test.go
  • internal/config/store_postgres_comprehensive_test.go
  • internal/config/store_postgres_db_test.go
  • internal/config/store_postgres_increment_step_test.go
  • internal/config/store_postgres_mock_test.go
  • internal/config/store_postgres_pgxmock_test.go
  • internal/config/store_postgres_recommendations.go
  • internal/config/store_postgres_recommendations_test.go
  • internal/config/store_postgres_registrations.go
  • internal/config/store_postgres_savings_filter_test.go
  • internal/config/store_postgres_test.go
  • internal/config/store_postgres_unit_test.go
  • internal/config/types.go
  • internal/config/types_test.go
  • internal/config/validation.go
  • internal/config/validation_test.go
  • internal/database/config.go
  • internal/database/config_test.go
  • internal/database/connection.go
  • internal/database/connection_test.go
  • internal/database/coverage_extra_test.go
  • internal/database/open_from_env.go
  • internal/database/postgres/migrations/000053_executions_account_fk_restrict_test.go
  • internal/database/postgres/migrations/000065_enforce_min_one_admin_test.go
  • internal/database/postgres/migrations/ensure_admin_user_test.go
  • internal/database/postgres/migrations/helpers_test.go
  • internal/database/postgres/migrations/migrate.go
  • internal/database/postgres/migrations/migrate_security_test.go
  • internal/database/postgres/migrations/migration_transactional_test.go
  • internal/database/postgres/migrations/split_savingsplans_test.go
  • internal/database/postgres/testhelpers/postgres.go
  • internal/database/security_test.go
  • internal/deploy/profiles.go
  • internal/deploy/types.go
  • internal/email/coverage_extra_test.go
  • internal/email/coverage_test.go
  • internal/email/factory.go
  • internal/email/factory_test.go
  • internal/email/interfaces.go
  • internal/email/nop_sender.go
  • internal/email/nop_sender_test.go
  • internal/email/sender.go
  • internal/email/sender_test.go
  • internal/email/smtp_sender.go
  • internal/email/smtp_sender_test.go
  • internal/email/smtp_server_test.go
  • internal/email/template_renderers.go
  • internal/email/template_renderers_test.go
  • internal/email/templates.go
  • internal/email/templates_test.go
  • internal/execution/executor.go
  • internal/execution/fanout.go
  • internal/execution/fanout_test.go
  • internal/mocks/email.go
  • internal/mocks/secretsmanager.go
  • internal/mocks/ses.go
  • internal/mocks/sns.go
  • internal/mocks/stores.go
  • internal/oidc/aws_signer.go
  • internal/oidc/aws_signer_test.go
  • internal/oidc/azure_factory_test.go
  • internal/oidc/azure_signer.go
  • internal/oidc/factory.go
  • internal/oidc/gcp_signer.go
  • internal/oidc/issuer_cache.go
  • internal/oidc/jwks.go
  • internal/oidc/lambda_issuer.go
  • internal/oidc/lambda_issuer_test.go
  • internal/oidc/signer_test.go
  • internal/purchase/coverage_extra_test.go
  • internal/purchase/execution.go
  • internal/purchase/execution_test.go
  • internal/purchase/finalize_revocations.go
  • internal/purchase/manager.go
  • internal/purchase/manager_test.go
  • internal/purchase/messages_test.go
  • internal/purchase/mocks_test.go
  • internal/purchase/money_path_regression_test.go
  • internal/purchase/notifications.go
  • internal/purchase/notifications_test.go
  • internal/purchase/reaper.go
  • internal/purchase/reaper_test.go
  • internal/purchase/scheduled_fire.go
  • internal/purchase/scheduled_fire_test.go
  • internal/reporter/reporter.go
  • internal/runtime/runtime.go
  • internal/scheduler/permission_log_test.go
  • internal/scheduler/scheduler.go
  • internal/scheduler/scheduler_overrides_test.go
  • internal/scheduler/scheduler_suppressions_test.go
  • internal/scheduler/scheduler_test.go
  • internal/secrets/aws_resolver.go
  • internal/secrets/aws_resolver_coverage_test.go
  • internal/secrets/aws_resolver_test.go
  • internal/secrets/azure_resolver.go
  • internal/secrets/azure_resolver_coverage_test.go
  • internal/secrets/azure_resolver_test.go
  • internal/secrets/constructor_error_test.go
  • internal/secrets/env_resolver.go
  • internal/secrets/env_resolver_coverage_test.go
  • internal/secrets/env_resolver_test.go
  • internal/secrets/gcp_resolver.go
  • internal/secrets/gcp_resolver_coverage_test.go
  • internal/secrets/gcp_resolver_grpc_test.go
  • internal/secrets/gcp_resolver_test.go
  • internal/secrets/resolver.go
  • internal/secrets/resolver_coverage_test.go
  • internal/secrets/resolver_test.go
  • internal/server/analytics_collect.go
  • internal/server/app.go
  • internal/server/app_coverage_test.go
  • internal/server/app_test.go
  • internal/server/handler.go
  • internal/server/handler_coverage_test.go
  • internal/server/handler_ri_exchange.go
  • internal/server/handler_ri_exchange_test.go
  • internal/server/handler_test.go
  • internal/server/health.go
  • internal/server/health_test.go
  • internal/server/http.go
  • internal/server/http_test.go
  • internal/server/integration_test.go
  • internal/server/interfaces.go
  • internal/server/lambda.go
  • internal/server/lambda_test.go
  • internal/server/scheduledauth/config.go
  • internal/server/scheduledauth/integration_test.go
  • internal/server/scheduledauth/validator.go
  • internal/server/scheduledauth/validator_test.go
  • internal/server/static.go
  • internal/server/static_test.go
  • internal/server/test_helpers_test.go
  • internal/testutil/mocks.go
  • internal/testutil/postgres.go
  • internal/testutil/testutil.go
  • pkg/common/audit.go
  • pkg/common/audit_test.go
  • pkg/common/engine.go
  • pkg/common/identifiers.go
  • pkg/common/matches.go
  • pkg/common/matches_test.go
  • pkg/common/reservation_name.go
  • pkg/common/reservation_name_test.go
  • pkg/common/service_details_codec.go
  • pkg/common/service_details_codec_test.go
  • pkg/common/tokens.go
  • pkg/common/types.go
  • pkg/common/types_test.go
  • pkg/concurrency/concurrency.go
  • pkg/concurrency/concurrency_test.go
  • pkg/config/config_test.go
  • pkg/config/load.go
  • pkg/config/types.go
  • pkg/errors/errors.go
  • pkg/exchange/auto.go
  • pkg/exchange/auto_test.go
  • pkg/exchange/exchange.go
  • pkg/exchange/exchange_test.go

Comment thread internal/accounts/org_discovery.go
Comment thread internal/api/handler_purchases.go
Comment thread internal/api/handler_ri_exchange_test.go
Comment thread internal/config/interfaces.go Outdated
Comment thread internal/config/store_postgres_savings_filter_test.go Outdated
Comment thread internal/database/postgres/migrations/migrate.go
Comment thread internal/email/factory.go
@cristim cristim added severity/medium Moderate harm urgency/this-sprint Within the current sprint impact/internal Team-internal only effort/xl Multi-week / refactor labels Jun 24, 2026
cristim added a commit that referenced this pull request Jun 24, 2026
…ncelled consistency

CodeRabbit findings on the value->pointer cascade and assembly artifacts:

Nil guards on exported pointer-param functions that dereference without a
check (panic -> explicit failure):
- internal/accounts/org_discovery.go DiscoverOrgAccounts: error on nil cfg
- internal/email/factory.go NewSenderWithConfig: error on nil cfg
- pkg/exchange/auto.go RunAutoExchange: error on nil params
- pkg/exchange/exchange.go NewClient: panic on nil cfg (no error return)
- pkg/common/{audit,reservation_name,types}.go NewAuditRecord /
  BuildReservationName / ScaleRecommendationCosts: panic on nil (no error return)
- providers/aws/internal/purchasecfg/config.go NewConfig: panic on nil base

Cancelled DB-status consistency: the assembly's blanket cancelled->canceled
misspell rename downgraded API response status values and store-mock returns
that the frontend matches on 'cancelled'. Revert the DB-status VALUES to
'cancelled' + nolint:misspell while leaving prose comments as 'canceled':
- handler_purchases.go (3 response values), handler_purchases_revoke.go (1)
- handler_ri_exchange_test.go fixture, plus response-status assertions in
  handler_purchases_test.go / handler_purchases_revoke_test.go / handler_test.go

HTTP status classification (handler_purchases.go cancelOrRecoverExecution):
non-conflict transition failures now return a plain wrapped error (-> 500,
generic body, raw backend text only in the server log) instead of a 409 that
leaked backend text. 409 stays reserved for true status conflicts.

Migration SSL mode (migrate.go buildMigrateDSN): recover the exact sslmode
from the parsed pgx TLSConfig instead of collapsing every TLS-enabled mode to
require, so verify-ca / verify-full are no longer silently downgraded during
migrations. Add a regression test pinning the pgx-version-specific mapping.

Doc/test accuracy:
- interfaces.go CancelExecutionAtomic doc: align with the store contract
  ('scheduled' is handled by CancelScheduledExecutionAtomic, not here)
- store_postgres_savings_filter_test.go: rename subtest to match MinSavingsPct=30
@cristim

cristim commented Jun 24, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jun 24, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@internal/api/handler_purchases_revoke_test.go`:
- Around line 591-592: The status assertion in the revoke test is inconsistent
with the current mock fixture: the shared CancelExecutionAtomic default returns
"canceled", while this case expects "cancelled". Update the test setup around
the relevant CancelExecutionAtomic mock in the revoke test to explicitly return
the DB schema value for this case, or change the shared default in the shared
mock helper so the assertion in m["status"] matches the mocked CAS result
consistently across the test suite.

In `@pkg/common/types.go`:
- Around line 181-184: ScaleRecommendationCosts currently panics when rec is
nil, which breaks the new nil-safe contract for this exported helper. Update
ScaleRecommendationCosts in types.go to handle a nil *Recommendation gracefully
by returning a safe zero value or otherwise preserving a non-panicking contract,
and keep the behavior consistent for callers of Recommendation and
ScaleRecommendationCosts.

In `@pkg/exchange/exchange.go`:
- Around line 173-176: The exported constructor NewClient currently panics when
passed a nil *sdkaws.Config, turning invalid input into a process crash. Update
NewClient in exchange.go to use a non-nil config requirement at the type level
again, or change its signature to return an error and handle the nil case
through normal validation instead of panic; also adjust any call sites or
related constructor logic in Client creation to match the new contract.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 8a3922e0-1755-4e34-aa67-45c518920bd6

📥 Commits

Reviewing files that changed from the base of the PR and between 87b00d6 and 3b6e353.

📒 Files selected for processing (18)
  • internal/accounts/org_discovery.go
  • internal/api/handler_purchases.go
  • internal/api/handler_purchases_revoke.go
  • internal/api/handler_purchases_revoke_test.go
  • internal/api/handler_purchases_test.go
  • internal/api/handler_ri_exchange_test.go
  • internal/api/handler_test.go
  • internal/config/interfaces.go
  • internal/config/store_postgres_savings_filter_test.go
  • internal/database/postgres/migrations/migrate.go
  • internal/database/postgres/migrations/migrate_security_test.go
  • internal/email/factory.go
  • pkg/common/audit.go
  • pkg/common/reservation_name.go
  • pkg/common/types.go
  • pkg/exchange/auto.go
  • pkg/exchange/exchange.go
  • providers/aws/internal/purchasecfg/config.go
✅ Files skipped from review due to trivial changes (1)
  • internal/api/handler_test.go
🚧 Files skipped from review as they are similar to previous changes (7)
  • internal/accounts/org_discovery.go
  • internal/config/store_postgres_savings_filter_test.go
  • internal/config/interfaces.go
  • internal/email/factory.go
  • internal/api/handler_purchases_revoke.go
  • internal/database/postgres/migrations/migrate.go
  • internal/api/handler_purchases_test.go

Comment thread internal/api/handler_purchases_revoke_test.go
Comment thread pkg/common/types.go
Comment thread pkg/exchange/exchange.go Outdated
@cristim

cristim commented Jun 24, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jun 24, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@pkg/common/reservation_name.go`:
- Around line 67-72: The nil fallback branch in
`SanitizeReservationName`/`SanitizeReservationID` bypasses the normal
`awsReservationNameMaxLen` cap, so a long `fallbackPrefix` can return an
overlong name. Update the `if f == nil` path to apply the same length limiting
as the regular sanitization flow before returning, using the existing max-length
constant and the same helper logic as the non-nil branch.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: a313321c-7f8d-47d0-963c-2ddcd7351b85

📥 Commits

Reviewing files that changed from the base of the PR and between 3b6e353 and cbfd1fb.

📒 Files selected for processing (17)
  • cmd/multi_service.go
  • internal/api/handler_purchases_revoke_test.go
  • internal/api/handler_purchases_test.go
  • internal/config/interfaces.go
  • internal/config/store_postgres.go
  • internal/config/types_test.go
  • internal/mocks/stores.go
  • internal/server/handler_ri_exchange.go
  • pkg/common/audit.go
  • pkg/common/audit_test.go
  • pkg/common/reservation_name.go
  • pkg/common/reservation_name_test.go
  • pkg/common/types.go
  • pkg/common/types_test.go
  • pkg/exchange/exchange.go
  • pkg/exchange/exchange_test.go
  • providers/aws/internal/purchasecfg/config.go
✅ Files skipped from review due to trivial changes (1)
  • internal/config/types_test.go
🚧 Files skipped from review as they are similar to previous changes (4)
  • internal/config/interfaces.go
  • cmd/multi_service.go
  • internal/api/handler_purchases_revoke_test.go
  • internal/config/store_postgres.go

Comment thread pkg/common/reservation_name.go Outdated
@cristim

cristim commented Jun 24, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jun 24, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@pkg/common/reservation_name_test.go`:
- Line 24: The assertion in SanitizeReservationID’s test is rebuilding the
expected value by calling SanitizeReservationID again, which reuses time.Now()
and can make the test flaky. Update the test to avoid generating the expected
value with a second time-based call; instead, capture the result once or compare
against a deterministic expected string derived from a fixed timestamp so the
check in reservation_name_test.go stays stable.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: c9bd6a0c-a2b0-45ef-9aa0-225608435d64

📥 Commits

Reviewing files that changed from the base of the PR and between cbfd1fb and 756ca62.

📒 Files selected for processing (4)
  • internal/api/handler_purchases.go
  • internal/api/handler_purchases_revoke.go
  • pkg/common/reservation_name.go
  • pkg/common/reservation_name_test.go
🚧 Files skipped from review as they are similar to previous changes (3)
  • pkg/common/reservation_name.go
  • internal/api/handler_purchases_revoke.go
  • internal/api/handler_purchases.go

Comment thread pkg/common/reservation_name_test.go Outdated
@cristim

cristim commented Jun 24, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai review

cristim added a commit that referenced this pull request Jun 25, 2026
…osec+misspell only

Drive the residual non-security nolints to zero so the only suppressions left
on #1265 are the 18 gosec security exceptions and the 16 DB-schema 'cancelled'
misspell exceptions. CUDly is an application with no external consumers, so
internal renames are safe (all in-repo callers updated).

RecommendationFilter cascade (matches #1276 so the branches reconcile):
- ListStoredRecommendations / ListRecommendations now take
  *config.RecommendationFilter across the StoreInterface, the server
  SchedulerInterface, the api recsLister/SchedulerInterface, the PostgresStore
  and Scheduler impls, the MockConfigStore/MockScheduler mocks, all test
  fakes, and ~40 call sites. parseRecommendationFilter / buildCoverageRecFilter
  return *RecommendationFilter; testify matchers use mock.Anything or
  &config.RecommendationFilter{...}, and the captured-filter assertions and
  MatchedBy closures take the pointer type.

revive renames:
- mocks.MockSESClient -> mocks.SESClient, mocks.MockSNSClient -> mocks.SNSClient.
- scheduler.SchedulerConfig -> scheduler.Config (NewScheduler takes *Config).
- package api -> package apihttp (the 8 external importers alias it back to
  api so their api.X references are unchanged).

SDK-mirror pointer-ize:
- Connection.BeginTx takes *pgx.TxOptions (nil = default opts), dereferencing
  at the pgx boundary; callers pass nil.
- Handler.runOrgDiscovery takes *aws.Config, dereferencing at the
  accounts.DiscoverOrgAccounts / discoverOrgFn boundary.

staticcheck SA1019:
- loadStoredGCPTokenSource now detects the credential JSON's "type" field
  (service_account vs external_account) and calls the non-deprecated
  CredentialsFromJSONWithTypeAndParams with the matching google.CredentialsType,
  so both service-account keys and WIF configs load without the deprecated
  CredentialsFromJSON.

Also dropped a stray gocritic appendAssign suppression in handler_history_test
by building the slice on a fresh backing array.

Verified with golangci-lint v2.10.1: --new-from-rev=origin/main reports 0 new
issues; the only nolints in any changed file are gosec and misspell;
.golangci.yml is identical to origin/main; no nolint:errcheck. go build ./...
and go test ./... pass (the one pre-existing Azure scheduler mock failure is
unrelated), and go test -race on the scheduler/purchase paths is clean.
@cristim

cristim commented Jun 25, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai full review

@coderabbitai

coderabbitai Bot commented Jun 25, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Full review finished.

cristim added 21 commits July 10, 2026 14:51
…gging,config,common,concurrency,retry,scorer}

Fix godot (add missing periods to all exported comments), misspell
(US spellings: behaviour->behavior, cancelled->canceled,
recognise->recognize, normaliser->normalizer, catalogue->catalog),
fieldalignment (reorder struct fields for memory efficiency, convert
positional literals to named-field syntax after reorder),
hugeParam/rangeValCopy (use pointer params or index range where
in-scope callers allow; add nolint directives with justification
for cross-package callers that cannot be changed), errcheck (explicit
ok-check on type assertion in concurrency.go), revive stutter
(nolint on ProviderConfig/ProviderFactory with justification),
unparam (nolint on resolveFilePath which reserves error slot for
future extension), and gofmt (restructure nolint comment blocks so
directives appear on the last line before the declaration).

No .golangci.yml edits; all lint changes are in pkg/ sources only.
Fix all golangci-lint v2.10.1 issues across assigned packages:
internal/testutil, internal/mocks, internal/analytics, internal/execution,
internal/accounts, internal/reporter, internal/oidc, internal/scheduler,
internal/runtime, ci_cd_sanity_tests.

Linter fixes applied:
- godot: add missing periods to function/method comments
- misspell: behaviour->behavior, cancelled->canceled, dialling->dialing
- govet/fieldalignment: reorder struct fields to reduce GC scan region
- govet/shadow: rename shadowed err variables in loops
- govet/nilness: remove impossible nil checks
- govet/unusedwrite: remove writes to fields that are never read
- gocritic/hugeParam: add nolint for interface methods and AWS SDK funcs
- gocritic/rangeValCopy: switch to index-based loops for large structs
- gocritic/paramTypeCombine: combine consecutive same-type parameters
- gocritic/emptyStringTest: use == "" instead of len(s) == 0
- gocritic/deprecatedComment: add blank line before Deprecated notice
- gocritic/exitAfterDefer: refactor main() to run() pattern to allow defer
- errcheck: add //nolint:errcheck with reason on testify mock assertions
- revive/exported stutter: rename MockSESClient->SESClient, MockSNSClient->SNSClient;
  add type alias for AnalyticsStore; nolint for SDK-constrained interface methods
- revive/var-naming: nolint for package name matching directory convention
- gosec/G115: nolint with reason for user-supplied flag int->int32 conversion
- unparam: remove parameters that always receive the same literal value
- staticcheck/SA9003: add t.Log inside empty CI-skip branch
Two leftover fieldalignment issues in exchange_lookup_test.go and
handler_purchases_guards_test.go were missed by the g1 branch (which
fixed misspell/godot in those files but skipped the struct reorder).
- gocritic hugeParam: pointer-ize all 14 federationIaCData params in
  handler_federation.go; update all callers (renderTemplate, shellEscapeData,
  renderSingleFile, buildZipResponse, buildFederationBundle, buildCFNZip,
  buildAzureTemplateZip, writeAzureTemplateFiles, buildAzureTemplateReadme,
  addBundleTerraform, addBundleCFN, writeCFNFiles, buildBundleReadme,
  buildCFParamsJSON); add named returns to resolve gocritic unnamedResult

- gosec G115: add safeInt32() helper with explicit bounds check; replace
  two blind int32() casts in handler_purchases_revoke.go with safeInt32

- gosec G117 (spurious): remove nolint from types_apikeys.go; G117 does not
  exist and G101 pattern does not match api_key

- revive: remove nolint from handler_registrations_recipients_test.go;
  package-comments rule is disabled in project config

- gocritic (test files): remove nolint from handler_history_test.go;
  gocritic is excluded for *_test.go by project config

- unparam: remove nolint from ri_utilization_cache_test.go; linter does not
  actually flag this func literal in practice

- misspell: standardize all DB-value exception comments to the canonical
  format '//nolint:misspell // DB schema value '<token>' -- see migration
  <file>'; fix British spellings in comments to US English throughout
  (synthesised->synthesized, honour->honor, modelled->modeled,
  authorises->authorizes, cancelledBy->canceledBy, cancelling->canceling,
  cancelled in non-DB contexts->canceled)
Replace nolint suppressions in providers/azure/ with proper fixes, without
relaxing .golangci.yml (config stays byte-identical to main):

bodyclose: extract mock HTTP response helpers to named variables, call
_ = var.Body.Close() immediately (NopCloser is a no-op); applies to all
.Return(helper(...)) call sites across cache, compute, cosmosdb, database,
internal/pricing, managedredis, reservations, savingsplans, search and
synapse test files.

misspell ("Cancelled"): source the Azure reservation provisioning-state
literals from the armreservations SDK enum
(armreservations.ProvisioningState{Cancelled,Failed,Expired}) so the value
lives in the vendored SDK (which misspell does not scan); removes the
finding from purchase.go and purchase_test.go with zero suppression and
satisfies the typed-enum-over-bare-string convention.

unparam (buildVMSKU region): remove the unused region parameter; all
callers hardcoded "eastus" so the function now encodes that directly.

godot, fieldalignment, hugeParam (pointer receivers), unused, unusedwrite:
fixed in production and test files across all nine service clients;
includes updating pkg/provider.ServiceClient and
pkg/provider.RecommendationsClient interface signatures to use pointer
receivers (*common.Recommendation, *common.RecommendationParams) and
propagating the change to all callers (AWS, GCP, internal, cmd).

staticcheck SA1019 (deprecated Profile field): this is our own deprecated
backwards-compat input slot with no non-deprecated equivalent (Profile IS
the legacy field that AzureSubscriptionID supersedes). Keep a single inline
//nolint:staticcheck with justification, matching the existing GCP provider
precedent on main; no config change.

All 696 providers/azure tests pass; golangci-lint reports zero issues.
…ernal/purchase/, internal/commitmentopts/

- errcheck (cmd/cleanup-lambda): replace _ = tx.Rollback(ctx) with proper
  rollback handling that logs and ignores pgx.ErrTxClosed

- gocritic hugeParam (cmd/multi_service_csv): change determineCSVCoverage
  param to *Config and update callers (cmd/multi_service.go,
  cmd/multi_service_csv_test.go)

- misspell (cmd/multi_service_helpers): fix "purchase cancelled by user" to
  US spelling "canceled"; update test assertion in
  cmd/multi_service_helpers_test.go accordingly (not a DB value)

- gosec G101 (internal/auth/service_password): change dummyPasswordHash from
  var to const to eliminate the credential-detection false positive

- errcheck x10 (internal/auth/test_helpers): replace bare type assertions
  with two-value form v, ok := ...; if !ok { return nil, err } per brief

- gocritic hugeParam x12 (internal/commitmentopts/probe): change Prober
  interface Probe signature and all implementations (RDS, ElastiCache,
  OpenSearch, Redshift, MemoryDB, EC2, SavingsPlans) from aws.Config to
  *aws.Config; update NewClient func fields, service.go call site (&cfg),
  probe_test.go and service_test.go stub implementations

- gocritic hugeParam x3 (internal/purchase): change NewManager to *ManagerConfig
  and update callers in internal/server/app.go and manager_test.go; change
  recIsSafeToRedrive to *RecommendationRecord and update caller; change
  shouldNotifyPlan and buildNotificationData to *config.PurchasePlan and
  update callers including notifications_test.go

- misspell (internal/purchase, DB-locked): 5 nolint:misspell retained for
  the literal "cancelled" DB enum value; updated comment to canonical form
  "DB schema value 'cancelled' -- see migration 000001_initial_schema.up.sql"
…rs/gcp, and pkg modules

Remove every //nolint suppressor in the three in-scope modules and fix the
underlying issues in place:

gocritic/hugeParam:
- pkg/common/types.go: ReservationNameFields.WithRandSource changed to pointer
  receiver; BuildReservationName takes *ReservationNameFields (3 callers updated
  across reservation_name_test.go plus 6 service clients in providers/aws).
- pkg/common/audit.go: NewAuditRecord takes *PurchaseResult (callers in
  cmd/multi_service.go updated).
- pkg/common/types.go: ScaleRecommendationCosts takes *Recommendation (4 call
  sites in cmd/helpers.go and 1 in providers/aws/recommendations/family_nu.go).
- pkg/exchange/auto.go: RunAutoExchange takes *RunAutoExchangeParams (11 callers
  in auto_test.go and internal/server/handler_ri_exchange.go updated).
- providers/aws/internal/purchasecfg/config.go: NewConfig takes *aws.Config
  (7 callers in service clients + 5 call sites in config_test.go updated).
- providers/aws/internal/tagging/purchase_tags.go: PurchasePairs takes
  *common.Recommendation (4 callers in service clients and purchase_tags_test.go).

revive/stutter (pkg/provider):
- ProviderConfig renamed to Config; backward-compat alias removed.
- ExchangeRecord renamed to Record; backward-compat alias removed.
  All callers across internal/, cmd/, ci_cd_sanity_tests/ updated.

govet/fieldalignment:
- pkg/exchange/fail_loud_test.go: sequentialFakeEC2 struct fields reordered.
- pkg/exchange/reshape_crossfamily_test.go: anonymous struct fields reordered.

gosec/G115:
- No G115 nolints were present in scope; pre-existing issues not touched.

Four nolint comments intentionally retained in pkg/common/types.go for
ComputeDetails.GetServiceType, ComputeDetails.GetDetailDescription,
DatabaseDetails.GetServiceType, and DatabaseDetails.GetDetailDescription:
these four value-receiver methods cannot be changed to pointer receivers because
providers/azure (out-of-scope module) stores ComputeDetails and DatabaseDetails
by value in ServiceDetails interface fields. Fixing this requires a coordinated
change to providers/azure which is out of scope for this pass.

misspell: no DB schema string literals with deliberate alternate spellings were
found in the three in-scope modules.
…nolint/E)

Replaces every //nolint directive in internal/secrets/, internal/email/,
internal/config/, internal/server/, internal/database/, internal/analytics/,
internal/mocks/, internal/testutil/, internal/execution/, internal/accounts/,
internal/oidc/, internal/scheduler/, internal/runtime/, internal/reporter/,
and ci_cd_sanity_tests/ with proper code fixes. The only retained exceptions
are verified DB-schema misspell values (cancelled, cancelled_by) guarded by
//nolint:misspell // DB schema value '<token>' -- see migration <file>.

Key changes:
- gocritic/hugeParam: pointer-ize FactoryConfig, ApplicationConfig,
  scheduledauth.Config, allProvidersResult, QueryRequest params + cascade
- gocritic/rangeValCopy: index-based loops in scheduler/collector
- gocritic/tooManyResultsChecker: collectAllProviders now returns
  (allProvidersResult, error) wrapping 5 formerly-separate returns
- gocritic/paramTypeCombine: combine adjacent same-type named returns
- gocritic/unnamedResult: add named results to ValidateUserAPIKeyAPI adapter
- revive/var-naming: rename package runtime -> appruntime; import alias
  preserves call sites
- govet/shadow: rename inner err vars in collectGCPForAccount and
  ListRecommendations cold-start path
- govet/fieldalignment: auto-fix allProvidersResult struct
- govet/unusedwrite: remove nil zero-value fields from Config literal in test
- gofmt: fix interfaces.go trailing blank line; mocks/stores.go inline if
- govet/shadow in analytics/postgres_analytics.go: rename valErr/marshalErr
- govet/unusedwrite in postgres_analytics_test.go: add assertions for fields
- unparam in scheduler_overrides_test.go: drop always-"us-east-1" region param
- revive/stutter for analytics: AnalyticsStore alias already absent on branch
- errcheck type assertions already handled in earlier nonolint passes
…ctor

Fix three new golangci-lint findings introduced by the parseArgs/runQuote
extraction in ci_cd_sanity_tests/cmd/ri-exchange/main.go:
- unnamedResult: add named results to parseArgs signature
- hugeParam: pass runArgs by pointer in runQuote
- fieldalignment: auto-fix runArgs struct field order
B changed ServiceClient to accept *common.Recommendation and
*common.RecommendationParams instead of value types. Test files across
providers/aws, providers/gcp, cmd, and internal/purchase that registered
mock expectations with value types now use pointer matchers
(mock.AnythingOfType("*common.Recommendation"), MatchedBy with pointer
receivers) and fix type assertions in Run() callbacks accordingly.

Also fixes mock.AnythingOfType("email.NotificationData") -> pointer form
to match the existing *NotificationData interface signature.
…ncelled consistency

CodeRabbit findings on the value->pointer cascade and assembly artifacts:

Nil guards on exported pointer-param functions that dereference without a
check (panic -> explicit failure):
- internal/accounts/org_discovery.go DiscoverOrgAccounts: error on nil cfg
- internal/email/factory.go NewSenderWithConfig: error on nil cfg
- pkg/exchange/auto.go RunAutoExchange: error on nil params
- pkg/exchange/exchange.go NewClient: panic on nil cfg (no error return)
- pkg/common/{audit,reservation_name,types}.go NewAuditRecord /
  BuildReservationName / ScaleRecommendationCosts: panic on nil (no error return)
- providers/aws/internal/purchasecfg/config.go NewConfig: panic on nil base

Cancelled DB-status consistency: the assembly's blanket cancelled->canceled
misspell rename downgraded API response status values and store-mock returns
that the frontend matches on 'cancelled'. Revert the DB-status VALUES to
'cancelled' + nolint:misspell while leaving prose comments as 'canceled':
- handler_purchases.go (3 response values), handler_purchases_revoke.go (1)
- handler_ri_exchange_test.go fixture, plus response-status assertions in
  handler_purchases_test.go / handler_purchases_revoke_test.go / handler_test.go

HTTP status classification (handler_purchases.go cancelOrRecoverExecution):
non-conflict transition failures now return a plain wrapped error (-> 500,
generic body, raw backend text only in the server log) instead of a 409 that
leaked backend text. 409 stays reserved for true status conflicts.

Migration SSL mode (migrate.go buildMigrateDSN): recover the exact sslmode
from the parsed pgx TLSConfig instead of collapsing every TLS-enabled mode to
require, so verify-ca / verify-full are no longer silently downgraded during
migrations. Add a regression test pinning the pgx-version-specific mapping.

Doc/test accuracy:
- interfaces.go CancelExecutionAtomic doc: align with the store contract
  ('scheduled' is handled by CancelScheduledExecutionAtomic, not here)
- store_postgres_savings_filter_test.go: rename subtest to match MinSavingsPct=30
…sweep

CodeRabbit round 2: exported functions must never panic on a nil pointer
argument, and the branch must be fully consistent on the 'cancelled' DB value.

Panic -> graceful conversions (policy: constructors return an error and
cascade callers; value/string helpers return a safe zero/no-op):
- pkg/exchange/exchange.go NewClient: now returns (*Client, error); the sole
  caller (internal/server/handler_ri_exchange.go) handles the error.
- pkg/common/audit.go NewAuditRecord: now returns (AuditRecord, error); callers
  in cmd/multi_service.go and audit_test.go updated.
- pkg/common/types.go ScaleRecommendationCosts: nil -> zero Recommendation.
- pkg/common/reservation_name.go BuildReservationName: nil -> fallbackPrefix via
  SanitizeReservationID (the name is only a console-display tag).
- providers/aws/internal/purchasecfg/config.go NewConfig: nil -> zero aws.Config
  (a downstream SDK call then fails loud on the credential-less config).
Added nil-input regression tests for each so the graceful path is asserted.

Cancelled DB-status sweep (git grep '"canceled"'): reverted the one remaining
code value -- the valid-status list in config/types_test.go -- to 'cancelled' +
nolint:misspell. Reworded the doc comments that quoted the literal
(true, "canceled", nil) return tuple (interfaces.go, store_postgres.go,
mocks/stores.go, and two test comments) to reference currentStatus / the
persisted cancel status instead, so they are accurate without a misspell flag.
The only remaining "canceled" literal in code is the context-cancellation error
text in multi_service_helpers_test.go, which is genuine prose.
…ation name

CodeRabbit round 3:

Reservation-name cap (pkg/common/reservation_name.go): the nil-fallback path
added in round 2 returned SanitizeReservationID(...) without the AWS
reservation-name length cap the normal path enforces, so a long fallbackPrefix
could exceed awsReservationNameMaxLen. Extract the existing inline hard-cap into
capReservationName and apply it on every return path (nil fallback + normal).
Add a regression test asserting the nil path respects the cap (fails on the
round-2 code: a 91-char name; passes now).

Cancelled status, root fix: three cancel/revoke handlers hardcoded the literal
"cancelled" in their JSON response (with a misspell nolint) instead of returning
the status the store actually persisted. Return the store-provided value
instead -- exec.Status from cancelOrRecoverExecution in deletePlannedPurchase,
and currentStatus from CancelExecutionAtomic / CancelScheduledExecutionAtomic in
cancelPurchaseViaSession and revokeScheduledExecution. The response can no longer
drift from the DB value, the shared mock's returned currentStatus now genuinely
flows through to the assertions, and three hardcoded misspell nolints are
removed. Verified: go test ./internal/api/... passes (1636) and the
Revoke/Cancel/Purchase subset (248) all green.
…ation test

CodeRabbit round 4:

TestRevokePurchase_ScheduledExecution_AdminFreeCancel relied on the shared mock
default for its CAS return and carried a comment naming the wrong method
(CancelExecutionAtomic), while a scheduled row is actually cancelled via
CancelScheduledExecutionAtomic. Stub that method explicitly with
Return(true, "cancelled", nil).Once() plus DeleteSuppressionsByExecutionTx,
matching the sibling scheduled-revoke tests. AssertExpectations now enforces the
stub, so the setup and the asserted status can never drift.

TestBuildReservationName_NilFieldsReturnsFallback rebuilt its expected value via
SanitizeReservationID("", prefix), which calls time.Now() a second time -- a
second-boundary cross between the actual call and the rebuild would flake the
equality assertion. Replace it with deterministic structural assertions: regexp
^rds-reserved-[0-9]+$ (sanitized prefix + unix timestamp), no trailing hyphen,
and the length cap. No second time.Now() comparison.

Verified by execution: go test ./internal/api/... (1636) and -run Revoke (33)
both green; reservation_name nil tests pass.
Sibling-consistency miss from 1017f66 (which aligned the test in
internal/config/store_postgres_db_test.go to the contract that
GetExecutionByID returns (nil, nil) for missing rows): the duplicate
"Get execution by ID - not found" subtest in store_postgres_test.go
was left on the pre-contract `assert.Error + err.Error()` shape, so
the Integration Tests job panicked with a nil-pointer deref the moment
it tried to format the nil err. The panic cascaded through
TestPostgresStore_PurchaseExecutions and aborted the rest of the
internal/config suite -- visible in the PR's failing CI as
`SIGSEGV ... store_postgres_test.go:313`.

Bring this twin test in line with the contract documented in
1017f66 and the sibling subtest at store_postgres_db_test.go:594:
expect (nil, nil), assert the returned execution is nil, no err
deref. GetExecutionByPlanAndDate's not-found assertion below stays
as-is -- that one DOES wrap a "not found" error (store_postgres.go:1317).
Four compatibility fixes required after rebasing onto main which included
PRs #1343 (errcheck), #1346 (ladder-sp-coverage), and #1340 (ladder-allocate):

- cmd/cleanup-lambda: remove unused `errors` and `pgx` imports left over
  from conflict resolution (main's rollback pattern doesn't use them)
- internal/mocks/stores.go: update ListStoredRecommendations signature to
  pointer (*RecommendationFilter) matching the interface change in #1343
- internal/scheduler/scheduler.go: pass &params (pointer) to
  GetRecommendations after PR #1346 changed the function signature
- providers/aws/service_client_test.go: add GetSavingsPlansCoverage and
  GetSavingsPlansUtilization stub methods to mockCostExplorerClient after
  PR #1346 extended the CostExplorerAPI interface
…lementation

The implementation wraps ErrNotFound when no row matches; require.NoError
in store_postgres_test.go contradicts both the implementation and the
sibling assertion in store_postgres_db_test.go which uses require.Error +
require.ErrorIs(err, ErrNotFound). Align this twin test to the correct
(and production-consistent) contract.
…ixer

Three groups of changes to internal/mocks/stores.go, internal/api/
handler_history.go, and internal/api/handler_ri_exchange.go were
inadvertently converted from the DB-persisted value "cancelled" (British
spelling, from migration 000001/000009) to "canceled" by the misspell
lint pass. This broke four tests that assert on the actual status string:

  - TestRevokePurchase_ScheduledExecution_RevokeOwnCreator
  - TestSummarizePurchaseHistory_CancelledExcludedFromKPIs
  - TestSummarizePurchaseHistory_CancelPendingDoesNotChangeKPIs
  - TestHandler_rejectRIExchange_AlreadyProcessed

Revert the DB status-value strings to "cancelled" and suppress misspell
with //nolint:misspell // DB schema value comments. Prose comments and
user-visible error messages that are not DB values keep the corrected
American-English spelling.
The gocyclo step of the Lint Code job fails on six test functions in
files this PR already touches (all over the >10 threshold). Extract
helpers and adopt testify to bring each under the limit without changing
behavior:

- email/smtp_server_test.go: split the mockSMTPServer command switch into
  respondToLine/respondToCommand, and handleFlexSMTPConn into
  handleFlexSMTPCommand/handleFlexAuth/handleFlexData/writeFlexReply.
- oidc/signer_test.go: replace manual if-err/if-neq checks in
  TestLocalSignerMintAndVerify and TestBuildJWKS with require/assert.
- api/ri_utilization_cache_test.go: extract the stored-row poll loop into
  waitForStoredRI.
- api/handler_history_test.go: hoist the two mock.MatchedBy predicates in
  TestHandler_getHistory_FilterParams into named matcher helpers.

gocyclo -over 10 is now clean repo-wide; build, vet, gofmt, and the
affected tests all pass.
@cristim
cristim force-pushed the fix/leftover-lint branch from 663a22d to 3b8f854 Compare July 10, 2026 13:02
@cristim

cristim commented Jul 10, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 10, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@cristim

cristim commented Jul 11, 2026

Copy link
Copy Markdown
Member Author

Superseded by main's independent golangci-lint sweep (PR #1358 + fix(lint) commits), which reached the same lint-clean state via root-cause fixes (~30 nolints) rather than this branch's ~291 suppressions. The one unique fix here (preserve verify-ca/verify-full TLS mode in the migration DSN) is extracted to #1360. Backup tag backup/leftover-lint-preRebase retained.

@cristim cristim closed this Jul 11, 2026
cristim added a commit that referenced this pull request Jul 11, 2026
…ncelled consistency

CodeRabbit findings on the value->pointer cascade and assembly artifacts:

Nil guards on exported pointer-param functions that dereference without a
check (panic -> explicit failure):
- internal/accounts/org_discovery.go DiscoverOrgAccounts: error on nil cfg
- internal/email/factory.go NewSenderWithConfig: error on nil cfg
- pkg/exchange/auto.go RunAutoExchange: error on nil params
- pkg/exchange/exchange.go NewClient: panic on nil cfg (no error return)
- pkg/common/{audit,reservation_name,types}.go NewAuditRecord /
  BuildReservationName / ScaleRecommendationCosts: panic on nil (no error return)
- providers/aws/internal/purchasecfg/config.go NewConfig: panic on nil base

Cancelled DB-status consistency: the assembly's blanket cancelled->canceled
misspell rename downgraded API response status values and store-mock returns
that the frontend matches on 'cancelled'. Revert the DB-status VALUES to
'cancelled' + nolint:misspell while leaving prose comments as 'canceled':
- handler_purchases.go (3 response values), handler_purchases_revoke.go (1)
- handler_ri_exchange_test.go fixture, plus response-status assertions in
  handler_purchases_test.go / handler_purchases_revoke_test.go / handler_test.go

HTTP status classification (handler_purchases.go cancelOrRecoverExecution):
non-conflict transition failures now return a plain wrapped error (-> 500,
generic body, raw backend text only in the server log) instead of a 409 that
leaked backend text. 409 stays reserved for true status conflicts.

Migration SSL mode (migrate.go buildMigrateDSN): recover the exact sslmode
from the parsed pgx TLSConfig instead of collapsing every TLS-enabled mode to
require, so verify-ca / verify-full are no longer silently downgraded during
migrations. Add a regression test pinning the pgx-version-specific mapping.

Doc/test accuracy:
- interfaces.go CancelExecutionAtomic doc: align with the store contract
  ('scheduled' is handled by CancelScheduledExecutionAtomic, not here)
- store_postgres_savings_filter_test.go: rename subtest to match MinSavingsPct=30
@cristim

cristim commented Jul 11, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai full review

@coderabbitai

coderabbitai Bot commented Jul 11, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Full review finished.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

effort/xl Multi-week / refactor impact/internal Team-internal only priority/p1 Next up; this sprint severity/medium Moderate harm triaged Item has been triaged type/chore Maintenance / non-user-visible urgency/this-sprint Within the current sprint

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant