Release to pub.dev
Prepare and execute a dart_node release. This is a multi-step process that publishes packages in tiers due to interdependencies.
Arguments
$ARGUMENTS = version to release (e.g., 0.12.0-beta, 1.0.0)
If no version provided, show current versions and prompt for the target version.
Step 1: Pre-flight checks
1.1 Verify clean state
git status git branch --show-current
- •Must be on
mainbranch (or create a release branch) - •Working directory should be clean
1.2 Check current versions
grep -h "^version:" packages/*/pubspec.yaml | head -20
1.3 Validate all packages have configs
dart run tools/prepare_publish.dart 2>&1 || true
This shows any packages missing from tools/lib/packages.dart.
Step 2: Switch dependencies to pub.dev versions
CRITICAL: Before publishing, all internal dependencies must point to pub.dev versions, NOT local paths!
Use tools/switch_deps.dart to switch:
# Switch from local paths to pub.dev versioned dependencies dart run tools/switch_deps.dart release
This converts:
# FROM (local development): dart_node_core: path: ../dart_node_core # TO (release): dart_node_core: ^0.11.0-beta
To switch back to local for development:
dart run tools/switch_deps.dart local
Note: The CI workflow handles this automatically on the release branch.
Step 3: Validate changelogs
Every publishable package must have a ## $ARGUMENTS entry in its CHANGELOG.md.
Publishable packages (must have changelog entries):
| Tier | Package |
|---|---|
| 1 | dart_logging |
| 1 | dart_node_core |
| 2 | reflux |
| 2 | dart_node_express |
| 2 | dart_node_ws |
| 2 | dart_node_better_sqlite3 |
| 2 | dart_node_mcp |
| 3 | dart_node_react |
| 3 | dart_node_react_native |
Check each changelog:
VERSION="$ARGUMENTS"
for pkg in dart_logging dart_node_core reflux dart_node_express dart_node_ws dart_node_better_sqlite3 dart_node_mcp dart_node_react dart_node_react_native; do
if grep -q "^## $VERSION" "packages/$pkg/CHANGELOG.md" 2>/dev/null; then
echo "✅ $pkg"
else
echo "❌ $pkg - missing ## $VERSION entry"
fi
done
If any are missing, stop and update the changelogs before proceeding.
Step 4: Validate READMEs
Each package should have a README.md. Quick sanity check:
for pkg in dart_logging dart_node_core reflux dart_node_express dart_node_ws dart_node_better_sqlite3 dart_node_mcp dart_node_react dart_node_react_native; do
if [[ -f "packages/$pkg/README.md" ]]; then
LINES=$(wc -l < "packages/$pkg/README.md")
echo "✅ $pkg - $LINES lines"
else
echo "❌ $pkg - missing README.md"
fi
done
Step 5: Check pub.dev status
Verify which versions are currently published:
for pkg in dart_logging dart_node_core reflux dart_node_express dart_node_ws dart_node_better_sqlite3 dart_node_mcp dart_node_react dart_node_react_native; do LATEST=$(curl -s "https://pub.dev/api/packages/$pkg" | grep -o '"version":"[^"]*"' | head -1 | cut -d'"' -f4) echo "$pkg: $LATEST" done
Step 6: Run tests
Before releasing, ensure all tests pass:
./tools/test.sh
Or run specific tiers:
./tools/test.sh --tier 1 ./tools/test.sh --tier 2 ./tools/test.sh --tier 3
Step 7: Bump versions (dry run)
Preview what changes the prepare script will make:
dart run tools/prepare_publish.dart $ARGUMENTS
This updates:
- •
version:in all pubspec.yaml files - •Interdependencies to use
^$ARGUMENTS(pub.dev versions) - •Removes
publish_to: none
Do NOT commit these changes yet - they are made on a release branch by CI.
Step 8: Create release tag
The release is triggered by pushing a tag:
git tag "Release/$ARGUMENTS" git push origin "Release/$ARGUMENTS"
This triggers the publish-tier1 workflow which:
- •Creates a
release/$ARGUMENTSbranch - •Runs
prepare_publish.dart - •Creates a PR to main
- •Publishes dart_logging and dart_node_core
Step 9: Tier 2 publishing
After tier 1 succeeds and packages are live on pub.dev (wait ~5 minutes for indexing):
git tag "Release-Tier2/$ARGUMENTS" git push origin "Release-Tier2/$ARGUMENTS"
Publishes: reflux, dart_node_express, dart_node_ws, dart_node_better_sqlite3, dart_node_mcp
Step 10: Tier 3 publishing
After tier 2 succeeds:
git tag "Release-Tier3/$ARGUMENTS" git push origin "Release-Tier3/$ARGUMENTS"
Publishes: dart_node_react, dart_node_react_native
After tier 3 completes, it switches dependencies back to local and pushes to the release branch.
Step 11: Merge the release PR
After all tiers complete successfully:
- •Go to the PR created by tier 1
- •Verify all packages are published on pub.dev
- •Merge the PR to main
Verification
After release, verify all packages are available:
VERSION="$ARGUMENTS"
for pkg in dart_logging dart_node_core reflux dart_node_express dart_node_ws dart_node_better_sqlite3 dart_node_mcp dart_node_react dart_node_react_native; do
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" "https://pub.dev/api/packages/$pkg/versions/$VERSION")
if [[ "$HTTP_CODE" == "200" ]]; then
echo "✅ $pkg@$VERSION published"
else
echo "❌ $pkg@$VERSION not found (HTTP $HTTP_CODE)"
fi
done
Troubleshooting
Package already published
If a package version already exists, the publish script skips it. This is safe.
Dependency resolution fails
Tier 2/3 packages depend on tier 1. Wait for tier 1 to be fully indexed on pub.dev before starting tier 2.
Changelog validation fails
Add the missing ## X.Y.Z header to the package's CHANGELOG.md with release notes.
Checklist summary
- • On main branch, clean working directory
- • No local path dependencies (all point to pub.dev versions)
- • All changelogs have
## $ARGUMENTSentries - • All READMEs are present and up-to-date
- • All tests pass
- •
Release/$ARGUMENTStag pushed (triggers tier 1) - • Tier 1 complete, packages live on pub.dev
- •
Release-Tier2/$ARGUMENTStag pushed - • Tier 2 complete, packages live on pub.dev
- •
Release-Tier3/$ARGUMENTStag pushed - • Tier 3 complete, packages live on pub.dev
- • Release PR merged to main