fix(schema-diff): guard deploy script execution

This commit is contained in:
skyler authored and GitHub committed 2026-08-30 10:35:08 +08:00
1 parent 469bd88c37
commit f664918e95
6 files changed
+125 -18

No files matched your search

@@ -465,10 +465,6 @@ function copyDeploySqlAll() {
<Copy class="w-3 h-3" />
{{ t("diff.copy") }}
</Button>
<Button variant="ghost" size="sm" class="h-6 px-2 text-xs gap-1" :disabled="canExecute === false" @click="$emit('executeScript')">
<Play class="w-3 h-3" />
{{ t("diff.execute") }}
</Button>
</div>
</div>
<div class="flex-1 overflow-auto p-3">
@@ -51,6 +51,7 @@ import {
type CompatibilityWarning,
type PermissionDiff,
type DependencyGraph,
normalizeSchemaDiffDependencyGraph,
} from "@/lib/schema/schemaDiff";
import { compileSchemaDiffTableFilter, filterSchemaDiffTables } from "@/lib/schema/schemaDiffTableFilter";
import { Splitpanes, Pane } from "splitpanes";
@@ -593,7 +594,7 @@ async function handleCompare() {
renameCandidates.value = result.renameCandidates ?? [];
compatibilityWarnings.value = result.compatibilityWarnings ?? [];
permissionDiffs.value = result.permissionDiffs ?? [];
dependencyGraph.value = result.dependencyGraph ?? null;
dependencyGraph.value = normalizeSchemaDiffDependencyGraph(result.dependencyGraph);
// Convert to unified objects
diffObjects.value = convertToSchemaDiffObjects(result.diffs, result.functionDiffs, result.sequenceDiffs, result.ruleDiffs, result.ownerDiffs, result.renameCandidates);
@@ -686,13 +687,19 @@ function formatSchemaSyncPlan(plan: Awaited<ReturnType<typeof api.generateSchema
return { forwardSql, rollbackSql: nextRollbackSql };
}
function clearSelectedDeploySql() {
selectedForwardDeploySql.value = "";
selectedDeploySql.value = "";
rollbackSql.value = "";
rollbackCompleteness.value = "complete";
missingRollbackObjects.value = [];
}
async function regenerateSelectedDeploySql() {
const result = lastDiffResult.value;
const generation = ++selectedDeploySqlGeneration;
clearSelectedDeploySql();
if (!result) {
selectedForwardDeploySql.value = "-- No objects selected";
selectedDeploySql.value = "-- No objects selected";
rollbackSql.value = "";
return;
}
@@ -718,10 +725,10 @@ async function regenerateSelectedDeploySql() {
async function regenerateFocusedDeploySql(objectId: string | null = selectedObjectId.value) {
const result = lastDiffResult.value;
const generation = ++focusedDeploySqlGeneration;
focusedForwardDeploySql.value = "";
focusedRollbackSql.value = "";
focusedDeploySql.value = "";
if (!result || !objectId || !findSchemaDiffObject(diffObjects.value, objectId)) {
focusedForwardDeploySql.value = "-- No objects selected";
focusedRollbackSql.value = "";
focusedDeploySql.value = "-- No objects selected";
return;
}
@@ -759,7 +766,8 @@ const canExecuteDeploy = computed(() => {
if (deploySqlMode.value === "rollback" && rollbackCompleteness.value === "incomplete") {
return false;
}
return true;
const sql = selectedDeploySql.value.trim();
return sql.length > 0 && sql !== "-- No objects selected";
});
const destructiveStatements = computed(() => {
@@ -18,4 +18,12 @@ describe("SchemaDiffDdlPanel diff highlighting", () => {
expect(panelSource).toContain("rollbackForwardSql?: string;");
expect(panelSource).toContain("props.rollbackForwardSql ?? props.deploySql");
});
it("does not expose selected-SQL execution from the focused script tab", () => {
const focusedScript = panelSource.slice(panelSource.indexOf("<!-- Deploy Script -->"), panelSource.indexOf("<!-- Deploy Script All -->"));
const selectedScript = panelSource.slice(panelSource.indexOf("<!-- Deploy Script All -->"));
expect(focusedScript).not.toContain("$emit('executeScript')");
expect(selectedScript).toContain("$emit('executeScript')");
});
});
@@ -120,5 +120,7 @@ describe("SchemaDiffDialog fullscreen layout", () => {
expect(dialogSource).toContain("sql: selectedDeploySql.value");
expect(dialogSource).toContain("[selectedDeploySql.value]");
expect(dialogSource).toContain("selectedObjectId.value !== objectId");
expect(dialogSource).toContain('selectedDeploySql.value = "";');
expect(dialogSource).toContain("const sql = selectedDeploySql.value.trim();");
});
});