Skip to content

Commit

Permalink
feat: swa deploy
Browse files Browse the repository at this point in the history
  • Loading branch information
manekinekko committed Apr 4, 2022
1 parent 23d8a5c commit c7f6dc8
Show file tree
Hide file tree
Showing 4 changed files with 187 additions and 104 deletions.
67 changes: 50 additions & 17 deletions src/cli/commands/deploy.ts
Original file line number Diff line number Diff line change
@@ -1,46 +1,79 @@
import { spawn } from "child_process";
import { logger, registerProcessExit } from "../../core";
import { downloadClient } from "../../core/deploy-client";
import path from "path";
import { logger } from "../../core";
import { cleanUp, getDeployClientPath } from "../../core/deploy-client";

// read package version
const pkg = require(path.join(__dirname, "..", "..", "..", "package.json"));

export async function deploy(deployContext: string, options: SWACLIConfig) {
if (!options.appOutputLocation) {
logger.error("--app-output-location option is missing", true);
if (!options.outputLocation) {
logger.error("--output-location option is missing", true);
}

if (!options.apiOutputLocation) {
logger.error("--api-output-location option is missing", true);
if (!options.apiLocation) {
logger.error("--api-location option is missing", true);
}

if (!options.deploymentToken) {
logger.error("--deployment-token option is missing", true);
let deploymentToken = "";
if (options.deploymentToken) {
deploymentToken = options.deploymentToken;
logger.log("Deployment token provide via flag", "deploy");
} else if (process.env.SWA_CLI_DEPLOYMENT_TOKEN) {
deploymentToken = process.env.SWA_CLI_DEPLOYMENT_TOKEN;
logger.log("Deployment token found in env: SWA_CLI_DEPLOYMENT_TOKEN=<hidden>", "deploy");
}
// TODO: add support for Azure CLI
// TODO: add support for Service Principal
// TODO: check that platform.apiRuntime in staticwebapp.config.json is provided.
// This is required by the StaticSiteClient!

try {
const clientPath = await downloadClient();
const clientPath = await getDeployClientPath();
logger.log(`Deploying using ${clientPath}`, "deploy");

if (clientPath) {
const env = {
...process.env,
DEPLOYMENT_ACTION: "upload",
DEPLOYMENT_PROVIDER: `swa-cli-${pkg}`,
DEPLOYMENT_PROVIDER: `swa-cli-${pkg.version}`,
REPOSITORY_BASE: deployContext,
SKIP_APP_BUILD: "true",
SKIP_API_BUILD: "true",
DEPLOYMENT_TOKEN: options.deploymentToken,
APP_LOCATION: options.appOutputLocation,
API_LOCATION: options.apiOutputLocation,
DEPLOYMENT_TOKEN: deploymentToken,
APP_LOCATION: options.outputLocation,
API_LOCATION: options.apiLocation,
VERBOSE: options.verbose === "silly" ? "true" : "false",
};

const child = spawn(clientPath, [], {
stdio: [process.stdin, process.stdout, process.stderr, "pipe"],
env,
});

child.on("exit", (code) => {
process.exit(code as number);
child.stdout!.on("data", (data) => {
data
.toString()
.trim()
.split("\n")
.forEach((line: string) => {
logger.log(line.trim(), "deploy");
});
});

child.stderr!.on("data", (data) => {
logger.warn(data.toString(), "deploy");
});

child.on("error", (error) => {
logger.error(error.toString());
});

child.on("close", (code) => {
cleanUp();
if (code === 0) {
logger.log("Deployment completed successfully", "deploy");
} else {
logger.error(`Deployment failed with exit code ${code}`, true);
}
});
}
} catch (error) {
Expand Down
33 changes: 18 additions & 15 deletions src/cli/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,14 +50,19 @@ export async function run(argv?: string[]) {
.usage("<command> [options]")
.version(pkg.version, "-v, --version")

// SWA config
/////////////////////////////////////////////////////////////////////////////////
// SWA CLI common configuration options
/////////////////////////////////////////////////////////////////////////////////

.option("--verbose [prefix]", "enable verbose output. Values are: silly,info,log,silent", DEFAULT_CONFIG.verbose)
.addHelpText("after", "\nDocumentation:\n https://aka.ms/swa/cli-local-development\n")

.option("--config <path>", "Path to swa-cli.config.json file to use.", path.relative(process.cwd(), swaCliConfigFilename))
.option("--print-config", "Print all resolved options.", false);
.option("--config <path>", "Path to swa-cli.config.json file to use", path.relative(process.cwd(), swaCliConfigFilename))
.option("--print-config", "Print all resolved options", false);

/////////////////////////////////////////////////////////////////////////////////
// start command
/////////////////////////////////////////////////////////////////////////////////
program
.command("login")
.usage("<command> [options]")
Expand Down Expand Up @@ -106,8 +111,6 @@ export async function run(argv?: string[]) {
"set the directory where the staticwebapp.config.json file is located",
DEFAULT_CONFIG.swaConfigLocation
)

// CLI config
.option<number>("--api-port <apiPort>", "set the API backend port", parsePort, DEFAULT_CONFIG.apiPort)
.option("--host <host>", "set the cli host address", DEFAULT_CONFIG.host)
.option<number>("--port <port>", "set the cli port", parsePort, DEFAULT_CONFIG.port)
Expand All @@ -118,19 +121,16 @@ export async function run(argv?: string[]) {
.option("--ssl", "serve the app and API over HTTPS", DEFAULT_CONFIG.ssl)
.option("--ssl-cert <sslCertLocation>", "SSL certificate (.crt) to use for serving HTTPS", DEFAULT_CONFIG.sslCert)
.option("--ssl-key <sslKeyLocation>", "SSL key (.key) to use for serving HTTPS", DEFAULT_CONFIG.sslKey)

.option("--run <startupScript>", "run a command at startup", DEFAULT_CONFIG.run)
.option<number>(
"--devserver-timeout <devserverTimeout>",
"time to wait (in ms) for the dev server to start",
parseDevserverTimeout,
DEFAULT_CONFIG.devserverTimeout
)

.option("--open", "open the browser to the dev server", DEFAULT_CONFIG.open)
.option("--func-args <funcArgs>", "pass additional arguments to the func start command")

.action(async (context: string = `.${path.sep}`, parsedOptions: SWACLIConfig) => {
.action(async (context = DEFAULT_CONFIG.outputLocation as string, parsedOptions: SWACLIConfig) => {
let { options, fileOptions } = await processConfigurationFile(cli, context, parsedOptions);
await start(fileOptions.context ?? context, options);
})
Expand All @@ -156,14 +156,17 @@ Examples:
`
);

/////////////////////////////////////////////////////////////////////////////////
// deploy command
/////////////////////////////////////////////////////////////////////////////////
program
.command("deploy [context]")
.usage("[context] [options]")
.description("deploy the current project to Azure Static Web Apps")
.option("--app-output-location <app-dist-folder>", "the location for the static app built folder")
.option("--api-output-location <api-dist-folder>", "the location for the API built folder")
.option("--output-location <outputLocation>", "the location for the static app built folder")
.option("--api-location <apiLocation>", "the location for the API built folder")
.option("--deployment-token <secret>", "the secret toekn used to authenticate with the Static Web Apps")
.action(async (context: string = `.${path.sep}`, parsedOptions: SWACLIConfig) => {
.action(async (context = DEFAULT_CONFIG.outputLocation as string, parsedOptions: SWACLIConfig) => {
let { options, fileOptions } = await processConfigurationFile(cli, context, parsedOptions);
await deploy(fileOptions.context ?? context, options);
})
Expand All @@ -173,12 +176,12 @@ Examples:
Examples:
Deploy using a deployment token
swa deploy --app-output-location ./app/dist/ --api-output-location ./api/ --deployment-token <token>
swa deploy --output-location ./app/dist/ --api-location ./api/ --deployment-token <token>
Deploy without a deployment token (requires swa login)
swa deploy --app-output-location ./app/dist/ --api-output-location ./api/
swa deploy --output-location ./app/dist/ --api-location ./api/
Deploy using a configuation file
Deploy using swa-cli.config.json file
swa deploy myproject
swa deploy --config ./swa-cli.config.json myproject
`
Expand Down
Loading

0 comments on commit c7f6dc8

Please sign in to comment.