Skip to content

Commit

Permalink
Support site snapshot upload (#1049)
Browse files Browse the repository at this point in the history
  • Loading branch information
tzyl authored Dec 11, 2024
1 parent cddc196 commit 2ffa338
Show file tree
Hide file tree
Showing 6 changed files with 145 additions and 12 deletions.
5 changes: 5 additions & 0 deletions .changeset/brave-toes-work.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@osdk/cli": patch
---

Support site snapshot upload
2 changes: 2 additions & 0 deletions packages/cli/src/commands/site/deploy/SiteDeployArgs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,6 @@ export interface SiteDeployArgs extends CommonSiteArgs {
uploadOnly: boolean;
autoVersion?: AutoVersionConfigType;
gitTagPrefix?: string;
snapshot: boolean;
snapshotId?: string;
}
27 changes: 27 additions & 0 deletions packages/cli/src/commands/site/deploy/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,17 @@ const command: CommandModule<
? { default: gitTagPrefix }
: {},
},
snapshot: {
type: "boolean",
description:
"Upload a snapshot version only with automatic retention",
default: false,
},
snapshotId: {
type: "string",
description:
"Optional id to associate with snapshot version as an alias",
},
})
.group(
["directory", "version", "uploadOnly"],
Expand All @@ -87,6 +98,10 @@ const command: CommandModule<
["autoVersion", "gitTagPrefix"],
"Auto Version Options",
)
.group(
["snapshot", "snapshotId"],
"Snapshot Options",
)
.check((args) => {
// This is required because we can't use demandOption with conflicts. conflicts protects us against the case where both are provided.
// So this case is for when nothing is provided.
Expand Down Expand Up @@ -120,6 +135,18 @@ const command: CommandModule<
);
}

if (args.uploadOnly && args.snapshot) {
throw new YargsCheckError(
`--uploadOnly and --snapshot cannot be enabled together`,
);
}

if (args.snapshotId != null && !args.snapshot) {
throw new YargsCheckError(
"--snapshotId is only supported when --snapshot is enabled",
);
}

return true;
}).middleware((args) =>
logDeployCommandConfigFileOverride(
Expand Down
73 changes: 61 additions & 12 deletions packages/cli/src/commands/site/deploy/siteDeployCommand.mts
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,17 @@ import * as fs from "node:fs";
import path from "node:path";
import { Readable } from "node:stream";
import prettyBytes from "pretty-bytes";
import type { InternalClientContext } from "../../../net/internalClientContext.mjs";
import type { ThirdPartyAppRid } from "../../../net/ThirdPartyAppRid.js";
import { autoVersion as findAutoVersion } from "../../../util/autoVersion.js";
import type { AutoVersionConfig } from "../../../util/config.js";
import { loadToken } from "../../../util/token.js";
import type { SiteDeployArgs } from "./SiteDeployArgs.js";

interface SiteDeployInternalArgs
extends Omit<SiteDeployArgs, "version" | "autoVersion">
extends Omit<SiteDeployArgs, "version" | "autoVersion" | "gitTagPrefix">
{
selectedVersion: string | AutoVersionConfig;
directory: string;
uploadOnly: boolean;
}

export default async function siteDeployCommand(
Expand All @@ -43,6 +43,8 @@ export default async function siteDeployCommand(
application,
foundryUrl,
uploadOnly,
snapshot,
snapshotId,
directory,
token,
tokenFile,
Expand Down Expand Up @@ -75,17 +77,24 @@ export default async function siteDeployCommand(
const archive = archiver("zip").directory(directory, false);
logArchiveStats(archive);

consola.start("Uploading site files");
await Promise.all([
thirdPartyApplications.uploadVersion(
if (snapshot) {
await uploadSnapshot(
clientCtx,
application,
siteVersion,
Readable.toWeb(archive) as ReadableStream<any>, // This cast is because the dom fetch doesn't align type wise with streams
),
archive.finalize(),
]);
consola.success("Upload complete");
snapshotId ?? "",
archive,
);
consola.info("Snapshot mode enabled, skipping deployment");
return;
}

await upload(
clientCtx,
application,
siteVersion,
archive,
);

if (!uploadOnly) {
const website = await thirdPartyApplications.deployWebsite(
Expand All @@ -107,7 +116,7 @@ export default async function siteDeployCommand(
application,
);
const domain = website?.subdomains[0];
consola.debug("Upload only mode enabled, skipping deployment");
consola.info("Upload only mode enabled, skipping deployment");
if (domain != null) {
logSiteLink(
"Preview link:",
Expand All @@ -117,6 +126,46 @@ export default async function siteDeployCommand(
}
}

async function uploadSnapshot(
clientCtx: InternalClientContext,
application: ThirdPartyAppRid,
siteVersion: string,
snapshotId: string,
archive: archiver.Archiver,
): Promise<void> {
consola.start("Uploading snapshot site files");
await Promise.all([
thirdPartyApplications.uploadSnapshotVersion(
clientCtx,
application,
siteVersion,
snapshotId,
Readable.toWeb(archive) as ReadableStream<any>, // This cast is because the dom fetch doesn't align type wise with streams
),
archive.finalize(),
]);
consola.success("Snapshot upload complete");
}

async function upload(
clientCtx: InternalClientContext,
application: ThirdPartyAppRid,
siteVersion: string,
archive: archiver.Archiver,
): Promise<void> {
consola.start("Uploading site files");
await Promise.all([
thirdPartyApplications.uploadVersion(
clientCtx,
application,
siteVersion,
Readable.toWeb(archive) as ReadableStream<any>, // This cast is because the dom fetch doesn't align type wise with streams
),
archive.finalize(),
]);
consola.success("Upload complete");
}

function logArchiveStats(archive: archiver.Archiver): void {
let archiveStats = { fileCount: 0, bytes: 0 };
archive.on("progress", (progress) => {
Expand Down
1 change: 1 addition & 0 deletions packages/cli/src/net/third-party-applications/index.mts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export { getWebsite } from "./getWebsite.mjs";
export { listVersions } from "./listVersions.mjs";
export type { ListVersionsResponse } from "./ListVersionsResponse.mjs";
export { undeployWebsite } from "./undeployWebsite.mjs";
export { uploadSnapshotVersion } from "./uploadSnapshotVersion.mjs";
export { uploadVersion } from "./uploadVersion.mjs";
export type { Version } from "./Version.mjs";
export type { Website } from "./Website.mjs";
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* Copyright 2024 Palantir Technologies, Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import { createFetch } from "../createFetch.mjs";
import type { InternalClientContext } from "../internalClientContext.mjs";
import type { ThirdPartyAppRid } from "../ThirdPartyAppRid.js";
import type { Version } from "./Version.mjs";

export async function uploadSnapshotVersion(
ctx: InternalClientContext,
thirdPartyAppRid: ThirdPartyAppRid,
version: string,
snapshotId: string,
zipFile: ReadableStream | Blob | BufferSource,
): Promise<Version> {
const fetch = createFetch(ctx.tokenProvider);
const url =
`${ctx.foundryUrl}/api/v2/thirdPartyApplications/${thirdPartyAppRid}/website/versions/uploadSnapshot?version=${version}&preview=true${
snapshotId !== ""
? `&snapshotIdentifier=${snapshotId}`
: ""
}`;

const result = await fetch(
url,
{
method: "POST",
body: zipFile,
headers: {
"Content-Type": "application/octet-stream",
},
duplex: "half", // Node hates me
} satisfies RequestInit & { duplex: "half" } as any,
);
return result.json();
}

0 comments on commit 2ffa338

Please sign in to comment.