Skip to content

Commit 00f1be7

Browse files
Merge branch 'main' into 4.x
2 parents f2d7122 + b38b795 commit 00f1be7

5 files changed

Lines changed: 46 additions & 101 deletions

File tree

docs/guides/deprecations.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,20 @@ Note:
3030
- The `serverless.yml` setting is ineffective for deprecations reported before the configuration is read.
3131
- `SLS_DEPRECATION_DISABLE` and `disabledDeprecations` remain respected, and no errors will be thrown for mentioned deprecation codes.
3232

33+
<a name="STANDALONE_UPGRADE_COMMAND_DEPRECATED"><div>&nbsp;</div></a>
34+
35+
## Command `sls upgrade`
36+
37+
Deprecation code: `STANDALONE_UPGRADE_COMMAND_DEPRECATED`
38+
39+
Removal target: osls v4.0.0
40+
41+
The standalone `sls upgrade` command no longer updates osls and is scheduled for removal in osls v4.0.0. Use npm to upgrade osls instead:
42+
43+
```sh
44+
npm install -g osls@latest
45+
```
46+
3347
<a name="VARIABLES_RESOLUTION_MODE"><div>&nbsp;</div></a>
3448

3549
## Property `variablesResolutionMode`

lib/cli/commands-schema/no-service.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -143,12 +143,12 @@ commands.set('plugin search', {
143143
'in non Windows environment.';
144144

145145
commands.set('upgrade', {
146-
usage: 'Upgrade osls',
147-
isHidden,
146+
usage: 'Deprecated: upgrade osls',
147+
isHidden: true,
148148
noSupportNotice,
149149
options: {
150150
major: {
151-
usage: 'Enable upgrade to a new major release',
151+
usage: 'Deprecated compatibility option',
152152
type: 'boolean',
153153
},
154154
},

lib/plugins/standalone.js

Lines changed: 13 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,24 @@
11
'use strict';
22

3-
const fs = require('fs');
4-
const fsp = require('fs').promises;
5-
const os = require('os');
63
const path = require('path');
7-
const stream = require('stream');
8-
const { Readable } = require('stream');
9-
const { promisify } = require('util');
104
const { log, progress, style } = require('../utils/serverless-utils/log');
11-
const currentVersion = require('../../package').version;
125
const ServerlessError = require('../serverless-error');
136
const standaloneUtils = require('../utils/standalone');
14-
const safeMoveFile = require('../utils/fs/safe-move-file');
157
const { remove } = require('../utils/fs/remove');
168
const cliCommandsSchema = require('../cli/commands-schema');
179

18-
const pipeline = promisify(stream.pipeline);
19-
20-
const BINARY_TMP_PATH = path.resolve(os.tmpdir(), 'serverless-binary-tmp');
21-
2210
const BINARY_PATH = standaloneUtils.path;
2311
const mainProgress = progress.get('main');
12+
const upgradeCommandDeprecationMessage = [
13+
'The standalone `sls upgrade` command is deprecated and no longer updates osls.',
14+
'It is scheduled for removal in osls v4.0.0.',
15+
'',
16+
'Upgrade osls via npm instead:',
17+
'',
18+
' npm install -g osls@latest',
19+
'',
20+
'More info: https://github.com/oss-serverless/osls/blob/main/docs/guides/deprecations.md#STANDALONE_UPGRADE_COMMAND_DEPRECATED',
21+
].join('\n');
2422

2523
module.exports = class Standalone {
2624
constructor(serverless, cliOptions) {
@@ -43,58 +41,9 @@ module.exports = class Standalone {
4341
}
4442

4543
async upgrade() {
46-
mainProgress.notice('Resolving latest standalone version', { isMainEvent: true });
47-
const tagName = await standaloneUtils.resolveLatestTag();
48-
const latestVersion = tagName.slice(1);
49-
if (latestVersion === currentVersion) {
50-
log.notice();
51-
log.notice.skip(
52-
`Already at latest version ${style.aside(
53-
`(${Math.floor(
54-
(Date.now() - this.serverless.pluginManager.commandRunStartTime) / 1000
55-
)}s)`
56-
)}`
57-
);
58-
return;
59-
}
60-
const currentMajor = Number(currentVersion.split('.')[0]);
61-
const latestMajor = Number(latestVersion.split('.')[0]);
62-
if (latestMajor > currentMajor && !this.cliOptions.major) {
63-
throw new ServerlessError(
64-
[
65-
'Cannot upgrade to a new major release without introducing a breaking changes',
66-
'',
67-
'If you\'ve confirmed it\'s safe and want to upgrade, run "sls upgrade --major"',
68-
'',
69-
'Note: Service is safe to upgrade if no deprecations are logged during its deployment.',
70-
` Check https://github.com/serverless/serverless/releases/tag/v${latestMajor}.0.0 ` +
71-
'for list of all breaking changes',
72-
].join('\n'),
73-
'CANNOT_UPGRADE_MAJOR'
74-
);
75-
}
76-
mainProgress.notice('Downloading latest standalone version', { isMainEvent: true });
77-
const executableUrl = standaloneUtils.resolveUrl(tagName);
78-
const standaloneResponse = await fetch(executableUrl);
79-
if (!standaloneResponse.ok) {
80-
throw new ServerlessError(
81-
'Sorry unable to `upgrade` at this point ' +
82-
`(server rejected request with ${standaloneResponse.status})`,
83-
'UPGRADE_ERROR'
84-
);
85-
}
86-
await remove(BINARY_TMP_PATH);
87-
await pipeline(
88-
Readable.fromWeb(standaloneResponse.body),
89-
fs.createWriteStream(BINARY_TMP_PATH)
90-
);
91-
await safeMoveFile(BINARY_TMP_PATH, BINARY_PATH);
92-
await fsp.chmod(BINARY_PATH, 0o755);
93-
log.notice();
94-
log.notice.success(
95-
`Successfully upgraded to ${tagName} ${style.aside(
96-
`(${Math.floor((Date.now() - this.serverless.pluginManager.commandRunStartTime) / 1000)}s)`
97-
)}`
44+
throw new ServerlessError(
45+
upgradeCommandDeprecationMessage,
46+
'STANDALONE_UPGRADE_COMMAND_DEPRECATED'
9847
);
9948
}
10049

lib/serverless.js

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,9 +58,7 @@ class Serverless {
5858
'Cannot run a local osls installation with an outdated global version.',
5959
'Please upgrade via:',
6060
'',
61-
colors.bold(
62-
isStandaloneExecutable ? 'serverless upgrade --major' : 'npm install -g osls'
63-
),
61+
colors.bold('npm install -g osls@latest'),
6462
colors.gray('Note: The latest release can run any locally installed osls version.'),
6563
'',
6664
'Alternatively run locally installed version directly via:',

test/unit/lib/plugins/standalone.test.js

Lines changed: 15 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -10,28 +10,14 @@ const { expect } = require('chai');
1010

1111
const { remove } = require('../../../../lib/utils/fs/remove');
1212

13-
const binaryTmpPath = path.resolve(os.tmpdir(), 'serverless-binary-tmp');
14-
15-
const createFetchResponse = (contents) => ({
16-
ok: true,
17-
body: new ReadableStream({
18-
start(controller) {
19-
controller.enqueue(new TextEncoder().encode(contents));
20-
controller.close();
21-
},
22-
}),
23-
});
24-
25-
const loadStandalone = ({ binaryPath, removeStub, safeMoveFile } = {}) =>
13+
const loadStandalone = ({ binaryPath, removeStub } = {}) =>
2614
proxyquire('../../../../lib/plugins/standalone', {
2715
'../utils/standalone': {
2816
path: binaryPath,
29-
resolveLatestTag: sinon.stub().resolves('v999.0.0'),
30-
resolveUrl: sinon.stub().returns('https://example.com/serverless'),
17+
resolveLatestTag: sinon.stub().throws(new Error('Unexpected latest tag lookup')),
18+
resolveUrl: sinon.stub().throws(new Error('Unexpected download URL lookup')),
3119
},
3220
'../utils/fs/remove': { remove: removeStub || remove },
33-
'../utils/fs/safe-move-file':
34-
safeMoveFile || require('../../../../lib/utils/fs/safe-move-file'),
3521
});
3622

3723
describe('test/unit/lib/plugins/standalone.test.js', () => {
@@ -46,29 +32,27 @@ describe('test/unit/lib/plugins/standalone.test.js', () => {
4632
afterEach(async () => {
4733
globalThis.fetch = originalFetch;
4834
await remove(tmpDir);
49-
await remove(binaryTmpPath);
5035
});
5136

52-
it('removes a stale temporary binary before upgrade download', async () => {
37+
it('rejects upgrade because the command is deprecated', async () => {
5338
const binaryPath = path.join(tmpDir, 'install', 'serverless');
54-
const removedPaths = [];
55-
const removeStub = async (targetPath) => {
56-
removedPaths.push(targetPath);
57-
await remove(targetPath);
58-
};
59-
await fsp.writeFile(binaryTmpPath, 'stale');
60-
await fsp.mkdir(path.dirname(binaryPath), { recursive: true });
61-
globalThis.fetch = sinon.stub().resolves(createFetchResponse('new binary'));
62-
const Standalone = loadStandalone({ binaryPath, removeStub });
39+
globalThis.fetch = sinon.stub().throws(new Error('Unexpected download'));
40+
const Standalone = loadStandalone({ binaryPath });
6341
const standalone = new Standalone(
6442
{ pluginManager: { commandRunStartTime: Date.now() } },
6543
{ major: true }
6644
);
6745

68-
await standalone.upgrade();
46+
let error;
47+
try {
48+
await standalone.upgrade();
49+
} catch (caughtError) {
50+
error = caughtError;
51+
}
6952

70-
expect(removedPaths).to.include(binaryTmpPath);
71-
expect(await fsp.readFile(binaryPath, 'utf8')).to.equal('new binary');
53+
expect(error).to.have.property('code', 'STANDALONE_UPGRADE_COMMAND_DEPRECATED');
54+
expect(error.message).to.include('npm install -g osls@latest');
55+
expect(globalThis.fetch).to.not.have.been.called;
7256
});
7357

7458
it('recursively removes the standalone install directory on uninstall', async () => {

0 commit comments

Comments
 (0)