Skip to content

Commit

Permalink
Merge branch 'master' into add-deprecation-policy
Browse files Browse the repository at this point in the history
  • Loading branch information
mtrezza committed Mar 30, 2021
2 parents 2d998fb + ba32dae commit f502c45
Show file tree
Hide file tree
Showing 8 changed files with 135 additions and 5 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ jobs:
MONGODB_VERSION: 4.4.4
MONGODB_TOPOLOGY: standalone
MONGODB_STORAGE_ENGINE: wiredTiger
NODE_VERSION: 12.21.0
NODE_VERSION: 12.22.0
- name: Node 15
MONGODB_VERSION: 4.4.4
MONGODB_TOPOLOGY: standalone
Expand Down
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,8 @@ ___
- LDAP: Properly unbind client on group search error (Diamond Lewis) [#7265](https://github.com/parse-community/parse-server/pull/7265)
- Improve data consistency in Push and Job Status update (Diamond Lewis) [#7267](https://github.com/parse-community/parse-server/pull/7267)
- Excluding keys that have trailing edges.node when performing GraphQL resolver (Chris Bland) [#7273](https://github.com/parse-community/parse-server/pull/7273)
- Adds Deprecation Policy to make the introduction of breaking changes more predictable. [#7199](https://github.com/parse-community/parse-server/pull/7199). Thanks to [Manuel Trezza](https://github.com/mtrezza).
- Add Deprecation Policy to make the introduction of breaking changes more predictable. [#7199](https://github.com/parse-community/parse-server/pull/7199). Thanks to [Manuel Trezza](https://github.com/mtrezza).
- Add centralized deprecation with standardized warning logs (Manuel Trezza) [#7303](https://github.com/parse-community/parse-server/pull/7303)
___
## 4.5.0
[Full Changelog](https://github.com/parse-community/parse-server/compare/4.4.0...4.5.0)
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,9 +113,9 @@ Parse Server is continuously tested with the most recent releases of Node.js to
| Version | Latest Patch Version | End-of-Life Date | Compatibility |
|------------|----------------------|------------------|--------------------|
| Node.js 10 | 10.24.0 | April 2021 | ✅ Fully compatible |
| Node.js 12 | 12.21.0 | April 2022 | ✅ Fully compatible |
| Node.js 12 | 12.22.0 | April 2022 | ✅ Fully compatible |
| Node.js 14 | 14.16.0 | April 2023 | ✅ Fully compatible |
| Node.js 15 | 15.12.0 | June 2021 | ✅ Fully compatible |
| Node.js 15 | 15.12.0 | June 2021 | ✅ Fully compatible |

#### MongoDB
Parse Server is continuously tested with the most recent releases of MongoDB to ensure compatibility. We follow the [MongoDB support schedule](https://www.mongodb.com/support-policy) and only test against versions that are officially supported and have not reached their end-of-life date.
Expand Down
36 changes: 36 additions & 0 deletions spec/Deprecator.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
'use strict';

const Deprecator = require('../lib/Deprecator/Deprecator');

describe('Deprecator', () => {
let deprecations = [];

beforeEach(async () => {
deprecations = [{ optionKey: 'exampleKey', changeNewDefault: 'exampleNewDefault' }];
});

it('deprecations are an array', async () => {
expect(Deprecator._getDeprecations()).toBeInstanceOf(Array);
});

it('logs deprecation for new default', async () => {
deprecations = [{ optionKey: 'exampleKey', changeNewDefault: 'exampleNewDefault' }];

spyOn(Deprecator, '_getDeprecations').and.callFake(() => deprecations);
const logger = require('../lib/logger').logger;
const logSpy = spyOn(logger, 'warn').and.callFake(() => {});

await reconfigureServer();
expect(logSpy.calls.all()[0].args[0]).toContain(deprecations[0].optionKey);
expect(logSpy.calls.all()[0].args[0]).toContain(deprecations[0].changeNewDefault);
});

it('does not log deprecation for new default if option is set manually', async () => {
deprecations = [{ optionKey: 'exampleKey', changeNewDefault: 'exampleNewDefault' }];

spyOn(Deprecator, '_getDeprecations').and.callFake(() => deprecations);
const logSpy = spyOn(Deprecator, '_log').and.callFake(() => {});
await reconfigureServer({ [deprecations[0].optionKey]: 'manuallySet' });
expect(logSpy).not.toHaveBeenCalled();
});
});
14 changes: 14 additions & 0 deletions src/Deprecator/Deprecations.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/**
* The deprecations.
*
* Add deprecations to the array using the following keys:
* - `optionKey`: The option key incl. its path, e.g. `security.enableCheck`.
* - `envKey`: The environment key, e.g. `PARSE_SERVER_SECURITY`.
* - `changeNewKey`: Set the new key name if the current key will be replaced,
* or set to an empty string if the current key will be removed without replacement.
* - `changeNewDefault`: Set the new default value if the key's default value
* will change in a future version.
*
* If there are no deprecations this must return an empty array anyway.
*/
module.exports = [];
71 changes: 71 additions & 0 deletions src/Deprecator/Deprecator.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import logger from '../logger';
import Deprecations from './Deprecations';

/**
* The deprecator class.
*/
class Deprecator {
/**
* Scans the Parse Server for deprecated options.
* This needs to be called before setting option defaults, otherwise it
* becomes indistinguishable whether an option has been set manually or
* by default.
* @param {any} options The Parse Server options.
*/
static scanParseServerOptions(options) {
// Scan for deprecations
for (const deprecation of Deprecator._getDeprecations()) {
// Get deprecation properties
const optionKey = deprecation.optionKey;
const changeNewDefault = deprecation.changeNewDefault;

// If default will change, only throw a warning if option is not set
if (changeNewDefault != null && options[optionKey] == null) {
Deprecator._log({ optionKey, changeNewDefault });
}
}
}

/**
* Returns the deprecation definitions.
* @returns {Array<Object>} The deprecations.
*/
static _getDeprecations() {
return Deprecations;
}

/**
* Logs a deprecation warning for a Parse Server option.
* @param {String} optionKey The option key incl. its path, e.g. `security.enableCheck`.
* @param {String} envKey The environment key, e.g. `PARSE_SERVER_SECURITY`.
* @param {String} changeNewKey Set the new key name if the current key will be replaced,
* or set to an empty string if the current key will be removed without replacement.
* @param {String} changeNewDefault Set the new default value if the key's default value
* will change in a future version.
* @param {String} [solution] The instruction to resolve this deprecation warning. This
* message must not include the warning that the parameter is deprecated, that is
* automatically added to the message. It should only contain the instruction on how
* to resolve this warning.
*/
static _log({ optionKey, envKey, changeNewKey, changeNewDefault, solution }) {
const type = optionKey ? 'option' : 'environment key';
const key = optionKey ? optionKey : envKey;
const keyAction =
changeNewKey == null
? undefined
: changeNewKey.length > 0
? `renamed to '${changeNewKey}'`
: `removed`;

// Compose message
let output = `DeprecationWarning: The Parse Server ${type} '${key}' `;
output += changeNewKey ? `is deprecated and will be ${keyAction} in a future version.` : '';
output += changeNewDefault
? `default will change to '${changeNewDefault}' in a future version.`
: '';
output += solution ? ` ${solution}` : '';
logger.warn(output);
}
}

module.exports = Deprecator;
4 changes: 4 additions & 0 deletions src/ParseServer.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ import * as controllers from './Controllers';
import { ParseGraphQLServer } from './GraphQL/ParseGraphQLServer';
import { SecurityRouter } from './Routers/SecurityRouter';
import CheckRunner from './Security/CheckRunner';
import Deprecator from './Deprecator/Deprecator';

// Mutate the Parse object to add the Cloud Code handlers
addParseCloud();
Expand All @@ -55,6 +56,9 @@ class ParseServer {
* @param {ParseServerOptions} options the parse server initialization options
*/
constructor(options: ParseServerOptions) {
// Scan for deprecated Parse Server options
Deprecator.scanParseServerOptions(options);
// Set option defaults
injectDefaults(options);
const {
appId = requiredParameter('You must provide an appId!'),
Expand Down
6 changes: 5 additions & 1 deletion src/cli/utils/commander.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
/* eslint-disable no-console */
import { Command } from 'commander';
import path from 'path';
import Deprecator from '../../Deprecator/Deprecator';

let _definitions;
let _reverseDefinitions;
let _defaults;
Expand Down Expand Up @@ -40,7 +42,7 @@ Command.prototype.loadDefinitions = function (definitions) {
}, {});

_defaults = Object.keys(definitions).reduce((defs, opt) => {
if (_definitions[opt].default) {
if (_definitions[opt].default !== undefined) {
defs[opt] = _definitions[opt].default;
}
return defs;
Expand Down Expand Up @@ -119,6 +121,8 @@ Command.prototype.parse = function (args, env) {
this.setValuesIfNeeded(envOptions);
// Load from file to override
this.setValuesIfNeeded(fromFile);
// Scan for deprecated Parse Server options
Deprecator.scanParseServerOptions(this);
// Last set the defaults
this.setValuesIfNeeded(_defaults);
};
Expand Down

0 comments on commit f502c45

Please sign in to comment.