feat: last try #20
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: CI/CD Pipeline | |
| on: | |
| push: | |
| branches: [main, develop] | |
| pull_request: | |
| branches: [main, develop] | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.ref }} | |
| cancel-in-progress: true | |
| env: | |
| FLUTTER_VERSION: "3.35.0" | |
| MELOS_VERSION: "6.0.0" | |
| jobs: | |
| # Job 1: Analyze and validate code quality | |
| analyze: | |
| name: 📊 Code Analysis | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 10 | |
| steps: | |
| - name: 📚 Checkout repository | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 # Full history for conventional commits | |
| - name: 🐦 Setup Flutter | |
| uses: subosito/flutter-action@v2 | |
| with: | |
| flutter-version: ${{ env.FLUTTER_VERSION }} | |
| cache: true | |
| - name: 📦 Get dependencies | |
| run: flutter pub global activate melos ${{ env.MELOS_VERSION }} | |
| - name: 🏗️ Bootstrap monorepo | |
| run: melos bootstrap | |
| - name: 🔍 Analyze code | |
| run: melos run analyze | |
| - name: 📝 Check formatting | |
| run: melos run format | |
| # Job 2: Run all tests | |
| test: | |
| name: 🧪 Tests | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 15 | |
| needs: [analyze] | |
| steps: | |
| - name: 📚 Checkout repository | |
| uses: actions/checkout@v4 | |
| - name: 🐦 Setup Flutter | |
| uses: subosito/flutter-action@v2 | |
| with: | |
| flutter-version: ${{ env.FLUTTER_VERSION }} | |
| cache: true | |
| - name: 📦 Get dependencies | |
| run: flutter pub global activate melos ${{ env.MELOS_VERSION }} | |
| - name: 🏗️ Bootstrap monorepo | |
| run: melos bootstrap | |
| - name: 🧪 Run tests | |
| run: melos run test:all | |
| - name: 📊 Upload coverage | |
| uses: codecov/codecov-action@v3 | |
| if: success() | |
| with: | |
| files: ./coverage/lcov.info | |
| # Job 3: Build packages | |
| build: | |
| name: 🏗️ Build | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 15 | |
| needs: [analyze] | |
| steps: | |
| - name: 📚 Checkout repository | |
| uses: actions/checkout@v4 | |
| - name: 🐦 Setup Flutter | |
| uses: subosito/flutter-action@v2 | |
| with: | |
| flutter-version: ${{ env.FLUTTER_VERSION }} | |
| cache: true | |
| - name: 📦 Get dependencies | |
| run: flutter pub global activate melos ${{ env.MELOS_VERSION }} | |
| - name: 🏗️ Bootstrap monorepo | |
| run: melos bootstrap | |
| - name: 🔨 Build packages | |
| run: melos run build_runner | |
| - name: 📱 Build example apps | |
| run: melos run build:all | |
| continue-on-error: true # Some packages might not have example apps | |
| # Job 4: Version and publish (only on main branch) | |
| version-and-publish: | |
| name: 🚀 Version & Publish | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 20 | |
| needs: [analyze, test, build] | |
| if: github.ref == 'refs/heads/main' && github.event_name == 'push' | |
| permissions: | |
| contents: write | |
| packages: write | |
| pull-requests: write | |
| steps: | |
| - name: 📚 Checkout repository | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| token: ${{ secrets.GITHUB_TOKEN }} | |
| - name: 🐦 Setup Flutter | |
| uses: subosito/flutter-action@v2 | |
| with: | |
| flutter-version: ${{ env.FLUTTER_VERSION }} | |
| cache: true | |
| - name: 📦 Get dependencies | |
| run: flutter pub global activate melos ${{ env.MELOS_VERSION }} | |
| - name: 🏗️ Bootstrap monorepo | |
| run: melos bootstrap | |
| - name: 🏷️ Check for changes requiring versioning | |
| id: check-changes | |
| run: | | |
| echo "🔍 Checking for changes requiring versioning..." | |
| # Check if we have any package tags (first release detection) | |
| PACKAGE_TAGS=$(git tag -l "*@*" | wc -l || echo "0") | |
| echo "📌 Found $PACKAGE_TAGS existing package tags" | |
| if [ "$PACKAGE_TAGS" -eq 0 ]; then | |
| echo "🎉 No package tags found - treating as first release" | |
| # For first release, count all public packages | |
| CHANGED_PACKAGES=$(melos list --no-private --parsable | wc -l || echo "0") | |
| echo "📦 First release: $CHANGED_PACKAGES public packages to publish" | |
| if [ "$CHANGED_PACKAGES" -gt 0 ]; then | |
| echo "📋 Packages to publish:" | |
| melos list --no-private --long || echo "Unable to list packages" | |
| fi | |
| else | |
| echo "🔄 Checking for changes since origin/develop..." | |
| # For subsequent releases, use git to check for changes in package directories | |
| CHANGED_PACKAGES=0 | |
| # Check each package directory for changes | |
| if git diff --quiet origin/develop HEAD -- packages/pillar-core/; then | |
| echo "📦 pillar-core: no changes" | |
| else | |
| echo "📦 pillar-core: has changes" | |
| CHANGED_PACKAGES=$((CHANGED_PACKAGES + 1)) | |
| fi | |
| if git diff --quiet origin/develop HEAD -- packages/pillar-remote-config/; then | |
| echo "📦 pillar-remote-config: no changes" | |
| else | |
| echo "📦 pillar-remote-config: has changes" | |
| # Only count if it's public (check pubspec.yaml) | |
| if ! grep -q "publish_to: none" packages/pillar-remote-config/pubspec.yaml 2>/dev/null; then | |
| CHANGED_PACKAGES=$((CHANGED_PACKAGES + 1)) | |
| fi | |
| fi | |
| echo "📦 Found $CHANGED_PACKAGES packages with changes" | |
| fi | |
| echo "changed_packages=$CHANGED_PACKAGES" >> $GITHUB_OUTPUT | |
| echo "✅ Final result: $CHANGED_PACKAGES packages to process" | |
| - name: 🔄 Version packages | |
| if: steps.check-changes.outputs.changed_packages > 0 | |
| run: | | |
| # Configure git for automated commits | |
| git config --global user.name "github-actions[bot]" | |
| git config --global user.email "github-actions[bot]@users.noreply.github.com" | |
| # Version only changed packages based on conventional commits | |
| echo "🔄 Versioning packages..." | |
| # Check if we have package tags (not first release) | |
| PACKAGE_TAGS=$(git tag -l "*@*" | wc -l || echo "0") | |
| if [ "$PACKAGE_TAGS" -eq 0 ]; then | |
| echo "🎉 First release - versioning all packages" | |
| melos version --yes --all | |
| else | |
| echo "📦 Versioning changed packages only" | |
| # Version only packages that have changes since origin/develop | |
| melos version --yes | |
| fi | |
| - name: 📝 Generate changelogs | |
| if: steps.check-changes.outputs.changed_packages > 0 | |
| run: | | |
| # Generate individual package changelogs | |
| melos exec --no-private -- "echo 'Generating changelog for \$MELOS_PACKAGE_NAME'" | |
| # Update workspace changelog | |
| echo "# Pillar Monorepo Changelog" > CHANGELOG.md | |
| echo "" >> CHANGELOG.md | |
| echo "This file tracks changes across all packages in the Pillar monorepo." >> CHANGELOG.md | |
| echo "" >> CHANGELOG.md | |
| echo "## $(date '+%Y-%m-%d')" >> CHANGELOG.md | |
| echo "" >> CHANGELOG.md | |
| # Add package versions to workspace changelog | |
| melos list --long --json | jq -r '.[] | "- **\(.name)** v\(.version)"' >> CHANGELOG.md | |
| - name: 🏷️ Create release tags | |
| if: steps.check-changes.outputs.changed_packages > 0 | |
| run: | | |
| # Get the list of packages that were versioned | |
| VERSIONED_PACKAGES=$(melos list --json | jq -r '.[].name') | |
| for package in $VERSIONED_PACKAGES; do | |
| VERSION=$(melos list --json | jq -r ".[] | select(.name == \"$package\") | .version") | |
| if [ ! -z "$VERSION" ] && [ "$VERSION" != "null" ]; then | |
| echo "Creating tag for $package@$VERSION" | |
| git tag "$package@$VERSION" -m "Release $package version $VERSION" | |
| fi | |
| done | |
| - name: 📤 Push changes and tags | |
| if: steps.check-changes.outputs.changed_packages > 0 | |
| run: | | |
| git push origin main | |
| git push origin --tags | |
| - name: 📦 Publish to pub.dev | |
| if: steps.check-changes.outputs.changed_packages > 0 | |
| env: | |
| PUB_CREDENTIALS: ${{ secrets.PUB_CREDENTIALS }} | |
| run: | | |
| # Setup pub.dev credentials for auto-refresh | |
| if [ -n "$PUB_CREDENTIALS" ]; then | |
| echo "🔐 Setting up pub.dev credentials with auto-refresh..." | |
| mkdir -p ~/.pub-cache | |
| echo "$PUB_CREDENTIALS" > ~/.pub-cache/credentials.json | |
| echo "✅ Credentials configured with refresh token" | |
| else | |
| echo "⚠️ PUB_CREDENTIALS not configured, skipping publish" | |
| exit 1 | |
| fi | |
| # Publish packages (dart pub will auto-refresh token if needed) | |
| echo "📦 Publishing packages to pub.dev..." | |
| melos publish --no-dry-run --yes || echo "⚠️ Some packages may have failed to publish" | |
| - name: 📋 Create GitHub release | |
| if: steps.check-changes.outputs.changed_packages > 0 | |
| uses: actions/create-release@v1 | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| with: | |
| tag_name: "release-$(date +'%Y%m%d-%H%M%S')" | |
| release_name: "Pillar Release $(date +'%Y-%m-%d %H:%M:%S')" | |
| body: | | |
| ## 🚀 Automated Release | |
| This release was automatically generated by our CI/CD pipeline. | |
| ### 📦 Updated Packages | |
| $(melos list --long | grep -v "PRIVATE" || echo "No public packages updated") | |
| ### 🔄 Changes | |
| See individual package changelogs for detailed changes. | |
| --- | |
| Generated on $(date) | |
| draft: false | |
| prerelease: false | |
| # Job 5: Notify on failure | |
| notify-failure: | |
| name: 📢 Notify Failure | |
| runs-on: ubuntu-latest | |
| needs: [analyze, test, build, version-and-publish] | |
| if: failure() && github.ref == 'refs/heads/main' | |
| steps: | |
| - name: 📢 Send notification | |
| run: | | |
| echo "🚨 CI/CD Pipeline failed for main branch" | |
| echo "Please check the logs and fix the issues" | |
| # Add Slack/Discord/Email notification here if needed |