fix(server): stabilize app install version-gate integration test (#22826)

## Why

The `failing-app-installation-workspace-version` integration suite fails
on CI (e.g. [this
run](https://github.com/twentyhq/twenty/actions/runs/29105697459/job/86405891168)):

```
App requires Twenty server >=2.21.0 but this server is 2.20.0.
subCode: SERVER_VERSION_INCOMPATIBLE
```

The test uploads an app requiring `>=${TWENTY_CURRENT_VERSION}` and
expects the install to be rejected by the **workspace** version gate.
But after the `2.21.0` version bump, `TWENTY_CURRENT_VERSION` (`2.21.0`)
moved ahead of the latest instance upgrade command (`2-20`, so
`getInferredVersion()` returns `2.20.0`). The tarball upload runs the
**instance** server-compat check first, which rejects `>=2.21.0` against
a `2.20.0` server before the workspace gate under test is ever reached.

The sibling sync test is unaffected because sync only validates
workspace compatibility, not the upload-time instance check.

## What

Derive the required version range from the version the instance actually
reached (the workspace upgrade cursor via
`extractVersionFromCommandName`) instead of the drifting
`TWENTY_CURRENT_VERSION` constant. This way:

- The upload passes the instance server-compat check (server satisfies
`>=<current version>`).
- The workspace, which resolves one version behind after the injected
failed cursor, still fails the workspace gate, producing the expected
`WORKSPACE_VERSION_INCOMPATIBLE` error.

The error assertion keeps using the normalized snapshot
(`scrubSemverVersions`), so the concrete version numbers do not leak
into the snapshot and future version bumps won't churn it.

---
_Generated by [Claude
Code](https://claude.ai/code/session_01XqhqQ8VGJZWBuznR8nRviX)_

<!-- This is an auto-generated description by cubic. -->
<a
href="https://cubic.dev/pr/twentyhq/twenty/pull/22826?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. -->
This commit is contained in:
Paul Rastoin
2026-07-10 18:33:25 +02:00
committed by GitHub
parent c9d84ba7f0
commit 3614183200
@@ -8,7 +8,7 @@ import { scrubSemverVersions } from 'test/utils/scrub-semver-versions.util';
import { isDefined } from 'twenty-shared/utils';
import { v4 as uuidv4 } from 'uuid';
import { TWENTY_CURRENT_VERSION } from 'src/engine/core-modules/upgrade/constants/twenty-current-version.constant';
import { extractVersionFromCommandName } from 'src/engine/core-modules/upgrade/utils/extract-version-from-command-name.util';
import { SEED_APPLE_WORKSPACE_ID } from 'src/engine/workspace-manager/dev-seeder/core/constants/seeder-workspaces.constant';
// The full install flow runs cache-lock retries with real delays, so fake
@@ -70,6 +70,7 @@ const uploadTarballApp = async ({
describe('Install application is gated by the workspace completed upgrade version', () => {
let currentVersionCommandName: string;
let currentServerVersion: string;
const createdApplicationUniversalIdentifiers: string[] = [];
beforeAll(async () => {
@@ -93,6 +94,22 @@ describe('Install application is gated by the workspace completed upgrade versio
}
currentVersionCommandName = workspaceCursor.name;
// Pin to the version the instance actually reached, not
// TWENTY_CURRENT_VERSION which can be bumped ahead of the latest instance
// command and trip the upload-time server-compat check before the
// workspace gate under test is reached.
const inferredServerVersion = extractVersionFromCommandName(
currentVersionCommandName,
);
if (!isDefined(inferredServerVersion)) {
throw new Error(
`Could not extract a server version from upgrade cursor "${currentVersionCommandName}"`,
);
}
currentServerVersion = inferredServerVersion;
});
afterEach(async () => {
@@ -116,7 +133,7 @@ describe('Install application is gated by the workspace completed upgrade versio
await uploadTarballApp({
universalIdentifier,
roleId,
requiredServerVersion: `>=${TWENTY_CURRENT_VERSION}`,
requiredServerVersion: `>=${currentServerVersion}`,
});
createdApplicationUniversalIdentifiers.push(universalIdentifier);