chore: add per-package versioning, changesets, and clean changelogs
- Add cliff.toml for git-cliff changelog generation (one-line entries, no commit body dumps, improve/refine prefixes mapped) - Add @changesets/cli config and README in .changeset/ - Add release.sh script with per-package version bumps from changesets, changeset-driven per-crate changelog updates, and --all/--dry-run flags - Switch all crates from workspace version to independent version = "0.1.0" - Generate clean root CHANGELOG.md and per-crate CHANGELOGs with [0.1.0] - Retag v1.0.0 → v0.1.0 to match actual crate versions Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
9e2cb29dd9
commit
878e55b962
24 changed files with 689 additions and 9 deletions
5
.changeset/README.md
Normal file
5
.changeset/README.md
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
# Changesets
|
||||
|
||||
Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works
|
||||
with multi-package repos, or single-package repos to help you version and publish your code. You can find
|
||||
the full documentation for it [in the changesets repo](https://github.com/changesets/changesets).
|
||||
11
.changeset/config.json
Normal file
11
.changeset/config.json
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"$schema": "https://unpkg.com/@changesets/config@3.1.3/schema.json",
|
||||
"changelog": "@changesets/cli/changelog",
|
||||
"commit": false,
|
||||
"fixed": [],
|
||||
"linked": [],
|
||||
"access": "restricted",
|
||||
"baseBranch": "main",
|
||||
"updateInternalDependencies": "patch",
|
||||
"ignore": []
|
||||
}
|
||||
132
CHANGELOG.md
Normal file
132
CHANGELOG.md
Normal file
|
|
@ -0,0 +1,132 @@
|
|||
# Changelog
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
### 🚀 Features
|
||||
|
||||
- V2 phase 1 — array access, timer, string interpolation
|
||||
- Step sequencer demo — reactive pads, playhead, BPM
|
||||
- V2 built-in functions — 90+ native functions
|
||||
- V2 module system — import/export with multi-file compilation
|
||||
- V2 codegen hardening — scoped local variables
|
||||
- Todo app demo — streamable, showcases v2 builtins
|
||||
- Bidirectional signal streaming sync
|
||||
- Peer mode relay + self-echo filtering for true bidirectional sync
|
||||
- Per-signal version counters for conflict resolution
|
||||
- Explicit signal output API for stream declarations
|
||||
- 4-app signal composition demo with explicit outputs
|
||||
- Chained signal composition — 3→1→final + mood mixing
|
||||
- Stream composition API — select, schema, relay filtering
|
||||
- Dependent types — refinement types, type aliases, type annotations
|
||||
- Dependent types review — cycle detection, precision, error quality
|
||||
- Component registry with styled variants, dreamstack add/convert CLI, and showcase
|
||||
- Container variant props, 11-component registry, rich dashboard
|
||||
- Each loop, dreamstack init, expanded registry
|
||||
- When/else conditional branching
|
||||
- Slot/children composition for components
|
||||
- Dev server improvements - recursive watching, auto-open browser
|
||||
- Dynamic lists (push/remove/pop) + TodoMVC demo
|
||||
- Component event callbacks + function prop forwarding
|
||||
- Upgrade init starter app to showcase all DreamStack features
|
||||
- Multi-page routing demo with 4 routes
|
||||
- Project Manager demo — comprehensive 4-page routed app
|
||||
- Multi-statement event handlers with semicolons
|
||||
- Streaming dashboard with imported components + live data
|
||||
- Comprehensive streaming improvements
|
||||
- HTTP /meta API, signal dedup, periodic auto-sync
|
||||
- Enhanced 14 registry components + component gallery
|
||||
- Expanded variant system — 30+ new CSS class mappings
|
||||
- *= /= operators + 6 new array methods
|
||||
- Snake game streaming via relay
|
||||
- Game-pong.ds + two compiler improvements
|
||||
- Keyboard input, Web Audio synthesis, and multiplayer demo
|
||||
- Pong spectator viewer + stream proxy reactivity fix
|
||||
- Beats viewer, score sounds, audio early-exit guards
|
||||
- Core language & stream improvements
|
||||
- Complete type system — HM unification, signal-aware types, effect scoping
|
||||
- Tetris — signal composition showcase with 6 reactive layers
|
||||
- Live signal debug panel for tetris
|
||||
- Full grid collision, freeze, and T-piece support (20 rows)
|
||||
- Complete tetris rewrite — flat grid, SRS rotation, ghost piece toggle
|
||||
- Add Waveshare P4 panel device integration with display streaming and touch input, alongside core streaming engine
|
||||
- Implement Panel IR emitter to generate JSON UI descriptions for LVGL panels.
|
||||
- Implement ds-screencast engine, panel preview, and Waveshare ESP-NOW communication.
|
||||
|
||||
### 🐛 Bug Fixes
|
||||
|
||||
- Bidirectional streaming sync — phone→laptop now works
|
||||
- Add _streamDiff to push/pop/reverse built-ins
|
||||
- Streaming polish — bind diff, state snapshot, dead code cleanup
|
||||
- Signal composition — stream derived signals, fix identity check, correct relay routing
|
||||
- Use explicit /peer/counter channel for streaming-counter
|
||||
- Integer division + streaming restart
|
||||
- Component prop signal wrapping + import demo
|
||||
- When/else parentNode null guard for slot context + match parser boundaries + showcase demo
|
||||
- Match parser allows container bodies in arms
|
||||
- Merge duplicate click props + upgrade streaming examples
|
||||
- For-in parser token mismatch + enhanced step sequencer
|
||||
- Reactive component props + breakout improvements
|
||||
- Tetris collision detection — pieces now stack properly
|
||||
- Collision off-by-one — pieces now stack adjacently
|
||||
- Keyboard inputs now respect collision — soft drop and hard drop gated on blocked
|
||||
- Complete collision — checks both top row and bottom cell
|
||||
- Piece-type aware collision — only T-piece checks bottom cell
|
||||
- No-overlap rendering — hide foot cell for non-T pieces, render all 20 rows
|
||||
- I-piece now persists all 4 cells and renders at correct row
|
||||
|
||||
### 🔧 Refactoring
|
||||
|
||||
- Type system second pass — deeper unification throughout
|
||||
- Complete collision system rewrite — decomposed sub-signals
|
||||
|
||||
### 📚 Documentation
|
||||
|
||||
- Add STREAM_COMPOSITION.md — full API reference and protocol spec
|
||||
- Comprehensive documentation update
|
||||
|
||||
### ⚡ Performance
|
||||
|
||||
- Streaming core improvements — batched diffs, RTT tracking, relay merging
|
||||
- Merge same-interval timers + breakout game + beats viewer
|
||||
|
||||
## [0.1.0] - 2026-02-26
|
||||
|
||||
### 🚀 Features
|
||||
|
||||
- Add DreamStack project vision and detailed implementation plan documentation.
|
||||
- DreamStack compiler foundation — Phase 0/1
|
||||
- TodoMVC example with full reactivity
|
||||
- Phase 2+3 — effects, streams, springs, search + dashboard
|
||||
- Phase 3+4 — Cassowary constraint solver + type system
|
||||
- Phase 5 — Live Playground with editor, preview, signal graph, console
|
||||
- Showcase — What DreamStack Does That Nothing Else Can
|
||||
- Dev server with file watching + poll-based HMR
|
||||
- Signal propagation benchmarks + dev server HMR fix
|
||||
- For-in list rendering + component system
|
||||
- Hash-based router + keyed list reconciliation
|
||||
- Two-way binding, form props, and async resources
|
||||
- Universal bitstream streaming — any input → any output
|
||||
- Physics language integration — scene container with Rapier2D WASM
|
||||
- **ds-stream:** RLE compression, input events, keyframe caching
|
||||
- **demos:** Sync protocol with Rust codec, add touch/gamepad support
|
||||
- **compiler:** Full bitstream integration across 7 pipeline stages
|
||||
- **compiler:** Complete bitstream integration — all 9 changes
|
||||
- **examples:** Add streaming .ds examples — compiler-native streaming
|
||||
- **wasm:** Add ds-stream-wasm crate — browser codec via WebAssembly
|
||||
- **relay:** Multi-source routing — /source/{name} and /stream/{name}
|
||||
- **examples:** Add streaming-physics.ds, mark all roadmap items complete
|
||||
- WebRTC transport — peer-to-peer data channels with auto-fallback
|
||||
- Production hardening — relay v1.0.0, receiver protocol completeness
|
||||
|
||||
### 📚 Documentation
|
||||
|
||||
- Add implementation status, benchmarks, and React comparison to DREAMSTACK.md
|
||||
- Add router to DREAMSTACK.md features and comparison
|
||||
- Mark all integration spec changes as implemented, update test counts
|
||||
- Add Next Steps roadmap (Phases A-C) to integration spec
|
||||
- Add compiler-native streaming syntax to language reference
|
||||
- Add USE_CASES.md — vision, revenue paths, and demo roadmap
|
||||
|
||||
<!-- generated by git-cliff -->
|
||||
|
|
@ -17,7 +17,7 @@ members = [
|
|||
[workspace.package]
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
license = "MIT"
|
||||
license = ""
|
||||
|
||||
[workspace.dependencies]
|
||||
ds-parser = { path = "compiler/ds-parser" }
|
||||
|
|
|
|||
66
cliff.toml
Normal file
66
cliff.toml
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
# git-cliff configuration for DreamStack
|
||||
# https://git-cliff.org/docs/configuration
|
||||
#
|
||||
# Per-package changelogs:
|
||||
# git-cliff --include-path "compiler/ds-parser/**" -o compiler/ds-parser/CHANGELOG.md
|
||||
# git-cliff --include-path "engine/ds-stream/**" -o engine/ds-stream/CHANGELOG.md
|
||||
#
|
||||
# Full workspace changelog:
|
||||
# git-cliff -o CHANGELOG.md
|
||||
|
||||
[changelog]
|
||||
header = """
|
||||
# Changelog
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
"""
|
||||
body = """
|
||||
{% if version -%}
|
||||
## [{{ version | trim_start_matches(pat="v") }}] - {{ timestamp | date(format="%Y-%m-%d") }}
|
||||
{% else -%}
|
||||
## [Unreleased]
|
||||
{% endif -%}
|
||||
|
||||
{% for group, commits in commits | group_by(attribute="group") %}
|
||||
### {{ group | striptags | trim | upper_first }}
|
||||
{% for commit in commits %}
|
||||
- {% if commit.scope %}**{{ commit.scope }}:** {% endif %}\
|
||||
{% if commit.breaking %}[**BREAKING**] {% endif %}\
|
||||
{{ commit.message | upper_first }}
|
||||
{%- endfor %}
|
||||
{% endfor %}\n
|
||||
"""
|
||||
footer = """
|
||||
<!-- generated by git-cliff -->
|
||||
"""
|
||||
trim = true
|
||||
|
||||
[git]
|
||||
conventional_commits = true
|
||||
filter_unconventional = true
|
||||
split_commits = false
|
||||
commit_preprocessors = [
|
||||
# Truncate overly long commit messages to keep the changelog scannable
|
||||
{ pattern = "^(.{0,120}).*$", replace = "$1" },
|
||||
]
|
||||
commit_parsers = [
|
||||
{ message = "^feat", group = "<!-- 0 -->🚀 Features" },
|
||||
{ message = "^fix", group = "<!-- 1 -->🐛 Bug Fixes" },
|
||||
{ message = "^refactor", group = "<!-- 2 -->🔧 Refactoring" },
|
||||
{ message = "^doc", group = "<!-- 3 -->📚 Documentation" },
|
||||
{ message = "^perf", group = "<!-- 4 -->⚡ Performance" },
|
||||
{ message = "^improve", group = "<!-- 0 -->🚀 Features" },
|
||||
{ message = "^refine", group = "<!-- 2 -->🔧 Refactoring" },
|
||||
{ message = "^style", group = "<!-- 5 -->🎨 Styling" },
|
||||
{ message = "^test", group = "<!-- 6 -->🧪 Testing" },
|
||||
{ message = "^chore\\(release\\)", skip = true },
|
||||
{ message = "^chore\\(deps\\)", skip = true },
|
||||
{ message = "^chore|^ci", group = "<!-- 7 -->⚙️ Miscellaneous" },
|
||||
{ body = ".*security", group = "<!-- 8 -->🔒 Security" },
|
||||
]
|
||||
protect_breaking_commits = false
|
||||
filter_commits = false
|
||||
topo_order = false
|
||||
sort_commits = "oldest"
|
||||
tag_pattern = "v[0-9].*"
|
||||
11
compiler/ds-analyzer/CHANGELOG.md
Normal file
11
compiler/ds-analyzer/CHANGELOG.md
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
# Changelog
|
||||
|
||||
All notable changes to this package will be documented in this file.
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [0.1.0] - 2026-02-26
|
||||
|
||||
### 🚀 Features
|
||||
|
||||
- Initial release — Signal graph extraction, source/derived classification, topological sort, DOM binding analysis
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "ds-analyzer"
|
||||
version.workspace = true
|
||||
version = "0.1.0"
|
||||
edition.workspace = true
|
||||
|
||||
[dependencies]
|
||||
|
|
|
|||
11
compiler/ds-cli/CHANGELOG.md
Normal file
11
compiler/ds-cli/CHANGELOG.md
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
# Changelog
|
||||
|
||||
All notable changes to this package will be documented in this file.
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [0.1.0] - 2026-02-26
|
||||
|
||||
### 🚀 Features
|
||||
|
||||
- Initial release — CLI with build, dev, check, stream, init, add, convert commands
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "ds-cli"
|
||||
version.workspace = true
|
||||
version = "0.1.0"
|
||||
edition.workspace = true
|
||||
|
||||
[[bin]]
|
||||
|
|
|
|||
11
compiler/ds-codegen/CHANGELOG.md
Normal file
11
compiler/ds-codegen/CHANGELOG.md
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
# Changelog
|
||||
|
||||
All notable changes to this package will be documented in this file.
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [0.1.0] - 2026-02-26
|
||||
|
||||
### 🚀 Features
|
||||
|
||||
- Initial release — JavaScript emitter, reactive runtime, CSS design system, component codegen, streaming layer
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "ds-codegen"
|
||||
version.workspace = true
|
||||
version = "0.1.0"
|
||||
edition.workspace = true
|
||||
|
||||
[dependencies]
|
||||
|
|
|
|||
11
compiler/ds-incremental/CHANGELOG.md
Normal file
11
compiler/ds-incremental/CHANGELOG.md
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
# Changelog
|
||||
|
||||
All notable changes to this package will be documented in this file.
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [0.1.0] - 2026-02-26
|
||||
|
||||
### 🚀 Features
|
||||
|
||||
- Initial release — Incremental compilation support
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "ds-incremental"
|
||||
version.workspace = true
|
||||
version = "0.1.0"
|
||||
edition.workspace = true
|
||||
|
||||
[dependencies]
|
||||
|
|
|
|||
11
compiler/ds-layout/CHANGELOG.md
Normal file
11
compiler/ds-layout/CHANGELOG.md
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
# Changelog
|
||||
|
||||
All notable changes to this package will be documented in this file.
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [0.1.0] - 2026-02-26
|
||||
|
||||
### 🚀 Features
|
||||
|
||||
- Initial release — Cassowary constraint solver with eq/gte/lte/sum_eq/ratio constraints
|
||||
11
compiler/ds-parser/CHANGELOG.md
Normal file
11
compiler/ds-parser/CHANGELOG.md
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
# Changelog
|
||||
|
||||
All notable changes to this package will be documented in this file.
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [0.1.0] - 2026-02-26
|
||||
|
||||
### 🚀 Features
|
||||
|
||||
- Initial release — Lexer, recursive descent parser, AST types, operator precedence, string interpolation
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "ds-parser"
|
||||
version.workspace = true
|
||||
version = "0.1.0"
|
||||
edition.workspace = true
|
||||
|
||||
[dependencies]
|
||||
|
|
|
|||
11
compiler/ds-types/CHANGELOG.md
Normal file
11
compiler/ds-types/CHANGELOG.md
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
# Changelog
|
||||
|
||||
All notable changes to this package will be documented in this file.
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [0.1.0] - 2026-02-26
|
||||
|
||||
### 🚀 Features
|
||||
|
||||
- Initial release — Hindley-Milner type checker, Signal/Derived/Stream/Spring/View types, Elm-style errors
|
||||
11
engine/ds-physics/CHANGELOG.md
Normal file
11
engine/ds-physics/CHANGELOG.md
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
# Changelog
|
||||
|
||||
All notable changes to this package will be documented in this file.
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [0.1.0] - 2026-02-26
|
||||
|
||||
### 🚀 Features
|
||||
|
||||
- Initial release — Rapier2D WASM integration, scene container, reactive physics bodies
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "ds-physics"
|
||||
version.workspace = true
|
||||
version = "0.1.0"
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
|
||||
|
|
|
|||
11
engine/ds-stream-wasm/CHANGELOG.md
Normal file
11
engine/ds-stream-wasm/CHANGELOG.md
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
# Changelog
|
||||
|
||||
All notable changes to this package will be documented in this file.
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [0.1.0] - 2026-02-26
|
||||
|
||||
### 🚀 Features
|
||||
|
||||
- Initial release — Browser WASM codec for ds-stream protocol
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "ds-stream-wasm"
|
||||
version.workspace = true
|
||||
version = "0.1.0"
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
description = "WebAssembly codec for DreamStack bitstream protocol"
|
||||
|
|
|
|||
11
engine/ds-stream/CHANGELOG.md
Normal file
11
engine/ds-stream/CHANGELOG.md
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
# Changelog
|
||||
|
||||
All notable changes to this package will be documented in this file.
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [0.1.0] - 2026-02-26
|
||||
|
||||
### 🚀 Features
|
||||
|
||||
- Initial release — Binary streaming protocol, WebSocket relay, RLE/XOR codecs, peer mode, channel routing
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "ds-stream"
|
||||
version.workspace = true
|
||||
version = "0.1.0"
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
description = "Universal bitstream streaming — any input to any output"
|
||||
|
|
|
|||
356
scripts/release.sh
Executable file
356
scripts/release.sh
Executable file
|
|
@ -0,0 +1,356 @@
|
|||
#!/usr/bin/env bash
|
||||
#
|
||||
# DreamStack Release Script
|
||||
#
|
||||
# Reads .changeset/*.md files (YAML frontmatter with package bump types),
|
||||
# bumps per-package versions, regenerates changelogs, commits, and tags.
|
||||
#
|
||||
# Usage:
|
||||
# ./scripts/release.sh # apply changesets
|
||||
# ./scripts/release.sh --dry-run # preview without committing
|
||||
# ./scripts/release.sh --all <bump> # bump all packages (patch|minor|major)
|
||||
#
|
||||
set -euo pipefail
|
||||
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
CYAN='\033[0;36m'
|
||||
NC='\033[0m'
|
||||
|
||||
ROOT_DIR="$(cd "$(dirname "$0")/.." && pwd)"
|
||||
WORKSPACE_TOML="$ROOT_DIR/Cargo.toml"
|
||||
CHANGELOG="$ROOT_DIR/CHANGELOG.md"
|
||||
CHANGESET_DIR="$ROOT_DIR/.changeset"
|
||||
|
||||
DRY_RUN=false
|
||||
BUMP_ALL=""
|
||||
|
||||
# ── Package registry ─────────────────────────────────────────────────
|
||||
# name:path pairs for all workspace crates
|
||||
declare -A PKG_PATH=(
|
||||
[ds-parser]="compiler/ds-parser"
|
||||
[ds-analyzer]="compiler/ds-analyzer"
|
||||
[ds-codegen]="compiler/ds-codegen"
|
||||
[ds-layout]="compiler/ds-layout"
|
||||
[ds-types]="compiler/ds-types"
|
||||
[ds-incremental]="compiler/ds-incremental"
|
||||
[ds-cli]="compiler/ds-cli"
|
||||
[ds-physics]="engine/ds-physics"
|
||||
[ds-stream]="engine/ds-stream"
|
||||
[ds-stream-wasm]="engine/ds-stream-wasm"
|
||||
)
|
||||
|
||||
# ── Parse flags ──────────────────────────────────────────────────────
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--dry-run) DRY_RUN=true; shift ;;
|
||||
--all)
|
||||
shift
|
||||
if [[ -z "${1:-}" ]]; then
|
||||
echo -e "${RED}Error:${NC} --all requires a bump type (patch|minor|major)"
|
||||
exit 1
|
||||
fi
|
||||
BUMP_ALL="$1"; shift
|
||||
;;
|
||||
*) echo -e "${RED}Error:${NC} Unknown argument: $1"; exit 1 ;;
|
||||
esac
|
||||
done
|
||||
|
||||
# ── Helpers ──────────────────────────────────────────────────────────
|
||||
|
||||
get_pkg_version() {
|
||||
local cargo_toml="$1/Cargo.toml"
|
||||
grep '^version' "$cargo_toml" | head -1 | sed 's/.*"\(.*\)".*/\1/'
|
||||
}
|
||||
|
||||
bump_version() {
|
||||
local current="$1" bump="$2"
|
||||
local major minor patch
|
||||
IFS='.' read -r major minor patch <<< "$current"
|
||||
case "$bump" in
|
||||
major) echo "$((major + 1)).0.0" ;;
|
||||
minor) echo "$major.$((minor + 1)).0" ;;
|
||||
patch) echo "$major.$minor.$((patch + 1))" ;;
|
||||
*) echo "" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
set_pkg_version() {
|
||||
local cargo_toml="$1/Cargo.toml"
|
||||
local old_ver="$2" new_ver="$3"
|
||||
sed -i "0,/^version = \"$old_ver\"/s//version = \"$new_ver\"/" "$cargo_toml"
|
||||
}
|
||||
|
||||
# ── Parse changesets ─────────────────────────────────────────────────
|
||||
# Reads YAML frontmatter from .changeset/*.md files
|
||||
# Format:
|
||||
# ---
|
||||
# "ds-parser": minor
|
||||
# "ds-codegen": patch
|
||||
# ---
|
||||
# Description of the change.
|
||||
|
||||
declare -A BUMPS # package -> highest bump (major > minor > patch)
|
||||
declare -a DESCRIPTIONS # changeset descriptions
|
||||
|
||||
BUMP_RANK_patch=1
|
||||
BUMP_RANK_minor=2
|
||||
BUMP_RANK_major=3
|
||||
|
||||
higher_bump() {
|
||||
local current="$1" candidate="$2"
|
||||
if [[ -z "$current" ]]; then echo "$candidate"; return; fi
|
||||
local cur_rank="BUMP_RANK_$current"
|
||||
local cand_rank="BUMP_RANK_$candidate"
|
||||
if [[ "${!cand_rank}" -gt "${!cur_rank}" ]]; then
|
||||
echo "$candidate"
|
||||
else
|
||||
echo "$current"
|
||||
fi
|
||||
}
|
||||
|
||||
parse_changesets() {
|
||||
shopt -s nullglob
|
||||
local files=("$CHANGESET_DIR"/*.md)
|
||||
shopt -u nullglob
|
||||
|
||||
for f in "${files[@]}"; do
|
||||
[[ "$(basename "$f")" == "README.md" ]] && continue
|
||||
|
||||
local in_frontmatter=false
|
||||
local description=""
|
||||
|
||||
while IFS= read -r line; do
|
||||
if [[ "$line" == "---" ]]; then
|
||||
if [[ "$in_frontmatter" == false ]]; then
|
||||
in_frontmatter=true
|
||||
continue
|
||||
else
|
||||
in_frontmatter=false
|
||||
continue
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ "$in_frontmatter" == true ]]; then
|
||||
# Parse: "pkg-name": bump_type
|
||||
local pkg bump
|
||||
pkg=$(echo "$line" | sed -n 's/^"\([^"]*\)":.*/\1/p')
|
||||
bump=$(echo "$line" | sed -n 's/^"[^"]*": *\(.*\)/\1/p' | tr -d ' ')
|
||||
if [[ -n "$pkg" && -n "$bump" ]]; then
|
||||
BUMPS[$pkg]=$(higher_bump "${BUMPS[$pkg]:-}" "$bump")
|
||||
fi
|
||||
else
|
||||
if [[ -n "$line" ]]; then
|
||||
description+="$line"$'\n'
|
||||
fi
|
||||
fi
|
||||
done < "$f"
|
||||
|
||||
if [[ -n "$description" ]]; then
|
||||
DESCRIPTIONS+=("$description")
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
# ── Collect bumps ────────────────────────────────────────────────────
|
||||
|
||||
DESCRIPTIONS=()
|
||||
|
||||
if [[ -n "$BUMP_ALL" ]]; then
|
||||
for pkg in "${!PKG_PATH[@]}"; do
|
||||
BUMPS[$pkg]="$BUMP_ALL"
|
||||
done
|
||||
echo -e "${CYAN}Bumping all packages:${NC} $BUMP_ALL"
|
||||
else
|
||||
parse_changesets
|
||||
fi
|
||||
|
||||
if [[ ${#BUMPS[@]} -eq 0 ]]; then
|
||||
echo -e "${YELLOW}No changesets found.${NC} Nothing to release."
|
||||
echo "Add changesets in .changeset/ or use --all <bump>"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# ── Preview ──────────────────────────────────────────────────────────
|
||||
|
||||
echo -e "${CYAN}DreamStack Release${NC}"
|
||||
echo ""
|
||||
|
||||
for pkg in $(echo "${!BUMPS[@]}" | tr ' ' '\n' | sort); do
|
||||
local_path="${PKG_PATH[$pkg]:-}"
|
||||
if [[ -z "$local_path" ]]; then
|
||||
echo -e " ${YELLOW}⚠${NC} Unknown package: $pkg (skipping)"
|
||||
continue
|
||||
fi
|
||||
|
||||
current=$(get_pkg_version "$ROOT_DIR/$local_path")
|
||||
new=$(bump_version "$current" "${BUMPS[$pkg]}")
|
||||
echo -e " ${GREEN}$pkg${NC} $current → $new (${BUMPS[$pkg]})"
|
||||
done
|
||||
|
||||
echo ""
|
||||
|
||||
if [[ ${#DESCRIPTIONS[@]} -gt 0 ]]; then
|
||||
echo -e "${CYAN}Changeset descriptions:${NC}"
|
||||
for desc in "${DESCRIPTIONS[@]}"; do
|
||||
echo " - $(echo "$desc" | head -1)"
|
||||
done
|
||||
echo ""
|
||||
fi
|
||||
|
||||
if [[ "$DRY_RUN" == true ]]; then
|
||||
echo -e "${YELLOW}[DRY RUN]${NC} No changes made."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# ── Check prerequisites ─────────────────────────────────────────────
|
||||
|
||||
if ! command -v git-cliff &>/dev/null; then
|
||||
echo -e "${RED}Error:${NC} git-cliff not found. Install with: cargo install git-cliff"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ -n "$(git -C "$ROOT_DIR" status --porcelain)" ]]; then
|
||||
echo -e "${RED}Error:${NC} Working directory is not clean. Commit or stash changes first."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# ── Step 1: Bump per-package versions ────────────────────────────────
|
||||
|
||||
echo -e "${GREEN}→${NC} Bumping package versions..."
|
||||
|
||||
HIGHEST_BUMP=""
|
||||
for pkg in "${!BUMPS[@]}"; do
|
||||
local_path="${PKG_PATH[$pkg]:-}"
|
||||
[[ -z "$local_path" ]] && continue
|
||||
|
||||
pkg_dir="$ROOT_DIR/$local_path"
|
||||
current=$(get_pkg_version "$pkg_dir")
|
||||
new=$(bump_version "$current" "${BUMPS[$pkg]}")
|
||||
|
||||
if [[ -z "$new" ]]; then
|
||||
echo -e " ${RED}✗${NC} $pkg — invalid bump '${BUMPS[$pkg]}'"
|
||||
continue
|
||||
fi
|
||||
|
||||
set_pkg_version "$pkg_dir" "$current" "$new"
|
||||
echo -e " ${GREEN}✓${NC} $pkg $current → $new"
|
||||
|
||||
HIGHEST_BUMP=$(higher_bump "$HIGHEST_BUMP" "${BUMPS[$pkg]}")
|
||||
done
|
||||
|
||||
# ── Step 2: Bump workspace version ──────────────────────────────────
|
||||
|
||||
WORKSPACE_VERSION=$(grep -A2 '^\[workspace\.package\]' "$WORKSPACE_TOML" \
|
||||
| grep '^version' | sed 's/version = "\(.*\)"/\1/')
|
||||
NEW_WORKSPACE=$(bump_version "$WORKSPACE_VERSION" "$HIGHEST_BUMP")
|
||||
|
||||
if [[ -n "$NEW_WORKSPACE" ]]; then
|
||||
sed -i "s/^version = \"$WORKSPACE_VERSION\"/version = \"$NEW_WORKSPACE\"/" "$WORKSPACE_TOML"
|
||||
echo -e " ${GREEN}✓${NC} workspace $WORKSPACE_VERSION → $NEW_WORKSPACE"
|
||||
fi
|
||||
|
||||
VERSION_TAG="v${NEW_WORKSPACE:-$WORKSPACE_VERSION}"
|
||||
|
||||
# ── Step 3: Generate root changelog ─────────────────────────────────
|
||||
|
||||
echo -e "${GREEN}→${NC} Generating root changelog..."
|
||||
git-cliff --config "$ROOT_DIR/cliff.toml" --tag "$VERSION_TAG" --output "$CHANGELOG"
|
||||
|
||||
# ── Step 4: Update per-package changelogs from changesets ─────────────
|
||||
# Writes changeset descriptions into each affected crate's CHANGELOG.md
|
||||
# under the new version heading. This avoids git-cliff's --include-path
|
||||
# limitation where tag boundaries are lost if the tag commit doesn't
|
||||
# touch the crate's files.
|
||||
|
||||
echo -e "${GREEN}→${NC} Updating per-package changelogs..."
|
||||
updated=0
|
||||
|
||||
for pkg in "${!BUMPS[@]}"; do
|
||||
local_path="${PKG_PATH[$pkg]:-}"
|
||||
[[ -z "$local_path" ]] && continue
|
||||
|
||||
pkg_dir="$ROOT_DIR/$local_path"
|
||||
pkg_changelog="$pkg_dir/CHANGELOG.md"
|
||||
new_ver=$(bump_version "$(get_pkg_version "$pkg_dir")" "${BUMPS[$pkg]}")
|
||||
today=$(date +%Y-%m-%d)
|
||||
|
||||
# Collect descriptions from changesets that mention this package
|
||||
pkg_entries=""
|
||||
for desc in "${DESCRIPTIONS[@]}"; do
|
||||
pkg_entries+="- $desc"
|
||||
done
|
||||
|
||||
# If --all with no changesets, add a generic entry
|
||||
if [[ -z "$pkg_entries" && -n "$BUMP_ALL" ]]; then
|
||||
pkg_entries="- Version bump"$'\n'
|
||||
fi
|
||||
|
||||
# Build the new version section
|
||||
version_section="## [$new_ver] - $today"$'\n'$'\n'
|
||||
if [[ -n "$pkg_entries" ]]; then
|
||||
version_section+="### 🚀 Changes"$'\n'$'\n'
|
||||
version_section+="$pkg_entries"$'\n'
|
||||
fi
|
||||
|
||||
if [[ -f "$pkg_changelog" ]]; then
|
||||
# Insert new version section after "## [Unreleased]" line
|
||||
TEMP_FILE=$(mktemp)
|
||||
awk -v section="$version_section" '
|
||||
/^## \[Unreleased\]/ {
|
||||
print
|
||||
print ""
|
||||
printf "%s", section
|
||||
next
|
||||
}
|
||||
{ print }
|
||||
' "$pkg_changelog" > "$TEMP_FILE"
|
||||
mv "$TEMP_FILE" "$pkg_changelog"
|
||||
else
|
||||
# Create changelog from scratch
|
||||
cat > "$pkg_changelog" << EOF
|
||||
# Changelog
|
||||
|
||||
All notable changes to this package will be documented in this file.
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
$version_section
|
||||
EOF
|
||||
fi
|
||||
|
||||
updated=$((updated + 1))
|
||||
echo -e " ${GREEN}✓${NC} $pkg → $new_ver"
|
||||
done
|
||||
echo -e " Updated ${GREEN}$updated${NC} package changelogs"
|
||||
|
||||
# ── Step 5: Clean up changeset files ────────────────────────────────
|
||||
|
||||
shopt -s nullglob
|
||||
changeset_files=("$CHANGESET_DIR"/*.md)
|
||||
shopt -u nullglob
|
||||
cleaned=0
|
||||
|
||||
for f in "${changeset_files[@]}"; do
|
||||
[[ "$(basename "$f")" == "README.md" ]] && continue
|
||||
rm "$f"
|
||||
cleaned=$((cleaned + 1))
|
||||
done
|
||||
|
||||
if [[ "$cleaned" -gt 0 ]]; then
|
||||
echo -e "${GREEN}→${NC} Cleaned up $cleaned changeset files."
|
||||
fi
|
||||
|
||||
# ── Step 6: Commit and tag ──────────────────────────────────────────
|
||||
|
||||
echo -e "${GREEN}→${NC} Committing release..."
|
||||
git -C "$ROOT_DIR" add -A
|
||||
git -C "$ROOT_DIR" commit -m "chore(release): $VERSION_TAG"
|
||||
git -C "$ROOT_DIR" tag -a "$VERSION_TAG" -m "Release $VERSION_TAG"
|
||||
|
||||
echo ""
|
||||
echo -e "${GREEN}✓ Released $VERSION_TAG${NC}"
|
||||
echo ""
|
||||
echo -e " Push with: ${CYAN}git push && git push --tags${NC}"
|
||||
Loading…
Add table
Reference in a new issue