Skip to content

Commit 693ecd0

Browse files
committed
Re-create 1.3.0
1 parent 9d90398 commit 693ecd0

File tree

13 files changed

+172
-50
lines changed

13 files changed

+172
-50
lines changed

components/framework/configuration.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ const configSchema = {
55
properties: {
66
path: { type: 'string' },
77
region: { type: 'string' },
8+
config: { type: 'string' },
89
params: {
910
type: 'object',
1011
additionalProperties: true,

components/framework/index.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,14 @@ class ServerlessFramework {
116116
this.context.successProgress('removed');
117117
}
118118

119+
async package() {
120+
this.context.startProgress('packaging');
121+
122+
await this.exec('serverless', ['package']);
123+
124+
this.context.successProgress('packaged');
125+
}
126+
119127
async info() {
120128
const { stdout: infoOutput } = await this.exec('serverless', ['info']);
121129
this.context.writeText(infoOutput);

package.json

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@serverless/compose",
3-
"version": "1.2.0",
3+
"version": "1.3.0",
44
"description": "Deploy and orchestrate multiple Serverless Framework services in monorepositories.",
55
"main": "src/index.js",
66
"repository": "serverless/compose",
@@ -19,14 +19,14 @@
1919
"author": "serverless.com",
2020
"license": "MIT",
2121
"dependencies": {
22-
"@aws-sdk/client-cloudformation": "^3.100.0",
23-
"@aws-sdk/client-s3": "^3.100.0",
24-
"@serverless-components/utils-aws": "^0.0.1",
25-
"@serverless/utils": "^6.6.0",
22+
"@aws-sdk/client-cloudformation": "^3.137.0",
23+
"@aws-sdk/client-s3": "^3.137.0",
24+
"@serverless-components/utils-aws": "^0.1.0",
25+
"@serverless/utils": "^6.7.0",
2626
"ajv": "^8.11.0",
2727
"chalk": "^4.1.2",
2828
"child-process-ext": "^2.1.1",
29-
"ci-info": "^3.3.1",
29+
"ci-info": "^3.3.2",
3030
"cli-cursor": "^3",
3131
"cross-spawn": "^7.0.3",
3232
"fs-extra": "^10.1.0",
@@ -38,6 +38,7 @@
3838
"js-yaml": "^4.1.0",
3939
"minimist": "^1.2.6",
4040
"node-fetch": "^2.6.7",
41+
"p-limit": "^3.1.0",
4142
"path2": "^0.1.0",
4243
"prettyoutput": "^1.2.0",
4344
"promise-queue": "^2.2.5",
@@ -46,7 +47,7 @@
4647
"signal-exit": "^3.0.7",
4748
"strip-ansi": "^6.0.1",
4849
"traverse": "^0.6.6",
49-
"type": "^2.6.0",
50+
"type": "^2.6.1",
5051
"uuid": "^8.3.2"
5152
},
5253
"devDependencies": {
@@ -56,12 +57,12 @@
5657
"aws-sdk-client-mock": "^0.6.2",
5758
"chai": "^4.3.6",
5859
"chai-as-promised": "^7.1.1",
59-
"eslint": "^8.16.0",
60+
"eslint": "^8.20.0",
6061
"eslint-plugin-import": "^2.26.0",
6162
"git-list-updated": "^1.2.1",
6263
"mocha": "^9.2.2",
63-
"pkg": "^5.7.0",
64-
"prettier": "^2.6.2",
64+
"pkg": "^5.8.0",
65+
"prettier": "^2.7.1",
6566
"proxyquire": "^2.1.3",
6667
"sinon": "^13.0.2",
6768
"sinon-chai": "^3.7.0"

src/ComponentsService.js

Lines changed: 46 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ const { resolve } = require('path');
44
const { isEmpty, path } = require('ramda');
55
const { Graph, alg } = require('graphlib');
66
const traverse = require('traverse');
7+
const pLimit = require('p-limit');
78
const ServerlessError = require('./serverless-error');
89
const utils = require('./utils');
910
const { loadComponent } = require('./load');
@@ -223,10 +224,12 @@ class ComponentsService {
223224
/**
224225
* @param {import('./Context')} context
225226
* @param configuration
227+
* @param options
226228
*/
227-
constructor(context, configuration) {
229+
constructor(context, configuration, options) {
228230
this.context = context;
229231
this.configuration = configuration;
232+
this.options = options;
230233

231234
// Variables that will be populated during init
232235
this.allComponents = null;
@@ -304,6 +307,13 @@ class ComponentsService {
304307
});
305308
}
306309

310+
async package(options) {
311+
this.context.output.log();
312+
this.context.output.log(`Packaging for stage ${this.context.stage}`);
313+
314+
await this.invokeComponentsInParallel('package', options);
315+
}
316+
307317
async logs(options) {
308318
await this.invokeComponentsInParallel('logs', options);
309319
}
@@ -330,16 +340,16 @@ class ComponentsService {
330340
}
331341

332342
async invokeGlobalCommand(command, options) {
333-
const globalCommands = ['deploy', 'remove', 'info', 'logs', 'outputs', 'refresh-outputs'];
343+
const globalCommands = [
344+
'deploy',
345+
'remove',
346+
'info',
347+
'logs',
348+
'outputs',
349+
'refresh-outputs',
350+
'package',
351+
];
334352
// Specific error messages for popular Framework commands
335-
if (command === 'package') {
336-
throw new ServerlessError(
337-
`"package" is not a global command in Serverless Framework Compose.\nAvailable global commands: ${globalCommands.join(
338-
', '
339-
)}.\nYou can package each Serverless Framework service by running "serverless <service-name>:${command}".`,
340-
'COMMAND_NOT_FOUND'
341-
);
342-
}
343353
if (command === 'invoke') {
344354
throw new ServerlessError(
345355
`"invoke" is not a global command in Serverless Framework Compose.\nAvailable global commands: ${globalCommands.join(
@@ -391,7 +401,7 @@ class ComponentsService {
391401
}
392402
this.context.logVerbose(`Invoking "${command}" on service "${componentName}"`);
393403

394-
const isDefaultCommand = ['deploy', 'remove', 'logs', 'info'].includes(command);
404+
const isDefaultCommand = ['deploy', 'remove', 'logs', 'info', 'package'].includes(command);
395405

396406
if (isDefaultCommand) {
397407
// Default command defined for all components (deploy, logs, dev, etc.)
@@ -440,21 +450,29 @@ class ComponentsService {
440450
await this.instantiateComponents();
441451

442452
this.context.logVerbose(`Executing "${method}" across all services in parallel`);
443-
const promises = Object.entries(this.allComponents).map(async ([id, { instance }]) => {
444-
if (typeof instance[method] !== 'function') return;
445-
try {
446-
await instance[method](options);
447-
this.context.componentCommandsOutcomes[id] = 'success';
448-
} catch (e) {
449-
// If the component has an ongoing progress, we automatically set it to "error"
450-
if (this.context.progresses.exists(id)) {
451-
this.context.progresses.error(id, e);
452-
} else {
453-
this.context.output.error(formatError(e), [id]);
453+
const limit = pLimit(options['max-concurrency'] || Infinity);
454+
455+
const promises = [];
456+
457+
for (const [id, { instance }] of Object.entries(this.allComponents)) {
458+
const fn = async () => {
459+
if (typeof instance[method] !== 'function') return;
460+
try {
461+
await instance[method](options);
462+
this.context.componentCommandsOutcomes[id] = 'success';
463+
} catch (e) {
464+
// If the component has an ongoing progress, we automatically set it to "error"
465+
if (this.context.progresses.exists(id)) {
466+
this.context.progresses.error(id, e);
467+
} else {
468+
this.context.output.error(formatError(e), [id]);
469+
}
470+
this.context.componentCommandsOutcomes[id] = 'failure';
454471
}
455-
this.context.componentCommandsOutcomes[id] = 'failure';
456-
}
457-
});
472+
};
473+
474+
promises.push(limit(fn));
475+
}
458476

459477
await Promise.all(promises);
460478
}
@@ -476,6 +494,8 @@ class ComponentsService {
476494
return;
477495
}
478496

497+
const limit = pLimit(this.options['max-concurrency'] || Infinity);
498+
479499
/** @type {Promise<boolean>[]} */
480500
const promises = [];
481501

@@ -519,7 +539,7 @@ class ComponentsService {
519539
}
520540
};
521541

522-
promises.push(fn());
542+
promises.push(limit(fn));
523543
}
524544

525545
const results = await Promise.all(promises);

src/cli/Progresses.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,7 @@ class Progresses {
245245
}
246246

247247
if (this.footerText) {
248-
output += `\n${this.footerText.trim()}`;
248+
output += `\n${this.footerText.trim()}\r`;
249249
}
250250

251251
output = this.wrapMultilineText(output);

src/configuration/resolve-variables.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ const resolveConfigurationVariables = async (
1313
unrecognizedVariableSources = new Set()
1414
) => {
1515
const regex = /\${(\w*:[\w\d.-]+)}/g;
16-
const slsStageRegex = /\${sls:stage}/g;
17-
const envRegex = /\${env:(\w*[\w.-_]+)}/g;
16+
const slsStageRegex = /\${sls:stage}/;
17+
const envRegex = /\${env:(\w*[\w.-_]+)}/;
1818

1919
let variableResolved = false;
2020
const resolvedConfiguration = traverse(configuration).forEach(function (value) {

src/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ const runComponents = async () => {
125125
validateOptions(options, method);
126126

127127
try {
128-
const componentsService = new ComponentsService(context, configuration);
128+
const componentsService = new ComponentsService(context, configuration, options);
129129
await componentsService.init();
130130

131131
// Additionally, we're raising the listener default limit by 1 for each component - we might revisit it in the future

src/render-help.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,12 @@ module.exports = async () => {
5555
output.writeText(colors.gray('Global options'));
5656
output.writeText(formatLine('--verbose', 'Enable verbose logs'));
5757
output.writeText(formatLine('--stage', 'Stage of the service'));
58+
output.writeText(
59+
formatLine(
60+
'--max-concurrency',
61+
'Specify the maximum number of concurrently running service commands'
62+
)
63+
);
5864
output.writeText();
5965
output.writeText(colors.gray('Commands'));
6066

src/utils/telemetry/generate-payload.js

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@ module.exports = ({
7171

7272
const commandType = componentName ? 'single' : 'global';
7373

74+
const stage = (options && options.stage) || 'dev';
75+
7476
const payload = {
7577
command,
7678
commandType,
@@ -81,6 +83,7 @@ module.exports = ({
8183
commandOptionNames: options ? Object.keys(options).filter((key) => key !== '_') : [],
8284
frameworkLocalUserId: userConfig.get('frameworkId'),
8385
interruptSignal,
86+
stage,
8487
timestamp: Date.now(),
8588
timezone,
8689
versions: usedVersions,
@@ -120,7 +123,7 @@ module.exports = ({
120123
return serviceDefinition.dependsOn.length;
121124
})();
122125
return {
123-
type: serviceDefinition.type || 'serverless-framework',
126+
type: serviceDefinition.component || 'serverless-framework',
124127
dependsOnCount,
125128
paramsCount: Object.values(serviceDefinition.params || {}).length,
126129
};
@@ -132,10 +135,10 @@ module.exports = ({
132135
if (!configuration.services[componentName]) {
133136
return ['unknown'];
134137
}
135-
return [configuration.services[componentName].type || 'serverless-framework'];
138+
return [configuration.services[componentName].component || 'serverless-framework'];
136139
}
137140
return Object.values(configuration.services).map(
138-
(serviceDefinition) => serviceDefinition.type || 'serverless-framework'
141+
(serviceDefinition) => serviceDefinition.component || 'serverless-framework'
139142
);
140143
})();
141144

src/validate-options.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ function validateCliOptions(options, method) {
1717
});
1818

1919
// Globally recognized options for global Compose methods
20-
const supportedOptions = new Set(['verbose', 'stage']);
20+
const supportedOptions = new Set(['verbose', 'stage', 'max-concurrency']);
2121
// We only validate methods that are explicitly recognized by Compose (excluding pass-through methods for Framework)
2222

2323
const recognizedMethods = new Set([
@@ -27,6 +27,7 @@ function validateCliOptions(options, method) {
2727
'logs',
2828
'outputs',
2929
'refresh-outputs',
30+
'package',
3031
]);
3132

3233
if (!recognizedMethods.has(method)) return;

0 commit comments

Comments
 (0)