feat(cli): add --id flag for stable preview URLs in docs generation#13660
feat(cli): add --id flag for stable preview URLs in docs generation#13660kennyderek merged 9 commits intomainfrom
Conversation
Co-Authored-By: kenny <kenny@buildwithfern.com>
🤖 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.
Code review is billed via overage credits. To resume reviews, an organization admin can raise the monthly limit in Settings → Usage.
Once credits are available, reopen this pull request to trigger a review.
Co-Authored-By: kenny <kenny@buildwithfern.com>
Co-Authored-By: kenny <kenny@buildwithfern.com>
Co-Authored-By: kenny <kenny@buildwithfern.com>
Co-Authored-By: kenny <kenny@buildwithfern.com>
| if (fullDomain.length <= SUBDOMAIN_LIMIT) { | ||
| return fullDomain; | ||
| } |
There was a problem hiding this comment.
Incorrect subdomain length validation. Line 24 compares the full domain length (including .docs.buildwithfern.com) against SUBDOMAIN_LIMIT (62), but line 29 treats SUBDOMAIN_LIMIT as the maximum length of just the subdomain part. This causes the truncation logic to trigger at the wrong threshold.
The subdomain part ${orgId}-preview-${previewId} should be limited to 63 characters (DNS label limit), not the full domain. Fix:
const subdomain = `${orgId}-preview-${previewId}`;
if (subdomain.length <= SUBDOMAIN_LIMIT) {
return `${subdomain}.${DOMAIN_SUFFIX}`;
}| if (fullDomain.length <= SUBDOMAIN_LIMIT) { | |
| return fullDomain; | |
| } | |
| const subdomain = `${orgId}-preview-${previewId}`; | |
| if (subdomain.length <= SUBDOMAIN_LIMIT) { | |
| return `${subdomain}.${DOMAIN_SUFFIX}`; | |
| } |
Spotted by Graphite
Is this helpful? React 👍 or 👎 to let us know.
There was a problem hiding this comment.
Good catch on the mismatch between the full domain vs subdomain comparison — however, the server-side truncateDomainName in getDocsWriteV2Service.ts has the exact same logic:
const subdomainLimit = 62;
const fullDomain = `${orgId}-preview-${docsRegistrationId}.${domainSuffix}`;
if (fullDomain.length <= subdomainLimit) {
return fullDomain;
}The CLI intentionally mirrors this so the predicted URL matches what the server produces. Fixing only the CLI side would cause a mismatch where the CLI checks one URL but the server generates a different one.
If this should be fixed, it should be fixed on both sides together (and is pre-existing, not introduced by this PR).
Co-Authored-By: kenny <kenny@buildwithfern.com>
Co-Authored-By: kenny <kenny@buildwithfern.com>
Co-Authored-By: kenny <kenny@buildwithfern.com>
Co-Authored-By: kenny <kenny@buildwithfern.com>
…ern-api#13660) * feat: add --id flag for stable preview URLs in docs generation Co-Authored-By: kenny <kenny@buildwithfern.com> * fix: use type assertion for previewId until SDK is republished Co-Authored-By: kenny <kenny@buildwithfern.com> * fix: add missing previewId parameter to LegacyDocsPublisher Co-Authored-By: kenny <kenny@buildwithfern.com> * fix: use FdrAPI.Url branded type for getDocsUrlMetadata call Co-Authored-By: kenny <kenny@buildwithfern.com> * fix: update comment explaining type assertion for previewId Co-Authored-By: kenny <kenny@buildwithfern.com> * fix: format publishDocs.ts to satisfy biome Co-Authored-By: kenny <kenny@buildwithfern.com> * chore: upgrade @fern-api/fdr-sdk to 1.1.13-c1ad12a2b8 Co-Authored-By: kenny <kenny@buildwithfern.com> --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: kenny <kenny@buildwithfern.com>
Description
Adds
--id <name>flag tofern generate --docs --previewso that preview URLs remain stable across repeated runs. Instead of generating a random UUID for each preview, the provided ID is used as the domain identifier, allowing subsequent runs with the same--idto overwrite the previous preview.Companion FDR PR: fern-api/fern-platform#8742 (merged) — adds
previewIdto thestartDocsPreviewRegisterschema and handler.Changes Made
cli.ts: Add--idstring option to the generate command with validation requiring--previewand--docsgenerateDocsWorkspace.ts:buildPreviewDomain()that replicates server-sidetruncateDomainNamelogic to predict the preview URL--idis provided (non-CI, no--force), check FDR metadata viagetDocsUrlMetadata(usingFdrAPI.Url()branded type) to see if URL already exists and prompt for overwrite confirmationpublishDocs.ts: PasspreviewIdthrough tostartDocsPreviewRegisterAPI call (usesascast — see review notes)runRemoteGenerationForDocsWorkspace.ts: ThreadpreviewIdparameter through the call chainLegacyDocsPublisher.ts: PasspreviewId: undefinedto match updated function signatureversions.yml: Add v4.35.0 changelog entrypnpm-workspace.yaml: Upgrade@fern-api/fdr-sdkcatalog entry to1.1.13-c1ad12a2b8Updates Since Last Revision
@fern-api/fdr-sdkcatalog entry from0.145.12-b50d999d1to1.1.13-c1ad12a2b8(published after fern-platform#8742 merged)FdrClientwrapper still uses old Fern-generated types that lackpreviewId, so theascast inpublishDocs.tsremains necessary until the client is migrated to use oRPC types for write methodsfern-dev:buildconfirmed the feature works end-to-end against the dev stack smoke-test project — preview published successfully tohttps://smoke-test-preview-my-test-preview.docs.dev.buildwithfern.comImportant Review Notes
SDK type cast:
previewIdis not yet in the FDR SDK'sStartDocsPreviewRegisterRequestV2type (theFdrClientwrapper hasn't been migrated to oRPC for write methods), so the request usesas DocsV2Write.StartDocsPreviewRegisterRequestV2. Manual testing confirmed the Fern-generated SDK passes unknown properties through in the JSON body —previewIdsuccessfully reached the server and the named preview URL was generated.Hardcoded
DOMAIN_SUFFIX:buildPreviewDomainhardcodes"docs.buildwithfern.com"which won't match dev/staging environments. The overwrite confirmation prompt won't fire in those environments (confirmed during testing). Production behavior is correct.Duplicated truncation logic:
buildPreviewDomainmirrors the server'struncateDomainName. If the server logic changes, these will drift.pnpm catalog vs override mismatch: The
pnpm-workspace.yamlcatalog now has@fern-api/fdr-sdk: 1.1.13-c1ad12a2b8, butpackage.jsonpnpm.overridesstill pins@fern-api/fdr-sdk: 0.145.12-b50d999d1. The override exists because the new SDK version has breaking type changes inFdrClientconstructor (e.g.tokentype changed) that affect other packages like@fern-api/core. Updating the override is a separate task.Human Review Checklist
previewIddelivered successfully)DOMAIN_SUFFIXis acceptable or should be derived from config/environmentTesting
pnpm run check(biome) passesfern-dev:build— published named preview to dev stack successfullyLink to Devin session: https://app.devin.ai/sessions/d3670821970e4e1687c12f99240e043e