From 8f5bb8ccb734a558f41f22ff90a6ae0e6f5b60d2 Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Thu, 9 Jan 2025 11:55:16 +0100 Subject: [PATCH 01/17] feat: adds script to run madge in a CI environment --- .../devops/circular/index.js | 72 +++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 src/Umbraco.Web.UI.Client/devops/circular/index.js diff --git a/src/Umbraco.Web.UI.Client/devops/circular/index.js b/src/Umbraco.Web.UI.Client/devops/circular/index.js new file mode 100644 index 000000000000..cb1ef9128798 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/devops/circular/index.js @@ -0,0 +1,72 @@ +/** + * This module is used to detect circular dependencies in the Umbraco backoffice. + * It is used in the build process to ensure that we don't have circular dependencies. + * @example node devops/circular/index.js + * @author Umbraco HQ + */ + +import madge from 'madge'; +import { join } from 'path'; +import { writeFileSync } from 'fs'; + +const __dirname = import.meta.dirname; +const IS_GITHUB_ACTIONS = process.env.GITHUB_ACTIONS === 'true'; +const IS_AZURE_PIPELINES = process.env.TF_BUILD === 'true'; +const baseDir = process.argv[2] || 'src'; +const specificPaths = (process.argv[3] || '').split(','); + +console.log('Scanning for circular dependencies in:', baseDir); + +const madgeSetup = await madge(specificPaths, { + baseDir, + fileExtensions: ['ts'], + tsConfig: join(baseDir, 'tsconfig.build.json'), + detectiveOptions: { + ts: { + skipTypeImports: true, + skipAsyncImports: true + } + } +}); + +console.log('-'.repeat(80)); + +const circular = madgeSetup.circular(); + +if (circular.length > 0) { + console.error(circular.length, 'circular dependencies detected:\n'); + for (let i = 0; i < circular.length; i++) { + printCircularDependency(circular[i], i + 1); + } + console.error('\nPlease fix the circular dependencies before proceeding.\n'); + + try { + const svg = await madgeSetup.svg(); + const svgString = svg.toString(); + writeFileSync(join(__dirname, '../..', 'circular-dependencies.svg'), svgString); + } catch { } + + process.exit(1); +} + +console.log('\nNo circular dependencies detected.\n'); +process.exit(0); + +/** + * + * @param {string[]} circular The circular dependencies. + * @param {number} idx The index of the circular dependency. + */ +function printCircularDependency(circular, idx) { + circular = circular.map(file => `${baseDir}/${file}`); + const circularPath = circular.join(' -> '); + console.error(idx, '=', circularPath, '\n'); + + if (IS_GITHUB_ACTIONS) { + console.error(`::error file=${circular[0]},title=Circular dependency::Circular dependencies detected: ${circularPath}`); + } + else if (IS_AZURE_PIPELINES) { + console.error(`##vso[task.logissue type=error;sourcepath=${circular[0]};]Circular dependencies detected: ${circularPath}`); + } + +} From 0b48a7dab970060d968b78c187f4770822775150 Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Thu, 9 Jan 2025 11:56:55 +0100 Subject: [PATCH 02/17] build: adds check for circular dependencies --- .github/workflows/test-backoffice.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/test-backoffice.yml b/.github/workflows/test-backoffice.yml index 65214436a3c8..f8325107539c 100644 --- a/.github/workflows/test-backoffice.yml +++ b/.github/workflows/test-backoffice.yml @@ -44,6 +44,10 @@ jobs: - run: npm run build:for:cms - run: npm run check:paths - run: npm run generate:jsonschema:dist + - name: Setup Graphviz + uses: ts-graphviz/setup-graphviz@v2.0.2 + - name: Check for circular dependencies + run: node devops/circular/index.js src test: runs-on: ubuntu-latest From 17626c9f57e21fb669ccc0c7b303303ed9261194 Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Thu, 9 Jan 2025 11:58:08 +0100 Subject: [PATCH 03/17] upload report --- .github/workflows/test-backoffice.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/test-backoffice.yml b/.github/workflows/test-backoffice.yml index f8325107539c..ad157ad3058a 100644 --- a/.github/workflows/test-backoffice.yml +++ b/.github/workflows/test-backoffice.yml @@ -48,6 +48,11 @@ jobs: uses: ts-graphviz/setup-graphviz@v2.0.2 - name: Check for circular dependencies run: node devops/circular/index.js src + - name: Upload report + uses: actions/upload-artifact@v2 + with: + path: circular-dependencies.svg + if: failure() test: runs-on: ubuntu-latest From 29861cba93f079edfc3564f4b63b61317151385e Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Thu, 9 Jan 2025 12:00:21 +0100 Subject: [PATCH 04/17] build: update action version --- .github/workflows/test-backoffice.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test-backoffice.yml b/.github/workflows/test-backoffice.yml index ad157ad3058a..e82566b3ff7a 100644 --- a/.github/workflows/test-backoffice.yml +++ b/.github/workflows/test-backoffice.yml @@ -49,8 +49,9 @@ jobs: - name: Check for circular dependencies run: node devops/circular/index.js src - name: Upload report - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v4 with: + name: circular-dependencies path: circular-dependencies.svg if: failure() From 351a5cb2bd3c4418d66b4a95038fa448118bca74 Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Thu, 9 Jan 2025 12:01:27 +0100 Subject: [PATCH 05/17] build: move actions higher up --- .github/workflows/test-backoffice.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/test-backoffice.yml b/.github/workflows/test-backoffice.yml index e82566b3ff7a..17d5753de411 100644 --- a/.github/workflows/test-backoffice.yml +++ b/.github/workflows/test-backoffice.yml @@ -40,10 +40,6 @@ jobs: cache: npm cache-dependency-path: ./src/Umbraco.Web.UI.Client/package-lock.json - run: npm ci --no-audit --no-fund --prefer-offline - - run: npm run lint:errors - - run: npm run build:for:cms - - run: npm run check:paths - - run: npm run generate:jsonschema:dist - name: Setup Graphviz uses: ts-graphviz/setup-graphviz@v2.0.2 - name: Check for circular dependencies @@ -54,6 +50,10 @@ jobs: name: circular-dependencies path: circular-dependencies.svg if: failure() + - run: npm run lint:errors + - run: npm run build:for:cms + - run: npm run check:paths + - run: npm run generate:jsonschema:dist test: runs-on: ubuntu-latest From d974d979c19a4f70925337345bd7a40adf741a0f Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Thu, 9 Jan 2025 12:10:02 +0100 Subject: [PATCH 06/17] build: try to generate an image --- .github/workflows/test-backoffice.yml | 2 +- src/Umbraco.Web.UI.Client/devops/circular/index.js | 9 ++++----- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/.github/workflows/test-backoffice.yml b/.github/workflows/test-backoffice.yml index 17d5753de411..dac3c3f56113 100644 --- a/.github/workflows/test-backoffice.yml +++ b/.github/workflows/test-backoffice.yml @@ -48,7 +48,7 @@ jobs: uses: actions/upload-artifact@v4 with: name: circular-dependencies - path: circular-dependencies.svg + path: madge if: failure() - run: npm run lint:errors - run: npm run build:for:cms diff --git a/src/Umbraco.Web.UI.Client/devops/circular/index.js b/src/Umbraco.Web.UI.Client/devops/circular/index.js index cb1ef9128798..aee6867baff9 100644 --- a/src/Umbraco.Web.UI.Client/devops/circular/index.js +++ b/src/Umbraco.Web.UI.Client/devops/circular/index.js @@ -33,7 +33,7 @@ console.log('-'.repeat(80)); const circular = madgeSetup.circular(); -if (circular.length > 0) { +if (circular.length) { console.error(circular.length, 'circular dependencies detected:\n'); for (let i = 0; i < circular.length; i++) { printCircularDependency(circular[i], i + 1); @@ -41,10 +41,9 @@ if (circular.length > 0) { console.error('\nPlease fix the circular dependencies before proceeding.\n'); try { - const svg = await madgeSetup.svg(); - const svgString = svg.toString(); - writeFileSync(join(__dirname, '../..', 'circular-dependencies.svg'), svgString); - } catch { } + const image = await madgeSetup.image(join(__dirname, '../../madge'), true); + console.log('Circular dependencies graph generated:', image); + } catch { console.warn('No image generated. Make sure Graphviz is in your $PATH if you want a visualization'); } process.exit(1); } From 0dff0114c36ea9827c4820db72d78945e73d7ba1 Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Thu, 9 Jan 2025 12:13:08 +0100 Subject: [PATCH 07/17] build: narrow path on which madge is run --- .github/workflows/test-backoffice.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test-backoffice.yml b/.github/workflows/test-backoffice.yml index dac3c3f56113..3e34c63eb277 100644 --- a/.github/workflows/test-backoffice.yml +++ b/.github/workflows/test-backoffice.yml @@ -43,12 +43,12 @@ jobs: - name: Setup Graphviz uses: ts-graphviz/setup-graphviz@v2.0.2 - name: Check for circular dependencies - run: node devops/circular/index.js src + run: node devops/circular/index.js src/Umbraco.Web.UI.Client/src - name: Upload report uses: actions/upload-artifact@v4 with: name: circular-dependencies - path: madge + path: src/Umbraco.Web.UI.Client/madge if: failure() - run: npm run lint:errors - run: npm run build:for:cms From 210d5362d5e600736688cfd753c450a88eca3b48 Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Thu, 9 Jan 2025 12:16:02 +0100 Subject: [PATCH 08/17] build: use local paths --- .github/workflows/test-backoffice.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test-backoffice.yml b/.github/workflows/test-backoffice.yml index 3e34c63eb277..dac3c3f56113 100644 --- a/.github/workflows/test-backoffice.yml +++ b/.github/workflows/test-backoffice.yml @@ -43,12 +43,12 @@ jobs: - name: Setup Graphviz uses: ts-graphviz/setup-graphviz@v2.0.2 - name: Check for circular dependencies - run: node devops/circular/index.js src/Umbraco.Web.UI.Client/src + run: node devops/circular/index.js src - name: Upload report uses: actions/upload-artifact@v4 with: name: circular-dependencies - path: src/Umbraco.Web.UI.Client/madge + path: madge if: failure() - run: npm run lint:errors - run: npm run build:for:cms From 50e54a8de5b0cd1a1ea133ec45401c78acf90af0 Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Thu, 9 Jan 2025 12:16:08 +0100 Subject: [PATCH 09/17] build: define output image --- src/Umbraco.Web.UI.Client/devops/circular/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/devops/circular/index.js b/src/Umbraco.Web.UI.Client/devops/circular/index.js index aee6867baff9..c80c6e72e854 100644 --- a/src/Umbraco.Web.UI.Client/devops/circular/index.js +++ b/src/Umbraco.Web.UI.Client/devops/circular/index.js @@ -41,7 +41,7 @@ if (circular.length) { console.error('\nPlease fix the circular dependencies before proceeding.\n'); try { - const image = await madgeSetup.image(join(__dirname, '../../madge'), true); + const image = await madgeSetup.image(join(__dirname, '../../madge/circular.jpg'), true); console.log('Circular dependencies graph generated:', image); } catch { console.warn('No image generated. Make sure Graphviz is in your $PATH if you want a visualization'); } From 4ee592808b92088076aecf7abf138ccf7e575b81 Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Thu, 9 Jan 2025 12:17:29 +0100 Subject: [PATCH 10/17] build: output an svg --- src/Umbraco.Web.UI.Client/devops/circular/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/devops/circular/index.js b/src/Umbraco.Web.UI.Client/devops/circular/index.js index c80c6e72e854..b76c7d72214a 100644 --- a/src/Umbraco.Web.UI.Client/devops/circular/index.js +++ b/src/Umbraco.Web.UI.Client/devops/circular/index.js @@ -41,7 +41,7 @@ if (circular.length) { console.error('\nPlease fix the circular dependencies before proceeding.\n'); try { - const image = await madgeSetup.image(join(__dirname, '../../madge/circular.jpg'), true); + const image = await madgeSetup.image(join(__dirname, '../../madge/circular.svg'), true); console.log('Circular dependencies graph generated:', image); } catch { console.warn('No image generated. Make sure Graphviz is in your $PATH if you want a visualization'); } From 85ceb2252512264d9978a76825194e8a88a507f4 Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Thu, 9 Jan 2025 12:19:30 +0100 Subject: [PATCH 11/17] build: only print annotation once --- src/Umbraco.Web.UI.Client/devops/circular/index.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/devops/circular/index.js b/src/Umbraco.Web.UI.Client/devops/circular/index.js index b76c7d72214a..74525463f2c2 100644 --- a/src/Umbraco.Web.UI.Client/devops/circular/index.js +++ b/src/Umbraco.Web.UI.Client/devops/circular/index.js @@ -1,13 +1,12 @@ /** * This module is used to detect circular dependencies in the Umbraco backoffice. * It is used in the build process to ensure that we don't have circular dependencies. - * @example node devops/circular/index.js + * @example node devops/circular/index.js src * @author Umbraco HQ */ import madge from 'madge'; import { join } from 'path'; -import { writeFileSync } from 'fs'; const __dirname = import.meta.dirname; const IS_GITHUB_ACTIONS = process.env.GITHUB_ACTIONS === 'true'; @@ -59,13 +58,14 @@ process.exit(0); function printCircularDependency(circular, idx) { circular = circular.map(file => `${baseDir}/${file}`); const circularPath = circular.join(' -> '); - console.error(idx, '=', circularPath, '\n'); if (IS_GITHUB_ACTIONS) { console.error(`::error file=${circular[0]},title=Circular dependency::Circular dependencies detected: ${circularPath}`); } else if (IS_AZURE_PIPELINES) { console.error(`##vso[task.logissue type=error;sourcepath=${circular[0]};]Circular dependencies detected: ${circularPath}`); + } else { + console.error(idx, '=', circularPath, '\n'); } } From 2881ad893b59645d88bb0a466bb0ee17a16e2d6e Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Thu, 9 Jan 2025 12:20:07 +0100 Subject: [PATCH 12/17] build: log error --- src/Umbraco.Web.UI.Client/devops/circular/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/devops/circular/index.js b/src/Umbraco.Web.UI.Client/devops/circular/index.js index 74525463f2c2..7634cfa52cac 100644 --- a/src/Umbraco.Web.UI.Client/devops/circular/index.js +++ b/src/Umbraco.Web.UI.Client/devops/circular/index.js @@ -42,7 +42,7 @@ if (circular.length) { try { const image = await madgeSetup.image(join(__dirname, '../../madge/circular.svg'), true); console.log('Circular dependencies graph generated:', image); - } catch { console.warn('No image generated. Make sure Graphviz is in your $PATH if you want a visualization'); } + } catch (e) { console.warn('No image generated. Make sure Graphviz is in your $PATH if you want a visualization', e); } process.exit(1); } From b065faca51ab1db444f0dab83a9e1813deb76184 Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Thu, 9 Jan 2025 12:24:43 +0100 Subject: [PATCH 13/17] build: generate path first --- src/Umbraco.Web.UI.Client/devops/circular/index.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/devops/circular/index.js b/src/Umbraco.Web.UI.Client/devops/circular/index.js index 7634cfa52cac..7e49ee4e80e6 100644 --- a/src/Umbraco.Web.UI.Client/devops/circular/index.js +++ b/src/Umbraco.Web.UI.Client/devops/circular/index.js @@ -7,6 +7,7 @@ import madge from 'madge'; import { join } from 'path'; +import { mkdirSync } from 'fs'; const __dirname = import.meta.dirname; const IS_GITHUB_ACTIONS = process.env.GITHUB_ACTIONS === 'true'; @@ -40,7 +41,9 @@ if (circular.length) { console.error('\nPlease fix the circular dependencies before proceeding.\n'); try { - const image = await madgeSetup.image(join(__dirname, '../../madge/circular.svg'), true); + const imagePath = join(__dirname, '../../madge'); + mkdirSync(imagePath, { recursive: true }); + const image = await madgeSetup.image(join(imagePath, 'circular.svg'), true); console.log('Circular dependencies graph generated:', image); } catch (e) { console.warn('No image generated. Make sure Graphviz is in your $PATH if you want a visualization', e); } From a5edb9d06988c89df49d26ad1cf1acafd81aa0a0 Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Thu, 9 Jan 2025 12:28:01 +0100 Subject: [PATCH 14/17] build: upload from root --- .github/workflows/test-backoffice.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test-backoffice.yml b/.github/workflows/test-backoffice.yml index dac3c3f56113..7bb2963e8844 100644 --- a/.github/workflows/test-backoffice.yml +++ b/.github/workflows/test-backoffice.yml @@ -47,8 +47,8 @@ jobs: - name: Upload report uses: actions/upload-artifact@v4 with: - name: circular-dependencies - path: madge + name: madge-report + path: src/Umbraco.Web.UI.Client/madge if: failure() - run: npm run lint:errors - run: npm run build:for:cms From 6681c28f31e5a1c35550a8dbc39263a4d2c16524 Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Thu, 9 Jan 2025 12:32:29 +0100 Subject: [PATCH 15/17] build: remove image generation as it is not as useful --- .github/workflows/test-backoffice.yml | 8 -------- src/Umbraco.Web.UI.Client/devops/circular/index.js | 2 +- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/.github/workflows/test-backoffice.yml b/.github/workflows/test-backoffice.yml index 7bb2963e8844..1c5776c470bf 100644 --- a/.github/workflows/test-backoffice.yml +++ b/.github/workflows/test-backoffice.yml @@ -40,16 +40,8 @@ jobs: cache: npm cache-dependency-path: ./src/Umbraco.Web.UI.Client/package-lock.json - run: npm ci --no-audit --no-fund --prefer-offline - - name: Setup Graphviz - uses: ts-graphviz/setup-graphviz@v2.0.2 - name: Check for circular dependencies run: node devops/circular/index.js src - - name: Upload report - uses: actions/upload-artifact@v4 - with: - name: madge-report - path: src/Umbraco.Web.UI.Client/madge - if: failure() - run: npm run lint:errors - run: npm run build:for:cms - run: npm run check:paths diff --git a/src/Umbraco.Web.UI.Client/devops/circular/index.js b/src/Umbraco.Web.UI.Client/devops/circular/index.js index 7e49ee4e80e6..34b6664cee98 100644 --- a/src/Umbraco.Web.UI.Client/devops/circular/index.js +++ b/src/Umbraco.Web.UI.Client/devops/circular/index.js @@ -45,7 +45,7 @@ if (circular.length) { mkdirSync(imagePath, { recursive: true }); const image = await madgeSetup.image(join(imagePath, 'circular.svg'), true); console.log('Circular dependencies graph generated:', image); - } catch (e) { console.warn('No image generated. Make sure Graphviz is in your $PATH if you want a visualization', e); } + } catch { console.warn('No image generated. Make sure Graphviz is in your $PATH if you want a visualization'); } process.exit(1); } From c0f3c6fe5d9aa423301659401022f2f8392803b8 Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Thu, 9 Jan 2025 12:35:35 +0100 Subject: [PATCH 16/17] build: make script not fail CI until dependencies are fixed --- src/Umbraco.Web.UI.Client/devops/circular/index.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/devops/circular/index.js b/src/Umbraco.Web.UI.Client/devops/circular/index.js index 34b6664cee98..4683c12e7c21 100644 --- a/src/Umbraco.Web.UI.Client/devops/circular/index.js +++ b/src/Umbraco.Web.UI.Client/devops/circular/index.js @@ -47,7 +47,8 @@ if (circular.length) { console.log('Circular dependencies graph generated:', image); } catch { console.warn('No image generated. Make sure Graphviz is in your $PATH if you want a visualization'); } - process.exit(1); + // TODO: Set this to 1 when we have fixed all circular dependencies + process.exit(0); } console.log('\nNo circular dependencies detected.\n'); From 675e511caac489fe2fe99ee6c492f7922f4d6974 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 15 Jan 2025 09:47:34 +0100 Subject: [PATCH 17/17] update script in package json to run devops version --- src/Umbraco.Web.UI.Client/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/package.json b/src/Umbraco.Web.UI.Client/package.json index d36eb74cebd4..d1021a8ce58e 100644 --- a/src/Umbraco.Web.UI.Client/package.json +++ b/src/Umbraco.Web.UI.Client/package.json @@ -158,7 +158,7 @@ "postbuild": "rollup -c ./src/rollup.config.js && node ./devops/build/global-types.js", "check": "npm run lint:errors && npm run compile && npm run build-storybook && npm run generate:jsonschema:dist", "check:paths": "node ./devops/build/check-path-length.js dist-cms 120", - "check:circular": "madge --circular --warning --extensions ts ./src", + "check:circular": "node ./devops/circular/index.js src", "compile": "tsc", "dev": "vite", "dev:server": "cross-env VITE_UMBRACO_USE_MSW=off vite",