Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,22 @@ All pull requests must pass these checks:
| Mock tests | `tests.yml` | Runs mock driver tests |
| Example validation | `tests.yml` | Validates example files syntax and imports |

## Releasing

Version tags are created with `make bump`:

```bash
make bump # patch: v1.0.0 → v1.0.1
make bump PART=minor # minor: v1.0.1 → v1.1.0
make bump PART=major # major: v1.1.0 → v2.0.0
```

This will:
1. Check you are on `main` with a clean working tree
2. Compute the next version from the latest git tag
3. Update `pyproject.toml` version
4. Commit, tag, and push to origin

## Notes

* Keep implementations simple and readable
Expand Down
35 changes: 35 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,41 @@ repl: ## Open MicroPython REPL on the board
mount: ## Mount lib/ on the board for live testing
mpremote connect $(PORT) mount lib/

# --- Release ---

PART ?= patch

.PHONY: bump
bump: ## Create a version tag (PART=patch|minor|major, default: patch)
@if [ "$$(git symbolic-ref --short HEAD)" != "main" ]; then \
echo "Error: bump must be run on the main branch."; exit 1; \
fi
@if [ -n "$$(git status --porcelain)" ]; then \
echo "Error: working tree is not clean. Commit or stash changes first."; exit 1; \
fi
@LAST=$$(git tag --sort=-v:refname | head -1); \
if [ -z "$$LAST" ]; then \
NEXT="v1.0.0"; \
else \
MAJOR=$$(echo "$$LAST" | sed 's/^v//' | cut -d. -f1); \
MINOR=$$(echo "$$LAST" | sed 's/^v//' | cut -d. -f2); \
PATCH=$$(echo "$$LAST" | sed 's/^v//' | cut -d. -f3); \
case "$(PART)" in \
major) MAJOR=$$((MAJOR + 1)); MINOR=0; PATCH=0 ;; \
minor) MINOR=$$((MINOR + 1)); PATCH=0 ;; \
patch) PATCH=$$((PATCH + 1)) ;; \
*) echo "Error: PART must be patch, minor or major."; exit 1 ;; \
esac; \
NEXT="v$$MAJOR.$$MINOR.$$PATCH"; \
Comment on lines +114 to +123
Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The bump logic assumes the latest tag is exactly v<major>.<minor>.<patch>. If the repo ever has non-semver tags (e.g., v1.2.3-rc1) or tags without a leading v, MAJOR/MINOR/PATCH parsing and arithmetic can fail. Add a validation step (regex match) and error out with a clear message when LAST isn't a supported format.

Suggested change
MAJOR=$$(echo "$$LAST" | sed 's/^v//' | cut -d. -f1); \
MINOR=$$(echo "$$LAST" | sed 's/^v//' | cut -d. -f2); \
PATCH=$$(echo "$$LAST" | sed 's/^v//' | cut -d. -f3); \
case "$(PART)" in \
major) MAJOR=$$((MAJOR + 1)); MINOR=0; PATCH=0 ;; \
minor) MINOR=$$((MINOR + 1)); PATCH=0 ;; \
patch) PATCH=$$((PATCH + 1)) ;; \
*) echo "Error: PART must be patch, minor or major."; exit 1 ;; \
esac; \
NEXT="v$$MAJOR.$$MINOR.$$PATCH"; \
if echo "$$LAST" | grep -Eq '^v[0-9]+\.[0-9]+\.[0-9]+$$'; then \
MAJOR=$$(echo "$$LAST" | sed 's/^v//' | cut -d. -f1); \
MINOR=$$(echo "$$LAST" | sed 's/^v//' | cut -d. -f2); \
PATCH=$$(echo "$$LAST" | sed 's/^v//' | cut -d. -f3); \
case "$(PART)" in \
major) MAJOR=$$((MAJOR + 1)); MINOR=0; PATCH=0 ;; \
minor) MINOR=$$((MINOR + 1)); PATCH=0 ;; \
patch) PATCH=$$((PATCH + 1)) ;; \
*) echo "Error: PART must be patch, minor or major."; exit 1 ;; \
esac; \
NEXT="v$$MAJOR.$$MINOR.$$PATCH"; \
else \
echo "Error: latest tag '$$LAST' is not in supported format v<major>.<minor>.<patch>."; exit 1; \
fi; \

Copilot uses AI. Check for mistakes.
fi; \
echo "$$LAST → $$NEXT"; \
sed -i "s/^version = \".*\"/version = \"$${NEXT#v}\"/" pyproject.toml; \
Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sed -i is not portable across GNU/BSD sed (e.g., macOS requires sed -i '' ...). Since this target is intended for contributors’ local environments, consider switching to a cross-platform edit approach (e.g., a small Python one-liner) or handling GNU vs BSD sed explicitly.

Suggested change
sed -i "s/^version = \".*\"/version = \"$${NEXT#v}\"/" pyproject.toml; \
VERSION=$${NEXT#v}; \
python - "$$VERSION" << 'PY'; \
import sys
import pathlib
import re
path = pathlib.Path("pyproject.toml")
text = path.read_text()
version = sys.argv[1]
text = re.sub(r'^version = ".*"$', f'version = "{version}"', text, count=1, flags=re.MULTILINE)
path.write_text(text)
PY

Copilot uses AI. Check for mistakes.
git add pyproject.toml; \
git commit -m "chore: Bump version to $$NEXT."; \
git tag "$$NEXT"; \
git push origin main "$$NEXT"; \
Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This creates a lightweight tag (git tag "$NEXT"), but the linked issue’s desired behavior calls for an annotated tag. If annotated tags are required for releases, switch to creating an annotated tag (and include a message), so metadata is preserved and git describe behaves as expected.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Push branch and tag atomically in bump target

The git push origin main "$$NEXT" call can partially update the remote: if main is accepted but the tag is rejected (for example because the tag already exists remotely or tag creation is restricted), the bump commit is published without its release tag. git push only guarantees all-or-nothing behavior when --atomic is used, so this target can leave the repository in an inconsistent release state even though it reports failure.

Useful? React with 👍 / 👎.

echo "Tag $$NEXT pushed to origin."
Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because this Makefile uses .ONESHELL, the long command chain starting here uses ; separators, so failures from sed, git commit, git tag, or git push may not stop the target (the final echo will still exit 0). Consider enabling fail-fast for this recipe (e.g., set -e at the start of the bump recipe or chaining critical commands with &&) so make bump reliably fails on errors and doesn't leave the repo in a partially-updated state.

Copilot uses AI. Check for mistakes.
Comment on lines +131 to +132
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Fail bump target when git push errors

The bump recipe runs all release steps in one .ONESHELL block and ends with echo, so a failed git push (e.g., auth issue, network problem, or non-fast-forward) is masked and make bump still exits successfully. This can leave a local commit/tag that was never published while printing a success message, which is risky for release automation.

Useful? React with 👍 / 👎.


# --- Utilities ---

.PHONY: clean
Expand Down
Loading