257f130fff
## What Makes `yarn twenty docker:start` version-selectable. Same core feature as #21686 — but here scaffolded apps default to `latest` (pinning is **opt-in**) rather than being pinned to the scaffolder's version. > Alternative to #21686. Pick one; the difference is only the scaffolded default. Two layers of resolution: 1. **Explicit flag** — `yarn twenty docker:start [version]`, mirroring the existing `docker:upgrade [version]`. 2. **App-pinned default** — when no version is passed, `docker:start` reads `twenty.serverVersion` from the app's `package.json`, falling back to `latest`. Generated apps ship `twenty.serverVersion: "latest"`, so default behavior is unchanged. To make the local server reproducible as code, set a version: ```json filename="package.json" { "twenty": { "serverVersion": "2.2.0" } } ``` ## Changes - `twenty-sdk`: new `getAppServerVersion()` util reads `twenty.serverVersion` from the cwd's `package.json`; `serverStart` gains a `version` option and resolves `option → app pin → latest`, building the image via `getImageForVersion()`; `docker:start [version]` (and the deprecated `server start [version]` alias) wired up. - `create-twenty-app`: template `package.json` ships `twenty.serverVersion: "latest"`. (`create-app` and the scaffolder are otherwise untouched.) - Docs: `local-server.mdx` documents version selection and the opt-in pin. ## Behavior notes - Default with no pin and no flag is `latest` — same as today. - Version only matters when **creating** a fresh container — an existing container keeps its image until `docker:upgrade` / `docker:reset`. ## Testing - New unit tests for `getAppServerVersion` (5 cases). - Extended the `app-template` scaffolding test to assert the `latest` default. - `twenty-sdk` cli vitest suite (273) and `create-twenty-app` jest suite (9) pass; oxlint + oxfmt clean on changed files. <!-- This is an auto-generated description by cubic. --> <a href="https://cubic.dev/pr/twentyhq/twenty/pull/21690?utm_source=github" target="_blank" rel="noopener noreferrer" data-no-image-dialog="true"><picture><source media="(prefers-color-scheme: dark)" srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img alt="Review in cubic" src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a> <!-- End of auto-generated description by cubic. -->
31 lines
836 B
TypeScript
31 lines
836 B
TypeScript
import semver from 'semver';
|
|
|
|
import { getEngineVersionRange } from '@/cli/utilities/version/get-engine-version-range';
|
|
import { getPublishedServerVersions } from '@/cli/utilities/version/get-published-server-versions';
|
|
|
|
export const resolveHighestEngineVersion = async (
|
|
explicitVersion?: string,
|
|
): Promise<string> => {
|
|
const explicit = explicitVersion?.trim();
|
|
|
|
if (explicit) {
|
|
return explicit;
|
|
}
|
|
|
|
const range = getEngineVersionRange();
|
|
|
|
if (range === null || semver.validRange(range) === null) {
|
|
return 'latest';
|
|
}
|
|
|
|
const published = await getPublishedServerVersions();
|
|
|
|
const bestMatch = published
|
|
.map((version) => version.name)
|
|
.filter((name) => semver.valid(name) !== null)
|
|
.filter((name) => semver.satisfies(name, range))
|
|
.sort(semver.rcompare)[0];
|
|
|
|
return bestMatch ?? 'latest';
|
|
};
|