-
Notifications
You must be signed in to change notification settings - Fork 15
openapi spec / docs poc #1550
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
base: main
Are you sure you want to change the base?
openapi spec / docs poc #1550
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -48,7 +48,32 @@ | |
| - uses: ./.github/actions/setup_node_environment | ||
| - run: pnpm test | ||
|
|
||
| openapi-sync-check: | ||
| name: "OpenAPI Spec Sync Check" | ||
| runs-on: blacksmith-4vcpu-ubuntu-2204 | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| - uses: ./.github/actions/setup_node_environment | ||
|
|
||
| - name: Generate OpenAPI spec from production | ||
| run: pnpm --filter ensapi openapi:generate | ||
notrab marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| - name: Format generated spec with Biome | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please see related comments about moving the responsibility for formatting into the route handler. |
||
| run: pnpm biome format --write docs/docs.ensnode.io/openapi.json | ||
|
|
||
| - name: Verify OpenAPI spec matches production | ||
| run: | | ||
| if git diff --exit-code docs/docs.ensnode.io/openapi.json; then | ||
| echo "✅ OpenAPI spec is in sync with production" | ||
| else | ||
| echo "❌ OpenAPI spec is out of sync with production" | ||
| echo "" | ||
| echo "The committed openapi.json differs from the production API." | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is there an easy way to output here specifically what was different in the git diff? |
||
| echo "Run 'pnpm --filter ensapi openapi:generate' and commit the changes." | ||
| exit 1 | ||
| fi | ||
|
|
||
| integrity-check: | ||
Check warningCode scanning / CodeQL Workflow does not contain permissions Medium test
Actions job or workflow does not limit the permissions of the GITHUB_TOKEN. Consider setting an explicit permissions block, using the following as a minimal starting point: {contents: read}
|
||
| name: "Integrity Check" | ||
| runs-on: blacksmith-4vcpu-ubuntu-2204 | ||
| services: | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,51 @@ | ||||||||||||||||||||||||||||||
| #!/usr/bin/env tsx | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||
| * Generate OpenAPI spec from a running ENSApi instance. | ||||||||||||||||||||||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe this script should live in the Mintlify app, rather than in ENSApi? Suggesting this because it writes to a file in the Mintlify app directory. The param it takes is a hostname/port and that could be from inside or outside the repo. |
||||||||||||||||||||||||||||||
| * | ||||||||||||||||||||||||||||||
| * Usage: | ||||||||||||||||||||||||||||||
| * pnpm openapi:generate # Uses default URL (production) | ||||||||||||||||||||||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Concerned about having any default URL for this script. I'm not aware of any cases where we would want to regularly run this script against production. That would violate the concept of where the Instead, I believe this script should not have any default for this param and always require this param to be explicitly passed. Otherwise it is too error prone. |
||||||||||||||||||||||||||||||
| * pnpm openapi:generate http://localhost:3223 # Uses custom URL | ||||||||||||||||||||||||||||||
| * ENSAPI_URL=http://localhost:3223 pnpm openapi:generate | ||||||||||||||||||||||||||||||
| * | ||||||||||||||||||||||||||||||
| * Output: | ||||||||||||||||||||||||||||||
| * Writes openapi.json to the docs directory for Mintlify to consume. | ||||||||||||||||||||||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Is that fair? |
||||||||||||||||||||||||||||||
| * Run `pnpm biome format --write docs/docs.ensnode.io/openapi.json` after to format. | ||||||||||||||||||||||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's a bummer that this is necessary as an additional step. What do you think about a strategy where we update the logic for the
|
||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| import { writeFileSync } from "node:fs"; | ||||||||||||||||||||||||||||||
| import { resolve } from "node:path"; | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| const DEFAULT_ENSAPI_URL = "https://api.alpha.ensnode.io"; | ||||||||||||||||||||||||||||||
| const OUTPUT_PATH = resolve(import.meta.dirname, "../../../docs/docs.ensnode.io/openapi.json"); | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| async function main() { | ||||||||||||||||||||||||||||||
| // Get URL from argument or environment variable | ||||||||||||||||||||||||||||||
| const ensapiUrl = process.argv[2] || process.env.ENSAPI_URL || DEFAULT_ENSAPI_URL; | ||||||||||||||||||||||||||||||
| const openapiUrl = `${ensapiUrl}/openapi.json`; | ||||||||||||||||||||||||||||||
|
Comment on lines
+24
to
+25
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧹 Nitpick | 🔵 Trivial Handle potential trailing slash in URL. If Proposed fix const ensapiUrl = process.argv[2] || process.env.ENSAPI_URL || DEFAULT_ENSAPI_URL;
- const openapiUrl = `${ensapiUrl}/openapi.json`;
+ const openapiUrl = `${ensapiUrl.replace(/\/+$/, '')}/openapi.json`;📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| console.log(`Fetching OpenAPI spec from: ${openapiUrl}`); | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| const response = await fetch(openapiUrl); | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| if (!response.ok) { | ||||||||||||||||||||||||||||||
| console.error(`Failed to fetch OpenAPI spec: ${response.status} ${response.statusText}`); | ||||||||||||||||||||||||||||||
| process.exit(1); | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
|
Comment on lines
+29
to
+34
|
||||||||||||||||||||||||||||||
| const response = await fetch(openapiUrl); | |
| if (!response.ok) { | |
| console.error(`Failed to fetch OpenAPI spec: ${response.status} ${response.statusText}`); | |
| process.exit(1); | |
| } | |
| const response = await fetch(openapiUrl, { | |
| signal: AbortSignal.timeout(30_000), // 30 second timeout | |
| }); | |
| if (!response.ok) { | |
| console.error(`Failed to fetch OpenAPI spec: ${response.status} ${response.statusText}`); | |
| process.exit(1); | |
| } |
🤖 Prompt for AI Agents
In `@apps/ensapi/scripts/generate-openapi.ts` around lines 28 - 33, Add a timeout
to the fetch in generate-openapi.ts by creating an AbortSignal via
AbortSignal.timeout(ms) and passing it as the signal option to the
fetch(openapiUrl) call; handle the abort case by catching the thrown error
(check for AbortError or error.name === 'AbortError') and log a clear timeout
message before exiting, and ensure the existing non-ok response handling remains
unchanged.
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.
Please see my other comment that suggested we might apply formatting within the API route handler such that it's not necessary to perform additional formatting of the response.
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -1,35 +1,58 @@ | ||||||
| # ENSNode Documentation | ||||||
| # ENSNode API Documentation | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I believe we should revert this change. It's true that at the moment the Mintlify site is only being used for the ENSApi docs. However, as soon as we can get there, we want to fully transition all ENSNode docs into Mintlify, not just the subset for ENSApi. |
||||||
|
|
||||||
| [docs.ensnode.io](https://docs.ensnode.io) runs on [Mintlify](https://mintlify.com). | ||||||
| [docs.ensnode.io](https://docs.ensnode.io) hosts the ENSApi reference documentation. | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I believe we should revert this change. It's true that at the moment the Mintlify site is only being used for the ENSApi docs. However, as soon as we can get there, we want to fully transition all ENSNode docs into Mintlify, not just the subset for ENSApi. |
||||||
|
|
||||||
| ## Local Development | ||||||
| Learn more about [ENSNode](https://ensnode.io) from [the ENSNode docs](https://ensnode.io/docs/). | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
|
|
||||||
| ### Getting Started | ||||||
| ## Architecture | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
|
|
||||||
| The documentation serves API reference from two sources: | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
|
|
||||||
| | Section | Source | Purpose | | ||||||
| | -------------------- | ------------------ | ------------------------------------------- | | ||||||
| | **API Reference** | Production API URL | Always reflects the live deployed API | | ||||||
| | **Preview** (hidden) | `./openapi.json` | PR preview deployments for upcoming changes | | ||||||
|
|
||||||
| When you change API routes or schemas, update the committed `openapi.json` to preview changes in Mintlify's PR deployments. | ||||||
|
|
||||||
| ## OpenAPI Spec Management | ||||||
|
|
||||||
| 1. Clone the repository: | ||||||
| We use a combination of runtime URLs and committed files to keep API docs in sync across environments. This setup achieves: | ||||||
|
|
||||||
| ```bash | ||||||
| git clone https://github.com/namehash/ensnode.git | ||||||
| ``` | ||||||
| - Production API docs match the production deployment, even when production lags behind `main` | ||||||
| - Non-API docs stay in sync with `main` through normal Git flow | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Suggest ideas about non-API docs move out of a section that's dedicated to API docs. |
||||||
| - Each branch has its own `openapi.json`, validated by CI | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| - PR previews show upcoming API changes before merge | ||||||
|
|
||||||
| 2. Navigate to the docs directory: | ||||||
| ### Generating the Spec | ||||||
|
|
||||||
| ```bash | ||||||
| cd ensnode/docs/docs.ensnode.io | ||||||
| ``` | ||||||
| ```bash | ||||||
| # Generate from production API | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Suggest to also include other example here for generating from the code for ENSApi in your local dev environment (on your current branch) |
||||||
| pnpm --filter ensapi openapi:generate | ||||||
| ``` | ||||||
|
|
||||||
| 3. Start the local development server: | ||||||
| ### CI Validation | ||||||
|
|
||||||
| ```bash | ||||||
| pnpm mint dev | ||||||
| ``` | ||||||
| CI runs an `openapi-sync-check` job that compares the committed `openapi.json` against production. If they differ, the check fails. | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This shouldn't be comparing against production. |
||||||
|
|
||||||
| Update the committed spec when: | ||||||
|
|
||||||
| - You've changed API routes or schemas (generate from your local instance) | ||||||
| - Production was updated (generate from production) | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We don't commit the spec from production. |
||||||
|
|
||||||
| ## Local Development | ||||||
|
|
||||||
| ### Getting Started | ||||||
|
|
||||||
| 1. `git clone https://github.com/namehash/ensnode.git` | ||||||
| 2. `cd docs/docs.ensnode.io` | ||||||
| 3. `pnpm mint dev` | ||||||
| 4. Open [http://localhost:3000](http://localhost:3000) in your browser | ||||||
|
|
||||||
| ### Troubleshooting | ||||||
|
|
||||||
| - If a page loads as a 404, make sure you are running in a folder with a valid `docs.json`. | ||||||
| - Run `pnpm mint --help` to read more details about Mintlify CLI. | ||||||
| - If a page loads as a 404, ensure you're running in a folder with a valid `docs.json` | ||||||
| - Run `pnpm mint --help` for more Mintlify CLI details | ||||||
|
|
||||||
| ## Publishing Changes | ||||||
|
|
||||||
|
|
@@ -38,3 +61,4 @@ Changes pushed to the main branch are automatically deployed to production. | |||||
| ## Resources | ||||||
|
|
||||||
| - [Mintlify documentation](https://mintlify.com/docs) | ||||||
| - [ENSNode documentation](https://ensnode.io/docs/) | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -24,7 +24,13 @@ | |||||||||||||||||
| }, | ||||||||||||||||||
| { | ||||||||||||||||||
| "group": "API Reference", | ||||||||||||||||||
| "openapi": "https://gist.githubusercontent.com/notrab/94b637e77468cbddd895d7933ce88f64/raw/12cb5ed183558a9bdda5d1c7004db6c794dbd13e/green-ensnode-openapi.json" | ||||||||||||||||||
| "openapi": "https://api.alpha.ensnode.io/openapi.json" | ||||||||||||||||||
| }, | ||||||||||||||||||
| { | ||||||||||||||||||
| "group": "Preview", | ||||||||||||||||||
| "pages": ["ensapi/preview"], | ||||||||||||||||||
| "openapi": "./openapi.json", | ||||||||||||||||||
| "hidden": true | ||||||||||||||||||
| } | ||||||||||||||||||
coderabbitai[bot] marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||||
| ] | ||||||||||||||||||
|
Comment on lines
+32
to
35
|
||||||||||||||||||
| "openapi": "./openapi.json", | |
| "hidden": true | |
| } | |
| ] | |
| "openapi": "./openapi.json" | |
| } | |
| ] | |
| ] |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| --- | ||
| title: API Preview | ||
| sidebarTitle: Preview | ||
| description: Preview upcoming API changes from the current branch. | ||
| --- | ||
|
|
||
| This page shows the OpenAPI specification from the current branch, which may include unreleased API changes. | ||
|
|
||
| For the production API documentation, see the [API Reference](/ensapi). |
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.
Since this is the
test_ci.ymlworkflow, I don't believe we should be checking against production here.My understanding is that the following will be required:
openapi:generateto the hostname / port described above.