mirror of
https://github.com/twonlyapp/twonly-app.git
synced 2026-06-02 19:42:12 +00:00
switch to fastlane for github and f-droid releases
Some checks are pending
Flutter analyze & test / flutter_analyze_and_test (push) Waiting to run
Some checks are pending
Flutter analyze & test / flutter_analyze_and_test (push) Waiting to run
This commit is contained in:
parent
62457f1f48
commit
7559434f86
6 changed files with 142 additions and 70 deletions
68
.github/workflows/release_github.yml
vendored
68
.github/workflows/release_github.yml
vendored
|
|
@ -1,68 +0,0 @@
|
||||||
name: Publish on Github
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_dispatch: {}
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
paths:
|
|
||||||
- pubspec.yaml
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build_and_publish:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
permissions:
|
|
||||||
contents: write
|
|
||||||
steps:
|
|
||||||
- name: Clone repository
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Set up Flutter
|
|
||||||
uses: subosito/flutter-action@v2
|
|
||||||
with:
|
|
||||||
channel: stable
|
|
||||||
|
|
||||||
- name: Install Rust
|
|
||||||
uses: dtolnay/rust-toolchain@stable
|
|
||||||
|
|
||||||
- name: Install requirements
|
|
||||||
run: sudo apt-get install protobuf-compiler
|
|
||||||
|
|
||||||
- name: Cloning sub-repos
|
|
||||||
run: git submodule update --init --recursive
|
|
||||||
|
|
||||||
# - name: Check flutter code
|
|
||||||
# run: |
|
|
||||||
# flutter pub get
|
|
||||||
# flutter analyze
|
|
||||||
# flutter test
|
|
||||||
|
|
||||||
- name: Check flutter code
|
|
||||||
run: flutter pub get
|
|
||||||
|
|
||||||
- name: Create key.properties file
|
|
||||||
run: |
|
|
||||||
echo "storePassword=${{ secrets.STORE_PASSWORD }}" >> ./android/key.properties
|
|
||||||
echo "keyPassword=${{ secrets.KEY_PASSWORD }}" >> ./android/key.properties
|
|
||||||
echo "keyAlias=github-releases-signature" >> ./android/key.properties
|
|
||||||
echo "storeFile=./keystore.jks" >> ./android/key.properties
|
|
||||||
|
|
||||||
- name: Create keystore file
|
|
||||||
env:
|
|
||||||
KEYSTORE_FILE: ${{ secrets.KEYSTORE_FILE }}
|
|
||||||
run: echo $KEYSTORE_FILE | base64 --decode > ./android/app/keystore.jks
|
|
||||||
|
|
||||||
- name: Build Android APK
|
|
||||||
run: flutter build apk --release --split-per-abi
|
|
||||||
|
|
||||||
- name: Extract pubspec version
|
|
||||||
run: |
|
|
||||||
echo "PUBSPEC_VERSION=$(grep -oP 'version:\s*\K[^+]+(?=\+)' pubspec.yaml)" >> $GITHUB_ENV
|
|
||||||
|
|
||||||
- name: Upload Release Binaries (stable)
|
|
||||||
uses: ncipollo/release-action@v1.18.0
|
|
||||||
with:
|
|
||||||
token: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
tag: v${{ env.PUBSPEC_VERSION }}
|
|
||||||
allowUpdates: true
|
|
||||||
artifacts: build/app/outputs/flutter-apk/*.apk
|
|
||||||
3
.gitignore
vendored
3
.gitignore
vendored
|
|
@ -54,4 +54,5 @@ app.*.map.json
|
||||||
android/.kotlin/
|
android/.kotlin/
|
||||||
devtools_options.yaml
|
devtools_options.yaml
|
||||||
rust/target
|
rust/target
|
||||||
rust_dependencies/target
|
rust_dependencies/target
|
||||||
|
fastlane/repo/status/running.json
|
||||||
|
|
|
||||||
2
android/.gitignore
vendored
2
android/.gitignore
vendored
|
|
@ -9,5 +9,7 @@ GeneratedPluginRegistrant.java
|
||||||
# Remember to never publicly share your keystore.
|
# Remember to never publicly share your keystore.
|
||||||
# See https://flutter.dev/to/reference-keystore
|
# See https://flutter.dev/to/reference-keystore
|
||||||
key.properties
|
key.properties
|
||||||
|
key.github.properties
|
||||||
|
key.properties.backup
|
||||||
**/*.keystore
|
**/*.keystore
|
||||||
**/*.jks
|
**/*.jks
|
||||||
|
|
|
||||||
8
android/key.github.properties.example
Normal file
8
android/key.github.properties.example
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
# Example signing credentials configuration for GitHub Releases.
|
||||||
|
# Copy this file to 'key.github.properties' and fill in your actual credentials.
|
||||||
|
# Do not commit the actual 'key.github.properties' file to version control.
|
||||||
|
|
||||||
|
storePassword=YOUR_GITHUB_RELEASE_STORE_PASSWORD
|
||||||
|
keyPassword=YOUR_GITHUB_RELEASE_KEY_PASSWORD
|
||||||
|
keyAlias=github-releases-signature
|
||||||
|
storeFile=/absolute/path/to/your/github-release-keystore.jks
|
||||||
|
|
@ -12,4 +12,133 @@ platform :android do
|
||||||
skip_upload_screenshots: true
|
skip_upload_screenshots: true
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
desc "Build the application locally and upload it as a new GitHub release"
|
||||||
|
lane :release_github do
|
||||||
|
# Read pubspec.yaml to get the version
|
||||||
|
pubspec_path = File.expand_path("../pubspec.yaml", __dir__)
|
||||||
|
unless File.exist?(pubspec_path)
|
||||||
|
UI.user_error!("Could not find pubspec.yaml at #{pubspec_path}")
|
||||||
|
end
|
||||||
|
|
||||||
|
pubspec_content = File.read(pubspec_path)
|
||||||
|
version_match = pubspec_content.match(/^version:\s*([^+]+)/)
|
||||||
|
unless version_match
|
||||||
|
UI.user_error!("Could not extract version from pubspec.yaml")
|
||||||
|
end
|
||||||
|
|
||||||
|
version = version_match[1].strip
|
||||||
|
tag_name = "v#{version}"
|
||||||
|
UI.message("Extracted version: #{version} (tag: #{tag_name})")
|
||||||
|
|
||||||
|
# Load release notes from CHANGELOG.md
|
||||||
|
changelog_path = File.expand_path("../CHANGELOG.md", __dir__)
|
||||||
|
release_notes = "Automated local release via Fastlane"
|
||||||
|
if File.exist?(changelog_path)
|
||||||
|
changelog_content = File.read(changelog_path)
|
||||||
|
escaped_version = Regexp.escape(version)
|
||||||
|
pattern = /##\s*\[?#{escaped_version}\]?(.*?)(?=##\s*|\z)/m
|
||||||
|
match = changelog_content.match(pattern)
|
||||||
|
if match
|
||||||
|
release_notes = match[1].strip
|
||||||
|
UI.message("Loaded release notes from CHANGELOG.md:\n#{release_notes}")
|
||||||
|
else
|
||||||
|
UI.important("Could not find release notes for version #{version} in CHANGELOG.md. Using default description.")
|
||||||
|
end
|
||||||
|
else
|
||||||
|
UI.important("CHANGELOG.md not found at #{changelog_path}. Using default description.")
|
||||||
|
end
|
||||||
|
|
||||||
|
# Handle key.properties swapping if key.github.properties exists
|
||||||
|
key_properties_path = File.expand_path("../android/key.properties", __dir__)
|
||||||
|
github_properties_path = File.expand_path("../android/key.github.properties", __dir__)
|
||||||
|
backup_properties_path = File.expand_path("../android/key.properties.backup", __dir__)
|
||||||
|
|
||||||
|
swapped_properties = false
|
||||||
|
if File.exist?(github_properties_path)
|
||||||
|
UI.message("Found key.github.properties. Swapping in for the build...")
|
||||||
|
if File.exist?(key_properties_path)
|
||||||
|
FileUtils.cp(key_properties_path, backup_properties_path)
|
||||||
|
end
|
||||||
|
FileUtils.cp(github_properties_path, key_properties_path)
|
||||||
|
swapped_properties = true
|
||||||
|
else
|
||||||
|
UI.message("No key.github.properties found. Building with default key.properties...")
|
||||||
|
end
|
||||||
|
|
||||||
|
begin
|
||||||
|
# Build the Android application
|
||||||
|
UI.message("Building Android APK...")
|
||||||
|
Dir.chdir(File.expand_path("..", __dir__)) do
|
||||||
|
sh("flutter build apk --release --split-per-abi")
|
||||||
|
end
|
||||||
|
ensure
|
||||||
|
# Restore original key.properties if swapped
|
||||||
|
if swapped_properties
|
||||||
|
UI.message("Restoring original key.properties...")
|
||||||
|
if File.exist?(backup_properties_path)
|
||||||
|
FileUtils.cp(backup_properties_path, key_properties_path)
|
||||||
|
FileUtils.rm(backup_properties_path)
|
||||||
|
else
|
||||||
|
FileUtils.rm_f(key_properties_path)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Find built APKs
|
||||||
|
apk_glob = File.expand_path("../build/app/outputs/flutter-apk/*-release.apk", __dir__)
|
||||||
|
apks = Dir.glob(apk_glob)
|
||||||
|
|
||||||
|
if apks.empty?
|
||||||
|
UI.user_error!("No release APKs found matching #{apk_glob}")
|
||||||
|
end
|
||||||
|
|
||||||
|
UI.message("Found APKs to upload: #{apks.join(', ')}")
|
||||||
|
|
||||||
|
# Retrieve GitHub Token (fall back to gh auth token)
|
||||||
|
github_token = ENV["GITHUB_TOKEN"]
|
||||||
|
if github_token.nil? || github_token.empty?
|
||||||
|
UI.message("GITHUB_TOKEN env variable not set. Retrieving token via GitHub CLI (gh auth token)...")
|
||||||
|
begin
|
||||||
|
github_token = sh("gh auth token").strip
|
||||||
|
rescue => e
|
||||||
|
UI.user_error!("Failed to retrieve token from gh CLI. Make sure gh is installed and authenticated, or GITHUB_TOKEN environment variable is set. Error: #{e}")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
UI.message("Creating GitHub Release #{tag_name}...")
|
||||||
|
set_github_release(
|
||||||
|
repository_name: "twonlyapp/twonly-app",
|
||||||
|
api_token: github_token,
|
||||||
|
tag_name: tag_name,
|
||||||
|
name: "Release #{tag_name}",
|
||||||
|
description: release_notes,
|
||||||
|
upload_assets: apks
|
||||||
|
)
|
||||||
|
UI.success("Successfully uploaded release #{tag_name} to GitHub!")
|
||||||
|
|
||||||
|
# F-Droid deployment
|
||||||
|
fdroid_repo_dir = "/Users/tobi/Documents/drive/twonly/F-Droid/repo"
|
||||||
|
UI.message("Starting F-Droid deployment...")
|
||||||
|
FileUtils.mkdir_p(fdroid_repo_dir)
|
||||||
|
|
||||||
|
apks.each do |apk_path|
|
||||||
|
basename = File.basename(apk_path)
|
||||||
|
new_name = "eu.twonly_v#{version}-#{basename}"
|
||||||
|
dest_path = File.join(fdroid_repo_dir, new_name)
|
||||||
|
UI.message("Copying APK to F-Droid repo: #{dest_path}")
|
||||||
|
FileUtils.cp(apk_path, dest_path)
|
||||||
|
end
|
||||||
|
|
||||||
|
fdroid_dir = "/Users/tobi/Documents/drive/twonly/F-Droid"
|
||||||
|
update_script = File.join(fdroid_dir, "update.sh")
|
||||||
|
if File.exist?(update_script)
|
||||||
|
UI.message("Executing F-Droid update script...")
|
||||||
|
Dir.chdir(fdroid_dir) do
|
||||||
|
sh("chmod +x ./update.sh && ./update.sh")
|
||||||
|
end
|
||||||
|
else
|
||||||
|
UI.important("F-Droid update script not found at #{update_script}")
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,7 @@ Future<void> reuploadMediaFiles() async {
|
||||||
|
|
||||||
final contacts = <int, Contact>{};
|
final contacts = <int, Contact>{};
|
||||||
|
|
||||||
for (var receipt in receipts) {
|
for (final receipt in receipts) {
|
||||||
if (receipt.retryCount > 1 && receipt.lastRetry != null) {
|
if (receipt.retryCount > 1 && receipt.lastRetry != null) {
|
||||||
final twentyFourHoursAgo = DateTime.now().subtract(
|
final twentyFourHoursAgo = DateTime.now().subtract(
|
||||||
const Duration(hours: 6),
|
const Duration(hours: 6),
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue