commit 7acb692d76f562d49491c1820374f24948ec4fdf
parent 3ea11ae93e48c8a4c3b171dd4e04246d3cce581d
Author: Amit Dutta <mail@amit.is-a.dev>
Date: Fri, 28 Aug 2026 20:40:30 +0530
Merge pull request #104 from notamitgamer/copilot/fix-apk-content-job
Initial plan
Diffstat:
2 files changed, 3 insertions(+), 321 deletions(-)
diff --git a/.github/workflows/build-apk.yml b/.github/workflows/build-apk.yml
@@ -1,196 +0,0 @@
-name: Build Offline APK
-
-on:
- workflow_dispatch:
- inputs:
- release_tag:
- description: 'Release tag to attach the APK to (created if it does not exist)'
- required: false
- default: 'apk-latest'
-
-permissions:
- contents: write
-
-jobs:
- build-apk:
- runs-on: ubuntu-latest
- steps:
- - name: Resolve release tag
- id: tag
- run: |
- echo "value=${{ inputs.release_tag || 'apk-latest' }}" >> "$GITHUB_OUTPUT"
-
- - name: Checkout
- uses: actions/checkout@v4
-
- - name: Setup Node
- uses: actions/setup-node@v4
- with:
- node-version: 20
- cache: 'npm'
-
- - name: Install site deps
- run: npm ci
-
- - name: Setup Python
- uses: actions/setup-python@v5
- with:
- python-version: '3.13'
-
- - name: Generate markdown files
- run: |
- python list.py
- python main.py
-
- - name: Build VitePress site
- run: npm run docs:build
-
- - name: Set up JDK 21
- uses: actions/setup-java@v4
- with:
- distribution: 'temurin'
- java-version: '21'
-
- - name: Scaffold Capacitor Android project
- run: |
- mkdir -p apk-build
- cd apk-build
- npm init -y
- npm install @capacitor/core @capacitor/cli @capacitor/android @capgo/capacitor-updater @capacitor/assets
-
- mkdir -p www
- cp -r ../docs/.vitepress/dist/. www/
-
- cat > capacitor.config.json <<'EOF'
- {
- "appId": "dev.amit.bsc",
- "appName": "BSc Code Index",
- "webDir": "www",
- "bundledWebRuntime": false,
- "plugins": {
- "CapacitorUpdater": {
- "autoUpdate": true,
- "updateUrl": "https://raw.githubusercontent.com/notamitgamer/bsc/main/apk-manifest/manifest.json"
- }
- }
- }
- EOF
-
- npx cap add android
- npx cap sync android
-
- - name: Generate Capacitor Assets (App Icon & Splash)
- run: |
- mkdir -p apk-build/assets
- # Copy the 512x512 logo to the assets folder as icon and splash targets
- cp docs/public/logo_512.png apk-build/assets/icon.png
- cp docs/public/logo_512.png apk-build/assets/splash.png
- cd apk-build
- npx @capacitor/assets generate --android
-
- - name: Bump Android compile SDK for okhttp-android
- working-directory: apk-build/android
- run: |
- sed -Ei 's/(compileSdkVersion\s*=\s*)[0-9]+/\136/' variables.gradle
- echo "android.suppressUnsupportedCompileSdk=36" >> gradle.properties
-
- - name: Decode signing keystore
- working-directory: apk-build/android/app
- env:
- ANDROID_KEYSTORE_BASE64: ${{ secrets.ANDROID_KEYSTORE_BASE64 }}
- run: echo "$ANDROID_KEYSTORE_BASE64" | base64 -d > release.keystore
-
- - name: Add signing config to Gradle
- working-directory: apk-build/android/app
- env:
- ANDROID_KEYSTORE_PASSWORD: ${{ secrets.ANDROID_KEYSTORE_PASSWORD }}
- ANDROID_KEY_ALIAS: ${{ secrets.ANDROID_KEY_ALIAS }}
- ANDROID_KEY_PASSWORD: ${{ secrets.ANDROID_KEY_PASSWORD }}
- run: |
- cat > keystore.properties <<EOF
- storeFile=release.keystore
- storePassword=${ANDROID_KEYSTORE_PASSWORD}
- keyAlias=${ANDROID_KEY_ALIAS}
- keyPassword=${ANDROID_KEY_PASSWORD}
- EOF
-
- python3 - <<'PYEOF'
- import re
- path = "build.gradle"
- with open(path) as f:
- content = f.read()
-
- props_load = (
- "def keystoreProperties = new Properties()\n"
- "def keystorePropertiesFile = rootProject.file('app/keystore.properties')\n"
- "if (keystorePropertiesFile.exists()) {\n"
- " keystoreProperties.load(new FileInputStream(keystorePropertiesFile))\n"
- "}\n\n"
- )
- if "keystoreProperties" not in content:
- content = props_load + content
-
- signing_block = (
- " signingConfigs {\n"
- " release {\n"
- " storeFile file(keystoreProperties['storeFile'])\n"
- " storePassword keystoreProperties['storePassword']\n"
- " keyAlias keystoreProperties['keyAlias']\n"
- " keyPassword keystoreProperties['keyPassword']\n"
- " }\n"
- " }\n"
- )
- content = re.sub(
- r"(android\s*\{)",
- r"\1\n" + signing_block,
- content,
- count=1,
- )
-
- content = re.sub(
- r"(buildTypes\s*\{\s*release\s*\{)",
- r"\1\n signingConfig signingConfigs.release",
- content,
- count=1,
- )
-
- with open(path, "w") as f:
- f.write(content)
- PYEOF
-
- - name: Build signed release APK
- working-directory: apk-build/android
- run: |
- chmod +x ./gradlew
- ./gradlew assembleRelease --no-daemon
-
- - name: Locate APK
- id: apk
- run: |
- APK_PATH=$(find apk-build/android -path "*release*" -name "*.apk" | head -n 1)
- echo "path=$APK_PATH" >> "$GITHUB_OUTPUT"
-
- - name: Upload APK as workflow artifact
- uses: actions/upload-artifact@v4
- with:
- name: bsc-offline-apk
- path: ${{ steps.apk.outputs.path }}
-
- - name: Publish to GitHub Release
- id: release
- uses: softprops/action-gh-release@v2
- with:
- tag_name: ${{ steps.tag.outputs.value }}
- name: Offline APK build (${{ github.run_number }})
- body: |
- Signed offline Android APK of the BSc code index site.
-
- - Release-signed with the repo's dedicated keystore.
- - Works fully offline after install.
- - Auto-pulls newer content when online, via the manifest at
- apk-manifest/manifest.json (raw.githubusercontent.com) —
- kept up to date on every push by main.yml's apk-content job,
- independently of this shell build.
- files: |
- ${{ steps.apk.outputs.path }}
- prerelease: true
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
@@ -129,14 +129,8 @@ jobs:
with:
path: docs/.vitepress/dist
- - name: Upload dist for APK content job
- uses: actions/upload-artifact@v4
- with:
- name: site-dist
- path: docs/.vitepress/dist
- retention-days: 1
-
- - name: Commit generated changelog
+ # Step 5: Save your files back to the branch only when deployment wraps up completely
+ - name: Commit generated changelog to repo
run: |
git config user.name "bot-for-notamitgamer[bot]"
git config user.email "bot-for-notamitgamer[bot]@users.noreply.github.com"
@@ -150,123 +144,7 @@ jobs:
echo "No changelog changes"
fi
- apk-content:
- runs-on: ubuntu-latest
- if: github.actor != 'bot-for-notamitgamer[bot]'
- needs: build
-
- permissions:
- contents: write
-
- steps:
-
- - name: Checkout latest main
- uses: actions/checkout@v7
- with:
- fetch-depth: 0
-
- - name: Download built site
- uses: actions/download-artifact@v4
- with:
- name: site-dist
- path: dist
-
- - name: Package content bundle
- id: bundle
- run: |
- cd dist
-
- zip -qr ../bundle.zip .
-
- cd ..
-
- CHECKSUM=$(sha256sum bundle.zip | cut -d' ' -f1)
-
- echo "checksum=$CHECKSUM" >> "$GITHUB_OUTPUT"
- echo "version=${{ github.run_number }}" >> "$GITHUB_OUTPUT"
-
- echo "Bundle checksum: $CHECKSUM"
- echo "Bundle version: ${{ github.run_number }}"
-
- - name: Publish content bundle to release
- uses: softprops/action-gh-release@v2
- with:
- tag_name: apk-content
- name: APK content bundle (latest)
- body: |
- Latest site content bundle for the offline APK's auto-updater.
-
- This is not a standalone release.
- It provides the bundle used by:
-
- apk-manifest/manifest.json
- files: bundle.zip
- prerelease: true
- overwrite_files: true
-
- - name: Create APK manifest
- run: |
- mkdir -p apk-manifest
-
- cat > apk-manifest/manifest.json <<EOF
- {
- "version": "${{ steps.bundle.outputs.version }}",
- "url": "https://github.com/${{ github.repository }}/releases/download/apk-content/bundle.zip",
- "checksum": "${{ steps.bundle.outputs.checksum }}",
- "built_at": "$(date -u +%Y-%m-%dT%H:%M:%SZ)"
- }
- EOF
-
- echo "Generated manifest:"
- cat apk-manifest/manifest.json
-
- - name: Commit and push APK manifest
- run: |
- git config user.name "bot-for-notamitgamer[bot]"
- git config user.email "bot-for-notamitgamer[bot]@users.noreply.github.com"
-
- git add apk-manifest/manifest.json
-
- if git diff --cached --quiet; then
- echo "No manifest changes"
- exit 0
- fi
-
- git commit -m "chore: update APK content manifest [skip ci]"
-
- for attempt in 1 2 3 4 5; do
- echo ""
- echo "=========================================="
- echo "Manifest push attempt $attempt/5"
- echo "=========================================="
-
- # Get the newest remote main.
- git fetch origin main
-
- # Rebase our manifest commit on the newest main.
- if ! git rebase origin/main; then
- echo "Rebase failed."
- git rebase --abort
- exit 1
- fi
-
- # Try pushing the rebased commit.
- if git push origin HEAD:main; then
- echo ""
- echo "Manifest pushed successfully."
- exit 0
- fi
-
- echo "Push rejected because main changed again."
- echo "Waiting before retry..."
-
- sleep 3
- done
-
- echo ""
- echo "ERROR: Failed to push manifest after 5 attempts."
- exit 1
-
+ # Job 3: Clean deployment production pipeline
deploy:
environment:
name: github-pages