Skip to content

feat(cli): support Postman's on-prem generator image - #17548

Draft
ATechAdventurer wants to merge 2 commits into
mainfrom
fsdk-onprem-cli-support
Draft

feat(cli): support Postman's on-prem generator image#17548
ATechAdventurer wants to merge 2 commits into
mainfrom
fsdk-onprem-cli-support

Conversation

@ATechAdventurer

@ATechAdventurer ATechAdventurer commented Aug 27, 2026

Copy link
Copy Markdown

Two independent changes local generation needs to run a generator image in an air-gapped customer environment, and to pin exactly which image runs.

Folds together #17509 and #17512, which were previously stacked, so there is one review instead of three.

Network mode

FERN_GENERATOR_NETWORK opts a run into a container network mode. none runs the generator with no network access, which air-gapped environments require. Unset, container networking is unchanged.

An environment variable rather than a generators.yml key so the switch exists without a schema change — a first-class config field or CLI flag is the natural follow-up if that is preferred.

Digest pinning

A generator image can be pinned by digest in generators.yml:

- name: fern-python-sdk@sha256:abc...

The digest passes through to the container runtime unchanged so the exact pinned image runs. The generator name used for IR version resolution is unaffected — that split matters, because Fern picks the IR version from a table keyed on the generator name, so folding the digest into the name would change which IR the generator receives.

A malformed digest is rejected with an error naming generators.yml. Tag-based references are unchanged.

Shared helper

Both route image resolution through one resolveGeneratorImage(), replacing the inline containerImage ?? name + version concatenation so every caller agrees on which image is run. It returns a digest reference untouched rather than appending :version, which would produce the invalid repo@sha256:...:1.2.3 and defeat the point of pinning.

What is deliberately not here

#17508 (raw-spec capability labels) is excluded and should be closed. The reason has been sharpened since this PR was opened.

Originally: the label could only be honoured by a CLI new enough to read it, and Postman's on-prem images are invoked by whatever CLI the customer already runs.

More accurately: the generator container never needs a raw-spec mount at all. It is handed a configuration that already points at its sources — source.specs[].specUrl — and resolves them itself. That is how the hosted route works today (sdk-gen-api, translateFernTargetToSdkConfigIrV1), and it is how the local route will work once the CLI emits sdk-config/v1. A label asking the CLI to mount specs describes a need that does not exist on either route.

Either way the label is not something Fern should carry, and its resolveGeneratorImage helper is kept here on its own merits.

Its resolveGeneratorImage helper is kept here, since digest pinning genuinely needs it and it has nothing to do with labels.

Compatibility

Both features are opt-in and inert when unused. An unset FERN_GENERATOR_NETWORK and a tag-based image reference both behave exactly as they do today.

Verification

  • resolveGeneratorImage — 3 tests (bare name tagged, explicit container image preferred, digest returned unchanged)
  • splitImageDigest — 8 tests, including that the name survives the split unchanged, since IR resolution keys on it
  • network passthrough — 3 tests
  • tsc --noEmit on local-workspace-runner produces 246 errors on this branch and 246 on main; diffing the error sets shows 3 added and 3 removed, and all six are the same pre-existing implicitly has an 'any' type errors shifted by one line. The monorepo reports these from uncompiled workspace deps regardless of this change.

ATechAdventurer and others added 2 commits August 27, 2026 13:13
Two independent changes local generation needs to run a generator image in
an air-gapped customer environment and to pin exactly which image runs.

Network mode. FERN_GENERATOR_NETWORK opts a run into a container network
mode; `none` runs the generator with no network access, which air-gapped
environments require. Unset, container networking is unchanged. An
environment variable rather than a generators.yml key so the switch exists
without a schema change.

Digest pinning. A generator image can be pinned by digest in generators.yml
(`name: fern-python-sdk@sha256:...`). The digest passes through to the
container runtime unchanged, while the generator name used for IR version
resolution is unaffected -- the split matters because IR version resolution
is keyed on the name. A malformed digest is rejected with an error naming
generators.yml. Tag-based references are unchanged.

Both route image resolution through one resolveGeneratorImage helper, which
replaces the inline containerImage/name/version concatenation so every
caller agrees on which image is run.

Supersedes #17509 and #17512, which are folded in here. #17508 (raw-spec
capability labels) is deliberately not included: it can only be honoured by
a CLI new enough to read the label, and Postman's images are published under
existing Fern generator names and invoked by whatever CLI the customer
already runs.
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.

1 participant