Skip to content

Commit

Permalink
feat: Introduce an opt-in "error" deprecation notification mode
Browse files Browse the repository at this point in the history
  • Loading branch information
medikoo committed Jun 21, 2021
1 parent 9e10cea commit c22a8b9
Show file tree
Hide file tree
Showing 7 changed files with 58 additions and 0 deletions.
15 changes: 15 additions & 0 deletions docs/deprecations.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,21 @@ disabledDeprecations:
- '*' # To disable all deprecation messages
```

## Notifications mode

By default deprecations are logged as warnings. If there's an intention to work with _deprecation_ free service, reporting mode can be switched so approached deprecation is reported with a thrown error.

Mode can be set via environment variable: `SLS_DEPRECATION_NOTIFICATION_MODE=error` or via top level service configuration setting:

```yaml
deprecationNotificationMode: error
```

Note:

- Configuration setting is ineffective for deprecations reported before service configuration is read.
- `SLS_DEPRECATION_DISABLE` env var and `disabledDeprecations` configuration setting remain respected, and no errors will be thrown for mentioned deprecation coodes.

<a name="CHANGE_OF_DEFAULT_RUNTIME_TO_NODEJS14X"><div>&nbsp;</div></a>

## Change of default runtime to `nodejs14.x`
Expand Down
1 change: 1 addition & 0 deletions docs/providers/aws/guide/serverless.yml.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ enableLocalInstallationFallback: false # If set to 'true', guarantees that it's
useDotenv: false # If set to 'true', environment variables will be automatically loaded from .env files
variablesResolutionMode: null # To crash on variable resolution errors (as coming from new resolver), set this value to "20210326"
unresolvedVariablesNotificationMode: warn # If set to 'error', references to variables that cannot be resolved will result in an error being thrown (applies to legacy resolver)
deprecationNotificationMode: warn # If set to 'error' any reported deprection will result in an error being thrown

disabledDeprecations: # Disable deprecation logs by their codes. Default is empty.
- DEP_CODE_1 # Deprecation code to disable
Expand Down
1 change: 1 addition & 0 deletions lib/classes/Service.js
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ class Service {

this.plugins = configurationInput.plugins;
this.disabledDeprecations = configurationInput.disabledDeprecations;
this.deprecationNotificationMode = configurationInput.deprecationNotificationMode;

// `package.path` is read by few core plugins at initialization
if (configurationInput.package) {
Expand Down
3 changes: 3 additions & 0 deletions lib/configSchema.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ const schema = {
required: [],
// User is free to add any properties for its own purpose
},
deprecationsNotificationMode: {
enum: ['error', 'warn'],
},
disabledDeprecations: {
anyOf: [
{ const: '*' },
Expand Down
17 changes: 17 additions & 0 deletions lib/utils/logDeprecation.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,13 @@

const chalk = require('chalk');
const weakMemoizee = require('memoizee/weak');
const _ = require('lodash');
const ServerlessError = require('../serverless-error');

const disabledCodesByEnv = extractCodes(process.env.SLS_DEPRECATION_DISABLE);

const notificationModeByEnv = process.env.SLS_DEPRECATION_NOTIFICATION_MODE;

const triggeredDeprecations = new Set();

function extractCodes(codesStr) {
Expand All @@ -24,6 +28,11 @@ const resolveDeprecatedByService = weakMemoizee((serviceConfig) => {
return new Set(disabledDeprecations);
});

const isErrorNotificationMode = (serviceConfig) => {
if (notificationModeByEnv) return notificationModeByEnv === 'error';
return _.get(serviceConfig, 'deprecationNotificationMode') === 'error';
};

function writeDeprecation(code, message) {
const prefix = 'Serverless: ';
const messageLines = message.split('\n');
Expand Down Expand Up @@ -53,13 +62,21 @@ module.exports = (code, message, { serviceConfig } = {}) => {
) {
return;
}

if (serviceConfig) {
const serviceDisabledCodes = resolveDeprecatedByService(serviceConfig);
if (serviceDisabledCodes.has(code) || serviceDisabledCodes.has('*')) {
return;
}
}

if (isErrorNotificationMode(serviceConfig)) {
throw new ServerlessError(
`${message}\n More Info: https://www.serverless.com/framework/docs/deprecations/#${code}`,
`REJECTED_DEPRECATION_${code}`
);
}

writeDeprecation(code, message);
} finally {
triggeredDeprecations.add(code);
Expand Down
1 change: 1 addition & 0 deletions scripts/serverless.js
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,7 @@ const processSpanPromise = (async () => {
// variable resolution choices
if (!ensureResolvedProperty('variablesResolutionMode')) return;
if (!ensureResolvedProperty('disabledDeprecations')) return;
if (!ensureResolvedProperty('deprecationNotificationMode')) return;

if (isPropertyResolved(variablesMeta, 'provider\0name')) {
providerName = resolveProviderName(configuration);
Expand Down
20 changes: 20 additions & 0 deletions test/unit/lib/utils/logDeprecation.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ const mockRequire = require('mock-require');
const overrideEnv = require('process-utils/override-env');
const overrideStdoutWrite = require('process-utils/override-stdout-write');
const runServerless = require('../../../utils/run-serverless');
const ServerlessError = require('../../../../lib/serverless-error');

describe('#logDeprecation()', () => {
let restoreEnv;
Expand Down Expand Up @@ -91,6 +92,25 @@ describe('#logDeprecation()', () => {
});
});

it('Should throw on deprecation if env.SLS_DEPRECATION_NOTIFICATION_MODE=error', () => {
process.env.SLS_DEPRECATION_NOTIFICATION_MODE = 'error';
logDeprecation = mockRequire.reRequire('../../../../lib/utils/logDeprecation');
expect(() => logDeprecation('CODE1', 'Start using deprecation log'))
.to.throw(ServerlessError)
.with.property('code', 'REJECTED_DEPRECATION_CODE1');
});

it('Should throw on deprecation if error notifications mode set in service config', () => {
logDeprecation = mockRequire.reRequire('../../../../lib/utils/logDeprecation');
expect(() =>
logDeprecation('CODE1', 'Start using deprecation log', {
serviceConfig: { deprecationNotificationMode: 'error' },
})
)
.to.throw(ServerlessError)
.with.property('code', 'REJECTED_DEPRECATION_CODE1');
});

it('Should not log deprecation twice', () => {
let stdoutData = '';
overrideStdoutWrite(
Expand Down

0 comments on commit c22a8b9

Please sign in to comment.