Skip to content

Conversation

@notrab
Copy link
Member

@notrab notrab commented Jan 19, 2026

Lite PR

Summary

  • What changed (1-3 bullets, no essays).

Why

  • Why this change exists. Link to related GitHub issues where relevant.

Testing

  • How this was tested.
  • If you didn't test it, say why.

Notes for Reviewer (Optional)

  • Anything non-obvious or worth a heads-up.

Pre-Review Checklist (Blocking)

  • This PR does not introduce significant changes and is low-risk to review quickly.
  • Relevant changesets are included (or are not required)
PR Creation Tips
  • If this PR introduces significant changes or is higher-risk to review use the "Substantial PR" template instead.
  • Changesets should optimize for the narrative of the next autogenerated release notes. Optimize for how the resulting release notes will read to a developer in the ENS Ecosystem. Communicate all ideas with a positive frame.
  • The "Require PR Description Checks" GitHub Action will report a failing CI check on non-draft PRs where there are unchecked checkboxes in the description. You should therefore make your PR a draft PR until it is ready for review.

Summary by CodeRabbit

  • Documentation

    • Updated API reference to point at the live API endpoint.
    • Added a hidden "Preview" page that displays the branch-local OpenAPI spec.
  • Infrastructure

    • Added a CI job to validate the committed OpenAPI spec matches the generated production spec.
    • Added a script to generate the OpenAPI JSON used by the preview and validation.

✏️ Tip: You can customize this high-level summary in your review settings.

Copilot AI review requested due to automatic review settings January 19, 2026 13:32
@vercel
Copy link

vercel bot commented Jan 19, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Review Updated (UTC)
admin.ensnode.io Ready Ready Preview, Comment Jan 19, 2026 3:43pm
ensnode.io Ready Ready Preview, Comment Jan 19, 2026 3:43pm
ensrainbow.io Ready Ready Preview, Comment Jan 19, 2026 3:43pm

@changeset-bot
Copy link

changeset-bot bot commented Jan 19, 2026

⚠️ No Changeset found

Latest commit: ddc8bf6

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@coderabbitai
Copy link

coderabbitai bot commented Jan 19, 2026

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

📝 Walkthrough

Walkthrough

Adds CI job to validate committed openapi.json against production, an npm script and TypeScript generator that fetches/writes the spec, and documentation updates including a hidden preview page and docs config pointing to local and production specs.

Changes

Cohort / File(s) Summary
CI / Workflows
\.github/workflows/test_ci.yml
Introduces "OpenAPI Spec Sync Check" job (duplicated blocks present) that generates the production OpenAPI spec, formats it, and diffs it against the committed openapi.json, failing with guidance if out of sync.
App package & script
apps/ensapi/package.json, apps/ensapi/scripts/generate-openapi.ts
Adds openapi:generate npm script and generate-openapi.ts which fetches /openapi.json from a URL/env/default, validates response, pretty-prints and writes docs/openapi.json, and logs spec metadata.
Docs configuration
docs/docs.ensnode.io/docs.json
Updates API Reference openapi URL to https://api.alpha.ensnode.io/openapi.json and adds a hidden "Preview" documentation group referencing local ./openapi.json.
Docs page
docs/docs.ensnode.io/ensapi/preview.mdx
Adds preview MDX page describing branch-local OpenAPI preview and linking to production docs.

Sequence Diagram(s)

sequenceDiagram
    participant CI as GitHub CI
    participant Runner as Job Runner
    participant Script as generate-openapi.ts
    participant Service as ENSApi Service
    participant FS as Docs Directory

    CI->>Runner: start "OpenAPI Spec Sync Check" job
    Runner->>Script: run `npm run openapi:generate` (arg/env/default URL)
    Script->>Service: GET /openapi.json
    Service-->>Script: 200 + OpenAPI JSON
    Script->>FS: write pretty `docs/openapi.json`
    Script-->>Runner: log spec version & path count
    Runner->>Service: fetch production /openapi.json (for diff)
    Runner->>FS: compare committed `docs/openapi.json` vs generated
    alt specs match
        Runner-->>CI: job passes
    else specs differ
        Runner-->>CI: job fails and prints regeneration/commit instructions
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 I fetched the spec with nimble feet,
I printed JSON tidy, neat.
CI peeks, then bops the drum,
If branch and prod disagree — no fun!
Hop, regenerate, commit — then repeat.

