From 367b6f63b69555bfa5dea504471f23724755645d Mon Sep 17 00:00:00 2001 From: Cliffano Subagio Date: Thu, 12 Oct 2023 23:45:40 +1100 Subject: [PATCH] Add toml resource type #13 --- CHANGELOG.md | 3 + README.md | 14 +++++ lib/resource-types/toml.js | 54 ++++++++++++++++++ package-lock.json | 6 ++ package.json | 3 +- test/resource-types/toml.js | 106 ++++++++++++++++++++++++++++++++++++ 6 files changed, 185 insertions(+), 1 deletion(-) create mode 100644 lib/resource-types/toml.js create mode 100644 test/resource-types/toml.js diff --git a/CHANGELOG.md b/CHANGELOG.md index 4fe2665e..400fc3c4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased +### Added +- Add toml resource type #13 + ## 3.0.0 - 2023-07-23 ### Added - Add label to log messages when dry-run is enabled diff --git a/README.md b/README.md index d49f515f..96b1ca8c 100644 --- a/README.md +++ b/README.md @@ -130,6 +130,20 @@ Example `keep-a-changelog` resource configuration: ] } +Example `toml` resource configuration: + + { + "resources": [ + { + "path": "pyproject.toml", + "type": "toml", + "params": { + "property": "version" + } + } + ] + } + Example `makefile` resource configuration: { diff --git a/lib/resource-types/toml.js b/lib/resource-types/toml.js new file mode 100644 index 00000000..f14ad7cb --- /dev/null +++ b/lib/resource-types/toml.js @@ -0,0 +1,54 @@ +"use strict" +import {getProperty, setProperty} from 'dot-prop'; +import fs from 'fs'; +import toml from '@iarna/toml'; + +/** + * Set version value in the TOML resource's property (defined in dot-notation). + * + * @param {String} version: version value to set + * @param {Object} resource: resource configuration which contains type, path, and params + * @param {Object} opts: optional settings + * - dryRun: when true, TOML file won't be modified + * @param {Function} cb: standard cb(err, result) callback + */ +function setVersion(version, resource, opts, cb) { + const property = resource.params.property; + let data = toml.parse(fs.readFileSync(resource.path, 'UTF-8')); + setProperty(data, property, version); + if (!opts.dryRun) { + fs.writeFile(resource.path, toml.stringify(data, null, 2), cb); + } else { + cb(); + } +} + +/** + * Get version value from the TOML resource's property (defined in dot-notation). + * + * @param {Object} resource: resource configuration which contains type, path, and params + * @param {Function} cb: standard cb(err, result) callback + */ +function getVersion(resource, cb) { + const property = resource.params.property; + + function readCb(err, result) { + let version; + if (!err) { + const data = toml.parse(result); + version = getProperty(data, property); + } + cb(err, version); + } + fs.readFile(resource.path, 'UTF-8', readCb); +} + +const exports = { + setReleaseVersion: setVersion, + setPostReleaseVersion: setVersion, + getVersion: getVersion +}; + +export { + exports as default +}; diff --git a/package-lock.json b/package-lock.json index 616be870..7338ce64 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,6 +9,7 @@ "version": "3.0.1-pre.0", "license": "MIT", "dependencies": { + "@iarna/toml": "^2.2.5", "@kba/makefile-parser": "^0.0.6", "async": "^3.2.4", "bagofcli": "^2.4.1", @@ -31,6 +32,11 @@ "node": ">= 16.0.0" } }, + "node_modules/@iarna/toml": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/@iarna/toml/-/toml-2.2.5.tgz", + "integrity": "sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg==" + }, "node_modules/@kba/makefile-parser": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/@kba/makefile-parser/-/makefile-parser-0.0.6.tgz", diff --git a/package.json b/package.json index 819fc704..ee063bb2 100644 --- a/package.json +++ b/package.json @@ -46,7 +46,8 @@ "lodash": "^4.17.21", "@kba/makefile-parser": "^0.0.6", "simple-git": "^3.20.0", - "string-format": "^2.0.0" + "string-format": "^2.0.0", + "@iarna/toml": "^2.2.5" }, "devDependencies": { "sinon": "^16.1.0", diff --git a/test/resource-types/toml.js b/test/resource-types/toml.js new file mode 100644 index 00000000..ac19c3b1 --- /dev/null +++ b/test/resource-types/toml.js @@ -0,0 +1,106 @@ +"use strict" +/* eslint no-unused-vars: 0 */ +import assert from 'assert'; +import fs from 'fs'; +import resourceType from '../../lib/resource-types/toml.js'; +import sinon from 'sinon'; + +describe('toml', function() { + + beforeEach(function (done) { + this.mockFs = sinon.mock(fs); + done(); + }); + afterEach(function (done) { + this.mockFs.verify(); + sinon.restore(); + done(); + }); + + describe('setVersion', function() { + it('should only set version but not modify toml file when dry run is enabled', function(done) { + let resource = { + path: 'somepackage.toml', + type: 'toml', + params: { + property: 'version' + } + }; + this.mockFs.expects('readFileSync').once().withExactArgs('somepackage.toml', 'UTF-8').returns('version = "0.0.0"'); + this.mockFs.expects('writeFile').never(); + function cb(err, result) { + assert.equal(err, null); + done(); + } + resourceType.setReleaseVersion('1.2.3', resource, { dryRun: true }, cb); + }); + it('should set version and modify toml file when dry run is disabled', function(done) { + let resource = { + path: 'somepackage.toml', + type: 'toml', + params: { + property: 'version' + } + }; + this.mockFs.expects('readFileSync').once().withExactArgs('somepackage.toml', 'UTF-8').returns('version = "0.0.0"'); + this.mockFs.expects('writeFile').once().withExactArgs('somepackage.toml', 'version = "1.2.3"\n', sinon.match.func).callsArgWith(2, null); + function cb(err, result) { + assert.equal(err, null); + done(); + } + resourceType.setReleaseVersion('1.2.3', resource, { dryRun: false }, cb); + }); + it('should set array property under a section', function(done) { + let resource = { + path: 'somepackage.toml', + type: 'toml', + params: { + property: 'package.versions[1]' + } + }; + this.mockFs.expects('readFileSync').once().withExactArgs('somepackage.toml', 'UTF-8').returns('[package]\nversions = ["9.9.9", "0.0.0", "8.8.8"]'); + this.mockFs.expects('writeFile').once().withExactArgs('somepackage.toml', '[package]\nversions = [ "9.9.9", "1.2.3", "8.8.8" ]\n', sinon.match.func).callsArgWith(2, null); + function cb(err, result) { + assert.equal(err, null); + done(); + } + resourceType.setReleaseVersion('1.2.3', resource, { dryRun: false }, cb); + }); + }); + + describe('getVersion', function() { + it('should get version from resource property', function(done) { + let resource = { + path: 'somepackage.toml', + type: 'toml', + params: { + property: 'version' + } + }; + this.mockFs.expects('readFile').once().withExactArgs('somepackage.toml', 'UTF-8', sinon.match.func).callsArgWith(2, null, 'version = "0.0.0"'); + function cb(err, result) { + assert.equal(err, null); + assert.equal(result, '0.0.0'); + done(); + } + resourceType.getVersion(resource, cb); + }); + it('should get array property under a section', function(done) { + let resource = { + path: 'somepackage.toml', + type: 'toml', + params: { + property: 'package.versions[1]' + } + }; + this.mockFs.expects('readFile').once().withExactArgs('somepackage.toml', 'UTF-8', sinon.match.func).callsArgWith(2, null, '[package]\nversions = ["9.9.9", "0.0.0", "8.8.8"]'); + function cb(err, result) { + assert.equal(err, null); + assert.equal(result, '0.0.0'); + done(); + } + resourceType.getVersion(resource, cb); + }); + }); + +});