Skip to content

v1.1.12

v1.1.12 #29

name: Google Play Production Release
on:
release:
types:
- published
permissions:
contents: write
concurrency:
group: google-play-production
cancel-in-progress: false
env:
PACKAGE_NAME: com.yourssu.ssutime.v2
jobs:
publish:
name: Build and publish production release
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up JDK
uses: actions/setup-java@v4
with:
distribution: temurin
java-version: "21"
- name: Set up Gradle
uses: gradle/actions/setup-gradle@v4
- name: Validate required secrets
env:
PLAY_SERVICE_ACCOUNT_JSON: ${{ secrets.ANDROID_GOOGLE_SERVICE_JSON }}
FIREBASE_GOOGLE_SERVICES_JSON: ${{ secrets.ANDROID_FIREBASE_GOOGLE_SERVICES_JSON }}
UPLOAD_KEYSTORE_BASE64: ${{ secrets.ANDROID_UPLOAD_KEYSTORE_BASE64 }}
UPLOAD_KEYSTORE_PASSWORD: ${{ secrets.ANDROID_UPLOAD_KEYSTORE_PASSWORD }}
UPLOAD_KEY_ALIAS: ${{ secrets.ANDROID_UPLOAD_KEY_ALIAS }}
POSTHOG_API_KEY: ${{ secrets.POSTHOG_API_KEY }}
run: |
test -n "$PLAY_SERVICE_ACCOUNT_JSON" || { echo "::error::Missing ANDROID_GOOGLE_SERVICE_JSON secret."; exit 1; }
test -n "$FIREBASE_GOOGLE_SERVICES_JSON" || { echo "::error::Missing ANDROID_FIREBASE_GOOGLE_SERVICES_JSON secret for app/google-services.json."; exit 1; }
test -n "$UPLOAD_KEYSTORE_BASE64" || { echo "::error::Missing ANDROID_UPLOAD_KEYSTORE_BASE64 secret."; exit 1; }
test -n "$UPLOAD_KEYSTORE_PASSWORD" || { echo "::error::Missing ANDROID_UPLOAD_KEYSTORE_PASSWORD secret."; exit 1; }
test -n "$UPLOAD_KEY_ALIAS" || { echo "::error::Missing ANDROID_UPLOAD_KEY_ALIAS secret."; exit 1; }
test -n "$POSTHOG_API_KEY" || { echo "::error::Missing POSTHOG_API_KEY secret."; exit 1; }
- name: Materialize private Android files
env:
FIREBASE_GOOGLE_SERVICES_JSON: ${{ secrets.ANDROID_FIREBASE_GOOGLE_SERVICES_JSON }}
UPLOAD_KEYSTORE_BASE64: ${{ secrets.ANDROID_UPLOAD_KEYSTORE_BASE64 }}
run: |
printf '%s' "$FIREBASE_GOOGLE_SERVICES_JSON" > app/google-services.json
printf '%s' "$UPLOAD_KEYSTORE_BASE64" | base64 --decode > "$RUNNER_TEMP/upload-keystore.jks"
- name: Create Play release notes
env:
RELEASE_BODY: ${{ github.event.release.body }}
run: |
node <<'NODE'
const fs = require('fs');
const requiredSections = [
{ locale: 'en-US', title: 'English', headings: ['english', 'en', 'en-us'] },
{ locale: 'ko-KR', title: '한국어', headings: ['한국어', 'korean', 'ko', 'ko-kr'] },
];
const headingToLocale = new Map();
for (const section of requiredSections) {
for (const heading of section.headings) {
headingToLocale.set(normalizeHeading(heading), section.locale);
}
}
const body = (process.env.RELEASE_BODY || '').replace(/\r\n/g, '\n').trim();
const sections = new Map(requiredSections.map((section) => [section.locale, '']));
let currentLocale = null;
for (const line of body.split('\n')) {
const headingMatch = line.match(/^#{2,6}\s+(.+?)\s*#*\s*$/);
if (headingMatch) {
const locale = headingToLocale.get(normalizeHeading(headingMatch[1]));
if (locale) {
currentLocale = locale;
continue;
}
}
if (currentLocale) {
sections.set(currentLocale, sections.get(currentLocale) + line + '\n');
}
}
const missingSections = requiredSections.filter((section) => !sections.get(section.locale).trim());
if (missingSections.length > 0) {
const missing = missingSections.map((section) => '## ' + section.title).join(', ');
console.error('::error::Missing required release note section(s): ' + missing);
process.exit(1);
}
fs.mkdirSync('distribution/whatsnew', { recursive: true });
for (const section of requiredSections) {
const notes = Array.from(sections.get(section.locale).trim()).slice(0, 500).join('');
fs.writeFileSync('distribution/whatsnew/whatsnew-' + section.locale, notes + '\n');
console.log('Created Play release notes for ' + section.locale + '.');
}
function normalizeHeading(value) {
return value.trim().toLowerCase();
}
NODE
- name: Build release APK and AAB
env:
ANDROID_KEYSTORE_PATH: ${{ runner.temp }}/upload-keystore.jks
ANDROID_KEYSTORE_PASSWORD: ${{ secrets.ANDROID_UPLOAD_KEYSTORE_PASSWORD }}
ANDROID_KEY_ALIAS: ${{ secrets.ANDROID_UPLOAD_KEY_ALIAS }}
ANDROID_KEY_PASSWORD: ${{ secrets.ANDROID_UPLOAD_KEY_PASSWORD }}
POSTHOG_API_KEY: ${{ secrets.POSTHOG_API_KEY }}
run: ./gradlew --no-daemon clean test assembleRelease bundleRelease
- name: Attach build outputs to GitHub Release
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ github.event.release.tag_name }}
files: |
app/build/outputs/apk/release/*.apk
app/build/outputs/bundle/release/app-release.aab
- name: Upload AAB to Google Play production
uses: r0adkll/upload-google-play@v1
with:
serviceAccountJsonPlainText: ${{ secrets.ANDROID_GOOGLE_SERVICE_JSON }}
packageName: ${{ env.PACKAGE_NAME }}
releaseFiles: app/build/outputs/bundle/release/app-release.aab
tracks: production
status: completed
releaseName: ${{ github.event.release.tag_name }}
inAppUpdatePriority: 0
whatsNewDirectory: distribution/whatsnew
mappingFile: app/build/outputs/mapping/release/mapping.txt
changesNotSentForReview: false