fix(server): stabilize flaky app-install workspace-version gate test (#22851)
## What The integration test `failing-app-installation-workspace-version.integration-spec.ts` is flaky depending on the shape of the upgrade sequence, especially right after a version bump. It intermittently fails at upload time with: ``` App requires Twenty server >=2.21.0 but this server is 2.20.0. (SERVER_VERSION_INCOMPATIBLE) ``` ## Why The test mixed two different version sources: - The upload-time check (`validateServerCompatibility`) compares the app's required version against the **instance** inferred version, i.e. the last attempted instance command (`workspaceId IS NULL`, via `getInferredVersion`). - The test's `beforeAll` instead derived the required version from the **workspace** cursor. These agree most of the time but diverge right after a version bump whose newest upgrade segment ends in workspace-scoped commands and adds no new instance command. In that state the seeded workspace cursor sits at the new version while the instance is still at the previous one. The test then uploads an app requiring `>=newVersion`, which fails the instance gate at upload time before the workspace gate under test is ever reached. ## How Derive the gate version in `beforeAll` from the last attempted instance command, mirroring exactly what `getInferredVersion()` uses. The required version is then always `>=` the instance's own version, so the upload passes; injecting that same command as a failed workspace attempt drops the workspace to the previous completed version, so the install reliably hits the workspace gate and returns `WORKSPACE_VERSION_INCOMPATIBLE` as the snapshot expects. This holds regardless of whether the newest version's segment ends in an instance or workspace command. No production code changed; the fix is confined to test setup logic. --- _Generated by [Claude Code](https://claude.ai/code/session_01UtEpU7fF4q6pydGRaawfve)_ <!-- This is an auto-generated description by cubic. --> <a href="https://cubic.dev/pr/twentyhq/twenty/pull/22851?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:
+25
-17
@@ -76,29 +76,37 @@ describe('Install application is gated by the workspace completed upgrade versio
|
||||
beforeAll(async () => {
|
||||
jest.useRealTimers();
|
||||
|
||||
// The seeded workspace's cursor is the last step of the current version.
|
||||
// Re-injecting it as a failed attempt makes the workspace resolve to the
|
||||
// previous completed version — i.e. behind the instance.
|
||||
const [workspaceCursor] = await global.testDataSource.query(
|
||||
`SELECT name FROM core."upgradeMigration"
|
||||
WHERE "workspaceId" = $1
|
||||
ORDER BY "createdAt" DESC, attempt DESC
|
||||
// Derive the gate version from the last attempted instance command, which
|
||||
// is exactly what the upload-time server-compat check uses
|
||||
// (getInferredVersion). The seeded workspace cursor can sit a version ahead
|
||||
// of the instance right after a version bump whose newest segment ends in
|
||||
// workspace-scoped commands with no new instance command: requiring
|
||||
// >=workspaceVersion would then fail the instance gate at upload time,
|
||||
// before the workspace gate under test is reached.
|
||||
const [instanceCommand] = await global.testDataSource.query(
|
||||
`SELECT migration.name AS name
|
||||
FROM core."upgradeMigration" migration
|
||||
WHERE migration."workspaceId" IS NULL
|
||||
AND migration."isInitial" = false
|
||||
AND migration.attempt = (
|
||||
SELECT MAX(sub.attempt)
|
||||
FROM core."upgradeMigration" sub
|
||||
WHERE sub.name = migration.name
|
||||
AND sub."workspaceId" IS NULL
|
||||
)
|
||||
ORDER BY migration."createdAt" DESC
|
||||
LIMIT 1`,
|
||||
[SEED_APPLE_WORKSPACE_ID],
|
||||
);
|
||||
|
||||
if (!isDefined(workspaceCursor)) {
|
||||
throw new Error(
|
||||
`Expected a seeded upgrade cursor for workspace ${SEED_APPLE_WORKSPACE_ID}`,
|
||||
);
|
||||
if (!isDefined(instanceCommand)) {
|
||||
throw new Error('Expected a seeded instance upgrade command');
|
||||
}
|
||||
|
||||
currentVersionCommandName = workspaceCursor.name;
|
||||
// Re-injecting this command as a failed workspace attempt makes the
|
||||
// workspace resolve to the previous completed version (behind the
|
||||
// instance), so the install reaches the workspace gate.
|
||||
currentVersionCommandName = instanceCommand.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,
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user