[MMCA] Add permissions external storage #45
Workflow file for this run
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
# make sure to generate requirements.txt with pipreqs first! | |
name: Build | |
on: | |
push: | |
tags: | |
- 'v*' # Push events to matching v*, i.e. v1.0, v20.15.10 | |
workflow_dispatch: | |
jobs: | |
# see https://data-dive.com/multi-os-deployment-in-cloud-using-pyinstaller-and-github-actions/ | |
# but here we build first and run our createrelease job afterwards, accessing the artifacts of our build job | |
build-android-MMCA: | |
name: Build MobileCrashAnalyzer for android | |
runs-on: ubuntu-latest | |
steps: | |
- name: Checkout | |
uses: actions/checkout@v4 | |
- name: Install dependencies | |
run: sudo apt -y install apksigner | |
# Build Mobile Crash Analyzer | |
- name: Prepare MMCA for buildozer | |
run: | | |
REFNAME="${{ github.ref_name }}" | |
echo "VERSION='${REFNAME}'" >src/shared/utils/version.py | |
mkdir MobileCrashAnalyzer_Deploy | |
cp -av src/MobileCrashAnalyzer.py MobileCrashAnalyzer_Deploy/ | |
cp -av src/MobileCrashAnalyzer MobileCrashAnalyzer_Deploy/ | |
cp -av src/shared MobileCrashAnalyzer_Deploy/ | |
cp -av src/MobileCrashAnalyzer/data/conf/intent_filters.xml MobileCrashAnalyzer_Deploy/ | |
cp -av src/MobileCrashAnalyzer/data/conf/buildozer.spec MobileCrashAnalyzer_Deploy/ | |
echo "" >>MobileCrashAnalyzer_Deploy/buildozer.spec | |
# buildozer does not like non-numeric version numbers | |
echo "version = ${REFNAME#v}" >>MobileCrashAnalyzer_Deploy/buildozer.spec | |
# dynamically build main.py proxy to load | |
echo "import os" >MobileCrashAnalyzer_Deploy/main.py | |
echo "os.environ['KIVY_LOG_MODE'] = 'MIXED'" >>MobileCrashAnalyzer_Deploy/main.py | |
echo "os.environ['KIVY_NO_FILELOG'] = '1'" >>MobileCrashAnalyzer_Deploy/main.py | |
echo "" >>MobileCrashAnalyzer_Deploy/main.py | |
echo "from importlib import util" >>MobileCrashAnalyzer_Deploy/main.py | |
echo "real_file = os.path.join(os.path.dirname(__file__), 'MobileCrashAnalyzer.py')" >>MobileCrashAnalyzer_Deploy/main.py | |
echo "if not os.path.exists(real_file):" >>MobileCrashAnalyzer_Deploy/main.py | |
echo " real_file = os.path.join(os.path.dirname(__file__), 'MobileCrashAnalyzer.pyc')" >>MobileCrashAnalyzer_Deploy/main.py | |
echo "print('Proxy loading real file: %s' % real_file)" >>MobileCrashAnalyzer_Deploy/main.py | |
echo "spec = util.spec_from_file_location('MobileCrashAnalyzer', real_file)" >>MobileCrashAnalyzer_Deploy/main.py | |
echo "print(f'{spec = }')" >>MobileCrashAnalyzer_Deploy/main.py | |
echo "mod = util.module_from_spec(spec)" >>MobileCrashAnalyzer_Deploy/main.py | |
echo "# we don't want to add our module to sys.modules to not interfere with the package path having the same name" >>MobileCrashAnalyzer_Deploy/main.py | |
echo "# (just like if our real_file was the real python script started)" >>MobileCrashAnalyzer_Deploy/main.py | |
echo "print(f'{mod = }')" >>MobileCrashAnalyzer_Deploy/main.py | |
echo "out = spec.loader.exec_module(mod)" >>MobileCrashAnalyzer_Deploy/main.py | |
echo "print(f'Proxied file returned with `{out}`, terminating...')" >>MobileCrashAnalyzer_Deploy/main.py | |
echo " " | |
echo "buildozer.spec:" | |
cat MobileCrashAnalyzer_Deploy/buildozer.spec | |
echo " " | |
echo "main.py:" | |
cat MobileCrashAnalyzer_Deploy/main.py | |
- name: Build with Buildozer | |
uses: Sobottasgithub/[email protected] | |
id: buildozer | |
with: | |
workdir: MobileCrashAnalyzer_Deploy | |
buildozer_version: stable | |
- name: Sign Apk | |
id: signer | |
run: | | |
apkinfile="${{ steps.buildozer.outputs.filename }}" | |
apkoutfile="$HOME/signed-$(basename "${apkinfile}")" | |
echo -n "${{ secrets.APK_SIGNING_KEY }}" >"$HOME/keystore.key" | |
openssl enc -d -chacha20 -pbkdf2 -in src/MobileCrashAnalyzer/data/conf/release.keystore.enc -out "$HOME/release.keystore" -kfile "$HOME/keystore.key" | |
cat "$HOME/keystore.key" | apksigner sign -ks "$HOME/release.keystore" -in "${apkinfile}" -out "${apkoutfile}" | |
echo "unsigned_apk=${apkinfile}" >> "$GITHUB_OUTPUT" | |
echo "signed_apk=${apkoutfile}" >> "$GITHUB_OUTPUT" | |
- name: Upload signed apk | |
uses: actions/upload-artifact@v4 | |
with: | |
name: MobileCrashAnalyzer | |
path: ${{ steps.signer.outputs.signed_apk }} | |
build-android-MMLV: | |
name: Build MobileLogViewer for android | |
runs-on: ubuntu-latest | |
steps: | |
- name: Checkout | |
uses: actions/checkout@v4 | |
- name: Install dependencies | |
run: sudo apt -y install apksigner | |
# Build Monal Mobile Log Viewer | |
- name: Prepare MMLV for buildozer | |
run: | | |
REFNAME="${{ github.ref_name }}" | |
echo "VERSION='${REFNAME}'" >src/shared/utils/version.py | |
mkdir MobileLogViewer_Deploy | |
cp -av src/MobileLogViewer.py MobileLogViewer_Deploy/ | |
cp -av src/MobileLogViewer MobileLogViewer_Deploy/ | |
cp -av src/shared MobileLogViewer_Deploy/ | |
cp -av src/MobileLogViewer/data/conf/intent_filters.xml MobileLogViewer_Deploy/ | |
cp -av src/MobileLogViewer/data/conf/buildozer.spec MobileLogViewer_Deploy/ | |
echo "" >>MobileLogViewer_Deploy/buildozer.spec | |
# buildozer does not like non-numeric version numbers | |
echo "version = ${REFNAME#v}" >>MobileLogViewer_Deploy/buildozer.spec | |
# dynamically build main.py proxy to load | |
echo "import os" >MobileLogViewer_Deploy/main.py | |
echo "os.environ['KIVY_LOG_MODE'] = 'MIXED'" >>MobileLogViewer_Deploy/main.py | |
echo "os.environ['KIVY_NO_FILELOG'] = '1'" >>MobileLogViewer_Deploy/main.py | |
echo "" >>MobileLogViewer_Deploy/main.py | |
echo "from importlib import util" >>MobileLogViewer_Deploy/main.py | |
echo "real_file = os.path.join(os.path.dirname(__file__), 'MobileCrashAnalyzer.py')" >>MobileLogViewer_Deploy/main.py | |
echo "if not os.path.exists(real_file):" >>MobileLogViewer_Deploy/main.py | |
echo " real_file = os.path.join(os.path.dirname(__file__), 'MobileCrashAnalyzer.pyc')" >>MobileLogViewer_Deploy/main.py | |
echo "print('Proxy loading real file: %s' % real_file)" >>MobileLogViewer_Deploy/main.py | |
echo "spec = util.spec_from_file_location('MobileCrashAnalyzer', real_file)" >>MobileLogViewer_Deploy/main.py | |
echo "print(f'{spec = }')" >>MobileLogViewer_Deploy/main.py | |
echo "mod = util.module_from_spec(spec)" >>MobileLogViewer_Deploy/main.py | |
echo "# we don't want to add our module to sys.modules to not interfere with the package path having the same name" >>MobileLogViewer_Deploy/main.py | |
echo "# (just like if our real_file was the real python script started)" >>MobileLogViewer_Deploy/main.py | |
echo "print(f'{mod = }')" >>MobileLogViewer_Deploy/main.py | |
echo "out = spec.loader.exec_module(mod)" >>MobileLogViewer_Deploy/main.py | |
echo "print(f'Proxied file returned with `{out}`, terminating...')" >>MobileLogViewer_Deploy/main.py | |
echo " " | |
echo "buildozer.spec:" | |
cat MobileLogViewer_Deploy/buildozer.spec | |
echo " " | |
echo "main.py:" | |
cat MobileLogViewer_Deploy/main.py | |
- name: Build with Buildozer | |
uses: Sobottasgithub/[email protected] | |
id: buildozer | |
with: | |
workdir: MobileLogViewer_Deploy | |
buildozer_version: stable | |
- name: Sign Apk | |
id: signer | |
run: | | |
apkinfile="${{ steps.buildozer.outputs.filename }}" | |
apkoutfile="$HOME/signed-$(basename "${apkinfile}")" | |
echo -n "${{ secrets.APK_SIGNING_KEY }}" >"$HOME/keystore.key" | |
openssl enc -d -chacha20 -pbkdf2 -in src/MobileLogViewer/data/conf/release.keystore.enc -out "$HOME/release.keystore" -kfile "$HOME/keystore.key" | |
cat "$HOME/keystore.key" | apksigner sign -ks "$HOME/release.keystore" -in "${apkinfile}" -out "${apkoutfile}" | |
echo "unsigned_apk=${apkinfile}" >> "$GITHUB_OUTPUT" | |
echo "signed_apk=${apkoutfile}" >> "$GITHUB_OUTPUT" | |
- name: Upload signed apk | |
uses: actions/upload-artifact@v4 | |
with: | |
name: MobileLogViewer | |
path: ${{ steps.signer.outputs.signed_apk }} | |
build-desktop: | |
name: Build ${{ matrix.OUT_FILE_NAME }} for ${{ matrix.TARGET }} | |
runs-on: ${{ matrix.os }} | |
strategy: | |
matrix: | |
include: | |
# LogViewer | |
- os: macos-latest | |
TARGET: macos | |
#--volicon "Hello World.icns" \ | |
# for the dmg stuff, see https://www.pythonguis.com/tutorials/packaging-pyqt5-applications-pyinstaller-macos-dmg/ | |
CMD_BUILD: > | |
pyinstaller --clean --log-level DEBUG --name "LogViewer" --add-data "LogViewer/data:LogViewer/data" --add-data "shared/ui/*.ui:shared/ui" --add-data "LogViewer/ui/*.ui:LogViewer/ui" --specpath src --windowed --icon LogViewer/data/art/icon.png --onefile --debug bootloader --argv-emulation src/LogViewer.py && | |
cd dist/ && | |
zip -r9 LogViewer LogViewer.app/ && | |
brew install create-dmg && | |
mkdir -p dmg && | |
cp -vr "LogViewer.app" dmg/ && | |
create-dmg --volname "LogViewer" --volicon LogViewer.app/Contents/Resources/generated-* --window-pos 200 120 --window-size 600 300 --icon-size 100 --icon "LogViewer.app" 175 120 --hide-extension "LogViewer.app" --app-drop-link 425 120 "LogViewer.dmg" "./dmg/" | |
OUT_FILE_NAME: LogViewer.dmg | |
ASSET_MIME: application/binary | |
- os: windows-latest | |
TARGET: windows | |
CMD_BUILD: > | |
pyinstaller --clean --log-level DEBUG --name "LogViewer" --add-data "LogViewer/data;LogViewer/data" --add-data "shared/ui/*.ui;shared/ui" --add-data "LogViewer/ui/*.ui;LogViewer/ui" --specpath src --windowed --icon LogViewer/data/art/icon.png --onefile --debug bootloader src/LogViewer.py | |
OUT_FILE_NAME: LogViewer.exe | |
ASSET_MIME: application/vnd.microsoft.portable-executable | |
- os: ubuntu-latest | |
TARGET: linux | |
#sudo apt install plasma-integration -y && | |
#sudo cp -av /usr/lib/x86_64-linux-gnu/qt5/plugins/platformthemes/KDEPlasmaPlatformTheme.so /opt/hostedtoolcache/Python/3.11.5/x64/lib/python3.11/site-packages/PyQt5/Qt5/plugins/platformthemes/ -f && | |
#--add-binary "/usr/lib/x86_64-linux-gnu/qt5/plugins/platformthemes/KDEPlasmaPlatformTheme.so:PyQt5/Qt5/plugins/platformthemes" | |
#--add-binary "/lib/x86_64-linux-gnu/libz.so.1:." | |
CMD_BUILD: > | |
pyinstaller --clean --log-level DEBUG --name "LogViewer" --add-data "LogViewer/data:LogViewer/data" --add-data "shared/ui/*.ui:shared/ui" --add-data "LogViewer/ui/*.ui:LogViewer/ui" --specpath src --windowed --icon LogViewer/data/art/icon.png --onefile src/LogViewer.py | |
OUT_FILE_NAME: LogViewer | |
ASSET_MIME: application/x-executable | |
# CrashAnalyzer | |
- os: macos-latest | |
TARGET: macos | |
#--volicon "Hello World.icns" \ | |
# for the dmg stuff, see https://www.pythonguis.com/tutorials/packaging-pyqt5-applications-pyinstaller-macos-dmg/ | |
CMD_BUILD: > | |
pyinstaller --clean --log-level DEBUG --name "CrashAnalyzer" --add-data "CrashAnalyzer/data:CrashAnalyzer/data" --add-data "shared/ui/*.ui:shared/ui" --add-data "CrashAnalyzer/ui/*.ui:CrashAnalyzer/ui" --specpath src --windowed --icon CrashAnalyzer/data/art/icon.png --onefile --debug bootloader --argv-emulation src/CrashAnalyzer.py && | |
cd dist/ && | |
zip -r9 CrashAnalyzer CrashAnalyzer.app/ && | |
brew install create-dmg && | |
mkdir -p dmg && | |
cp -vr "CrashAnalyzer.app" dmg/ && | |
create-dmg --volname "CrashAnalyzer" --volicon CrashAnalyzer.app/Contents/Resources/generated-* --window-pos 200 120 --window-size 600 300 --icon-size 100 --icon "CrashAnalyzer.app" 175 120 --hide-extension "CrashAnalyzer.app" --app-drop-link 425 120 "CrashAnalyzer.dmg" "./dmg/" | |
OUT_FILE_NAME: CrashAnalyzer.dmg | |
ASSET_MIME: application/binary | |
- os: windows-latest | |
TARGET: windows | |
CMD_BUILD: > | |
pyinstaller --clean --log-level DEBUG --name "CrashAnalyzer" --add-data "CrashAnalyzer/data;CrashAnalyzer/data" --add-data "shared/ui/*.ui;shared/ui" --add-data "CrashAnalyzer/ui/*.ui;CrashAnalyzer/ui" --specpath src --windowed --icon CrashAnalyzer/data/art/icon.png --onefile --debug bootloader src/CrashAnalyzer.py | |
OUT_FILE_NAME: CrashAnalyzer.exe | |
ASSET_MIME: application/vnd.microsoft.portable-executable | |
- os: ubuntu-latest | |
TARGET: linux | |
#sudo apt install plasma-integration -y && | |
#sudo cp -av /usr/lib/x86_64-linux-gnu/qt5/plugins/platformthemes/KDEPlasmaPlatformTheme.so /opt/hostedtoolcache/Python/3.11.5/x64/lib/python3.11/site-packages/PyQt5/Qt5/plugins/platformthemes/ -f && | |
#--add-binary "/usr/lib/x86_64-linux-gnu/qt5/plugins/platformthemes/KDEPlasmaPlatformTheme.so:PyQt5/Qt5/plugins/platformthemes" | |
#--add-binary "/lib/x86_64-linux-gnu/libz.so.1:." | |
CMD_BUILD: > | |
pyinstaller --clean --log-level DEBUG --name "CrashAnalyzer" --add-data "CrashAnalyzer/data:CrashAnalyzer/data" --add-data "shared/ui/*.ui:shared/ui" --add-data "CrashAnalyzer/ui/*.ui:CrashAnalyzer/ui" --specpath src --windowed --icon CrashAnalyzer/data/art/icon.png --onefile src/CrashAnalyzer.py | |
OUT_FILE_NAME: CrashAnalyzer | |
ASSET_MIME: application/x-executable | |
steps: | |
- uses: actions/checkout@v4 | |
- name: Set up Python 3.11 | |
uses: actions/setup-python@v5 | |
with: | |
python-version: 3.11 | |
# requirements.txt was created using pipreqs | |
- name: Install common dependencies | |
run: | | |
python -m pip install --upgrade pip | |
pip install --upgrade pyinstaller | |
pip install --upgrade pyinstaller-hooks-contrib | |
pip install --upgrade Pillow | |
pip install --upgrade tk | |
pip install --upgrade tcl | |
pip install --upgrade -r src/requirements.txt | |
- name: Extract version string | |
run: echo "VERSION='${{ github.ref_name }}'" >src/shared/utils/version.py | |
- name: Build with pyinstaller for ${{matrix.TARGET}} | |
run: ${{matrix.CMD_BUILD}} | |
- uses: actions/upload-artifact@v4 | |
with: | |
name: ${{ matrix.OUT_FILE_NAME}} | |
path: ./dist/${{ matrix.OUT_FILE_NAME}} | |
createrelease: | |
name: Create Release | |
runs-on: [ubuntu-latest] | |
needs: [build-desktop, build-android-MMCA, build-android-MMLV] | |
steps: | |
- name: Load build artifacts | |
uses: actions/download-artifact@v4 | |
- name: Generate release notes | |
id: releasenotes | |
uses: tmolitor-stud-tu/github-releasenotes-generator@main | |
with: | |
NO_CREATE_RELEASE: true | |
env: | |
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
- name: Release | |
uses: softprops/action-gh-release@v2 | |
with: | |
name: Release ${{ github.ref_name }} | |
tag_name: ${{ github.ref }} | |
target_commitish: master | |
generate_release_notes: false | |
body: ${{ steps.releasenotes.outputs.notes }} | |
files: | | |
LogViewer*/* | |
CrashAnalyzer*/* | |
MobileCrashAnalyzer*/* | |
MobileLogViewer*/* | |
fail_on_unmatched_files: true | |
token: ${{ secrets.GITHUB_TOKEN }} | |
draft: false |