🚥 Pre-merge checks | ❌ 3
❌ Failed checks (2 warnings, 1 inconclusive)
Check name Status Explanation Resolution
Description check ⚠️ Warning The pull request description contains only the empty template structure with no concrete information filled in—all sections (Summary, Why, Testing, Notes) are blank, and both checklist items remain unchecked. Fill in all required template sections with actual details: provide a concise summary of changes, explain the rationale, describe how changes were tested, and check the blocking checklist items before merging.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'openapi spec / docs poc' is vague and generic, using abbreviations ('poc') without clearly conveying the main change or intent of the changeset. Replace the vague title with a specific, descriptive summary like 'Add OpenAPI spec generation and validation in CI' to clearly communicate the primary change.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch openapi-spec-generator

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

- uses: ./.github/actions/setup_node_environment

- name: Generate OpenAPI spec from production
run: pnpm --filter ensapi openapi:generate
Copy link
Member Author

Choose a reason for hiding this comment

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

could fail because no linting is done. need to investigate.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR adds OpenAPI specification generation and documentation capabilities to the ENSNode project. It introduces a script to fetch and save the OpenAPI spec from a running ENSApi instance, integrates it with Mintlify documentation, and adds CI checks to ensure the spec stays in sync with production.

Changes:

  • Added a 5,106-line OpenAPI specification file documenting all ENSApi endpoints
  • Created a generation script to fetch and update the spec from a running instance
  • Configured Mintlify docs to reference both production and local OpenAPI specs
  • Added CI workflow to validate spec synchronization on the main branch

Reviewed changes

Copilot reviewed 4 out of 5 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
docs/docs.ensnode.io/openapi.json Complete OpenAPI 3.1.0 specification documenting all ENSApi endpoints including resolution, meta, explore, and ENSAwards APIs
apps/ensapi/scripts/generate-openapi.ts TypeScript script to fetch OpenAPI spec from running instance and save to docs directory
apps/ensapi/package.json Added npm script openapi:generate to run the generation script
docs/docs.ensnode.io/docs.json Updated configuration to reference production API spec and added hidden preview section for local spec
.github/workflows/test_ci.yml Added CI job to verify OpenAPI spec stays in sync with production on main branch

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

* ENSAPI_URL=http://localhost:3223 pnpm openapi:generate
*
* Output:
* Writes openapi.json to the docs directory for Mintilify
Copy link

Copilot AI Jan 19, 2026

Choose a reason for hiding this comment

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

The comment mentions "Mintilify" but the context suggests this should be "Mintlify" (the documentation platform). This appears to be a typo in the documentation.

Suggested change
* Writes openapi.json to the docs directory for Mintilify
* Writes openapi.json to the docs directory for Mintlify

Copilot uses AI. Check for mistakes.
Comment on lines +28 to +33
const response = await fetch(openapiUrl);

if (!response.ok) {
console.error(`Failed to fetch OpenAPI spec: ${response.status} ${response.statusText}`);
process.exit(1);
}
Copy link

Copilot AI Jan 19, 2026

Choose a reason for hiding this comment

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

The script lacks error handling for network timeouts or when the URL is unreachable. Consider adding a timeout to the fetch call and providing more helpful error messages for common failure scenarios (e.g., connection refused, timeout, invalid JSON response).

Copilot uses AI. Check for mistakes.
Comment on lines 54 to 55
# Only run on main branch - PRs may intentionally have different specs
if: github.ref == 'refs/heads/main'
Copy link

