From 2548ff3511e215975617886246d771bd24599790 Mon Sep 17 00:00:00 2001 From: ehennestad Date: Fri, 17 Jul 2026 07:12:50 +0200 Subject: [PATCH 1/4] feat: write badge JSON instead of rendering SVG via pybadges Badge SVG rendering moves out of MATLAB: testToolbox and codecheckToolbox now write badge descriptions as JSON files to docs/reports/badges/, and the matbox-actions check-code/test-code actions render them to .github/badges/*.svg with badge-maker, the shields.io reference implementation. This removes the runtime dependency on Python, pip, and the deprecated pybadges package. - createBadgeSvg is deprecated (kept for backward compatibility) - matbox.py namespace is retained; it is useful for downstream toolboxes with Python requirements - MatBox's own CI migrates from the legacy internal actions (@v0.9) to the matbox-actions@v1 reusable test workflow; the duplicate internal actions and reusable workflows are deleted from main (tag-pinned @v0.9 consumers are unaffected) - tools/tasks/codecheckToolbox wrapper accepts varargin, required because the v1 check-code action forwards name-value arguments Co-Authored-By: Claude Fable 5 --- .github/actions/check-code/action.yml | 36 -------- .github/actions/install-matbox/action.yml | 23 ----- .../actions/install-matbox/installMatBox.m | 45 ---------- .github/actions/push-badges/action.yml | 44 ---------- .github/actions/test-code/action.yml | 34 -------- .github/workflows/reusable_check_code.yml | 49 ----------- .github/workflows/reusable_test_workflow.yml | 87 ------------------- .github/workflows/run_tests.yml | 5 +- code/+matbox/+tasks/codecheckToolbox.m | 5 +- code/+matbox/+tasks/testToolbox.m | 3 +- code/+matbox/+utility/createBadgeSvg.m | 7 ++ tools/tasks/codecheckToolbox.m | 4 +- .../tests/+matboxtools/+unittest/TasksTest.m | 17 ++++ 13 files changed, 35 insertions(+), 324 deletions(-) delete mode 100644 .github/actions/check-code/action.yml delete mode 100644 .github/actions/install-matbox/action.yml delete mode 100644 .github/actions/install-matbox/installMatBox.m delete mode 100644 .github/actions/push-badges/action.yml delete mode 100644 .github/actions/test-code/action.yml delete mode 100644 .github/workflows/reusable_check_code.yml delete mode 100644 .github/workflows/reusable_test_workflow.yml diff --git a/.github/actions/check-code/action.yml b/.github/actions/check-code/action.yml deleted file mode 100644 index 77e9921..0000000 --- a/.github/actions/check-code/action.yml +++ /dev/null @@ -1,36 +0,0 @@ -# Should only be used in a job where MATLAB and MatBox is installed in previous steps - -name: 'Check code and upload report' -description: 'Analyse code for code issues and upload code issues report to GitHub' - -inputs: - code_directory: - description: 'Which folder to run the code check on' - required: false - default: './code' - tools_directory: - description: 'Where the codecheckToolbox function is located' - required: false - default: './tools' - -runs: - using: "composite" - steps: - - name: Check for MATLAB code issues - uses: matlab-actions/run-command@v2 - if: always() - with: - command: | - addpath(genpath("${{ inputs.tools_directory }}")); - if exist("codecheckToolbox", "file") - codecheckToolbox(); - else - matbox.tasks.codecheckToolbox(pwd, ... - "FoldersToCheck", "${{ inputs.code_directory }}"); - end - - - name: Upload SARIF file - uses: github/codeql-action/upload-sarif@v3 - continue-on-error: true # Will fail for MATLAB release < R2023a - with: - sarif_file: docs/reports/code_issues.sarif diff --git a/.github/actions/install-matbox/action.yml b/.github/actions/install-matbox/action.yml deleted file mode 100644 index 0a72a35..0000000 --- a/.github/actions/install-matbox/action.yml +++ /dev/null @@ -1,23 +0,0 @@ -name: 'Install MatBox' -description: 'Install MatBox in MATLAB on GitHub runner' -inputs: - mode: # mode of installation: release or commit, i.e install latest released version or use latest commit - description: 'Which installation mode to use' - required: true - default: 'commit' -runs: - using: "composite" - steps: - - name: Install MatBox - uses: matlab-actions/run-command@v2 - with: - command: | - addpath( "${{ github.action_path }}" ) - installMatBox( "${{ inputs.mode }}" ) - - - name: Confirm installation of MatBox - uses: matlab-actions/run-command@v2 - with: - command: | - versionStr = matbox.toolboxversion(); - assert(~isempty(versionStr), 'Failed to install MatBox.'); diff --git a/.github/actions/install-matbox/installMatBox.m b/.github/actions/install-matbox/installMatBox.m deleted file mode 100644 index 68223be..0000000 --- a/.github/actions/install-matbox/installMatBox.m +++ /dev/null @@ -1,45 +0,0 @@ -function installMatBox(mode) -% installMatBox - Install MatBox from latest release or latest commit - - arguments - mode (1,1) string {mustBeMember(mode, ["release", "commit"])} = "release" - end - - if mode == "release" - installFromRelease() % local function - elseif mode == "commit" - installFromCommit() % local function - end -end - -function installFromRelease() - addonsTable = matlab.addons.installedAddons(); - isMatchedAddon = addonsTable.Name == "MatBox"; - - if ~isempty(isMatchedAddon) && any(isMatchedAddon) - matlab.addons.enableAddon('MatBox') - else - info = webread('https://api.github.com/repos/ehennestad/MatBox/releases/latest'); - assetNames = {info.assets.name}; - isMltbx = startsWith(assetNames, 'MatBox'); - - mltbx_URL = info.assets(isMltbx).browser_download_url; - - % Download matbox - tempFilePath = websave(tempname, mltbx_URL); - cleanupObj = onCleanup(@(fp) delete(tempFilePath)); - - % Install toolbox - matlab.addons.install(tempFilePath); - end -end - -function installFromCommit() - - scriptPath = mfilename('fullpath'); - projectFolder = extractBefore(scriptPath, fullfile('.github', 'actions')); - codeDirectory = fullfile(projectFolder, 'code'); - - addpath(genpath(codeDirectory)) - savepath() -end diff --git a/.github/actions/push-badges/action.yml b/.github/actions/push-badges/action.yml deleted file mode 100644 index 67df8b9..0000000 --- a/.github/actions/push-badges/action.yml +++ /dev/null @@ -1,44 +0,0 @@ -name: 'Push GitHub badges' -description: 'Push badges for use on GitHub and located in .github/badges if there are detected changes.' - -inputs: - pr-ref: - description: "Branch ref to check out" - required: true - pr-repo: - description: "Repository (owner/repo) to check out from" - required: true - -runs: - using: "composite" - steps: - # Check out the actual source branch in a separate working tree - - name: Checkout PR branch for pushing badges - uses: actions/checkout@v4 - with: - ref: ${{ inputs.pr-ref }} - repository: ${{ inputs.pr-repo }} - path: pr-branch - - # Copy generated files to actual branch - - name: Copy badges to PR branch - shell: bash - run: | - cp -r .github/badges/* pr-branch/.github/badges/ 2>/dev/null || echo "No badges to copy" - - # Commit updated SVG badges for the issues and tests (if changed) - - name: Commit and push SVG badges if updated - working-directory: pr-branch - shell: bash - run: | - git config user.name "github-actions[bot]" - git config user.email "41898282+github-actions[bot]@users.noreply.github.com" - git fetch - - if [[ $(git add .github/badges/* --dry-run | wc -l) -gt 0 ]]; then - git add .github/badges - git commit -m "Update GitHub badges" - git push origin HEAD - else - echo "Nothing to commit" - fi diff --git a/.github/actions/test-code/action.yml b/.github/actions/test-code/action.yml deleted file mode 100644 index 0b784c5..0000000 --- a/.github/actions/test-code/action.yml +++ /dev/null @@ -1,34 +0,0 @@ -# Should only be used in a job where MATLAB and MatBox is installed in previous steps - -name: 'Run toolbox test suites' -description: 'Run the test suites available for a MATLAB toolbox' - -inputs: - code_directory: - description: 'Which folder to run the tests on' - default: './code' - tools_directory: - description: 'Where the testToolbox function is located' - default: './tools' - -runs: - using: "composite" - steps: - - name: Run MATLAB test suites - uses: matlab-actions/run-command@v2 - if: always() - with: - command: | - addpath(genpath("${{ inputs.tools_directory }}")); - if exist("testToolbox", "file") - testToolbox(); - else - matbox.tasks.testToolbox(pwd, ... - "SourceFolderName", "${{ inputs.code_directory }}"); - end - - - name: Publish test results - uses: EnricoMi/publish-unit-test-result-action@v2 - if: always() - with: - files: "docs/reports/test-results.xml" diff --git a/.github/workflows/reusable_check_code.yml b/.github/workflows/reusable_check_code.yml deleted file mode 100644 index fbc4c19..0000000 --- a/.github/workflows/reusable_check_code.yml +++ /dev/null @@ -1,49 +0,0 @@ -name: Analyse code - -on: - workflow_call: - inputs: - code_directory: - description: Path to the directory containing code. Code analysis will run on the contents of this folder and its subfolders. - type: string - default: 'code' - tools_directory: - description: Path to the directory containing CI tools. Used for locating customized MatBox tasks. - type: string - default: 'tools' - matlab_release: - description: MATLAB release to use when running code analysis. - type: string - default: 'latest' - -jobs: - # This workflow contains a single job called "check" - check: - name: Check code - runs-on: ubuntu-latest - - steps: - - name: Check out repo - uses: actions/checkout@v4 - - - name: Set up MATLAB (${{ inputs.matlab_release }}) - uses: matlab-actions/setup-matlab@v2 - with: - release: ${{ inputs.matlab_release }} - cache: true - - - name: Install MatBox - uses: ehennestad/matbox/.github/actions/install-matbox@v0.9 - - - name: Check code and upload report - uses: ehennestad/matbox/.github/actions/check-code@v0.9 - with: - code_directory: ${{ inputs.code_directory }} - tools_directory: ${{ inputs.tools_directory }} - - - name: Commit SVG badges if updated - if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository - uses: ehennestad/matbox/.github/actions/push-badges@v0.9 - with: - pr-ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.ref || github.ref_name }} - pr-repo: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name || github.repository }} diff --git a/.github/workflows/reusable_test_workflow.yml b/.github/workflows/reusable_test_workflow.yml deleted file mode 100644 index 8107f3d..0000000 --- a/.github/workflows/reusable_test_workflow.yml +++ /dev/null @@ -1,87 +0,0 @@ -name: Run tests - -on: - workflow_call: - inputs: - code_directory: - description: Path to the directory containing code. Code coverage and code analysis will run on the contents of this folder and its subfolders. - type: string - default: 'code' - tools_directory: - description: Path to the directory containing CI tools or tests. Used for locating unit tests and running customized MatBox tasks. - type: string - default: 'tools' - matlab_release: - description: MATLAB release to use for running test suites and code analysis. - type: string - default: 'latest' - matlab_use_cache: - description: Whether to cache the MATLAB installation for faster subsequent setups. - type: boolean - default: false - matlab_products: - description: Optional list of MATLAB products to install. - type: string - default: '' - - secrets: - CODECOV_TOKEN: - required: false - -jobs: - # This workflow contains a single job called "test" - test: - name: Test toolbox code - # The type of runner that the job will run on - runs-on: ubuntu-latest - env: # Assign secret to env to be able to use it in "if:" conditional below - CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} - - # Steps represent a sequence of tasks that will be executed as part of the job - steps: - - - name: Check out repository - uses: actions/checkout@v4 - - - name: Set up MATLAB (${{ inputs.matlab_release }}) - uses: matlab-actions/setup-matlab@v2 - with: - release: ${{ inputs.matlab_release }} - cache: ${{ inputs.matlab_use_cache }} - products: ${{ inputs.matlab_products }} - - - name: Install MatBox - uses: ehennestad/matbox/.github/actions/install-matbox@v0.9 - - - name: Check code and upload report - uses: ehennestad/matbox/.github/actions/check-code@v0.9 - with: - code_directory: ${{ inputs.code_directory }} - tools_directory: ${{ inputs.tools_directory }} - - - name: Run tests - uses: ehennestad/matbox/.github/actions/test-code@v0.9 - with: - code_directory: ${{ inputs.code_directory }} - tools_directory: ${{ inputs.tools_directory }} - - - name: Commit SVG badges if updated - if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository - uses: ehennestad/matbox/.github/actions/push-badges@v0.9 - with: - pr-ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.ref || github.ref_name }} - pr-repo: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name || github.repository }} - - - name: Upload code coverage report to Codecov - uses: codecov/codecov-action@v5 - if: ${{ env.CODECOV_TOKEN != '' }} - with: - token: ${{ env.CODECOV_TOKEN }} - files: docs/reports/codecoverage.xml - - - name: Save reports directory - uses: actions/upload-artifact@v4 - if: always() - with: - name: reports - path: docs/reports diff --git a/.github/workflows/run_tests.yml b/.github/workflows/run_tests.yml index cc4122c..a250cdd 100644 --- a/.github/workflows/run_tests.yml +++ b/.github/workflows/run_tests.yml @@ -27,8 +27,11 @@ concurrency: jobs: call-workflow-test-toolbox: name: Test toolbox code - uses: ehennestad/matbox/.github/workflows/reusable_test_workflow.yml@v0.9 + uses: ehennestad/matbox-actions/.github/workflows/test-code-workflow.yml@v1 with: + source_directory: code + tests_directory: tools/tests + tools_directory: tools matlab_use_cache: true secrets: CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} diff --git a/code/+matbox/+tasks/codecheckToolbox.m b/code/+matbox/+tasks/codecheckToolbox.m index 45d6f64..ec8cc5a 100644 --- a/code/+matbox/+tasks/codecheckToolbox.m +++ b/code/+matbox/+tasks/codecheckToolbox.m @@ -92,8 +92,9 @@ function createCodeIssuesBadge(issueCount, projectRootDir) color = "red"; end - matbox.utility.createBadgeSvg("code issues", ... - string(issueCount.Total), color, projectRootDir) + matbox.utility.writeBadgeJSONFile("code issues", ... + string(issueCount.Total), color, ... + "OutputFolder", fullfile(projectRootDir, "docs", "reports", "badges")) end function ME = throwUnresolvedCodeIssuesException() diff --git a/code/+matbox/+tasks/testToolbox.m b/code/+matbox/+tasks/testToolbox.m index de11b1c..07a7cc1 100644 --- a/code/+matbox/+tasks/testToolbox.m +++ b/code/+matbox/+tasks/testToolbox.m @@ -131,7 +131,8 @@ function createTestResultBadge(results, projectRootDirectory) color = "red"; message = sprintf("%d/%d passed", numPassedTests, numTests); end - matbox.utility.createBadgeSvg("tests", message, color, projectRootDirectory) + matbox.utility.writeBadgeJSONFile("tests", message, color, ... + "OutputFolder", fullfile(projectRootDirectory, "docs", "reports", "badges")) end function displayTestResultSummary(testResults) diff --git a/code/+matbox/+utility/createBadgeSvg.m b/code/+matbox/+utility/createBadgeSvg.m index 82e0aa5..a20a074 100644 --- a/code/+matbox/+utility/createBadgeSvg.m +++ b/code/+matbox/+utility/createBadgeSvg.m @@ -1,4 +1,11 @@ function createBadgeSvg(label, message, color, projectRootDirectory, options) +% createBadgeSvg - Create an SVG badge using the pybadges Python package +% +% Deprecated: MatBox tasks now write badge descriptions as JSON files +% (see matbox.utility.writeBadgeJSONFile), which are rendered to SVG in +% CI by the matbox-actions workflows. This function requires Python and +% the deprecated pybadges package, and will be removed in a future +% release. arguments label (1,1) string diff --git a/tools/tasks/codecheckToolbox.m b/tools/tasks/codecheckToolbox.m index f781459..c5819b5 100644 --- a/tools/tasks/codecheckToolbox.m +++ b/tools/tasks/codecheckToolbox.m @@ -1,5 +1,5 @@ -function codecheckToolbox() +function codecheckToolbox(varargin) installMatBox() projectRootDir = matboxtools.projectdir(); - matbox.tasks.codecheckToolbox(projectRootDir) + matbox.tasks.codecheckToolbox(projectRootDir, varargin{:}) end diff --git a/tools/tests/+matboxtools/+unittest/TasksTest.m b/tools/tests/+matboxtools/+unittest/TasksTest.m index 40073a1..7500cb2 100644 --- a/tools/tests/+matboxtools/+unittest/TasksTest.m +++ b/tools/tests/+matboxtools/+unittest/TasksTest.m @@ -34,6 +34,23 @@ function testCodecheckToolbox(testCase) testCase.verifyTrue(isfolder(fullfile(pwd, "docs", "reports"))) end + function testCodecheckToolboxCreatesBadgeJson(testCase) + pathStr = matboxtools.projectdir(); + copyfile(pathStr, pwd); + + matbox.tasks.codecheckToolbox(pwd, ... + "CreateBadge", true, "SaveReport", false); + + badgeFile = fullfile(pwd, "docs", "reports", "badges", "code_issues.json"); + testCase.verifyTrue(isfile(badgeFile), ... + "Expected badge JSON file was not created.") + + badgeInfo = jsondecode(fileread(badgeFile)); + testCase.verifyEqual(badgeInfo.label, 'code issues') + testCase.verifyTrue(ismember(string(badgeInfo.color), ... + ["green", "yellow", "red"])) + end + function testPackageToolbox(testCase) pathStr = matboxtools.projectdir(); copyfile(pathStr, pwd); From ef17b6e55adf59c62d7d629805b19a0e0e04973e Mon Sep 17 00:00:00 2001 From: ehennestad Date: Fri, 17 Jul 2026 12:06:14 +0200 Subject: [PATCH 2/4] feat: gate badge JSON behind MATBOX_BADGE_FORMAT env variable Repositories pinned to older matbox-actions refs still install the latest MatBox, so unconditionally switching to badge JSON would leave their committed badges silently stale (nothing renders the JSON). Badge creation now writes JSON only when MATBOX_BADGE_FORMAT=json, which current matbox-actions set; otherwise it falls back to the legacy pybadges SVG path. Every action/MatBox version combination keeps producing badges, and merge order no longer matters. Co-Authored-By: Claude Fable 5 --- code/+matbox/+tasks/+internal/createBadge.m | 27 +++++++++++++++++++ code/+matbox/+tasks/codecheckToolbox.m | 5 ++-- code/+matbox/+tasks/testToolbox.m | 3 +-- code/+matbox/+utility/createBadgeSvg.m | 11 ++++---- .../tests/+matboxtools/+unittest/TasksTest.m | 6 +++++ 5 files changed, 42 insertions(+), 10 deletions(-) create mode 100644 code/+matbox/+tasks/+internal/createBadge.m diff --git a/code/+matbox/+tasks/+internal/createBadge.m b/code/+matbox/+tasks/+internal/createBadge.m new file mode 100644 index 0000000..60a1c01 --- /dev/null +++ b/code/+matbox/+tasks/+internal/createBadge.m @@ -0,0 +1,27 @@ +function createBadge(label, message, color, projectRootDirectory) +% createBadge - Write a badge as JSON or as a legacy SVG file +% +% Writes a badge description as a JSON file (docs/reports/badges) when +% the MATBOX_BADGE_FORMAT environment variable is set to "json". The +% matbox-actions workflows set this variable and render the JSON files +% to SVG badges with badge-maker. +% +% Otherwise falls back to rendering the SVG in MATLAB via the deprecated +% pybadges Python package, for callers without a render step: local runs +% and repositories pinned to older matbox-actions versions. This +% fallback will be removed in a future major release. + + arguments + label (1,1) string + message (1,1) string + color (1,1) string + projectRootDirectory (1,1) string {mustBeFolder} + end + + if strcmpi(getenv("MATBOX_BADGE_FORMAT"), "json") + matbox.utility.writeBadgeJSONFile(label, message, color, ... + "OutputFolder", fullfile(projectRootDirectory, "docs", "reports", "badges")) + else + matbox.utility.createBadgeSvg(label, message, color, projectRootDirectory) + end +end diff --git a/code/+matbox/+tasks/codecheckToolbox.m b/code/+matbox/+tasks/codecheckToolbox.m index ec8cc5a..b81c753 100644 --- a/code/+matbox/+tasks/codecheckToolbox.m +++ b/code/+matbox/+tasks/codecheckToolbox.m @@ -92,9 +92,8 @@ function createCodeIssuesBadge(issueCount, projectRootDir) color = "red"; end - matbox.utility.writeBadgeJSONFile("code issues", ... - string(issueCount.Total), color, ... - "OutputFolder", fullfile(projectRootDir, "docs", "reports", "badges")) + matbox.tasks.internal.createBadge("code issues", ... + string(issueCount.Total), color, projectRootDir) end function ME = throwUnresolvedCodeIssuesException() diff --git a/code/+matbox/+tasks/testToolbox.m b/code/+matbox/+tasks/testToolbox.m index 07a7cc1..da15d6f 100644 --- a/code/+matbox/+tasks/testToolbox.m +++ b/code/+matbox/+tasks/testToolbox.m @@ -131,8 +131,7 @@ function createTestResultBadge(results, projectRootDirectory) color = "red"; message = sprintf("%d/%d passed", numPassedTests, numTests); end - matbox.utility.writeBadgeJSONFile("tests", message, color, ... - "OutputFolder", fullfile(projectRootDirectory, "docs", "reports", "badges")) + matbox.tasks.internal.createBadge("tests", message, color, projectRootDirectory) end function displayTestResultSummary(testResults) diff --git a/code/+matbox/+utility/createBadgeSvg.m b/code/+matbox/+utility/createBadgeSvg.m index a20a074..da0999b 100644 --- a/code/+matbox/+utility/createBadgeSvg.m +++ b/code/+matbox/+utility/createBadgeSvg.m @@ -1,11 +1,12 @@ function createBadgeSvg(label, message, color, projectRootDirectory, options) % createBadgeSvg - Create an SVG badge using the pybadges Python package % -% Deprecated: MatBox tasks now write badge descriptions as JSON files -% (see matbox.utility.writeBadgeJSONFile), which are rendered to SVG in -% CI by the matbox-actions workflows. This function requires Python and -% the deprecated pybadges package, and will be removed in a future -% release. +% Deprecated: when running via current matbox-actions workflows, MatBox +% tasks write badge descriptions as JSON files instead (see +% matbox.utility.writeBadgeJSONFile), which CI renders to SVG with +% badge-maker. This function remains as a fallback for local runs and +% older matbox-actions versions. It requires Python and the deprecated +% pybadges package, and will be removed in a future major release. arguments label (1,1) string diff --git a/tools/tests/+matboxtools/+unittest/TasksTest.m b/tools/tests/+matboxtools/+unittest/TasksTest.m index 7500cb2..9ea5c36 100644 --- a/tools/tests/+matboxtools/+unittest/TasksTest.m +++ b/tools/tests/+matboxtools/+unittest/TasksTest.m @@ -38,6 +38,12 @@ function testCodecheckToolboxCreatesBadgeJson(testCase) pathStr = matboxtools.projectdir(); copyfile(pathStr, pwd); + % The matbox-actions workflows set this environment variable to + % request badge JSON instead of legacy in-MATLAB SVG rendering. + previousValue = getenv("MATBOX_BADGE_FORMAT"); + setenv("MATBOX_BADGE_FORMAT", "json") + testCase.addTeardown(@() setenv("MATBOX_BADGE_FORMAT", previousValue)) + matbox.tasks.codecheckToolbox(pwd, ... "CreateBadge", true, "SaveReport", false); From 2817a81845a7f6febffa0274080fb0319b85fae3 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 17 Jul 2026 10:08:35 +0000 Subject: [PATCH 3/4] Update GitHub badges [skip ci] --- .github/badges/tests.svg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/badges/tests.svg b/.github/badges/tests.svg index b2979d5..11daccf 100644 --- a/.github/badges/tests.svg +++ b/.github/badges/tests.svg @@ -1 +1 @@ -teststests23 passed23 passed \ No newline at end of file +teststests24 passed24 passed \ No newline at end of file From dd7d3c74381510638367e17e00094cc96e90d0a4 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 20 Jul 2026 20:14:45 +0000 Subject: [PATCH 4/4] Update GitHub badges [skip ci] --- .github/badges/code_issues.svg | 2 +- .github/badges/tests.svg | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/badges/code_issues.svg b/.github/badges/code_issues.svg index 892f431..6071791 100644 --- a/.github/badges/code_issues.svg +++ b/.github/badges/code_issues.svg @@ -1 +1 @@ -code issuescode issues11 \ No newline at end of file +code issues: 1code issues1 diff --git a/.github/badges/tests.svg b/.github/badges/tests.svg index 11daccf..b8630e0 100644 --- a/.github/badges/tests.svg +++ b/.github/badges/tests.svg @@ -1 +1 @@ -teststests24 passed24 passed \ No newline at end of file +tests: 24 passedtests24 passed