Skip to content

Commit 69eaefb

Browse files
zachdunnclaude
andauthored
ci: detect graphql schema drift (#761)
* ci: detect drift between committed graphql snapshot and live schema (#754) Adds a CI step that regenerates packages/api-types/graphql/schema.graphql and fails on any diff, so a Pothos type/resolver change without the paired regen surfaces in CI rather than as a runtime mismatch in codegen consumers. Also refreshes the snapshot itself — graphql-js's printer collapses single-line descriptions to inline """...""", and the committed copy predated that formatting, so the new check would have failed on its own PR without this regen. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * ci: ignore generated graphql snapshot in prettier graphql-js's printSchema collapses single-line descriptions inline (""text""), but prettier expands them to multi-line. The two formatters were silently fighting — every regen triggers a prettier diff, and every prettier-write triggers a schema-drift diff. Add the snapshot to .prettierignore so the print script is the sole source of truth for its format. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent cd6714a commit 69eaefb

3 files changed

Lines changed: 22 additions & 36 deletions

File tree

.github/workflows/ci.yml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,5 +80,14 @@ jobs:
8080
echo "Found new wrangler migration file(s):"
8181
echo "$added" | sed 's/^/ /'
8282
83+
- name: Verify GraphQL schema snapshot is up to date
84+
run: |
85+
bun workers/api/scripts/print-graphql-schema.ts
86+
if ! git diff --exit-code packages/api-types/graphql/schema.graphql; then
87+
echo "ERROR: packages/api-types/graphql/schema.graphql is stale." >&2
88+
echo "Regenerate with: bun workers/api/scripts/print-graphql-schema.ts" >&2
89+
exit 1
90+
fi
91+
8392
- name: Run tests
8493
run: bun run test

.prettierignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,4 @@ package-lock.json
1111
plugins/claude-code/skills
1212
packages/*/dist
1313
tests/evals/fixtures/tool-ux/runs
14+
packages/api-types/graphql/schema.graphql

packages/api-types/graphql/schema.graphql

Lines changed: 12 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,15 @@ scalar DateTime
55

66
scalar JSON
77

8-
"""
9-
An image, video, or GIF attached to a release.
10-
"""
8+
"""An image, video, or GIF attached to a release."""
119
type Media {
1210
alt: String
1311
r2Url: String
1412
type: MediaKind!
1513
url: String!
1614
}
1715

18-
"""
19-
Kind of media attached to a release.
20-
"""
16+
"""Kind of media attached to a release."""
2117
enum MediaKind {
2218
gif
2319
image
@@ -46,17 +42,13 @@ type Org {
4642
updatedAt: DateTime!
4743
}
4844

49-
"""
50-
Catalog-shaped page of organizations.
51-
"""
45+
"""Catalog-shaped page of organizations."""
5246
type OrgConnection {
5347
items: [Org!]!
5448
pagination: Pagination!
5549
}
5650

57-
"""
58-
Page-based pagination envelope. Mirrors REST's Pagination shape.
59-
"""
51+
"""Page-based pagination envelope. Mirrors REST's Pagination shape."""
6052
type Pagination {
6153
hasMore: Boolean
6254
page: Int!
@@ -66,9 +58,7 @@ type Pagination {
6658
totalPages: Int
6759
}
6860

69-
"""
70-
Optional grouping layer between an Org and its Sources.
71-
"""
61+
"""Optional grouping layer between an Org and its Sources."""
7262
type Product {
7363
category: String
7464
createdAt: DateTime!
@@ -88,27 +78,19 @@ type Query {
8878
latestReleases(
8979
cursor: String
9080

91-
"""
92-
Drop releases whose source.type is in this list.
93-
"""
81+
"""Drop releases whose source.type is in this list."""
9482
excludeSourceTypes: [SourceType!]
9583
limit: Int = 20
9684
orgIdOrSlug: String
9785
): ReleaseFeed!
9886

99-
"""
100-
Look up an organization by id (org_…) or slug.
101-
"""
87+
"""Look up an organization by id (org_…) or slug."""
10288
org(idOrSlug: String!): Org
10389

104-
"""
105-
Catalog-shaped page of organizations, newest first.
106-
"""
90+
"""Catalog-shaped page of organizations, newest first."""
10791
orgs(limit: Int = 20, page: Int = 1): OrgConnection!
10892

109-
"""
110-
Look up a release by id (rel_…) — or by url for legacy callers.
111-
"""
93+
"""Look up a release by id (rel_…) — or by url for legacy callers."""
11294
release(idOrUrl: String!): Release
11395

11496
"""
@@ -117,9 +99,7 @@ type Query {
11799
source(id: String!): Source
118100
}
119101

120-
"""
121-
A single release (changelog entry).
122-
"""
102+
"""A single release (changelog entry)."""
123103
type Release {
124104
"""
125105
Full markdown body. Often large — request only when you need it (this is the field-selection win).
@@ -129,9 +109,7 @@ type Release {
129109
fetchedAt: DateTime!
130110
id: ID!
131111

132-
"""
133-
Images / videos / GIFs attached to the release. Empty list if none.
134-
"""
112+
"""Images / videos / GIFs attached to the release. Empty list if none."""
135113
media: [Media!]!
136114
publishedAt: DateTime
137115
source: Source!
@@ -149,9 +127,7 @@ type ReleaseFeed {
149127
nextCursor: String
150128
}
151129

152-
"""
153-
A changelog source (github / scrape / feed / agent).
154-
"""
130+
"""A changelog source (github / scrape / feed / agent)."""
155131
type Source {
156132
createdAt: DateTime!
157133
discovery: String!

0 commit comments

Comments
 (0)