1+ name : Release
2+
3+ on :
4+ push :
5+ tags : ["v*"]
6+
7+ env :
8+ CARGO_TERM_COLOR : always
9+
10+ jobs :
11+ # Create GitHub release and publish to crates.io when tags are pushed
12+ release :
13+ name : Release
14+ runs-on : ubuntu-latest
15+ permissions :
16+ contents : write
17+ packages : write
18+ steps :
19+ - name : Checkout sources
20+ 21+ with :
22+ fetch-depth : 0
23+
24+ - name : Install stable toolchain
25+ uses : dtolnay/rust-toolchain@stable
26+ with :
27+ components : clippy, rustfmt
28+
29+ - name : Install Dependencies
30+ run : |
31+ sudo apt-get update
32+ sudo apt-get install -y \
33+ pkg-config \
34+ libx11-dev \
35+ libasound2-dev \
36+ libudev-dev \
37+ libxcb-render0-dev \
38+ libxcb-shape0-dev \
39+ libxcb-xfixes0-dev \
40+ libwayland-dev \
41+ libxkbcommon-dev \
42+ libvulkan-dev
43+
44+ - name : Cache cargo registry
45+ uses : actions/cache@v4
46+ with :
47+ path : |
48+ ~/.cargo/bin/
49+ ~/.cargo/registry/index/
50+ ~/.cargo/registry/cache/
51+ ~/.cargo/git/db/
52+ key : ${{ runner.os }}-cargo-release-${{ hashFiles('**/Cargo.toml') }}
53+ restore-keys : |
54+ ${{ runner.os }}-cargo-release-
55+
56+ - name : Cache cargo build
57+ uses : actions/cache@v4
58+ with :
59+ path : target/
60+ key : ${{ runner.os }}-cargo-release-build-${{ hashFiles('**/Cargo.toml') }}
61+ restore-keys : |
62+ ${{ runner.os }}-cargo-release-build-
63+
64+ - name : Extract version from tag
65+ id : version
66+ run : echo "VERSION=${GITHUB_REF#refs/tags/v}" >> $GITHUB_OUTPUT
67+
68+ - name : Verify version matches Cargo.toml
69+ run : |
70+ CARGO_VERSION=$(grep '^version = ' Cargo.toml | sed 's/version = "//' | sed 's/"//g')
71+ if [ "$CARGO_VERSION" != "${{ steps.version.outputs.VERSION }}" ]; then
72+ echo "Version mismatch: tag v${{ steps.version.outputs.VERSION }} vs Cargo.toml $CARGO_VERSION"
73+ exit 1
74+ fi
75+ echo "✅ Version verified: $CARGO_VERSION"
76+
77+ - name : Run tests before release
78+ run : cargo test --all-features
79+
80+ - name : Run clippy before release
81+ run : cargo clippy --all-features -- -D warnings
82+
83+ - name : Check formatting before release
84+ run : cargo fmt --all -- --check
85+
86+ - name : Check if this is a pre-release
87+ id : prerelease_check
88+ run : |
89+ VERSION="${{ steps.version.outputs.VERSION }}"
90+ if [[ "$VERSION" =~ (alpha|beta|rc) ]]; then
91+ echo "prerelease=true" >> $GITHUB_OUTPUT
92+ else
93+ echo "prerelease=false" >> $GITHUB_OUTPUT
94+ fi
95+
96+ - name : Generate release notes
97+ id : release_notes
98+ run : |
99+ # Get the previous tag
100+ PREV_TAG=$(git describe --tags --abbrev=0 HEAD^ 2>/dev/null || echo "")
101+
102+ # Generate changelog from commits
103+ if [ -n "$PREV_TAG" ]; then
104+ echo "## 🚀 bevy_mqtt v${{ steps.version.outputs.VERSION }}" > release_notes.md
105+ echo "" >> release_notes.md
106+
107+ # Get commits since last tag and categorize them
108+ COMMITS=$(git log ${PREV_TAG}..HEAD --oneline --no-merges)
109+
110+ # Check for different types of changes
111+ FEATURES=$(echo "$COMMITS" | grep -E "(feat|✨)" || true)
112+ FIXES=$(echo "$COMMITS" | grep -E "(fix|🐛)" || true)
113+ DOCS=$(echo "$COMMITS" | grep -E "(docs|📝)" || true)
114+ CI=$(echo "$COMMITS" | grep -E "(ci|🚀|⬆️)" || true)
115+ REFACTOR=$(echo "$COMMITS" | grep -E "(refactor|♻️)" || true)
116+ SECURITY=$(echo "$COMMITS" | grep -E "(security|🔒|🛡️)" || true)
117+ PERF=$(echo "$COMMITS" | grep -E "(perf|⚡)" || true)
118+
119+ echo "### What's Changed" >> release_notes.md
120+ echo "" >> release_notes.md
121+
122+ if [ -n "$FEATURES" ]; then
123+ echo "#### ✨ New Features" >> release_notes.md
124+ echo "$FEATURES" | sed 's/^[a-f0-9]* /- /' >> release_notes.md
125+ echo "" >> release_notes.md
126+ fi
127+
128+ if [ -n "$SECURITY" ]; then
129+ echo "#### 🔒 Security Improvements" >> release_notes.md
130+ echo "$SECURITY" | sed 's/^[a-f0-9]* /- /' >> release_notes.md
131+ echo "" >> release_notes.md
132+ fi
133+
134+ if [ -n "$PERF" ]; then
135+ echo "#### ⚡ Performance Improvements" >> release_notes.md
136+ echo "$PERF" | sed 's/^[a-f0-9]* /- /' >> release_notes.md
137+ echo "" >> release_notes.md
138+ fi
139+
140+ if [ -n "$FIXES" ]; then
141+ echo "#### 🐛 Bug Fixes" >> release_notes.md
142+ echo "$FIXES" | sed 's/^[a-f0-9]* /- /' >> release_notes.md
143+ echo "" >> release_notes.md
144+ fi
145+
146+ if [ -n "$DOCS" ]; then
147+ echo "#### 📝 Documentation" >> release_notes.md
148+ echo "$DOCS" | sed 's/^[a-f0-9]* /- /' >> release_notes.md
149+ echo "" >> release_notes.md
150+ fi
151+
152+ if [ -n "$CI" ]; then
153+ echo "#### 🚀 CI/CD Improvements" >> release_notes.md
154+ echo "$CI" | sed 's/^[a-f0-9]* /- /' >> release_notes.md
155+ echo "" >> release_notes.md
156+ fi
157+
158+ if [ -n "$REFACTOR" ]; then
159+ echo "#### ♻️ Code Improvements" >> release_notes.md
160+ echo "$REFACTOR" | sed 's/^[a-f0-9]* /- /' >> release_notes.md
161+ echo "" >> release_notes.md
162+ fi
163+
164+ # Add remaining commits that don't match categories
165+ OTHER=$(echo "$COMMITS" | grep -vE "(feat|fix|docs|ci|refactor|security|perf|✨|🐛|📝|🚀|♻️|🔒|🛡️|⚡|⬆️)" || true)
166+ if [ -n "$OTHER" ]; then
167+ echo "#### 🔧 Other Changes" >> release_notes.md
168+ echo "$OTHER" | sed 's/^[a-f0-9]* /- /' >> release_notes.md
169+ echo "" >> release_notes.md
170+ fi
171+
172+ else
173+ # Fallback for first release
174+ cat > release_notes.md << 'EOF'
175+ ## 🚀 bevy_mqtt v${{ steps.version.outputs.VERSION }}
176+
177+ ### What's New
178+ This is the initial release or a release without a previous tag for comparison.
179+
180+ ### Key Features
181+ - 🔌 **Easy Integration** - Simple plugin architecture for Bevy ECS
182+ - 🔒 **Security First** - Regex injection protection and robust error handling
183+ - ⚡ **High Performance** - Optimized message dispatch with memory reuse patterns
184+ - 🌐 **Multiple Transports** - Support for TCP and WebSocket connections
185+ - 📦 **Message Caching** - Built-in packet caching with configurable capacity limits
186+ EOF
187+ fi
188+
189+ # Add installation and footer
190+ cat >> release_notes.md << EOF
191+
192+ ### 📦 Installation
193+ \`\`\`toml
194+ [dependencies]
195+ bevy_mqtt = "${{ steps.version.outputs.VERSION }}"
196+ \`\`\`
197+
198+ ### 🔗 Full Changelog
199+ **Full Changelog**: https://github.com/foxzool/bevy_mqtt/compare/${PREV_TAG}...v${{ steps.version.outputs.VERSION }}
200+
201+ ---
202+ *Built with ❤️ using Bevy ECS*
203+ EOF
204+
205+ - name : Create GitHub Release
206+ 207+ with :
208+ tag_name : v${{ steps.version.outputs.VERSION }}
209+ name : bevy_mqtt v${{ steps.version.outputs.VERSION }}
210+ body_path : release_notes.md
211+ draft : false
212+ prerelease : ${{ steps.prerelease_check.outputs.prerelease }}
213+ files : |
214+ target/release/bevy_mqtt-*.tar.gz
215+ env :
216+ GITHUB_TOKEN : ${{ secrets.GITHUB_TOKEN }}
217+
218+ - name : Clean up generated files before publish
219+ run : rm -f release_notes.md
220+
221+ - name : Build release artifacts
222+ run : cargo build --release
223+
224+ - name : Publish to crates.io
225+ run : cargo publish --token ${{ secrets.CARGO_REGISTRY_TOKEN }}
226+ env :
227+ CARGO_REGISTRY_TOKEN : ${{ secrets.CARGO_REGISTRY_TOKEN }}
228+
229+ - name : Wait for crates.io index (with timeout)
230+ run : |
231+ echo "⏳ Waiting for crates.io to index the new version..."
232+ timeout 300 bash -c 'until cargo search bevy_mqtt --limit 1 | grep -q "${{ steps.version.outputs.VERSION }}"; do sleep 10; done' || echo "⚠️ Timeout waiting for crates.io indexing, but release should still be successful"
0 commit comments