diff --git a/package.json b/package.json index dc24c71..e480ea3 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@subsquid/cli", "description": "squid cli tool", - "version": "3.3.3", + "version": "3.3.4", "license": "GPL-3.0-or-later", "repository": { "type": "git", @@ -81,7 +81,7 @@ "@oclif/plugin-autocomplete": "3.2.2", "@oclif/plugin-warn-if-update-available": "^3.1.13", "@subsquid/commands": "^2.3.1", - "@subsquid/manifest": "^2.1.2", + "@subsquid/manifest": "^2.1.3", "@types/fast-levenshtein": "^0.0.4", "@types/lodash": "^4.17.7", "@types/targz": "^1.0.4", diff --git a/src/commands/deploy.ts b/src/commands/deploy.ts index b55006a..c12f3b2 100644 --- a/src/commands/deploy.ts +++ b/src/commands/deploy.ts @@ -3,7 +3,7 @@ import path from 'node:path'; import { promisify } from 'util'; import { Args, Flags, ux as CliUx } from '@oclif/core'; -import { Manifest } from '@subsquid/manifest'; +import { Manifest, ManifestValue } from '@subsquid/manifest'; import chalk from 'chalk'; import diff from 'cli-diff'; import { globSync } from 'glob'; @@ -258,6 +258,17 @@ export default class Deploy extends DeployCommand { if (!update) return; } + /** + * Prevent deploying if the Postgres version has changed (requires hard reset) + */ + const versionMismatch = getPostgresVersionMismatch(target, manifest); + if (!hardReset && versionMismatch) { + this.error( + `The squid ${printSquid(target!)} is currently using Postgres ${versionMismatch.currentVersion}, but the new manifest specifies Postgres ${versionMismatch.newVersion}. ` + + `Changing the Postgres version requires a hard reset. Please do it explicitly using "--hard-reset" flag.`, + ); + } + /** * Warn if the existing squid has a Postgres addon but the new manifest removes it */ @@ -545,3 +556,20 @@ export function getIgnorePatterns(ignoreDir: string, raw: string) { function toRootPattern(pattern: string) { return pattern.startsWith('/') ? pattern : `/${pattern}`; } + +export function getPostgresVersionMismatch( + target: Squid | null, + manifest: Manifest, +): { currentVersion: string; newVersion: string } | null { + if (!target?.addons?.postgres || !manifest.deploy?.addons?.postgres) return null; + + const currentManifest = target.manifest.current as ManifestValue; + const currentVersion = currentManifest.deploy?.addons?.postgres?.version; + const newVersion = manifest.deploy.addons.postgres.version; + + if (currentVersion && newVersion && currentVersion !== newVersion) { + return { currentVersion, newVersion }; + } + + return null; +} diff --git a/src/commands/deploy.unit.spec.ts b/src/commands/deploy.unit.spec.ts index 843b38f..9e9c11b 100644 --- a/src/commands/deploy.unit.spec.ts +++ b/src/commands/deploy.unit.spec.ts @@ -1,4 +1,4 @@ -import { getIgnorePatterns } from './deploy'; +import { getIgnorePatterns, getPostgresVersionMismatch } from './deploy'; describe('Deploy', () => { describe('get squid ignore paths', () => { @@ -25,4 +25,58 @@ describe('Deploy', () => { expect(patterns).toEqual(['/dir/.git', '/dir/builds', '/dir/abi', '/dir/**/test', '/dir/**/.env', '/dir/**/foo']); }); }); + + describe('getPostgresVersionMismatch', () => { + function makeTarget(pgVersion?: string) { + return { + addons: pgVersion + ? { postgres: { connections: [], disk: { usageStatus: 'NORMAL', usedBytes: 0, totalBytes: 0 } } } + : undefined, + manifest: { + current: pgVersion + ? { deploy: { addons: { postgres: { version: pgVersion } } } } + : { deploy: {} }, + raw: '', + }, + } as any; + } + + function makeManifest(pgVersion?: string) { + return { + deploy: pgVersion ? { addons: { postgres: { version: pgVersion } } } : { addons: {} }, + } as any; + } + + it('returns mismatch when versions differ', () => { + const result = getPostgresVersionMismatch(makeTarget('16'), makeManifest('17')); + expect(result).toEqual({ currentVersion: '16', newVersion: '17' }); + }); + + it('returns null when versions match', () => { + const result = getPostgresVersionMismatch(makeTarget('16'), makeManifest('16')); + expect(result).toBeNull(); + }); + + it('returns null when target is null', () => { + const result = getPostgresVersionMismatch(null, makeManifest('17')); + expect(result).toBeNull(); + }); + + it('returns null when target has no postgres addon', () => { + const result = getPostgresVersionMismatch(makeTarget(), makeManifest('17')); + expect(result).toBeNull(); + }); + + it('returns null when new manifest has no postgres addon', () => { + const result = getPostgresVersionMismatch(makeTarget('16'), makeManifest()); + expect(result).toBeNull(); + }); + + it('returns null when current manifest has no postgres version', () => { + const target = makeTarget('16'); + target.manifest.current = { deploy: { addons: { postgres: {} } } }; + const result = getPostgresVersionMismatch(target, makeManifest('17')); + expect(result).toBeNull(); + }); + }); }); diff --git a/yarn.lock b/yarn.lock index 76de593..6a0f07e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1411,7 +1411,7 @@ __metadata: "@oclif/plugin-autocomplete": "npm:3.2.2" "@oclif/plugin-warn-if-update-available": "npm:^3.1.13" "@subsquid/commands": "npm:^2.3.1" - "@subsquid/manifest": "npm:^2.1.2" + "@subsquid/manifest": "npm:^2.1.3" "@types/async-retry": "npm:^1.4.8" "@types/blessed": "npm:^0.1.25" "@types/cross-spawn": "npm:^6.0.6" @@ -1505,14 +1505,14 @@ __metadata: languageName: node linkType: hard -"@subsquid/manifest@npm:^2.1.2": - version: 2.1.2 - resolution: "@subsquid/manifest@npm:2.1.2" +"@subsquid/manifest@npm:^2.1.3": + version: 2.1.3 + resolution: "@subsquid/manifest@npm:2.1.3" dependencies: joi: "npm:17.13.3" js-yaml: "npm:^4.1.0" lodash: "npm:^4.17.21" - checksum: 10c0/20282d0e6278a4df28313fb4ade39c6a81a11caa49eb43a117e5cb115e731d693797a784080deab4587d4df17da94475c843550cdedf444f0543f32ac338084a + checksum: 10c0/ad569035cebd8c4fc6c67f7af7e827cc5a5925186fcb9205c88f28f18257779cb8f456cfbe0ae5ce1d735928cdc530b1b0974ca088a13056b4f4e6bab24f1025 languageName: node linkType: hard