1+ name : Beta Release (Thursday)
2+
3+ on :
4+ schedule :
5+ # Thursday at 2 AM UTC - consolidate week's alpha changes into beta
6+ - cron : ' 0 2 * * 4'
7+ workflow_dispatch :
8+ inputs :
9+ dry_run :
10+ description : ' Dry run (skip PyPI publish)'
11+ required : false
12+ default : ' false'
13+ type : boolean
14+ force_build :
15+ description : ' Force build even if no changes'
16+ required : false
17+ default : ' false'
18+ type : boolean
19+
20+ jobs :
21+ check-changes :
22+ runs-on : ubuntu-latest
23+ outputs :
24+ has_changes : ${{ steps.changes.outputs.has_changes }}
25+ commit_count : ${{ steps.changes.outputs.commit_count }}
26+ last_beta : ${{ steps.changes.outputs.last_beta }}
27+ steps :
28+ - uses : actions/checkout@v4
29+ with :
30+ fetch-depth : 0
31+ ref : dev
32+
33+ - name : Check for changes since last beta release
34+ id : changes
35+ run : |
36+ # Get last beta release tag
37+ LAST_BETA=$(git tag -l "*b*" --sort=-version:refname | head -n1)
38+
39+ if [ -z "$LAST_BETA" ]; then
40+ echo "No previous beta release found, checking last week"
41+ SINCE="1 week ago"
42+ COMMIT_COUNT=$(git rev-list --count --since="$SINCE" dev)
43+ else
44+ echo "Last beta release: $LAST_BETA"
45+ COMMIT_COUNT=$(git rev-list --count ${LAST_BETA}..dev)
46+ fi
47+
48+ echo "Commits since last beta: $COMMIT_COUNT"
49+ echo "commit_count=$COMMIT_COUNT" >> $GITHUB_OUTPUT
50+ echo "last_beta=$LAST_BETA" >> $GITHUB_OUTPUT
51+
52+ if [ "$COMMIT_COUNT" -gt 0 ] || [ "${{ github.event.inputs.force_build }}" = "true" ]; then
53+ echo "has_changes=true" >> $GITHUB_OUTPUT
54+ echo "✅ Changes detected, proceeding with beta build"
55+ else
56+ echo "has_changes=false" >> $GITHUB_OUTPUT
57+ echo "ℹ️ No changes since last beta, skipping build"
58+ fi
59+
60+ beta-release :
61+ needs : check-changes
62+ if : needs.check-changes.outputs.has_changes == 'true'
63+ runs-on : ubuntu-latest
64+ outputs :
65+ beta_version : ${{ steps.version.outputs.beta_version }}
66+ steps :
67+ - uses : actions/checkout@v4
68+ with :
69+ fetch-depth : 0
70+ ref : dev
71+ token : ${{ secrets.GITHUB_TOKEN }}
72+
73+ - name : Set up Python
74+ uses : actions/setup-python@v5
75+ with :
76+ python-version : ' 3.11'
77+
78+ - name : Install dependencies
79+ run : |
80+ python -m pip install --upgrade pip
81+ pip install bump2version build twine
82+ pip install -e ".[dev]"
83+
84+ - name : Configure git
85+ run : |
86+ git config --local user.email "action@github.com"
87+ git config --local user.name "GitHub Action"
88+
89+ - name : Generate beta version
90+ id : version
91+ run : |
92+ # Get current version
93+ CURRENT_VERSION=$(python -c "from datafog.__about__ import __version__; print(__version__)")
94+ echo "Current version: $CURRENT_VERSION"
95+
96+ # Generate beta version
97+ if [[ $CURRENT_VERSION == *"b"* ]]; then
98+ # If already beta, increment beta number
99+ BASE_VERSION=$(echo $CURRENT_VERSION | cut -d'b' -f1)
100+ BETA_NUM=$(echo $CURRENT_VERSION | cut -d'b' -f2)
101+ BETA_VERSION="${BASE_VERSION}b$((BETA_NUM + 1))"
102+ elif [[ $CURRENT_VERSION == *"a"* ]]; then
103+ # If alpha, convert to beta
104+ BASE_VERSION=$(echo $CURRENT_VERSION | cut -d'a' -f1)
105+ BETA_VERSION="${BASE_VERSION}b1"
106+ else
107+ # If stable, bump minor and add beta (4.1.1 -> 4.2.0)
108+ BASE_VERSION=$(python -c "import re; version = '$CURRENT_VERSION'; parts = version.split('.'); parts[1] = str(int(parts[1]) + 1); parts[2] = '0'; print('.'.join(parts))")
109+ BETA_VERSION="${BASE_VERSION}b1"
110+ fi
111+
112+ echo "Beta version: $BETA_VERSION"
113+ echo "beta_version=$BETA_VERSION" >> $GITHUB_OUTPUT
114+
115+ # Update version in files
116+ sed -i "s/__version__ = \".*\"/__version__ = \"$BETA_VERSION\"/" datafog/__about__.py
117+ sed -i "s/version=\".*\"/version=\"$BETA_VERSION\"/" setup.py
118+
119+ - name : Generate changelog for beta
120+ run : |
121+ python scripts/generate_changelog.py --beta --output BETA_CHANGELOG.md
122+
123+ - name : Run comprehensive tests
124+ run : |
125+ echo "🧪 Running comprehensive test suite for beta release..."
126+
127+ # Run core tests
128+ python -m pytest tests/ -v --tb=short
129+
130+ # Run integration tests
131+ python -m pytest -m integration -v
132+
133+ # Run benchmarks to ensure performance
134+ python -m pytest tests/benchmark_text_service.py -v
135+
136+ echo "✅ All tests passed for beta release"
137+
138+ - name : Build package
139+ run : |
140+ python -m build
141+
142+ # Verify wheel size
143+ python scripts/check_wheel_size.py
144+
145+ echo "📦 Beta package built successfully"
146+
147+ - name : Create beta release
148+ env :
149+ GITHUB_TOKEN : ${{ secrets.GITHUB_TOKEN }}
150+ run : |
151+ BETA_VERSION="${{ steps.version.outputs.beta_version }}"
152+
153+ # Create and push tag
154+ git add datafog/__about__.py setup.py
155+ git commit -m "chore: bump version to $BETA_VERSION for beta release"
156+ git tag -a "v$BETA_VERSION" -m "Beta release $BETA_VERSION"
157+ git push origin "v$BETA_VERSION"
158+
159+ # Create GitHub release
160+ gh release create "v$BETA_VERSION" \
161+ --title "🚧 Beta Release $BETA_VERSION" \
162+ --notes-file BETA_CHANGELOG.md \
163+ --prerelease \
164+ --target dev \
165+ dist/*
166+
167+ - name : Publish to PyPI (Beta)
168+ if : github.event.inputs.dry_run != 'true'
169+ env :
170+ TWINE_USERNAME : __token__
171+ TWINE_PASSWORD : ${{ secrets.PYPI_API_TOKEN }}
172+ run : |
173+ echo "🚀 Publishing beta release to PyPI..."
174+ python -m twine upload dist/* --verbose
175+
176+ - name : Dry run summary
177+ if : github.event.inputs.dry_run == 'true'
178+ run : |
179+ echo "🏃♂️ DRY RUN COMPLETED"
180+ echo "Would have published: ${{ steps.version.outputs.beta_version }}"
181+ echo "Package contents:"
182+ ls -la dist/
183+ echo "Test results: All tests would be run"
184+
185+ - name : Cleanup old beta releases
186+ env :
187+ GITHUB_TOKEN : ${{ secrets.GITHUB_TOKEN }}
188+ run : |
189+ echo "🧹 Cleaning up old beta releases (keep last 5)..."
190+
191+ # Get all beta releases, sorted by creation date
192+ BETA_RELEASES=$(gh release list --limit 30 | grep "🚧.*b[0-9]" | tail -n +6 | cut -f3)
193+
194+ for release in $BETA_RELEASES; do
195+ echo "Deleting old beta release: $release"
196+ gh release delete "$release" --yes || true
197+ git push --delete origin "$release" || true
198+ done
199+
200+ notify-beta :
201+ needs : [check-changes, beta-release]
202+ if : needs.check-changes.outputs.has_changes == 'true' && success()
203+ runs-on : ubuntu-latest
204+ steps :
205+ - name : Beta release notification
206+ run : |
207+ echo "🚧 Thursday beta release completed!"
208+ echo "📦 Beta version ready for final testing"
209+ echo "💡 Install with: pip install datafog==${{ needs.beta-release.outputs.beta_version }}"
210+ echo "📊 Commits included: ${{ needs.check-changes.outputs.commit_count }}"
211+ echo "🗓️ Stable release scheduled for Friday"
212+ echo ""
213+ echo "🧪 Beta Testing Checklist:"
214+ echo " ✅ All automated tests passed"
215+ echo " ⏳ Manual testing recommended"
216+ echo " ⏳ Performance validation"
217+ echo " ⏳ Integration testing"
218+
219+ prepare-friday-release :
220+ needs : [beta-release]
221+ if : success()
222+ runs-on : ubuntu-latest
223+ steps :
224+ - name : Prepare Friday stable release
225+ run : |
226+ echo "🎯 Preparing for Friday stable release..."
227+ echo "Current beta: ${{ needs.beta-release.outputs.beta_version }}"
228+
229+ # Extract base version for Friday
230+ BETA_VERSION="${{ needs.beta-release.outputs.beta_version }}"
231+ STABLE_VERSION=$(echo $BETA_VERSION | cut -d'b' -f1)
232+
233+ echo "Planned stable version: $STABLE_VERSION"
234+ echo "📋 Friday Release Checklist:"
235+ echo " ⏳ Final beta testing"
236+ echo " ⏳ Update CHANGELOG.md"
237+ echo " ⏳ Run weekly release workflow"
238+ echo " ⏳ Social media announcement"
0 commit comments