Skip to content

refactor: unify release workflow to tag-based trigger #520

@mostronatorcoder

Description

@mostronatorcoder

Problem

The current release process is split across two workflows with different triggers, making it confusing and error-prone:

Workflow Trigger What it builds
main.yml Push to main + version change in pubspec.yaml Android APK + AAB + GitHub Release
desktop.yml Tag push v*.*.* Linux, macOS, Windows desktop builds

What goes wrong

To create a full release today, you need three manual steps:

  1. Edit pubspec.yaml with the new version
  2. Push to main
  3. Create and push a tag v*.*.*

If you forget step 1 (version bump), the Android build is skipped silently. If you only push a tag (like happened with v1.2.1), only the desktop builds run — no APK, no GitHub Release with Android artifacts.

This is exactly what happened: tag v1.2.1 was pushed, desktop builds completed successfully, but no Android APK was generated because pubspec.yaml wasn't updated.

Proposed Solution

Unify everything into a single tag-based workflow (like Choke does). One trigger, one manual step:

git tag v1.2.1 && git push --tags

The workflow handles everything else automatically.

New release.yml workflow

Trigger: push tags: v*

Steps (in order):

  1. Extract version from tag — parse v1.2.11.2.1
  2. Generate changelog — categorize commits between previous and current tag (features, fixes, docs, other)
  3. Update pubspec.yaml — set version: 1.2.1+{commit_count} automatically
  4. Commit changelog + version bump to main — so main always reflects the latest release
  5. Verify signing secrets — fail fast with clear error if any secret is missing
  6. Setup Android keystore — decode ANDROID_KEYSTORE_FILE from secrets, create key.properties
  7. Build Androidflutter build apk --split-per-abi + flutter build appbundle
  8. Verify APK signing — existing jarsigner/apksigner checks
  9. Create GitHub Release — with APKs, AAB, and generated release notes
  10. Trigger desktop buildsrepository_dispatch to desktop.yml (keeps desktop builds parallel on different OS runners)
  11. Cleanup — remove keystore and key.properties

What changes

File Change
.github/workflows/release.yml New — unified tag-based workflow (combines current main.yml Android build + changelog + version management)
.github/workflows/main.yml Remove or repurpose as CI-only (no release logic)
.github/workflows/desktop.yml Keep — still triggered by repository_dispatch from the new release workflow, plus manual workflow_dispatch and direct tag push
.github/workflows/flutter.yml No change — CI on PRs stays the same

What stays the same

  • Android keystore signing (same secrets: ANDROID_KEYSTORE_FILE, ANDROID_KEYSTORE_PASSWORD, ANDROID_KEY_PASSWORD, ANDROID_KEY_ALIAS)
  • Split APKs per ABI (armeabi-v7a, arm64-v8a)
  • AAB for Play Store
  • Desktop builds via desktop.yml (Linux, macOS, Windows)
  • APK signing verification
  • flutter.yml CI on PRs

Release flow comparison

Before (3 manual steps, easy to mess up):

1. Edit pubspec.yaml → version: 1.2.1+42
2. git commit && git push origin main
3. git tag v1.2.1 && git push --tags
   ↳ If you forget step 1: no Android build
   ↳ If you forget step 3: no desktop builds

After (1 manual step):

1. git tag v1.2.1 && git push --tags
   ↳ Everything happens automatically

Benefits

  • Single source of truth — the tag IS the version, no manual pubspec.yaml edits
  • Impossible to forget a step — one trigger builds everything
  • Automatic changelog — generated from commits between tags
  • Version consistencypubspec.yaml is always in sync with the tag
  • Existing secrets work as-is — no new secrets needed
  • Desktop builds unchangeddesktop.yml keeps working via repository_dispatch

Migration

  • No breaking changes — existing secrets and signing config work as-is
  • main.yml can be kept temporarily as a CI build (without release logic) or removed entirely since flutter.yml already handles CI on PRs
  • First release with the new workflow can be the next version after merging

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions