Skip to content

Commit

Permalink
feat: add community CITGM checks (#64)
Browse files Browse the repository at this point in the history
Output a warning for packages either not included in the list of
community CITGM runs or are in the list but skipped for an in
support version of Node.js.
  • Loading branch information
richardlau authored Aug 27, 2021
1 parent ada7116 commit 7ceeced
Show file tree
Hide file tree
Showing 3 changed files with 245 additions and 1 deletion.
4 changes: 3 additions & 1 deletion src/cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ const chalk = require('chalk');

const deprecationPlugin = require('./plugins/deprecation');
const archivePlugin = require('./plugins/archive');
const citgmPlugin = require('./plugins/citgm');
const licensePlugin = require('./plugins/license');
const licenseTreePlugin = require('./plugins/licenseTree');
const testsPlugin = require('./plugins/tests');
Expand Down Expand Up @@ -52,7 +53,8 @@ module.exports = {
testsPlugin,
maintenancePlugin,
supportPlugin,
typingsPlugin
typingsPlugin,
citgmPlugin
];

for (const pkg of config.modules) {
Expand Down
55 changes: 55 additions & 0 deletions src/plugins/citgm.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
const { createWarning } = require('../lib/result');
const { stringBuilder, success, warning } = require('../lib/format');
const { fetchGithub } = require('../lib/network');
const nv = require('@pkgjs/nv');
const semver = require('semver');

const CITGM_REPO = 'nodejs/citgm';
const LOOKUP_PATH = 'lib/lookup.json';
const BRANCH = 'HEAD';

const getCITGMLookup = async (token) => {
const metadata = await fetchGithub(
`/repos/${CITGM_REPO}/contents/${LOOKUP_PATH}?ref=${BRANCH}`,
token
);
const content = Buffer.from(metadata.content, metadata.encoding);
return JSON.parse(content);
}

const citgmPlugin = async (pkg, _, options) => {
// Support plugin output
const output = stringBuilder(
'\nChecking if module is tested by community CITGM runs'
).withPadding(66);

const lookup = await getCITGMLookup(options.token);
if (!lookup[pkg.name]) {
warning(output.get());
return createWarning(
`The module "${pkg.name}" is not tested by community CITGM runs.`
);
}
const skip = lookup[pkg.name].skip;
if (skip !== undefined) {
if (skip === true || (Array.isArray(skip) && skip.includes(true))) {
warning(output.get());
return createWarning(
`The module "${pkg.name}" is not tested (skipped) by community CITGM runs.`
);
}
const lts = (await nv('supported')).map(v => v.version);
for (version of lts) {
if ((!Array.isArray(skip) && semver.satisfies(version, skip)) || Array.isArray(skip) && skip.some(v => semver.satisfies(version, v))) {
warning(output.get());
return createWarning(
`The module "${pkg.name}" is not tested (skipped on ${version}) by community CITGM runs.`
);
}
}
}
success(output.get());
return null;
};

module.exports = citgmPlugin;
187 changes: 187 additions & 0 deletions test/plugins/citgm.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
/* eslint-env jest */

const nv = require('@pkgjs/nv');

const network = require('../../src/lib/network');
const format = require('../../src/lib/format');
const citgmPlugin = require('../../src/plugins/citgm');

jest.mock('@pkgjs/nv');
jest.mock('../../src/lib/network');
jest.mock('../../src/lib/format', () => ({
...jest.requireActual('../../src/lib/format'),
failure: jest.fn(),
success: jest.fn(),
warning: jest.fn()
}));

const CITGM_LOOKUP_URL = '/repos/nodejs/citgm/contents/lib/lookup.json?ref=HEAD';

const mockCITGMLookup = (content, encoding = 'utf8') => {
network.fetchGithub.mockImplementation(() => {
return Promise.resolve({ content, encoding });
});
}

beforeEach(() => {
nv.mockImplementation(() => {
return Promise.resolve([{ version: '12.22.5' }, { version: '14.17.5' }, { version: '16.7.0' }]);
});
});

afterEach(() => {
jest.clearAllMocks();
});

it('should succeed if package is tested by community CITGM', async () => {
mockCITGMLookup('{ "mymodule": {} }');

const pkg = {
name: 'mymodule'
};

const result = await citgmPlugin(pkg, null, {});
expect(network.fetchGithub).toHaveBeenCalled();
expect(network.fetchGithub).toBeCalledWith(CITGM_LOOKUP_URL, undefined);
expect(format.success).toHaveBeenCalled();
expect(result).toBeNull();
});

it('should warn if package is not tested by community CITGM', async () => {
mockCITGMLookup('{}');

const pkg = {
name: 'mymodule'
};

const result = await citgmPlugin(pkg, null, {});
expect(network.fetchGithub).toHaveBeenCalled();
expect(network.fetchGithub).toBeCalledWith(CITGM_LOOKUP_URL, undefined);
expect(format.warning).toHaveBeenCalled();
expect(result.type).toBe('warning');
});

it('should warn if package is skipped everywhere', async () => {
mockCITGMLookup('{ "mymodule": { "skip": true } }');

const pkg = {
name: 'mymodule'
};

const result = await citgmPlugin(pkg, null, {});
expect(network.fetchGithub).toHaveBeenCalled();
expect(network.fetchGithub).toBeCalledWith(CITGM_LOOKUP_URL, undefined);
expect(format.warning).toHaveBeenCalled();
expect(result.type).toBe('warning');
});

it('should warn if package is skipped everywhere (array version)', async () => {
mockCITGMLookup('{ "mymodule": { "skip": [ true ] } }');

const pkg = {
name: 'mymodule'
};

const result = await citgmPlugin(pkg, null, {});
expect(network.fetchGithub).toHaveBeenCalled();
expect(network.fetchGithub).toBeCalledWith(CITGM_LOOKUP_URL, undefined);
expect(format.warning).toHaveBeenCalled();
expect(result.type).toBe('warning');
});

it('should warn if package is skipped for in support versions', async () => {
mockCITGMLookup('{ "mymodule": { "skip": ">10" } }');

const pkg = {
name: 'mymodule'
};

const result = await citgmPlugin(pkg, null, {});
expect(network.fetchGithub).toHaveBeenCalled();
expect(network.fetchGithub).toBeCalledWith(CITGM_LOOKUP_URL, undefined);
expect(format.warning).toHaveBeenCalled();
expect(result.type).toBe('warning');
});

it('should warn if package is skipped for in support versions (array version)', async () => {
mockCITGMLookup('{ "mymodule": { "skip": [ ">10" ] } }');

const pkg = {
name: 'mymodule'
};

const result = await citgmPlugin(pkg, null, {});
expect(network.fetchGithub).toHaveBeenCalled();
expect(network.fetchGithub).toBeCalledWith(CITGM_LOOKUP_URL, undefined);
expect(format.warning).toHaveBeenCalled();
expect(result.type).toBe('warning');
});

it('should succeed if package if skips do not affect in support versions', async () => {
mockCITGMLookup('{ "mymodule": { "skip": "<10" } }');

const pkg = {
name: 'mymodule'
};

const result = await citgmPlugin(pkg, null, {});
expect(network.fetchGithub).toHaveBeenCalled();
expect(network.fetchGithub).toBeCalledWith(CITGM_LOOKUP_URL, undefined);
expect(format.success).toHaveBeenCalled();
expect(result).toBeNull();
});

it('should succeed if package if skips do not affect in support versions (array version)', async () => {
mockCITGMLookup('{ "mymodule": { "skip": ["<10"] } }');

const pkg = {
name: 'mymodule'
};

const result = await citgmPlugin(pkg, null, {});
expect(network.fetchGithub).toHaveBeenCalled();
expect(network.fetchGithub).toBeCalledWith(CITGM_LOOKUP_URL, undefined);
expect(format.success).toHaveBeenCalled();
expect(result).toBeNull();
});

it('should succeed if package if skips are only platform specific', async () => {
mockCITGMLookup('{ "mymodule": { "skip": "aix" } }');

const pkg = {
name: 'mymodule'
};

const result = await citgmPlugin(pkg, null, {});
expect(network.fetchGithub).toHaveBeenCalled();
expect(network.fetchGithub).toBeCalledWith(CITGM_LOOKUP_URL, undefined);
expect(format.success).toHaveBeenCalled();
expect(result).toBeNull();
});

it('should succeed if package if skips are only platform specific (array version)', async () => {
mockCITGMLookup('{ "mymodule": { "skip": ["aix", "s390", "ppc" ] } }');

const pkg = {
name: 'mymodule'
};

const result = await citgmPlugin(pkg, null, {});
expect(network.fetchGithub).toHaveBeenCalled();
expect(network.fetchGithub).toBeCalledWith(CITGM_LOOKUP_URL, undefined);
expect(format.success).toHaveBeenCalled();
expect(result).toBeNull();
});

it('should not perform partial matches', async () => {
mockCITGMLookup('{ "mymodule2": {} }');

const pkg = {
name: 'mymodule'
};

const result = await citgmPlugin(pkg, null, {});
expect(network.fetchGithub).toHaveBeenCalled();
expect(network.fetchGithub).toBeCalledWith(CITGM_LOOKUP_URL, undefined);
expect(format.warning).toHaveBeenCalled();
});

0 comments on commit 7ceeced

Please sign in to comment.