feat: prepare API for Render deployment (PostgreSQL, health check, CORS, Swagger, pagination) - #30
Open
devin-ai-integration[bot] wants to merge 1 commit into
Open
feat: prepare API for Render deployment (PostgreSQL, health check, CORS, Swagger, pagination)#30devin-ai-integration[bot] wants to merge 1 commit into
devin-ai-integration[bot] wants to merge 1 commit into
Conversation
…RS, Swagger, pagination) Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Contributor
Author
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
There was a problem hiding this comment.
Pull request overview
Prepares the AirAware ASP.NET Core API for deployment on Render by adding PostgreSQL support (via DATABASE_URL), health checks, configurable CORS, Swagger, and paginated responses for readings.
Changes:
- Add Render blueprint (
render.yaml) and production configuration (appsettings.Production.json), plus Docker ignore hardening. - Add PostgreSQL runtime selection + initial Npgsql EF Core migrations; adjust startup to migrate on PostgreSQL and
EnsureCreated()on SQLite. - Add
/health, Swagger (non-Production), CORS policy, and paginateGET /api/v1/readingswith a typedPagedResult<T>(tests updated).
Reviewed changes
Copilot reviewed 15 out of 16 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| render.yaml | Render blueprint to provision the API service and PostgreSQL database. |
| README.md | Documents Render deployment, env vars, and SQLite vs PostgreSQL behavior. |
| AirAware/ViewModels/PagedResult.cs | Introduces a typed pagination envelope for API responses/tests. |
| AirAware/Startup.cs | Adds CORS + Swagger configuration and updates middleware pipeline. |
| AirAware/Program.cs | Applies migrations on PostgreSQL; uses EnsureCreated() for SQLite fallback. |
| AirAware/Migrations/AppDbContextModelSnapshot.cs | EF Core snapshot for the new PostgreSQL migration set. |
| AirAware/Migrations/20260614040505_InitialPostgres.Designer.cs | Generated migration designer for PostgreSQL schema. |
| AirAware/Migrations/20260614040505_InitialPostgres.cs | Creates initial PostgreSQL tables + indexes. |
| AirAware/Middleware/ApiKeyAuthMiddleware.cs | Exempts /health from API-key auth. |
| AirAware/Data/AppDbContext.cs | Selects provider from DATABASE_URL and normalizes Render-style Postgres URIs. |
| AirAware/Controllers/ReadingController.cs | Adds pagination parameters and returns PagedResult<Reading>. |
| AirAware/Controllers/HealthController.cs | Adds unauthenticated health check endpoint. |
| AirAware/appsettings.Production.json | Production log-level tuning and allowed hosts. |
| AirAware/AirAware.csproj | Adds Npgsql EF provider and Swashbuckle dependencies. |
| AirAware.Tests/Controllers/ReadingControllerTests.cs | Updates tests for the paginated response contract + adds pagination tests. |
| .dockerignore | Excludes dev configs/secrets and SQLite files from Docker build context. |
Files not reviewed (1)
- AirAware/Migrations/20260614040505_InitialPostgres.Designer.cs: Generated file
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+29
to
+31
| var origins = Configuration.GetValue<string>("AllowedOrigins")?.Split( | ||
| ',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries) | ||
| ?? Array.Empty<string>(); |
Comment on lines
+78
to
82
| app.UseCors(CorsPolicyName); | ||
|
|
||
| app.UseMiddleware<ApiKeyAuthMiddleware>(); | ||
|
|
||
| app.UseRouting(); |
| <PrivateAssets>all</PrivateAssets> | ||
| </PackageReference> | ||
| <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="10.0.2" /> | ||
| <PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="10.0.0" /> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Makes the API deployable to Render: adds PostgreSQL support, a
render.yamlblueprint, an unauthenticated/healthcheck, configurable CORS, Swagger, and pagination onGET /api/v1/readings.Database provider selected at runtime
AppDbContext.OnConfiguringnow picks the provider fromDATABASE_URL:Render exposes connection strings as URIs (
postgres://user:pass@host:port/db), which Npgsql does not accept directly, soNormalizePostgresConnectionStringconverts apostgres(ql)://URI into the Npgsql key/value format (and passes through already-formatted strings). A new EF migrationInitialPostgreswas generated against the Npgsql provider.Because EF migrations are provider-specific, startup now branches:
(The repo previously had no committed migrations even though
Program.cscalledMigrate(), so the SQLite path effectively created no schema —EnsureCreated()fixes local dev too.)/healthendpointNew
HealthControllerreturns200 { "status": "healthy" }.ApiKeyAuthMiddlewareshort-circuits before key validation for/healthso Render's health probe works without the API key:CORS + Swagger (
Startup.cs)Startupnow takesIConfiguration. CORS policyFrontendPolicyreadsALLOWED_ORIGINS(comma-separated); when empty it falls back toAllowAnyOrigin(dev-friendly).app.UseCors(...)runs before the API-key middleware and routing.X-API-KEYApiKey security scheme; the UI is exposed only outside Production.Pagination on
GET /api/v1/readingsAdds
page(default 1) andpageSize(default 50, clamped to 200) and returns a typed envelopePagedResult<Reading>serialized as{ data, page, pageSize, total }(ordered byCreatedAtdesc). A concrete DTO is used instead of an anonymous type so the response is assertable from the test assembly;ReadingControllerTestswere updated for the new contract and two pagination tests added.Infra / config
render.yaml(Docker web service + free PostgreSQL,healthCheckPath: /health,DATABASE_URLfrom the DB,ApiKey/ALLOWED_ORIGINSassync: false).appsettings.Production.jsonwith reduced log verbosity..dockerignorenow excludesappsettings.Development.json, local secrets, and*.sqlite*.Verification
dotnet build -c Releaseanddotnet testpass (91/91). Ran locally against the SQLite fallback:/health→ 200 without key, readings → 401 without key, paginated envelope returned with key, CORS preflight returns headers, and/swagger/v1/swagger.jsonserves in Development.Link to Devin session: https://app.devin.ai/sessions/829418a074784cbaa96bc62faf058bea
Requested by: @joaoferreira-dev