docs(sdks): document SDK auto-versioning for self-hosted setups#5473
docs(sdks): document SDK auto-versioning for self-hosted setups#5473jsklan wants to merge 10 commits into
Conversation
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.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:
|
| ``` | ||
|
|
||
| <Info> | ||
| `--version AUTO` requires: |
There was a problem hiding this comment.
📝 [vale] reported by reviewdog 🐶
[FernStyles.Acronyms] 'AUTO' has no definition.
| } | ||
| ``` | ||
|
|
||
| `originGitCommit` is the SHA in the **config repo** that produced the SDK at its current version. Check that commit out, run `fern ir`, then switch back to `HEAD` and run `fern ir` again to produce both inputs to `fern diff`. |
There was a problem hiding this comment.
📝 [vale] reported by reviewdog 🐶
[FernStyles.Acronyms] 'SHA' has no definition.
|
🌿 Preview your docs: https://fern-preview-devin-1778610174-self-hosted-versioning.docs.buildwithfern.com/learn Here are the markdown pages you've updated: |
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
|
Three corrections needed, verified against the fern-api/fern codebase via DeepWiki: 1. Remove the editorial sentence in the deterministic section Remove this sentence from the
The intro bullets already establish the relative framing. This sentence is redundant and reads as a sales pitch. 2. Fix the The current Info block says:
This is incorrect. When running Replace the requirements bullet list with: 3. Add The actual {
"bump": "minor",
"nextVersion": "1.5.0",
"errors": []
}Everything else checks out: |
- Fix --version AUTO requirements: LLM call is made locally from the user's machine, not via a hosted Fern service. List FERN_TOKEN plus the supported LLM provider keys (OpenAI, Anthropic, AWS Bedrock). - Drop redundant editorial sentence from the fern ir + fern diff intro; the bullet summary already covers the framing. - Add the errors field to the fern diff JSON output example so it matches the actual Result shape. Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
|
All three applied in 2bc6bb0:
One related thing I left alone: the intro bullet still says "or when you can't depend on Fern's hosted AI service." That phrasing is in tension with correction (2) — the LLM call is the user's, not Fern-hosted. Happy to tighten that to "…or when you can't depend on an LLM provider" if you want; left it untouched per your "only these three" instruction. CI is green. Preview: https://fern-preview-devin-1778610174-self-hosted-versioning.docs.buildwithfern.com/learn/sdks/deep-dives/self-hosted#determining-sdk-versions |
The Fern CLI calls the configured LLM provider's API directly using the user's credentials; Fern's infrastructure is not involved in the analysis. Also drop the matching 'Fern's hosted AI service' phrasing from the intro bullet. Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
| - Standard AWS credentials (`AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, `AWS_REGION`) for AWS Bedrock. | ||
| - A self-hosted GitHub output configured in `generators.yml` (with `github.uri` and `github.token`, [as shown above](#setup)), because the auto-versioning pipeline pushes the version bump and changelog back to the SDK repo. | ||
|
|
||
| The diff is sent to whichever LLM provider you configure. The Fern CLI calls that provider's API directly using your credentials — Fern's infrastructure is not involved in the analysis. |
There was a problem hiding this comment.
🚫 [vale] reported by reviewdog 🐶
[Microsoft.Contractions] Use 'isn't' instead of 'is not'.
--version AUTO needs both an ai: block in generators.yml (picking the provider and model) and the corresponding API key in the environment. List both, plus the FERN_TOKEN and self-hosted GitHub output. Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
| - Standard AWS credentials (`AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, `AWS_REGION`) for AWS Bedrock. | ||
| - A self-hosted GitHub output configured in `generators.yml` (with `github.uri` and `github.token`, [as shown above](#setup)), because the auto-versioning pipeline pushes the version bump and changelog back to the SDK repo. | ||
|
|
||
| The diff is sent to the provider's API using your credentials — Fern's infrastructure is not involved in the analysis. |
There was a problem hiding this comment.
🚫 [vale] reported by reviewdog 🐶
[Microsoft.Contractions] Use 'isn't' instead of 'is not'.
…lout Nested code blocks inside list items inside <Info> were not parsing cleanly: the title="generators.yml" was bleeding into the bullet text and the [as shown above](#setup) link was being stripped. Keep the requirements as plain bullets in the callout, then show the config snippet and env-var list as regular prose below. Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…nippet - Remove the dead link to the private fern-api/fern-generate repo and reword the sentence to use 'fern automations generate'. - Replace the hardcoded '--api plants' placeholder with '--api <your-api-name>' so readers don't copy the example name. - Fix the Compute next version step: 'fern diff' exits 1 on a major bump, which under set -e killed the step before jq ran. Capture with '|| true', read .bump, exit 1 with an explicit message on major, and only write next_version for minor/patch/no_change. This matches what the Info callout above the snippet describes. Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
| - A [conventional commit](https://www.conventionalcommits.org/) message | ||
|
|
||
| ```bash | ||
| FERN_TOKEN=<token> fern generate --version AUTO |
There was a problem hiding this comment.
🔴 Missing --local flag in --version AUTO example command
The example command on this self-hosted generation page omits the --local flag. The CLI changelog at fern/products/cli-api-reference/cli-changelog/2025-11-18.mdx:10 documents this feature as "Add automatic semantic versioning to local generation with --version AUTO --local flags", confirming both flags are required together. Without --local, the command would attempt cloud generation instead of self-hosted generation, which defeats the purpose of this page and could send API data over the network — exactly what organizations choosing self-hosted want to avoid.
| FERN_TOKEN=<token> fern generate --version AUTO | |
| FERN_TOKEN=<token> fern generate --local --version AUTO |
Was this helpful? React with 👍 or 👎 to provide feedback.
| echo "next_version=$(echo "$result" | jq -r .nextVersion)" >> "$GITHUB_OUTPUT" | ||
|
|
||
| - name: Generate SDK | ||
| run: fern generate --group python-sdk --version ${{ steps.diff.outputs.next_version }} |
There was a problem hiding this comment.
🔴 Missing --local flag in CI workflow's fern generate step
The complete CI workflow example omits the --local flag from the final fern generate command. Per the CLI changelog (fern/products/cli-api-reference/cli-changelog/2025-11-18.mdx:10), --local is required for self-hosted generation. Since this is a copy-paste-ready workflow that users are instructed to adapt, the missing flag would cause CI to run cloud generation instead of local generation, contradicting the entire self-hosted setup documented on this page.
| run: fern generate --group python-sdk --version ${{ steps.diff.outputs.next_version }} | |
| run: fern generate --local --group python-sdk --version ${{ steps.diff.outputs.next_version }} |
Was this helpful? React with 👍 or 👎 to provide feedback.
| <Tabs> | ||
| <Tab title="CLI v1" language="cli-v1"> | ||
| ```bash | ||
| fern generate --version 1.5.0 |
There was a problem hiding this comment.
🟡 Missing --local flag in deterministic versioning example commands
The fern generate commands in both CLI v1 and CLI v2 tabs omit the --local flag. Since these examples appear on the self-hosted generation page and follow a self-hosted versioning workflow (fern ir + fern diff), users would expect --local to be present. Without it, the commands would trigger cloud generation instead of local generation.
| fern generate --version 1.5.0 | |
| fern generate --local --version 1.5.0 |
Was this helpful? React with 👍 or 👎 to provide feedback.
|
|
||
| ## Determining SDK versions | ||
|
|
||
| When self-hosting, your pipeline picks the version number for each SDK release. Cloud generation handles this automatically via [Fern Autorelease](/learn/sdks/overview/autorelease), but self-hosted setups need to compute the next version themselves. |
There was a problem hiding this comment.
I wouldn't link to autorelease, it's a hidden page for now.
There was a problem hiding this comment.
Good catch — dropped the link, kept the prose reference. d30f602.
|
|
||
| ### Deterministic versioning with `fern ir` + `fern diff` | ||
|
|
||
| If you'd rather derive the version number yourself, use the `fern ir` and `fern diff` commands to compute the bump from your API definition. This flow has no LLM dependency: `fern diff` walks the intermediate representation (IR) of both specs and returns a deterministic result. |
There was a problem hiding this comment.
I think we should explain why someone would pick AUTO over deterministic versioning. At face value deterministic looks a lot more logica.
There was a problem hiding this comment.
Agreed — rewrote the comparison bullets to make the AUTO advantage concrete instead of just asserting "recommended" (d30f602):
--version AUTO: classifies the change, picks the next version, and writes the changelog entry, PR description, and conventional-commit message for you. Also the path that continues to receive improvements.fern ir+fern diff: returns only the computed bump and next version — the rest of the release artifacts are yours to write. Use when you need explicit control over how the number is derived, or can't depend on an external LLM provider.
So the answer to "why pick AUTO" is: AUTO does the release-prep work for you, deterministic only hands back the version number. Happy to iterate if you'd like more concrete examples (e.g., side-by-side of what each command actually outputs) — let me know.
…tic framing - Drop link to /learn/sdks/overview/autorelease since that page is hidden today; keep the prose reference to Fern Autorelease. - Rewrite the AUTO vs deterministic intro bullets to make the AUTO advantage concrete: AUTO also writes the changelog entry, PR description, and conventional-commit message, while fern ir + fern diff only returns the bump and next version. Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
| - `ANTHROPIC_API_KEY` for Anthropic | ||
| - Standard AWS credentials (`AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, `AWS_REGION`) for AWS Bedrock | ||
|
|
||
| The diff is sent to the provider's API using your credentials — Fern's infrastructure is not involved in the analysis. |
There was a problem hiding this comment.
🚫 [vale] reported by reviewdog 🐶
[Microsoft.Contractions] Use 'isn't' instead of 'is not'.
Summary
Adds a new Determining SDK versions section to the Self-hosted SDKs deep dive, covering the two CLI workflows for auto-determining the next version when generating SDKs on your own infrastructure. This is a real docs gap — Anduril and Cohere North both hit it independently and assumed they had to pick versions by hand.
The new section sits after How it works on the same page (
fern/products/sdks/deep-dives/self-hosted.mdx) and documents:--version AUTO(recommended): one-linefern generate --version AUTOinvocation, what the LLM-powered diff analysis produces (changelog entry, PR description, conventional-commit message), and theFERN_TOKEN+ self-hosted GitHub config requirements. Framed as the modern path that will continue to receive improvements.fern ir+fern diff(deterministic/legacy): three-step workflow with the JSON output shape fromfern diff --from-version, including the--version/--output-versionsplit between CLI v1 and v2.fern ir+fern diffinto CI: full GitHub Actions snippet that readsoriginGitCommitandsdkVersionfrom the SDK repo's.fern/metadata.json, checks out the previous spec, runsfern iragainst both revisions, computes the next version, and generates the SDK. Includes thefetch-depth: 0callout.Linear: FER-10500
Review & Testing Checklist for Human
GITHUB_TOKEN) and thegit checkout ${{ github.sha }}step that returns to HEAD.--version AUTOvs.fern ir+fern diffmatches how you want enterprise customers to think about the two paths. Easiest to flag any phrasing nits as inline comments on the preview.Notes
--version AUTOrequirements callout is based on theselfhostedGithubConfigcheck inrunLocalGenerationForWorkspace.ts— it explicitly rejects AUTO whengithub.uri/github.tokenare absent, so the page now states that requirement up front.main. If your typical customer setup runs the SDK generation from the SDK repo instead, happy to add a second variant.Link to Devin session: https://app.devin.ai/sessions/27d62d318ccf41778b6cef95603e28fc
Requested by: @jsklan