@adobe/sizewatcher 1.2.0 → 1.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.js CHANGED
@@ -14,60 +14,5 @@
14
14
 
15
15
  'use strict';
16
16
 
17
- // index.js - main cli entry point
18
-
19
- const debug = require("debug")("sizewatcher");
20
- const gitCheckoutBeforeAndAfter = require("./lib/checkout");
21
- const compare = require("./lib/compare");
22
- const report = require("./lib/report");
23
- const Git = require("simple-git/promise");
24
-
25
- function printUsage() {
26
- console.log(`Usage: sizewatcher [<options>] [<before> [<after>]]`);
27
- console.log();
28
- console.log("Arguments:");
29
- console.log(" <before> Before branch/commit for comparison. Defaults to default branch or main/master.");
30
- console.log(" <after> After branch/commit for comparison. Defaults to current branch.");
31
- console.log();
32
- console.log("Options:");
33
- console.log(" -h Show help");
34
- }
35
-
36
- async function main(argv) {
37
- try {
38
- // yes, this should probably use a framework like oclif or yargs.
39
- // but cli arguments are very limited now and so manual handling is enough
40
- if (argv[0] === "-h") {
41
- printUsage();
42
- process.exit(1);
43
- }
44
-
45
- if (!await Git().checkIsRepo()) {
46
- throw new Error(`Not inside a git checkout: ${process.cwd()}`);
47
- }
48
-
49
- console.log(`Checking out git branches...`);
50
- const { before, after } = await gitCheckoutBeforeAndAfter(process.cwd(), argv[0], argv[1]);
51
-
52
- if (before.branch === after.branch) {
53
- console.log(`Branches are identical, nothing to compare (${before.branch}=${after.branch}). Compare selected branches using 'sizewatcher <before> <after>'.`);
54
- process.exit();
55
- }
56
-
57
- console.log(`Comparing changes from '${before.branch}' to '${after.branch}'\n`);
58
-
59
- const deltas = await compare(before, after);
60
-
61
- await report(deltas);
62
-
63
- } catch (e) {
64
- debug(e);
65
- console.error("Error:", e.message || e);
66
- process.exit(1);
67
- } finally {
68
- console.log("Done. Cleaning up...");
69
- }
70
- }
71
-
72
-
73
- main(process.argv.slice(2));
17
+ const sizewatcher = require("./lib/sizewatcher");
18
+ sizewatcher(process.argv.slice(2));
package/lib/checkout.js CHANGED
@@ -18,7 +18,7 @@ const debug = require("debug")("sizewatcher");
18
18
  const tmp = require("tmp");
19
19
  tmp.setGracefulCleanup();
20
20
  const path = require("path");
21
- const Git = require("simple-git/promise");
21
+ const Git = require("simple-git");
22
22
 
