-
-
Notifications
You must be signed in to change notification settings - Fork 268
154 lines (131 loc) · 6.26 KB
/
Copy pathrelease.yml
File metadata and controls
154 lines (131 loc) · 6.26 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
name: Build and Release Android
# NOTE: The iOS workflow (release-ios.yml) triggers via workflow_run on this workflow.
# If you rename this workflow, update the workflow_run trigger in release-ios.yml.
on:
push:
branches: [main] # every merge to main cuts a release
workflow_dispatch: {} # manual fallback
permissions:
contents: write
jobs:
release:
runs-on: ubuntu-latest
# Lift store secrets to job-level env so the `if:` guards on the Play steps can test
# for their presence (if: conditions can read env, not secrets directly). Absent
# secrets => empty => Play upload steps skip, GitHub Release path still runs.
env:
ANDROID_KEYSTORE_BASE64: ${{ secrets.ANDROID_KEYSTORE_BASE64 }}
PLAY_STORE_JSON_KEY: ${{ secrets.PLAY_STORE_JSON_KEY }}
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
token: ${{ secrets.GITHUB_TOKEN }}
fetch-depth: 0 # Fetch all history for changelog
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- name: Setup Java
uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: '17'
- name: Setup Android SDK
uses: android-actions/setup-android@v3
- name: Setup Ruby (fastlane)
uses: ruby/setup-ruby@v1
with:
ruby-version: '3.3'
bundler-cache: true
- name: Cache Gradle
uses: actions/cache@v4
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
restore-keys: gradle-
- name: Install dependencies
run: npm ci
- name: Bump patch version
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
npm version patch --no-git-tag-version
NEW_VERSION=$(node -p "require('./package.json').version")
echo "NEW_VERSION=$NEW_VERSION" >> $GITHUB_ENV
# Update Android versionCode and versionName
VERSION_CODE=$(date +%s)
echo "VERSION_CODE=$VERSION_CODE" >> $GITHUB_ENV
# Update build.gradle
sed -i "s/versionCode .*/versionCode $VERSION_CODE/" android/app/build.gradle
sed -i "s/versionName .*/versionName \"$NEW_VERSION\"/" android/app/build.gradle
git add package.json package-lock.json android/app/build.gradle
git commit -m "chore: bump version to $NEW_VERSION [skip ci]"
git push
- name: Generate release notes
run: |
# Get commits since last tag (or all commits if no tags)
LAST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "")
if [ -z "$LAST_TAG" ]; then
COMMITS=$(git log --pretty=format:"- %s (%h)" --no-merges -20)
else
COMMITS=$(git log ${LAST_TAG}..HEAD --pretty=format:"- %s (%h)" --no-merges)
fi
# Write release notes
echo "## What's Changed" > release-notes.md
echo "" >> release-notes.md
echo "$COMMITS" >> release-notes.md
echo "" >> release-notes.md
echo "**Full Changelog**: https://github.com/${{ github.repository }}/compare/${LAST_TAG:-v0.0.0}...v${{ env.NEW_VERSION }}" >> release-notes.md
cat release-notes.md
- name: Build Android Release APK
run: |
cd android
./gradlew assembleRelease
- name: Rename APK
run: |
mv android/app/build/outputs/apk/release/app-release.apk \
android/app/build/outputs/apk/release/OffgridMobile-v${{ env.NEW_VERSION }}.apk
- name: Create GitHub Release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
gh release create v${{ env.NEW_VERSION }} \
android/app/build/outputs/apk/release/OffgridMobile-v${{ env.NEW_VERSION }}.apk \
--title "Off Grid v${{ env.NEW_VERSION }}" \
--notes-file release-notes.md
- name: Upload APK artifact
uses: actions/upload-artifact@v4
with:
name: OffgridMobile-v${{ env.NEW_VERSION }}
# No product flavors, so the APK lives under apk/release/ (not apk/standard/release/).
path: android/app/build/outputs/apk/release/OffgridMobile-v${{ env.NEW_VERSION }}.apk
if-no-files-found: error
# ── Play Store upload (in addition to the GitHub Release above) ──────────
# Decodes the production keystore + Play service-account key from secrets, builds
# a signed AAB, and uploads to the Play production track as a DRAFT (a human
# confirms rollout in the Play Console). Skipped automatically if the secrets are
# absent, so the GitHub Release path still works without them.
- name: Decode signing secrets
if: ${{ env.ANDROID_KEYSTORE_BASE64 != '' && env.PLAY_STORE_JSON_KEY != '' }}
run: |
echo "$ANDROID_KEYSTORE_BASE64" | base64 --decode > "$RUNNER_TEMP/release.keystore"
# PLAY_STORE_JSON_KEY may be stored raw-JSON or base64 — handle both (matches uat-dev.yml).
echo "$PLAY_STORE_JSON_KEY" | base64 --decode > "$RUNNER_TEMP/play-key.json" \
|| printf '%s' "$PLAY_STORE_JSON_KEY" > "$RUNNER_TEMP/play-key.json"
echo "PLAY_UPLOAD=1" >> $GITHUB_ENV
- name: Build signed AAB + upload to Play (draft)
if: ${{ env.PLAY_UPLOAD == '1' }}
env:
PLAY_STORE_JSON_KEY_PATH: ${{ runner.temp }}/play-key.json
# build.gradle gates release signing on project.hasProperty(...), so these must be
# Gradle PROJECT properties (ORG_GRADLE_PROJECT_<name>), not plain env — otherwise
# the AAB falls back to debug signing and Play rejects it.
ORG_GRADLE_PROJECT_OFFGRID_UPLOAD_STORE_FILE: ${{ runner.temp }}/release.keystore
ORG_GRADLE_PROJECT_OFFGRID_UPLOAD_STORE_PASSWORD: ${{ secrets.ANDROID_KEYSTORE_PASSWORD }}
ORG_GRADLE_PROJECT_OFFGRID_UPLOAD_KEY_ALIAS: ${{ secrets.ANDROID_KEY_ALIAS }}
ORG_GRADLE_PROJECT_OFFGRID_UPLOAD_KEY_PASSWORD: ${{ secrets.ANDROID_KEY_PASSWORD }}
run: bundle exec fastlane android release