Copilot AI Jan 19, 2026

Choose a reason for hiding this comment

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

The CI check only runs on the main branch, which means PRs that update the API won't validate that the OpenAPI spec needs to be regenerated. Consider running this check on all branches but only failing on main, or add a comment to the PR when the spec is out of sync.

Copilot uses AI. Check for mistakes.
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 5

🤖 Fix all issues with AI agents
In @.github/workflows/test_ci.yml:
- Around line 51-55: The openapi-sync-check job currently only runs when
github.ref == 'refs/heads/main', which lets PRs merge with out-of-sync specs;
update the condition on the openapi-sync-check job (the if: line) to also run
for pull requests (e.g., include github.event_name == 'pull_request' or
github.head_ref checks) and mark it non-blocking for PRs by using
continue-on-error: true (or alternatively remove the if entirely and rely on
branch protection or add contributor documentation). Target the job named
openapi-sync-check and the existing if: github.ref == 'refs/heads/main'
condition when making the change.

In `@apps/ensapi/scripts/generate-openapi.ts`:
- Around line 23-24: ensapiUrl may end with a trailing slash causing openapiUrl
to become "//openapi.json"; normalize ensapiUrl before composing openapiUrl (the
variables to change are ensapiUrl and openapiUrl in generate-openapi.ts) by
trimming any trailing '/' from ensapiUrl (or using a URL-safe join) so
openapiUrl is built as `${normalizedEnsapiUrl}/openapi.json` even when
ENSAPI_URL or process.argv[2] includes a trailing slash; ensure
DEFAULT_ENSAPI_URL remains fallback and normalization runs after selecting the
value.
- Line 12: Update the header comment string that reads "Writes openapi.json to
the docs directory for Mintilify" and correct the product name typo to
"Mintlify" so the comment reads "Writes openapi.json to the docs directory for
Mintlify"; locate this exact comment text in generate-openapi.ts and make the
single-word change.
- Around line 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.

In `@docs/docs.ensnode.io/docs.json`:
- Around line 29-34: The docs.json "Preview" group references a non-existent
page "ensapi/preview"; fix by either adding a new page file named preview.mdx
under the docs/docs.ensnode.io/ensapi/ folder (so the path matches
"ensapi/preview") or remove the entire Preview group entry (the object with
"group": "Preview", "pages": ["ensapi/preview"], "openapi": "./openapi.json",
"hidden": true) from docs.json; update whichever you choose and ensure the
"pages" array references only existing MDX/MD files.

Comment on lines +23 to +24
const ensapiUrl = process.argv[2] || process.env.ENSAPI_URL || DEFAULT_ENSAPI_URL;
const openapiUrl = `${ensapiUrl}/openapi.json`;
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Handle potential trailing slash in URL.

If ensapiUrl ends with a /, the constructed URL will have //openapi.json. Consider normalizing:

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

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const ensapiUrl = process.argv[2] || process.env.ENSAPI_URL || DEFAULT_ENSAPI_URL;
const openapiUrl = `${ensapiUrl}/openapi.json`;
const ensapiUrl = process.argv[2] || process.env.ENSAPI_URL || DEFAULT_ENSAPI_URL;
const openapiUrl = `${ensapiUrl.replace(/\/+$/, '')}/openapi.json`;
🤖 Prompt for AI Agents
In `@apps/ensapi/scripts/generate-openapi.ts` around lines 23 - 24, ensapiUrl may
end with a trailing slash causing openapiUrl to become "//openapi.json";
normalize ensapiUrl before composing openapiUrl (the variables to change are
ensapiUrl and openapiUrl in generate-openapi.ts) by trimming any trailing '/'
from ensapiUrl (or using a URL-safe join) so openapiUrl is built as
`${normalizedEnsapiUrl}/openapi.json` even when ENSAPI_URL or process.argv[2]
includes a trailing slash; ensure DEFAULT_ENSAPI_URL remains fallback and
normalization runs after selecting the value.

