@backstage/cli 0.29.0-next.0 → 0.29.0-next.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/CHANGELOG.md CHANGED
@@ -1,5 +1,34 @@
1
1
  # @backstage/cli
2
2
 
3
+ ## 0.29.0-next.1
4
+
5
+ ### Minor Changes
6
+
7
+ - 6819f8c: Added a new optimization to the `repo test` command that will filter out unused packages in watch mode if all provide filters are paths that point from the repo root. This significantly speeds up running individual tests from the repo root in a large workspace, for example:
8
+
9
+ ```sh
10
+ yarn test packages/app/src/App.test.tsx
11
+ ```
12
+
13
+ ### Patch Changes
14
+
15
+ - 4046d53: Fixed an issue where the `--successCache` option for the `repo test` and `repo lint` commands would be include the workspace path in generated cache keys. This previously broke caching in environments where the workspace path varies across builds.
16
+ - 6b2888c: Fixed an issue with the `--successCache` flag for `repo test` where the tree hash for the wrong package directory would sometimes be used to generate the cache key.
17
+ - 6266ed3: Updated dependency `del` to `^8.0.0`.
18
+ - 4046d53: Fixed an issue with the `repo lint` command where the cache key for the `--successCache` option would not properly ignore files that should be ignored according to `.eslintignore`s.
19
+ - 702f41d: Bumped dev dependencies `@types/node`
20
+ - Updated dependencies
21
+ - @backstage/cli-common@0.1.15-next.0
22
+ - @backstage/catalog-model@1.7.0
23
+ - @backstage/cli-node@0.2.10-next.0
24
+ - @backstage/config@1.2.0
25
+ - @backstage/config-loader@1.9.2-next.0
26
+ - @backstage/errors@1.2.4
27
+ - @backstage/eslint-plugin@0.1.10
28
+ - @backstage/integration@1.15.1
29
+ - @backstage/release-manifests@0.0.11
30
+ - @backstage/types@1.1.1
31
+
3
32
  ## 0.29.0-next.0
4
33
 
5
34
  ### Minor Changes
package/config/jest.js CHANGED
@@ -264,7 +264,7 @@ async function getProjectConfig(targetPath, extraConfig, extraOptions) {
264
264
  .createHash('sha256')
265
265
  .update(version)
266
266
  .update(Buffer.alloc(1))
267
- .update(JSON.stringify(config.transform))
267
+ .update(JSON.stringify(config.transform).replaceAll(paths.targetRoot, ''))
268
268
  .digest('hex');
269
269
  config.id = `backstage_cli_${configHash}`;
270
270
  }
@@ -326,7 +326,7 @@ async function getRootConfig() {
326
326
  ),
327
327
  ).then(_ => _.flat());
328
328
 
