UNPKG

@azure/static-web-apps-cli

Version:
129 lines 6.82 kB
import fs from "node:fs"; import path from "node:path"; import YAML from "yaml"; import { DEFAULT_CONFIG } from "../../config.js"; import { logger } from "./logger.js"; import { isHttpUrl } from "./net.js"; import { validateUserWorkflowConfig } from "./user-config.js"; /** * Read and parse the project workflow configuration (if available). * @param userWorkflowConfig An object containing GithubActionWorkflow configuration used to override the project workflow config (if available). * @returns The project workflow configuraiton. */ export function readWorkflowFile({ userWorkflowConfig } = {}) { let isAppDevServer = false; let isApiDevServer = false; logger.silly(`Trying to read workflow config with values:`); logger.silly(userWorkflowConfig); if (userWorkflowConfig) { // is dev servers? Skip reading workflow file isAppDevServer = isHttpUrl(userWorkflowConfig?.outputLocation); isApiDevServer = isHttpUrl(userWorkflowConfig?.apiLocation); if (isAppDevServer && isApiDevServer) { logger.silly(`Detected dev server configuration`); return userWorkflowConfig; } } const githubActionFolder = path.resolve(userWorkflowConfig?.appLocation || process.cwd(), ".github/workflows/"); // does the config folder exist? if (fs.existsSync(githubActionFolder) === false) { logger.silly(`No workflow config folder found at ${githubActionFolder}`); // no github actions folder found return userWorkflowConfig && validateUserWorkflowConfig(userWorkflowConfig); } // find the SWA GitHub action file // TODO: handle multiple workflow files (see #32) let githubActionFile = fs .readdirSync(githubActionFolder) .filter((file) => file.includes("azure-static-web-apps") && file.endsWith(".yml")) .pop(); if (!githubActionFile) { logger.silly(`No SWA workflow config entry found under ${githubActionFolder}. Skipping`); // no SWA workflow file found return userWorkflowConfig && validateUserWorkflowConfig(userWorkflowConfig); } githubActionFile = path.resolve(githubActionFolder, githubActionFile); // does the config file exist? if (fs.existsSync(githubActionFile) === false) { logger.silly(`No workflow config file found at ${path.resolve(githubActionFile)}. Skipping`); // no SWA workflow file found return userWorkflowConfig && validateUserWorkflowConfig(userWorkflowConfig); } logger.silly(`Found a SWA workflow file: ${githubActionFile}`); let githubActionContent = fs.readFileSync(githubActionFile, "utf8"); if (typeof githubActionContent !== "string") { throw Error("TypeError: GitHub action file content should be a string"); } // MOTE: the YAML library will parse and return properties as sanke_case // we will convert those properties to camelCase at the end of the function const swaYaml = YAML.parse(githubActionContent); if (!swaYaml) { throw Error(`could not parse the SWA workflow file "${githubActionFile}".`); } if (!swaYaml.jobs) { throw Error(`missing property "jobs" in the SWA workflow file "${githubActionFile}".`); } if (!swaYaml.jobs.build_and_deploy_job) { throw Error(`missing property "jobs.build_and_deploy_job" in the SWA workflow file "${githubActionFile}".`); } if (!swaYaml.jobs.build_and_deploy_job.steps) { throw Error(`missing property "jobs.build_and_deploy_job.steps" in the SWA workflow file "${githubActionFile}".`); } // hacking this to have an `any` on the type in .find, mainly because a typescript definition for the YAML file is painful... const swaBuildConfig = swaYaml.jobs.build_and_deploy_job.steps.find((step) => step.uses && step.uses.includes("static-web-apps-deploy")); if (!swaBuildConfig) { throw Error(`invalid property "jobs.build_and_deploy_job.steps[]" in the SWA workflow file "${githubActionFile}".`); } if (!swaBuildConfig.with) { throw Error(`missing property "jobs.build_and_deploy_job.steps[].with" in the SWA workflow file "${githubActionFile}".`); } // extract the user's config and set defaults let { app_build_command = userWorkflowConfig?.appBuildCommand || DEFAULT_CONFIG.appBuildCommand, api_build_command = userWorkflowConfig?.apiBuildCommand || DEFAULT_CONFIG.apiBuildCommand, app_location = userWorkflowConfig?.appLocation || DEFAULT_CONFIG.appLocation, output_location = userWorkflowConfig?.outputLocation || DEFAULT_CONFIG.outputLocation, api_location = userWorkflowConfig?.apiLocation || DEFAULT_CONFIG.apiLocation, data_api_location = userWorkflowConfig?.dataApiLocation || DEFAULT_CONFIG.dataApiLocation, } = swaBuildConfig.with; logger.silly({ app_build_command, api_build_command, app_location, output_location, api_location, data_api_location, }); // the following locations (extracted from the config) should be under the user's project folder: // - app_location // - api_location // - output_location // - data_api_location app_location = path.normalize(path.join(process.cwd(), app_location)); if (typeof api_location !== "undefined") { api_location = path.normalize(path.join(process.cwd(), api_location || path.sep)); } output_location = path.normalize(output_location); output_location = path.join(app_location, output_location); if (typeof data_api_location !== "undefined") { data_api_location = path.normalize(path.join(process.cwd(), data_api_location || path.sep)); } // override SWA config with user's config (if provided): // if the user provides different app location, app artifact location or api location, use that information if (userWorkflowConfig) { userWorkflowConfig = validateUserWorkflowConfig(userWorkflowConfig); app_location = userWorkflowConfig?.appLocation; output_location = userWorkflowConfig?.outputLocation; api_location = userWorkflowConfig?.apiLocation; data_api_location = userWorkflowConfig?.dataApiLocation; } const files = isAppDevServer && isApiDevServer ? undefined : [githubActionFile]; // convert variable names to camelCase // instead of snake_case const config = { appBuildCommand: isAppDevServer ? undefined : app_build_command, apiBuildCommand: isApiDevServer ? undefined : api_build_command, appLocation: app_location, apiLocation: api_location, outputLocation: output_location, dataApiLocation: data_api_location, files, }; logger.silly(`Workflow configuration:`); logger.silly({ config }); return config; } //# sourceMappingURL=workflow-config.js.map