Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Manifest migration strategy update #1286

Merged
merged 4 commits into from
Oct 4, 2022
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -10,34 +10,15 @@ import {
{{#latest}}{{type}}{{/latest}}Formats,
latest{{#latest}}{{type}}{{/latest}}Format
} from ".";

{{#prevFormats}}
import {
migrate as migrate_{{tsVersion}}_to_{{#latest}}{{tsVersion}}{{/latest}}
} from "./migrators/{{version}}_to_{{#latest}}{{version}}{{/latest}}";
{{/prevFormats}}

type Migrator = {
[key in {{#latest}}{{type}}{{/latest}}Formats]?: (m: Any{{#latest}}{{type}}{{/latest}}) => {{#latest}}{{type}}{{/latest}};
};

export const migrators: Migrator = {
{{#prevFormats}}
"{{version}}": migrate_{{tsVersion}}_to_{{#latest}}{{tsVersion}}{{/latest}},
{{/prevFormats}}
};
import { findShortestMigrationPath } from "../../migrations";
import { migrators } from "./migrators";

export function migrate{{#latest}}{{type}}{{/latest}}(
manifest: Any{{#latest}}{{type}}{{/latest}},
to: {{#latest}}{{type}}{{/latest}}Formats
): {{#latest}}{{type}}{{/latest}} {
let from = manifest.format as {{#latest}}{{type}}{{/latest}}Formats;

// HACK: Patch fix for backwards compatability
if(from === "0.1" && ("0.1.0" in migrators)) {
from = "0.1.0" as {{#latest}}{{type}}{{/latest}}Formats;
}

if (from === latest{{#latest}}{{type}}{{/latest}}Format) {
return manifest as {{#latest}}{{type}}{{/latest}};
}
Expand All @@ -46,17 +27,18 @@ export function migrate{{#latest}}{{type}}{{/latest}}(
throw new Error(`Unrecognized {{#latest}}{{type}}{{/latest}}Format "${manifest.format}"`);
}

{{#prevFormats.length}}
const migrator = migrators[from];
if (!migrator) {
const migrationPath = findShortestMigrationPath(migrators, from, to);
if (!migrationPath) {
throw new Error(
`Migrator from {{#latest}}{{type}}{{/latest}}Format "${from}" to "${to}" is not available`
`Migration path from {{#latest}}{{type}}{{/latest}}Format "${from}" to "${to}" is not available`
);
}

return migrator(manifest);
{{/prevFormats.length}}
{{^prevFormats.length}}
throw new Error(`This should never happen, {{#latest}}{{type}}{{/latest}} migrators is empty. from: ${from}, to: ${to}`);
{{/prevFormats.length}}
let newManifest = manifest;

for(const migrator of migrationPath){
newManifest = migrator.migrate(newManifest) as Any{{#latest}}{{type}}{{/latest}};
}

return newManifest as {{#latest}}{{type}}{{/latest}};
}
77 changes: 69 additions & 8 deletions packages/js/manifests/polywrap/src/__tests__/migrations.spec.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,70 @@
import { deserializeDeployManifest, deserializePolywrapManifest } from "../";

import fs from "fs";
import { findShortestMigrationPath, Migrator } from "../migrations";

describe("Polywrap Manifest Migrations", () => {
it("Should succesfully migrate from 0.1.0 to 0.2.0", async() => {
const manifestPath = __dirname + "/manifest/polywrap/migrations/polywrap-0.1.0.yaml";
const expectedManifestPath = __dirname + "/manifest/polywrap/migrations/polywrap-0.2.0.yaml";
describe("Manifest migration pathfinding", () => {
const migrators: Migrator[] = [
{
from: "0.1.0",
to: "0.2.0",
migrate: () => {},
},
{
from: "0.2.0",
to: "0.3.0",
migrate: () => {},
},
{
from: "0.3.0",
to: "0.4.0",
migrate: () => {},
},
{
from: "0.4.0",
to: "0.5.0",
migrate: () => {},
},
{
from: "0.2.0",
to: "0.4.0",
migrate: () => {},
},
];

it("Should return undefined when no migration path exists", async () => {
const path = findShortestMigrationPath(migrators, "0.1.0", "0.6.0");

expect(path).toBeUndefined();

const reverseUnsupportedPath = findShortestMigrationPath(
migrators,
"0.2.0",
"0.1.0"
);

expect(reverseUnsupportedPath).toBeUndefined();
});

it("Should return an empty array when from and to are the same", async () => {
const path = findShortestMigrationPath(migrators, "0.1.0", "0.1.0");

expect(path).toEqual([]);
});

it("Should return the shortest migration path", async () => {
const path = findShortestMigrationPath(migrators, "0.1.0", "0.5.0");

expect(path).toEqual([migrators[0], migrators[4], migrators[3]]);
});
});

describe("Polywrap Project Manifest Migrations", () => {
it("Should succesfully migrate from 0.1.0 to 0.2.0", async () => {
const manifestPath =
__dirname + "/manifest/polywrap/migrations/polywrap-0.1.0.yaml";
const expectedManifestPath =
__dirname + "/manifest/polywrap/migrations/polywrap-0.2.0.yaml";

const manifestFile = fs.readFileSync(manifestPath, "utf-8");
const expectedManifestFile = fs.readFileSync(expectedManifestPath, "utf-8");
Expand All @@ -18,9 +77,11 @@ describe("Polywrap Manifest Migrations", () => {
});

describe("Polywrap Deploy Manifest Migrations", () => {
it("Should succesfully migrate from 0.1.0 to 0.2.0", async() => {
const manifestPath = __dirname + "/manifest/deploy/migrations/polywrap-0.1.0.yaml";
const expectedManifestPath = __dirname + "/manifest/deploy/migrations/polywrap-0.2.0.yaml";
it("Should succesfully migrate from 0.1.0 to 0.2.0", async () => {
const manifestPath =
__dirname + "/manifest/deploy/migrations/polywrap-0.1.0.yaml";
const expectedManifestPath =
__dirname + "/manifest/deploy/migrations/polywrap-0.2.0.yaml";

const manifestFile = fs.readFileSync(manifestPath, "utf-8");
const expectedManifestFile = fs.readFileSync(expectedManifestPath, "utf-8");
Expand All @@ -30,4 +91,4 @@ describe("Polywrap Deploy Manifest Migrations", () => {

expect(manifest).toEqual(expectedManifest);
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -10,30 +10,15 @@ import {
AppManifestFormats,
latestAppManifestFormat
} from ".";

import {
migrate as migrate_0_1_0_to_0_2_0
} from "./migrators/0.1.0_to_0.2.0";

type Migrator = {
[key in AppManifestFormats]?: (m: AnyAppManifest) => AppManifest;
};

export const migrators: Migrator = {
"0.1.0": migrate_0_1_0_to_0_2_0,
};
import { findShortestMigrationPath } from "../../migrations";
import { migrators } from "./migrators";

export function migrateAppManifest(
manifest: AnyAppManifest,
to: AppManifestFormats
): AppManifest {
let from = manifest.format as AppManifestFormats;

// HACK: Patch fix for backwards compatability
if(from === "0.1" && ("0.1.0" in migrators)) {
from = "0.1.0" as AppManifestFormats;
}

if (from === latestAppManifestFormat) {
return manifest as AppManifest;
}
Expand All @@ -42,12 +27,18 @@ export function migrateAppManifest(
throw new Error(`Unrecognized AppManifestFormat "${manifest.format}"`);
}

const migrator = migrators[from];
if (!migrator) {
const migrationPath = findShortestMigrationPath(migrators, from, to);
if (!migrationPath) {
throw new Error(
`Migrator from AppManifestFormat "${from}" to "${to}" is not available`
`Migration path from AppManifestFormat "${from}" to "${to}" is not available`
);
}

return migrator(manifest);
let newManifest = manifest;

for(const migrator of migrationPath){
newManifest = migrator.migrate(newManifest) as AnyAppManifest;
}

return newManifest as AppManifest;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { Migrator } from "../../../migrations";
import { migrate as migrate_0_1_0_to_0_2_0 } from "./0.1.0_to_0.2.0";

export const migrators: Migrator[] = [
{
from: "0.1",
to: "0.2.0",
migrate: migrate_0_1_0_to_0_2_0
},
{
from: "0.1.0",
to: "0.2.0",
migrate: migrate_0_1_0_to_0_2_0
}
];
Original file line number Diff line number Diff line change
Expand Up @@ -10,26 +10,15 @@ import {
BuildManifestFormats,
latestBuildManifestFormat
} from ".";


type Migrator = {
[key in BuildManifestFormats]?: (m: AnyBuildManifest) => BuildManifest;
};

export const migrators: Migrator = {
};
import { findShortestMigrationPath } from "../../migrations";
import { migrators } from "./migrators";

export function migrateBuildManifest(
manifest: AnyBuildManifest,
to: BuildManifestFormats
): BuildManifest {
let from = manifest.format as BuildManifestFormats;

// HACK: Patch fix for backwards compatability
if(from === "0.1" && ("0.1.0" in migrators)) {
from = "0.1.0" as BuildManifestFormats;
}

if (from === latestBuildManifestFormat) {
return manifest as BuildManifest;
}
Expand All @@ -38,5 +27,18 @@ export function migrateBuildManifest(
throw new Error(`Unrecognized BuildManifestFormat "${manifest.format}"`);
}

throw new Error(`This should never happen, BuildManifest migrators is empty. from: ${from}, to: ${to}`);
const migrationPath = findShortestMigrationPath(migrators, from, to);
if (!migrationPath) {
throw new Error(
`Migration path from BuildManifestFormat "${from}" to "${to}" is not available`
);
}

let newManifest = manifest;

for(const migrator of migrationPath){
newManifest = migrator.migrate(newManifest) as AnyBuildManifest;
}

return newManifest as BuildManifest;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { Migrator } from "../../../migrations";

export const migrators: Migrator[] = [];
Original file line number Diff line number Diff line change
Expand Up @@ -10,30 +10,15 @@ import {
DeployManifestFormats,
latestDeployManifestFormat
} from ".";

import {
migrate as migrate_0_1_0_to_0_2_0
} from "./migrators/0.1.0_to_0.2.0";

type Migrator = {
[key in DeployManifestFormats]?: (m: AnyDeployManifest) => DeployManifest;
};

export const migrators: Migrator = {
"0.1.0": migrate_0_1_0_to_0_2_0,
};
import { findShortestMigrationPath } from "../../migrations";
import { migrators } from "./migrators";

export function migrateDeployManifest(
manifest: AnyDeployManifest,
to: DeployManifestFormats
): DeployManifest {
let from = manifest.format as DeployManifestFormats;

// HACK: Patch fix for backwards compatability
if(from === "0.1" && ("0.1.0" in migrators)) {
from = "0.1.0" as DeployManifestFormats;
}

if (from === latestDeployManifestFormat) {
return manifest as DeployManifest;
}
Expand All @@ -42,12 +27,18 @@ export function migrateDeployManifest(
throw new Error(`Unrecognized DeployManifestFormat "${manifest.format}"`);
}

const migrator = migrators[from];
if (!migrator) {
const migrationPath = findShortestMigrationPath(migrators, from, to);
if (!migrationPath) {
throw new Error(
`Migrator from DeployManifestFormat "${from}" to "${to}" is not available`
`Migration path from DeployManifestFormat "${from}" to "${to}" is not available`
);
}

return migrator(manifest);
let newManifest = manifest;

for(const migrator of migrationPath){
newManifest = migrator.migrate(newManifest) as AnyDeployManifest;
}

return newManifest as DeployManifest;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { Migrator } from "../../../migrations";
import { migrate as migrate_0_1_0_to_0_2_0 } from "./0.1.0_to_0.2.0";

export const migrators: Migrator[] = [
{
from: "0.1",
to: "0.2.0",
migrate: migrate_0_1_0_to_0_2_0
},
{
from: "0.1.0",
to: "0.2.0",
migrate: migrate_0_1_0_to_0_2_0
}
];
Loading