-
Notifications
You must be signed in to change notification settings - Fork 0
feat(api-contract): adopt checked-in OpenAPI contract as source of truth #21
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
11 commits
Select commit
Hold shift + click to select a range
3e52033
docs(brainstorms): frame OpenAPI-first web/api read contract
sommio 42d74b8
docs(plans): add openapi-first web/api contract plan
sommio 9b4afa0
feat(api-contract): keep generated contract files out of hooks
sommio 0c9b54c
fix(api-contract): keep generated clients out of hooks
sommio a212a03
docs(api-contract): align README terminology with summaryError
sommio 78571d3
chore(agents): add plan completion GitHub Actions check
sommio bccc9b2
chore(prettier): ignore generated OpenAPI outputs
sommio b7bdaaf
chore: stop tracking generated API client output
sommio ff53e04
fix(api-contract): keep contract refresh portable
sommio 1266a9f
docs(plans): mark openapi contract units complete
sommio ba178a3
chore(openapi): tighten contract lint and guidance
sommio File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,5 +4,6 @@ | |
| .codex/ | ||
| .omx/ | ||
| .turbo/ | ||
| packages/api-contract/src/generated/ | ||
| pnpm-lock.yaml | ||
| tmp/ | ||
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
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
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,65 @@ | ||
| import { afterAll, beforeAll, describe, expect, it, jest } from "@jest/globals"; | ||
| import { type INestApplication } from "@nestjs/common"; | ||
| import { Test } from "@nestjs/testing"; | ||
| import { readFileSync } from "node:fs"; | ||
| import { resolve } from "node:path"; | ||
| import YAML from "yaml"; | ||
|
|
||
| import { AppModule } from "../src/app.module"; | ||
| import { ArticlesService } from "../src/articles/articles.service"; | ||
| import { PrismaService } from "../src/prisma/prisma.service"; | ||
| import { createOpenApiDocument } from "../src/openapi/openapi-document"; | ||
| import { FeedBootstrapService } from "../src/feeds/feed-bootstrap.service"; | ||
|
|
||
| describe("OpenAPI contract", () => { | ||
| let app: INestApplication | undefined; | ||
|
|
||
| beforeAll(async () => { | ||
| process.env["TEST_DATABASE_URL"] ??= | ||
| "postgresql://rssift:rssift@127.0.0.1:5432/rssift_test"; | ||
| process.env["DATABASE_URL"] = process.env["TEST_DATABASE_URL"]; | ||
| process.env["INGEST_ON_BOOT"] = "false"; | ||
|
|
||
| const moduleRef = await Test.createTestingModule({ | ||
| imports: [AppModule], | ||
| }) | ||
| .overrideProvider(ArticlesService) | ||
| .useValue({ | ||
| getArticleById: jest.fn(), | ||
| getArticles: jest.fn(), | ||
| }) | ||
| .overrideProvider(PrismaService) | ||
| .useValue({ | ||
| $queryRawUnsafe: jest.fn(), | ||
| }) | ||
| .overrideProvider(FeedBootstrapService) | ||
| .useValue({ | ||
| onApplicationBootstrap: () => undefined, | ||
| }) | ||
| .compile(); | ||
|
|
||
| app = moduleRef.createNestApplication(); | ||
| await app.init(); | ||
| }); | ||
|
|
||
| afterAll(async () => { | ||
| if (app) { | ||
| await app.close(); | ||
| } | ||
| }); | ||
|
|
||
| it("matches the checked-in contract", () => { | ||
| const emitted = createOpenApiDocument(app as INestApplication); | ||
| const checkedIn: unknown = YAML.parse( | ||
| readFileSync( | ||
| resolve( | ||
| __dirname, | ||
| "../../../packages/api-contract/openapi/openapi.yaml", | ||
| ), | ||
|
coderabbitai[bot] marked this conversation as resolved.
|
||
| "utf8", | ||
| ), | ||
| ); | ||
|
|
||
| expect(emitted).toEqual(checkedIn); | ||
| }); | ||
| }); | ||
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
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
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,17 +1,41 @@ | ||
| import { ApiProperty } from "@nestjs/swagger"; | ||
|
|
||
| export class ArticleSummaryErrorDto { | ||
| @ApiProperty({ type: String }) | ||
| action!: string; | ||
|
|
||
| @ApiProperty({ type: String }) | ||
| code!: string; | ||
|
|
||
| @ApiProperty({ type: String }) | ||
| copyText!: string; | ||
|
|
||
| @ApiProperty({ type: String }) | ||
| message!: string; | ||
|
|
||
| @ApiProperty({ type: String }) | ||
| title!: string; | ||
| } | ||
|
|
||
| export class ArticleDetailItemDto { | ||
| @ApiProperty({ type: String }) | ||
| title!: string; | ||
|
|
||
| @ApiProperty({ type: String }) | ||
| translatedTitle!: string; | ||
|
|
||
| @ApiProperty({ type: String }) | ||
| sourceTitle!: string; | ||
|
|
||
| @ApiProperty({ type: String, format: "date-time" }) | ||
| publishedAt!: string; | ||
|
|
||
| @ApiProperty({ type: String }) | ||
| summary!: string; | ||
|
|
||
| @ApiProperty({ type: () => ArticleSummaryErrorDto, nullable: true }) | ||
| summaryError!: ArticleSummaryErrorDto | null; | ||
|
|
||
| @ApiProperty({ type: String }) | ||
| originalUrl!: string; | ||
| } |
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,8 +1,21 @@ | ||
| import { ApiProperty } from "@nestjs/swagger"; | ||
|
|
||
| export class ArticleListItemDto { | ||
| @ApiProperty({ type: String }) | ||
| id!: string; | ||
|
|
||
| @ApiProperty({ type: String }) | ||
| title!: string; | ||
|
|
||
| @ApiProperty({ type: String }) | ||
| translatedTitle!: string; | ||
|
|
||
| @ApiProperty({ type: String }) | ||
| sourceTitle!: string; | ||
|
|
||
| @ApiProperty({ type: String, format: "date-time" }) | ||
| publishedAt!: string; | ||
|
|
||
| @ApiProperty({ type: String }) | ||
| originalUrl!: string; | ||
| } |
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| import { ApiProperty } from "@nestjs/swagger"; | ||
|
|
||
| export class HealthLiveChecksDto { | ||
| @ApiProperty({ type: String }) | ||
| application!: string; | ||
| } | ||
|
|
||
| export class HealthReadyChecksDto { | ||
| @ApiProperty({ type: String }) | ||
| application!: string; | ||
|
|
||
| @ApiProperty({ type: String }) | ||
| database!: string; | ||
| } | ||
|
|
||
| export class HealthLiveResponseDto { | ||
| @ApiProperty({ type: () => HealthLiveChecksDto }) | ||
| checks!: HealthLiveChecksDto; | ||
|
|
||
| @ApiProperty({ type: String }) | ||
| service!: string; | ||
|
|
||
| @ApiProperty({ type: String }) | ||
| status!: string; | ||
| } | ||
|
|
||
| export class HealthReadyResponseDto { | ||
| @ApiProperty({ type: () => HealthReadyChecksDto }) | ||
| checks!: HealthReadyChecksDto; | ||
|
|
||
| @ApiProperty({ type: String }) | ||
| service!: string; | ||
|
|
||
| @ApiProperty({ type: String }) | ||
| status!: string; | ||
| } |
Oops, something went wrong.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Clarify policy sentences to avoid ambiguous enforcement language.
Several updated lines use terse grammar (“No break…”, “No add…”, “No make…”), which weakens interpretation consistency for contributors and automation-facing guidance.
✍️ Proposed wording cleanup
Also applies to: 13-13, 44-46, 57-58
🤖 Prompt for AI Agents