diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index cc20f4fadfe..f49db00ae9c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -11,6 +11,7 @@ The `redhat-developer/rhdh-plugins` repository is designed as a collaborative sp - [Forking the Repository](#forking-the-repository) - [Developing Plugins in Workspaces](#developing-plugins-in-workspaces) - [Coding Guidelines](#coding-guidelines) + - [yarn fix](#yarn-fix) - [Versioning](#versioning) - [Creating Changesets](#creating-changesets) - [Release](#release) @@ -80,6 +81,27 @@ For consistency across the monorepo, we suggest following the same Yarn setup as All code is formatted with `prettier` using the configuration in the repo. If possible we recommend configuring your editor to format automatically, but you can also use the `yarn prettier --write ` command to format files. +### yarn fix + +From a workspace root (`workspaces/`), run `yarn fix` before you consider the work done. Do not run it from the repository root; each workspace has its own install and its own `yarn fix`. + +The command delegates to `backstage-cli repo fix`, then runs additional fixers when they are available. Execution order is defined in `scripts/workspace-fix.mjs`: + +1. `backstage-cli repo fix` (pass `--publish` with `rhdhFix.publish` or `--publish`) +2. `sort-package-json` (skipped unless the workspace depends on it) +3. `backstage-cli repo lint --fix` +4. `markdownlint --fix` (skipped unless the workspace depends on it) +5. `prettier --write .` (always last among formatters) +6. `knip --fix` (opt-in only: `rhdhFix.knip` or `--knip`) + +`yarn fix` exits 0 when every run fixer succeeds, even if files changed. It exits non-zero if a fixer fails. Missing optional fixers are skipped, not treated as failures. + +`yarn fix --check` runs only `backstage-cli repo fix --check` (and `--publish` when configured). CI uses this mode; lint, prettier, and publish validation run as separate workflow steps. + +Memory-heavy fixers run with `NODE_OPTIONS=--max-old-space-size=8192`, matching CI. Workspaces that build dynamic plugin bundles should list `dist-dynamic` and `dist-scalprum` in `.eslintignore` and `.prettierignore` so `repo lint --fix` and `prettier --write` do not traverse generated output. If a workspace still runs out of memory during `repo lint --fix`, set a higher value in `rhdhFix.nodeOptions` in that workspace's `package.json`. + +To add a new fixer, change `scripts/workspace-fix.mjs` only. Workspace `package.json` files should keep `"fix": "node ../../scripts/workspace-fix.mjs"`. The `noop` workspace is the exception and stays a no-op. + ## Versioning For the versioning all packages in this repository are following the semantic versioning standard enforced through Changesets. This is the same approach as in the “backstage/community-plugins" repository. If this is your first time working with Changesets checkout [this documentation](https://github.com/backstage/backstage/blob/master/CONTRIBUTING.md#creating-changesets) or read a quick summary below. diff --git a/README.md b/README.md index 31fe4e541d0..cda51284bfb 100644 --- a/README.md +++ b/README.md @@ -13,3 +13,7 @@ Contributions are welcome! To contribute a plugin, please follow the guidelines ## Plugins Workflow The `rhdh-plugins` repository is organized into multiple workspaces, with each workspace containing a plugin or a set of related plugins. Each workspace operates independently, with its own release cycle and dependencies managed via npm. When a new changeset is added (each workspace has its own `.changesets` directory), a "Version packages ($workspace_name)" PR is automatically generated. Merging this PR triggers the release of all plugins in the workspace and updates the corresponding `CHANGELOG` files. + +## yarn fix + +From a workspace directory (`workspaces/`), run `yarn fix` to auto-correct fixable package, lint, and format issues. The pipeline is defined once in `scripts/workspace-fix.mjs`. See [CONTRIBUTING.md](CONTRIBUTING.md#yarn-fix) for the fixer order and how to add a new fixer. diff --git a/package.json b/package.json index 816dd755ca7..bc075e95e76 100644 --- a/package.json +++ b/package.json @@ -8,6 +8,7 @@ }, "scripts": { "create-workspace": "rhdh-repo-tools workspace create", + "test:workspace-fix": "node --test scripts/workspace-fix.test.mjs", "postinstall": "husky", "prettier:check": "prettier --check .", "prettier:fix": "prettier --write ." diff --git a/scripts/workspace-fix.mjs b/scripts/workspace-fix.mjs new file mode 100644 index 00000000000..a2c72719b6a --- /dev/null +++ b/scripts/workspace-fix.mjs @@ -0,0 +1,331 @@ +/* + * Copyright Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { spawn } from 'node:child_process'; +import { existsSync, readFileSync } from 'node:fs'; +import { resolve } from 'node:path'; +import { pathToFileURL } from 'node:url'; + +export const REPO_ROOT_PACKAGE_NAME = '@redhat-developer/rhdh-plugins'; + +// Match .github/workflows/ci.yml so local yarn fix behaves like CI. +export const DEFAULT_NODE_OPTIONS = '--max-old-space-size=8192'; + +const MEMORY_HEAVY_STEPS = new Set([ + 'repo-fix', + 'lint-fix', + 'prettier', + 'knip', +]); + +const MARKDOWNLINT_PACKAGES = [ + 'markdownlint-cli2', + 'markdownlint-cli', + 'markdownlint', +]; + +/** + * Deterministic fixer order. Add new fixers here — workspace package.json + * scripts should keep pointing at this file. + * + * 1. backstage-cli repo fix (package.json exports / metadata) + * 2. sort-package-json (optional; skipped unless installed) + * 3. backstage-cli repo lint --fix + * 4. markdownlint --fix (optional; skipped unless installed) + * 5. prettier --write (last formatter so eslint and prettier do not fight) + * 6. knip --fix (opt-in only; skipped unless rhdhFix.knip or --knip) + */ +export const FIXER_ORDER = [ + 'repo-fix', + 'sort-package-json', + 'lint-fix', + 'markdownlint', + 'prettier', + 'knip', +]; + +export function parseArgs(argv) { + const extra = []; + const flags = { publish: false, knip: false, check: false, help: false }; + for (const arg of argv) { + if (arg === '--publish') { + flags.publish = true; + } else if (arg === '--knip') { + flags.knip = true; + } else if (arg === '--check') { + flags.check = true; + } else if (arg === '--help' || arg === '-h') { + flags.help = true; + } else if (arg.startsWith('-')) { + throw Object.assign( + new Error(`Unknown flag '${arg}'. Use --check, --publish, or --knip.`), + { exitCode: 1 }, + ); + } else { + extra.push(arg); + } + } + return { flags, extra }; +} + +export function readPackageJson(cwd) { + const pkgPath = resolve(cwd, 'package.json'); + if (!existsSync(pkgPath)) { + throw Object.assign( + new Error( + `No package.json in ${cwd}. Run yarn fix from a workspace root (workspaces/).`, + ), + { exitCode: 1 }, + ); + } + return JSON.parse(readFileSync(pkgPath, 'utf8')); +} + +export function assertWorkspaceRoot(pkg) { + if (pkg.name === REPO_ROOT_PACKAGE_NAME) { + throw Object.assign( + new Error( + 'yarn fix is per workspace. cd into workspaces/ and run yarn fix there.', + ), + { exitCode: 1 }, + ); + } + if (!pkg.workspaces) { + throw Object.assign( + new Error( + 'yarn fix must run from a workspace root that declares a workspaces field.', + ), + { exitCode: 1 }, + ); + } +} + +export function resolveConfig(pkg, flags) { + const fromPkg = pkg.rhdhFix ?? {}; + return { + check: Boolean(flags.check), + publish: Boolean(fromPkg.publish || flags.publish), + knip: Boolean(fromPkg.knip || flags.knip), + nodeOptions: fromPkg.nodeOptions, + }; +} + +export function mergeNodeOptions(existing, additional, options = {}) { + const { overrideHeapLimit = false } = options; + if (!additional) { + return existing; + } + if (!existing) { + return additional; + } + if (existing.includes('max-old-space-size')) { + if (overrideHeapLimit) { + const replacement = additional.match(/--max-old-space-size=\d+/)?.[0]; + if (replacement) { + return existing.replace(/--max-old-space-size=\d+/, replacement); + } + } + return existing; + } + return `${existing} ${additional}`.trim(); +} + +export function resolveSpawnEnv(step, config, baseEnv = process.env) { + const extra = + config.nodeOptions ?? + (MEMORY_HEAVY_STEPS.has(step.id) ? DEFAULT_NODE_OPTIONS : undefined); + if (!extra) { + return baseEnv; + } + return { + ...baseEnv, + NODE_OPTIONS: mergeNodeOptions(baseEnv.NODE_OPTIONS, extra, { + overrideHeapLimit: Boolean(config.nodeOptions), + }), + }; +} + +export function detectTools(pkg) { + const deps = { ...pkg.dependencies, ...pkg.devDependencies }; + const markdownlintPkg = MARKDOWNLINT_PACKAGES.find(name => name in deps); + return { + backstageCli: '@backstage/cli' in deps, + prettier: 'prettier' in deps, + sortPackageJson: 'sort-package-json' in deps, + markdownlint: markdownlintPkg, + knip: 'knip' in deps, + }; +} + +function markdownlintArgs(packageName) { + if (packageName === 'markdownlint-cli2') { + return ['exec', 'markdownlint-cli2', '--fix']; + } + return ['exec', 'markdownlint', '--fix', '**/*.md']; +} + +function repoFixArgs(config) { + return [ + 'backstage-cli', + 'repo', + 'fix', + ...(config.check ? ['--check'] : []), + ...(config.publish ? ['--publish'] : []), + ]; +} + +export function buildSteps({ tools, config }) { + const repoFixStep = { + id: 'repo-fix', + required: true, + available: tools.backstageCli, + command: 'yarn', + args: repoFixArgs(config), + }; + + if (config.check) { + return [repoFixStep]; + } + + return [ + repoFixStep, + { + id: 'sort-package-json', + required: false, + available: Boolean(tools.sortPackageJson), + command: 'yarn', + args: ['exec', 'sort-package-json', 'package.json'], + }, + { + id: 'lint-fix', + required: true, + available: tools.backstageCli, + command: 'yarn', + args: ['backstage-cli', 'repo', 'lint', '--fix'], + }, + { + id: 'markdownlint', + required: false, + available: Boolean(tools.markdownlint), + command: 'yarn', + args: markdownlintArgs(tools.markdownlint), + }, + { + id: 'prettier', + required: false, + available: Boolean(tools.prettier), + command: 'yarn', + args: ['prettier', '--write', '.'], + }, + { + id: 'knip', + required: false, + available: Boolean(tools.knip) && config.knip, + skipReason: config.knip + ? 'knip is not installed' + : 'knip --fix is opt-in (set rhdhFix.knip or pass --knip)', + command: 'yarn', + args: ['knip', '--fix'], + }, + ]; +} + +export async function runPipeline(steps, { run, log }) { + for (const step of steps) { + if (!step.available) { + if (step.required) { + throw Object.assign( + new Error(`Required fixer '${step.id}' is not available`), + { exitCode: 1 }, + ); + } + log(`skip ${step.id}: ${step.skipReason ?? 'not installed'}`); + continue; + } + + log(`run ${step.id}: ${step.command} ${step.args.join(' ')}`); + const code = await run(step); + if (code !== 0) { + throw Object.assign( + new Error(`Fixer '${step.id}' failed with exit code ${code}`), + { exitCode: code }, + ); + } + } +} + +function spawnStep(step, cwd, config) { + return new Promise(resolvePromise => { + const child = spawn(step.command, step.args, { + cwd, + stdio: 'inherit', + env: resolveSpawnEnv(step, config), + }); + child.on('error', () => resolvePromise(1)); + child.on('close', code => resolvePromise(code ?? 1)); + }); +} + +export function helpText() { + return [ + 'Usage: yarn fix [--check] [--publish] [--knip]', + '', + 'Run from a workspace root (workspaces/).', + 'Fixer order is defined in scripts/workspace-fix.mjs.', + '', + ' --check Run backstage-cli repo fix --check only (matches CI)', + ' --publish Pass --publish to backstage-cli repo fix', + ' --knip Run knip --fix (off by default)', + '', + 'Exit 0 when every run fixer succeeds, even if files changed.', + 'Exit non-zero when a fixer fails. Missing optional fixers are skipped.', + ].join('\n'); +} + +export async function main(argv, cwd, io = console) { + const { flags } = parseArgs(argv); + if (flags.help) { + io.log(helpText()); + return; + } + + const pkg = readPackageJson(cwd); + assertWorkspaceRoot(pkg); + const config = resolveConfig(pkg, flags); + const tools = detectTools(pkg); + const steps = buildSteps({ tools, config }); + await runPipeline(steps, { + log: msg => io.log(msg), + run: step => spawnStep(step, cwd, config), + }); +} + +function isMainModule() { + const entry = process.argv[1]; + if (!entry) { + return false; + } + return import.meta.url === pathToFileURL(resolve(entry)).href; +} + +if (isMainModule()) { + try { + await main(process.argv.slice(2), process.cwd()); + } catch (error) { + console.error(error.message); + process.exit(error.exitCode ?? 1); + } +} diff --git a/scripts/workspace-fix.test.mjs b/scripts/workspace-fix.test.mjs new file mode 100644 index 00000000000..cfadc6a8586 --- /dev/null +++ b/scripts/workspace-fix.test.mjs @@ -0,0 +1,353 @@ +/* + * Copyright Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import assert from 'node:assert/strict'; +import { mkdtempSync, writeFileSync } from 'node:fs'; +import { tmpdir } from 'node:os'; +import { join } from 'node:path'; +import { test } from 'node:test'; + +import { + DEFAULT_NODE_OPTIONS, + FIXER_ORDER, + REPO_ROOT_PACKAGE_NAME, + assertWorkspaceRoot, + buildSteps, + detectTools, + mergeNodeOptions, + parseArgs, + readPackageJson, + resolveConfig, + resolveSpawnEnv, + runPipeline, +} from './workspace-fix.mjs'; + +const ALL_TOOLS = { + backstageCli: true, + prettier: true, + sortPackageJson: true, + markdownlint: 'markdownlint-cli', + knip: true, +}; + +test('fixer order is documented and stable', () => { + assert.deepEqual(FIXER_ORDER, [ + 'repo-fix', + 'sort-package-json', + 'lint-fix', + 'markdownlint', + 'prettier', + 'knip', + ]); +}); + +test('parseArgs accepts publish, check, and knip flags', () => { + assert.deepEqual(parseArgs(['--publish', '--check', '--knip']), { + flags: { publish: true, check: true, knip: true, help: false }, + extra: [], + }); +}); + +test('parseArgs rejects unknown flags', () => { + assert.throws(() => parseArgs(['--write']), /Unknown flag '--write'/); +}); + +test('assertWorkspaceRoot rejects the monorepo root', () => { + assert.throws( + () => assertWorkspaceRoot({ name: REPO_ROOT_PACKAGE_NAME, workspaces: {} }), + /per workspace/, + ); +}); + +test('assertWorkspaceRoot rejects a package without workspaces', () => { + assert.throws( + () => assertWorkspaceRoot({ name: '@internal/noop' }), + /workspaces field/, + ); +}); + +test('readPackageJson fails without package.json', () => { + const cwd = mkdtempSync(join(tmpdir(), 'workspace-fix-')); + assert.throws(() => readPackageJson(cwd), /No package.json/); +}); + +test('resolveConfig merges package.json with CLI flags', () => { + assert.deepEqual( + resolveConfig({ rhdhFix: { publish: true } }, { check: true, knip: true }), + { + check: true, + publish: true, + knip: true, + nodeOptions: undefined, + }, + ); +}); + +test('mergeNodeOptions preserves an existing heap limit', () => { + assert.equal( + mergeNodeOptions('--max-old-space-size=16384', DEFAULT_NODE_OPTIONS), + '--max-old-space-size=16384', + ); +}); + +test('mergeNodeOptions appends when existing lacks a heap limit', () => { + assert.equal( + mergeNodeOptions('--inspect', DEFAULT_NODE_OPTIONS), + '--inspect --max-old-space-size=8192', + ); +}); + +test('mergeNodeOptions replaces heap limit for workspace overrides', () => { + assert.equal( + mergeNodeOptions( + '--max-old-space-size=8192', + '--max-old-space-size=16384', + { overrideHeapLimit: true }, + ), + '--max-old-space-size=16384', + ); +}); + +test('resolveSpawnEnv sets NODE_OPTIONS for lint-fix', () => { + const env = resolveSpawnEnv( + { id: 'lint-fix' }, + resolveConfig({}, { publish: false, knip: false, check: false }), + {}, + ); + assert.equal(env.NODE_OPTIONS, DEFAULT_NODE_OPTIONS); +}); + +test('resolveSpawnEnv honors rhdhFix.nodeOptions', () => { + const env = resolveSpawnEnv( + { id: 'lint-fix' }, + resolveConfig( + { rhdhFix: { nodeOptions: '--max-old-space-size=16384' } }, + {}, + ), + {}, + ); + assert.equal(env.NODE_OPTIONS, '--max-old-space-size=16384'); +}); + +test('resolveSpawnEnv lets rhdhFix.nodeOptions override CI NODE_OPTIONS', () => { + const env = resolveSpawnEnv( + { id: 'lint-fix' }, + resolveConfig( + { rhdhFix: { nodeOptions: '--max-old-space-size=16384' } }, + {}, + ), + { NODE_OPTIONS: DEFAULT_NODE_OPTIONS }, + ); + assert.equal(env.NODE_OPTIONS, '--max-old-space-size=16384'); +}); + +test('detectTools reads workspace dependencies', () => { + assert.deepEqual( + detectTools({ + devDependencies: { + '@backstage/cli': '^0.36.0', + prettier: '^3.0.0', + knip: '^5.0.0', + }, + }), + { + backstageCli: true, + prettier: true, + sortPackageJson: false, + markdownlint: undefined, + knip: true, + }, + ); +}); + +test('buildSteps keeps documented order and default knip off', () => { + const steps = buildSteps({ + tools: ALL_TOOLS, + config: { check: false, publish: false, knip: false }, + }); + assert.deepEqual( + steps.map(step => step.id), + FIXER_ORDER, + ); + const knip = steps.find(step => step.id === 'knip'); + assert.equal(knip.available, false); + assert.match(knip.skipReason, /opt-in/); + + const repoFix = steps.find(step => step.id === 'repo-fix'); + assert.deepEqual(repoFix.args, ['backstage-cli', 'repo', 'fix']); +}); + +test('buildSteps passes --publish to repo fix and enables knip when opted in', () => { + const steps = buildSteps({ + tools: ALL_TOOLS, + config: { check: false, publish: true, knip: true }, + }); + assert.deepEqual(steps.find(step => step.id === 'repo-fix').args, [ + 'backstage-cli', + 'repo', + 'fix', + '--publish', + ]); + assert.equal(steps.find(step => step.id === 'knip').available, true); +}); + +test('buildSteps in check mode only runs repo fix with --check', () => { + const steps = buildSteps({ + tools: ALL_TOOLS, + config: { check: true, publish: true, knip: true }, + }); + assert.deepEqual( + steps.map(step => step.id), + ['repo-fix'], + ); + assert.deepEqual(steps[0].args, [ + 'backstage-cli', + 'repo', + 'fix', + '--check', + '--publish', + ]); +}); + +test('runPipeline in check mode only runs repo fix', async () => { + const ran = []; + await runPipeline( + buildSteps({ + tools: ALL_TOOLS, + config: { check: true, publish: false, knip: true }, + }), + { + log: () => {}, + run: async step => { + ran.push(step.id); + return 0; + }, + }, + ); + assert.deepEqual(ran, ['repo-fix']); +}); + +test('optional fixers are skipped when their packages are not installed', () => { + const steps = buildSteps({ + tools: { + backstageCli: true, + prettier: false, + sortPackageJson: false, + markdownlint: undefined, + knip: false, + }, + config: { check: false, publish: false, knip: false }, + }); + assert.equal( + steps.find(step => step.id === 'sort-package-json').available, + false, + ); + assert.equal(steps.find(step => step.id === 'markdownlint').available, false); + assert.equal(steps.find(step => step.id === 'prettier').available, false); +}); + +test('runPipeline skips optional missing fixers and still succeeds', async () => { + const ran = []; + const logs = []; + await runPipeline( + buildSteps({ + tools: { + backstageCli: true, + prettier: true, + sortPackageJson: false, + markdownlint: undefined, + knip: true, + }, + config: { check: false, publish: false, knip: false }, + }), + { + log: msg => logs.push(msg), + run: async step => { + ran.push(step.id); + return 0; + }, + }, + ); + assert.deepEqual(ran, ['repo-fix', 'lint-fix', 'prettier']); + assert.ok(logs.some(line => line.startsWith('skip sort-package-json'))); + assert.ok(logs.some(line => line.startsWith('skip knip'))); +}); + +test('runPipeline exits non-zero when a fixer fails', async () => { + await assert.rejects( + () => + runPipeline( + buildSteps({ + tools: ALL_TOOLS, + config: { check: false, publish: false, knip: false }, + }), + { + log: () => {}, + run: async step => (step.id === 'lint-fix' ? 2 : 0), + }, + ), + error => error.exitCode === 2 && /lint-fix/.test(error.message), + ); +}); + +test('runPipeline fails when a required fixer is missing', async () => { + await assert.rejects( + () => + runPipeline( + buildSteps({ + tools: { + backstageCli: false, + prettier: true, + sortPackageJson: false, + markdownlint: undefined, + knip: false, + }, + config: { check: false, publish: false, knip: false }, + }), + { log: () => {}, run: async () => 0 }, + ), + /Required fixer 'repo-fix'/, + ); +}); + +test('runPipeline succeeds when fixers report changes as success', async () => { + const cwd = mkdtempSync(join(tmpdir(), 'workspace-fix-pkg-')); + writeFileSync( + join(cwd, 'package.json'), + JSON.stringify({ + name: '@internal/example', + workspaces: { packages: ['packages/*'] }, + devDependencies: { '@backstage/cli': '1.0.0', prettier: '3.0.0' }, + }), + ); + const pkg = readPackageJson(cwd); + assertWorkspaceRoot(pkg); + const ran = []; + await runPipeline( + buildSteps({ + tools: detectTools(pkg), + config: resolveConfig(pkg, { publish: false, knip: false, check: false }), + }), + { + log: () => {}, + run: async step => { + ran.push(step.id); + return 0; + }, + }, + ); + assert.deepEqual(ran, ['repo-fix', 'lint-fix', 'prettier']); +}); diff --git a/workspaces/adoption-insights/package.json b/workspaces/adoption-insights/package.json index 1dcd4bbdb95..64a21cf4568 100644 --- a/workspaces/adoption-insights/package.json +++ b/workspaces/adoption-insights/package.json @@ -25,7 +25,7 @@ "test:e2e:nfs": "APP_MODE=nfs playwright test", "test:e2e:all": "yarn test:e2e:legacy && yarn test:e2e:nfs", "playwright": "bash -c 'if [[ $@ == test ]]; then yarn test:e2e:all; else npx playwright \"$@\"; fi' _", - "fix": "backstage-cli repo fix", + "fix": "node ../../scripts/workspace-fix.mjs", "lint": "backstage-cli repo lint --since origin/main", "lint:all": "backstage-cli repo lint", "prettier:check": "prettier --check .", diff --git a/workspaces/ai-integrations/package.json b/workspaces/ai-integrations/package.json index 139bc77d42b..99282b356a6 100644 --- a/workspaces/ai-integrations/package.json +++ b/workspaces/ai-integrations/package.json @@ -20,7 +20,7 @@ "clean": "backstage-cli repo clean", "test": "backstage-cli repo test", "test:all": "backstage-cli repo test --coverage", - "fix": "backstage-cli repo fix", + "fix": "node ../../scripts/workspace-fix.mjs", "lint": "backstage-cli repo lint --since origin/main", "lint:all": "backstage-cli repo lint", "prettier:check": "prettier --check .", diff --git a/workspaces/app-defaults/package.json b/workspaces/app-defaults/package.json index 353bd3ce7e7..a184a35b2e0 100644 --- a/workspaces/app-defaults/package.json +++ b/workspaces/app-defaults/package.json @@ -19,7 +19,7 @@ "clean": "backstage-cli repo clean", "test": "backstage-cli repo test", "test:all": "backstage-cli repo test --coverage", - "fix": "backstage-cli repo fix", + "fix": "node ../../scripts/workspace-fix.mjs", "lint": "backstage-cli repo lint --since origin/main", "lint:all": "backstage-cli repo lint", "prettier:fix": "prettier --write .", diff --git a/workspaces/augment/package.json b/workspaces/augment/package.json index c45fecc8612..fde8323f135 100644 --- a/workspaces/augment/package.json +++ b/workspaces/augment/package.json @@ -20,7 +20,7 @@ "test": "backstage-cli repo test", "test:all": "yarn prettier:check && yarn lint:all && backstage-cli repo test --coverage", "test:e2e": "echo Skipping until we have tests: playwright test", - "fix": "backstage-cli repo fix", + "fix": "node ../../scripts/workspace-fix.mjs", "lint": "backstage-cli repo lint --since origin/main", "lint:all": "backstage-cli repo lint", "prettier:check": "prettier --check .", diff --git a/workspaces/boost/package.json b/workspaces/boost/package.json index 831ef862ac6..fc4821fcb56 100644 --- a/workspaces/boost/package.json +++ b/workspaces/boost/package.json @@ -17,7 +17,7 @@ "clean": "backstage-cli repo clean", "test": "backstage-cli repo test", "test:all": "yarn prettier:check && yarn lint:all && backstage-cli repo test --coverage", - "fix": "backstage-cli repo fix", + "fix": "node ../../scripts/workspace-fix.mjs", "lint": "backstage-cli repo lint --since origin/main", "lint:all": "backstage-cli repo lint", "prettier:check": "prettier --check .", diff --git a/workspaces/bulk-import/package.json b/workspaces/bulk-import/package.json index 17101db1993..9045246887f 100644 --- a/workspaces/bulk-import/package.json +++ b/workspaces/bulk-import/package.json @@ -17,7 +17,7 @@ "clean": "backstage-cli repo clean", "test": "backstage-cli repo test", "test:all": "backstage-cli repo test --coverage", - "fix": "backstage-cli repo fix", + "fix": "node ../../scripts/workspace-fix.mjs", "lint": "backstage-cli repo lint --since origin/main", "lint:all": "backstage-cli repo lint", "prettier:check": "prettier --check .", diff --git a/workspaces/cost-management/package.json b/workspaces/cost-management/package.json index e5c1ccf8baa..5f1029010b1 100644 --- a/workspaces/cost-management/package.json +++ b/workspaces/cost-management/package.json @@ -20,7 +20,7 @@ "clean": "backstage-cli repo clean", "test": "backstage-cli repo test", "test:all": "backstage-cli repo test --coverage", - "fix": "backstage-cli repo fix", + "fix": "node ../../scripts/workspace-fix.mjs", "lint": "backstage-cli repo lint --since origin/main", "lint:all": "backstage-cli repo lint", "prettier:check": "prettier --check .", diff --git a/workspaces/dcm/package.json b/workspaces/dcm/package.json index 06107b91d9d..d93bd9d8582 100644 --- a/workspaces/dcm/package.json +++ b/workspaces/dcm/package.json @@ -21,7 +21,7 @@ "clean": "backstage-cli repo clean", "test": "backstage-cli repo test", "test:all": "backstage-cli repo test --coverage", - "fix": "backstage-cli repo fix", + "fix": "node ../../scripts/workspace-fix.mjs", "lint": "backstage-cli repo lint --since origin/main", "lint:all": "backstage-cli repo lint", "prettier:check": "prettier --check .", diff --git a/workspaces/extensions/package.json b/workspaces/extensions/package.json index 5181b362931..a05ebcebc45 100644 --- a/workspaces/extensions/package.json +++ b/workspaces/extensions/package.json @@ -24,7 +24,7 @@ "test:nfs": "APP_MODE=nfs playwright test", "test:e2e:ci": "yarn test:legacy && yarn test:nfs", "playwright": "sh -c 'if [ \"$1\" = test ] && [ $# -eq 1 ]; then yarn test:e2e:ci; else exec playwright \"$@\"; fi' _", - "fix": "backstage-cli repo fix", + "fix": "node ../../scripts/workspace-fix.mjs", "lint": "backstage-cli repo lint --since origin/main", "lint:all": "backstage-cli repo lint", "prettier:check": "prettier --check .", diff --git a/workspaces/global-header/.eslintignore b/workspaces/global-header/.eslintignore index 3f52266d2bf..78218b21597 100644 --- a/workspaces/global-header/.eslintignore +++ b/workspaces/global-header/.eslintignore @@ -1,2 +1,6 @@ playwright.config.ts e2e-tests/ +dist-dynamic +dist-scalprum +!.eslintrc.js +!.prettierrc.js diff --git a/workspaces/global-header/.gitignore b/workspaces/global-header/.gitignore index 9f1da0e28dd..0f2d9197e7e 100644 --- a/workspaces/global-header/.gitignore +++ b/workspaces/global-header/.gitignore @@ -33,6 +33,7 @@ node_modules/ # Build output dist +dist-dynamic dist-scalprum dist-types diff --git a/workspaces/global-header/.prettierignore b/workspaces/global-header/.prettierignore index 1cfaa894795..3f67d113f8e 100644 --- a/workspaces/global-header/.prettierignore +++ b/workspaces/global-header/.prettierignore @@ -1,4 +1,6 @@ dist +dist-dynamic +dist-scalprum dist-types coverage .vscode diff --git a/workspaces/global-header/package.json b/workspaces/global-header/package.json index 0ebb9040f3f..99c4c23a3e6 100644 --- a/workspaces/global-header/package.json +++ b/workspaces/global-header/package.json @@ -25,7 +25,7 @@ "test:e2e:nfs": "APP_MODE=nfs playwright test", "test:e2e:all": "yarn test:e2e:legacy && yarn test:e2e:nfs", "playwright": "bash -c 'if [[ $@ == test ]]; then yarn test:e2e:legacy; else npx playwright \"$@\"; fi' _", - "fix": "backstage-cli repo fix", + "fix": "node ../../scripts/workspace-fix.mjs", "lint": "backstage-cli repo lint --since origin/main", "lint:all": "backstage-cli repo lint", "prettier:check": "prettier --check .", diff --git a/workspaces/global-header/plugins/global-header/.eslintignore b/workspaces/global-header/plugins/global-header/.eslintignore new file mode 100644 index 00000000000..8674aee2f61 --- /dev/null +++ b/workspaces/global-header/plugins/global-header/.eslintignore @@ -0,0 +1,4 @@ +dist-dynamic +dist-scalprum +!.eslintrc.js +!.prettierrc.js diff --git a/workspaces/global-header/plugins/global-header/.prettierignore b/workspaces/global-header/plugins/global-header/.prettierignore new file mode 100644 index 00000000000..e23b6927e5c --- /dev/null +++ b/workspaces/global-header/plugins/global-header/.prettierignore @@ -0,0 +1,8 @@ +dist +dist-dynamic +dist-scalprum +dist-types +coverage +.vscode +!.eslintrc.js +!.prettierrc.js diff --git a/workspaces/homepage/package.json b/workspaces/homepage/package.json index 8ee7c663291..58aae69fa15 100644 --- a/workspaces/homepage/package.json +++ b/workspaces/homepage/package.json @@ -20,7 +20,7 @@ "clean": "backstage-cli repo clean", "test": "backstage-cli repo test", "test:all": "backstage-cli repo test --coverage", - "fix": "backstage-cli repo fix", + "fix": "node ../../scripts/workspace-fix.mjs", "lint": "backstage-cli repo lint --since origin/main", "lint:all": "backstage-cli repo lint", "test:e2e": "yarn test:e2e:all", diff --git a/workspaces/install-dynamic-plugins/package.json b/workspaces/install-dynamic-plugins/package.json index 30890ec117d..256f761d7de 100644 --- a/workspaces/install-dynamic-plugins/package.json +++ b/workspaces/install-dynamic-plugins/package.json @@ -20,7 +20,7 @@ "clean": "backstage-cli repo clean", "test": "backstage-cli repo test", "test:all": "backstage-cli repo test --coverage", - "fix": "backstage-cli repo fix", + "fix": "node ../../scripts/workspace-fix.mjs", "lint": "backstage-cli repo lint --since origin/main", "lint:all": "backstage-cli repo lint", "prettier:check": "prettier --check .", diff --git a/workspaces/intelligent-assistant/package.json b/workspaces/intelligent-assistant/package.json index fce1e20da4f..a9b1abf560d 100644 --- a/workspaces/intelligent-assistant/package.json +++ b/workspaces/intelligent-assistant/package.json @@ -25,7 +25,7 @@ "test:e2e:all": "yarn test:e2e:legacy && yarn test:e2e:nfs", "test:e2e:ci": "yarn test:e2e:all", "playwright": "bash -c 'if [[ $@ == test ]]; then yarn test:e2e:all; else npx playwright \"$@\"; fi' _", - "fix": "backstage-cli repo fix", + "fix": "node ../../scripts/workspace-fix.mjs", "lint": "backstage-cli repo lint --since origin/main", "lint:all": "backstage-cli repo lint", "lint:check": "backstage-cli package lint", diff --git a/workspaces/konflux/package.json b/workspaces/konflux/package.json index 02258ece7c6..e655b324164 100644 --- a/workspaces/konflux/package.json +++ b/workspaces/konflux/package.json @@ -18,7 +18,7 @@ "clean": "backstage-cli repo clean", "test": "backstage-cli repo test", "test:all": "backstage-cli repo test --coverage", - "fix": "backstage-cli repo fix", + "fix": "node ../../scripts/workspace-fix.mjs", "lint": "backstage-cli repo lint --since origin/main", "lint:all": "backstage-cli repo lint", "prettier:check": "prettier --check .", diff --git a/workspaces/mcp-integrations/package.json b/workspaces/mcp-integrations/package.json index d9b839f2b52..c9edf00da30 100644 --- a/workspaces/mcp-integrations/package.json +++ b/workspaces/mcp-integrations/package.json @@ -21,7 +21,7 @@ "test:all": "backstage-cli repo test --coverage", "test:unit": "backstage-cli repo test --testPathIgnorePatterns=integration\\.test", "test:integration": "backstage-cli repo test --testPathPatterns=integration\\.test --watch=false", - "fix": "backstage-cli repo fix", + "fix": "node ../../scripts/workspace-fix.mjs", "lint": "backstage-cli repo lint --since origin/main", "lint:all": "backstage-cli repo lint", "prettier:check": "prettier --check .", diff --git a/workspaces/orchestrator/.prettierignore b/workspaces/orchestrator/.prettierignore index 4d30a47997a..ec02ec19dde 100644 --- a/workspaces/orchestrator/.prettierignore +++ b/workspaces/orchestrator/.prettierignore @@ -1,4 +1,6 @@ dist +dist-dynamic +dist-scalprum dist-types coverage .vscode diff --git a/workspaces/orchestrator/package.json b/workspaces/orchestrator/package.json index d77405cfb77..035ef54cd27 100644 --- a/workspaces/orchestrator/package.json +++ b/workspaces/orchestrator/package.json @@ -23,7 +23,7 @@ "test:nfs": "APP_MODE=nfs playwright test", "test:e2e:ci": "yarn test:legacy && yarn test:nfs", "playwright": "sh -c 'if [ \"$1\" = test ] && [ $# -eq 1 ]; then yarn test:e2e:ci; else exec playwright \"$@\"; fi' _", - "fix": "backstage-cli repo fix", + "fix": "node ../../scripts/workspace-fix.mjs", "lint": "backstage-cli repo lint --since origin/main", "lint:all": "backstage-cli repo lint", "prettier:check": "prettier --check .", diff --git a/workspaces/quickstart/package.json b/workspaces/quickstart/package.json index 200018685ca..81b86a2a792 100644 --- a/workspaces/quickstart/package.json +++ b/workspaces/quickstart/package.json @@ -16,7 +16,7 @@ "clean": "backstage-cli repo clean", "test": "backstage-cli repo test", "test:all": "backstage-cli repo test --coverage", - "fix": "backstage-cli repo fix", + "fix": "node ../../scripts/workspace-fix.mjs", "lint": "backstage-cli repo lint --since origin/main", "lint:all": "backstage-cli repo lint", "prettier:check": "prettier --check .", diff --git a/workspaces/repo-tools/package.json b/workspaces/repo-tools/package.json index afec7e1d905..d75def8df3e 100644 --- a/workspaces/repo-tools/package.json +++ b/workspaces/repo-tools/package.json @@ -17,7 +17,7 @@ "clean": "backstage-cli repo clean", "test": "backstage-cli repo test", "test:all": "backstage-cli repo test --coverage", - "fix": "backstage-cli repo fix", + "fix": "node ../../scripts/workspace-fix.mjs", "lint": "backstage-cli repo lint --since origin/main", "lint:all": "backstage-cli repo lint", "prettier:check": "prettier --check .", diff --git a/workspaces/repo-tools/packages/cli/src/lib/workspaces/templates/workspace/.eslintignore b/workspaces/repo-tools/packages/cli/src/lib/workspaces/templates/workspace/.eslintignore index e5b19947ff1..6d586507535 100644 --- a/workspaces/repo-tools/packages/cli/src/lib/workspaces/templates/workspace/.eslintignore +++ b/workspaces/repo-tools/packages/cli/src/lib/workspaces/templates/workspace/.eslintignore @@ -1 +1,5 @@ playwright.config.ts +dist-dynamic +dist-scalprum +!.eslintrc.js +!.prettierrc.js diff --git a/workspaces/repo-tools/packages/cli/src/lib/workspaces/templates/workspace/.prettierignore b/workspaces/repo-tools/packages/cli/src/lib/workspaces/templates/workspace/.prettierignore index 1cfaa894795..3f67d113f8e 100644 --- a/workspaces/repo-tools/packages/cli/src/lib/workspaces/templates/workspace/.prettierignore +++ b/workspaces/repo-tools/packages/cli/src/lib/workspaces/templates/workspace/.prettierignore @@ -1,4 +1,6 @@ dist +dist-dynamic +dist-scalprum dist-types coverage .vscode diff --git a/workspaces/repo-tools/packages/cli/src/lib/workspaces/templates/workspace/package.json.hbs b/workspaces/repo-tools/packages/cli/src/lib/workspaces/templates/workspace/package.json.hbs index 74590744486..9fb1c0a9846 100644 --- a/workspaces/repo-tools/packages/cli/src/lib/workspaces/templates/workspace/package.json.hbs +++ b/workspaces/repo-tools/packages/cli/src/lib/workspaces/templates/workspace/package.json.hbs @@ -16,7 +16,7 @@ "clean": "backstage-cli repo clean", "test": "backstage-cli repo test", "test:all": "backstage-cli repo test --coverage", - "fix": "backstage-cli repo fix", + "fix": "node ../../scripts/workspace-fix.mjs", "lint": "backstage-cli repo lint --since origin/main", "lint:all": "backstage-cli repo lint", "prettier:check": "prettier --check .", diff --git a/workspaces/scorecard/package.json b/workspaces/scorecard/package.json index a1efb331374..9e71aa8f4cc 100644 --- a/workspaces/scorecard/package.json +++ b/workspaces/scorecard/package.json @@ -25,7 +25,7 @@ "test:e2e:nfs": "APP_MODE=nfs playwright test", "test:e2e:all": "yarn test:e2e:legacy && yarn test:e2e:nfs", "playwright": "bash -c 'if [[ \"$*\" == \"test\" ]]; then yarn test:e2e:all; else npx playwright \"$@\"; fi' _", - "fix": "backstage-cli repo fix", + "fix": "node ../../scripts/workspace-fix.mjs", "lint": "backstage-cli repo lint --since origin/main", "lint:all": "backstage-cli repo lint", "prettier:check": "prettier --check .", diff --git a/workspaces/theme/package.json b/workspaces/theme/package.json index ce4cf18ccc2..3ba31634eed 100644 --- a/workspaces/theme/package.json +++ b/workspaces/theme/package.json @@ -24,7 +24,7 @@ "test:nfs": "APP_MODE=nfs playwright test packages/app/e2e-tests", "test:e2e:ci": "yarn test:legacy && yarn test:nfs", "playwright": "sh -c 'if [ \"$1\" = test ] && [ $# -eq 1 ]; then yarn test:e2e:ci; else exec playwright \"$@\"; fi' _", - "fix": "backstage-cli repo fix", + "fix": "node ../../scripts/workspace-fix.mjs", "lint": "backstage-cli repo lint --since origin/main", "lint:all": "backstage-cli repo lint", "prettier:check": "prettier --check .", diff --git a/workspaces/translations/package.json b/workspaces/translations/package.json index 196f3112033..9534bb015f2 100644 --- a/workspaces/translations/package.json +++ b/workspaces/translations/package.json @@ -25,7 +25,7 @@ "test:e2e:nfs": "APP_MODE=nfs playwright test", "test:e2e:all": "yarn test:e2e:legacy && yarn test:e2e:nfs", "playwright": "bash -c 'if [[ \"$*\" == \"test\" ]]; then yarn test:e2e:all; else npx playwright \"$@\"; fi' _", - "fix": "backstage-cli repo fix", + "fix": "node ../../scripts/workspace-fix.mjs", "lint": "backstage-cli repo lint --since origin/main", "lint:all": "backstage-cli repo lint", "prettier:check": "prettier --check .", diff --git a/workspaces/x2a/package.json b/workspaces/x2a/package.json index 5c8dfa7cdb2..e7d91e756d9 100644 --- a/workspaces/x2a/package.json +++ b/workspaces/x2a/package.json @@ -26,7 +26,7 @@ "test:e2e:nfs": "APP_MODE=nfs playwright test", "test:e2e:all": "yarn test:e2e:nfs", "playwright": "bash -c 'if [[ $1 == test ]]; then echo \"Skipping test:e2e:all e2e tests (no real tests yet)\"; else npx playwright \"$@\"; fi' _", - "fix": "backstage-cli repo fix --publish", + "fix": "node ../../scripts/workspace-fix.mjs", "lint": "backstage-cli repo lint --since origin/main", "lint:all": "backstage-cli repo lint", "prettier:check": "prettier --check .", @@ -85,6 +85,9 @@ "zod@^3.25.76 || ^4.0.0": "3.25.76", "zod@^3.25 || ^4.0": "3.25.76" }, + "rhdhFix": { + "publish": true + }, "prettier": "@backstage/cli/config/prettier", "lint-staged": { "*.{js,jsx,ts,tsx,mjs,cjs}": [