diff options
-rw-r--r-- | package-lock.json | 26 | ||||
-rw-r--r-- | package.json | 3 | ||||
-rw-r--r-- | scripts/package.js | 49 |
3 files changed, 64 insertions, 14 deletions
diff --git a/package-lock.json b/package-lock.json index f79e224..a2dfaff 100644 --- a/package-lock.json +++ b/package-lock.json | |||
@@ -274,6 +274,21 @@ | |||
274 | } | 274 | } |
275 | } | 275 | } |
276 | }, | 276 | }, |
277 | "@kwsites/file-exists": { | ||
278 | "version": "1.1.1", | ||
279 | "resolved": "https://registry.npmjs.org/@kwsites/file-exists/-/file-exists-1.1.1.tgz", | ||
280 | "integrity": "sha512-m9/5YGR18lIwxSFDwfE3oA7bWuq9kdau6ugN4H2rJeyhFQZcG9AgSHkQtSD15a8WvTgfz9aikZMrKPHvbpqFiw==", | ||
281 | "dev": true, | ||
282 | "requires": { | ||
283 | "debug": "^4.1.1" | ||
284 | } | ||
285 | }, | ||
286 | "@kwsites/promise-deferred": { | ||
287 | "version": "1.1.1", | ||
288 | "resolved": "https://registry.npmjs.org/@kwsites/promise-deferred/-/promise-deferred-1.1.1.tgz", | ||
289 | "integrity": "sha512-GaHYm+c0O9MjZRu0ongGBRbinu8gVAMd2UZjji6jVmqKtZluZnptXGWhz1E8j8D2HJ3f/yMxKAUC0b+57wncIw==", | ||
290 | "dev": true | ||
291 | }, | ||
277 | "@nodelib/fs.scandir": { | 292 | "@nodelib/fs.scandir": { |
278 | "version": "2.1.3", | 293 | "version": "2.1.3", |
279 | "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.3.tgz", | 294 | "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.3.tgz", |
@@ -4350,6 +4365,17 @@ | |||
4350 | "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", | 4365 | "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", |
4351 | "dev": true | 4366 | "dev": true |
4352 | }, | 4367 | }, |
4368 | "simple-git": { | ||
4369 | "version": "2.39.0", | ||
4370 | "resolved": "https://registry.npmjs.org/simple-git/-/simple-git-2.39.0.tgz", | ||
4371 | "integrity": "sha512-VOsrmc3fpp1lGVIpo+1SKNqJzrdVJeSGZCeenPKnJPNo5UouAlSkWFc037pfm9wRYtfxBdwp2deVJGCG8J6C8A==", | ||
4372 | "dev": true, | ||
4373 | "requires": { | ||
4374 | "@kwsites/file-exists": "^1.1.1", | ||
4375 | "@kwsites/promise-deferred": "^1.1.1", | ||
4376 | "debug": "^4.3.1" | ||
4377 | } | ||
4378 | }, | ||
4353 | "slash": { | 4379 | "slash": { |
4354 | "version": "3.0.0", | 4380 | "version": "3.0.0", |
4355 | "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", | 4381 | "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", |
diff --git a/package.json b/package.json index 45dfaa6..ff973c1 100644 --- a/package.json +++ b/package.json | |||
@@ -38,7 +38,8 @@ | |||
38 | "eslint": "^5.10.0", | 38 | "eslint": "^5.10.0", |
39 | "husky": "^6.0.0", | 39 | "husky": "^6.0.0", |
40 | "imagemin-cli": "^6.0.0", | 40 | "imagemin-cli": "^6.0.0", |
41 | "prettier": "^2.3.0" | 41 | "prettier": "^2.3.0", |
42 | "simple-git": "^2.39.0" | ||
42 | }, | 43 | }, |
43 | "husky": { | 44 | "husky": { |
44 | "hooks": { | 45 | "hooks": { |
diff --git a/scripts/package.js b/scripts/package.js index 82dfc81..dca3de6 100644 --- a/scripts/package.js +++ b/scripts/package.js | |||
@@ -5,6 +5,8 @@ const targz = require('targz'); | |||
5 | const fs = require('fs-extra'); | 5 | const fs = require('fs-extra'); |
6 | const path = require('path'); | 6 | const path = require('path'); |
7 | const sizeOf = require('image-size'); | 7 | const sizeOf = require('image-size'); |
8 | const simpleGit = require('simple-git'); | ||
9 | const pkgVersionChangedMatcher = new RegExp(/\n\+.*version.*/); | ||
8 | 10 | ||
9 | // Publicly availible link to this repository's recipe folder | 11 | // Publicly availible link to this repository's recipe folder |
10 | // Used for generating public icon URLs | 12 | // Used for generating public icon URLs |
@@ -33,10 +35,11 @@ const compress = (src, dest) => new Promise((resolve, reject) => { | |||
33 | // Let us work in an async environment | 35 | // Let us work in an async environment |
34 | (async () => { | 36 | (async () => { |
35 | // Create paths to important files | 37 | // Create paths to important files |
36 | const recipesFolder = path.join(__dirname, '../recipes'); | 38 | const repoRoot = path.join(__dirname, '..'); |
37 | const outputFolder = path.join(__dirname, '../archives'); | 39 | const recipesFolder = path.join(repoRoot, 'recipes'); |
38 | const allJson = path.join(__dirname, '../all.json'); | 40 | const outputFolder = path.join(repoRoot, 'archives'); |
39 | const featuredFile = path.join(__dirname, '../featured.json'); | 41 | const allJson = path.join(repoRoot, 'all.json'); |
42 | const featuredFile = path.join(repoRoot, 'featured.json'); | ||
40 | const featuredRecipes = await fs.readJSON(featuredFile); | 43 | const featuredRecipes = await fs.readJSON(featuredFile); |
41 | let recipeList = []; | 44 | let recipeList = []; |
42 | let unsuccessful = 0; | 45 | let unsuccessful = 0; |
@@ -45,6 +48,8 @@ const compress = (src, dest) => new Promise((resolve, reject) => { | |||
45 | await fs.emptyDir(outputFolder); | 48 | await fs.emptyDir(outputFolder); |
46 | await fs.remove(allJson); | 49 | await fs.remove(allJson); |
47 | 50 | ||
51 | const git = await simpleGit(repoRoot); | ||
52 | |||
48 | const availableRecipes = fs.readdirSync(recipesFolder, { withFileTypes: true }) | 53 | const availableRecipes = fs.readdirSync(recipesFolder, { withFileTypes: true }) |
49 | .filter(dir => dir.isDirectory()) | 54 | .filter(dir => dir.isDirectory()) |
50 | .map(dir => dir.name); | 55 | .map(dir => dir.name); |
@@ -54,14 +59,14 @@ const compress = (src, dest) => new Promise((resolve, reject) => { | |||
54 | const packageJson = path.join(recipeSrc, 'package.json'); | 59 | const packageJson = path.join(recipeSrc, 'package.json'); |
55 | const svgIcon = path.join(recipeSrc, 'icon.svg'); | 60 | const svgIcon = path.join(recipeSrc, 'icon.svg'); |
56 | const pngIcon = path.join(recipeSrc, 'icon.png'); | 61 | const pngIcon = path.join(recipeSrc, 'icon.png'); |
57 | 62 | ||
58 | // Check that package.json exists | 63 | // Check that package.json exists |
59 | if (!await fs.pathExists(packageJson)) { | 64 | if (!await fs.pathExists(packageJson)) { |
60 | console.log(`⚠️ Couldn't package "${recipe}": Folder doesn't contain a "package.json".`); | 65 | console.log(`⚠️ Couldn't package "${recipe}": Folder doesn't contain a "package.json".`); |
61 | unsuccessful++; | 66 | unsuccessful++; |
62 | continue; | 67 | continue; |
63 | } | 68 | } |
64 | 69 | ||
65 | // Check that icons exist | 70 | // Check that icons exist |
66 | const hasSvg = await fs.pathExists(svgIcon); | 71 | const hasSvg = await fs.pathExists(svgIcon); |
67 | const hasPng = await fs.pathExists(pngIcon); | 72 | const hasPng = await fs.pathExists(pngIcon); |
@@ -97,7 +102,7 @@ const compress = (src, dest) => new Promise((resolve, reject) => { | |||
97 | 102 | ||
98 | // Read package.json | 103 | // Read package.json |
99 | const config = await fs.readJson(packageJson) | 104 | const config = await fs.readJson(packageJson) |
100 | 105 | ||
101 | // Make sure it contains all required fields | 106 | // Make sure it contains all required fields |
102 | if (!config) { | 107 | if (!config) { |
103 | console.log(`⚠️ Couldn't package "${recipe}": Could not read or parse "package.json"`); | 108 | console.log(`⚠️ Couldn't package "${recipe}": Could not read or parse "package.json"`); |
@@ -119,14 +124,33 @@ const compress = (src, dest) => new Promise((resolve, reject) => { | |||
119 | if (!config.config || typeof config.config !== "object") { | 124 | if (!config.config || typeof config.config !== "object") { |
120 | configErrors.push("The recipe's package.json contains no 'config' object. This field should contain a configuration for your service."); | 125 | configErrors.push("The recipe's package.json contains no 'config' object. This field should contain a configuration for your service."); |
121 | } | 126 | } |
122 | 127 | ||
128 | const relativeRepoSrc = path.relative(repoRoot, recipeSrc); | ||
129 | // Check for changes in recipe's directory, and if changes are present, then the changes should contain a version bump | ||
130 | await git.diffSummary(relativeRepoSrc, (err, result) => { | ||
131 | if (err) { | ||
132 | configErrors.push(`Got the following error while checking for git changes: ${err}`); | ||
133 | } else if (result && (result.changed !== 0 || result.insertions !== 0 || result.deletions !== 0)) { | ||
134 | const pkgJsonRelative = path.relative(repoRoot, packageJson); | ||
135 | if (!result.files.find(({file}) => file === pkgJsonRelative)) { | ||
136 | configErrors.push(`Found changes in '${relativeRepoSrc}' without the corresponding version bump in '${pkgJsonRelative}'`); | ||
137 | } else { | ||
138 | git.diff(pkgJsonRelative, (_diffErr, diffResult) => { | ||
139 | if (diffResult && !pkgVersionChangedMatcher.test(diffResult)) { | ||
140 | configErrors.push(`Found changes in '${relativeRepoSrc}' without the corresponding version bump in '${pkgJsonRelative}' (found other changes though)`); | ||
141 | } | ||
142 | }); | ||
143 | } | ||
144 | } | ||
145 | }); | ||
146 | |||
123 | if (configErrors.length > 0) { | 147 | if (configErrors.length > 0) { |
124 | console.log(`⚠️ Couldn't package "${recipe}": There were errors in the recipe's package.json: | 148 | console.log(`⚠️ Couldn't package "${recipe}": There were errors in the recipe's package.json: |
125 | ${configErrors.reduce((str, err) => `${str}\n${err}`)}`); | 149 | ${configErrors.reduce((str, err) => `${str}\n${err}`)}`); |
126 | unsuccessful++; | 150 | unsuccessful++; |
127 | continue; | 151 | continue; |
128 | } | 152 | } |
129 | 153 | ||
130 | if (!await fs.exists(path.join(recipeSrc, 'webview.js'))) { | 154 | if (!await fs.exists(path.join(recipeSrc, 'webview.js'))) { |
131 | console.log(`⚠️ Couldn't package "${recipe}": The recipe doesn't contain a "webview.js"`); | 155 | console.log(`⚠️ Couldn't package "${recipe}": The recipe doesn't contain a "webview.js"`); |
132 | unsuccessful++; | 156 | unsuccessful++; |
@@ -137,10 +161,10 @@ const compress = (src, dest) => new Promise((resolve, reject) => { | |||
137 | unsuccessful++; | 161 | unsuccessful++; |
138 | continue; | 162 | continue; |
139 | } | 163 | } |
140 | 164 | ||
141 | // Package to .tar.gz | 165 | // Package to .tar.gz |
142 | compress(recipeSrc, path.join(outputFolder, `${config.id}.tar.gz`)); | 166 | compress(recipeSrc, path.join(outputFolder, `${config.id}.tar.gz`)); |
143 | 167 | ||
144 | // Add recipe to all.json | 168 | // Add recipe to all.json |
145 | const isFeatured = featuredRecipes.includes(config.id); | 169 | const isFeatured = featuredRecipes.includes(config.id); |
146 | const packageInfo = { | 170 | const packageInfo = { |
@@ -148,7 +172,7 @@ const compress = (src, dest) => new Promise((resolve, reject) => { | |||
148 | "featured": isFeatured, | 172 | "featured": isFeatured, |
149 | "id": config.id, | 173 | "id": config.id, |
150 | "name": config.name, | 174 | "name": config.name, |
151 | "version": config.version || '1.0.0', | 175 | "version": config.version, |
152 | "icons": { | 176 | "icons": { |
153 | "png": `${repo}${config.id}/icon.png`, | 177 | "png": `${repo}${config.id}/icon.png`, |
154 | "svg": `${repo}${config.id}/icon.svg`, | 178 | "svg": `${repo}${config.id}/icon.svg`, |
@@ -157,7 +181,6 @@ const compress = (src, dest) => new Promise((resolve, reject) => { | |||
157 | recipeList.push(packageInfo); | 181 | recipeList.push(packageInfo); |
158 | } | 182 | } |
159 | 183 | ||
160 | |||
161 | // Sort package list alphabetically | 184 | // Sort package list alphabetically |
162 | recipeList = recipeList.sort((a, b) => { | 185 | recipeList = recipeList.sort((a, b) => { |
163 | var textA = a.id.toLowerCase(); | 186 | var textA = a.id.toLowerCase(); |