Skip to content

docs(sdks): document SDK auto-versioning for self-hosted setups#5473

Open
jsklan wants to merge 10 commits into
mainfrom
devin/1778610174-self-hosted-versioning
Open

docs(sdks): document SDK auto-versioning for self-hosted setups#5473
jsklan wants to merge 10 commits into
mainfrom
devin/1778610174-self-hosted-versioning

Conversation

@jsklan
Copy link
Copy Markdown
Contributor

@jsklan jsklan commented May 12, 2026

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-line fern generate --version AUTO invocation, what the LLM-powered diff analysis produces (changelog entry, PR description, conventional-commit message), and the FERN_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 from fern diff --from-version, including the --version/--output-version split between CLI v1 and v2.
  • Wiring fern ir + fern diff into CI: full GitHub Actions snippet that reads originGitCommit and sdkVersion from the SDK repo's .fern/metadata.json, checks out the previous spec, runs fern ir against both revisions, computes the next version, and generates the SDK. Includes the fetch-depth: 0 callout.

Linear: FER-10500

Review & Testing Checklist for Human

  • Open the preview link and confirm the page renders cleanly (Steps, Tabs, Info blocks, code blocks all formatted as expected).
  • Sanity-check the GitHub Actions snippet — in particular the metadata-fetch step (uses the GitHub Contents API with the workflow's GITHUB_TOKEN) and the git checkout ${{ github.sha }} step that returns to HEAD.
  • Confirm the framing of --version AUTO vs. fern ir + fern diff matches how you want enterprise customers to think about the two paths. Easiest to flag any phrasing nits as inline comments on the preview.

Notes

  • The --version AUTO requirements callout is based on the selfhostedGithubConfig check in runLocalGenerationForWorkspace.ts — it explicitly rejects AUTO when github.uri/github.token are absent, so the page now states that requirement up front.
  • The CI snippet assumes the workflow runs in the config repo on push to 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


Open in Devin Review

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
@devin-ai-integration
Copy link
Copy Markdown
Contributor

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment and CI monitoring

```

<Info>
`--version AUTO` requires:
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

📝 [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`.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

📝 [vale] reported by reviewdog 🐶
[FernStyles.Acronyms] 'SHA' has no definition.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 12, 2026

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Copy link
Copy Markdown
Contributor

@devin-ai-integration devin-ai-integration Bot left a comment

Choose a reason for hiding this comment

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

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no potential bugs to report.

View in Devin Review to see 2 additional findings.

Open in Devin Review

@jsklan
Copy link
Copy Markdown
Contributor Author

jsklan commented May 12, 2026

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 fern ir + fern diff section:

It's the legacy path — --version AUTO will keep getting improvements first — but it remains fully supported for setups that need explicit control.

The intro bullets already establish the relative framing. This sentence is redundant and reads as a sales pitch.


2. Fix the --version AUTO requirements block — LLM runs locally, not via a hosted Fern service

The current Info block says:

the diff analysis runs as a hosted Fern service that authenticates your organization the same way cloud generation does

This is incorrect. When running fern generate --local --version AUTO, the Fern CLI calls an LLM provider directly from the user's machine using their own credentials. No Fern-hosted service is involved.

Replace the requirements bullet list with:

- `FERN_TOKEN` (for organization verification, same as all local generation)
- An LLM provider API key for the diff analysis — set one of:
  - `OPENAI_API_KEY` for OpenAI
  - `ANTHROPIC_API_KEY` for Anthropic
  - 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`), because the pipeline pushes the version bump and changelog back to the SDK repo

3. Add errors field to the fern diff JSON example

The actual Result interface from fern diff has three fields: bump, nextVersion, and errors. The current example only shows two. Update it to:

{
  "bump": "minor",
  "nextVersion": "1.5.0",
  "errors": []
}

Everything else checks out: fern-api/setup-fern-cli@v1 is a real action, the fern diff exit-code callout (exits 1 on major) is accurate, the GitHub config requirement for --version AUTO is confirmed correct, and the CI snippet structure is sound.

- 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>
@devin-ai-integration
Copy link
Copy Markdown
Contributor

All three applied in 2bc6bb0:

  1. Dropped the editorial sentence from the fern ir + fern diff intro; the body of that paragraph now reads "This flow has no LLM dependency: fern diff walks the IR of both specs and returns a deterministic result."
  2. Reworked the --version AUTO requirements block to FERN_TOKEN + LLM provider key (OpenAI / Anthropic / Bedrock) + self-hosted GitHub output.
  3. Added "errors": [] to the fern diff JSON example.

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.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🚫 [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.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🚫 [vale] reported by reviewdog 🐶
[Microsoft.Contractions] Use 'isn't' instead of 'is not'.

jsklan and others added 2 commits May 12, 2026 21:06
…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>
@jsklan jsklan marked this pull request as ready for review May 12, 2026 21:41
@jsklan jsklan requested a review from devalog as a code owner May 12, 2026 21:41
Copy link
Copy Markdown
Contributor

@devin-ai-integration devin-ai-integration Bot left a comment

Choose a reason for hiding this comment

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

Devin Review found 3 new potential issues.

View 5 additional findings in Devin Review.

Open in Devin Review

- A [conventional commit](https://www.conventionalcommits.org/) message

```bash
FERN_TOKEN=<token> fern generate --version AUTO
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔴 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.

Suggested change
FERN_TOKEN=<token> fern generate --version AUTO
FERN_TOKEN=<token> fern generate --local --version AUTO
Open in Devin Review

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 }}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔴 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.

Suggested change
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 }}
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

<Tabs>
<Tab title="CLI v1" language="cli-v1">
```bash
fern generate --version 1.5.0
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 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.

Suggested change
fern generate --version 1.5.0
fern generate --local --version 1.5.0
Open in Devin Review

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.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I wouldn't link to autorelease, it's a hidden page for now.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

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.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think we should explain why someone would pick AUTO over deterministic versioning. At face value deterministic looks a lot more logica.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

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.

jsklan and others added 2 commits May 13, 2026 01:17
…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.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🚫 [vale] reported by reviewdog 🐶
[Microsoft.Contractions] Use 'isn't' instead of 'is not'.

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.

3 participants