1+ name : Release Management
2+
3+ # Comprehensive release workflow with multi-platform builds
4+ permissions :
5+ contents : write
6+ packages : read
7+
8+ on :
9+ push :
10+ tags :
11+ - ' v*.*.*'
12+ workflow_dispatch :
13+ inputs :
14+ tag :
15+ description : ' Release tag (e.g., v1.0.0)'
16+ required : true
17+ type : string
18+ prerelease :
19+ description : ' Mark as prerelease'
20+ required : false
21+ default : false
22+ type : boolean
23+
24+ concurrency :
25+ group : release-${{ github.ref }}
26+ cancel-in-progress : false # Never cancel releases
27+
28+ env :
29+ CARGO_TERM_COLOR : always
30+
31+ jobs :
32+ # Create the GitHub release with enhanced notes
33+ create-release :
34+ name : Create GitHub Release
35+ runs-on : ubuntu-latest
36+ outputs :
37+ tag_name : ${{ steps.tag.outputs.tag }}
38+ is_prerelease : ${{ steps.release-type.outputs.prerelease }}
39+ steps :
40+ - name : Checkout
41+ uses : actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955
42+ with :
43+ fetch-depth : 0
44+
45+ - name : Determine tag
46+ id : tag
47+ run : |
48+ if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
49+ echo "tag=${{ inputs.tag }}" >> $GITHUB_OUTPUT
50+ else
51+ echo "tag=${{ github.ref_name }}" >> $GITHUB_OUTPUT
52+ fi
53+
54+ - name : Determine release type
55+ id : release-type
56+ run : |
57+ TAG="${{ steps.tag.outputs.tag }}"
58+ if [[ "$TAG" == *"-"* ]] || [[ "${{ inputs.prerelease }}" == "true" ]]; then
59+ echo "prerelease=true" >> $GITHUB_OUTPUT
60+ echo "π§ Prerelease detected"
61+ else
62+ echo "prerelease=false" >> $GITHUB_OUTPUT
63+ echo "π Stable release detected"
64+ fi
65+
66+ - name : Install git-cliff
67+ run : cargo install git-cliff
68+
69+ - name : Generate release notes
70+ run : |
71+ TAG="${{ steps.tag.outputs.tag }}"
72+
73+ # Generate base changelog
74+ git cliff --tag "$TAG" --strip header > base_notes.md
75+
76+ # Create enhanced release notes
77+ cat > enhanced_notes.md << EOF
78+ ## Code Guardian $TAG π‘οΈ
79+
80+ $(cat base_notes.md)
81+
82+ ### π¦ Installation
83+
84+ #### Download Binary
85+ Download the appropriate binary for your platform from the assets below:
86+ - **Linux (x86_64)**: \`code-guardian-x86_64-unknown-linux-gnu.tar.gz\`
87+ - **macOS (Intel)**: \`code-guardian-x86_64-apple-darwin.tar.gz\`
88+ - **macOS (Apple Silicon)**: \`code-guardian-aarch64-apple-darwin.tar.gz\`
89+ - **Windows**: \`code-guardian-x86_64-pc-windows-msvc.zip\`
90+
91+ #### Using Cargo
92+ \`\`\`bash
93+ cargo install --git https://github.com/d-oit/code-guardian --tag $TAG
94+ \`\`\`
95+
96+ ### π Quick Start
97+ \`\`\`bash
98+ # Basic scan
99+ ./code_guardian_cli scan /path/to/project
100+
101+ # With custom config
102+ ./code_guardian_cli scan /path/to/project --config config.toml
103+
104+ # Generate HTML report
105+ ./code_guardian_cli scan /path/to/project --format html --output report.html
106+ \`\`\`
107+
108+ ### π Links
109+ - [Documentation](https://github.com/d-oit/code-guardian/tree/main/docs)
110+ - [Configuration Guide](https://github.com/d-oit/code-guardian/blob/main/docs/configuration/schema.md)
111+ - [Tutorials](https://github.com/d-oit/code-guardian/tree/main/docs/tutorials)
112+
113+ EOF
114+
115+ # If no changelog content, add default message
116+ if ! grep -q "###\|##\|feat\|fix\|BREAKING" enhanced_notes.md; then
117+ cat >> enhanced_notes.md << EOF
118+
119+ ### Changes
120+ - Version bump to $TAG
121+ - See commit history for detailed changes
122+ EOF
123+ fi
124+
125+ echo "RELEASE_NOTES<<EOF" >> $GITHUB_ENV
126+ cat enhanced_notes.md >> $GITHUB_ENV
127+ echo "EOF" >> $GITHUB_ENV
128+
129+ - name : Create or update release
130+ run : |
131+ TAG="${{ steps.tag.outputs.tag }}"
132+ PRERELEASE="${{ steps.release-type.outputs.prerelease }}"
133+
134+ # Check if release exists
135+ if gh release view "$TAG" >/dev/null 2>&1; then
136+ echo "π Release $TAG already exists, updating..."
137+ gh release edit "$TAG" --notes "$RELEASE_NOTES"
138+ else
139+ echo "π Creating new release $TAG..."
140+ if [[ "$PRERELEASE" == "true" ]]; then
141+ gh release create "$TAG" \
142+ --title "Code Guardian $TAG" \
143+ --notes "$RELEASE_NOTES" \
144+ --prerelease
145+ else
146+ gh release create "$TAG" \
147+ --title "Code Guardian $TAG" \
148+ --notes "$RELEASE_NOTES"
149+ fi
150+ fi
151+ env :
152+ GITHUB_TOKEN : ${{ secrets.GITHUB_TOKEN }}
153+
154+ # Build release binaries for all platforms
155+ build-release :
156+ name : Build Release (${{ matrix.target }})
157+ needs : create-release
158+ runs-on : ${{ matrix.os }}
159+ strategy :
160+ fail-fast : false
161+ matrix :
162+ include :
163+ - os : ubuntu-latest
164+ target : x86_64-unknown-linux-gnu
165+ binary : code_guardian_cli
166+ archive : tar.gz
167+ - os : windows-latest
168+ target : x86_64-pc-windows-msvc
169+ binary : code_guardian_cli.exe
170+ archive : zip
171+ - os : macos-latest
172+ target : x86_64-apple-darwin
173+ binary : code_guardian_cli
174+ archive : tar.gz
175+ - os : macos-latest
176+ target : aarch64-apple-darwin
177+ binary : code_guardian_cli
178+ archive : tar.gz
179+
180+ steps :
181+ - name : Checkout
182+ uses : actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955
183+
184+ - name : Setup Rust
185+ uses : ./.github/actions/setup-rust
186+ with :
187+ toolchain : stable
188+ targets : ${{ matrix.target }}
189+
190+ - name : Setup Cache
191+ uses : ./.github/actions/setup-cache
192+ with :
193+ cache-key-suffix : release-${{ matrix.target }}
194+
195+ - name : Build release binary
196+ run : |
197+ cargo build --release --target ${{ matrix.target }} --locked
198+ echo "β
Built binary for ${{ matrix.target }}"
199+
200+ - name : Run tests (native targets only)
201+ if : matrix.target == 'x86_64-unknown-linux-gnu' || matrix.target == 'x86_64-pc-windows-msvc' || (matrix.target == 'x86_64-apple-darwin' && runner.arch == 'X64')
202+ run : cargo test --release --target ${{ matrix.target }}
203+
204+ - name : Create release archive
205+ shell : bash
206+ run : |
207+ TAG="${{ needs.create-release.outputs.tag_name }}"
208+ TARGET="${{ matrix.target }}"
209+ BINARY="${{ matrix.binary }}"
210+
211+ # Create staging directory
212+ mkdir -p staging
213+
214+ # Copy binary
215+ cp "target/$TARGET/release/$BINARY" staging/
216+
217+ # Copy additional files
218+ cp README.md staging/
219+ cp LICENSE staging/
220+ cp -r docs/ staging/ 2>/dev/null || echo "No docs directory"
221+ cp -r examples/ staging/ 2>/dev/null || echo "No examples directory"
222+
223+ # Create archive
224+ cd staging
225+ if [[ "${{ matrix.archive }}" == "zip" ]]; then
226+ ARCHIVE_NAME="code-guardian-$TARGET.zip"
227+ 7z a "../$ARCHIVE_NAME" *
228+ else
229+ ARCHIVE_NAME="code-guardian-$TARGET.tar.gz"
230+ tar czf "../$ARCHIVE_NAME" *
231+ fi
232+ cd ..
233+
234+ echo "ARCHIVE_NAME=$ARCHIVE_NAME" >> $GITHUB_ENV
235+ echo "π¦ Created archive: $ARCHIVE_NAME"
236+
237+ - name : Upload release asset
238+ run : |
239+ TAG="${{ needs.create-release.outputs.tag_name }}"
240+ gh release upload "$TAG" "$ARCHIVE_NAME" --clobber
241+ echo "β¬οΈ Uploaded $ARCHIVE_NAME to release $TAG"
242+ env :
243+ GITHUB_TOKEN : ${{ secrets.GITHUB_TOKEN }}
244+
245+ # Post-release tasks
246+ post-release :
247+ name : Post-Release Tasks
248+ needs : [create-release, build-release]
249+ runs-on : ubuntu-latest
250+ if : always() && needs.create-release.result == 'success'
251+ steps :
252+ - name : Release summary
253+ run : |
254+ TAG="${{ needs.create-release.outputs.tag_name }}"
255+ PRERELEASE="${{ needs.create-release.outputs.is_prerelease }}"
256+
257+ echo "## π Release Summary" >> $GITHUB_STEP_SUMMARY
258+ echo "" >> $GITHUB_STEP_SUMMARY
259+ echo "**Tag:** $TAG" >> $GITHUB_STEP_SUMMARY
260+ echo "**Type:** $([ "$PRERELEASE" = "true" ] && echo "Prerelease" || echo "Stable Release")" >> $GITHUB_STEP_SUMMARY
261+ echo "**Builds:** ${{ strategy.job-total }} platforms" >> $GITHUB_STEP_SUMMARY
262+ echo "" >> $GITHUB_STEP_SUMMARY
263+ echo "### Assets Built" >> $GITHUB_STEP_SUMMARY
264+ echo "- Linux (x86_64)" >> $GITHUB_STEP_SUMMARY
265+ echo "- Windows (x86_64)" >> $GITHUB_STEP_SUMMARY
266+ echo "- macOS Intel (x86_64)" >> $GITHUB_STEP_SUMMARY
267+ echo "- macOS Apple Silicon (aarch64)" >> $GITHUB_STEP_SUMMARY
268+ echo "" >> $GITHUB_STEP_SUMMARY
269+ echo "π [View Release](https://github.com/${{ github.repository }}/releases/tag/$TAG)" >> $GITHUB_STEP_SUMMARY
0 commit comments