Release #25
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: Release | |
| on: | |
| push: | |
| tags: | |
| - "v*" | |
| workflow_run: | |
| workflows: | |
| - Sync Version Tag | |
| types: | |
| - completed | |
| workflow_dispatch: | |
| inputs: | |
| tag: | |
| description: Existing release tag to build, for example v1.0.0 | |
| required: true | |
| type: string | |
| permissions: | |
| contents: write | |
| env: | |
| FLUTTER_VERSION: 3.41.4 | |
| JAVA_VERSION: "17" | |
| jobs: | |
| metadata: | |
| name: Resolve release metadata | |
| runs-on: ubuntu-latest | |
| if: ${{ github.event_name != 'workflow_run' || github.event.workflow_run.conclusion == 'success' }} | |
| outputs: | |
| ref: ${{ steps.version.outputs.ref }} | |
| version: ${{ steps.version.outputs.version }} | |
| tag: ${{ steps.version.outputs.tag }} | |
| steps: | |
| - name: Resolve source ref | |
| id: ref | |
| shell: bash | |
| env: | |
| DISPATCH_TAG: ${{ inputs.tag }} | |
| EVENT_NAME: ${{ github.event_name }} | |
| WORKFLOW_HEAD_SHA: ${{ github.event.workflow_run.head_sha }} | |
| run: | | |
| case "$EVENT_NAME" in | |
| push) | |
| source_ref="$GITHUB_REF_NAME" | |
| ;; | |
| workflow_dispatch) | |
| source_ref="$DISPATCH_TAG" | |
| ;; | |
| workflow_run) | |
| source_ref="$WORKFLOW_HEAD_SHA" | |
| ;; | |
| *) | |
| echo "Unsupported event: $EVENT_NAME" >&2 | |
| exit 1 | |
| ;; | |
| esac | |
| if [ -z "$source_ref" ]; then | |
| echo "Could not determine source ref for release workflow." >&2 | |
| exit 1 | |
| fi | |
| echo "source_ref=$source_ref" >> "$GITHUB_OUTPUT" | |
| - name: Checkout repository | |
| uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 0 | |
| ref: ${{ steps.ref.outputs.source_ref }} | |
| - name: Fetch tags | |
| shell: bash | |
| run: git fetch --force --tags origin | |
| - name: Resolve tag and validate pubspec version | |
| id: version | |
| shell: bash | |
| env: | |
| DISPATCH_TAG: ${{ inputs.tag }} | |
| EVENT_NAME: ${{ github.event_name }} | |
| PUSH_TAG: ${{ github.ref_name }} | |
| run: | | |
| version=$(sed -n 's/^version: *//p' pubspec.yaml | head -n1 | cut -d+ -f1) | |
| if [ -z "$version" ]; then | |
| echo "Could not determine app version from pubspec.yaml." >&2 | |
| exit 1 | |
| fi | |
| expected_tag="v$version" | |
| case "$EVENT_NAME" in | |
| push) | |
| actual_tag="$PUSH_TAG" | |
| ;; | |
| workflow_dispatch) | |
| actual_tag="$DISPATCH_TAG" | |
| ;; | |
| workflow_run) | |
| actual_tag="$expected_tag" | |
| if ! git rev-parse -q --verify "refs/tags/$actual_tag" >/dev/null; then | |
| echo "Expected tag '$actual_tag' was not found after Sync Version Tag completed." >&2 | |
| exit 1 | |
| fi | |
| ;; | |
| *) | |
| echo "Unsupported event: $EVENT_NAME" >&2 | |
| exit 1 | |
| ;; | |
| esac | |
| if [ "$actual_tag" != "$expected_tag" ]; then | |
| echo "Tag '$actual_tag' does not match pubspec version '$expected_tag'." >&2 | |
| exit 1 | |
| fi | |
| echo "ref=$actual_tag" >> "$GITHUB_OUTPUT" | |
| echo "version=$version" >> "$GITHUB_OUTPUT" | |
| echo "tag=$actual_tag" >> "$GITHUB_OUTPUT" | |
| windows-release: | |
| name: Build Windows release artifacts | |
| runs-on: windows-latest | |
| needs: metadata | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v6 | |
| with: | |
| ref: ${{ needs.metadata.outputs.ref }} | |
| - name: Set up Flutter | |
| uses: subosito/flutter-action@v2 | |
| with: | |
| channel: stable | |
| flutter-version: ${{ env.FLUTTER_VERSION }} | |
| cache: true | |
| - name: Enable Windows desktop | |
| shell: pwsh | |
| run: flutter config --enable-windows-desktop | |
| - name: Install dependencies | |
| shell: pwsh | |
| run: flutter pub get | |
| - name: Build Windows release | |
| shell: pwsh | |
| env: | |
| KICK_APTABASE_APP_KEY_RELEASE: ${{ secrets.KICK_APTABASE_APP_KEY_RELEASE }} | |
| KICK_APTABASE_HOST_RELEASE: ${{ secrets.KICK_APTABASE_HOST_RELEASE }} | |
| SENTRY_DSN: ${{ secrets.SENTRY_DSN }} | |
| KICK_GLITCHTIP_TRACES_SAMPLE_RATE: ${{ secrets.KICK_GLITCHTIP_TRACES_SAMPLE_RATE }} | |
| run: | | |
| $flutterArgs = @('build', 'windows', '--release') | |
| if (-not [string]::IsNullOrWhiteSpace($env:KICK_APTABASE_APP_KEY_RELEASE)) { | |
| $flutterArgs += "--dart-define=KICK_APTABASE_APP_KEY_RELEASE=$($env:KICK_APTABASE_APP_KEY_RELEASE)" | |
| } | |
| if (-not [string]::IsNullOrWhiteSpace($env:KICK_APTABASE_HOST_RELEASE)) { | |
| $flutterArgs += "--dart-define=KICK_APTABASE_HOST_RELEASE=$($env:KICK_APTABASE_HOST_RELEASE)" | |
| } | |
| if (-not [string]::IsNullOrWhiteSpace($env:SENTRY_DSN)) { | |
| $flutterArgs += "--dart-define=SENTRY_DSN=$($env:SENTRY_DSN)" | |
| } | |
| $flutterArgs += "--dart-define=SENTRY_ENVIRONMENT=production" | |
| if (-not [string]::IsNullOrWhiteSpace($env:KICK_GLITCHTIP_TRACES_SAMPLE_RATE)) { | |
| $flutterArgs += "--dart-define=KICK_GLITCHTIP_TRACES_SAMPLE_RATE=$($env:KICK_GLITCHTIP_TRACES_SAMPLE_RATE)" | |
| } | |
| flutter @flutterArgs | |
| - name: Install Inno Setup | |
| shell: pwsh | |
| run: choco install innosetup --no-progress -y | |
| - name: Build Windows installer and portable bundle | |
| shell: pwsh | |
| run: | | |
| & .\scripts\build-windows-installer.ps1 ` | |
| -AppVersion '${{ needs.metadata.outputs.version }}' ` | |
| -SkipBuild | |
| - name: Upload Windows release artifacts | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: kick-windows-release | |
| path: build/dist/* | |
| if-no-files-found: error | |
| android-release: | |
| name: Build Android release artifacts | |
| runs-on: ubuntu-latest | |
| needs: metadata | |
| env: | |
| HAS_SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN != '' }} | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v6 | |
| with: | |
| ref: ${{ needs.metadata.outputs.ref }} | |
| - name: Set up Java | |
| uses: actions/setup-java@v5 | |
| with: | |
| distribution: temurin | |
| java-version: ${{ env.JAVA_VERSION }} | |
| - name: Set up Gradle cache | |
| uses: gradle/actions/setup-gradle@v5 | |
| - name: Set up Android SDK | |
| uses: android-actions/setup-android@v3 | |
| - name: Install Android SDK packages | |
| run: sdkmanager "platform-tools" "platforms;android-36" "build-tools;36.1.0" | |
| - name: Validate Android signing secrets | |
| env: | |
| KICK_ANDROID_KEYSTORE_BASE64: ${{ secrets.KICK_ANDROID_KEYSTORE_BASE64 }} | |
| KICK_ANDROID_KEYSTORE_PASSWORD: ${{ secrets.KICK_ANDROID_KEYSTORE_PASSWORD }} | |
| KICK_ANDROID_KEY_ALIAS: ${{ secrets.KICK_ANDROID_KEY_ALIAS }} | |
| KICK_ANDROID_KEY_PASSWORD: ${{ secrets.KICK_ANDROID_KEY_PASSWORD }} | |
| shell: bash | |
| run: | | |
| for secret_name in \ | |
| KICK_ANDROID_KEYSTORE_BASE64 \ | |
| KICK_ANDROID_KEYSTORE_PASSWORD \ | |
| KICK_ANDROID_KEY_ALIAS \ | |
| KICK_ANDROID_KEY_PASSWORD; do | |
| if [ -z "${!secret_name}" ]; then | |
| echo "Missing required secret: $secret_name" >&2 | |
| exit 1 | |
| fi | |
| done | |
| - name: Prepare Android signing config | |
| env: | |
| KICK_ANDROID_KEYSTORE_BASE64: ${{ secrets.KICK_ANDROID_KEYSTORE_BASE64 }} | |
| KICK_ANDROID_KEYSTORE_PASSWORD: ${{ secrets.KICK_ANDROID_KEYSTORE_PASSWORD }} | |
| KICK_ANDROID_KEY_ALIAS: ${{ secrets.KICK_ANDROID_KEY_ALIAS }} | |
| KICK_ANDROID_KEY_PASSWORD: ${{ secrets.KICK_ANDROID_KEY_PASSWORD }} | |
| shell: bash | |
| run: | | |
| keystore_path="$RUNNER_TEMP/kick-upload.jks" | |
| echo "$KICK_ANDROID_KEYSTORE_BASE64" | base64 --decode > "$keystore_path" | |
| { | |
| echo "KICK_ANDROID_KEYSTORE_PATH=$keystore_path" | |
| echo "KICK_ANDROID_KEYSTORE_PASSWORD=$KICK_ANDROID_KEYSTORE_PASSWORD" | |
| echo "KICK_ANDROID_KEY_ALIAS=$KICK_ANDROID_KEY_ALIAS" | |
| echo "KICK_ANDROID_KEY_PASSWORD=$KICK_ANDROID_KEY_PASSWORD" | |
| } >> "$GITHUB_ENV" | |
| - name: Set up Flutter | |
| uses: subosito/flutter-action@v2 | |
| with: | |
| channel: stable | |
| flutter-version: ${{ env.FLUTTER_VERSION }} | |
| cache: true | |
| - name: Install dependencies | |
| run: flutter pub get | |
| - name: Build Android release APK | |
| env: | |
| KICK_APTABASE_APP_KEY_RELEASE: ${{ secrets.KICK_APTABASE_APP_KEY_RELEASE }} | |
| KICK_APTABASE_HOST_RELEASE: ${{ secrets.KICK_APTABASE_HOST_RELEASE }} | |
| SENTRY_DSN: ${{ secrets.SENTRY_DSN }} | |
| KICK_GLITCHTIP_TRACES_SAMPLE_RATE: ${{ secrets.KICK_GLITCHTIP_TRACES_SAMPLE_RATE }} | |
| shell: bash | |
| run: | | |
| flutter_args=(build apk --release --target-platform android-arm,android-arm64) | |
| if [ -n "${KICK_APTABASE_APP_KEY_RELEASE:-}" ]; then | |
| flutter_args+=("--dart-define=KICK_APTABASE_APP_KEY_RELEASE=$KICK_APTABASE_APP_KEY_RELEASE") | |
| fi | |
| if [ -n "${KICK_APTABASE_HOST_RELEASE:-}" ]; then | |
| flutter_args+=("--dart-define=KICK_APTABASE_HOST_RELEASE=$KICK_APTABASE_HOST_RELEASE") | |
| fi | |
| if [ -n "${SENTRY_DSN:-}" ]; then | |
| flutter_args+=("--dart-define=SENTRY_DSN=$SENTRY_DSN") | |
| fi | |
| flutter_args+=("--dart-define=SENTRY_ENVIRONMENT=production") | |
| if [ -n "${KICK_GLITCHTIP_TRACES_SAMPLE_RATE:-}" ]; then | |
| flutter_args+=("--dart-define=KICK_GLITCHTIP_TRACES_SAMPLE_RATE=$KICK_GLITCHTIP_TRACES_SAMPLE_RATE") | |
| fi | |
| flutter "${flutter_args[@]}" | |
| - name: Build Android release App Bundle | |
| env: | |
| KICK_APTABASE_APP_KEY_RELEASE: ${{ secrets.KICK_APTABASE_APP_KEY_RELEASE }} | |
| KICK_APTABASE_HOST_RELEASE: ${{ secrets.KICK_APTABASE_HOST_RELEASE }} | |
| SENTRY_DSN: ${{ secrets.SENTRY_DSN }} | |
| KICK_GLITCHTIP_TRACES_SAMPLE_RATE: ${{ secrets.KICK_GLITCHTIP_TRACES_SAMPLE_RATE }} | |
| shell: bash | |
| run: | | |
| flutter_args=(build appbundle --release --target-platform android-arm,android-arm64) | |
| if [ -n "${KICK_APTABASE_APP_KEY_RELEASE:-}" ]; then | |
| flutter_args+=("--dart-define=KICK_APTABASE_APP_KEY_RELEASE=$KICK_APTABASE_APP_KEY_RELEASE") | |
| fi | |
| if [ -n "${KICK_APTABASE_HOST_RELEASE:-}" ]; then | |
| flutter_args+=("--dart-define=KICK_APTABASE_HOST_RELEASE=$KICK_APTABASE_HOST_RELEASE") | |
| fi | |
| if [ -n "${SENTRY_DSN:-}" ]; then | |
| flutter_args+=("--dart-define=SENTRY_DSN=$SENTRY_DSN") | |
| fi | |
| flutter_args+=("--dart-define=SENTRY_ENVIRONMENT=production") | |
| if [ -n "${KICK_GLITCHTIP_TRACES_SAMPLE_RATE:-}" ]; then | |
| flutter_args+=("--dart-define=KICK_GLITCHTIP_TRACES_SAMPLE_RATE=$KICK_GLITCHTIP_TRACES_SAMPLE_RATE") | |
| fi | |
| flutter "${flutter_args[@]}" | |
| - name: Install Sentry CLI | |
| if: ${{ env.HAS_SENTRY_AUTH_TOKEN == 'true' }} | |
| shell: bash | |
| run: curl -sL https://sentry.io/get-cli/ | bash | |
| - name: Upload Android debug files to GlitchTip | |
| if: ${{ env.HAS_SENTRY_AUTH_TOKEN == 'true' }} | |
| env: | |
| SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} | |
| SENTRY_URL: https://app.glitchtip.com/ | |
| SENTRY_ORG: kick | |
| SENTRY_PROJECT: kick | |
| shell: bash | |
| run: | | |
| chmod +x scripts/upload-android-debug-files.sh | |
| scripts/upload-android-debug-files.sh | |
| - name: Prepare Android release artifacts | |
| id: android_artifacts | |
| shell: bash | |
| run: | | |
| artifact_dir="build/dist/android" | |
| mkdir -p "$artifact_dir" | |
| cp build/app/outputs/flutter-apk/app-release.apk "$artifact_dir/kick-android-${{ needs.metadata.outputs.version }}.apk" | |
| cp build/app/outputs/bundle/release/app-release.aab "$artifact_dir/kick-android-${{ needs.metadata.outputs.version }}.aab" | |
| echo "artifact_dir=$artifact_dir" >> "$GITHUB_OUTPUT" | |
| - name: Upload Android release artifacts | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: kick-android-release | |
| path: ${{ steps.android_artifacts.outputs.artifact_dir }}/* | |
| if-no-files-found: error | |
| publish-release: | |
| name: Publish GitHub release | |
| runs-on: ubuntu-latest | |
| needs: | |
| - metadata | |
| - windows-release | |
| - android-release | |
| steps: | |
| - name: Checkout workflow sources | |
| uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 0 | |
| - name: Fetch tags | |
| shell: bash | |
| run: git fetch --force --tags origin | |
| - name: Download release artifacts | |
| uses: actions/download-artifact@v8 | |
| with: | |
| path: release-artifacts | |
| merge-multiple: true | |
| - name: Generate release notes | |
| shell: bash | |
| run: | | |
| chmod +x scripts/generate-release-notes.sh | |
| scripts/generate-release-notes.sh \ | |
| --tag "${{ needs.metadata.outputs.tag }}" \ | |
| --version "${{ needs.metadata.outputs.version }}" \ | |
| --repository "${{ github.repository }}" \ | |
| --template ".github/release_template.md" \ | |
| --output "release-notes.md" | |
| - name: Create or update GitHub release | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| tag_name: ${{ needs.metadata.outputs.tag }} | |
| body_path: release-notes.md | |
| overwrite_files: true | |
| files: | | |
| release-artifacts/**/*.zip | |
| release-artifacts/**/*.exe | |
| release-artifacts/**/*.apk | |
| release-artifacts/**/*.aab |