build-scripts/generateResources.ts (180 lines of code) (raw):

/*! * Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: MIT */ import * as fs from 'fs-extra' import JsonQuery from 'json-query' import * as path from 'path' import validator from 'validator' import axios from 'axios' import { buildTasks, releaseVersion, repoRoot, sourceTasks } from './scriptUtils' import isUUID = validator.isUUID import isAlphanumeric = validator.isAlphanumeric import isLength = validator.isLength const timeMessage = 'Generated resources' const taskJson = 'task.json' const taskLocJson = 'task.loc.json' const vssPath = path.join(repoRoot, 'vss-extension.json') const vssBuildPath = path.join(repoRoot, 'build', 'vss-extension.json') function findMatchingFiles(directory: string): string[] { return fs.readdirSync(directory) } // Downloads the latest known AWS regions file used by the various // AWS toolkits and constructs an object we can inject into each // task's region picker options. async function fetchLatestRegions(): Promise<string[]> { console.log('Fetching AWS regions') const endpointsFileUrl = 'https://aws-toolkit-endpoints.s3.amazonaws.com/endpoints.json' const availableRegions: any = {} try { const response = await axios.get(endpointsFileUrl) const allEndpoints = response.data for (const partition of allEndpoints.partitions) { const regionKeys = Object.keys(partition.regions) regionKeys.forEach((rk: string) => { availableRegions[rk] = `${partition.regions[rk].description} [${rk.toString()}]` }) } return availableRegions } catch (err) { console.error('Error fetching AWS regions:', err) throw err } } function validateTask(task: any) { if (!task.id || !isUUID(task.id)) { console.error(`Validation failure, id is a required guid for task:\n${task}`) process.exit(1) } if (!task.name || !isAlphanumeric(task.name)) { console.error(`name is a required alphanumeric string for task:\n${task}`) process.exit(1) } if (!task.friendlyName || !isLength(task.friendlyName, { min: 1, max: 40 })) { console.error(`friendlyName is a required string <= 40 chars for task:\n${task}`) process.exit(1) } if (!task.instanceNameFormat) { console.error(`instanceNameFormat is required for task:\n${task}`) process.exit(1) } } function generateTaskLoc(taskLoc: any, taskPath: string) { taskLoc.friendlyName = 'ms-resource:loc.friendlyName' taskLoc.helpMarkDown = 'ms-resource:loc.helpMarkDown' taskLoc.description = 'ms-resource:loc.description' taskLoc.instanceNameFormat = 'ms-resource:loc.instanceNameFormat' if (Object.hasOwnProperty.call(taskLoc, 'releaseNotes')) { taskLoc.releaseNotes = 'ms-resource:loc.releaseNotes' } if (Object.hasOwnProperty.call(taskLoc, 'groups')) { taskLoc.groups.forEach(function(group: any) { if (Object.hasOwnProperty.call(group, 'name')) { group.displayName = `ms-resource:loc.group.displayName.${group.name}` } }) } if (Object.hasOwnProperty.call(taskLoc, 'inputs')) { taskLoc.inputs.forEach(function(input: any) { if (Object.hasOwnProperty.call(input, 'name')) { input.label = `ms-resource:loc.input.label.${input.name}` if (Object.hasOwnProperty.call(input, 'helpMarkDown') && input.helpMarkDown) { input.helpMarkDown = `ms-resource:loc.input.help.${input.name}` } } }) } if (Object.hasOwnProperty.call(taskLoc, 'messages')) { Object.keys(taskLoc.messages).forEach(function(key) { taskLoc.messages[key] = `ms-resource:loc.messages.${key}` }) } fs.writeFileSync(path.join(buildTasks, taskPath, taskLocJson), JSON.stringify(taskLoc, undefined, 2)) } function addVersionToTask(task: any, versionInfo: string) { const info = versionInfo.split('.') task.version = { Major: info[0], Minor: info[1], Patch: info[2] } } function addAWSRegionsToTask(task: any, knownRegions: string[]) { const regionNameInput = JsonQuery('inputs[name=regionName]', { data: task }).value regionNameInput.options = knownRegions } function writeTask(task: any, taskPath: string): void { fs.writeFileSync(path.join(buildTasks, taskPath, taskJson), JSON.stringify(task, undefined, 2)) } function createResjson(task: any, taskPath: string): void { const resources: any = {} if (Object.hasOwnProperty.call(task, 'friendlyName')) { resources['loc.friendlyName'] = task.friendlyName } if (Object.hasOwnProperty.call(task, 'helpMarkDown')) { resources['loc.helpMarkDown'] = task.helpMarkDown } if (Object.hasOwnProperty.call(task, 'description')) { resources['loc.description'] = task.description } if (Object.hasOwnProperty.call(task, 'instanceNameFormat')) { resources['loc.instanceNameFormat'] = task.instanceNameFormat } if (Object.hasOwnProperty.call(task, 'releaseNotes')) { resources['loc.releaseNotes'] = task.releaseNotes } if (Object.hasOwnProperty.call(task, 'groups')) { task.groups.forEach(function(group: any) { if (Object.hasOwnProperty.call(group, 'name')) { resources[`loc.group.displayName.${group.name}`] = group.displayName } }) } if (Object.hasOwnProperty.call(task, 'inputs')) { task.inputs.forEach(function(input: any) { if (Object.hasOwnProperty.call(input, 'name')) { resources[`loc.input.label.${input.name}`] = input.label if (Object.hasOwnProperty.call(input, 'helpMarkDown') && input.helpMarkDown) { resources[`loc.input.help.${input.name}`] = input.helpMarkDown } } }) } if (Object.hasOwnProperty.call(task, 'messages')) { Object.keys(task.messages).forEach(function(key) { resources[`loc.messages.${key}`] = task.messages[key] }) } const resjsonPath = path.join(buildTasks, taskPath, 'Strings', 'resources.resjson', 'en-US', 'resources.resjson') fs.mkdirpSync(path.dirname(resjsonPath)) fs.writeFileSync(resjsonPath, JSON.stringify(resources, undefined, 2)) } function generateTaskResources(taskPath: string, knownRegions: string[], versionInfo: string): void { const taskJsonPath = path.join(sourceTasks, taskPath, taskJson) try { fs.accessSync(taskJsonPath) } catch (e) { return } const task = JSON.parse(fs.readFileSync(taskJsonPath, 'utf-8')) validateTask(task) addVersionToTask(task, versionInfo) addAWSRegionsToTask(task, knownRegions) writeTask(task, taskPath) createResjson(task, taskPath) generateTaskLoc(task, taskPath) } function addVersionToVssExtension(versionInfo: string): void { const vss = JSON.parse(fs.readFileSync(vssPath, 'utf-8')) vss.version = versionInfo fs.writeFileSync(vssBuildPath, JSON.stringify(vss, undefined, 2)) } ;(async () => { try { console.time(timeMessage) const knownRegions = await fetchLatestRegions() findMatchingFiles(sourceTasks).forEach(path => { generateTaskResources(path, knownRegions, releaseVersion) }) addVersionToVssExtension(releaseVersion) } catch (err) { console.error('Error generating resources:', err) throw err } console.timeEnd(timeMessage) })()