Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
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
2 changes: 1 addition & 1 deletion .claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"name": "mpftp",
"source": "./integrations/claude-code-plugin",
"description": "A skill that teaches the mpftp CLI for MicroPython/CircuitPython boards: file transfer, REPL, driving a running app, and firmware.",
"version": "0.1.2-rc.4"
"version": "0.0.1-dev.0"
}
]
}
64 changes: 62 additions & 2 deletions .github/workflows/prepare-release.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# Open a release PR (VERSION + CHANGELOG). The version in the PR is the
# human's to edit before merging; merging tags and publishes.
# Open a release PR: VERSION and CHANGELOG from the shared workflow, then one
# more commit that sets every other version declaration from VERSION, so the
# PR's Tests pass without anyone touching the branch. The version in the PR is
# the human's to edit before merging; merging tags and publishes.
name: Prepare release

on:
Expand All @@ -19,3 +21,61 @@ jobs:
with:
version: ${{ inputs.version }}
secrets: inherit

# The shared workflow moves only VERSION and CHANGELOG.md and has no hook for
# more, so this job follows it: it checks out the release branch it opened and
# runs check_versions.py --write, which sets the npm manifests, both
# lockfiles and the plugin manifests. It pushes with the App token, not the
# default one, because a push made with GITHUB_TOKEN does not start the PR's
# Tests again.
sync-versions:
needs: release-pr
runs-on: ubuntu-latest
steps:
- name: Mint App token
id: app-token
uses: actions/create-github-app-token@v3
with:
app-id: ${{ secrets.PYDEVICES_APP_ID }}
private-key: ${{ secrets.PYDEVICES_APP_PRIVATE_KEY }}

- uses: actions/checkout@v7
with:
fetch-depth: 0
token: ${{ steps.app-token.outputs.token }}

- name: Find the release branch
id: branch
env:
REQUESTED: ${{ inputs.version }}
run: |
git fetch -q origin '+refs/heads/release/*:refs/remotes/origin/release/*'
if [[ -n "$REQUESTED" ]]; then
BRANCH="release/v$REQUESTED"
else
# No version was given, so the shared workflow picked one: the
# branch it just pushed is the newest release branch.
BRANCH=$(git for-each-ref --sort=-committerdate --count=1 \
--format='%(refname:strip=3)' 'refs/remotes/origin/release/*')
fi
git rev-parse -q --verify "refs/remotes/origin/$BRANCH" >/dev/null \
|| { echo "No branch $BRANCH" >&2; exit 1; }
echo "name=$BRANCH" >> "$GITHUB_OUTPUT"

- name: Set every version declaration from VERSION
env:
BRANCH: ${{ steps.branch.outputs.name }}
run: |
git checkout -q -B "$BRANCH" "origin/$BRANCH"
V=$(tr -d '[:space:]' < VERSION)
[[ "$BRANCH" == "release/v$V" ]] \
|| { echo "$BRANCH carries VERSION $V" >&2; exit 1; }
python3 scripts/check_versions.py --write
if git diff --quiet; then
echo "Every declaration already carries $V."
exit 0
fi
git config user.name "pydevices-release-automation[bot]"
git config user.email "pydevices-release-automation[bot]@users.noreply.github.com"
git commit -qam "Release $V: every declaration carries the version"
git push origin "$BRANCH"
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## v0.0.1.dev0 (2026-10-20)

- Prepare release: the release PR carries every version declaration

## v0.1.2rc4 (2026-10-20)

- put -r from WSL: the Windows sidecar opens /mnt/<drive> paths
Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.1.2rc4
0.0.1.dev0
30 changes: 16 additions & 14 deletions docs/publishing.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,20 +66,22 @@ gh workflow run prepare-release.yml -f version=X.Y.Z # or e.g. 0.1.0rc1
gh pr list --state open # the bot's "Release X.Y.Z" PR
```

The bot's PR only moves `VERSION` and prepends a commit list to
`CHANGELOG.md`. Before merging, on its `release/vX.Y.Z` branch:

1. Run `python scripts/check_versions.py --write`. It sets every other
version site from `VERSION`, in the form each one takes, and checks
them: `extension/package.json`, `ui/package.json`, the root entry of
both `package-lock.json` files (two lines each),
`.claude-plugin/marketplace.json` and
`integrations/claude-code-plugin/.claude-plugin/plugin.json`.
2. In `CHANGELOG.md`, turn the curated `## Unreleased` notes into the
`## vX.Y.Z (date)` section and drop the bot's commit list, so there is one
heading per release.

Push, wait for Tests to pass on the PR, and merge it. Then watch:
The bot opens the PR in two steps. It sets `VERSION` and prepends a commit
list to `CHANGELOG.md`, then a second commit runs
`python scripts/check_versions.py --write`, which sets every other version site
from `VERSION` in the form each one takes: `extension/package.json`,
`ui/package.json`, the root entry of both `package-lock.json` files,
`.claude-plugin/marketplace.json` and
`integrations/claude-code-plugin/.claude-plugin/plugin.json`. The PR's Tests
then pass without anyone touching the branch. If the second commit is missing
(the workflow's `sync-versions` job failed), run that command on the
`release/vX.Y.Z` branch and push.

Before merging, on the `release/vX.Y.Z` branch, in `CHANGELOG.md`, turn the
curated `## Unreleased` notes into the `## vX.Y.Z (date)` section and drop the
bot's commit list, so there is one heading per release.

Push any edit, wait for Tests to pass on the PR, and merge it. Then watch:

```bash
gh run list --workflow tag-release.yml --limit 1
Expand Down
4 changes: 2 additions & 2 deletions extension/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion extension/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "mpftp",
"displayName": "mpftp — MicroPython / CircuitPython Board Tools",
"description": "Connect to MicroPython and CircuitPython boards over USB serial or Wi-Fi (WebREPL): dual-pane file transfer, ANSI REPL, mip/circup packages, and guided MicroPython firmware download/build/flash. Works on Linux, Windows, and WSL (COM ports via Windows Python).",
"version": "0.1.2-rc.4",
"version": "0.0.1-dev.0",
"publisher": "pydevices",
"license": "MIT",
"engines": {
Expand Down
2 changes: 1 addition & 1 deletion integrations/claude-code-plugin/.claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "mpftp",
"description": "A skill that teaches the mpftp CLI for MicroPython/CircuitPython boards: file transfer, REPL, driving a running app, and firmware.",
"version": "0.1.2-rc.4",
"version": "0.0.1-dev.0",
"author": {
"name": "Brad Barnett"
},
Expand Down
4 changes: 2 additions & 2 deletions ui/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion ui/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "mpftp-ui",
"version": "0.1.2-rc.4",
"version": "0.0.1-dev.0",
"private": true,
"description": "mpftp local PWA: file transfer + REPL for a MicroPython/CircuitPython board.",
"scripts": {
Expand Down
Loading