23
23
  async function getGitRoot(dir) {
24
24
  // --git-dir will return relative directories
@@ -43,10 +43,14 @@ async function currentSha(dir) {
43
43
  }
44
44
 
45
45
  async function getDefaultBranch(dir) {
46
- const originInfo = await Git(dir).remote(["show", "origin"]);
47
- const m = originInfo.match(/HEAD branch: (.*)$/m);
48
- if (m) {
49
- return m[1];
46
+ try {
47
+ const originInfo = await Git(dir).remote(["show", "origin"]);
48
+ const m = originInfo.match(/HEAD branch: (.*)$/m);
49
+ if (m) {
50
+ return m[1];
51
+ }
52
+ } catch (e) {
53
+ debug(`ignoring error in getDefaultBranch(): ${e.message}`);
50
54
  }
51
55
  }
52
56
 
@@ -54,22 +58,12 @@ async function hasBranch(dir, branch) {
54
58
  try {
55
59
  await Git(dir).revparse(["--verify", branch]);
56
60
  return branch;
57
- } catch (e) { // eslint-disable-line no-unused-vars
61
+ } catch (e) {
62
+ debug(`ignoring error in hasBranch(): ${e.message}`);
58
63
  return undefined;
59
64
  }
60
65
  }
61
66
 
62
- async function hasRemoteTrackingBranch(dir) {
63
- const git = Git(dir);
64
- try {
65
- const remoteBranch = await git.revparse(["--abbrev-ref", "--symbolic-full-name", "@{u}"]);
66
- console.log(remoteBranch);
67
- return true;
68
- } catch (e) { // eslint-disable-line no-unused-vars
69
- return false;
70
- }
71
- }
72
-
73
67
  async function getPullRequestBaseBranch() {
74
68
  return process.env.GITHUB_BASE_REF
75
69
  || (process.env.TRAVIS_PULL_REQUEST !== "false" && process.env.TRAVIS_BRANCH);
@@ -110,14 +104,18 @@ async function cloneLocalAndCheckout(from, to, branch) {
110
104
  const gitRoot = await getGitRoot(from);
111
105
 
112
106
  debug(`local cloning ${gitRoot} into ${to}`);
113
- await Git().clone(gitRoot, to, { local: true });
107
+ await Git().clone(gitRoot, to, { '--local' : true });
114
108
 
115
- debug(`checking out '${branch}'...`);
116
- await Git(to).checkout(branch);
109
+ if (branch) {
110
+ debug(`checking out '${branch}'...`);
111
+ await Git(to).checkout(branch);
112
+ }
117
113
  }
118
114
 
119
115
  async function gitCheckoutBeforeAndAfter(gitDir, beforeBranch, afterBranch) {
116
+ debug(`retrieving before branch: ${beforeBranch}`);
120
117
  beforeBranch = await getBeforeBranch(gitDir, beforeBranch);
118
+ debug(`retrieving after branch: ${afterBranch}`);
121
119
  afterBranch = await getAfterBranch(gitDir, afterBranch);
122
120
  if (beforeBranch === afterBranch) {
123
121
  return {
@@ -135,24 +133,33 @@ async function gitCheckoutBeforeAndAfter(gitDir, beforeBranch, afterBranch) {
135
133
  const tempDir = tmp.dirSync({unsafeCleanup: true}).name;
136
134
  debug(`temporary directory: ${tempDir}`);
137
135
 
136
+ // before checkout --------------------------------------------------------------
137
+
138
138
  const beforeDir = path.join(tempDir, "before");
139
- await cloneRemoteAndCheckout(gitDir, beforeDir, beforeBranch);
139
+
140
+ // we can use the faster local clone only if the "branch" is present locally
141
+ if (await hasBranch(gitDir, beforeBranch)) {
142
+ debug(`[before] using local cloning because existing checkout already has before branch '${beforeBranch}'`);
143
+ await cloneLocalAndCheckout(gitDir, beforeDir, beforeBranch);
144
+ } else {
145
+ debug(`[before] using remote cloning, as existing checkout does not have before branch '${beforeBranch}'`);
146
+ // ...otherwise need to do a full remote clone
147
+ await cloneRemoteAndCheckout(gitDir, beforeDir, beforeBranch);
148
+ }
149
+
150
+ // after checkout --------------------------------------------------------------
140
151
 
141
152
  const afterDir = path.join(tempDir, "after");
142
- if (process.env.CI || await hasRemoteTrackingBranch(afterDir)) {
143
- await cloneRemoteAndCheckout(gitDir, afterDir, afterBranch);
144
153
 
145
- } else {
146
- // if sizewatcher is run locally inside checkout
147
- await cloneLocalAndCheckout(gitDir, afterDir, afterBranch);
148
-
149
- try {
150
- // need to ensure before branch is available under local name
151
- await Git(afterDir).branch([beforeBranch, "-t", `origin/${beforeBranch}`]);
152
- } catch (e) {
153
- debug("ignoring error", e);
154
- }
154
+ debug(`[after] using local cloning`);
155
+ await cloneLocalAndCheckout(gitDir, afterDir);
156
+ try {
157
+ // need to ensure before branch is available under local name
158
+ await Git(afterDir).branch([beforeBranch, "-t", `origin/${beforeBranch}`]);
159
+ } catch (e) {
160
+ debug("ignoring error", e);
155
161
  }
162
+ debug(`[after] current branch: ${await currentBranch(afterDir)}`);
156
163
 
157
164
  debug("folders ready");
158
165
 
@@ -19,7 +19,7 @@ const du = require("du");
19
19
  const path = require("path");
20
20
  const fs = require("fs");
21
21
  const { execSync } = require("child_process");
22
- const Git = require("simple-git/promise");
22
+ const Git = require("simple-git");
23
23
 
24
24
  async function getSize(dir) {
25
25
  debug(`git garbage collection of '${dir}'...`);
@@ -50,7 +50,7 @@ module.exports = {
50
50
  compare: async function(before, after) {
51
51
  const beforeSize = await getSize(before.dir);
52
52
  const afterSize = await getSize(after.dir);
53
- const details = await largestCommits(after.dir, before.branch, after.branch);
53
+ const details = await largestCommits(after.dir, before.branch, after.sha);
54
54
 
55
55
  return {
56
56
  beforeSize,
@@ -24,19 +24,36 @@ function isEmptyObject(obj) {
24
24
  return Object.keys(obj).length === 0 && obj.constructor === Object;
25
25
  }
26
26
 
27
+ function hasPackageJson(dir) {
28
+ return fs.existsSync(path.join(dir, "package.json"));
29
+ }
30
+
27
31
  async function getSize(dir) {
32
+ if (!hasPackageJson(dir)) {
33
+ return 0;
34
+ }
28
35
  process.chdir(dir);
36
+
29
37
  debug(`installing node dependencies inside ${dir}...`);
30
38
  if (fs.existsSync("package-lock.json") || fs.existsSync("npm-shrinkwrap.json")) {
31
39
  execSync("npm ci");
32
40
  } else {
33
41
  execSync("npm install");
34
42
  }
35
- debug(`calculating folder size of ${dir}/node_modules...`);
36
- return du(path.join(dir, "node_modules"));
43
+
44
+ const nodeModules = path.join(dir, "node_modules");
45
+ if (fs.existsSync(nodeModules)) {
46
+ debug(`calculating folder size of ${nodeModules}...`);
47
+ return du(nodeModules);
48
+ } else {
49
+ return 0;
50
+ }
37
51
  }
38
52
 
39
53
  async function costOfModules(dir) {
54
+ if (!hasPackageJson(dir)) {
55
+ return "(no package.json)";
56
+ }
40
57
  process.chdir(dir);
41
58
 
42
59
  const pkgJsonPath = path.join(dir, "package.json");
@@ -62,7 +79,7 @@ async function costOfModules(dir) {
62
79
  module.exports = {
63
80
 
64
81
  shouldRun: async function(beforeDir, afterDir) {
65
- return fs.existsSync(path.join(afterDir, "package.json"));
82
+ return hasPackageJson(beforeDir) || hasPackageJson(afterDir);
66
83
  },
67
84
 
68
85
  compare: async function(before, after) {
package/lib/compare.js CHANGED
@@ -136,6 +136,7 @@ function process(deltas) {
136
136
  };
137
137
 
138
138
  for (const d of deltas) {
139
+ debug("processing delta:", d);
139
140
  if (d.error) {
140
141
  summary.error++;
141
142
  continue;
@@ -147,14 +148,14 @@ function process(deltas) {
147
148
  };
148
149
 
149
150
  let increase;
150
- if (d.beforeSize <= 0) {
151
- if (d.afterSize <= 0) {
152
- increase = 0;
153
- } else {
154
- increase = -100;
155
- }
151
+ if (d.beforeSize <= 0 && d.afterSize <= 0) {
152
+ increase = 0;
153
+ } else if (d.afterSize <= 0) {
154
+ increase = -100;
155
+ } else if (d.beforeSize <= 0) {
156
+ increase = 100;
156
157
  } else {
157
- increase = d.beforeSize <= 0 ? -100 : (d.afterSize - d.beforeSize) / d.beforeSize * 100;
158
+ increase = (d.afterSize - d.beforeSize) / d.beforeSize * 100;
158
159
  }
159
160
  d.increase = increase.toFixed(1);
160
161
 
@@ -0,0 +1,74 @@
1
+ /*
2
+ * Copyright 2020 Adobe. All rights reserved.
3
+ * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
+ * you may not use this file except in compliance with the License. You may obtain a copy
5
+ * of the License at http://www.apache.org/licenses/LICENSE-2.0
6
+ *
7
+ * Unless required by applicable law or agreed to in writing, software distributed under
8
+ * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9
+ * OF ANY KIND, either express or implied. See the License for the specific language
10
+ * governing permissions and limitations under the License.
11
+ */
12
+
13
+ 'use strict';
14
+
15
+ // main cli entry point
16
+
17
+ const debug = require("debug")("sizewatcher");
18
+ const gitCheckoutBeforeAndAfter = require("./checkout");
19
+ const compare = require("./compare");
20
+ const report = require("./report");
21
+ const Git = require("simple-git");
22
+
23
+ function printUsage() {
24
+ console.error(`Usage: sizewatcher [<options>] [<before> [<after>]]`);
25
+ console.error();
26
+ console.error("Arguments:");
27
+ console.error(" <before> Before branch/commit for comparison. Defaults to default branch or main/master.");
28
+ console.error(" <after> After branch/commit for comparison. Defaults to current branch.");
29
+ console.error();
30
+ console.error("Options:");
31
+ console.error(" -h Show help");
32
+ }
33
+
34
+ async function sizewatcher(argv) {
35
+ try {
36
+ if (!argv) argv = [];
37
+
38
+ // yes, this should probably use a framework like oclif or yargs.
39
+ // but cli arguments are very limited now and so manual handling is enough
40
+ if (argv[0] === "-h") {
41
+ printUsage();
42
+ return process.exit(1);
43
+ }
44
+
45
+ debug(`Running inside ${process.cwd()}`);
46
+
47
+ if (!await Git().checkIsRepo()) {
48
+ throw new Error(`Not inside a git checkout: ${process.cwd()}`);
49
+ }
50
+
51
+ console.log(`Checking out git branches...`);
52
+ const { before, after } = await gitCheckoutBeforeAndAfter(process.cwd(), argv[0], argv[1]);
53
+
54
+ if (before.branch === after.branch) {
55
+ console.log(`Branches are identical, nothing to compare (${before.branch}=${after.branch}). Compare selected branches using 'sizewatcher <before> <after>'.`);
56
+ return process.exit();
57
+ }
58
+
59
+ console.log(`Comparing changes from '${before.branch}' to '${after.branch}'\n`);
60
+
61
+ const deltas = await compare(before, after);
62
+
63
+ await report(deltas);
64
+
65
+ console.log("Done. Cleaning up...");
66
+
67
+ } catch (e) {
68
+ debug(e);
69
+ console.error("Error:", e.message || e);
70
+ return process.exit(1);
71
+ }
72
+ }
73
+
74
+ module.exports = sizewatcher;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adobe/sizewatcher",
3
- "version": "1.2.0",
3
+ "version": "1.2.1",
4
4
  "description": "Warns if your pull requests introduce large size increases.",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -30,7 +30,8 @@
30
30
  "eslint": "^7.1.0",
31
31
  "mocha": "^7.2.0",
32
32
  "mock-fs": "^4.13.0",
33
- "nyc": "^15.1.0"
33
+ "nyc": "^15.1.0",
34
+ "supports-color": "^8.1.1"
34
35
  },
35
36
  "dependencies": {
36
37
  "@octokit/rest": "^18.0.3",
@@ -41,7 +42,7 @@
41
42
  "js-yaml": "^3.14.0",
42
43
  "pretty-bytes": "^5.3.0",
43
44
  "require-dir": "^1.2.0",
44
- "simple-git": "^2.5.0",
45
+ "simple-git": "^3.7.1",
45
46
  "tmp": "^0.2.1",
46
47
  "xbytes": "^1.6.2"
47
48
  }