🤖 Generate Android App #645
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: 🤖 Generate Android App | |
permissions: | |
contents: write | |
on: | |
workflow_dispatch: | |
inputs: | |
id: | |
description: 'Run identifier' | |
required: true | |
domain: | |
description: 'URL of the Website or IP address' | |
required: true | |
second_domain: | |
description: 'Second domain or IP (for example files subdomain)' | |
app_name: | |
description: 'Name of the App' | |
required: true | |
block_media: | |
description: 'Block images' | |
type: boolean | |
default: false | |
block_ads: | |
description: 'Block ads' | |
type: boolean | |
default: true | |
view_mode: | |
description: 'View Mode' | |
required: true | |
type: choice | |
default: 'AUTO' | |
options: | |
- 'AUTO' | |
- 'PORTRAIT' | |
- 'LANDSCAPE' | |
icon_url: | |
description: 'Icon URL' | |
startup_url: | |
description: 'Start URL' | |
no_ssl: | |
description: 'No SSL - Not recommended!!' | |
type: boolean | |
default: false | |
jobs: | |
id: | |
# https://stackoverflow.com/a/73837663 | |
name: Workflow ID Provider | |
runs-on: ubuntu-latest | |
steps: | |
- name: ${{github.event.inputs.id}} | |
run: echo run identifier ${{ inputs.id }} | |
build: | |
runs-on: ubuntu-latest | |
steps: | |
- name: Checkout repo | |
uses: actions/checkout@v4 | |
- name: Validate domains and IPs | |
run: | | |
validate_domain_or_ip() { | |
INPUT="${1}" | |
# Remove protocol from URL if present | |
INPUT="${INPUT#http://}" | |
INPUT="${INPUT#https://}" | |
INPUT="${INPUT%%/*}" | |
# Check if it's an IP address | |
if [[ $INPUT =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]]; then | |
# Validate IP address | |
IFS='.' read -r -a OCTETS <<< "$INPUT" | |
for OCTET in "${OCTETS[@]}"; do | |
if [[ $OCTET -lt 0 || $OCTET -gt 255 ]]; then | |
echo "Error: Invalid IP address format in $INPUT!" | |
exit 1 | |
fi | |
done | |
elif ! [[ $INPUT =~ ^[A-Za-z0-9.-]+\.[A-Za-z0-9-]{2,}$ ]]; then | |
echo "Error: Invalid domain or IP format in $INPUT!" | |
exit 1 | |
fi | |
echo $INPUT | |
} | |
# Validate and format primary domain or IP | |
PRIMARY_INPUT=$(validate_domain_or_ip "${{ inputs.domain }}") | |
echo "PRIMARY_DOMAIN=$PRIMARY_INPUT" >> $GITHUB_ENV | |
ALLOWED_DOMAINS="$PRIMARY_INPUT" | |
# Validate and add second domain or IP if present | |
if [ -n "${{ inputs.second_domain }}" ]; then | |
SECOND_INPUT=$(validate_domain_or_ip "${{ inputs.second_domain }}") | |
echo "SECOND_DOMAIN=$SECOND_INPUT" >> $GITHUB_ENV | |
ALLOWED_DOMAINS="$ALLOWED_DOMAINS,$SECOND_INPUT" | |
fi | |
echo "ALLOWED_DOMAINS=$ALLOWED_DOMAINS" >> $GITHUB_ENV | |
- name: Validate app_name input | |
run: | | |
if ! perl -e "exit 1 unless '${{ inputs.app_name }}' =~ /^[:a-zA-Zא-ת0-9 \"_.-]+$/"; then | |
echo "Error: Invalid app_name format!" | |
exit 1 | |
fi | |
- name: Fix applicationId | |
run: | | |
# remove all not-allowed characters and replace dots with underscores for IP addresses | |
APPLICATION_ID=$(echo "${{ env.PRIMARY_DOMAIN }}" | perl -pe 's/[^a-zA-Z0-9.]//g' | tr '.' '_' | tr '[:upper:]' '[:lower:]') | |
echo "APPLICATION_ID=com.restictedwebview.$APPLICATION_ID" >> $GITHUB_ENV | |
- name: Use Node.js 20 | |
uses: actions/setup-node@v4 | |
with: | |
node-version: 20 | |
- name: Create mipmap images | |
run: | | |
if [ -n "${{ inputs.icon_url }}" ]; then | |
npm install && node create_mipmap_images.js "${{ inputs.icon_url }}" | |
fi | |
- name: Download AdBlock List | |
run: curl "https://pgl.yoyo.org/adservers/serverlist.php?hostformat=plain&showintro=1&mimetype=plaintext" -o app/src/main/assets/adblock.txt --create-dirs | |
- name: Set up JDK 17 | |
uses: actions/setup-java@v4 | |
with: | |
java-version: 17 | |
distribution: 'temurin' | |
- name: Make gradlew executable | |
run: chmod +x ./gradlew | |
- name: Decode Keystore | |
id: decode_keystore | |
uses: timheuer/[email protected] | |
with: | |
fileName: 'android_keystore.jks' | |
fileDir: '/home/runner/work/AndroidRestrictedWebView/AndroidRestrictedWebView/app/keystore/' | |
encodedString: ${{ secrets.KEYSTORE }} | |
- name: Build APK | |
run: ./gradlew assembleRelease | |
env: | |
SIGNING_KEY_ALIAS: ${{ secrets.SIGNING_KEY_ALIAS }} | |
SIGNING_KEY_PASSWORD: ${{ secrets.SIGNING_KEY_PASSWORD }} | |
SIGNING_STORE_PASSWORD: ${{ secrets.SIGNING_STORE_PASSWORD }} | |
APPLICATION_ID: ${{ env.APPLICATION_ID }} | |
APP_NAME: ${{ inputs.app_name }} | |
VIEW_MODE: ${{ inputs.view_mode }} | |
STARTUP_URL: ${{ inputs.startup_url }} | |
ALLOWED_DOMAINS: ${{ env.ALLOWED_DOMAINS }} | |
BLOCK_MEDIA: ${{ inputs.block_media }} | |
BLOCK_ADS: ${{ inputs.block_ads }} | |
NO_SSL: ${{ inputs.no_ssl }} | |
- name: Rename APK | |
run: mv app/build/outputs/apk/release/app-release.apk app/build/outputs/apk/release/webview-${{ env.PRIMARY_DOMAIN }}.apk | |
- name: Create Release | |
id: create_release | |
uses: softprops/action-gh-release@v2 | |
env: | |
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
with: | |
tag_name: v${{ github.run_id }} | |
name: Release v${{ github.run_id }} (${{ env.PRIMARY_DOMAIN }}) | |
prerelease: true | |
draft: false | |
files: app/build/outputs/apk/release/webview-${{ env.PRIMARY_DOMAIN }}.apk | |
body: | | |
Restricted WebView App. | |
Domain: [${{ env.PRIMARY_DOMAIN }}](//${{ env.PRIMARY_DOMAIN }}) | |
Second Domain: [${{ env.SECOND_DOMAIN }}](//${{ env.SECOND_DOMAIN }}) | |
No Secured: ${{ inputs.no_ssl }} | |
App Name: ${{ inputs.app_name }} | |
View Mode: ${{ inputs.view_mode }} | |
Block Media: ${{ inputs.block_media }} | |
Block Ads: ${{ inputs.block_ads }} | |
Custom Icon: ${{ inputs.icon_url }} | |
- name: Get the APK URL | |
run: | | |
echo "APK URL: ${{ fromJSON(steps.create_release.outputs.assets)[0].browser_download_url }}" |