diff --git a/README.md b/README.md index 6dfdb3e..88a2205 100644 --- a/README.md +++ b/README.md @@ -245,6 +245,24 @@ If you have scripts that need to be executable when they're installed on your ta } ``` +### Config files + +If you have files that need to be preserved after every `yum update`, you can add them to the `config` array. +On update you can achieve following two behaviors: +1. `"noreplace": false` (default): Local edited file will be renamed with `.rpmsave` +2. `"noreplace": true`: Local edited file will be preserved and new file from update will be renamed with `.rpmnew` + +```json +{ + "spec": { + "config": [ + {"file": "./my-config.js", "noreplace": true}, + {"file": "./my-other-config.js"} + ] + } +} +``` + ### Post Install Actions If you need to perform any actions after installing your package (such as moving files on the target server) you can specify these inline using the `post` property: diff --git a/lib/spec.js b/lib/spec.js index 151b50f..25e89ea 100644 --- a/lib/spec.js +++ b/lib/spec.js @@ -43,6 +43,17 @@ function getExecutableFiles(pkg) { }; } +function getConfigFiles(pkg) { + const name = pkg.name; + + return _.get(pkg, 'spec.config', []).map((o) => { + return { + file: path.join('/usr/lib/', name, o.file), + noreplace: o.noreplace || false + }; + }); +} + function getPostInstallCommands(pkg) { return _.get(pkg, 'spec.post', []); } @@ -60,7 +71,8 @@ module.exports = function (pkg, release) { nodeVersion: getNodeVersion(pkg), version: pkg.version, license: pkg.license, - prune: shouldPrune(pkg) + prune: shouldPrune(pkg), + configFiles: getConfigFiles(pkg) }, getExecutableFiles(pkg), getServiceProperties(pkg) diff --git a/templates/spec.mustache b/templates/spec.mustache index bc74642..bad36f7 100644 --- a/templates/spec.mustache +++ b/templates/spec.mustache @@ -61,3 +61,6 @@ rm -rf %{buildroot} %attr(755, {{username}}, {{username}}) {{.}} {{/executableFiles}} {{/hasExecutableFiles}} +{{#configFiles}} +%config{{#noreplace}}(noreplace){{/noreplace}} {{file}} +{{/configFiles}} diff --git a/test/fixtures/my-cool-api-with-config-files.json b/test/fixtures/my-cool-api-with-config-files.json new file mode 100644 index 0000000..3616e42 --- /dev/null +++ b/test/fixtures/my-cool-api-with-config-files.json @@ -0,0 +1,17 @@ +{ + "name": "my-cool-api", + "version": "1.1.1", + "scripts": { + "start": "node index.js" + }, + "description": "My Cool API", + "main": "index.js", + "author": "bob@example.com", + "license": "MIT", + "spec": { + "config": [ + {"file": "./no-replace.js", "noreplace": true}, + {"file": "./config.js"} + ] + } +} diff --git a/test/fixtures/my-cool-api-with-config-files.spec b/test/fixtures/my-cool-api-with-config-files.spec new file mode 100644 index 0000000..a50cd00 --- /dev/null +++ b/test/fixtures/my-cool-api-with-config-files.spec @@ -0,0 +1,49 @@ +%define name my-cool-api +%define version 1.1.1 +%define release 1 +%define buildroot %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX) + +Name: %{name} +Version: %{version} +Release: %{release} +Summary: my-cool-api + +Group: Installation Script +License: MIT +Source: %{name}.tar.gz +BuildRoot: %{buildroot} +Requires: nodejs +BuildRequires: nodejs +AutoReqProv: no + +%description +My Cool API + +%prep +%setup -q -c -n %{name} + +%build +npm prune --production +npm rebuild + +%pre +getent group my-cool-api >/dev/null || groupadd -r my-cool-api +getent passwd my-cool-api >/dev/null || useradd -r -g my-cool-api -G my-cool-api -d / -s /sbin/nologin -c "my-cool-api" my-cool-api + +%install +mkdir -p %{buildroot}/usr/lib/my-cool-api +cp -r ./ %{buildroot}/usr/lib/my-cool-api +mkdir -p %{buildroot}/var/log/my-cool-api + +%post +systemctl enable /usr/lib/my-cool-api/my-cool-api.service + +%clean +rm -rf %{buildroot} + +%files +%defattr(644, my-cool-api, my-cool-api, 755) +/usr/lib/my-cool-api +/var/log/my-cool-api +%config(noreplace) /usr/lib/my-cool-api/no-replace.js +%config /usr/lib/my-cool-api/config.js diff --git a/test/spec.js b/test/spec.js index 9034c60..654998c 100644 --- a/test/spec.js +++ b/test/spec.js @@ -70,6 +70,14 @@ describe('spec', () => { assert.equal(spec, expected); }); + it('adds all of the config files from the spec.config property in package.json', () => { + const pkg = require('./fixtures/my-cool-api-with-config-files'); + const expected = loadFixture('my-cool-api-with-config-files.spec'); + const spec = createSpecFile(pkg); + + assert.equal(spec, expected); + }); + it('includes post-install actions from the spec.post property in package.json', () => { const pkg = require('./fixtures/my-cool-api-with-post'); const expected = loadFixture('my-cool-api-with-post.spec');