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

enhance(publish): track templateVersion on initialization #3036

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all 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
6 changes: 6 additions & 0 deletions packages/common-all/data/dendron-yml.validator.json
Original file line number Diff line number Diff line change
Expand Up @@ -768,6 +768,9 @@
},
"apiEndpoint": {
"type": "string"
},
"templateHierarchy": {
"type": "string"
}
},
"required": [
Expand Down Expand Up @@ -1173,6 +1176,9 @@
},
"enablePrettyLinks": {
"type": "boolean"
},
"publishTemplateVersion": {
"type": "number"
}
},
"required": [
Expand Down
4 changes: 4 additions & 0 deletions packages/common-all/src/constants/configs/publishing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -207,4 +207,8 @@ export const PUBLISHING: DendronConfigEntryCollection<DendronPublishingConfig> =
label: "Enable special formatting for task notes.",
desc: "Task notes will have checkboxes, owner information and more displayed on links leading to them. This applies both in preview and publishing.",
},
templateVersion: {
label: "Version of publishing template",
desc: "What version of the publishing template to use",
},
};
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ export type DendronPublishingConfig = {
cognitoUserPoolId?: string;
cognitoClientId?: string;
enablePrettyLinks: boolean;
templateVersion?: string;
};

export type CleanDendronPublishingConfig = DendronPublishingConfig &
Expand Down
86 changes: 57 additions & 29 deletions packages/dendron-cli/src/commands/publishCLICommand.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,29 +4,31 @@ import {
DendronError,
DendronSiteConfig,
error2PlainObject,
ErrorFactory,
getStage,
RespV3,
Stage,
} from "@dendronhq/common-all";
import { SiteUtils } from "@dendronhq/engine-server";
import { GitUtils } from "@dendronhq/common-server";
import { DConfig, SiteUtils } from "@dendronhq/engine-server";
import {
BuildOverrides,
NextjsExportConfig,
NextjsExportPod,
NextjsExportPodUtils,
BuildOverrides,
PublishTarget,
} from "@dendronhq/pods-core";
import fs from "fs-extra";
import _ from "lodash";
import ora from "ora";
import path from "path";
import prompts from "prompts";
import yargs from "yargs";
import { CLIUtils, SpinnerUtils } from "../utils/cli";
import { CLICommand } from "./base";
import { ExportPodCLICommand } from "./exportPod";
import { PodSource } from "./pod";
import { SetupEngineCLIOpts } from "./utils";
import prompts from "prompts";
import fs from "fs-extra";
import ora from "ora";
import { GitUtils } from "@dendronhq/common-server";

type CommandCLIOpts = {
cmd: PublishCommands;
Expand Down Expand Up @@ -323,29 +325,19 @@ export class PublishCLICommand extends CLICommand<CommandOpts, CommandOutput> {
nextPath,
spinner,
});

if (nextPathExists) {
try {
await this._updateNextTemplate({
nextPath,
spinner,
});
} catch (err) {
SpinnerUtils.renderAndContinue({
spinner,
text: `failed to update next NextJS template working copy (${err}); cloning fresh`,
});
await this._removeNextPath({
nextPath,
spinner,
});
await this._initialize({ nextPath, spinner });
}
} else {
await this._initialize({ nextPath, spinner });
this.print("Nextjs template already exists. Skipping initialization");
return {
error: ErrorFactory.createInvalidStateError({
message: "template exists",
}),
};
}

return { error: null };
return this._initialize({
nextPath,
spinner,
wsRoot,
});
}

async _isInitialized(opts: { wsRoot: string; spinner: ora.Ora }) {
Expand Down Expand Up @@ -414,14 +406,50 @@ export class PublishCLICommand extends CLICommand<CommandOpts, CommandOutput> {
});
}

