Skip to content

Commit

Permalink
refactor: license transforms (#61)
Browse files Browse the repository at this point in the history
  • Loading branch information
FantasticFiasco authored Jul 24, 2020
1 parent f55baa2 commit 417b74b
Show file tree
Hide file tree
Showing 8 changed files with 268 additions and 188 deletions.
5 changes: 3 additions & 2 deletions src/action-update-license-year.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
const { getInput, setFailed, info } = require('@actions/core');
const { context } = require('@actions/github');
const { updateLicense } = require('./license');
const { transformLicense } = require('./license');
const Repository = require('./Repository');

const FILENAME = 'LICENSE';
Expand All @@ -17,7 +17,8 @@ async function run() {
const licenseResponse = await repository.getContent(hasBranch ? BRANCH_NAME : MASTER, FILENAME);
const license = Buffer.from(licenseResponse.data.content, 'base64').toString('ascii');

const updatedLicense = updateLicense(license);
const currentYear = new Date().getFullYear();
const updatedLicense = transformLicense(license, currentYear);
if (updatedLicense === license) {
info('License file is already up-to-date, my work here is done');
return;
Expand Down
95 changes: 11 additions & 84 deletions src/license.js
Original file line number Diff line number Diff line change
@@ -1,97 +1,24 @@
// Regular expressions finding the copyright year(s) in GNU Affero General Public License v3.0 only
// (AGPL-3.0-only) license files
const GNU_AGPLv3_COPYRIGHT_YEAR = /(Copyright\s+\(C\)\s+)(\d{4})(?!\s+Free Software Foundation)(\s+\w+)/m;
const GNU_AGPLv3_COPYRIGHT_YEAR_RANGE = /(Copyright\s+\(C\)\s+)(\d{4})-(\d{4})(?!\s+Free Software Foundation)(\s+\w+)/m;
const apache = require('./transforms/apache');
const bsd = require('./transforms/bsd');
const gnuAgpl3 = require('./transforms/gnuAgpl3');
const mit = require('./transforms/mit');

// Regular expressions finding the copyright year(s) in Apache 2.0 (Apache-2.0) license files
const APACHE_COPYRIGHT_YEAR = /(Copyright\s+)(\d{4})(\s+\w+)/m;
const APACHE_COPYRIGHT_YEAR_RANGE = /(Copyright\s+)(\d{4})-(\d{4})(\s+\w+)/m;

// Regular expressions finding the copyright year(s) in BSD 2-clause "Simplified" (BSD-2-Clause)
// and BSD 3-clause "New" or "Revised" (BSD-3-Clause) license files
const BSD_COPYRIGHT_YEAR = /(Copyright\s+\(c\)\s+)(\d{4})(,\s+\w+)/m;
const BSD_COPYRIGHT_YEAR_RANGE = /(Copyright\s+\(c\)\s+)(\d{4})-(\d{4})(,\s+\w+)/m;

// Regular expressions finding the copyright year(s) in MIT (MIT) license files
const MIT_COPYRIGHT_YEAR = /(Copyright\s+\(c\)\s+)(\d{4})(\s+\w+)/m;
const MIT_COPYRIGHT_YEAR_RANGE = /(Copyright\s+\(c\)\s+)(\d{4})-(\d{4})(\s+\w+)/m;

/**
* @param {string} license
*/
function updateLicense(license) {
const currentYear = new Date().getFullYear();
return updateLicenseToYear(license, currentYear);
}
const TRANSFORMS = [gnuAgpl3, apache, bsd, mit];

/**
* @param {string} license
* @param {number} year
* @param {number} currentYear
*/
function updateLicenseToYear(license, year) {
// GNU Affero General Public License v3.0 only
let match = GNU_AGPLv3_COPYRIGHT_YEAR.exec(license);
if (match !== null) {
if (isYearUnchanged(match, year)) {
return license;
}
return license.replace(GNU_AGPLv3_COPYRIGHT_YEAR, `$1$2-${year}$3`);
}
if (GNU_AGPLv3_COPYRIGHT_YEAR_RANGE.test(license)) {
return license.replace(GNU_AGPLv3_COPYRIGHT_YEAR_RANGE, `$1$2-${year}$4`);
}

// Apache 2.0
match = APACHE_COPYRIGHT_YEAR.exec(license);
if (match !== null) {
if (isYearUnchanged(match, year)) {
return license;
}
return license.replace(APACHE_COPYRIGHT_YEAR, `$1$2-${year}$3`);
}
if (APACHE_COPYRIGHT_YEAR_RANGE.test(license)) {
return license.replace(APACHE_COPYRIGHT_YEAR_RANGE, `$1$2-${year}$4`);
}

// BSD 2-clause "Simplified"
// BSD 3-clause "New" or "Revised"
match = BSD_COPYRIGHT_YEAR.exec(license);
if (match !== null) {
if (isYearUnchanged(match, year)) {
return license;
}
return license.replace(BSD_COPYRIGHT_YEAR, `$1$2-${year}$3`);
}
if (BSD_COPYRIGHT_YEAR_RANGE.test(license)) {
return license.replace(BSD_COPYRIGHT_YEAR_RANGE, `$1$2-${year}$4`);
}

// MIT
match = MIT_COPYRIGHT_YEAR.exec(license);
if (match !== null) {
if (isYearUnchanged(match, year)) {
return license;
function transformLicense(license, currentYear) {
for (const transform of TRANSFORMS) {
if (transform.canTransform(license)) {
return transform.transform(license, currentYear);
}
return license.replace(MIT_COPYRIGHT_YEAR, `$1$2-${year}$3`);
}
if (MIT_COPYRIGHT_YEAR_RANGE.test(license)) {
return license.replace(MIT_COPYRIGHT_YEAR_RANGE, `$1$2-${year}$4`);
}

throw new Error('Specified license is not supported');
}

/**
*
* @param {string[]} match
* @param {number} year
*/
function isYearUnchanged(match, year) {
const yearInLicense = Number(match[2]);
return yearInLicense === year;
}

module.exports = {
updateLicense,
updateLicenseToYear,
transformLicense,
};
37 changes: 37 additions & 0 deletions src/transforms/apache.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// Module capable of transforming the following license files:
// - Apache 2.0 (Apache-2.0)

const COPYRIGHT_YEAR = /(Copyright\s+)(\d{4})(\s+\w+)/m;
const COPYRIGHT_YEARS = /(Copyright\s+)(\d{4})-(\d{4})(\s+\w+)/m;

/**
* @param {string} license
*/
function canTransform(license) {
return COPYRIGHT_YEAR.test(license) || COPYRIGHT_YEARS.test(license);
}

/**
* @param {string} license
* @param {number} currentYear
*/
function transform(license, currentYear) {
const match = COPYRIGHT_YEAR.exec(license);
if (match !== null) {
const licenseYear = Number(match[2]);
if (licenseYear === currentYear) {
return license;
}
return license.replace(COPYRIGHT_YEAR, `$1$2-${currentYear}$3`);
}
if (COPYRIGHT_YEARS.test(license)) {
return license.replace(COPYRIGHT_YEARS, `$1$2-${currentYear}$4`);
}

throw new Error('Transforming Apache-2.0 license failed');
}

module.exports = {
canTransform,
transform,
};
38 changes: 38 additions & 0 deletions src/transforms/bsd.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// Module capable of transforming the following license files:
// - BSD 2-clause "Simplified" (BSD-2-Clause)
// - BSD 3-clause "New" or "Revised" (BSD-3-Clause)

const COPYRIGHT_YEAR = /(Copyright\s+\(c\)\s+)(\d{4})(,\s+\w+)/m;
const COPYRIGHT_YEARS = /(Copyright\s+\(c\)\s+)(\d{4})-(\d{4})(,\s+\w+)/m;

/**
* @param {string} license
*/
function canTransform(license) {
return COPYRIGHT_YEAR.test(license) || COPYRIGHT_YEARS.test(license);
}

/**
* @param {string} license
* @param {number} currentYear
*/
function transform(license, currentYear) {
const match = COPYRIGHT_YEAR.exec(license);
if (match !== null) {
const licenseYear = Number(match[2]);
if (licenseYear === currentYear) {
return license;
}
return license.replace(COPYRIGHT_YEAR, `$1$2-${currentYear}$3`);
}
if (COPYRIGHT_YEARS.test(license)) {
return license.replace(COPYRIGHT_YEARS, `$1$2-${currentYear}$4`);
}

throw new Error('Transforming BSD-2-Clause or BSD-3-Clause license failed');
}

module.exports = {
canTransform,
transform,
};
37 changes: 37 additions & 0 deletions src/transforms/gnuAgpl3.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// Module capable of transforming the following license files:
// - GNU Affero General Public License v3.0 only (AGPL-3.0-only)

const COPYRIGHT_YEAR = /(Copyright\s+\(C\)\s+)(\d{4})(?!\s+Free Software Foundation)(\s+\w+)/m;
const COPYRIGHT_YEARS = /(Copyright\s+\(C\)\s+)(\d{4})-(\d{4})(?!\s+Free Software Foundation)(\s+\w+)/m;

/**
* @param {string} license
*/
function canTransform(license) {
return COPYRIGHT_YEAR.test(license) || COPYRIGHT_YEARS.test(license);
}

/**
* @param {string} license
* @param {number} currentYear
*/
function transform(license, currentYear) {
const match = COPYRIGHT_YEAR.exec(license);
if (match !== null) {
const licenseYear = Number(match[2]);
if (licenseYear === currentYear) {
return license;
}
return license.replace(COPYRIGHT_YEAR, `$1$2-${currentYear}$3`);
}
if (COPYRIGHT_YEARS.test(license)) {
return license.replace(COPYRIGHT_YEARS, `$1$2-${currentYear}$4`);
}

throw new Error('Transforming AGPL-3.0-only license failed');
}

module.exports = {
canTransform,
transform,
};
37 changes: 37 additions & 0 deletions src/transforms/mit.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// Module capable of transforming the following license files:
// - MIT (MIT)

const COPYRIGHT_YEAR = /(Copyright\s+\(c\)\s+)(\d{4})(\s+\w+)/m;
const COPYRIGHT_YEARS = /(Copyright\s+\(c\)\s+)(\d{4})-(\d{4})(\s+\w+)/m;

/**
* @param {string} license
*/
function canTransform(license) {
return COPYRIGHT_YEAR.test(license) || COPYRIGHT_YEARS.test(license);
}

/**
* @param {string} license
* @param {number} currentYear
*/
function transform(license, currentYear) {
const match = COPYRIGHT_YEAR.exec(license);
if (match !== null) {
const licenseYear = Number(match[2]);
if (licenseYear === currentYear) {
return license;
}
return license.replace(COPYRIGHT_YEAR, `$1$2-${currentYear}$3`);
}
if (COPYRIGHT_YEARS.test(license)) {
return license.replace(COPYRIGHT_YEARS, `$1$2-${currentYear}$4`);
}

throw new Error('Transforming MIT license failed');
}

module.exports = {
canTransform,
transform,
};
6 changes: 3 additions & 3 deletions test/action-update-license-year.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ jest.mock('../src/Repository', () => {
});

const mockLicense = {
updateLicense: jest.fn(),
transformLicense: jest.fn(),
};
jest.mock('../src/license', () => {
return mockLicense;
Expand Down Expand Up @@ -91,7 +91,7 @@ describe('action should', () => {
});

test('skip creating branch given license is unchanged', async () => {
mockLicense.updateLicense.mockReturnValue(LICESE_CONTENT);
mockLicense.transformLicense.mockReturnValue(LICESE_CONTENT);
await run();
expect(mockRepository.createBranch).toBeCalledTimes(0);
expect(setFailed).toBeCalledTimes(0);
Expand All @@ -118,7 +118,7 @@ describe('action should', () => {
});

test('skip creating pull request given license is unchanged', async () => {
mockLicense.updateLicense.mockReturnValue(LICESE_CONTENT);
mockLicense.transformLicense.mockReturnValue(LICESE_CONTENT);
await run();
expect(mockRepository.createPullRequest).toBeCalledTimes(0);
expect(setFailed).toBeCalledTimes(0);
Expand Down
Loading

0 comments on commit 417b74b

Please sign in to comment.