Developer Guide
Prerequisites
Install Node.js using fnm (Fast Node Manager).
# Install fnm (Windows)
winget install --id Schniz.fnm
# Install fnm (macOS)
brew install fnm
# Install fnm (Linux)
curl -fsSL https://fnm.vercel.app/install | bash
# Initialize fnm for your shell (example for bash)
eval "$(fnm env --use-on-cd)"
# Install and use the latest LTS Node.js
fnm install --lts
fnm use --lts
# Verify Node and npm
node -v
npm -v
Enable Corepack to manage package managers like pnpm. Note: as of Node.js 25, Corepack is no longer bundled, so install it separately if needed.
# Install Corepack when it is not bundled with Node.js
npm install -g corepack
Then enable Corepack and activate pnpm:
# Enable Corepack shims
corepack enable
# Ensure pnpm is available via Corepack
corepack install
# Verify pnpm
pnpm -v
Use pnpm to install dependencies:
# Install dependencies and update the lockfile if needed
pnpm i
# Install dependencies without modifying pnpm-lock.yaml
pnpm i --frozen-lockfile
pnpm iresolves and installs dependencies; it can updatepnpm-lock.yamlif versions change.pnpm i --frozen-lockfileenforces the existing lockfile and fails if it is out of date.
Install and use uv for Python dependencies and tooling (docs builds, Sphinx, etc.):
# Install uv (recommended)
curl -LsSf https://astral.sh/uv/install.sh | sh
# Create a virtual environment and sync dependencies
uv venv
uv sync
# Run commands inside the uv-managed environment
uv run python -V
uv run sphinx-build --version
Development Workflow
Clone the repo.
Run
pnpm iorpnpm i --frozen-lockfile. In thepreparescript, the git hooks are configured. This sets up git-conventional-commits to lint the commit messages. Without this, commit messages are not checked.Run
setupRegularizeNdProjectPath.mto set up the MATLAB path for this project before running any MATLAB scripts. When you are done, run it again to clean up and remove the project paths.Develop.
Commit using conventional commits.
Run
matlab -batch "release_workflow_part1()"for a dry run, ormatlab -batch "release_workflow_part1('DryRun',false)"to execute part 1.After part 1 completes, manually package the toolbox:
Open the
build\regularizeNd.prj.Click “Package Toolbox”.
Set the version.
Make the Getting Started file is correctly configured.
Run
matlab -batch "release_workflow_part2()"for a dry run, ormatlab -batch "release_workflow_part2('DryRun',false)"to execute part 2.
Note: other scripts assume the MATLAB path has already been set. The only script that adjusts the path internally is createPackage, which adds the build folder briefly for builddocsearchdb and removes it immediately.
To run a live-reloading docs server during documentation development, use the Sphinx autobuild target from the docs folder:
cd docs
make livehtml
Release Workflow
release_workflow_part1 performs the following steps:
Determines the next semantic version using
git-conventional-commits.Updates
package.json,pyproject.toml, anddocs/conf.pywith the next version.Generates
CHANGELOG.md.Runs
deploy_documentationwith the same DryRun setting; when DryRun is true, it does everything except push.Sets up the
builddirectory and toolbox project files usingcreatePackage(..., "PackageToolbox", false).Stops and prints the manual packaging instructions.
After manually packaging the toolbox, release_workflow_part2 performs:
Commits the version/changelog changes as
chore(release): vX.Y.Zand tagsvX.Y.Z(skipped in dry run).Creates a GitHub release with notes generated from conventional commits since the previous tag (skipped in dry run).
Dry run behavior:
In part 1, version/changelog/file updates are skipped, and documentation deploy runs without push.
In part 2, git commits/tags/push and GitHub release creation are skipped.
Semantic Versioning
This repo adheres to Semantic Versioning.
Given a version number MAJOR.MINOR.PATCH, increment the:
MAJOR version when you make incompatible API changes (BREAKING CHANGES). Any type of commit.
MINOR version when you add functionality in a backwards compatible manner (
feattype commit).PATCH version when you make backwards compatible bug fixes (
fix/perf/docs/choretype commit).
Conventional Commits
The commit format used is:
<type>: <subject>
<optional body>
<optional footer>
Commit Types
API relevant changes
feat- Commits that add a new feature. MINOR version bump.fix- Commits that fix a bug. PATCH version bump.
perf- Commits that improve performance. PATCH version bump.docs- Commits that update internal or external documentation. PATCH version bump.chore- Miscellaneous commits e.g. modifying.gitignore,tests, refactoring, etc. This is the catch all type if one of the other types doesn’t fit. Note that this type will not show up in the Changelog. PATCH version bump.
Breaking Changes Modifier: !
If you add an exclamation mark to any of the commit types, it signifies BREAKING CHANGES which increments the MAJOR version:
fix!: fixed a bug that changed user outputfeat!: Changed a feature that changes the user input
Recommendations when using the ! modifier:
Use the exclamation mark when making BREAKING CHANGES even if you have a footer describing the breaking change. The exclamation mark makes it easy to recognize that
type!: subject hereis a BREAKING CHANGE.If BREAKING CHANGES can be described by the subject, you may use only the exclamation mark to signify the BREAKING CHANGES, skipping the footer. Due diligence to communicate the BREAKING CHANGES well is recommended, so use the footer if needed.
Scopes
The commit scope is not used in this repo.
Subject
The subject contains a succinct description of the change:
Is a mandatory part of the format
Don’t capitalize the first letter
No dot (
.) at the end
Body
The body shall include the motivation for the change and contrast this with previous behavior:
Is an optional part of the format
This is the place to mention issue identifiers and their relations
Example Commit Messages
fix - Increments the PATCH (1.0.0 → 1.0.1)
fix: fixed a small bug related to when an exception is thrown
feat - Increments the MINOR (1.0.0 → 1.1.0)
feat: Added monotonicConstraint.m function
monotonicConstraint.m adds new functionality that works well with regularizeNdMatrices.
fix with BREAKING CHANGES - Increments MAJOR (1.0.0 → 2.0.0)
fix!: iterative solver now works
pcg and lsqr iterative solvers were not working. pcg is the main iterative solver. lsqr is just a backup in my opinion.
BREAKING CHANGE: Output to the user is now correct.
feat with BREAKING CHANGES - Using only the exclamation mark. Increments MAJOR (1.0.0 → 2.0.0)
feat!: change of iterative solver
feat with BREAKING CHANGES and footer - Increments MAJOR (1.0.0 → 2.0.0)
feat!: change of iterative solver
I was able to find a couple of acceptable iterative solvers. pcg and lsqr. pcg is the main iterative solver. lsqr is just a backup in my opinion.
BREAKING CHANGES: removed fmincon solver
perf - Increments the PATCH (1.0.0 → 1.0.1)
perf: improved performance of pcg iterative solver
docs - Increments the PATCH (1.0.0 → 1.0.1)
docs: improved the internal and external documentation of regularizeNd
The comments in regularizeNd.m were updated to better communicate the algorithm.
The regularizeNdDoc.m file was updated to better communicate how to use regularizeNd.m.
chore - Does not show up in the changelog. Increments the PATCH (1.0.0 → 1.0.1)
chore: Updated the git configuration and git-conventional-commits.yaml
chore: updated .gitignore with ignore files used in the build
chore: updated the .gitattributes for a couple binary files
chore: Excluding invalid commits in git-conventional-commits.yaml
Further Reading
See https://github.com/jasonnicholson/regularizeNd/blob/main/git-conventional-commits.yaml for the configuration of the conventional commits. The tooling used to check and manage conventional commits is git-conventional-commits.
Conventional Commits standard
Semantic Versioning standard