Comment on lines +28 to +33
const response = await fetch(openapiUrl);

if (!response.ok) {
console.error(`Failed to fetch OpenAPI spec: ${response.status} ${response.statusText}`);
process.exit(1);
}
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Consider adding a timeout to the fetch request.

The fetch call has no timeout, which could cause the CI job to hang indefinitely if the production API is unresponsive. Node.js fetch supports AbortSignal.timeout():

Proposed fix
- const response = await fetch(openapiUrl);
+ const response = await fetch(openapiUrl, {
+   signal: AbortSignal.timeout(30_000), // 30 second timeout
+ });
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
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.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In @.github/workflows/test_ci.yml:
- Around line 58-70: The CI step runs the openapi:generate npm script which
currently relies on a hardcoded production default; make the behavior explicit
by passing the production URL via the ENSAPI_URL env in the workflow step or by
updating the openapi:generate script to accept an ENSAPI_URL argument and
default it to https://api.alpha.ensnode.io; update the step that invokes
openapi:generate to export ENSAPI_URL or call the script with the URL so the
action is explicit and maintainable.

Comment on lines 58 to 70
- name: Generate OpenAPI spec from production
run: pnpm --filter ensapi openapi:generate

- 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."
echo "Run 'pnpm --filter ensapi openapi:generate' and commit the changes."
exit 1
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

🧩 Analysis chain

🏁 Script executed:

# Find the ensapi package and its configuration
find . -name "package.json" -type f | xargs grep -l "ensapi" | head -5

Repository: namehash/ensnode

Length of output: 137


🏁 Script executed:

# Search for openapi:generate script definition
rg "openapi:generate" --type json

Repository: namehash/ensnode

Length of output: 142


🏁 Script executed:

# Find any openapi generator script files
fd -e ts -e js | xargs grep -l "openapi" | grep -i "generate\|api" | head -10

Repository: namehash/ensnode

Length of output: 431


🏁 Script executed:

# Examine the OpenAPI generator script
cat -n apps/ensapi/scripts/generate-openapi.ts

Repository: namehash/ensnode

Length of output: 1894


🏁 Script executed:

# Check if there's environment variable usage in the script
rg "ENSAPI_URL|process.env" apps/ensapi/scripts/generate-openapi.ts -A 2 -B 2

Repository: namehash/ensnode

Length of output: 617


The OpenAPI generator already defaults to production; explicit URL is optional.

The openapi:generate script uses a hardcoded default of https://api.alpha.ensnode.io (the production API), making the CI behavior deterministic. While explicitly passing ENSAPI_URL would improve clarity and maintainability, the current implementation correctly targets production and won't drift due to changing defaults.

🤖 Prompt for AI Agents
In @.github/workflows/test_ci.yml around lines 58 - 70, The CI step runs the
openapi:generate npm script which currently relies on a hardcoded production
default; make the behavior explicit by passing the production URL via the
ENSAPI_URL env in the workflow step or by updating the openapi:generate script
to accept an ENSAPI_URL argument and default it to https://api.alpha.ensnode.io;
update the step that invokes openapi:generate to export ENSAPI_URL or call the
script with the URL so the action is explicit and maintainable.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 5 out of 6 changed files in this pull request and generated 1 comment.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +32 to 35
"openapi": "./openapi.json",
"hidden": true
}
]
Copy link

Copilot AI Jan 19, 2026

Choose a reason for hiding this comment

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

The "hidden" property may not be a valid field in the Mintlify docs.json schema. According to Mintlify documentation, there is no "hidden" property for navigation groups. If you want to hide this section, you should verify this property is supported or use a different approach.

Suggested change
"openapi": "./openapi.json",
"hidden": true
}
]
"openapi": "./openapi.json"
}
]
]

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants