@alteriom/painlessmesh 1.10.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/BRIDGE_TO_INTERNET.md +167 -29
  2. package/CHANGELOG.md +483 -0
  3. package/CONTRIBUTING.md +56 -53
  4. package/README.md +100 -95
  5. package/RELEASE_GUIDE.md +81 -780
  6. package/examples/alteriom/README.md +8 -10
  7. package/examples/alteriom/alteriom.ino +2 -2
  8. package/examples/alteriom/alteriom_sensor_package.hpp +17 -11
  9. package/examples/alteriom/mppt_example/alteriom_custom_package_template.hpp +320 -0
  10. package/examples/alteriom/mppt_example/alteriom_sensor_package.hpp +1389 -0
  11. package/examples/alteriom/mppt_example/{alteriom_mppt_example.ino → mppt_example.ino} +4 -0
  12. package/examples/basic/test/simulator/README.md +3 -3
  13. package/examples/bridge_failover/README.md +51 -14
  14. package/examples/commandControl/commandControl.ino +86 -0
  15. package/examples/commandControl/platformio.ini +26 -0
  16. package/examples/mqttBridge/mqttBridge.ino +4 -0
  17. package/examples/mqttBridge/platformio.ini +1 -1
  18. package/examples/otaSender/otaSender.ino +5 -1
  19. package/examples/priority/README.md +1 -1
  20. package/examples/priority/{priority_basic_example.ino → priority_basic_example/priority_basic_example.ino} +4 -4
  21. package/examples/priority/{priority_with_queue.ino → priority_with_queue/priority_with_queue.ino} +20 -2
  22. package/examples/reliableSensorLogging/platformio.ini +26 -0
  23. package/examples/reliableSensorLogging/reliableSensorLogging.ino +151 -0
  24. package/examples/sendToInternet/README.md +12 -5
  25. package/examples/sendToInternet/{CMakeLists.txt → pc_node/CMakeLists.txt} +7 -7
  26. package/examples/sendToInternet/{PC_NODE_README.md → pc_node/PC_NODE_README.md} +15 -15
  27. package/examples/sendToInternet/{build.sh → pc_node/build.sh} +5 -5
  28. package/examples/sendToInternet/{pc_mesh_node.cpp → pc_node/pc_mesh_node.cpp} +12 -1
  29. package/examples/sharedGateway/README.md +1 -2
  30. package/keywords.txt +50 -1
  31. package/library.json +8 -6
  32. package/library.properties +2 -2
  33. package/package.json +3 -3
  34. package/src/AlteriomPainlessMesh.h +3 -3
  35. package/src/arduino/wifi.hpp +556 -126
  36. package/src/painlessMesh.h +2 -2
  37. package/src/painlessMeshSTA.cpp +607 -87
  38. package/src/painlessMeshSTA.h +135 -3
  39. package/src/painlessmesh/ack.hpp +283 -0
  40. package/src/painlessmesh/buffer.hpp +70 -8
  41. package/src/painlessmesh/callback.hpp +38 -5
  42. package/src/painlessmesh/configuration.hpp +69 -1
  43. package/src/painlessmesh/connection.hpp +12 -5
  44. package/src/painlessmesh/gateway.hpp +270 -5
  45. package/src/painlessmesh/layout.hpp +70 -2
  46. package/src/painlessmesh/logger.hpp +15 -0
  47. package/src/painlessmesh/mesh.hpp +552 -48
  48. package/src/painlessmesh/ntp.hpp +2 -4
  49. package/src/painlessmesh/plugin.hpp +30 -6
  50. package/src/painlessmesh/protocol.hpp +55 -2
  51. package/src/painlessmesh/router.hpp +192 -77
  52. package/src/painlessmesh/tcp.hpp +10 -0
  53. package/src/painlessmesh/message_tracker.hpp +0 -311
  54. /package/examples/sendToInternet/{mock_server_test.ino → mock_server_test/mock_server_test.ino} +0 -0
package/RELEASE_GUIDE.md CHANGED
@@ -1,819 +1,120 @@
1
- # painlessMesh Release Guide
1
+ # AlteriomPainlessMesh Release Guide
2
2
 
3
- This document provides comprehensive instructions for releasing new versions of the Alteriom painlessMesh library across all distribution channels.
3
+ This repository publishes one version to the Arduino Library Manager,
4
+ PlatformIO, npm, GitHub Packages, and GitHub Releases. A release starts only
5
+ after the release pull request is reviewed, all required CI checks pass, and
6
+ the version commit reaches `main`.
4
7
 
5
- ## ⚠️ Important: Agent Requirements for Releases
8
+ ## Release checklist
6
9
 
7
- **Releases MUST be performed by Alteriom AI Agent (`@alteriom-ai-agent`) with full tool access.**
10
+ 1. Start from a clean branch based on the current release branch.
11
+ 2. Confirm the intended changes are documented under `Unreleased` in
12
+ [CHANGELOG.md](CHANGELOG.md).
13
+ 3. Run the complete desktop, Arduino, PlatformIO, simulator, and hardware test
14
+ suites required by the pull request.
15
+ 4. Obtain approval and resolve every review conversation.
16
+ 5. After approval, select the next semantic version and update the version
17
+ metadata.
18
+ 6. Move the `Unreleased` changes to a dated version section.
19
+ 7. Run the release validation scripts.
20
+ 8. Merge the release pull request. Do not create a tag by hand; the release
21
+ workflow owns tags and publication.
8
22
 
