From 84319e616fcb334ca9f9640e071e746bd7f1bd5d Mon Sep 17 00:00:00 2001 From: Martin Grosche Date: Fri, 2 May 2025 16:12:53 +0200 Subject: [PATCH 01/17] Add build and deploy workflows for browser extension (#3) --- .github/workflows/deploy.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index a581819..2a6cedb 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -11,6 +11,9 @@ concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true +env: + DEPLOYMENT: 'False' + jobs: version-check: runs-on: ubuntu-latest From 928b53b072ed5d0aed89bd3eae41422c0187c813 Mon Sep 17 00:00:00 2001 From: Martin Grosche Date: Fri, 2 May 2025 18:01:29 +0200 Subject: [PATCH 02/17] Add integration section to Developer Guide and clarify build folder note (#3) --- docs/DeveloperGuide.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 7ee4757..79ec3db 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -84,11 +84,11 @@ cd ./dist web-ext build ``` -This tooling also provide a help in the ['signing' process](https://extensionworkshop.com/documentation/develop/extensions-and-the-add-on-id/) which is required for the use of add-ons without debug-mode in firefox. +This tooling also provides a help in the ['signing process](https://extensionworkshop.com/documentation/develop/extensions-and-the-add-on-id/) which is required for the use of add-ons without debug-mode in firefox. ## Testing / Linting / Code formatting -For these purposes there are three additional scripts which execute the local tests, start the linter in the source code and do some code formatting: +For these purposes, there are three additional scripts that execute the local tests, start the linter in the source code and do some code formatting: ### Prettier @@ -100,7 +100,7 @@ npm run prettier ### Linting -Use the internal npm linter with the follwing command: +Use the internal npm linter with the following command: ```bash npm run lint @@ -133,10 +133,10 @@ Those workflows are running automatically after having some changes to the remot * `deploy` * Chrome * a Google Chrome developer account is required - * any secrets that are neccessary for the publish process are set as `Actions secret` + * any secrets that are necessary for the publication process are set as `Actions secret` * any additional information, see [Publish in the Chrome Web Store](https://developer.chrome.com/docs/webstore/publish) * after publishing the application, a review is mostly outstanding and has to be publish - manually afterwards + manually afterward * to automatically publish an application after the review, check "Publish '' automatically after it has passed review" when submitting to review From 0409220e3de2bf9d13a22e1e4b4ad4cbd940b415 Mon Sep 17 00:00:00 2001 From: Martin Grosche Date: Thu, 8 May 2025 08:17:30 +0200 Subject: [PATCH 03/17] Add review notes (#3) - fix tag pattern in deploy workflow - add GitLab information to manifest description --- .github/workflows/deploy.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 2a6cedb..a581819 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -11,9 +11,6 @@ concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true -env: - DEPLOYMENT: 'False' - jobs: version-check: runs-on: ubuntu-latest From fcbb7dfda1e17ac0bee2d05b79d6cd521cc9fc6a Mon Sep 17 00:00:00 2001 From: Martin Grosche Date: Thu, 8 May 2025 13:22:13 +0200 Subject: [PATCH 04/17] Add browser-specific settings for Gecko in manifest.json (#5) --- static/manifest.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/static/manifest.json b/static/manifest.json index c3c4b0f..372fd02 100644 --- a/static/manifest.json +++ b/static/manifest.json @@ -4,6 +4,11 @@ "description": "Extension to open the ecu.test/trace.check diff viewer on GitHub/GitLab.", "version": "0.2.0", "background": {}, + "browser_specific_settings": { + "gecko": { + "id": "open-with-ecu-test-diff@tracetronic.com" + } + }, "permissions": ["storage", "activeTab", "downloads"], "options_ui": { "page": "options.html", From 17cbecab109d1d9526f3119b7aea5f59c6836f4c Mon Sep 17 00:00:00 2001 From: Martin Grosche Date: Fri, 9 May 2025 15:52:33 +0200 Subject: [PATCH 05/17] Enhance deployment workflow to support Firefox extension publishing and linting (#5) --- .github/workflows/deploy.yml | 45 +++++++++++++++++++++++++++++------- 1 file changed, 37 insertions(+), 8 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index a581819..122ec82 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -4,12 +4,6 @@ on: push: tags: - 'ecu-test-diff-[0-9]+.[0-9]+.[0-9]+' - release: - types: [published] - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true jobs: version-check: @@ -55,15 +49,50 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - browser: ['chrome'] # After supporting multiple browsers, this will be changed to ["chrome", "firefox"] + browser: ['chrome', 'firefox'] steps: - name: Get artifact from build job uses: actions/download-artifact@v4 with: name: ${{ matrix.browser }}-extension + - name: Set up Node v20 + if: ${{ matrix.browser == 'firefox' }} + uses: actions/setup-node@v4 + with: + node-version: 20 + cache: 'npm' + cache-dependency-path: 'package-lock.json' + - name: Install web-ext + if: matrix.browser == 'mozilla' + run: npm install -g web-ext - name: Publish to Firefox Add-on if: ${{ matrix.browser == 'firefox' }} - run: echo "Publishing to Firefox Add-on is not implemented yet." + run: | + # extract artifact + mkdir -p "./${{ matrix.browser }}-extension" + unzip -o "${{ matrix.browser }}-extension.zip" -d "./${{ matrix.browser }}-extension" + + # lint the extension before signing + web-ext lint \ + --source-dir="./${{ matrix.browser }}-extension" \ + --output=json \ + --pretty \ + --warnings-as-errors + LINT_EXIT_CODE=$? + if [ $LINT_EXIT_CODE -ne 0 ]; then + echo "::error::Linting failed with exit code $LINT_EXIT_CODE. Submission canceled." + exit 1 + fi + + # sign the extension + web-ext sign \ + --api-key="${{ secrets.AMO_JWT_ISSUER }}" \ + --api-secret="${{ secrets.AMO_JWT_SECRET }}" \ + --channel=listed \ + --source-dir="./${{ matrix.browser }}-extension" + env: + AMO_JWT_ISSUER: ${{ secrets.AMO_JWT_ISSUER }} + AMO_JWT_SECRET: ${{ secrets.AMO_JWT_SECRET }} - name: Publish to Chrome Web Store if: ${{ matrix.browser == 'chrome' }} uses: mnao305/chrome-extension-upload@v5.0.0 From 87fc461cf7338578d6c7388828943b1cea5e00e1 Mon Sep 17 00:00:00 2001 From: Martin Grosche Date: Wed, 14 May 2025 13:02:37 +0200 Subject: [PATCH 06/17] Add review notes (#5) - update deploy workflow - enhance documentation --- .github/workflows/deploy.yml | 12 ++++++------ README.md | 2 +- docs/DeveloperGuide.md | 11 +++++++---- 3 files changed, 14 insertions(+), 11 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 122ec82..4e65585 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -63,10 +63,13 @@ jobs: cache: 'npm' cache-dependency-path: 'package-lock.json' - name: Install web-ext - if: matrix.browser == 'mozilla' + if: matrix.browser == 'firefox' run: npm install -g web-ext - name: Publish to Firefox Add-on if: ${{ matrix.browser == 'firefox' }} + env: + AMO_JWT_ISSUER: ${{ secrets.AMO_JWT_ISSUER }} + AMO_JWT_SECRET: ${{ secrets.AMO_JWT_SECRET }} run: | # extract artifact mkdir -p "./${{ matrix.browser }}-extension" @@ -86,13 +89,10 @@ jobs: # sign the extension web-ext sign \ - --api-key="${{ secrets.AMO_JWT_ISSUER }}" \ - --api-secret="${{ secrets.AMO_JWT_SECRET }}" \ + --api-key="$AMO_JWT_ISSUER" \ + --api-secret="$AMO_JWT_SECRET" \ --channel=listed \ --source-dir="./${{ matrix.browser }}-extension" - env: - AMO_JWT_ISSUER: ${{ secrets.AMO_JWT_ISSUER }} - AMO_JWT_SECRET: ${{ secrets.AMO_JWT_SECRET }} - name: Publish to Chrome Web Store if: ${{ matrix.browser == 'chrome' }} uses: mnao305/chrome-extension-upload@v5.0.0 diff --git a/README.md b/README.md index 09214e4..a4d3d84 100644 --- a/README.md +++ b/README.md @@ -87,7 +87,7 @@ A detailed documentation on features, build and development setup can be found i ### Contribution At the moment, no external contributions are intended and merge requests from forks will automatically be rejected! -To report a bug or request an enhancement to this plugin please raise a new [GitHub issue](https://github.com/tracetronic/ecu.test-diff/issues). +To report a bug or request an enhancement to this plugin, please raise a new [GitHub issue](https://github.com/tracetronic/ecu.test-diff/issues). ### Support diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 79ec3db..39fe1fc 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -68,21 +68,24 @@ npm run build-firefox npm run start-chrome npm run build-chrome ``` -Your compiles files are available inside the `./dist` folder after the build process. - **Note:** Since the build folder is `./dist`, only the last build execution is present. + +Your compiled files are available inside the `./dist` folder after the build process. +**Note:** Since the build folder is `./dist`, only the last build execution is present. ## Integration -For integration and testing into you browser you have to note some differences: +For integration and testing into your browser, you have to note some differences: In **Chrome/Edge** you can just select the `./dist` folder inside you browser windows for importing the extension. -In **Firefox** you can test the extension only in debug-mode. You have to klick on 'debug add-ons' and can afterwards select a .zip file for the import. You can create the .zip file on your own or use the tool web-ext (from mozilla). +In **Firefox**, you can test the extension only in debug-mode. You have to klick on 'debug add-ons' and can afterwards select a .zip file for the import. You can create the .zip file on your own or use the tool web-ext (from mozilla). + ``` npm install web-ext cd ./dist web-ext build ``` +This tooling also provide a help in the ['signing' process](https://extensionworkshop.com/documentation/develop/extensions-and-the-add-on-id/) which is required for the use of add-ons without debug-mode in firefox. This tooling also provides a help in the ['signing process](https://extensionworkshop.com/documentation/develop/extensions-and-the-add-on-id/) which is required for the use of add-ons without debug-mode in firefox. From 85270c0b14c3871554071109b1e4181293fda6f3 Mon Sep 17 00:00:00 2001 From: Martin Grosche Date: Thu, 15 May 2025 08:38:14 +0200 Subject: [PATCH 07/17] Provide screenshots (#5) --- docs/images/firefox/addon_icon.png | Bin 0 -> 2745 bytes docs/images/firefox/configuration.png | Bin 0 -> 19113 bytes docs/images/firefox/dialog.png | Bin 0 -> 10813 bytes docs/images/firefox/diff_viewer.png | Bin 0 -> 30810 bytes 4 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 docs/images/firefox/addon_icon.png create mode 100644 docs/images/firefox/configuration.png create mode 100644 docs/images/firefox/dialog.png create mode 100644 docs/images/firefox/diff_viewer.png diff --git a/docs/images/firefox/addon_icon.png b/docs/images/firefox/addon_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..5689adfbdeb75ec2bc4e8a61b6f3684bc900807b GIT binary patch literal 2745 zcmZ`*dpHy9``>{%ZOkEUF^rr`!&|(em{U?Yv%RE^NKsCcb2i5e@gkO9=VVE!#KI7w zaws{JDWjqT6EZo>d{^)F`{Q?A-|rvK>2p8N=eeKjd7k_Jq&uFng^BMG2LJ#tyJJ?) z001ya(AN}&2x?BrUT;AI40pE00_uhozX}FI=PXWI008&1C3r+(!B{Nh7(N^TknH|d zfPKOAvjR|tWQ`-a1pAXBiD7;K+b}=BOW^^*ByTrS!4h$dot1@alsBh1I!Nvfs&B;o z_?B(CZQ1pJ8k_PgaSJ!uI+~&4C5En^up)BTh>!>du0kWjXhpg`pnZjKACPb&Tny`o zB^UKGp3WTKqhg+wr7vBm4*{>SdVg@X1_wN+>Pk7qW=nNHw(OJ#2W}b#YbeZaO+*{c zn>yj~uv8*qt`*i#CL&UaNDQ9HWhi>D z5Ieu7%7)S-h4cy~Qi?xYmmze>t2%w^79J{&}wS3%gZAT7shPon(EG!Jp)KEUNnQNlE@~BBFb;GPPPg- zg{&db(S?rgYv!%>`sINYfg>DWS_@rA56)h>Io~}cLh?;5()Fk#^46PAh{3}@>vg?v z{rM=~Qn>hlw)R;5@Ni|{pr7;Wt{ks4D5mu8YNqIx?pms|2Lx=i1yl!<6@2jRZ>EMx zg0mm*G+3XzDe<=XyNbBDUf@q7jg5`M!NAJEQO-F8N~$@#9<^fUKn>nL$_=XI+)|Ed z68p7#W24(8>46)07x-EkEL|O)&@Zn#0=ZI$l| zP~C#IYG^;`*dV;Fidtv?b$5HpZhFn82&5YpdeZ<;ta}yqA3WlRSPt_TIAwTB! zKOCH`>7wqsE3JH#>Apj#kfrQ(#pVF#T&g03r?!Qchzf+kAM_XatdV~Ekgzbl_M-b@ zDf4;cHYKb)R=h9>dQPO&F2bO)haM^Ot1E-8X!g5flG@~Tth{sIM-V#jW? z)imb}7rusqcfMUlZKeH#9X>iG6Df9@9L^+5U?I`l+jh-9DjSk5PirA*hJn=f9quAwi9EfuHIgjo&%BV0b8V$=JropN@aL z0&a%3;hCFi9DT}%4AH$c@WkafCxJ_ku*q?8o@fv{DLVlc6lzE1A-gBzCXF z+ZefHUKQWflT>`BUtc^P;j0fVhqOMgx#Yg2j8kpuIES4dm6sf`diqqIcEk*?n`oEk zUvcY}YphqtcH^KbYs<8cTgHnehFNW;iRIx+tH&X8WKlTzmTyaA$yj5(Dk|#m`p6*kIoFvSlNHEA*AQZfMNvfx$ldH zPh(-V2*&q95NF{8T>$V`M}=z8oA(P+Mf0jFl@`l*L0%NSeImLK`ZhTk&$z)Ziz*f^mb4cEa5Wy-d7zh95dS5L~jNoZqt2U)t; zj5P&nWLCY5T78p+404rz^+4asJgT33#k1kkd;f=71*D5%XMCSc^YbIjo7>Gv4up{1 zD&?rDZ2KO%cdNAFG`!dPGvPvY&_9a1MfRPS`e=sc??*X3yf2lx02O!{7ItnL4gRjJ zoQ_&7F?glu;AXEiPWqc4vsxu?{`3G6Za|Py<~!gdD0NxZoyHch%Xu4vlo6BKrK3$# z7d%HMW8UX4N*=mK`gsq(slcH<>G2e5yf^>Tc&UKW!a?z~&`B>AGPDBC_FSbxVz{8q z^kCjc@6H*IK9&73`UOAnR0+$p^rp4W$wX@ud3A_hWFn{aTBMe3P^MCUPN%Qh1YEEG zg(g|)8^{hFbrJk9UIDONyu5ZFFWFqREYMdPb1KB%+;2#VaEs@)uQYD7fTuRRW_X_; zA351wEXLALvNld9i$)?HuS1X9TDQ(%4s%6XsI5Y|ppz)rf;ewOef~z*vuox-ngky? zonA?sh~BWRFRa;S=t5IV`%{xE{$(eSV~3kc1o=`X2P(QbskZ7rTxD;~+RhR?Et^3O zrJ5`h=dwU<>gC(t3FEbLhK^r}_j#dsUl}n2%%bbG%^P*b_CkPZTZOeAzSo)7QB3JIAph6dgRK$y_2 z)2(Ya<{R_FR16G_2rHj#U&28a5L&%8R%@~JT19nl`KJjd#+%EC8gFB+sV4)kG0vC?$v)-4z4ssF-)Z0syrU~9*n4M zPOJ6sR8Z9qZSR}3rU(+@`Rl=l{q4#pguE^(9f*?kC{mwZqd(GON4;AdYy59o1flUE z2iQCNza>m6@vU^%^SsL4yZo!zT3qKWNc`%0=4%`yxfTyW@{=)5(P2 zQtH)Co9*s^%$?uz=-4sQZzzx~;vejf8j*hiwivEoY@_=Uuda`Kv@FptWR0h IVF`)<0WYQpKL7v# literal 0 HcmV?d00001 diff --git a/docs/images/firefox/configuration.png b/docs/images/firefox/configuration.png new file mode 100644 index 0000000000000000000000000000000000000000..0279c4cf7fbea48adef965e6799210adb90f96b7 GIT binary patch literal 19113 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 literal 0 HcmV?d00001 diff --git a/docs/images/firefox/dialog.png b/docs/images/firefox/dialog.png new file mode 100644 index 0000000000000000000000000000000000000000..f5465d2b5aadee8468535e2e82dd5f2742b03709 GIT binary patch literal 10813 zcmdUV2T+sS)+ipt4ycHQsvvL#gVH;QfS@!f0jUwxK&VmzLTJi4bcl#jLhleDfIyHg z(i8{?frJ*~0jVJ%C85LrMeq6N-ZyvNym>SKy!$ef2fc63N)Vg)_UY^;tuupwex(&r0x0anVXlRySFX)1Tf@A^?gls z(-*eXbk-N9GcQ*}uAE;}|9CX?=*`y;+rbatKiU(u9f~65B>I%uOr5GJTS8OK2+nki z;wbM(`wl{mPhAB6B}D6DPGSjsRKVGF?~yg%TP^EoGgkWKRs9TbPTb5|%Ziehu%DEl zgXGIIBDY(}>wDM~1&2O_r{washbmMcDR{S>7VEzMZZ>fJlnp)BeIbnd5~WM6S@-Zq zs1=+P+`@Mb_;?k$ijUi3TV0|@g{xdIRvtPm&zR5OnhO+DZF?i6JG{4ddJK=%=3m-p z`gh%Hp!^d-yT}?SuAkN#e!y~7KtRBrO@EP$ z*vmbRvH}P_m>f~PSc~>VlnVP|`bh=}_Bt$1fFAdo+xa`1nwmWFW3tgBR%(G9448y+ zq%_djeq>%VV6Go7oZR4_L6D5EK23BsrVKGlY?8Kf1imI#L>V z3OV~jCQ0mP>)GF$XFY`m8SuLwfx((T>73X?^}N$zFnHn!#H;Q+L!_CmeRCE!7hnaR zt{x4*%{<6s5d9QSVP%%S!}rl#rdc}I?PJg` zeYvgGAtO+dUr^bDQ&ex~_=20Ge0n@1?Xu+Jb!T1E%MkY`0~dIOOH{KWYE}m6)N$H9 zU8^5wn3#C__UxurEUO)jg@*0rXauKps)e6m(Gj>hphLPnhWmQVQ<+6g6g$t2ZtoMr?{k5@}JC2_LwNY&!C z3i!ZvPA%OFAXJ_fN!Cmli>?&U$&HID!bngq9bx*&G#d-ArA1Va6PnKH@m>bD3m&3n zS-JX1KU2xvi@8Pl$(wucQbJC>Dr;;u;M7nFUAwqxB;mbpeUGK%@y7Sa@ygs@~TOH^E4r?TfGa@Lwo zqNyR#i;P7AvEVsD_qe-X3%^5Q0@aAR3}_qNZWlQkaAhfbr^l5?uwSZUW=}(q^OsX!*64C;YI+il zf{YcUH;nC%E0pNy9yH_pVdDl=r+##)mj*-tluB-qv!{;Lc%|BQ`=oL!`m~hsT6s2= z?fkGkjn!D8B#;m>I?N%~KU%%SYUE|wcfQ+~1&F6nRswM|{*Sa!q${Njc@w=)41)D3RkOlFaqV(_sV!{UzR zLd2+BBsgY)28Ik*h8h=MDsmhetzRuptp2MC7E~jUpC4t~Z%({2@vXYXCSz_pr#qti zmPOJdXuv*ze$&W|!mT-05rGzo`I`0CF9+;U4D(7H7^>74YnB|ViorLHPq>vN7Gj2B z@0JmQFZ5?%^;j>fXHg|LKZ*5hqJ$1qlP$AfxvgI)dNE;Mvq)PW&xUK{s>(_GnHVGu zWQ!~ga*pd296x;cAZ7AK>oKO|8eJF5nmaDp25uw{kG&za6z*~|_7@rt9g&6%&mPuY zy5fL2<#V|>K2bSpU@t_R*VX5!P^XmpL$9j!Tl?P!-pq1)7g(4@dTivgx6dumKC6!# z((>!?qq+UUFxK1LQtk~tEiW>~`JAUJKQ2||NNwQ1vpipgiy3E+e$hH^KA+d(XIj2A zk-zD?Vx~Rk548;+($VGffHnW6SJm_&CKtZIJnONpI|fbU4Yq&~1_qscHaH{kUsyO3 zWH$S{h8pc+-L^c_yK#G=r*cv6zt`G~Q(x-JC_b8#a<6zI=iC!l`%KQ&B``EBh3xn6 zX+!}T+fiz$M|Iz;N=$>~=0w?vDqxIYsUkt?q_gXr@HjRsi0Cb4VBck%TarLTb!6T$ z1z&fv7kl*BDeqZj^B0}y!(|pDaAwsbLswF<`N6h-x`OnGt%ifxOvc-c>M~-ZkrC&G zi{7qnUCTogUxZ)uN}f7}m>d~&BGi6rlsgr}nJ~B5*M+LF!?Eso+SK{su5#Wh{Om># zjjO&%b{^Z&(63qvy~|-KBL#0mv98imES?Aqx*gvPi%Hix=MUugx1Wc}rTpH{kh~CmMkhFM2YFVAP_$X6FBe`@p=~$tniA|$kNoKJ5 zs_s{MV4iO#B%LljKb5~(vc2Cfz%B$BKb1WJ(1=}9y;9zg4&^$rP|4&(oY}}TINK#< z2c*GpFZnGr{H-6av0z!ki`N@I^-?TkMW;g4BF;eG$>$TNPZyUm@7H?QR4jLc3f0Eo z6^(T!>dXzrirniGRiK=6tTOQr`FTWLtyD=j%O!)Zmu)yYaF?aKVkyr#KH_VXM^yni zyWX~gid@~iZ&aM3>h*4OlgC95gUtLU{+D`a@2+cs8Qe;z#0)1LETZK4D3l;VKDzo@ zVuh6>oD-T~?@l*!9mkTA1L#))7WLMTt%SDD20m=aLg;kKI;)pO*0w?eDXG0_gG%}| zs1iH1t_=Ti!GP)W$;!=*^37ZN3Ns68e~zvX&D(?a`MEdDbPg>y814a~kk{J%MItAp zHk<3>l@gXz4nx}Yb;S+mynLIk->UR;Q3KQ;md7MD`{{pjaNdy2HuJ|UzYjOx(M(M= zL>5(aw})6f?^Qlnh$#}irv>)&j1|x}zahCj`{H`LVJw^6bh6`oZ((SJ^kFP>s&tED zM8fD5w;k8Xw-C)))pJJrw^AkrQ^;zhFSp%)sQ&JS z)Kje9_YRAkI>ph^ntyCnN8DUJ&&*t9eD|CL;Hh|aK~+XT&CA5-=2Y2DKyVsxn^}I( zUI6Bj_F0)UdLJWzv(@&_?c+1SOgXAgnVJnPg&?ow$3qq9rp9yc2QjI-vvBze9ZH)b zef(Tq2$r@(9}%chuIjs|wEWGk%V}*i$$5c;u9)B3j{JHd<+50Ck z&!RmW%bfmQcyNOKvr14O$g(Qi0!iAf-7$8xK=OL*z`edSvK>DU3$*Myh^v<89owH0 zte-|eh8Gf?!C=|nRSQTdn_CYjO{aRq!CHBiPNDj^`g-A<#i)qI!{rrI z{u{&}L;Vq_6$YbXy9`!#(ppRpcfyotpL-(Ppv+Q(OAef7j)Q+5&}t7{@elUV>m}gx zMDEF5cJf!hVE*nLfHNOQI`@6?OLcRnO*$#M;{AoUKR^3cGyAooez3_9}6qEC0fq5Zzt z13@mofZ_+LCWC&P(7g)|xU*WFNb|grJszZ7c!dB+o@8PFTYkZMUs&%3)qBnoC);yN zriXugy3r3Z*>+`C<@M&v@JBt8fs>__vvc)#PXj*kzCkcazQUzO)@%BXzoa&5-3|+# zd$V(EqrGqDp_b(o_o?pa_Y)QcHgZY5l&_mQlxao!dMvY(GuXLAV#eEi&8_z@;ol@} zCZ9!;10Fsj6j$5WDG@z`vGO`0HrQ+Ff`UBBaeh4-*HtW$id>q< z$1=Bey*?vbaL<4unGOvqcPp&GzgcJ^pl9&-7Iy#hd+CVYq==>5UfI+S6_n_wfOkLd zyF(F_5BgwW7qI#d_lb5;^H8e`LYj8YW^>IGYN6nld!1;wF6w4v=TP&Ex{X9}wU>%g z(mQaTP>$$9F3@67_!BPs zSzpRtBev*dSl>3sxag|Vi@2@4=;~^Uvj|-~?}~lu@Qbw3S$eK$jtt7Ljmy>1APuTI zmwXLf%xCvom&F_@Bb zgG=&*X=u2fM{}3-Is&(=>NuGtQ`!y{qqpE#!Fo_|>HG?zGdiGhpiZwD^1EQC7W z!nYNhzui5tJXND@kSi6mxb!)JD1?%KuI4Xzzh0-Ox_O@ymbm4^Uue&vuq=O$1C-m> zY-H#c5NF^%;YQ();D-e_tVQEcgiz;XDQ6?NFQE zKk}~O5g-H9ruub7QxV(xyXhqtoCi#Z83li7*~BMHThjbUdjZ|SWx`Aj=J5ScF>&o- zrf*rWfdsWvuf!VN*M_! zwvYM3=CDbF0lW{1$5VU)pSyf`YD+%2PBIV47pZe=axZa7;x*9*ypy@~w>Si7TlMqQ ze)7J#r4W&{{p}f3Na*zg7K&l>#P-a>?wIdlq;2zKQqV~yNCg`ZqCSuCdqQ$m5ujq> zeb1Dbnf?xFpSQ1u$8K&!R3l^$t|cqp{_mJro6lV}H=NJED7D`^sB`*fNcbNX7ym~@ z@K8=z1n_y`C^UE$NS_?fN?T^6E&d;;4E`gQ=HF&a6dwzeO_#;`f6ET9o;7zr*3WZy zOtyG|KI2qBCpW7ej&+^LbC7G!BD9;v|RUU zSEoU0PwEB!K8@Mc$)P8)(ZfS8kb{jpK>p~n1Ec}l=-DK0A)${ySQV?M&&&ZM)Pn~lY`%wAyTO)>) zZVu>tW29F#7Nlwv3#Td8`qU?O@pET18;kVH8*Ws1pe-{;=L(!n0CuEZvg34_g#yE9VC-<8NGFvO@ zHebJmr109E?YJSc2 zlCd9o%z5F$^_yI8A;^jvQu&facds{TJr<$)JW~$_FGiB=PQgzXw%n0|eiiGZ!6)XGt zdQ8D`7n4HYP-Ye5FJH4;->6Q%#KiRYjy)ZrhRUxB8cII+eY9C0)w1NB-qgFqjZm3M zX9deyRp8D1D`=|IM4jc+Op@I+?mAwNbZrtZY+%#Yf+gUl1qmKD3JFJ1E>4 zo2WxMrw5ga#+94U_Vl4^n)>P67WylVAA8w|UHEiT5X5(%;N;VBbokxS!o>HHO9sXr z$!Y`7cXw-0e%hub=u%@2sPz1f65l{{+T>BDkhW7*w{#KLK?OL&jH3GBQhcPLaR1{g ziD}}jH{P5&&5?K}VOEt(Pda%Y-5Vr>i`#nr7qDY{5!EB2xSMMFw7RHjjzZ^&?<)(% zvrrik(t8c})T`ZodEm@!6SVk{r|(h{7Ur;4-}I=#XCE3H^dc~H5y_Y1A*j7Lo3q4hF?NbooG(uu>c8+! zT8^#VVHt!v)4KLXPT<13w~Iyh$-|xO2?=w>So?~o8&3p2Nk^((wq&97 zoM)RxcuuaGVRxw;Gcq_YrWL@-0 zi$%2Jko%Em&j}pW&p`U)5;aUK?>Fb?TtkX^4=e}aDJ|# zG>+4q^gWD^(%y19IVJedGaF9BxlEWWZ7aH|xgXc;<4y!fOHoe05l-aWS<4 znM3C|%yv?Zed&bC9=5>C%9+l_M8V-B+%RMyA|{Ss&N%)S zX2W2mqq`O;MmTZob1QmfaSz9{XRdW$>tQjAg- zkwLThAl0oA@zx-4L&WlM)<St7 zsqT79YF_$_^?8bq1ziot`2wG>Y%3t85gYYRm#tK=HBRLX>?C-@0r?NgM&-5w(c6k0$-IlI4vMK3YeDEEnHmOLzvLUay}7reIE<9(hj_>L z@j!}KAq|jns!f@~@G$!KICS-(xI>)T@g75dD=~P`(=>xEyi;tknu*Chu+z|XErlE^ zhuW=IIrOU)zZ{IlkR8b%TI<1l^f;BZcYFq{4iU z&GL<|gg!!HtEv=nFIwg$uR`k=MjytT8jbLi>nx z#Kx8SK;m(K{GLHqjFO3Y09pC)hm^mwFOdR7nRCwhyVm0*MTg#Df5M&%#CPM12~DI> zdeOY^GJwZ8>2S~wHwm>d(f!G&W0)Y!9R+)`LQ#BdUv9p;G2}!oU-l&TrxB}FO4Kr* zzdG2WV0zwq>d%e9dQ)}qv7v}#j~)ZEH!3w4N9bU8A<~J~kd;O^mwrS!B_&)xFYxfU zSQTgn-)UPSIi8;4)lyJAU9c!T$EwYscG$2pMdlU`r_2@j5t{W_W&Rsr0iAxF$CP4&6X zSH3spkYO%$b|A}2-2tbWc}WyNVyD~TJ(+6O64}Y zk2lp8Zpo7(BO=0csqPE3%?5H-?HtY7`;#H&i|SW;bMeTfF8T>+XUu)xTVMfPGH}?J z{qoeic%<&n1^s0YiY3cGegzwtlRTPbDoCp3C|+j1I~Qyuri?7b5* z0ZT0F*?7pZE6&J+ zz)`&_w|8g^#*DUFxcF26xaCHk;5X4Q(d^KN9%8F|hLrBus7dbHYUwtlA0t6jv?ZiK z#4SP>{IRyB+ArO=GE6F%MFdRT+vH{j&dxpJf}uG=bg0Py)RciwKc1&T8ih-<1ILEr zr?U3rht(HfFIiyjXO68_+1ZA(T5kQ28ao)%wLIKkK%ZJxru8EuB9b$I_TJ`zMRzM7 zF+&^5-t2bT`M3_=pTa=q0nOXH?6;y&wtv7`Kc5rr-2tN1fJy{?|5>4j0WTw$80sIm zW(MdFJYi`12Y_@42>AEPG)vh0yr0)ZGBmwdJfr)(1aYg=`&ay_@_%Ss{uw#SJf05W z56U71kL3Cu_9K$>eGsG6+3^ejxAyzLEeb0uH!r`>66?J`T`I8+^ypn#s$zC zIKFcNU)jzyke2A{uI51bfZ*_dLs(xice$yNeY7++m5p(~X7KqGV{*TSztagVy$S@+ z66AkO@BbQDt$dZRmPRPGE`En>EX96PSTD8Au*!WmyRB`z>@Um9FuAj-zZNd>ZWopl zB?nJKcjrVUf?@3^g9|z{U5yYolkIlT>)*)8A8u{?T1k;AHnN&#$1a8+x}pzeQ@(d| zjS-ya6?P~e8gKoRZT}|x_J#{9x2(Q7*&{r$+)y=@@1LjUHCq3WBU;4iVA{R7O*O8D z5*yniz0z*S<+GZ*b6eFgcTs@(_rax|AtAvsFa?uZf;i89KKXLA0c4p+UAMx=#}uEm z8FUnMlCjg<&|k8k-~y318eW%UL0T&gohz3O<$wW!pg+Rb^Hq2pDW#DAwnWX!So(=C zZt=5rw3}K`nqK#CmB5;E`o(|Y&CyELCcd6!Y$*-2q^>-;C{2wSKyyjl6%4yr^1&yA zP;(3qD&zL1y_I~&DuXZSHdWp`BjcviR{@TN!=08&MR(-~sYQgHFgxL_0I_p;N>58( z{Ih4Pl_gN*lHH^#xsQ z7bN}Uzc3c*YKFhk#wlYY<+ixJvp8{&wAvoM=yUsKMD>btX25%m{@_A`nWR#wlh1DV zIHt*4OC`GM@+?StE4N$?;)2_qg{ID$mo(q_z}72XUT-;^UU*#&7DV&j?$g9#GV=f8 zm@BE;>^(8=mX7gs&trLh9T3LVkbj6DJ6(D<+OTw}yTg28uUHVw!;2X$36=CT@b!7` z_p(!1xinp?MW81-!B zY;03*!H)lEsM8mdv=!;$5)8$s>m@ov&G*j6L+pI2=R66*6VR&t_;jG#lGmI|5zJFnr?`#J~< zZ@8okZ~=bYxU((7)RAK<6Bci*6M(5Ei~Z7LW!%F4X1(~K_>R_eBv@2T9REkO`2y|f zB>-DujIZypMtt5*1R}|y_YadHg|S(|0;0K1>DZJ#E9>%dnrB9&3S+XBp-Mr}hA7msLL8Y@+(1URU@jdd3WARz&rze?Zp^{f-43h?P?Bf+Q0f-;MBufv$1y+2p$L&tCO!8GE~X81Sb=d(M{$pDDkHOgVP z$L+CSTvD|}MS%;myEwB{l}2cPsHfBsK*sHtYjDrTdt{ScCB~m(ae8^YxtNFC*ATI& w^wvolOf7>MAbQTL@K@>M8x=Dng}aCRYsO6x2lG80j0L!_WuS?<`}oy=0YhQim;e9( literal 0 HcmV?d00001 diff --git a/docs/images/firefox/diff_viewer.png b/docs/images/firefox/diff_viewer.png new file mode 100644 index 0000000000000000000000000000000000000000..a9056c66416a6c84b35ec70cdcea5811c39ce016 GIT binary patch literal 30810 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 F{{(Xm%47fl literal 0 HcmV?d00001 From 6361efc4068820b28d44ee3211e026b188f3e9dd Mon Sep 17 00:00:00 2001 From: Martin Grosche Date: Thu, 15 May 2025 18:38:23 +0200 Subject: [PATCH 08/17] Use only tag as build reference (#5) --- .github/workflows/deploy.yml | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 4e65585..0639fda 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -8,9 +8,6 @@ on: jobs: version-check: runs-on: ubuntu-latest - if: | - startsWith(github.ref, 'refs/tags/ecu-test-diff-') || - github.event_name == 'release' outputs: proceed: ${{ steps.version-check.outputs.proceed }} steps: @@ -31,8 +28,6 @@ jobs: echo "❌ Tag version ($TAG_VERSION) does not match manifest version ($MANIFEST_VERSION)." echo "proceed=false" >> $GITHUB_OUTPUT exit 1 - elif [[ "{{ github.event_name }}" == "release" ]]; then - ]] fi echo "✅ Tag version matches manifest version." @@ -45,7 +40,6 @@ jobs: publish: needs: [version-check, build] - if: ${{ github.env.DEPLOYMENT == 'True' }} runs-on: ubuntu-latest strategy: matrix: @@ -75,18 +69,6 @@ jobs: mkdir -p "./${{ matrix.browser }}-extension" unzip -o "${{ matrix.browser }}-extension.zip" -d "./${{ matrix.browser }}-extension" - # lint the extension before signing - web-ext lint \ - --source-dir="./${{ matrix.browser }}-extension" \ - --output=json \ - --pretty \ - --warnings-as-errors - LINT_EXIT_CODE=$? - if [ $LINT_EXIT_CODE -ne 0 ]; then - echo "::error::Linting failed with exit code $LINT_EXIT_CODE. Submission canceled." - exit 1 - fi - # sign the extension web-ext sign \ --api-key="$AMO_JWT_ISSUER" \ From 34982dff9b0e1cda47d8dfabac548d130cb3ac89 Mon Sep 17 00:00:00 2001 From: Martin Grosche Date: Thu, 15 May 2025 18:39:06 +0200 Subject: [PATCH 09/17] Add build validation for firefox (#5) --- .github/workflows/build.yml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a0d69d5..fd71df7 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -48,6 +48,23 @@ jobs: - name: Build extension for ${{ matrix.browser }} run: npm run build-${{ matrix.browser }} + - name: Validate build result + if: ${{ matrix.browser == 'firefox' }} + run: | + npm install -g web-ext + + # lint the extension before signing + web-ext lint \ + --source-dir="./dist \ + --output=json \ + --pretty \ + --warnings-as-errors + LINT_EXIT_CODE=$? + if [ $LINT_EXIT_CODE -ne 0 ]; then + echo "::error::Linting failed with exit code $LINT_EXIT_CODE. Build validation for Firefox failed." + exit 1 + fi + - name: Upload extension zip uses: actions/upload-artifact@v4 with: From e7acad5f4bb8da99c159db68670b69342c75b212 Mon Sep 17 00:00:00 2001 From: Martin Grosche Date: Thu, 15 May 2025 19:53:17 +0200 Subject: [PATCH 10/17] Refactor standardize npm script naming to use colon syntax (#5) --- package.json | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 9e3d9f9..a43c229 100644 --- a/package.json +++ b/package.json @@ -3,12 +3,13 @@ "version": "1.0.0", "description": "Browser plugin to open the diff viewer of tracetronic products ecu.test and trace.check from browser", "scripts": { - "start-chrome": "webpack --env TARGET=chrome --watch --config webpack.dev.cjs", - "start-firefox": "webpack --env TARGET=firefox --watch --config webpack.dev.cjs", - "build-chrome": "webpack --env TARGET=chrome --config webpack.prod.cjs", - "build-firefox": "webpack --env TARGET=firefox --config webpack.prod.cjs", + "start:chrome": "webpack --env TARGET=chrome --watch --config webpack.dev.cjs", + "start:firefox": "webpack --env TARGET=firefox --watch --config webpack.dev.cjs", + "build:chrome": "webpack --env TARGET=chrome --config webpack.prod.cjs", + "build:firefox": "webpack --env TARGET=firefox --config webpack.prod.cjs", "lint": "eslint --ext .ts,.js --max-warnings=0 .", - "prettier": "prettier --write", + "prettier:write": "prettier --write", + "prettier:check": "prettier --check .", "test": "c8 mocha --require ts-node/register ./test/setup.ts ./test/**/*.ts" }, "type": "module", From 930c5967b067d63c490ce96ab9fedbfc3dd3fb81 Mon Sep 17 00:00:00 2001 From: Martin Grosche Date: Thu, 15 May 2025 19:53:44 +0200 Subject: [PATCH 11/17] Update npm script naming syntax (#5) --- docs/DeveloperGuide.md | 48 ++++++++++++++++++++++++++---------------- 1 file changed, 30 insertions(+), 18 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 39fe1fc..08830fa 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -38,7 +38,7 @@ This project is based on the boilerplate [Chrome Extension Webpack](https://gith ### Install node.js -First you have to install [node.js](https://nodejs.org/en/download) to have access to the package manager npm for building the browser extension. +First, you have to install [node.js](https://nodejs.org/en/download) to have access to the package manager npm for building the browser extension. ## Development Setup @@ -51,22 +51,22 @@ Open the ecu.test diff project in your IDE of choice and run the following termi ## Build process -If you want to build the ecu.test diff extension locally for development purpose or for production use, you have access to different scripts: +If you want to build the ecu.test diff extension locally for development purposes or for production use, you have access to different scripts: **Note:** All of these scripts can be found and modified within the './package.json' of the project. **Firefox:** ``` -npm run start-firefox -npm run build-firefox +npm run start:firefox +npm run build:firefox ``` **Chrome/Edge:** ``` -npm run start-chrome -npm run build-chrome +npm run start:chrome +npm run build:chrome ``` Your compiled files are available inside the `./dist` folder after the build process. @@ -76,18 +76,19 @@ Your compiled files are available inside the `./dist` folder after the build pro For integration and testing into your browser, you have to note some differences: -In **Chrome/Edge** you can just select the `./dist` folder inside you browser windows for importing the extension. +In **Chrome/Edge** you can select the `./dist` folder inside you browser windows for importing the extension. -In **Firefox**, you can test the extension only in debug-mode. You have to klick on 'debug add-ons' and can afterwards select a .zip file for the import. You can create the .zip file on your own or use the tool web-ext (from mozilla). +In **Firefox**, you can test the extension only in debug-mode. +You have to klick on 'debug add-ons' and can afterward select a .zip file for the import. +You can create the .zip file on your own or use the tool web-ext (from mozilla). ``` npm install web-ext cd ./dist web-ext build ``` -This tooling also provide a help in the ['signing' process](https://extensionworkshop.com/documentation/develop/extensions-and-the-add-on-id/) which is required for the use of add-ons without debug-mode in firefox. - -This tooling also provides a help in the ['signing process](https://extensionworkshop.com/documentation/develop/extensions-and-the-add-on-id/) which is required for the use of add-ons without debug-mode in firefox. +This tooling also provides help in the ['signing process](https://extensionworkshop.com/documentation/develop/extensions-and-the-add-on-id/) +which is required for the use of add-ons without a debug-mode in firefox. ## Testing / Linting / Code formatting @@ -95,10 +96,18 @@ For these purposes, there are three additional scripts that execute the local te ### Prettier -Prettier is a code formatter that enforces a consistent style by parsing your code and re-printing it. +Prettier is a code formatter that enforces a consistent style by parsing your code and re-printing it. +Select the files you want to format and run the following command: ```bash -npm run prettier +# check all files +npm prettier:check + +# fix findings for all files +npm run prettier:write . + +# fix finding for specific files +npm run prettier:write ./ ``` ### Linting @@ -111,7 +120,8 @@ npm run lint ### Testing -Your definded tests can be run with the command blow. The command runs all tests definded in the root 'test' folder and generates a coverage report. +Your defined tests can be run with the command blow. +The command runs all tests defined in the root 'test' folder and generates a coverage report. ```bash npm run test @@ -122,8 +132,8 @@ npm run test All CI workflows are located in `.github/workflows` | name | on | output | artifacts | -| :---------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------- | :---------- | :----------------------- | -| [deploy](../.github/workflows/deploy.yml) |
  • tag
  • release published
| - | - | +|:------------------------------------------|:-----------------------------------------------------------------------------------------------------------------------------------------|:------------|:-------------------------| +| [deploy](../.github/workflows/deploy.yml) | tag | - | - | | [build](../.github/workflows/build.yml) |
  • push and pr to `main`
  • workflow dispatch
  • reused by [deploy](../.github/workflows/deploy.yml) workflow
| - | chrome and firefox build | | [test](../.github/workflows/test.yml) | reused by [build](../.github/workflows/build.yml) workflow | test result | - | | [reuse](../.github/workflows/reuse.yml) |
  • push and pr to `main`
  • workflow dispatch
| spdx sbom | sbom.spdx | @@ -138,7 +148,7 @@ Those workflows are running automatically after having some changes to the remot * a Google Chrome developer account is required * any secrets that are necessary for the publication process are set as `Actions secret` * any additional information, see [Publish in the Chrome Web Store](https://developer.chrome.com/docs/webstore/publish) - * after publishing the application, a review is mostly outstanding and has to be publish + * after publishing the application, a review is mostly outstanding and has to be published manually afterward * to automatically publish an application after the review, check "Publish '' automatically after it has passed review" when submitting to review @@ -148,7 +158,9 @@ Those workflows are running automatically after having some changes to the remot ### reuse -To ensure open-source complience with our provided software at tracetronic GmbH we use the tool [reuse](https://reuse.readthedocs.io/en/stable/readme.html). After installing the tooling in your local environment you can check for open-source compliance with: +To ensure open-source difference with our provided software at tracetronic GmbH, +we use the tool [reuse](https://reuse.readthedocs.io/en/stable/readme.html). +After installing the tooling in your local environment, you can check for open-source compliance with: `reuse lint` From abf2fafb8a6a81b367ea312111adc1fc7ad3cb03 Mon Sep 17 00:00:00 2001 From: Martin Grosche Date: Thu, 15 May 2025 20:06:11 +0200 Subject: [PATCH 12/17] Add Firefox installation information (#5) --- README.md | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index a4d3d84..eaed61f 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ - [Description](#description) - [Features](#features) - [Getting started](#getting-started) - - [Installing and running](#installing-and-running) + - [Installation](#installation) - [Usage](#usage) - [Documentation](#documentation) - [Contribution](#contribution) @@ -14,7 +14,9 @@ Browser plugin to open the diff viewer of tracetronic products ecu.test and trace.check from browser. -ecu.test Diff Extension is a bridge between the current browser tab and an installed ecu.test. It allows you to diff packages (`.pkg`) and other artifacts from an open commit or merge request with only a few simple clicks. +Ecu.test Diff Extension is a bridge between the current browser tab and an installed ecu.test. +It allows you to diff packages (`.pkg`) +and other artifacts from an open commit or merge request with only a few simple clicks. ## Features @@ -36,17 +38,18 @@ Detected file extensions ## Getting started -### Installing and running +### Installation -TODO: The extention is not yet released on chrome or firefox app stores! - -Use the extention in development mode (this mode is probably forbidden via company IT rules!): +To install the extension, use the specific installation method for your browser. **Firefox** - 1. Download the relevant .xpi file from releases. - 2. Go to `about:debugging#/runtime/this-firefox` - 3. Click on load temporary addon select the .xpi file. + 1. Click extension icon in the top right corner or Go to "https://addons.mozilla.org" and continue with step 3 + 2. Click on the "Manage extensions" button + 3. Click on "Find more add-ons" and type "Open with ecu.test diff" + 4. Click on the "Add to Firefox" button + 5. Click on "Add" in the pop-up dialog + 6. Click on "OK" in the pop-up dialog (if needed) **Chrome/Edge** @@ -64,17 +67,17 @@ You are good to go! You can also pin the extension to the toolbar for easy acces - Select the correct platform type and add the host - Go to the options e.g., via click on the cog-wheel icon - Now enter your API token - - ⚠️Don't give the token all permissions⚠️ + - ⚠️Don not give the token all permissions⚠️ - Only reading repository and API access - fine-grained tokens are recommended -Configuration +Configuration - Save the settings - Go back to the commit page and open the popup again - The supported files of the changes will be listed -Configuration +Configuration - Click on a file and click on "Show diff" - ecu.test Diff-Viewer will be opened @@ -82,7 +85,7 @@ You are good to go! You can also pin the extension to the toolbar for easy acces ### Documentation -A detailed documentation on features, build and development setup can be found inside [docs folder](./docs/DeveloperGuide.md). +For detailed documentation on features, build and development setup, see the [DeveloperGuide](./docs/DeveloperGuide.md). ### Contribution @@ -101,7 +104,7 @@ This project uses the [Red Hat Display Text Font](https://github.com/RedHatOffic This project uses the [Material Symbols Outlined Font](https://fonts.google.com/icons) with is licensed under Apache License Version 2.0 (see [Apache-2.0.txt](./LICENSES/Apache-2.0.txt)) -To generate a software bill of material (sbom) we recommend using the [cyclondx](https://github.com/CycloneDX/cyclonedx-node-npm) tool: +To generate a software bill of material (sbom), we recommend using the [CycloneDX](https://github.com/CycloneDX/cyclonedx-node-npm) tool: ```bash #skip if you have cyclonedx already installed globally From 8fb5445795a331da252bcf429790672f9eb7246f Mon Sep 17 00:00:00 2001 From: Martin Grosche Date: Thu, 15 May 2025 20:08:33 +0200 Subject: [PATCH 13/17] Run prettier (#5) --- docs/DeveloperGuide.md | 47 +++++++++++++++++-------------------- styles/material_symbols.css | 6 ++++- 2 files changed, 27 insertions(+), 26 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 08830fa..ea44348 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -23,24 +23,20 @@ Please have a look at section 'Description' inside [README.md](../README.md#description). - ## Features Please have a look at section 'Features' inside [README.md](../README.md#features). - ## Fork information This project is based on the boilerplate [Chrome Extension Webpack](https://github.com/sszczep/chrome-extension-webpack) from Sebastian Szczepański. - ## Prerequisites ### Install node.js First, you have to install [node.js](https://nodejs.org/en/download) to have access to the package manager npm for building the browser extension. - ## Development Setup ### Install dependencies @@ -87,6 +83,7 @@ npm install web-ext cd ./dist web-ext build ``` + This tooling also provides help in the ['signing process](https://extensionworkshop.com/documentation/develop/extensions-and-the-add-on-id/) which is required for the use of add-ons without a debug-mode in firefox. @@ -96,7 +93,7 @@ For these purposes, there are three additional scripts that execute the local te ### Prettier -Prettier is a code formatter that enforces a consistent style by parsing your code and re-printing it. +Prettier is a code formatter that enforces a consistent style by parsing your code and re-printing it. Select the files you want to format and run the following command: ```bash @@ -131,29 +128,29 @@ npm run test All CI workflows are located in `.github/workflows` -| name | on | output | artifacts | -|:------------------------------------------|:-----------------------------------------------------------------------------------------------------------------------------------------|:------------|:-------------------------| -| [deploy](../.github/workflows/deploy.yml) | tag | - | - | -| [build](../.github/workflows/build.yml) |
  • push and pr to `main`
  • workflow dispatch
  • reused by [deploy](../.github/workflows/deploy.yml) workflow
| - | chrome and firefox build | -| [test](../.github/workflows/test.yml) | reused by [build](../.github/workflows/build.yml) workflow | test result | - | -| [reuse](../.github/workflows/reuse.yml) |
  • push and pr to `main`
  • workflow dispatch
| spdx sbom | sbom.spdx | - -Those workflows are running automatically after having some changes to the remote repository. -* `build` - * provides its artifacts additionally after each execution - * firefox - * chrome -* `deploy` - * Chrome - * a Google Chrome developer account is required - * any secrets that are necessary for the publication process are set as `Actions secret` - * any additional information, see [Publish in the Chrome Web Store](https://developer.chrome.com/docs/webstore/publish) - * after publishing the application, a review is mostly outstanding and has to be published +| name | on | output | artifacts | +| :---------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------- | :---------- | :----------------------- | +| [deploy](../.github/workflows/deploy.yml) | tag | - | - | +| [build](../.github/workflows/build.yml) |
  • push and pr to `main`
  • workflow dispatch
  • reused by [deploy](../.github/workflows/deploy.yml) workflow
| - | chrome and firefox build | +| [test](../.github/workflows/test.yml) | reused by [build](../.github/workflows/build.yml) workflow | test result | - | +| [reuse](../.github/workflows/reuse.yml) |
  • push and pr to `main`
  • workflow dispatch
| spdx sbom | sbom.spdx | + +Those workflows are running automatically after having some changes to the remote repository. + +- `build` + - provides its artifacts additionally after each execution + - firefox + - chrome +- `deploy` + - Chrome + - a Google Chrome developer account is required + - any secrets that are necessary for the publication process are set as `Actions secret` + - any additional information, see [Publish in the Chrome Web Store](https://developer.chrome.com/docs/webstore/publish) + - after publishing the application, a review is mostly outstanding and has to be published manually afterward - * to automatically publish an application after the review, check "Publish '' + - to automatically publish an application after the review, check "Publish '' automatically after it has passed review" when submitting to review - ## Open-Source Software compliance ### reuse diff --git a/styles/material_symbols.css b/styles/material_symbols.css index 05f0589..1bba4b2 100644 --- a/styles/material_symbols.css +++ b/styles/material_symbols.css @@ -23,5 +23,9 @@ } .material-symbols-outlined { - font-variation-settings: 'FILL' 0, 'wght' 300, 'GRAD' 0, 'opsz' 48; + font-variation-settings: + 'FILL' 0, + 'wght' 300, + 'GRAD' 0, + 'opsz' 48; } From 85589a73a425ff904ddb89a860905a428eeeb3f9 Mon Sep 17 00:00:00 2001 From: Martin Grosche Date: Thu, 15 May 2025 20:14:50 +0200 Subject: [PATCH 14/17] Fix unexpected EOF with never closed quotes (#5) --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index fd71df7..04e9f44 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -55,7 +55,7 @@ jobs: # lint the extension before signing web-ext lint \ - --source-dir="./dist \ + --source-dir="./dist" \ --output=json \ --pretty \ --warnings-as-errors From 620b0c249d63c2dfaa8699cbef888e3c8bbdcd69 Mon Sep 17 00:00:00 2001 From: Martin Grosche Date: Thu, 15 May 2025 20:20:09 +0200 Subject: [PATCH 15/17] Update build command (#5) --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 04e9f44..6086920 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -46,7 +46,7 @@ jobs: run: npm ci - name: Build extension for ${{ matrix.browser }} - run: npm run build-${{ matrix.browser }} + run: npm run build:${{ matrix.browser }} - name: Validate build result if: ${{ matrix.browser == 'firefox' }} From 528de65fb08517fb6319f302d673271a90a0a7f4 Mon Sep 17 00:00:00 2001 From: Martin Grosche Date: Thu, 15 May 2025 20:50:43 +0200 Subject: [PATCH 16/17] Enhance deployment workflow with browser input and tag validation (#5) --- .github/workflows/deploy.yml | 46 ++++++++++++++++++++++++++++++++---- 1 file changed, 41 insertions(+), 5 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 0639fda..d6dac81 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -1,12 +1,45 @@ name: Deploy Browser Extension on: + workflow_dispatch: + inputs: + browser: + description: Browser platform to build for as an array (e.g., '["chrome"]", '["firefox", "chrome"]') + required: false + default: '["chrome", "firefox"]' + type: string + tag: + description: Tag to deploy (e.g., "ecu-test-diff-1.0.0") + required: true + type: string push: tags: - 'ecu-test-diff-[0-9]+.[0-9]+.[0-9]+' jobs: + setup: + runs-on: ubuntu-latest + outputs: + tag-version: ${{ steps.set-tag.outputs.tag-version }} + steps: + - name: Set tag + id: set-tag + run: | + # determine if the workflow was triggered by a dispatch event or a tag push, and set the tag version accordingly + if [ "${{ github.event_name }}" == "workflow_dispatch" ]; then + TAG_VERSION="${{ github.event.inputs.tag }}" + # validate tag version + if [[ ! $TAG_VERSION =~ ^ecu-test-diff-[0-9]+\.[0-9]+\.[0-9]+$ ]]; then + echo "❌ Invalid tag version format. Expected format: ecu-test-diff-x.y.z" + exit 1 + fi + echo "tag-version=$TAG_VERSION" >> $GITHUB_OUTPUT + else + TAG_VERSION="${GITHUB_REF#refs/tags/}" + echo "tag-version=$TAG_VERSION" >> $GITHUB_OUTPUT + fi version-check: + needs: set-tag runs-on: ubuntu-latest outputs: proceed: ${{ steps.version-check.outputs.proceed }} @@ -18,12 +51,13 @@ jobs: sudo apt-get update -y sudo apt-get install -y jq - # Tag ref of release refs/tags/ as well - TAG_VERSION="${GITHUB_REF#refs/tags/ecu-test-diff-}" + TAG_VERSION="${{ needs.setup.outputs.tag-version }}" MANIFEST_VERSION=$(jq -r '.version' static/manifest.json) echo "Tag version: $TAG_VERSION" echo "Manifest version: $MANIFEST_VERSION" - + + # extract the version from the tag + TAG_VERSION=${TAG_VERSION#ecu-test-diff-} if [ "$TAG_VERSION" != "$MANIFEST_VERSION" ]; then echo "❌ Tag version ($TAG_VERSION) does not match manifest version ($MANIFEST_VERSION)." echo "proceed=false" >> $GITHUB_OUTPUT @@ -37,13 +71,15 @@ jobs: needs: version-check if: needs.version-check.outputs.proceed == 'true' uses: ./.github/workflows/build.yml + with: + browser: ${{ fromJSON(github.event.inputs.browser || '["chrome", "firefox"]') }} publish: needs: [version-check, build] runs-on: ubuntu-latest strategy: matrix: - browser: ['chrome', 'firefox'] + browser: ${{ fromJSON(github.event.inputs.browser || '["chrome", "firefox"]') }} steps: - name: Get artifact from build job uses: actions/download-artifact@v4 @@ -59,7 +95,7 @@ jobs: - name: Install web-ext if: matrix.browser == 'firefox' run: npm install -g web-ext - - name: Publish to Firefox Add-on + - name: Publish as Firefox add-on if: ${{ matrix.browser == 'firefox' }} env: AMO_JWT_ISSUER: ${{ secrets.AMO_JWT_ISSUER }} From 145dd101e062382dd0678194e1aa1ae480da54c6 Mon Sep 17 00:00:00 2001 From: Martin Grosche Date: Mon, 19 May 2025 09:51:29 +0200 Subject: [PATCH 17/17] Refine terminology from "plugin" to "extension" in documentation and metadata (#5) --- README.md | 5 +++-- REUSE.toml | 2 +- docs/DeveloperGuide.md | 2 +- package.json | 2 +- static/popup.html | 2 +- 5 files changed, 7 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index eaed61f..bd60244 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ ## Description -Browser plugin to open the diff viewer of tracetronic products ecu.test and trace.check from browser. +Browser extension to open the diff viewer of tracetronic products ecu.test and trace.check from browser. Ecu.test Diff Extension is a bridge between the current browser tab and an installed ecu.test. It allows you to diff packages (`.pkg`) @@ -90,7 +90,8 @@ For detailed documentation on features, build and development setup, see the [De ### Contribution At the moment, no external contributions are intended and merge requests from forks will automatically be rejected! -To report a bug or request an enhancement to this plugin, please raise a new [GitHub issue](https://github.com/tracetronic/ecu.test-diff/issues). +To report a bug or request an enhancement to this extension, +please raise a new [GitHub issue](https://github.com/tracetronic/ecu.test-diff/issues). ### Support diff --git a/REUSE.toml b/REUSE.toml index e02e562..f7e2352 100644 --- a/REUSE.toml +++ b/REUSE.toml @@ -1,5 +1,5 @@ version = 1 -SPDX-PackageName = "ecu.test diff plugin" +SPDX-PackageName = "ecu.test diff extension" SPDX-PackageSupplier = "2025 tracetronic GmbH " SPDX-PackageDownloadLocation = "https://github.com/tracetronic/ecu.test-diff" diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index ea44348..6146af9 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -84,7 +84,7 @@ cd ./dist web-ext build ``` -This tooling also provides help in the ['signing process](https://extensionworkshop.com/documentation/develop/extensions-and-the-add-on-id/) +This tooling also provides help in the [signing process](https://extensionworkshop.com/documentation/develop/extensions-and-the-add-on-id/) which is required for the use of add-ons without a debug-mode in firefox. ## Testing / Linting / Code formatting diff --git a/package.json b/package.json index a43c229..e78f708 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "ecu.test_diff-extension", "version": "1.0.0", - "description": "Browser plugin to open the diff viewer of tracetronic products ecu.test and trace.check from browser", + "description": "Browser extension to open the diff viewer of tracetronic products ecu.test and trace.check from browser", "scripts": { "start:chrome": "webpack --env TARGET=chrome --watch --config webpack.dev.cjs", "start:firefox": "webpack --env TARGET=firefox --watch --config webpack.dev.cjs", diff --git a/static/popup.html b/static/popup.html index 14299fc..83a14f9 100644 --- a/static/popup.html +++ b/static/popup.html @@ -28,7 +28,7 @@