diff --git a/.github/workflows/flutter_test.yaml b/.github/workflows/flutter-ci.yaml similarity index 53% rename from .github/workflows/flutter_test.yaml rename to .github/workflows/flutter-ci.yaml index cbbaf59..eb9d9eb 100644 --- a/.github/workflows/flutter_test.yaml +++ b/.github/workflows/flutter-ci.yaml @@ -1,14 +1,11 @@ -name: Flutter Test +name: Flutter CI & Release on: push: - branches: - - main + branches: [main] + tags: ["v*.*.*"] pull_request: - branches: - - main - - # Allows you to run this workflow manually from the Actions tab + branches: [main] workflow_dispatch: jobs: @@ -75,16 +72,26 @@ jobs: - name: Decode android/key.properties run: echo "${{ secrets.KEY_PROPERTIES }}" | base64 --decode > android/key.properties + - name: Build APKs + run: flutter build apk --release --split-per-abi + - name: Build Universal APK run: flutter build apk --release - name: Rename Universal APK run: mv build/app/outputs/flutter-apk/{app-release,app-universal-release}.apk + + - name: Build App Bundle + run: flutter build appbundle --release + - name: Upload Android APK Artifact uses: actions/upload-artifact@v4 with: - name: release-apk - path: build/app/outputs/flutter-apk/*.apk + name: android-release-artifacts + path: | + build/app/outputs/flutter-apk/*-release*.apk + build/app/outputs/bundle/release/*.aab + build_linux: needs: test runs-on: ubuntu-latest @@ -96,9 +103,7 @@ jobs: submodules: recursive - name: Setup Flutter Environment uses: ./.github/actions/flutter-setup # Path to the composite action directory - with: - flutter-channel: stable - java-version: 17 + - name: Install Linux dependencies run: | sudo apt-get update -y @@ -113,6 +118,65 @@ jobs: - name: Upload deb Artifacts uses: actions/upload-artifact@v4 with: - name: build-artifacts + name: linux-release-artifacts path: | dist/*/*.deb + + # Job 4: Create GitHub Release (NEW - runs only on tag pushes) + create_release: + name: Create GitHub Release + needs: [build_android, build_linux] # Depends on successful builds + runs-on: ubuntu-latest + permissions: + contents: write # Need write access to create release + # <<< CONDITION: Only run this job if the trigger was a tag starting with 'v' + if: startsWith(github.ref, 'refs/tags/v') + + steps: + # No checkout needed if only downloading artifacts and using context variables + # - name: Checkout repository + # uses: actions/checkout@v4 + + # Download artifacts created earlier IN THIS SAME WORKFLOW RUN + - name: Download Android Artifacts + uses: actions/download-artifact@v4 + with: + name: android-release-artifacts + path: ./release-artifacts/android + + - name: Download Linux Artifacts + uses: actions/download-artifact@v4 + with: + name: linux-release-artifacts + path: ./release-artifacts/linux + + - name: List downloaded files (for debugging) + run: ls -R ./release-artifacts + shell: bash + + # Extract version info from the tag + - name: Extract Version from Tag + id: version + run: | + TAG_NAME=${GITHUB_REF#refs/tags/} + VERSION=${TAG_NAME#v} + echo "tag=${TAG_NAME}" >> $GITHUB_OUTPUT + echo "version=${VERSION}" >> $GITHUB_OUTPUT + shell: bash + + # Generate release notes (optional, consider its configuration for tags) + - name: Generate Release Notes + id: generate_release_notes + uses: release-drafter/release-drafter@v6 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + # Create the GitHub Release using downloaded artifacts + - name: Create GitHub Release + uses: ncipollo/release-action@v1 + with: + artifacts: "./release-artifacts/**/*" # Use downloaded artifacts + name: Release v${{ steps.version.outputs.version }} + tag: ${{ github.ref }} + body: ${{ steps.generate_release_notes.outputs.body }} + # token: ${{ secrets.GITHUB_TOKEN }} # Usually inferred diff --git a/.github/workflows/flutter-setup.yaml b/.github/workflows/flutter-setup.yaml deleted file mode 100644 index 17bbaa4..0000000 --- a/.github/workflows/flutter-setup.yaml +++ /dev/null @@ -1,49 +0,0 @@ -name: 🛠️ Reusable Flutter Setup - -on: - workflow_call: - inputs: - flutter-channel: - description: "Flutter channel to use (stable, beta, dev, master)" - required: false - type: string - default: "stable" - java-version: - description: "Java version to set up" - required: false - type: string - default: "17" - -jobs: - setup: - name: Setup Flutter Environment - runs-on: ubuntu-latest - steps: - - name: Checkout repository - uses: actions/checkout@v4 - with: - submodules: recursive - - name: Set up Java - uses: actions/setup-java@v4 - with: - distribution: "temurin" - # Use the input value, fallback to default if not provided - java-version: ${{ inputs.java-version }} - - name: Set up Flutter - uses: subosito/flutter-action@v2 - with: - channel: ${{ inputs.flutter-channel }} - flutter-version-file: pubspec.yaml - cache: true # Cache Flutter SDK itself - - name: Cache Flutter dependencies - id: cache-pub # Give the step an ID to potentially reference its outputs later if needed - uses: actions/cache@v4 - with: - path: ${{ env.FLUTTER_HOME }}/.pub-cache - # Use a consistent key structure based on the lock file - key: ${{ runner.os }}-flutter-pub-${{ hashFiles('**/pubspec.lock') }} - restore-keys: | - ${{ runner.os }}-flutter-pub- - - - name: Get Flutter dependencies - run: flutter pub get diff --git a/.github/workflows/flutter_release.yaml b/.github/workflows/flutter_release.yaml deleted file mode 100644 index 22698fa..0000000 --- a/.github/workflows/flutter_release.yaml +++ /dev/null @@ -1,110 +0,0 @@ -name: Flutter Release Workflow - -on: - push: - tags: - - "v**" - # manually trigger a release if needed - workflow_dispatch: - -jobs: - setup: - permissions: - # write permission is required to create a github release - contents: write - runs-on: ubuntu-latest - - steps: - - name: Checkout repository - uses: actions/checkout@v4 - with: - submodules: recursive - - name: Set up Flutter - uses: subosito/flutter-action@v2 - with: - channel: "stable" - flutter-version-file: pubspec.yaml - - - name: Install dependencies - run: flutter pub get - - build_android: - needs: setup - permissions: - # write permission is required to create a github release - contents: write - runs-on: ubuntu-latest - - steps: - - name: Set Up Java - uses: actions/setup-java@v3.12.0 - with: - distribution: "oracle" - java-version: "17" - - # - name: Run tests - # run: flutter test - - - name: Decode android/upload.jks - run: echo "${{ secrets.UPLOAD_KEYSTORE_JKS }}" | base64 --decode > android/upload.jks - - - name: Decode android/key.properties - run: echo "${{ secrets.KEY_PROPERTIES }}" | base64 --decode > android/key.properties - - - name: Build APKs - run: flutter build apk --release --split-per-abi - - - name: Build Universal APK - run: flutter build apk --release - - - name: Rename Universal APK - run: mv build/app/outputs/flutter-apk/{app-release,app-universal-release}.apk - - - name: Build App Bundle - run: flutter build appbundle --release - - build_linux: - needs: setup - permissions: - # write permission is required to create a github release - contents: write - runs-on: ubuntu-latest - - steps: - - name: setup fastforge - run: | - dart pub global activate fastforge - - name: Build Linux AppImage - run: fastforge package --platform linux --targets deb - - create_release: - needs: [build_android, build_linux] - permissions: - # write permission is required to create a github release - contents: write - runs-on: ubuntu-latest - - steps: - - name: version - id: version - run: | - tag=${GITHUB_REF/refs\/tags\//} - version=${tag#v} - major=${version%%.*} - echo "tag=${tag}" >> $GITHUB_OUTPUT - echo "version=${version}" >> $GITHUB_OUTPUT - echo "major=${major}" >> $GITHUB_OUTPUT - - - name: Generate Release Notes - id: generate_release_notes - uses: release-drafter/release-drafter@v6 - env: - GITHUB_TOKEN: ${{ github.token }} - - - name: Create GitHub Release - uses: ncipollo/release-action@v1 - with: - artifacts: "build/app/outputs/flutter-apk/*-release*.apk,build/app/outputs/bundle/release/*.aab,dist/*/*.deb" - name: v${{ steps.version.outputs.version }} - tag: ${{ github.ref }} - body: ${{ steps.generate_release_notes.outputs.body }} diff --git a/.github/workflows/prepare-release.yaml b/.github/workflows/prepare-release.yaml new file mode 100644 index 0000000..f1cb4a6 --- /dev/null +++ b/.github/workflows/prepare-release.yaml @@ -0,0 +1,130 @@ +# .github/workflows/prepare-release.yml +name: Prepare Release (using Cider) + +on: + workflow_dispatch: + inputs: + bump_type: + description: "Type of version bump (patch, minor, major)" + required: true + type: choice + options: + - patch + - minor + - major + default: "patch" + +permissions: + contents: write # NEEDED to commit, push, and tag + +jobs: + bump_version_and_tag: + name: Bump Version and Tag using Cider + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + # Use a PAT if pushing to protected branches is restricted for GITHUB_TOKEN + # token: ${{ secrets.PAT_TOKEN }} # Create PAT with repo scope + token: ${{ secrets.GITHUB_TOKEN }} + + # Setup Flutter/Dart environment needed to run dart pub global activate + - name: Setup Flutter + uses: subosito/flutter-action@v2 + with: + channel: "stable" # Or match your project's channel + flutter-version-file: pubspec.yaml + + - name: Install Cider + run: dart pub global activate cider + shell: bash + + # Add pub global bin to PATH for this job + - name: Add pub global bin to PATH + run: echo "$HOME/.pub-cache/bin" >> $GITHUB_PATH + shell: bash + + - name: Configure Git + run: | + git config user.name "github-actions[bot]" + git config user.email "41898282+github-actions[bot]@users.noreply.github.com" + shell: bash + + - name: Bump version using Cider + id: bump + run: | + echo "Current version:" + grep '^version:' pubspec.yaml + + # Run cider to bump version and build number + # Cider modifies pubspec.yaml in place + cider bump ${{ github.event.inputs.bump_type }} --bump-build + + echo "New version (after cider bump):" + # Read the *new* version directly from the modified file + new_version_line=$(grep '^version:' pubspec.yaml) + # Extract just the version string (e.g., 1.2.3+4) + new_version=$(echo "$new_version_line" | sed 's/version: *//') + + echo "$new_version_line" + echo "Extracted new version: $new_version" + + if [[ -z "$new_version" ]]; then + echo "Error: Could not extract new version after cider bump." + exit 1 + fi + + # Create tag name (e.g., v1.2.3 - usually tags don't include build number) + # Extract version part before '+' for the tag + version_for_tag=$(echo "$new_version" | cut -d'+' -f1) + new_tag="v$version_for_tag" + echo "New tag: $new_tag" + + # Set outputs for later steps + echo "new_version=$new_version" >> $GITHUB_OUTPUT + echo "new_tag=$new_tag" >> $GITHUB_OUTPUT + shell: bash + + - name: Commit version bump + run: | + # Add pubspec.yaml. Add CHANGELOG.md if cider modifies it and you want to commit it. + git add pubspec.yaml + # git add CHANGELOG.md # Uncomment if needed + + # Check if there are changes to commit + if git diff --staged --quiet; then + echo "No changes detected in pubspec.yaml (or CHANGELOG.md) to commit." + else + # Use the version *without* build number for the commit message usually + git commit -m "chore(release): bump version to ${{ steps.bump.outputs.new_tag }}" + fi + shell: bash + + - name: Create Git tag + # Only run if the commit step actually committed something (check git status) + # or simply run always, it won't hurt if the commit was skipped + run: | + git tag ${{ steps.bump.outputs.new_tag }} + shell: bash + + - name: Push changes and tag + run: | + # Push the commit first (e.g., to main branch - adjust if needed) + # Handle potential conflicts if main changed since checkout? (More advanced setup) + # Check if there are commits to push before pushing branch + if ! git diff --quiet HEAD^ HEAD; then + echo "Pushing commit to main..." + git push origin HEAD:main + else + echo "No new commits to push to main." + fi + + # Always push the tag + echo "Pushing tag ${{ steps.bump.outputs.new_tag }}..." + git push origin ${{ steps.bump.outputs.new_tag }} + shell: bash + + - name: Output New Tag + run: echo "Successfully tagged release ${{ steps.bump.outputs.new_tag }}"