9
- ### Why This Matters
23
+ The workflow tags only when the push to `main` carries a version-file
24
+ change or a head commit whose message starts with `release:`. When the
25
+ version metadata was bumped earlier in the cycle (as for 2.0.0), merge the
26
+ release pull request with a commit titled `release: vX.Y.Z` — a squash or
27
+ merge commit with that title — or the push is ignored.
10
28
 
11
- A release requires updating 7 files consistently:
12
- 1. library.properties
13
- 2. library.json
14
- 3. package.json
15
- 4. src/painlessMesh.h
16
- 5. src/AlteriomPainlessMesh.h
17
- 6. README.md
18
- 7. CHANGELOG.md
29
+ ## Version metadata
19
30
 
20
- **✅ Correct Agent:** `@alteriom-ai-agent`
21
- - Has file editing tools (`replace_string_in_file`, `multi_replace_string_in_file`)
22
- - Can run terminal commands (`run_in_terminal`)
23
- - Can execute git operations
24
- - **Use this for release preparation**
31
+ These files must always contain the same semantic version:
25
32
 
26
- **❌ Wrong Agent:** `@painlessmesh-coordinator` or specialized agents without tools
27
- - Lack file editing capabilities
28
- - Can only provide documentation/checklists
29
- - Cannot actually perform releases
30
- - Will result in manual work
33
+ - `library.properties`
34
+ - `library.json`
35
+ - `package.json`
31
36
 
32
- ### Agent-Assisted Release (Recommended)
37
+ Use the repository script to change them together:
33
38
 