async _initialize(opts: { nextPath: string; spinner: ora.Ora }) {
const { spinner } = opts;
/**
* Clone template
* If templateVersion is set in dendron.yml, clone at version
* Otherwise, get same version as engine
* @param opts
* @return: string, version of template
*/
async _initialize(opts: {
jonathanyeung marked this conversation as resolved.
Show resolved Hide resolved
nextPath: string;
spinner: ora.Ora;
wsRoot: string;
}): Promise<RespV3<{ templateVersion: string }>> {
const { spinner, wsRoot } = opts;
SpinnerUtils.renderAndContinue({
spinner,
text: "Initializing NextJS template.",
});
const config = DConfig.readConfigAndApplyLocalOverrideSync(opts.wsRoot);
await this._cloneTemplate(opts);

// get template version from config or get latest version
let templateVersion = NextjsExportPodUtils.templateVersion(config);

await NextjsExportPodUtils.switchToBranch({
version: templateVersion || NextjsExportPodUtils.LATEST_TEMPLATE_VERSION,
nextPath: opts.nextPath,
});

// if template version was latest, write current version as the template version
if (!templateVersion) {
const resp = NextjsExportPodUtils.getNextVersion(wsRoot);
if (resp.error) {
return resp;
}
templateVersion = resp.data;
}

await this._installDependencies(opts);

if (!NextjsExportPodUtils.templateVersion(config)) {
ConfigUtils.setPublishProp(config, "templateVersion", templateVersion);
await DConfig.writeConfig({ wsRoot, config });
}
return { data: { templateVersion }, error: undefined };
}

async _cloneTemplate(opts: { nextPath: string; spinner: ora.Ora }) {
Expand Down
6 changes: 6 additions & 0 deletions packages/dendron-next-server/data/dendron-yml.validator.json
Original file line number Diff line number Diff line change
Expand Up @@ -768,6 +768,9 @@
},
"apiEndpoint": {
"type": "string"
},
"templateHierarchy": {
"type": "string"
}
},
"required": [
Expand Down Expand Up @@ -1173,6 +1176,9 @@
},
"enablePrettyLinks": {
"type": "boolean"
},
"publishTemplateVersion": {
"type": "number"
}
},
"required": [
Expand Down
1 change: 1 addition & 0 deletions packages/engine-server/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,4 @@ export * from "./doctor";
export * from "./backup";
export * from "./backfillV2";
export * from "./cache";
export * from "./services";
1 change: 1 addition & 0 deletions packages/engine-server/src/services/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./version-provider";
7 changes: 7 additions & 0 deletions packages/engine-server/src/services/version-provider/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { NodeJSUtils } from "@dendronhq/common-server";

export class VersionProvider {
static engineVersion(): string {
return NodeJSUtils.getVersionFromPkg();
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {
ConfigUtils,
IntermediateDendronConfig,
RespV3,
URI,
} from "@dendronhq/common-all";
import {
Expand All @@ -9,6 +10,7 @@ import {
PublishCLICommandOpts,
PublishCommands,
} from "@dendronhq/dendron-cli";
import { DConfig } from "@dendronhq/engine-server";
import { NextjsExportPodUtils, PublishTarget } from "@dendronhq/pods-core";
import fs from "fs-extra";
import _ from "lodash";
Expand Down Expand Up @@ -47,18 +49,119 @@ describe("WHEN run `dendron publish init`", () => {
afterEach(() => {
sinon.restore();
});
test("THEN succeed", async () => {
await runEngineTestV5(
async ({ wsRoot }) => {
const cli = new PublishCLICommand();
const initStub = stub(cli, "init").resolves({ error: null });
await runPublishCmd({ cli, cmd, wsRoot });
expect(initStub.calledOnce).toBeTruthy();
},
{
expect,
}
);

const getData = (resp: RespV3<any>) => {
if (!_.isUndefined(resp.error)) {
throw Error("error is not undefined");
}
return resp.data;
};

describe("AND WHEN no templateVersion set", () => {
test("THEN clone with latest version", async () => {
await runEngineTestV5(
async ({ wsRoot }) => {
const cli = new PublishCLICommand();
const latestVersion = "0.97.0";
const stubClone = stub(cli, "_cloneTemplate").returns(
new Promise<void>((resolve) => {
resolve();
})
);
const stubSwitch = stub(
NextjsExportPodUtils,
"switchToBranch"
).resolves();
const stubGetNextVersion = stub(
NextjsExportPodUtils,
"getNextVersion"
).returns({ data: latestVersion });
const stubInstall = stub(cli, "_installDependencies").resolves();
const resp = await runPublishCmd({ cli, cmd, wsRoot });

// cloned
expect(stubClone.calledOn).toBeTruthy();
// switch to latest branch
expect(
stubSwitch.calledWith({
version: "tags/vlatest",
nextPath: path.join(wsRoot, ".next"),
})
).toBeTruthy();
// install dependencies
expect(stubInstall.calledOn).toBeTruthy();
// get next version checked
expect(stubGetNextVersion.calledOn).toBeTruthy();
// templateVersion set to latest
expect(getData(resp).templateVersion).toEqual(latestVersion);
// templateVersion written to config
const newConfig = DConfig.getOrCreate(wsRoot);
expect(NextjsExportPodUtils.templateVersion(newConfig)).toEqual(
latestVersion
);
},
{
expect,
}
);
});
});

describe("AND WHEN templateVersion set", () => {
const templateVersion = "0.95.0";
test("THEN clone with templateVersion", async () => {
await runEngineTestV5(
async ({ wsRoot }) => {
const cli = new PublishCLICommand();
const latestVersion = templateVersion;
const stubClone = stub(cli, "_cloneTemplate").resolves();
const stubSwitch = stub(
NextjsExportPodUtils,
"switchToBranch"
).resolves();
const stubInstall = stub(cli, "_installDependencies").resolves();
const resp = await runPublishCmd({ cli, cmd, wsRoot });

expect(stubClone.calledOn).toBeTruthy();
expect(
stubSwitch.calledWith({
version: latestVersion,
nextPath: path.join(wsRoot, ".next"),
})
).toBeTruthy();
expect(stubInstall.calledOn).toBeTruthy();
expect(getData(resp).templateVersion).toEqual(latestVersion);
// template version unchanged
const newConfig = DConfig.getOrCreate(wsRoot);
expect(NextjsExportPodUtils.templateVersion(newConfig)).toEqual(
templateVersion
);
},
{
expect,
modConfigCb: (config: IntermediateDendronConfig) => {
config.publishing!.templateVersion = templateVersion;
return config;
},
}
);
});
});

describe("AND WHEN template exists", () => {
test("THEN do not clone", async () => {
await runEngineTestV5(
async ({ wsRoot }) => {
const cli = new PublishCLICommand();
stub(cli, "_nextPathExists").resolves(true);
const resp = await runPublishCmd({ cli, cmd, wsRoot });
expect(resp.error.message).toEqual("template exists");
},
{
expect,
}
);
});
});
});

Expand Down Expand Up @@ -202,7 +305,9 @@ describe("WHEN run `dendron publish dev`", () => {
await runEngineTestV5(
async ({ wsRoot }) => {
const cli = new PublishCLICommand();
const initStub = stub(cli, "init").resolves({ error: null });
const initStub = stub(cli, "init").resolves({
data: { templateVersion: "" },
});
const buildStub = stub(cli, "build").resolves({ error: null });
const devStub = stub(cli, "dev").resolves({ error: null });
await runPublishCmd({ cli, cmd, wsRoot });
Expand Down Expand Up @@ -235,7 +340,9 @@ describe("WHEN run `dendron publish export`", () => {
fs.ensureFileSync(
path.join(wsRoot, ".next", "out", "canary-success")
);
const initStub = stub(cli, "init").resolves({ error: null });
const initStub = stub(cli, "init").resolves({
data: { templateVersion: "" },
});
const buildStub = stub(cli, "build").resolves({ error: null });
const exportStub = stub(cli, "export").resolves({} as any);
prompts.inject([true]);
Expand Down Expand Up @@ -278,7 +385,9 @@ describe("WHEN run `dendron publish export`", () => {
fs.ensureFileSync(
path.join(wsRoot, ".next", "out", "canary-success")
);
const initStub = stub(cli, "init").resolves({ error: null });
const initStub = stub(cli, "init").resolves({
data: { templateVersion: "" },
});
const buildStub = stub(cli, "build").resolves({ error: null });
const exportStub = stub(cli, "export").resolves({} as any);
prompts.inject([false]);
Expand Down
Loading