name: Build APK and Create GitHub Release on: workflow_dispatch: inputs: version: description: "Release version without leading v. Example: 1.0.0. Leave empty to read the top CHANGELOG heading." required: false type: string permissions: contents: write jobs: release: runs-on: ubuntu-latest steps: - name: Checkout repository uses: actions/checkout@v5.0.0 with: fetch-depth: 0 - name: Set up Java 17 uses: actions/setup-java@v5.2.0 with: distribution: temurin java-version: "17" - name: Set up Android SDK uses: android-actions/setup-android@v4.0.1 - name: Set up Flutter uses: subosito/flutter-action@v2.23.0 with: channel: stable cache: true - name: Install required Android SDK packages shell: bash run: | set -euo pipefail sdkmanager \ "platform-tools" \ "platforms;android-35" \ "build-tools;34.0.0" \ "build-tools;35.0.0" \ "ndk;28.2.12676356" - name: Get dependencies run: flutter pub get - name: Resolve version and tag id: meta shell: bash run: | set -euo pipefail INPUT_VERSION="${{ github.event.inputs.version }}" if [[ -n "${INPUT_VERSION}" ]]; then VERSION="${INPUT_VERSION#v}" else VERSION="$(python3 - <<'PY' from pathlib import Path import re text = Path("CHANGELOG.md").read_text(encoding="utf-8") m = re.search(r'^##\s+FocusGram\s+([0-9]+\.[0-9]+\.[0-9]+)\s*$', text, re.M) if not m: raise SystemExit("Could not find a top changelog heading like: ## FocusGram 2.0.0") print(m.group(1)) PY )" fi TAG="v${VERSION}" echo "version=${VERSION}" >> "$GITHUB_OUTPUT" echo "tag=${TAG}" >> "$GITHUB_OUTPUT" - name: Extract release notes from CHANGELOG.md shell: bash env: VERSION: ${{ steps.meta.outputs.version }} run: | set -euo pipefail python3 - <<'PY' from pathlib import Path import os import re version = os.environ["VERSION"] text = Path("CHANGELOG.md").read_text(encoding="utf-8") pattern = rf'(?ms)^##\s+FocusGram\s+{re.escape(version)}\s*$.*?(?=^##\s+|\Z)' m = re.search(pattern, text) if not m: raise SystemExit(f"Could not find changelog section for version {version}") Path("release_notes.md").write_text(m.group(0).strip() + "\n", encoding="utf-8") PY - name: Build release APK run: flutter build apk --release - name: Upload APK artifact uses: actions/upload-artifact@v7.0.1 with: name: focusgram-apk-${{ steps.meta.outputs.tag }} path: build/app/outputs/flutter-apk/app-release.apk if-no-files-found: error - name: Create Git tag shell: bash env: TAG: ${{ steps.meta.outputs.tag }} run: | set -euo pipefail git config user.name "github-actions[bot]" git config user.email "github-actions[bot]@users.noreply.github.com" if git ls-remote --exit-code --tags origin "refs/tags/${TAG}" >/dev/null 2>&1; then echo "Tag already exists on remote: ${TAG}" exit 1 fi git tag -a "${TAG}" -m "Release ${TAG}" git push origin "${TAG}" - name: Create GitHub Release uses: softprops/action-gh-release@v3.0.0 with: tag_name: ${{ steps.meta.outputs.tag }} name: FocusGram ${{ steps.meta.outputs.tag }} body_path: release_notes.md files: build/app/outputs/flutter-apk/app-release.apk draft: false prerelease: false env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}