Flutter Auto Upgrade #23
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: Flutter Auto Upgrade | |
| on: | |
| schedule: | |
| # Run every Sunday at 2 AM UTC | |
| - cron: '0 2 * * 0' | |
| workflow_dispatch: # Allow manual triggering | |
| jobs: | |
| check-and-upgrade-flutter: | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: write | |
| pull-requests: write | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| with: | |
| token: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Setup Flutter | |
| uses: subosito/flutter-action@v2 | |
| with: | |
| channel: 'stable' | |
| - name: Get current Flutter version | |
| id: current-version | |
| run: | | |
| # Check if we have a tracked version file | |
| if [ -f ".flutter-version-tracked" ]; then | |
| TRACKED_VERSION=$(cat .flutter-version-tracked) | |
| echo "tracked=$TRACKED_VERSION" >> $GITHUB_OUTPUT | |
| echo "Previously tracked Flutter version: $TRACKED_VERSION" | |
| else | |
| # Get current installed version as fallback | |
| CURRENT_VERSION=$(flutter --version | head -n 1 | grep -oE '[0-9]+\.[0-9]+\.[0-9]+') | |
| echo "tracked=$CURRENT_VERSION" >> $GITHUB_OUTPUT | |
| echo "No tracked version found, using current Flutter version: $CURRENT_VERSION" | |
| fi | |
| # Also get the actual installed version for reference | |
| INSTALLED_VERSION=$(flutter --version | head -n 1 | grep -oE '[0-9]+\.[0-9]+\.[0-9]+') | |
| echo "installed=$INSTALLED_VERSION" >> $GITHUB_OUTPUT | |
| echo "Currently installed Flutter version: $INSTALLED_VERSION" | |
| - name: Check for Flutter upgrades | |
| id: check-upgrade | |
| run: | | |
| # Get the latest stable Flutter version (filter out pre-releases) | |
| LATEST_VERSION=$(curl -s https://api.github.com/repos/flutter/flutter/releases | grep '"tag_name"' | grep -v 'pre' | head -1 | cut -d '"' -f 4) | |
| # Fallback to current installed version if API call fails | |
| if [ -z "$LATEST_VERSION" ]; then | |
| LATEST_VERSION=${{ steps.current-version.outputs.installed }} | |
| echo "Warning: Could not fetch latest version from GitHub, using installed version" | |
| fi | |
| echo "latest=$LATEST_VERSION" >> $GITHUB_OUTPUT | |
| echo "Latest Flutter version: $LATEST_VERSION" | |
| # Compare with tracked version (not current installed version) | |
| TRACKED_VERSION="${{ steps.current-version.outputs.tracked }}" | |
| if [ "$TRACKED_VERSION" != "$LATEST_VERSION" ]; then | |
| echo "upgrade_available=true" >> $GITHUB_OUTPUT | |
| echo "Upgrade available: $TRACKED_VERSION -> $LATEST_VERSION" | |
| else | |
| echo "upgrade_available=false" >> $GITHUB_OUTPUT | |
| echo "Flutter is already up to date (tracked: $TRACKED_VERSION)" | |
| fi | |
| - name: Check for dependency updates | |
| id: check-deps | |
| run: | | |
| echo "Checking for dependency updates..." | |
| # Check dio version | |
| DIO_CURRENT=$(grep "dio:" pubspec.yaml | sed 's/.*: \^//') | |
| echo "Current dio version: $DIO_CURRENT" | |
| DIO_LATEST=$(curl -s https://pub.dev/api/packages/dio | jq -r '.latest.version') | |
| echo "Latest dio version: $DIO_LATEST" | |
| # Check http version | |
| HTTP_CURRENT=$(grep "http:" pubspec.yaml | sed 's/.*: \^//') | |
| echo "Current http version: $HTTP_CURRENT" | |
| HTTP_LATEST=$(curl -s https://pub.dev/api/packages/http | jq -r '.latest.version') | |
| echo "Latest http version: $HTTP_LATEST" | |
| # Set outputs | |
| echo "dio_current=$DIO_CURRENT" >> $GITHUB_OUTPUT | |
| echo "dio_latest=$DIO_LATEST" >> $GITHUB_OUTPUT | |
| echo "http_current=$HTTP_CURRENT" >> $GITHUB_OUTPUT | |
| echo "http_latest=$HTTP_LATEST" >> $GITHUB_OUTPUT | |
| # Check if dependency updates are available | |
| DEPS_AVAILABLE=false | |
| if [ "$DIO_CURRENT" != "$DIO_LATEST" ]; then | |
| echo "Dio update available: $DIO_CURRENT -> $DIO_LATEST" | |
| DEPS_AVAILABLE=true | |
| fi | |
| if [ "$HTTP_CURRENT" != "$HTTP_LATEST" ]; then | |
| echo "HTTP update available: $HTTP_CURRENT -> $HTTP_LATEST" | |
| DEPS_AVAILABLE=true | |
| fi | |
| echo "deps_available=$DEPS_AVAILABLE" >> $GITHUB_OUTPUT | |
| if [ "$DEPS_AVAILABLE" = "true" ]; then | |
| echo "Dependency updates are available" | |
| else | |
| echo "All dependencies are up to date" | |
| fi | |
| - name: Create upgrade branch | |
| if: steps.check-upgrade.outputs.upgrade_available == 'true' || steps.check-deps.outputs.deps_available == 'true' | |
| run: | | |
| git config --local user.email "[email protected]" | |
| git config --local user.name "GitHub Action" | |
| # Create unique branch name with timestamp to avoid conflicts | |
| TIMESTAMP=$(date +%Y%m%d-%H%M%S) | |
| if [ "${{ steps.check-upgrade.outputs.upgrade_available }}" == "true" ]; then | |
| BRANCH_NAME="flutter/auto-upgrade-${{ steps.check-upgrade.outputs.latest }}-$TIMESTAMP" | |
| else | |
| BRANCH_NAME="deps/auto-update-$TIMESTAMP" | |
| fi | |
| # Delete remote branch if it exists (cleanup from previous runs) | |
| git push origin --delete "$BRANCH_NAME" 2>/dev/null || echo "Remote branch doesn't exist, continuing..." | |
| # Create and checkout new branch | |
| git checkout -b "$BRANCH_NAME" | |
| echo "BRANCH_NAME=$BRANCH_NAME" >> $GITHUB_ENV | |
| - name: Upgrade Flutter | |
| if: steps.check-upgrade.outputs.upgrade_available == 'true' | |
| run: | | |
| echo "Upgrading Flutter to ${{ steps.check-upgrade.outputs.latest }}" | |
| # Try normal upgrade first | |
| if ! flutter upgrade; then | |
| echo "Normal upgrade failed, attempting force upgrade..." | |
| flutter upgrade --force | |
| fi | |
| # Update Flutter version in pubspec.yaml if it exists with version constraints | |
| if [ -f "pubspec.yaml" ] && grep -q "flutter:" "pubspec.yaml"; then | |
| echo "Checking pubspec.yaml for Flutter version constraints..." | |
| # Note: This is a basic approach - you might need more sophisticated version handling | |
| fi | |
| - name: Update dependencies | |
| if: steps.check-deps.outputs.deps_available == 'true' | |
| run: | | |
| echo "Updating dependencies..." | |
| # Update dio if newer version available | |
| if [ "${{ steps.check-deps.outputs.dio_current }}" != "${{ steps.check-deps.outputs.dio_latest }}" ]; then | |
| echo "Updating dio from ${{ steps.check-deps.outputs.dio_current }} to ${{ steps.check-deps.outputs.dio_latest }}" | |
| sed -i.bak "s/dio: \^${{ steps.check-deps.outputs.dio_current }}/dio: ^${{ steps.check-deps.outputs.dio_latest }}/" pubspec.yaml | |
| fi | |
| # Update http if newer version available | |
| if [ "${{ steps.check-deps.outputs.http_current }}" != "${{ steps.check-deps.outputs.http_latest }}" ]; then | |
| echo "Updating http from ${{ steps.check-deps.outputs.http_current }} to ${{ steps.check-deps.outputs.http_latest }}" | |
| sed -i.bak "s/http: \^${{ steps.check-deps.outputs.http_current }}/http: ^${{ steps.check-deps.outputs.http_latest }}/" pubspec.yaml | |
| fi | |
| # Clean up backup files | |
| rm -f pubspec.yaml.bak | |
| - name: Apply automatic fixes | |
| if: steps.check-upgrade.outputs.upgrade_available == 'true' || steps.check-deps.outputs.deps_available == 'true' | |
| run: | | |
| echo "Applying automatic Dart fixes for deprecations and lint issues..." | |
| # First check what fixes are available (dry run) | |
| echo "Checking available fixes:" | |
| dart fix --dry-run || echo "No automatic fixes available or dry-run failed" | |
| # Apply the fixes | |
| echo "Applying fixes:" | |
| dart fix --apply || echo "No fixes applied or apply failed" | |
| - name: Update tracked Flutter version | |
| if: steps.check-upgrade.outputs.upgrade_available == 'true' | |
| run: | | |
| echo "Updating tracked Flutter version to ${{ steps.check-upgrade.outputs.latest }}" | |
| echo "${{ steps.check-upgrade.outputs.latest }}" > .flutter-version-tracked | |
| echo "Tracked version file updated" | |
| - name: Install dependencies and test | |
| if: steps.check-upgrade.outputs.upgrade_available == 'true' || steps.check-deps.outputs.deps_available == 'true' | |
| run: | | |
| flutter pub get | |
| # Run basic checks to ensure upgrade didn't break anything | |
| echo "Running Flutter doctor..." | |
| flutter doctor | |
| echo "Analyzing project..." | |
| flutter analyze | |
| echo "Running tests..." | |
| flutter test || echo "Tests failed - upgrade may need manual review" | |
| - name: Check for changes | |
| if: steps.check-upgrade.outputs.upgrade_available == 'true' || steps.check-deps.outputs.deps_available == 'true' | |
| id: check-changes | |
| run: | | |
| git add . | |
| if git diff --staged --quiet; then | |
| echo "has_changes=false" >> $GITHUB_OUTPUT | |
| echo "No changes detected after Flutter upgrade" | |
| else | |
| echo "has_changes=true" >> $GITHUB_OUTPUT | |
| echo "Changes detected after Flutter upgrade" | |
| fi | |
| - name: Commit changes | |
| if: steps.check-changes.outputs.has_changes == 'true' | |
| run: | | |
| # Create appropriate commit message based on what was updated | |
| if [ "${{ steps.check-upgrade.outputs.upgrade_available }}" == "true" ] && [ "${{ steps.check-deps.outputs.deps_available }}" == "true" ]; then | |
| COMMIT_MSG="chore: upgrade Flutter to ${{ steps.check-upgrade.outputs.latest }} and update dependencies | |
| - Automated Flutter upgrade from ${{ steps.current-version.outputs.tracked }} to ${{ steps.check-upgrade.outputs.latest }} | |
| - Updated dependencies (dio, http) | |
| - Applied automatic fixes with dart fix | |
| - Updated tracked Flutter version | |
| - Verified with flutter analyze and flutter test" | |
| elif [ "${{ steps.check-upgrade.outputs.upgrade_available }}" == "true" ]; then | |
| COMMIT_MSG="chore: upgrade Flutter to ${{ steps.check-upgrade.outputs.latest }} | |
| - Automated Flutter upgrade from ${{ steps.current-version.outputs.tracked }} to ${{ steps.check-upgrade.outputs.latest }} | |
| - Applied automatic fixes with dart fix | |
| - Updated tracked Flutter version | |
| - Verified with flutter analyze and flutter test" | |
| else | |
| COMMIT_MSG="chore: update dependencies | |
| - Updated dependencies (dio: ${{ steps.check-deps.outputs.dio_latest }}, http: ${{ steps.check-deps.outputs.http_latest }}) | |
| - Applied automatic fixes with dart fix | |
| - Verified with flutter analyze and flutter test" | |
| fi | |
| git commit -m "$COMMIT_MSG" | |
| - name: Push changes | |
| if: steps.check-changes.outputs.has_changes == 'true' | |
| run: | | |
| # Try normal push first, then force push if it fails | |
| if ! git push origin "$BRANCH_NAME"; then | |
| echo "Normal push failed, attempting force push..." | |
| git push --force origin "$BRANCH_NAME" | |
| fi | |
| - name: Create Pull Request | |
| if: steps.check-changes.outputs.has_changes == 'true' | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| const latestVersion = '${{ steps.check-upgrade.outputs.latest }}'; | |
| const trackedVersion = '${{ steps.current-version.outputs.tracked }}'; | |
| const { data: pullRequest } = await github.rest.pulls.create({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| title: `chore: upgrade Flutter to ${latestVersion} and dependencies`, | |
| head: process.env.BRANCH_NAME, | |
| base: 'master', // Change to 'main' if that's your default branch | |
| body: `## Flutter Auto Upgrade | |
| This PR was automatically created to upgrade Flutter from **${trackedVersion}** to **${latestVersion}** and update dependencies. | |
| ### Changes Made: | |
| - Upgraded Flutter to the latest stable version | |
| - Updated dependencies with \`flutter pub get\` | |
| - Applied automatic fixes for deprecations with \`dart fix --apply\` | |
| - Used force upgrade fallback if normal upgrade failed | |
| - Verified with \`flutter analyze\` | |
| - Ran \`flutter test\` (check CI results) | |
| ### Review Checklist: | |
| - [ ] Verify all tests pass in CI | |
| - [ ] Check for any breaking changes in Flutter release notes | |
| - [ ] Test the app manually if needed | |
| - [ ] Review any dependency conflicts | |
| ### Flutter Release Notes: | |
| Check the [Flutter releases page](https://github.com/flutter/flutter/releases/tag/${latestVersion}) for detailed information about this version. | |
| --- | |
| *This PR was created automatically by the Flutter Auto Upgrade workflow.*` | |
| }); | |
| console.log('Created PR #' + pullRequest.number); | |
| - name: Add labels to PR | |
| if: steps.check-changes.outputs.has_changes == 'true' | |
| continue-on-error: true | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| try { | |
| // Get the PR number from the previous step | |
| const prs = await github.rest.pulls.list({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| head: context.repo.owner + ':' + process.env.BRANCH_NAME, | |
| state: 'open' | |
| }); | |
| if (prs.data.length > 0) { | |
| const prNumber = prs.data[0].number; | |
| console.log(`Attempting to add labels to PR #${prNumber}`); | |
| await github.rest.issues.addLabels({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: prNumber, | |
| labels: ['dependencies', 'flutter', 'automated', 'upgrade'] | |
| }); | |
| console.log('Successfully added labels to PR'); | |
| } else { | |
| console.log('No PR found to add labels to'); | |
| } | |
| } catch (error) { | |
| console.log('Failed to add labels to PR (this is non-critical):', error.message); | |
| console.log('The PR was created successfully, labels can be added manually if needed'); | |
| } | |
| - name: Summary | |
| run: | | |
| if [ "${{ steps.check-upgrade.outputs.upgrade_available }}" == "true" ]; then | |
| if [ "${{ steps.check-changes.outputs.has_changes }}" == "true" ]; then | |
| echo "Flutter upgrade available, changes detected, and PR created!" | |
| echo "Upgraded from ${{ steps.current-version.outputs.tracked }} to ${{ steps.check-upgrade.outputs.latest }}" | |
| echo "Branch created: $BRANCH_NAME" | |
| else | |
| echo "Flutter upgrade available, but no changes detected" | |
| fi | |
| elif [ "${{ steps.check-deps.outputs.deps_available }}" == "true" ]; then | |
| if [ "${{ steps.check-changes.outputs.has_changes }}" == "true" ]; then | |
| echo "Dependency updates available, changes detected, and PR created!" | |
| echo "Branch created: $BRANCH_NAME" | |
| else | |
| echo "Dependency updates available, but no changes detected" | |
| fi | |
| else | |
| echo "Flutter is already up to date (tracked: ${{ steps.current-version.outputs.tracked }})" | |
| fi |