329
- let configs = await Promise.all(
329
+ let projects = await Promise.all(
330
330
  projectPaths.flat().map(async projectPath => {
331
331
  const packagePath = path.resolve(projectPath, 'package.json');
332
332
  if (!(await fs.pathExists(packagePath))) {
@@ -357,12 +357,16 @@ async function getRootConfig() {
357
357
 
358
358
  const cache = global.__backstageCli_jestSuccessCache;
359
359
  if (cache) {
360
- configs = await cache.filterConfigs(configs, globalRootConfig);
360
+ projects = await cache.filterConfigs(projects, globalRootConfig);
361
+ }
362
+ const watchProjectFilter = global.__backstageCli_watchProjectFilter;
363
+ if (watchProjectFilter) {
364
+ projects = await watchProjectFilter.filter(projects);
361
365
  }
362
366
 
363
367
  return {
364
368
  rootDir: paths.targetRoot,
365
- projects: configs,
369
+ projects,
366
370
  testResultsProcessor: cache
367
371
  ? require.resolve('./jestCacheResultProcessor.cjs')
368
372
  : undefined,
@@ -89,7 +89,7 @@ async function command(opts, cmd) {
89
89
  const crypto = require("crypto");
90
90
  const globby = require("globby");
91
91
  const { readFile } = require("fs/promises");
92
- const { relative: workerRelativePath } = require("path");
92
+ const workerPath = require("path");
93
93
  return async ({
94
94
  fullDir,
95
95
  relativeDir,
@@ -114,15 +114,19 @@ async function command(opts, cmd) {
114
114
  hash.update(parentHash);
115
115
  hash.update("\0");
116
116
  for (const path of result.sort()) {
117
- if (await eslint.isPathIgnored(path)) {
117
+ const absPath = workerPath.resolve(rootDir, path);
118
+ const pathInPackage = workerPath.relative(fullDir, absPath);
119
+ if (await eslint.isPathIgnored(pathInPackage)) {
118
120
  continue;
119
121
  }
120
- hash.update(workerRelativePath(fullDir, path));
122
+ hash.update(pathInPackage);
121
123
  hash.update("\0");
122
- hash.update(await readFile(path));
124
+ hash.update(await readFile(absPath));
123
125
  hash.update("\0");
124
126
  hash.update(
125
- JSON.stringify(await eslint.calculateConfigForFile(path))
127
+ JSON.stringify(
128
+ await eslint.calculateConfigForFile(pathInPackage)
129
+ ).replaceAll(rootDir, "")
126
130
  );
127
131
  hash.update("\0");
128
132
  }
@@ -3,6 +3,7 @@
3
3
  var os = require('os');
4
4
  var crypto = require('node:crypto');
5
5
  var yargs = require('yargs');
6
+ var jestCli = require('jest-cli');
6
7
  var path = require('path');
7
8
  var cliNode = require('@backstage/cli-node');
8
9
  var paths = require('../../lib/paths.cjs.js');
@@ -17,23 +18,30 @@ var crypto__default = /*#__PURE__*/_interopDefaultCompat(crypto);
17
18
  var yargs__default = /*#__PURE__*/_interopDefaultCompat(yargs);
18
19
 
19
20
  async function readPackageTreeHashes(graph) {
20
- const pkgs = Array.from(graph.values());
21
+ const pkgs = Array.from(graph.values()).map((pkg) => ({
22
+ ...pkg,
23
+ path: path.relative(paths.paths.targetRoot, pkg.dir)
24
+ }));
21
25
  const output = await run.runPlain(
22
26
  "git",
23
27
  "ls-tree",
24
- "--object-only",
28
+ '--format="%(objectname)=%(path)"',
25
29
  "HEAD",
26
30
  "--",
27
- ...pkgs.map((pkg) => path.relative(paths.paths.targetRoot, pkg.dir))
31
+ ...pkgs.map((pkg) => pkg.path)
28
32
  );
29
- const treeShaList = output.trim().split(/\r?\n/);
30
- if (treeShaList.length !== pkgs.length) {
31
- throw new Error(
32
- `Error listing project git tree hashes, output length does not equal input length`
33
- );
34
- }
35
33
  const map = new Map(
36
- pkgs.map((pkg, i) => [pkg.packageJson.name, treeShaList[i]])
34
+ output.trim().split(/\r?\n/).map((line) => {
35
+ const [itemSha, ...itemPathParts] = line.split("=");
36
+ const itemPath = itemPathParts.join("=");
37
+ const pkg = pkgs.find((p) => p.path === itemPath);
38
+ if (!pkg) {
39
+ throw new Error(
40
+ `Unexpectedly missing tree sha entry for path ${itemPath}`
41
+ );
42
+ }
43
+ return [pkg.packageJson.name, itemSha];
44
+ })
37
45
  );
38
46
  return (pkgName) => {
39
47
  const sha = map.get(pkgName);
@@ -83,6 +91,7 @@ function removeOptionArg(args, option, size = 2) {
83
91
  } while (changed);
84
92
  }
85
93
  async function command(opts, cmd) {
94
+ const testGlobal = global;
86
95
  let parent = cmd;
87
96
  while (parent.parent) {
88
97
  parent = parent.parent;
@@ -90,21 +99,44 @@ async function command(opts, cmd) {
90
99
  const allArgs = parent.args;
91
100
  const args = allArgs.slice(allArgs.indexOf("test") + 1);
92
101
  const hasFlags = createFlagFinder(args);
102
+ const { _: parsedArgs } = await yargs__default.default(args).options(jestCli.yargsOptions).argv;
93
103
  if (!hasFlags("-c", "--config")) {
94
104
  args.push("--config", paths.paths.resolveOwn("config/jest.js"));
95
105
  }
96
106
  if (!hasFlags("--passWithNoTests")) {
97
107
  args.push("--passWithNoTests");
98
108
  }
109
+ let isSingleWatchMode = args.includes("--watch");
99
110
  if (!opts.since && !process.env.CI && !hasFlags("--coverage", "--watch", "--watchAll")) {
100
111
  const isGitRepo = () => run.runCheck("git", "rev-parse", "--is-inside-work-tree");
101
112
  const isMercurialRepo = () => run.runCheck("hg", "--cwd", ".", "root");
102
113
  if (await isGitRepo() || await isMercurialRepo()) {
114
+ isSingleWatchMode = true;
103
115
  args.push("--watch");
104
116
  } else {
105
117
  args.push("--watchAll");
106
118
  }
107
119
  }
120
+ if (isSingleWatchMode && parsedArgs.length > 0) {
121
+ testGlobal.__backstageCli_watchProjectFilter = {
122
+ async filter(projectConfigs) {
123
+ const selectedProjects2 = [];
124
+ const usedArgs = /* @__PURE__ */ new Set();
125
+ for (const project of projectConfigs) {
126
+ for (const arg of parsedArgs) {
127
+ if (cliCommon.isChildPath(project.rootDir, String(arg))) {
128
+ selectedProjects2.push(project);
129
+ usedArgs.add(arg);
130
+ }
131
+ }
132
+ }
133
+ if (usedArgs.size !== parsedArgs.length) {
134
+ return projectConfigs;
135
+ }
136
+ return selectedProjects2;
137
+ }
138
+ };
139
+ }
108
140
  if (!hasFlags("--workerIdleMemoryLimit")) {
109
141
  args.push("--workerIdleMemoryLimit=1000M");
110
142
  }
@@ -153,11 +185,9 @@ async function command(opts, cmd) {
153
185
  args.push("--help");
154
186
  process.stdout._handle.setBlocking(true);
155
187
  }
156
- const jestCli = require("jest-cli");
157
188
  if (opts.successCache) {
158
189
  removeOptionArg(args, "--successCache", 1);
159
190
  removeOptionArg(args, "--successCacheDir");
160
- const { _: parsedArgs } = await yargs__default.default(args).options(jestCli.yargsOptions).argv;
161
191
  if (parsedArgs.length > 0) {
162
192
  throw new Error(
163
193
  `The --successCache flag can not be combined with the following arguments: ${parsedArgs.join(
@@ -174,8 +204,7 @@ async function command(opts, cmd) {
174
204
  const graph = await getPackageGraph();
175
205
  const projectHashes = /* @__PURE__ */ new Map();
176
206
  const outputSuccessCache = new Array();
177
- const globalWithCache = global;
178
- globalWithCache.__backstageCli_jestSuccessCache = {
207
+ testGlobal.__backstageCli_jestSuccessCache = {
179
208
  // This is called by `config/jest.js` after the project configs have been gathered
180
209
  async filterConfigs(projectConfigs, globalRootConfig) {
181
210
  const cacheEntries = await cache.read();
@@ -188,7 +217,9 @@ async function command(opts, cmd) {
188
217
  baseHash.update("\0");
189
218
  baseHash.update(process.version);
190
219
  baseHash.update("\0");
191
- baseHash.update(JSON.stringify(globalRootConfig));
220
+ baseHash.update(
221
+ SuccessCache.SuccessCache.trimPaths(JSON.stringify(globalRootConfig))
222
+ );
192
223
  const baseSha = baseHash.digest("hex");
193
224
  return projectConfigs.filter((project) => {
194
225
  const packageName = project.displayName;
@@ -206,7 +237,7 @@ async function command(opts, cmd) {
206
237
  const depHash = getPackageTreeHash(depPkg.name);
207
238
  hash.update(`${depName}:${depHash}`);
208
239
  }
209
- hash.update(JSON.stringify(project));
240
+ hash.update(SuccessCache.SuccessCache.trimPaths(JSON.stringify(project)));
210
241
  hash.update(lockfile.getDependencyTreeHash(packageName));
211
242
  const sha = hash.digest("hex");
212
243
  projectHashes.set(packageName, sha);
@@ -2,6 +2,7 @@
2
2
 
3
3
  var fs = require('fs-extra');
4
4
  var node_path = require('node:path');
5
+ var paths = require('../paths.cjs.js');
5
6
 
6
7
  function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
7
8
 
@@ -11,6 +12,14 @@ const DEFAULT_CACHE_BASE_PATH = "node_modules/.cache/backstage-cli";
11
12
  const CACHE_MAX_AGE_MS = 7 * 24 * 36e5;
12
13
  class SuccessCache {
13
14
  #path;
15
+ /**
16
+ * Trim any occurrences of the workspace root path from the input string. This
17
+ * is useful to ensure stable hashes that don't vary based on the workspace
18
+ * location.
19
+ */
20
+ static trimPaths(input) {
21
+ return input.replaceAll(paths.paths.targetRoot, "");
22
+ }
14
23
  constructor(name, basePath) {
15
24
  this.#path = node_path.resolve(basePath ?? DEFAULT_CACHE_BASE_PATH, name);
16
25
  }
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var version = "0.5.3-next.0";
3
+ var version = "0.5.3-next.1";
4
4
 
5
5
  exports.version = version;
6
6
  //# sourceMappingURL=package.json.cjs.js.map
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var version = "1.0.2-next.0";
3
+ var version = "1.0.2-next.1";
4
4
 
5
5
  exports.version = version;
6
6
  //# sourceMappingURL=package.json.cjs.js.map
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var version = "1.0.3-next.0";
3
+ var version = "1.0.3-next.1";
4
4
 
5
5
  exports.version = version;
6
6
  //# sourceMappingURL=package.json.cjs.js.map
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var version = "0.29.0-next.0";
3
+ var version = "0.29.0-next.1";
4
4
  var dependencies = {
5
5
  "@backstage/catalog-model": "workspace:^",
6
6
  "@backstage/cli-common": "workspace:^",
@@ -144,7 +144,7 @@ var devDependencies = {
144
144
  "@types/fs-extra": "^11.0.0",
145
145
  "@types/http-proxy": "^1.17.4",
146
146
  "@types/inquirer": "^8.1.3",
147
- "@types/node": "^18.17.8",
147
+ "@types/node": "^20.16.0",
148
148
  "@types/npm-packlist": "^3.0.0",
149
149
  "@types/recursive-readdir": "^2.2.0",
150
150
  "@types/rollup-plugin-peer-deps-external": "^2.2.0",
@@ -155,7 +155,7 @@ var devDependencies = {
155
155
  "@types/webpack-sources": "^3.2.3",
156
156
  "@types/yarnpkg__lockfile": "^1.1.4",
157
157
  "@vitejs/plugin-react": "^4.3.1",
158
- del: "^7.0.0",
158
+ del: "^8.0.0",
159
159
  msw: "^1.0.0",
160
160
  nodemon: "^3.0.1",
161
161
  vite: "^5.0.0",
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var version = "0.16.0-next.0";
3
+ var version = "0.16.0-next.1";
4
4
 
5
5
  exports.version = version;
6
6
  //# sourceMappingURL=package.json.cjs.js.map
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var version = "1.1.3-next.0";
3
+ var version = "1.1.3-next.1";
4
4
 
5
5
  exports.version = version;
6
6
  //# sourceMappingURL=package.json.cjs.js.map
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var version = "1.7.0";
3
+ var version = "1.7.1-next.0";
4
4
 
5
5
  exports.version = version;
6
6
  //# sourceMappingURL=package.json.cjs.js.map
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var version = "0.6.0";
3
+ var version = "0.6.1-next.0";
4
4
 
5
5
  exports.version = version;
6
6
  //# sourceMappingURL=package.json.cjs.js.map
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var version = "0.24.0-next.0";
3
+ var version = "0.24.0-next.1";
4
4
 
5
5
  exports.version = version;
6
6
  //# sourceMappingURL=package.json.cjs.js.map
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var version = "0.2.2-next.0";
3
+ var version = "0.2.2-next.1";
4
4
 
5
5
  exports.version = version;
6
6
  //# sourceMappingURL=package.json.cjs.js.map
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var version = "1.14.0-next.0";
3
+ var version = "1.14.0-next.1";
4
4
 
5
5
  exports.version = version;
6
6
  //# sourceMappingURL=package.json.cjs.js.map
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var version = "0.5.1-next.0";
3
+ var version = "0.5.1-next.1";
4
4
 
5
5
  exports.version = version;
6
6
  //# sourceMappingURL=package.json.cjs.js.map
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var version = "0.1.15-next.0";
3
+ var version = "0.1.15-next.1";
4
4
 
5
5
  exports.version = version;
6
6
  //# sourceMappingURL=package.json.cjs.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@backstage/cli",
3
- "version": "0.29.0-next.0",
3
+ "version": "0.29.0-next.1",
4
4
  "description": "CLI for developing Backstage plugins and apps",
5
5
  "backstage": {
6
6
  "role": "cli"
@@ -43,10 +43,10 @@
43
43
  },
44
44
  "dependencies": {
45
45
  "@backstage/catalog-model": "1.7.0",
46
- "@backstage/cli-common": "0.1.14",
47
- "@backstage/cli-node": "0.2.9",
46
+ "@backstage/cli-common": "0.1.15-next.0",
47
+ "@backstage/cli-node": "0.2.10-next.0",
48
48
  "@backstage/config": "1.2.0",
49
- "@backstage/config-loader": "1.9.1",
49
+ "@backstage/config-loader": "1.9.2-next.0",
50
50
  "@backstage/errors": "1.2.4",
51
51
  "@backstage/eslint-plugin": "0.1.10",
52
52
  "@backstage/integration": "1.15.1",
@@ -159,22 +159,22 @@
159
159
  },
160
160
  "devDependencies": {
161
161
  "@backstage/backend-common": "^0.25.0",
162
- "@backstage/backend-plugin-api": "1.0.2-next.0",
163
- "@backstage/backend-test-utils": "1.0.3-next.0",
162
+ "@backstage/backend-plugin-api": "1.0.2-next.1",
163
+ "@backstage/backend-test-utils": "1.0.3-next.1",
164
164
  "@backstage/catalog-client": "1.8.0-next.0",
165
165
  "@backstage/config": "1.2.0",
166
166
  "@backstage/core-app-api": "1.15.1",
167
- "@backstage/core-components": "0.16.0-next.0",
167
+ "@backstage/core-components": "0.16.0-next.1",
168
168
  "@backstage/core-plugin-api": "1.10.0",
169
- "@backstage/dev-utils": "1.1.3-next.0",
169
+ "@backstage/dev-utils": "1.1.3-next.1",
170
170
  "@backstage/errors": "1.2.4",
171
- "@backstage/plugin-auth-backend": "0.24.0-next.0",
172
- "@backstage/plugin-auth-backend-module-guest-provider": "0.2.2-next.0",
173
- "@backstage/plugin-catalog-node": "1.14.0-next.0",
174
- "@backstage/plugin-scaffolder-node": "0.5.1-next.0",
175
- "@backstage/plugin-scaffolder-node-test-utils": "0.1.15-next.0",
176
- "@backstage/test-utils": "1.7.0",
177
- "@backstage/theme": "0.6.0",
171
+ "@backstage/plugin-auth-backend": "0.24.0-next.1",
172
+ "@backstage/plugin-auth-backend-module-guest-provider": "0.2.2-next.1",
173
+ "@backstage/plugin-catalog-node": "1.14.0-next.1",
174
+ "@backstage/plugin-scaffolder-node": "0.5.1-next.1",
175
+ "@backstage/plugin-scaffolder-node-test-utils": "0.1.15-next.1",
176
+ "@backstage/test-utils": "1.7.1-next.0",
177
+ "@backstage/theme": "0.6.1-next.0",
178
178
  "@rspack/core": "^1.0.10",
179
179
  "@rspack/dev-server": "^1.0.9",
180
180
  "@rspack/plugin-react-refresh": "^1.0.0",
@@ -184,7 +184,7 @@
184
184
  "@types/fs-extra": "^11.0.0",
185
185
  "@types/http-proxy": "^1.17.4",
186
186
  "@types/inquirer": "^8.1.3",
187
- "@types/node": "^18.17.8",
187
+ "@types/node": "^20.16.0",
188
188
  "@types/npm-packlist": "^3.0.0",
189
189
  "@types/recursive-readdir": "^2.2.0",
190
190
  "@types/rollup-plugin-peer-deps-external": "^2.2.0",
@@ -195,7 +195,7 @@
195
195
  "@types/webpack-sources": "^3.2.3",
196
196
  "@types/yarnpkg__lockfile": "^1.1.4",
197
197
  "@vitejs/plugin-react": "^4.3.1",
198
- "del": "^7.0.0",
198
+ "del": "^8.0.0",
199
199
  "msw": "^1.0.0",
200
200
  "nodemon": "^3.0.1",
201
201
  "vite": "^5.0.0",