name: Release APK on: push: tags: - 'v*.*.*' workflow_dispatch: concurrency: group: build-android-${{ github.ref }} cancel-in-progress: true jobs: build: if: github.server_url == 'https://github.com' runs-on: ubuntu-latest timeout-minutes: 60 permissions: contents: write steps: - name: Free disk space run: | sudo rm -rf /usr/share/dotnet /usr/local/share/boost /opt/ghc sudo rm -rf /usr/local/share/chromium /usr/local/share/powershell sudo rm -rf /usr/share/swift /usr/local/julia* sudo apt-get autoremove -y > /dev/null 2>&1 sudo apt-get clean - uses: actions/checkout@v4 - uses: actions/setup-java@v4 with: distribution: temurin java-version: '17' - uses: actions/setup-node@v4 with: node-version: '20' cache: 'npm' - name: Install dependencies run: npm ci - name: Accept Android SDK licenses run: yes | "$ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager" --licenses || true - name: Install SDK components run: | "$ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager" \ "platform-tools" "platforms;android-35" "build-tools;35.0.0" - name: Cache Gradle uses: actions/cache@v4 with: path: | ~/.gradle/caches ~/.gradle/wrapper key: ${{ runner.os }}-gradle-${{ hashFiles('package.json') }} restore-keys: | ${{ runner.os }}-gradle- - name: Decode keystore env: KEYSTORE_B64: ${{ secrets.KEYSTORE_B64 }} KEYSTORE_ALIAS: ${{ secrets.KEYSTORE_ALIAS }} KEYSTORE_STORE_PASSWORD: ${{ secrets.KEYSTORE_STORE_PASSWORD }} KEYSTORE_KEY_PASSWORD: ${{ secrets.KEYSTORE_KEY_PASSWORD }} run: | mkdir -p ~/.config/sheethappens echo "$KEYSTORE_B64" | base64 -d > ~/.config/sheethappens/sheethappens.jks { printf 'KEYSTORE_PATH=%s\n' "$HOME/.config/sheethappens/sheethappens.jks" printf 'KEYSTORE_ALIAS=%q\n' "$KEYSTORE_ALIAS" printf 'KEYSTORE_STORE_PASSWORD=%q\n' "$KEYSTORE_STORE_PASSWORD" printf 'KEYSTORE_KEY_PASSWORD=%q\n' "$KEYSTORE_KEY_PASSWORD" } > ~/.config/sheethappens/signing.env chmod 600 ~/.config/sheethappens/signing.env ~/.config/sheethappens/sheethappens.jks - name: Verify signing.env run: | echo "Keys present in signing.env:" grep -o '^[^=]*' ~/.config/sheethappens/signing.env source ~/.config/sheethappens/signing.env [ -n "$KEYSTORE_PATH" ] && echo "KEYSTORE_PATH: set" || echo "KEYSTORE_PATH: EMPTY" [ -n "$KEYSTORE_ALIAS" ] && echo "KEYSTORE_ALIAS: set" || echo "KEYSTORE_ALIAS: EMPTY" [ -n "$KEYSTORE_STORE_PASSWORD" ] && echo "KEYSTORE_STORE_PASSWORD: set" || echo "KEYSTORE_STORE_PASSWORD: EMPTY" [ -n "$KEYSTORE_KEY_PASSWORD" ] && echo "KEYSTORE_KEY_PASSWORD: set" || echo "KEYSTORE_KEY_PASSWORD: EMPTY" - name: Patch native modules for Android 15 16KB page size run: | WORKLETS="node_modules/react-native-worklets/android/CMakeLists.txt" REANIMATED="node_modules/react-native-reanimated/android/CMakeLists.txt" if [ -f "$WORKLETS" ] && ! grep -q "max-page-size" "$WORKLETS"; then printf '\ntarget_link_options(worklets PRIVATE "-Wl,-z,max-page-size=16384")\n' >> "$WORKLETS" fi if [ -f "$REANIMATED" ] && ! grep -q "max-page-size" "$REANIMATED"; then printf '\ntarget_link_options(reanimated PRIVATE "-Wl,-z,max-page-size=16384")\n' >> "$REANIMATED" fi - name: Build signed APK run: ./build-apk.sh - name: Find built APK id: apk run: | APK=$(ls dist/*.apk | sort | tail -1) echo "path=$APK" >> "$GITHUB_OUTPUT" - name: Generate changelog id: changelog run: | PREV_TAG=$(git tag --sort=-version:refname | grep -v "^${{ github.ref_name }}$" | head -1) echo "Previous tag: $PREV_TAG" echo "prev_tag=$PREV_TAG" >> "$GITHUB_OUTPUT" FEATS=$(git log "${PREV_TAG}..HEAD" --pretty=format:"%s" --no-merges \ | grep -E "^feat(\([^)]+\))?: " \ | sed -E 's/^feat(\([^)]+\))?: //' \ | sed 's/^/- /') FIXES=$(git log "${PREV_TAG}..HEAD" --pretty=format:"%s" --no-merges \ | grep -E "^fix(\([^)]+\))?: " \ | sed -E 's/^fix(\([^)]+\))?: //' \ | sed 's/^/- /') { echo "changelog<> "$GITHUB_OUTPUT" - name: Create GitHub Release uses: softprops/action-gh-release@v2 with: name: "SheetHappens ${{ github.ref_name }}" body: | ## SheetHappens ${{ github.ref_name }} ${{ steps.changelog.outputs.changelog }} [Full changelog](https://github.com/${{ github.repository }}/compare/${{ steps.changelog.outputs.prev_tag }}...${{ github.ref_name }}) · [CHANGELOG.md](https://github.com/${{ github.repository }}/blob/main/CHANGELOG.md) ### Installation 1. Enable "Unknown sources" on the device 2. Transfer the APK to the device and open it to install files: ${{ steps.apk.outputs.path }} draft: false prerelease: ${{ contains(github.ref_name, '-') }} - name: Create Gitea Release env: GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }} TAG: ${{ github.ref_name }} PREV_TAG: ${{ steps.changelog.outputs.prev_tag }} CHANGELOG: ${{ steps.changelog.outputs.changelog }} GH_REPO: ${{ github.repository }} run: | if [ -z "$GITEA_TOKEN" ]; then echo "GITEA_TOKEN not set — skipping Gitea release" exit 0 fi BODY="## SheetHappens ${TAG} ${CHANGELOG} [Full changelog](https://homegit.gyozamancave.fr/billisdead/SheetHappens/compare/${PREV_TAG}...${TAG}) · [CHANGELOG.md](https://homegit.gyozamancave.fr/billisdead/SheetHappens/raw/branch/main/CHANGELOG.md) ### Installation Download the APK from the [GitHub release](https://github.com/${GH_REPO}/releases/tag/${TAG}), enable \"Unknown sources\" on the device and install." curl -sf -X POST \ -H "Authorization: token ${GITEA_TOKEN}" \ -H "Content-Type: application/json" \ "https://homegit.gyozamancave.fr/api/v1/repos/billisdead/SheetHappens/releases" \ -d "{ \"tag_name\": \"${TAG}\", \"name\": \"SheetHappens ${TAG}\", \"body\": $(printf '%s' "$BODY" | jq -Rs .), \"draft\": false, \"prerelease\": $([ "${TAG#*-}" != "${TAG}" ] && echo true || echo false) }"