34
39
  ```bash
35
- # Ask Alteriom AI Agent to prepare release
36
- @alteriom-ai-agent Prepare release v1.9.9 with these changes:
37
- - Fixed ESP8266 WiFiClientSecure scope issue
38
- - Fixed TCP retry crash with AsyncClient cleanup
39
-
40
- # Agent will:
41
- # ✅ Update all 7 version files
42
- # ✅ Restructure CHANGELOG.md
43
- # ✅ Run validation: ./scripts/release-agent.sh
44
- # ✅ Commit: "release: v1.9.9 - Description"
45
- # ✅ Push to trigger automation
46
- ```
47
-
48
- ## 🚀 Quick Release Process
49
-
50
- ### Standard Release (Manual)
51
-
52
- ```bash
53
- # 1. Update version using the bump script
54
- ./scripts/bump-version.sh patch # or minor, major
55
-
56
- # 2. Update CHANGELOG.md with your changes
57
- # Add your changes under the new version section
58
-
59
- # 3. Update header file version comments (recommended)
60
- # Edit src/painlessMesh.h and src/AlteriomPainlessMesh.h
61
- # Update @version comments to match the new library version
62
-
63
- # 4. Run the Release Agent to validate readiness
64
- ./scripts/release-agent.sh
65
-
66
- # 5. If all checks pass, commit and trigger release
67
- git add library.properties library.json package.json CHANGELOG.md src/*.h README.md
68
- git commit -m "release: v1.7.9 - Brief description"
69
- git push origin main
70
- ```
71
-
72
- **That's it!** GitHub Actions will automatically handle:
73
- - ✅ Comprehensive testing across platforms
74
- - ✅ Git tag creation and GitHub release
75
- - ✅ NPM publishing (public + GitHub Packages)
76
- - ✅ **PlatformIO Library Registry publishing**
77
- - ✅ GitHub Wiki synchronization
78
- - ✅ Arduino Library Manager package preparation
79
- - ✅ Release notes generation from changelog
80
-
81
- ## 📋 Distribution Channels
82
-
83
- ### Automatic (Zero Manual Work Required)
84
-
85
- 1. **GitHub Releases** - Created with changelog and downloadable packages
86
- 2. **NPM Public Registry** - Published to <https://www.npmjs.com/package/@alteriom/painlessmesh>
87
- 3. **GitHub Packages** - Published to GitHub's NPM registry (@alteriom/painlessmesh)
88
- 4. **PlatformIO Registry** - Automatically published via GitHub Actions workflow
89
- 5. **GitHub Wiki** - Documentation synchronized from repository
90
-
91
- ### Semi-Automatic (One-Time Manual Submission)
92
-
93
- 1. **Arduino Library Manager** - Submit once, then automatically indexed
94
-
95
- ## 🎯 Detailed Process
96
-
97
- ### Version Management
98
-
99
- > **📖 For detailed information about version management, see [VERSION_MANAGEMENT.md](docs/VERSION_MANAGEMENT.md)**
100
-
101
- **File Consistency**: All three files must have matching versions:
102
-
103
- ```properties
104
- # library.properties
105
- version=1.6.1
106
- ```
107
-
108
- ```json
109
- // library.json
110
- {
111
- "version": "1.6.1"
112
- }
113
- ```
114
-
115
- ```json
116
- // package.json
117
- {
118
- "version": "1.6.1"
119
- }
120
- ```
121
-
122
- **Semantic Versioning**: Follow [semver.org](https://semver.org/):
123
- - **MAJOR**: Breaking changes (e.g., 1.6.0 → 2.0.0)
124
- - **MINOR**: New features, backward compatible (e.g., 1.6.0 → 1.7.0)
125
- - **PATCH**: Bug fixes, backward compatible (e.g., 1.6.0 → 1.6.1)
126
-
127
- ### Automation Triggers
128
-
129
- The release workflow triggers on commits to `main` that:
130
- 1. Modify `library.properties`, `library.json`, `package.json`, or `CHANGELOG.md`
131
- 2. Have version files modified OR commit message starting with `release:`
132
-
133
- ### What Gets Automated
134
-
135
- #### Testing Pipeline
136
- - **Desktop builds**: gcc & clang with strict warnings
137
- - **Arduino CLI**: ESP32 & ESP8266 compilation
138
- - **PlatformIO**: Cross-platform build validation
139
- - **Code quality**: Formatting and lint checks
140
-
141
- #### Release Artifacts
142
- - **Git tag**: `v1.6.1` format
143
- - **GitHub Release**: With changelog excerpt
144
- - **Library package**: `painlessMesh-v1.6.1.zip`
145
- - **Documentation**: Auto-deployed to GitHub Pages
146
-
147
- #### NPM Publishing
148
- - **Public NPM**: Available to anyone via `npm install @alteriom/painlessmesh`
149
- - **GitHub Packages**: Scoped package for authenticated users
150
- - **Version consistency**: Verified across all package files
151
-
152
- #### Wiki Updates
153
- - **Home Page**: Generated from README.md
154
- - **API Reference**: Auto-generated documentation
155
- - **Examples**: Links to repository examples
156
- - **Installation Guide**: Multi-platform instructions
157
-
158
- ## 📦 NPM Publishing Details
159
-
160
- ### Dual Publishing Strategy
161
-
162
- Each release publishes to **two NPM registries**:
163
-
164
- 1. **Public NPM** (npmjs.com)
165
- - Package: `@alteriom/painlessmesh`
166
- - Installation: `npm install @alteriom/painlessmesh`
167
- - No authentication required
168
-
169
- 2. **GitHub Packages** (npm.pkg.github.com)
170
- - Package: `@alteriom/painlessmesh`
171
- - Installation: Requires `.npmrc` configuration
172
- - Authentication required for installation
173
-
174
- ### NPM Package Contents
175
-
176
- The NPM package includes:
177
- - `src/` - Complete library source code
178
- - `examples/` - All Arduino examples
179
- - `docs/` - Documentation files
180
- - `library.properties` - Arduino metadata
181
- - `library.json` - PlatformIO metadata
182
- - Core documentation files (README, LICENSE, CHANGELOG)
183
-
184
- Excluded from NPM package:
185
-
186
- - Development files (`.github/`, `test/`, `scripts/`)
187
- - Build artifacts (`bin/`, `build/`)
188
- - IDE files and OS-specific files
189
-
190
- ## 🔧 PlatformIO Library Registry
191
-
192
- ### Automatic Publishing
193
-
194
- Each release triggers the **PlatformIO Library Publishing** workflow:
195
-
196
- 1. **Validation**: Comprehensive library.json validation
197
- 2. **Dependencies**: Verification that all dependencies exist in PlatformIO Registry
198
- 3. **Authentication**: Uses `PLATFORMIO_AUTH_TOKEN` secret
199
- 4. **Publication**: Direct publishing via PlatformIO CLI
200
- 5. **Verification**: Post-publication registry verification
201
-
202
- ### Setup Requirements
203
-
204
- #### One-Time Setup: PlatformIO Account & Token
205
-
206
- 1. **Create Account**: <https://platformio.org/account/register>
207
- 2. **Generate Token**: <https://platformio.org/account/token>
208
- 3. **Add Secret**: Repository Settings → Secrets → `PLATFORMIO_AUTH_TOKEN`
209
-
210
- #### Automatic Workflow Trigger
211
-
212
- The PlatformIO workflow is started by:
213
-
214
- - The `platformio-dispatch` job in **Automated Release**, which calls
215
- `gh workflow run platformio-publish.yml --ref v<version> -f version=<version>`
216
- right after the release is created
217
- - A GitHub release published by a human (via the UI or a PAT)
218
- - Manual workflow dispatch for testing
219
-
220
- > **Why the explicit dispatch?** `platformio-publish.yml` also listens for
221
- > `release: published`, but that event never fires for releases created by
222
- > `release.yml`: GitHub suppresses events raised by the built-in `GITHUB_TOKEN`.
223
- > `workflow_dispatch` is one of the two documented exceptions to that rule, so
224
- > the release workflow dispatches the publish explicitly and then verifies a run
225
- > actually appeared. Before this was added, PlatformIO publication silently did
226
- > not happen and had to be dispatched by hand (v1.9.21).
227
-
228
- ### PlatformIO Package Contents
229
-
230
- Published package includes:
231
-
232
- - Complete source code (`src/`)
233
- - All examples (`examples/`)
234
- - PlatformIO metadata (`library.json`)
235
- - Arduino compatibility (`library.properties`)
236
- - Documentation files
237
-
238
- ### Installation
239
-
240
- Users can install via PlatformIO:
241
-
242
- ```ini
243
- # platformio.ini
244
- [env:esp32dev]
245
- platform = espressif32
246
- board = esp32dev
247
- framework = arduino
248
- lib_deps = alteriom/AlteriomPainlessMesh@^1.6.1
249
- ```
250
-
251
- Or via CLI:
252
-
253
- ```bash
254
- pio pkg install --library "alteriom/AlteriomPainlessMesh@^1.6.1"
255
- ```
256
-
257
- ### Manual Publication (Fallback)
258
-
259
- If automatic publishing fails:
260
-
261
- ```bash
262
- # Install PlatformIO CLI
263
- pip install platformio
264
-
265
- # Authenticate
266
- pio account token --set YOUR_TOKEN
267
-
268
- # Publish from repository root
269
- pio pkg publish .
40
+ ./scripts/bump-version.sh patch
270
41
  ```
271
42
 
272
- ### Monitoring
273
-
274
- - **Registry**: <https://registry.platformio.org/libraries>
275
- - **Search**: <https://registry.platformio.org/search?q=AlteriomPainlessMesh>
276
- - **Workflow**: GitHub Actions → PlatformIO Library Publishing
277
-
278
- ## 🛠️ Arduino Library Manager
279
-
280
- ### ✅ IMPORTANT: Library Name Fixed
281
-
282
- **Current Status**: ✅ **REGISTERED AND FIXED**
43
+ You may use `minor`, `major`, or an explicit version when the release plan
44
+ requires it. Version 2.0 patch releases must remain wire-compatible with the
45
+ 2.0 protocol.
283
46
 
284
- The library IS registered in the Arduino Library Manager. The issue was a library name change that prevented new versions from being indexed.
47
+ ## Changelog
285
48
 
286
- **Issue Resolved**: Library name in `library.properties` has been restored to match the original registration.
287
-
288
- **Result**: New releases will now be automatically indexed by Arduino Library Manager within 24-48 hours.
289
-
290
- ### One-Time Submission Process
291
-
292
- **This must be done once** to enable Arduino IDE installation:
293
-
294
- 1. **Go to**: https://github.com/arduino/library-registry
295
- 2. **Click**: "Issues" → "New Issue"
296
- 3. **Create issue** with this template:
49
+ During development, add user-visible changes to `## [Unreleased]`. At release
50
+ time, create a dated section:
297
51
 
298
52
  ```markdown
299
- Title: Add AlteriomPainlessMesh library
300
-
301
- Repository URL: https://github.com/Alteriom/painlessMesh
302
- Library Name: AlteriomPainlessMesh
303
- Current Version: 1.8.2
304
- Release Tag: v1.8.2
305
-
306
- Description:
307
- AlteriomPainlessMesh is a user-friendly library for creating mesh networks
308
- with ESP8266 and ESP32 devices. Enhanced fork of painlessMesh with:
309
-
310
- - SensorPackage (Type 200): Environmental data collection
311
- - StatusPackage (Type 202): Device health monitoring
312
- - CommandPackage (Type 400): Remote device control
313
- - MetricsPackage (Type 204): Performance metrics
314
- - HealthCheckPackage (Type 605): Proactive monitoring
315
- - Bridge Coordination: Multi-bridge high availability
316
- - Message Queue: Offline message queueing
317
-
318
- Category: Communication
319
- Architectures: esp8266, esp32
320
- Dependencies: ArduinoJson (^7.4.2), TaskScheduler (^4.0.0)
321
- License: LGPL-3.0
322
- Documentation: https://alteriom.github.io/painlessMesh/
323
-
324
- All Arduino requirements met. Ready for indexing.
325
- ```
326
-
327
- 4. **Monitor** the issue for Arduino team approval (1-2 weeks typical)
328
- 5. **Verify** registration via Arduino IDE Library Manager search
329
- 6. **Future releases** automatically indexed (24-48 hour delay)
330
-
331
- ### Detailed Submission Guide
332
-
333
- For complete instructions, see: [docs/ARDUINO_LIBRARY_MANAGER_SUBMISSION.md](docs/ARDUINO_LIBRARY_MANAGER_SUBMISSION.md)
334
-
335
- The guide includes:
336
- - Pre-submission checklist
337
- - Detailed submission template
338
- - Testing procedures
339
- - Troubleshooting common issues
340
- - Post-registration maintenance
341
-
342
- ### Arduino Library Compliance
343
-
344
- The library meets all Arduino Library Manager requirements:
345
- - ✅ Correct directory structure
346
- - ✅ Valid `library.properties` file (version=1.8.2)
347
- - ✅ Source files in `src/` directory
348
- - ✅ Examples compile successfully (19+ examples)
349
- - ✅ Consistent version numbering across files
350
- - ✅ Open source license (LGPL-3.0)
351
- - ✅ Git tags match library versions
352
- - ✅ Comprehensive documentation
353
-
354
- ## 📚 GitHub Wiki Management
355
-
356
- ### Automatic Synchronization
357
-
358
- Wiki pages are automatically updated on each release:
359
-
360
- - **Home** - From README.md
361
- - **Release-Guide** - From RELEASE_GUIDE.md
362
- - **Changelog** - From CHANGELOG.md
363
- - **API-Reference** - Generated documentation
364
- - **Examples** - Auto-generated from examples directory
365
- - **Installation** - Multi-platform installation guide
366
- - **Contributing** - From CONTRIBUTING.md
367
-
368
- ### Manual Wiki Updates
369
-
370
- If you need to update the wiki manually:
371
-
372
- ```bash
373
- # Clone wiki repository
374
- git clone https://github.com/Alteriom/painlessMesh.wiki.git
375
-
376
- # Edit markdown files directly
377
- # Commit and push changes
378
- ```
379
-
380
- Note: Manual changes may be overwritten by automatic synchronization.
381
-
382
- ## 🔧 Scripts Reference
383
-
384
- ### `./scripts/release-agent.sh` ⭐ NEW
385
-
386
- **Comprehensive release validation and quality assurance.**
387
-
388
- The Release Agent performs 21+ automated checks to ensure release readiness:
389
-
390
- - ✅ Version consistency across all package files
391
- - ✅ CHANGELOG completeness and format validation
392
- - ✅ Build system configuration
393
- - ✅ Dependency validation
394
- - ✅ Git tag existence check
395
- - ✅ Release workflow configuration
396
- - ✅ Documentation link validation
397
- - ✅ Test suite status (when available)
398
-
399
- **Usage:**
400
- ```bash
401
- ./scripts/release-agent.sh # Full validation
402
- ./scripts/release-agent.sh --help # Show help
403
- ./scripts/release-agent.sh --version # Show version
404
- ```
405
-
406
- **Benefits:**
407
- - 🎯 Catches issues before they reach CI/CD
408
- - 📊 Clear, color-coded output for easy scanning
409
- - 🔧 Specific solutions for each type of issue
410
- - 🚀 Comprehensive validation in under 5 seconds
411
- - ✨ Professional release summary with next steps
412
-
413
- **When to Use:**
414
- - Before every release commit
415
- - After making version changes
416
- - When troubleshooting release issues
417
- - As part of your local release workflow
418
-
419
- **See Also:** `.github/agents/release-agent.md` for complete documentation
420
-
421
- ### `./scripts/bump-version.sh`
422
- Updates version in all library files with consistency checks.
423
-
424
- **Usage:**
425
- ```bash
426
- ./scripts/bump-version.sh patch # Increment patch version
427
- ./scripts/bump-version.sh minor # Increment minor version
428
- ./scripts/bump-version.sh major # Increment major version
429
- ./scripts/bump-version.sh patch 1.6.2 # Set specific version
430
- ```
431
-
432
- ### `./scripts/validate-release.sh`
433
- Comprehensive pre-release validation.
434
-
435
- **Checks:**
436
- - Version consistency between all files
437
- - Changelog entries for current version
438
- - Git working tree status
439
- - Tag existence validation
440
- - Dependency declarations
441
- - Build file presence
442
- - Quick compilation test
443
-
444
- ## 🚨 Troubleshooting
445
-
446
- ### Common Issues
447
-
448
- **Version Mismatch Error**
449
- ```bash
450
- # Fix version inconsistencies
451
- ./scripts/bump-version.sh patch 1.6.2 # Force set version
452
- ```
453
-
454
- **Missing Changelog Entry**
455
- ```bash
456
- # Add changelog entry for current version
457
- vim CHANGELOG.md
458
- # Add section: ## [1.6.2] - YYYY-MM-DD
459
- ```
460
-
461
- **Build Failures**
462
- ```bash
463
- # Test locally before release
464
- npm run build
465
- npm run test
466
- ```
467
-
468
- **NPM Token Expired / Invalid (`E401 Unauthorized`)**
469
-
470
- Symptom: the `npm-publish` job fails at *Verify NPM authentication* with
471
- `401 Unauthorized - GET https://registry.npmjs.org/-/whoami`. npm tokens
472
- expire; everything else in the release (tag, GitHub Release, zip asset,
473
- GitHub Packages, PlatformIO) succeeds independently, so **the release can look
474
- green-ish while npmjs.org is missing the version**. Always confirm with
475
- `npm view @alteriom/painlessmesh version`.
476
-
477
- Rotating the token is operator-only — it cannot be automated from CI:
478
-
479
- ```bash
480
- # 1. Mint a fresh granular token, scoped to @alteriom/painlessmesh, with
481
- # "Read and write" AND the "Bypass 2FA" option enabled <-- see EOTP below
482
- # https://www.npmjs.com/settings/tokens
483
- # 2. Verify the new token before saving it (recommended).
484
- # Ask the registry directly — do NOT use a bare `npm whoami`, which answers
485
- # for whatever credential your local ~/.npmrc already holds and will happily
486
- # pass while the new token is bad:
487
- curl -sS -H "Authorization: Bearer <new-token>" \
488
- https://registry.npmjs.org/-/whoami # -> {"username":"..."} , not 401
489
-
490
- # 3. Update the NPM_TOKEN *organisation* secret — NOT a repository secret.
491
- # painlessMesh has no repo-level NPM_TOKEN and must not gain one; see
492
- # "Where NPM_TOKEN actually lives" below.
493
- # https://github.com/organizations/Alteriom/settings/secrets/actions
494
-
495
- # 4a. Re-run the failed release job (keeps the original run's context)
496
- gh run rerun <run-id> --failed --repo Alteriom/painlessMesh
497
-
498
- # 4b. …or republish a missed version out-of-band. Pass the TAG as ref:
499
- # without it the workflow builds the default branch, and if main has moved
500
- # on since the tag it would upload today's code under the old version
501
- # number. The workflow now refuses that outright — pass ref so you never
502
- # have to rely on the guard catching it.
503
- gh workflow run manual-publish.yml --repo Alteriom/painlessMesh \
504
- -f ref=v1.9.21 -f publish_npm=true -f publish_github=false
505
-
506
- # 5. Confirm the version actually landed
507
- npm view @alteriom/painlessmesh version
508
- ```
509
-
510
- #### Where NPM_TOKEN actually lives
511
-
512
- `NPM_TOKEN` is an **organisation** secret on `Alteriom`, shared by every repo
513
- that publishes to npm. painlessMesh has **no repository-level copy**, and adding
514
- one is a trap rather than a tightening:
515
-
516
- > A repository secret silently takes precedence over an organisation secret of
517
- > the same name. The repo then stops seeing org-wide rotations and keeps using
518
- > its own copy until that copy expires — which is invisible until a release day
519
- > fails.
520
-
521
- Two sibling repos already sit in that state, with repo-level `NPM_TOKEN` copies
522
- that shadow the org secret (`webhook-client`, `repository-metadata-manager`).
523
- Rotate the org secret and those two are still broken; delete the repo-level copy
524
- and they inherit the fresh one. Check before assuming a rotation reached a repo:
525
-
526
- ```bash
527
- # Empty output = good (inherits the org secret)
528
- gh api repos/Alteriom/<repo>/actions/secrets \
529
- --jq '.secrets[] | select(.name=="NPM_TOKEN") | "SHADOWED, updated \(.updated_at)"'
530
- ```
531
-
532
- While rotating `NPM_TOKEN`, check `PLATFORMIO_AUTH_TOKEN` too — it expires the
533
- same way and `platformio-publish.yml` hard-fails on an invalid one.
534
-
535
- **NPM asks for a one-time password (`EOTP`)**
536
-
537
- Symptom: authentication *succeeds* — `npm whoami` prints the username — and then
538
- `npm publish` fails with:
539
-
540
- ```
541
- npm error code EOTP
542
- npm error This operation requires a one-time password from your authenticator.
543
- ```
544
-
545
- The token is valid but is not allowed to bypass 2FA, and CI has no authenticator
546
- to answer the challenge with. **A rotation that fixes `E401` lands here if the
547
- replacement token is minted without the bypass option** — which is what happened
548
- on the second rotation attempt for #381.
549
-
550
- npm removed the legacy token types (`read-only` / `automation` / `publish`) in
551
- **November 2025**; only granular access tokens exist now. The old *Automation*
552
- token bypassed 2FA by virtue of its type, so this was never a decision anyone had
553
- to make. On a granular token it is an explicit checkbox, and a token minted from
554
- muscle memory does not have it:
555
-
556
- > **Bypass 2FA** — required. Takes precedence over account-level and
557
- > package-level 2FA settings for publishing.
558
-
559
- Re-mint at <https://www.npmjs.com/settings/tokens> with *Read and write* on
560
- `@alteriom/painlessmesh` **and Bypass 2FA enabled**, update the secret, re-run.
561
- `npm whoami` cannot detect this ahead of time — it passes for both token kinds,
562
- so the failure necessarily surfaces at the publish call.
563
-
564
- ### Trusted publishing (OIDC) — the way out of token rotation
565
-
566
- Both failures above are symptoms of the same thing: a long-lived credential that
567
- expires silently and is only exercised on release day. npm's replacement is
568
- **trusted publishing** — the workflow authenticates to npm over OIDC, and
569
- `NPM_TOKEN` stops existing.
570
-
571
- This is on a clock rather than merely being nicer: as of **2026-07-31** bypass-2FA
572
- tokens can no longer manage tokens, package access, or trusted-publishing config,
573
- and npm has targeted **January 2027** for removing *direct publish* from them —
574
- after which they can only stage a publish for a maintainer to approve with 2FA.
575
- The current setup stops working at that point.
576
-
577
- Requirements, none of which this repo blocks on today:
578
-
579
- | Requirement | Status here |
580
- |---|---|
581
- | `id-token: write` permission | ✅ already set in `release.yml` and `manual-publish.yml` |
582
- | npm CLI ≥ 11.5.1, Node ≥ 22.14.0 | ❌ workflows pin `node-version: '18'` — needs a bump |
583
- | Trusted publisher registered on npmjs.com | ❌ operator, one-time, per workflow file |
584
-
585
- The npmjs.com side is under *Package settings → Trusted publisher*: org
586
- `Alteriom`, repository `painlessMesh`, workflow filename `release.yml` (add a
587
- second entry for `manual-publish.yml` if that path should keep working).
588
-
589
- **GitHub Packages Authentication**
590
- ```bash
591
- # Check if GITHUB_TOKEN has packages:write permission
592
- # Repository Settings → Actions → General → Permissions
593
- ```
594
-
595
- **Wiki Update Failure**
596
- ```bash
597
- # Wiki may need manual initialization
598
- # Go to: https://github.com/Alteriom/painlessMesh/wiki
599
- # Create any page to initialize, then re-run release
600
- ```
601
-
602
- **NPM/GitHub Packages Not Published Automatically**
603
-
604
- The automated workflow triggers a release in two ways:
605
-
606
- 1. **Automatic (Recommended)**: When version files are updated in a commit
607
- - The workflow detects changes to `library.properties`, `library.json`, or `package.json`
608
- - Automatically creates tag, release, and publishes packages when these files are modified
609
- - Works seamlessly with PR merges and direct commits
610
-
611
- 2. **Manual trigger**: Commit message starts with `release:` (lowercase with colon):
612
-
613
- ```bash
614
- # ✅ Correct - Will trigger full release
615
- git commit -m "release: v1.7.7 - Complete mqtt-schema implementation"
53
+ ## [X.Y.Z] - YYYY-MM-DD
616
54
 
617
- # ✅ Also works - Version file changes detected automatically
618
- # (No special commit message needed when library.properties/json/package.json are modified)
619
- git commit -m "Bump version to 1.7.8"
620
- ```
621
-
622
- **Note**: If version files weren't modified and commit message doesn't start with "release:", the workflow will skip publishing.
623
-
624
- **Solution: Use Manual Publishing Workflow**
625
-
626
- If this happens, you can manually publish packages:
627
-
628
- 1. Go to **Actions** → **Manual Package Publishing**
629
- 2. Click **Run workflow**
630
- 3. Select options:
631
- - ✅ Publish to NPM Registry
632
- - ✅ Publish to GitHub Packages
633
- 4. Click **Run workflow**
634
-
635
- The manual workflow will:
636
- - Read the current version from `library.properties` and refuse to run if it
637
- disagrees with `package.json` (npm publishes the `package.json` version)
638
- - Validate `NPM_TOKEN` against the registry before attempting to publish, so an
639
- expired token fails immediately with rotation instructions
640
- - Publish to NPM (if selected)
641
- - Publish to GitHub Packages (if selected)
642
- - Show success/failure status for each
643
-
644
- It does **not** publish to the PlatformIO registry — use
645
- `gh workflow run platformio-publish.yml --ref v<version> -f version=<version>`
646
- for that.
55
+ ### Fixed
647
56
 
648
- Alternatively, from command line:
649
- ```bash
650
- # Trigger via GitHub CLI
651
- gh workflow run manual-publish.yml
57
+ - Describe the observed defect, its impact, and the verified correction.
652
58
  ```
653
59
 
654
- ### Manual Override
655
-
656
- If automation fails, you can manually perform any step:
60
+ Keep operational evidence in the pull request and concise user-facing impact
61
+ in the changelog. Historical release entries remain immutable.
657
62
 
658
- ```bash
659
- # Manual NPM publish
660
- npm publish --access public
63
+ ## Validation
661
64
 
662
- # Manual GitHub release
663
- gh release create v1.6.2 --title "painlessMesh v1.6.2" --notes-file CHANGELOG.md
65
+ Run both validation scripts from the repository root:
664
66
 
665
- # Manual tag creation
666
- git tag v1.6.2
667
- git push origin v1.6.2
668
- ```
669
-
670
- ## 🔍 Validation Commands
671
-
672
- ### Pre-Release Checks
673
67
  ```bash
674
- # Comprehensive validation
675
68
  ./scripts/validate-release.sh
676
-
677
- # Version consistency check
678
- ./scripts/bump-version.sh --verify || echo "Use proper arguments"
679
-
680
- # NPM package validation
681
- npm run validate-library
682
-
683
- # Build test
684
- npm run build && npm run test
685
- ```
686
-
687
- ### Post-Release Verification
688
- ```bash
689
- # Check NPM publication
690
- npm view @alteriom/painlessmesh
691
-
692
- # Check GitHub Packages
693
- npm view @alteriom/painlessmesh --registry=https://npm.pkg.github.com
694
-
695
- # Check PlatformIO Registry
696
- pio pkg search "AlteriomPainlessMesh"
697
-
698
- # Verify GitHub release
699
- gh release view
700
-
701
- # Check wiki update
702
- curl -s https://github.com/Alteriom/painlessMesh/wiki | grep -q "v1.6.2"
703
- ```
704
-
705
- ## 🎉 Success Indicators
706
-
707
- ### Successful Release Shows:
708
- - ✅ GitHub release created with changelog
709
- - ✅ Git tag pushed to repository
710
- - ✅ NPM package published (check npmjs.com)
711
- - ✅ GitHub Packages updated
712
- - ✅ Wiki pages synchronized
713
- - ✅ All GitHub Actions workflows completed successfully
714
-
715
- ### Distribution Verification:
716
- ```bash
717
- # Public NPM
718
- npm view @alteriom/painlessmesh
719
-
720
- # GitHub Packages
721
- npm view @alteriom/painlessmesh --registry=https://npm.pkg.github.com
722
-
723
- # PlatformIO (updated within minutes via GitHub Actions)
724
- # Check: https://registry.platformio.org/libraries/alteriom/AlteriomPainlessMesh
725
-
726
- # Arduino Library Manager (after manual submission)
727
- # Search in Arduino IDE Library Manager
728
- ```
729
-
730
- ## 🌟 Advanced Topics
731
-
732
- ### Custom Release Notes
733
-
734
- To customize release notes beyond the changelog:
735
-
736
- 1. Edit the generated `release_notes.txt` in the workflow
737
- 2. Or create a custom release notes file in `.github/release-template.md`
738
-
739
- ### Environment-Specific Releases
740
-
741
- For testing releases:
742
-
743
- ```bash
744
- # Use pre-release tags
745
- git tag v1.6.2-beta
746
- git push origin v1.6.2-beta
747
-
748
- # This creates a pre-release without full publication
749
- ```
750
-
751
- ### Rollback Procedure
752
-
753
- If a release has issues:
754
-
755
- ```bash
756
- # Delete remote tag
757
- git push origin :refs/tags/v1.6.2
758
-
759
- # Delete local tag
760
- git tag -d v1.6.2
761
-
762
- # Delete GitHub release
763
- gh release delete v1.6.2
764
-
765
- # Unpublish NPM package (contact npm support)
766
- # GitHub Packages: Delete from package settings
69
+ ./scripts/release-agent.sh
767
70
  ```
768
71
 
769
- ## 📊 Release Metrics
72
+ The pull request must also pass all required GitHub checks, including:
770
73
 
771
- Monitor your releases:
772
- - **GitHub**: https://github.com/Alteriom/painlessMesh/releases
773
- - **NPM**: https://www.npmjs.com/package/@alteriom/painlessmesh
774
- - **PlatformIO**: https://registry.platformio.org/libraries/alteriom/painlessMesh
775
- - **Wiki**: https://github.com/Alteriom/painlessMesh/wiki
74
+ - gcc, clang, and AddressSanitizer desktop builds
75
+ - Arduino ESP32 and ESP8266 compilation
76
+ - PlatformIO builds and build-flag validation
77
+ - formatting and documentation checks
78
+ - CodeQL
79
+ - simulator scenarios
80
+ - ESP32, ESP32-C3, and ESP32-S3 hardware-in-the-loop coverage when the change
81
+ touches radio, routing, gateway, OTA, or platform-specific behavior
776
82
 
777
- ## 🤝 Security & Permissions
83
+ For a hardware defect, attach the HIL run identifier and report link to the
84
+ pull request. A unit test alone is not sufficient evidence for a radio or
85
+ multi-device timing fix.
778
86
 
779
- ### Required GitHub Secrets
87
+ ## Review gate
780
88
 
781
- - `GITHUB_TOKEN`: Automatically provided by GitHub Actions
782
- - `NPM_TOKEN`: Required for NPM publishing. Lives in the **Alteriom
783
- organisation** secrets and is inherited — do not add a repository-level copy,
784
- which would shadow it (see [Where NPM_TOKEN actually lives](#where-npm_token-actually-lives))
785
- - `PLATFORMIO_AUTH_TOKEN`: Required for PlatformIO Library Registry publishing
89
+ A release pull request is ready only when:
786
90
 
787
- Both `NPM_TOKEN` and `PLATFORMIO_AUTH_TOKEN` are user-minted tokens that
788
- **expire**. Their expiry is invisible until a release fails, so rotate them
789
- together and re-check after any expiry date you set. See
790
- [NPM Token Expired / Invalid](#-troubleshooting) for the rotation runbook.
91
+ - it has an approving review;
92
+ - all review comments are resolved;
93
+ - required checks are green on the final commit;
94
+ - the branch is current with its target branch;
95
+ - version metadata and changelog validation pass;
96
+ - there are no unexplained skipped hardware scenarios.
791
97
 
792
- ### Repository Settings
793
- - **Actions**: Enabled with write permissions
794
- - **Packages**: Enabled for GitHub Packages publication
795
- - **Wiki**: Enabled for documentation deployment
796
- - **Releases**: Public releases enabled
98
+ Any code change after approval invalidates the approval and requires another
99
+ review of the final commit.
797
100
 
798
- ---
101
+ ## Automated publication
799
102
 
800
- ## Quick Reference
103
+ When a qualifying version commit reaches `main`, `.github/workflows/release.yml`
104
+ validates the metadata, creates the `vX.Y.Z` tag and GitHub release, uploads the
105
+ Arduino archive, publishes npm and GitHub Packages, and dispatches the
106
+ PlatformIO publication workflow.
801
107
 
802
- **Release a patch version:**
803
- ```bash
804
- ./scripts/bump-version.sh patch
805
- # Edit CHANGELOG.md
806
- git add . && git commit -m "release: v1.6.2" && git push
807
- ```
108
+ Monitor every publication job to completion. Verify the version is visible in
109
+ each registry before announcing the release. Arduino Library Manager indexing
110
+ can lag behind the GitHub release.
808
111
 
809
- **Check release status:**
810
- ```bash
811
- ./scripts/validate-release.sh
812
- ```
112
+ ## Recovery
813
113
 
814
- **Monitor release:**
815
- - GitHub Actions: https://github.com/Alteriom/painlessMesh/actions
816
- - Releases: https://github.com/Alteriom/painlessMesh/releases
817
- - Documentation: https://github.com/Alteriom/painlessMesh/wiki
114
+ Never reuse a published semantic version. If publication succeeds in one
115
+ registry and fails in another, fix the credential or workflow problem and
116
+ rerun only the failed publication path for the same tag. If shipped code is
117
+ defective, prepare a new patch release rather than replacing the existing tag.
818
118
 
819
- For questions or issues with the release process, create an issue with the `ci/cd` label.
119
+ Security-sensitive release failures or suspected credential exposure must be
120
+ handled according to [SECURITY.md](SECURITY.md).