Skip to content

docs: add 2.2.0 changelog entry #81

docs: add 2.2.0 changelog entry

docs: add 2.2.0 changelog entry #81

Workflow file for this run

name: CD Pipeline
on:
push:
branches: [main]
tags: ["v*"]
paths-ignore:
- "docs/**"
- "*.md"
- ".github/**"
- ".kiro/**"
workflow_dispatch:
inputs:
version_name:
description: "Version name for the release"
required: false
default: "manual-build"
permissions:
contents: write
packages: write
jobs:
build-and-deploy:
name: Build and Deploy
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
persist-credentials: false
- name: Extract version and determine deployment
id: version
env:
GITHUB_REF: ${{ github.ref }}
GITHUB_REF_NAME: ${{ github.ref_name }}
GITHUB_RUN_NUMBER: ${{ github.run_number }}
VERSION_NAME_INPUT: ${{ github.event.inputs.version_name }}
run: |
if [[ "$GITHUB_REF" == refs/tags/v* ]]; then
VERSION_NAME="$GITHUB_REF_NAME"
VERSION_NAME="${VERSION_NAME#v}" # Remove 'v' prefix
DEPLOY_TARGET="production"
IS_TAG_BUILD="true"
echo "Tag build detected: $VERSION_NAME -> production release"
elif [[ "$GITHUB_REF" == refs/heads/main ]]; then
VERSION_NAME="main-$GITHUB_RUN_NUMBER"
DEPLOY_TARGET="beta"
IS_TAG_BUILD="false"
echo "Main branch build: $VERSION_NAME -> open testing"
else
if [[ -z "$VERSION_NAME_INPUT" ]]; then
VERSION_NAME="manual-build"
else
VERSION_NAME="$VERSION_NAME_INPUT"
fi
DEPLOY_TARGET="internal"
IS_TAG_BUILD="false"
echo "Manual build: $VERSION_NAME -> internal testing"
fi
echo "version_name=$VERSION_NAME" >> $GITHUB_OUTPUT
echo "deploy_target=$DEPLOY_TARGET" >> $GITHUB_OUTPUT
echo "is_tag_build=$IS_TAG_BUILD" >> $GITHUB_OUTPUT
- name: Set Version
uses: chkfung/android-version-actions@fcf89abef1c7afba2083146dcca0c6da4705ba4b
with:
gradlePath: app/build.gradle.kts
versionCode: ${{ github.run_number }}
versionName: ${{ steps.version.outputs.version_name }}
- name: Set up JDK 17
uses: actions/setup-java@v4
with:
java-version: "17"
distribution: "temurin"
- name: Cache Gradle dependencies
uses: actions/cache@v4
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
restore-keys: |
${{ runner.os }}-gradle-
save: false
lookup-only: true
- name: Grant execute permission for gradlew
run: chmod +x gradlew
- name: Build prod release APK and AAB
run: |
./gradlew assembleProdRelease bundleProdRelease
env:
SIGNING_KEY_BASE64: ${{ secrets.SIGNING_KEY }}
KEY_ALIAS: ${{ secrets.KEY_ALIAS }}
KEY_STORE_PASSWORD: ${{ secrets.KEY_STORE_PASSWORD }}
KEY_PASSWORD: ${{ secrets.KEY_PASSWORD }}
- name: Prepare release artifacts
id: artifacts
run: |
# Find the generated files (Gradle handles the naming)
APK_PATH=$(find app/build/outputs/apk/prod/release -name "*.apk" | head -1)
AAB_PATH=$(find app/build/outputs/bundle/prodRelease -name "*.aab" | head -1)
# Extract the actual filenames generated by Gradle
APK_NAME=$(basename "$APK_PATH")
AAB_NAME=$(basename "$AAB_PATH")
echo "apk_path=$APK_PATH" >> $GITHUB_OUTPUT
echo "aab_path=$AAB_PATH" >> $GITHUB_OUTPUT
- name: Upload build artifacts
uses: actions/upload-artifact@v4
with:
name: coffee-shot-timer-${{ steps.version.outputs.version_name }}
path: |
${{ steps.artifacts.outputs.apk_path }}
${{ steps.artifacts.outputs.aab_path }}
- name: Generate GitHub release notes
id: gen_release_notes
env:
VERSION_NAME_OUTPUT: ${{ steps.version.outputs.version_name }}
IS_TAG_BUILD_OUTPUT: ${{ steps.version.outputs.is_tag_build }}
run: |
set -euo pipefail
VERSION_NAME="$VERSION_NAME_OUTPUT"
IS_TAG_BUILD="$IS_TAG_BUILD_OUTPUT"
NOTES_FILE="RELEASE_NOTES.md"
if [[ ! -f CHANGELOG.md ]]; then
echo "ERROR: CHANGELOG.md not found."
exit 1
fi
# Extract notes for tag builds from the matching version section, otherwise from [Unreleased]
if [[ "$IS_TAG_BUILD" == "true" ]]; then
awk -v v="$VERSION_NAME" '
BEGIN{p=0}
/^## \[/{
if (p==1) exit
if ($0 ~ "^## \\[(" v ")\\]") p=1
}
p==1{print}
' CHANGELOG.md | sed '1d' | sed '/^## \[/Q' > "$NOTES_FILE"
else
awk '
BEGIN{p=0}
/^## \[/{
if (p==1) exit
if ($0 ~ /^## \[Unreleased\]/) p=1
}
p==1{print}
' CHANGELOG.md | sed '1d' | sed '/^## \[/Q' > "$NOTES_FILE"
fi
# Fail if notes are empty after extraction
if [[ ! -s "$NOTES_FILE" ]]; then
echo "ERROR: Release notes are empty. Ensure the appropriate section exists in CHANGELOG.md."
exit 1
fi
echo "notes_file=$NOTES_FILE" >> $GITHUB_OUTPUT
- name: Print extracted release notes
env:
NOTES_FILE_OUTPUT: ${{ steps.gen_release_notes.outputs.notes_file }}
run: |
echo "=== Extracted release notes ($NOTES_FILE_OUTPUT) ==="
cat "$NOTES_FILE_OUTPUT"
echo "=== End of release notes ==="
- name: Create or update GitHub release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
VERSION_NAME_OUTPUT: ${{ steps.version.outputs.version_name }}
IS_TAG_BUILD_OUTPUT: ${{ steps.version.outputs.is_tag_build }}
APK_PATH_OUTPUT: ${{ steps.artifacts.outputs.apk_path }}
AAB_PATH_OUTPUT: ${{ steps.artifacts.outputs.aab_path }}
NOTES_FILE_OUTPUT: ${{ steps.gen_release_notes.outputs.notes_file }}
run: |
VERSION_NAME="$VERSION_NAME_OUTPUT"
IS_TAG_BUILD="$IS_TAG_BUILD_OUTPUT"
APK_PATH="$APK_PATH_OUTPUT"
AAB_PATH="$AAB_PATH_OUTPUT"
NOTES_FILE="$NOTES_FILE_OUTPUT"
if [[ "$IS_TAG_BUILD" == "true" ]]; then
# Tag build - create new release
TAG_NAME="v${VERSION_NAME}"
RELEASE_TITLE="Coffee Shot Timer v${VERSION_NAME}"
echo "Creating tag release: $TAG_NAME"
gh release create "$TAG_NAME" \
--title "$RELEASE_TITLE" \
--notes-file "$NOTES_FILE" \
"$APK_PATH" \
"$AAB_PATH"
echo "Created release: $RELEASE_TITLE"
else
# Main branch build - replace existing main release
RELEASE_TAG="main-latest"
RELEASE_TITLE="Coffee Shot Timer (Latest Main)"
echo "Creating/updating main release: $RELEASE_TAG"
# Delete existing release if it exists
if gh release view "$RELEASE_TAG" > /dev/null 2>&1; then
echo "Deleting existing main release..."
gh release delete "$RELEASE_TAG" --yes
fi
# Create new release
gh release create "$RELEASE_TAG" \
--title "$RELEASE_TITLE" \
--notes-file "$NOTES_FILE" \
--prerelease \
"$APK_PATH" \
"$AAB_PATH"
echo "Created/updated main release: $RELEASE_TITLE"
fi
- name: Prepare Play Store what's new (en-US)
id: play_whatsnew
env:
VERSION_NAME_OUTPUT: ${{ steps.version.outputs.version_name }}
IS_TAG_BUILD_OUTPUT: ${{ steps.version.outputs.is_tag_build }}
run: |
set -euo pipefail
VERSION_NAME="$VERSION_NAME_OUTPUT"
IS_TAG_BUILD="$IS_TAG_BUILD_OUTPUT"
WHATSNEW_DIR="whatsnew"
mkdir -p "$WHATSNEW_DIR"
# Determine which version to extract from CHANGELOG.md
if [[ "$IS_TAG_BUILD" == "true" ]]; then
EXTRACT_VERSION="$VERSION_NAME"
else
EXTRACT_VERSION="unreleased"
fi
# Use the extract-whatsnew.sh script to get priority items (or all items if no priorities)
# This extracts items marked with [*] in CHANGELOG.md for Play Store
./scripts/extract-whatsnew.sh "$EXTRACT_VERSION" 500 > "$WHATSNEW_DIR/whatsnew-en-US"
# Verify the extraction worked
if [[ ! -s "$WHATSNEW_DIR/whatsnew-en-US" ]]; then
echo "ERROR: Failed to extract Play Store release notes from CHANGELOG.md"
exit 1
fi
# Character count is already enforced by the script (max 500)
CHAR_COUNT=$(wc -m < "$WHATSNEW_DIR/whatsnew-en-US" | tr -d ' ')
echo "Play Store release notes: $CHAR_COUNT characters"
echo "=== Play Store What's New (en-US) ==="
cat "$WHATSNEW_DIR/whatsnew-en-US"
echo "=== End of What's New ==="
echo "whatsnew_dir=$WHATSNEW_DIR" >> $GITHUB_OUTPUT
- name: Deploy to Google Play Console
uses: r0adkll/upload-google-play@935ef9c68bb393a8e6116b1575626a7f5be3a7fb
with:
serviceAccountJsonPlainText: ${{ secrets.GOOGLE_PLAY_SERVICE_ACCOUNT_JSON }}
packageName: com.jodli.coffeeshottimer
releaseFiles: ${{ steps.artifacts.outputs.aab_path }}
track: ${{ steps.version.outputs.deploy_target }}
inAppUpdatePriority: 2
whatsNewDirectory: ${{ steps.play_whatsnew.outputs.whatsnew_dir }}