diff --git a/.github/utils/_get_password.py b/.github/utils/_get_password.py index 33071b6c..9b120c17 100644 --- a/.github/utils/_get_password.py +++ b/.github/utils/_get_password.py @@ -23,8 +23,6 @@ def get_password( auth_plugin="mysql_native_password", ) - print(f"Generating passwords for version {version_name} ({version_code})") - password = base64.b64encode(secrets.token_bytes(16)).decode() iv = secrets.token_bytes(16) diff --git a/.github/utils/_utils.py b/.github/utils/_utils.py index 09b59f4a..0ad46d54 100644 --- a/.github/utils/_utils.py +++ b/.github/utils/_utils.py @@ -102,7 +102,9 @@ def get_commit_log(project_dir: str, format: str, max_lines: int = None) -> str: ) log = subprocess.run( - args=f"git log {last_tag}..HEAD --format=%an%x00%at%x00%h%x00%s%x00%D".split(" "), + args=f"git log {last_tag}..HEAD --format=%an%x00%at%x00%h%x00%s%x00%D".split( + " " + ), cwd=project_dir, stdout=subprocess.PIPE, ) diff --git a/.github/utils/bump_nightly.py b/.github/utils/bump_nightly.py index 88b4798c..3fb74fa4 100644 --- a/.github/utils/bump_nightly.py +++ b/.github/utils/bump_nightly.py @@ -1,11 +1,8 @@ -import json import os import re import sys from datetime import datetime, timedelta -import requests - from _utils import ( get_commit_log, get_project_dir, @@ -25,17 +22,6 @@ if __name__ == "__main__": print("Missing GitHub environment variables.") exit(-1) - with requests.get( - f"https://api.github.com/repos/{repo}/actions/runs?per_page=5&status=success" - ) as r: - data = json.loads(r.text) - runs = [run for run in data["workflow_runs"] if run["head_sha"] == sha] - if runs: - print("::set-output name=hasNewChanges::false") - exit(0) - - print("::set-output name=hasNewChanges::true") - project_dir = get_project_dir() (version_code, version_name) = read_gradle_version(project_dir) @@ -48,8 +34,8 @@ if __name__ == "__main__": date -= timedelta(days=1) version_name += "+nightly." + date.strftime("%Y%m%d") - print("::set-output name=appVersionName::" + version_name) - print("::set-output name=appVersionCode::" + str(version_code)) + print("appVersionName=" + version_name) + print("appVersionCode=" + str(version_code)) write_gradle_version(project_dir, version_code, version_name) diff --git a/.github/utils/check_nightly.py b/.github/utils/check_nightly.py new file mode 100644 index 00000000..bf8b56cf --- /dev/null +++ b/.github/utils/check_nightly.py @@ -0,0 +1,23 @@ +import json +import os + +import requests + +if __name__ == "__main__": + repo = os.getenv("GITHUB_REPOSITORY") + sha = os.getenv("GITHUB_SHA") + + if not repo or not sha: + print("Missing GitHub environment variables.") + exit(-1) + + with requests.get( + f"https://api.github.com/repos/{repo}/actions/runs?per_page=5&status=success" + ) as r: + data = json.loads(r.text) + runs = [run for run in data["workflow_runs"] if run["head_sha"] == sha] + if runs: + print("hasNewChanges=false") + exit(0) + + print("hasNewChanges=true") diff --git a/.github/utils/extract_changelogs.py b/.github/utils/extract_changelogs.py index d5a659cc..544df813 100644 --- a/.github/utils/extract_changelogs.py +++ b/.github/utils/extract_changelogs.py @@ -12,13 +12,13 @@ if __name__ == "__main__": (version_code, version_name) = read_gradle_version(project_dir) - print("::set-output name=appVersionName::" + version_name) - print("::set-output name=appVersionCode::" + str(version_code)) + print("appVersionName=" + version_name) + print("appVersionCode=" + str(version_code)) dir = f"{project_dir}/app/release/whatsnew-{version_name}/" os.makedirs(dir, exist_ok=True) - print("::set-output name=changelogDir::" + dir) + print("changelogDir=" + dir) (title, changelog) = get_changelog(project_dir, format="plain") @@ -27,9 +27,9 @@ if __name__ == "__main__": f.write(title) f.write("\n") f.write(changelog) - print("::set-output name=changelogPlainTitledFile::" + dir + "whatsnew_titled.txt") + print("changelogPlainTitledFile=" + dir + "whatsnew_titled.txt") - print("::set-output name=changelogTitle::" + title) + print("changelogTitle=" + title) # plain text changelog, max 500 chars - Google Play with open(dir + "whatsnew-pl-PL", "w", encoding="utf-8") as f: @@ -41,32 +41,31 @@ if __name__ == "__main__": changelog = changelog.strip() f.write(changelog) - print("::set-output name=changelogPlainFile::" + dir + "whatsnew-pl-PL") + print("changelogPlainFile=" + dir + "whatsnew-pl-PL") # markdown changelog - Discord webhook (_, changelog) = get_changelog(project_dir, format="markdown") with open(dir + "whatsnew.md", "w", encoding="utf-8") as f: f.write(changelog) - print("::set-output name=changelogMarkdownFile::" + dir + "whatsnew.md") + print("changelogMarkdownFile=" + dir + "whatsnew.md") # html changelog - version info in DB (_, changelog) = get_changelog(project_dir, format="html") with open(dir + "whatsnew.html", "w", encoding="utf-8") as f: f.write(changelog) - print("::set-output name=changelogHtmlFile::" + dir + "whatsnew.html") - + print("changelogHtmlFile=" + dir + "whatsnew.html") changelog = get_commit_log(project_dir, format="plain", max_lines=10) with open(dir + "commit_log.txt", "w", encoding="utf-8") as f: f.write(changelog) - print("::set-output name=commitLogPlainFile::" + dir + "commit_log.txt") + print("commitLogPlainFile=" + dir + "commit_log.txt") changelog = get_commit_log(project_dir, format="markdown", max_lines=10) with open(dir + "commit_log.md", "w", encoding="utf-8") as f: f.write(changelog) - print("::set-output name=commitLogMarkdownFile::" + dir + "commit_log.md") + print("commitLogMarkdownFile=" + dir + "commit_log.md") changelog = get_commit_log(project_dir, format="html", max_lines=10) with open(dir + "commit_log.html", "w", encoding="utf-8") as f: f.write(changelog) - print("::set-output name=commitLogHtmlFile::" + dir + "commit_log.html") + print("commitLogHtmlFile=" + dir + "commit_log.html") diff --git a/.github/utils/rename_artifacts.py b/.github/utils/find_artifacts.py similarity index 73% rename from .github/utils/rename_artifacts.py rename to .github/utils/find_artifacts.py index 4eeabfaf..286836ae 100644 --- a/.github/utils/rename_artifacts.py +++ b/.github/utils/find_artifacts.py @@ -13,7 +13,7 @@ if __name__ == "__main__": files = glob.glob(f"{project_dir}/app/release/*.*") for file in files: - file_relative = file.replace(os.getenv("GITHUB_WORKSPACE") + "/", "") + file_relative = file.replace(project_dir + "/", "") if "-aligned.apk" in file: os.unlink(file) elif "-signed.apk" in file: @@ -22,5 +22,5 @@ if __name__ == "__main__": os.unlink(new_file) os.rename(file, new_file) elif ".apk" in file or ".aab" in file: - print("::set-output name=signedReleaseFile::" + file) - print("::set-output name=signedReleaseFileRelative::" + file_relative) + print("signedReleaseFile=" + file) + print("signedReleaseFileRelative=" + file_relative) diff --git a/.github/utils/save_version.py b/.github/utils/save_version.py index 01de17a7..a0eacb49 100644 --- a/.github/utils/save_version.py +++ b/.github/utils/save_version.py @@ -64,7 +64,14 @@ def save_version( if build_type in ["nightly", "daily"]: download_url = apk_server_nightly + apk_name if apk_name else None else: - download_url = apk_server_release + apk_name if apk_name else None + # download_url = apk_server_release + apk_name if apk_name else None + download_url = ( + f"https://github.com/szkolny-eu/szkolny-android/releases/download/v{version_name}/{apk_name}" + if apk_name + else None + ) + if download_url: + print("downloadUrl=" + download_url) cols = [ "versionCode", @@ -119,4 +126,12 @@ if __name__ == "__main__": APK_SERVER_RELEASE = os.getenv("APK_SERVER_RELEASE") APK_SERVER_NIGHTLY = os.getenv("APK_SERVER_NIGHTLY") - save_version(project_dir, DB_HOST, DB_USER, DB_PASS, DB_NAME, APK_SERVER_RELEASE, APK_SERVER_NIGHTLY) + save_version( + project_dir, + DB_HOST, + DB_USER, + DB_PASS, + DB_NAME, + APK_SERVER_RELEASE, + APK_SERVER_NIGHTLY, + ) diff --git a/.github/utils/sign.py b/.github/utils/sign.py index 026d819b..bdf417d9 100644 --- a/.github/utils/sign.py +++ b/.github/utils/sign.py @@ -31,8 +31,6 @@ def sign( SIGNING_FORMAT = "$param1.{}.$param2" CPP_FORMAT = "/*{}*/\nstatic toys AES_IV[16] = {{\n\t{} }};" - print(f"Writing passwords for version {version_name} ({version_code})") - iv_hex = " ".join(["{:02x}".format(x) for x in iv]) iv_cpp = ", ".join(["0x{:02x}".format(x) for x in iv]) @@ -71,8 +69,8 @@ if __name__ == "__main__": version_name, version_code, DB_HOST, DB_USER, DB_PASS, DB_NAME ) - print("::set-output name=appVersionName::" + version_name) - print("::set-output name=appVersionCode::" + str(version_code)) + print("appVersionName=" + version_name) + print("appVersionCode=" + str(version_code)) sign( project_dir, diff --git a/.github/utils/webhook_discord.py b/.github/utils/webhook_discord.py index 3c1404ae..cb1e6a0b 100644 --- a/.github/utils/webhook_discord.py +++ b/.github/utils/webhook_discord.py @@ -11,8 +11,7 @@ from _utils import get_changelog, get_commit_log, get_project_dir, read_gradle_v def post_webhook( project_dir: str, apk_file: str, - apk_server_release: str, - apk_server_nightly: str, + download_url: str, webhook_release: str, webhook_testing: str, ): @@ -25,12 +24,6 @@ def post_webhook( testing = ["dev", "beta", "nightly", "daily"] testing = build_type in testing - apk_name = os.path.basename(apk_file) - if build_type in ["nightly", "daily"]: - download_url = apk_server_nightly + apk_name - else: - download_url = apk_server_release + apk_name - if testing: build_date = int(os.stat(apk_file).st_mtime) if build_date: @@ -48,13 +41,17 @@ def post_webhook( requests.post(url=webhook_testing, json=webhook) else: changelog = get_changelog(project_dir, format="markdown") - webhook = get_webhook_release(changelog, download_url) + webhook = get_webhook_release(version_name, changelog, download_url) requests.post(url=webhook_release, json=webhook) -def get_webhook_release(changelog: str, download_url: str): +def get_webhook_release(version_name: str, changelog: str, download_url: str): (title, content) = changelog - return {"content": f"__**{title}**__\n{content}\n{download_url}"} + return { + "content": ( + f"__**{title}**__\n{content}\n[Szkolny.eu {version_name}]({download_url})" + ), + } def get_webhook_testing( @@ -73,9 +70,11 @@ def get_webhook_testing( "fields": [ { "name": f"Wersja `{version_name}`", - "value": f"[Pobierz .APK]({download_url})" - if download_url - else "*Pobieranie niedostępne*", + "value": ( + f"[Pobierz .APK]({download_url})" + if download_url + else "*Pobieranie niedostępne*" + ), "inline": False, }, { @@ -103,16 +102,14 @@ if __name__ == "__main__": load_dotenv() APK_FILE = os.getenv("APK_FILE") - APK_SERVER_RELEASE = os.getenv("APK_SERVER_RELEASE") - APK_SERVER_NIGHTLY = os.getenv("APK_SERVER_NIGHTLY") + DOWNLOAD_URL = os.getenv("DOWNLOAD_URL") WEBHOOK_RELEASE = os.getenv("WEBHOOK_RELEASE") WEBHOOK_TESTING = os.getenv("WEBHOOK_TESTING") post_webhook( project_dir, APK_FILE, - APK_SERVER_RELEASE, - APK_SERVER_NIGHTLY, + DOWNLOAD_URL, WEBHOOK_RELEASE, WEBHOOK_TESTING, ) diff --git a/.github/workflows/_build.yml b/.github/workflows/_build.yml new file mode 100644 index 00000000..491de21b --- /dev/null +++ b/.github/workflows/_build.yml @@ -0,0 +1,195 @@ +name: "[reusable] Szkolny.eu Build" + +on: + workflow_call: + inputs: + nightly: + type: boolean + default: false + build-apk: + type: boolean + default: false + build-aab: + type: boolean + default: false + + release-ssh: + type: boolean + default: false + release-github: + type: boolean + default: false + release-firebase: + type: boolean + default: false + release-google-play: + type: boolean + default: false + release-discord: + type: boolean + default: false + secrets: + APK_SERVER_NIGHTLY: + APK_SERVER_RELEASE: + DB_HOST: + DB_NAME: + DB_PASS: + DB_USER: + FIREBASE_APP_ID: + FIREBASE_GROUPS_NIGHTLY: + FIREBASE_GROUPS_RELEASE: + FIREBASE_SERVICE_ACCOUNT_JSON: + KEY_ALIAS_PASSWORD: + KEY_ALIAS: + KEY_STORE_PASSWORD: + KEY_STORE: + PLAY_RELEASE_TRACK: + PLAY_SERVICE_ACCOUNT_JSON: + SSH_IP: + SSH_KEY: + SSH_PATH_NIGHTLY: + SSH_PATH_RELEASE: + SSH_USERNAME: + WEBHOOK_RELEASE: + WEBHOOK_TESTING: + +permissions: + contents: write + +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v3 + with: + fetch-depth: 0 + clean: false + - name: Setup JDK 17 + uses: actions/setup-java@v3 + with: + distribution: "temurin" + java-version: "17" + - name: Setup Python + uses: actions/setup-python@v4 + - name: Install Python packages + uses: BSFishy/pip-action@v1 + with: + packages: | + python-dotenv + pycryptodome + mysql-connector-python + requests + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v3 + + - name: Bump nightly version + if: ${{ inputs.nightly }} + run: python $GITHUB_WORKSPACE/.github/utils/bump_nightly.py $GITHUB_WORKSPACE >> $GITHUB_OUTPUT + - name: Write signing passwords and keystore + env: + DB_HOST: ${{ secrets.DB_HOST }} + DB_USER: ${{ secrets.DB_USER }} + DB_PASS: ${{ secrets.DB_PASS }} + DB_NAME: ${{ secrets.DB_NAME }} + KEY_STORE: ${{ secrets.KEY_STORE }} + run: | + python $GITHUB_WORKSPACE/.github/utils/sign.py $GITHUB_WORKSPACE commit >> $GITHUB_OUTPUT + echo $KEY_STORE | base64 --decode > keystore.jks + - name: Clean build artifacts + run: | + rm -rf app/release/* + rm -rf app/build/outputs/apk/* + rm -rf app/build/outputs/bundle/* + + - name: Build app with Gradle + if: ${{ inputs.build-apk || inputs.build-aab }} + run: | + chmod +x ./gradlew + ./gradlew \ + ${{ inputs.build-apk && 'assembleOfficialRelease' || '' }} \ + ${{ inputs.build-aab && 'bundlePlayRelease' || '' }} \ + -P android.injected.signing.store.file=${{ github.workspace }}/keystore.jks \ + -P android.injected.signing.store.password=${{ secrets.KEY_STORE_PASSWORD }} \ + -P android.injected.signing.key.alias=${{ secrets.KEY_ALIAS }} \ + -P android.injected.signing.key.password=${{ secrets.KEY_ALIAS_PASSWORD }} + + - name: Upload release to server + if: ${{ inputs.release-ssh }} + uses: easingthemes/ssh-deploy@v2.1.6 + env: + REMOTE_HOST: ${{ secrets.SSH_IP }} + REMOTE_USER: ${{ secrets.SSH_USERNAME }} + SSH_PRIVATE_KEY: ${{ secrets.SSH_KEY }} + SOURCE: app/release/ + TARGET: ${{ inputs.nightly && secrets.SSH_PATH_NIGHTLY || secrets.SSH_PATH_RELEASE }} + + - name: Find signed artifacts + id: artifacts + run: python $GITHUB_WORKSPACE/.github/utils/find_artifacts.py $GITHUB_WORKSPACE >> $GITHUB_OUTPUT + - name: Extract release changelogs + id: changelog + run: python $GITHUB_WORKSPACE/.github/utils/extract_changelogs.py $GITHUB_WORKSPACE >> $GITHUB_OUTPUT + - name: Save version to database + id: save + env: + DB_HOST: ${{ secrets.DB_HOST }} + DB_USER: ${{ secrets.DB_USER }} + DB_PASS: ${{ secrets.DB_PASS }} + DB_NAME: ${{ secrets.DB_NAME }} + APK_SERVER_RELEASE: ${{ secrets.APK_SERVER_RELEASE }} + APK_SERVER_NIGHTLY: ${{ secrets.APK_SERVER_NIGHTLY }} + run: python $GITHUB_WORKSPACE/.github/utils/save_version.py $GITHUB_WORKSPACE >> $GITHUB_OUTPUT + + - name: Release on GitHub + if: ${{ inputs.release-github }} + uses: softprops/action-gh-release@v1 + with: + name: ${{ steps.changelog.outputs.changelogTitle }} + body_path: ${{ steps.changelog.outputs.changelogMarkdownFile }} + files: ${{ steps.artifacts.outputs.signedReleaseFile }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Distribute to App Distribution + if: ${{ inputs.release-firebase }} + uses: wzieba/Firebase-Distribution-Github-Action@v1 + with: + appId: ${{ secrets.FIREBASE_APP_ID }} + serviceCredentialsFileContent: ${{ secrets.FIREBASE_SERVICE_ACCOUNT_JSON }} + file: ${{ steps.artifacts.outputs.signedReleaseFile }} + groups: ${{ inputs.nightly && secrets.FIREBASE_GROUPS_NIGHTLY || secrets.FIREBASE_GROUPS_RELEASE }} + releaseNotesFile: ${{ inputs.nightly && steps.changelog.outputs.commitLogPlainFile || steps.changelog.outputs.changelogPlainTitledFile }} + + - name: Publish AAB to Google Play + if: ${{ inputs.release-google-play }} + uses: r0adkll/upload-google-play@v1 + with: + serviceAccountJsonPlainText: ${{ secrets.PLAY_SERVICE_ACCOUNT_JSON }} + packageName: pl.szczodrzynski.edziennik + releaseFiles: ${{ steps.artifacts.outputs.signedReleaseFile }} + releaseName: ${{ steps.changelog.outputs.appVersionName }} + track: ${{ secrets.PLAY_RELEASE_TRACK }} + whatsNewDirectory: ${{ steps.changelog.outputs.changelogDir }} + status: completed + + - name: Post Discord webhook + if: ${{ inputs.release-discord }} + env: + APK_FILE: ${{ steps.artifacts.outputs.signedReleaseFile }} + DOWNLOAD_URL: ${{ steps.save.outputs.downloadUrl }} + WEBHOOK_RELEASE: ${{ secrets.WEBHOOK_RELEASE }} + WEBHOOK_TESTING: ${{ secrets.WEBHOOK_TESTING }} + run: python $GITHUB_WORKSPACE/.github/utils/webhook_discord.py $GITHUB_WORKSPACE >> $GITHUB_OUTPUT + + - name: Upload workflow artifact + uses: actions/upload-artifact@v2 + if: always() + with: + name: ${{ steps.changelog.outputs.appVersionName }} + path: | + app/release/whatsnew*/ + app/release/*.apk + app/release/*.aab + app/release/*.json + app/release/*.txt diff --git a/.github/workflows/build-nightly-apk.yml b/.github/workflows/build-nightly-apk.yml deleted file mode 100644 index 0951149e..00000000 --- a/.github/workflows/build-nightly-apk.yml +++ /dev/null @@ -1,154 +0,0 @@ -name: Nightly build - -on: - schedule: - # 23:30 UTC, 0:30 or 1:30 CET/CEST - - cron: "30 23 * * *" - workflow_dispatch: - -jobs: - prepare: - name: Prepare build environment - runs-on: self-hosted - outputs: - hasNewChanges: ${{ steps.nightly.outputs.hasNewChanges }} - steps: - - name: Checkout repository - uses: actions/checkout@v2 - with: - fetch-depth: 0 - clean: false - - name: Set executable permissions to gradlew - run: chmod +x ./gradlew - - name: Setup Python - uses: actions/setup-python@v2 - - name: Install packages - uses: BSFishy/pip-action@v1 - with: - packages: | - python-dotenv - pycryptodome - mysql-connector-python - requests - - name: Bump nightly version - id: nightly - run: python $GITHUB_WORKSPACE/.github/utils/bump_nightly.py $GITHUB_WORKSPACE - - name: Write signing passwords - if: steps.nightly.outputs.hasNewChanges - env: - DB_HOST: ${{ secrets.DB_HOST }} - DB_USER: ${{ secrets.DB_USER }} - DB_PASS: ${{ secrets.DB_PASS }} - DB_NAME: ${{ secrets.DB_NAME }} - run: python $GITHUB_WORKSPACE/.github/utils/sign.py $GITHUB_WORKSPACE commit - build: - name: Build APK - runs-on: self-hosted - needs: - - prepare - if: ${{ needs.prepare.outputs.hasNewChanges == 'true' }} - outputs: - androidHome: ${{ env.ANDROID_HOME }} - androidSdkRoot: ${{ env.ANDROID_SDK_ROOT }} - steps: - - name: Setup JDK 11 - uses: actions/setup-java@v2 - with: - distribution: 'temurin' - java-version: '11' - - name: Setup Android SDK - uses: android-actions/setup-android@v2 - - name: Clean build artifacts - run: | - rm -rf app/release/* - rm -rf app/build/outputs/apk/* - rm -rf app/build/outputs/bundle/* - - name: Assemble official release with Gradle - uses: gradle/gradle-build-action@v2 - with: - arguments: assembleOfficialRelease - sign: - name: Sign APK - runs-on: self-hosted - needs: - - build - outputs: - signedReleaseFile: ${{ steps.artifacts.outputs.signedReleaseFile }} - signedReleaseFileRelative: ${{ steps.artifacts.outputs.signedReleaseFileRelative }} - steps: - - name: Sign build artifacts - id: sign_app - uses: r0adkll/sign-android-release@v1 - with: - releaseDirectory: app/release - signingKeyBase64: ${{ secrets.KEY_STORE }} - alias: ${{ secrets.KEY_ALIAS }} - keyStorePassword: ${{ secrets.KEY_STORE_PASSWORD }} - keyPassword: ${{ secrets.KEY_ALIAS_PASSWORD }} - env: - ANDROID_HOME: ${{ needs.build.outputs.androidHome }} - ANDROID_SDK_ROOT: ${{ needs.build.outputs.androidSdkRoot }} - BUILD_TOOLS_VERSION: "30.0.2" - - name: Rename signed artifacts - id: artifacts - run: python $GITHUB_WORKSPACE/.github/utils/rename_artifacts.py $GITHUB_WORKSPACE - publish: - name: Publish APK - runs-on: self-hosted - needs: - - sign - steps: - - name: Setup Python - uses: actions/setup-python@v2 - - - name: Extract changelogs - id: changelog - run: python $GITHUB_WORKSPACE/.github/utils/extract_changelogs.py $GITHUB_WORKSPACE - - - name: Upload APK to SFTP - uses: easingthemes/ssh-deploy@v2.1.6 - env: - REMOTE_HOST: ${{ secrets.SSH_IP }} - REMOTE_USER: ${{ secrets.SSH_USERNAME }} - SSH_PRIVATE_KEY: ${{ secrets.SSH_KEY }} - SOURCE: ${{ needs.sign.outputs.signedReleaseFileRelative }} - TARGET: ${{ secrets.SSH_PATH_NIGHTLY }} - - name: Save version metadata - env: - DB_HOST: ${{ secrets.DB_HOST }} - DB_USER: ${{ secrets.DB_USER }} - DB_PASS: ${{ secrets.DB_PASS }} - DB_NAME: ${{ secrets.DB_NAME }} - APK_SERVER_RELEASE: ${{ secrets.APK_SERVER_RELEASE }} - APK_SERVER_NIGHTLY: ${{ secrets.APK_SERVER_NIGHTLY }} - run: python $GITHUB_WORKSPACE/.github/utils/save_version.py $GITHUB_WORKSPACE - - - name: Distribute to App Distribution - uses: wzieba/Firebase-Distribution-Github-Action@v1 - with: - appId: ${{ secrets.FIREBASE_APP_ID }} - token: ${{ secrets.FIREBASE_TOKEN }} - groups: ${{ secrets.FIREBASE_GROUPS_NIGHTLY }} - file: ${{ needs.sign.outputs.signedReleaseFile }} - releaseNotesFile: ${{ steps.changelog.outputs.commitLogPlainFile }} - - - name: Post Discord webhook - env: - APK_FILE: ${{ needs.sign.outputs.signedReleaseFile }} - APK_SERVER_RELEASE: ${{ secrets.APK_SERVER_RELEASE }} - APK_SERVER_NIGHTLY: ${{ secrets.APK_SERVER_NIGHTLY }} - WEBHOOK_RELEASE: ${{ secrets.WEBHOOK_RELEASE }} - WEBHOOK_TESTING: ${{ secrets.WEBHOOK_TESTING }} - run: python $GITHUB_WORKSPACE/.github/utils/webhook_discord.py $GITHUB_WORKSPACE - - - name: Upload workflow artifact - uses: actions/upload-artifact@v2 - if: true - with: - name: ${{ steps.changelog.outputs.appVersionName }} - path: | - app/release/whatsnew*/ - app/release/*.apk - app/release/*.aab - app/release/*.json - app/release/*.txt diff --git a/.github/workflows/build-release-aab-play.yml b/.github/workflows/build-release-aab-play.yml deleted file mode 100644 index eb6923bb..00000000 --- a/.github/workflows/build-release-aab-play.yml +++ /dev/null @@ -1,132 +0,0 @@ -name: Release build - Google Play [AAB] - -on: - push: - branches: - - "master" - -jobs: - prepare: - name: Prepare build environment - runs-on: self-hosted - steps: - - name: Checkout repository - uses: actions/checkout@v2 - with: - fetch-depth: 0 - clean: false - - name: Set executable permissions to gradlew - run: chmod +x ./gradlew - - name: Setup Python - uses: actions/setup-python@v2 - - name: Install packages - uses: BSFishy/pip-action@v1 - with: - packages: | - python-dotenv - pycryptodome - mysql-connector-python - requests - - name: Write signing passwords - env: - DB_HOST: ${{ secrets.DB_HOST }} - DB_USER: ${{ secrets.DB_USER }} - DB_PASS: ${{ secrets.DB_PASS }} - DB_NAME: ${{ secrets.DB_NAME }} - run: python $GITHUB_WORKSPACE/.github/utils/sign.py $GITHUB_WORKSPACE commit - build: - name: Build App Bundle - runs-on: self-hosted - needs: - - prepare - outputs: - androidHome: ${{ env.ANDROID_HOME }} - androidSdkRoot: ${{ env.ANDROID_SDK_ROOT }} - steps: - - name: Setup JDK 11 - uses: actions/setup-java@v2 - with: - distribution: 'temurin' - java-version: '11' - - name: Setup Android SDK - uses: android-actions/setup-android@v2 - - name: Clean build artifacts - run: | - rm -rf app/release/* - rm -rf app/build/outputs/apk/* - rm -rf app/build/outputs/bundle/* - - name: Bundle play release with Gradle - uses: gradle/gradle-build-action@v2 - with: - arguments: bundlePlayRelease - sign: - name: Sign App Bundle - runs-on: self-hosted - needs: - - build - outputs: - signedReleaseFile: ${{ steps.artifacts.outputs.signedReleaseFile }} - signedReleaseFileRelative: ${{ steps.artifacts.outputs.signedReleaseFileRelative }} - steps: - - name: Sign build artifacts - id: sign_app - uses: r0adkll/sign-android-release@v1 - with: - releaseDirectory: app/release - signingKeyBase64: ${{ secrets.KEY_STORE }} - alias: ${{ secrets.KEY_ALIAS }} - keyStorePassword: ${{ secrets.KEY_STORE_PASSWORD }} - keyPassword: ${{ secrets.KEY_ALIAS_PASSWORD }} - env: - ANDROID_HOME: ${{ needs.build.outputs.androidHome }} - ANDROID_SDK_ROOT: ${{ needs.build.outputs.androidSdkRoot }} - BUILD_TOOLS_VERSION: "30.0.2" - - name: Rename signed artifacts - id: artifacts - run: python $GITHUB_WORKSPACE/.github/utils/rename_artifacts.py $GITHUB_WORKSPACE - publish: - name: Publish App Bundle - runs-on: self-hosted - needs: - - sign - steps: - - name: Setup Python - uses: actions/setup-python@v2 - - - name: Extract changelogs - id: changelog - run: python $GITHUB_WORKSPACE/.github/utils/extract_changelogs.py $GITHUB_WORKSPACE - - - name: Save version metadata - env: - DB_HOST: ${{ secrets.DB_HOST }} - DB_USER: ${{ secrets.DB_USER }} - DB_PASS: ${{ secrets.DB_PASS }} - DB_NAME: ${{ secrets.DB_NAME }} - APK_SERVER_RELEASE: ${{ secrets.APK_SERVER_RELEASE }} - APK_SERVER_NIGHTLY: ${{ secrets.APK_SERVER_NIGHTLY }} - run: python $GITHUB_WORKSPACE/.github/utils/save_version.py $GITHUB_WORKSPACE - - - name: Publish AAB to Google Play - uses: r0adkll/upload-google-play@v1 - if: ${{ endsWith(needs.sign.outputs.signedReleaseFile, '.aab') }} - with: - serviceAccountJsonPlainText: ${{ secrets.PLAY_SERVICE_ACCOUNT_JSON }} - packageName: pl.szczodrzynski.edziennik - releaseFiles: ${{ needs.sign.outputs.signedReleaseFile }} - releaseName: ${{ steps.changelog.outputs.appVersionName }} - track: ${{ secrets.PLAY_RELEASE_TRACK }} - whatsNewDirectory: ${{ steps.changelog.outputs.changelogDir }} - status: completed - - - name: Upload workflow artifact - uses: actions/upload-artifact@v2 - if: always() - with: - name: ${{ steps.changelog.outputs.appVersionName }} - path: | - app/release/whatsnew*/ - app/release/*.apk - app/release/*.aab - app/release/*.json - app/release/*.txt diff --git a/.github/workflows/build-release-apk.yml b/.github/workflows/build-release-apk.yml deleted file mode 100644 index 5ca055b9..00000000 --- a/.github/workflows/build-release-apk.yml +++ /dev/null @@ -1,154 +0,0 @@ -name: Release build - official - -on: - push: - tags: - - "*" - -jobs: - prepare: - name: Prepare build environment - runs-on: self-hosted - steps: - - name: Checkout repository - uses: actions/checkout@v2 - with: - fetch-depth: 0 - clean: false - - name: Set executable permissions to gradlew - run: chmod +x ./gradlew - - name: Setup Python - uses: actions/setup-python@v2 - - name: Install packages - uses: BSFishy/pip-action@v1 - with: - packages: | - python-dotenv - pycryptodome - mysql-connector-python - requests - - name: Write signing passwords - env: - DB_HOST: ${{ secrets.DB_HOST }} - DB_USER: ${{ secrets.DB_USER }} - DB_PASS: ${{ secrets.DB_PASS }} - DB_NAME: ${{ secrets.DB_NAME }} - run: python $GITHUB_WORKSPACE/.github/utils/sign.py $GITHUB_WORKSPACE commit - build: - name: Build APK - runs-on: self-hosted - needs: - - prepare - outputs: - androidHome: ${{ env.ANDROID_HOME }} - androidSdkRoot: ${{ env.ANDROID_SDK_ROOT }} - steps: - - name: Setup JDK 11 - uses: actions/setup-java@v2 - with: - distribution: 'temurin' - java-version: '11' - - name: Setup Android SDK - uses: android-actions/setup-android@v2 - - name: Clean build artifacts - run: | - rm -rf app/release/* - rm -rf app/build/outputs/apk/* - rm -rf app/build/outputs/bundle/* - - name: Assemble official release with Gradle - uses: gradle/gradle-build-action@v2 - with: - arguments: assembleOfficialRelease - sign: - name: Sign APK - runs-on: self-hosted - needs: - - build - outputs: - signedReleaseFile: ${{ steps.artifacts.outputs.signedReleaseFile }} - signedReleaseFileRelative: ${{ steps.artifacts.outputs.signedReleaseFileRelative }} - steps: - - name: Sign build artifacts - id: sign_app - uses: r0adkll/sign-android-release@v1 - with: - releaseDirectory: app/release - signingKeyBase64: ${{ secrets.KEY_STORE }} - alias: ${{ secrets.KEY_ALIAS }} - keyStorePassword: ${{ secrets.KEY_STORE_PASSWORD }} - keyPassword: ${{ secrets.KEY_ALIAS_PASSWORD }} - env: - ANDROID_HOME: ${{ needs.build.outputs.androidHome }} - ANDROID_SDK_ROOT: ${{ needs.build.outputs.androidSdkRoot }} - BUILD_TOOLS_VERSION: "30.0.2" - - name: Rename signed artifacts - id: artifacts - run: python $GITHUB_WORKSPACE/.github/utils/rename_artifacts.py $GITHUB_WORKSPACE - publish: - name: Publish APK - runs-on: self-hosted - needs: - - sign - steps: - - name: Setup Python - uses: actions/setup-python@v2 - - - name: Extract changelogs - id: changelog - run: python $GITHUB_WORKSPACE/.github/utils/extract_changelogs.py $GITHUB_WORKSPACE - - - name: Upload APK to SFTP - uses: easingthemes/ssh-deploy@v2.1.6 - env: - REMOTE_HOST: ${{ secrets.SSH_IP }} - REMOTE_USER: ${{ secrets.SSH_USERNAME }} - SSH_PRIVATE_KEY: ${{ secrets.SSH_KEY }} - SOURCE: ${{ needs.sign.outputs.signedReleaseFileRelative }} - TARGET: ${{ secrets.SSH_PATH_RELEASE }} - - name: Save version metadata - env: - DB_HOST: ${{ secrets.DB_HOST }} - DB_USER: ${{ secrets.DB_USER }} - DB_PASS: ${{ secrets.DB_PASS }} - DB_NAME: ${{ secrets.DB_NAME }} - APK_SERVER_RELEASE: ${{ secrets.APK_SERVER_RELEASE }} - APK_SERVER_NIGHTLY: ${{ secrets.APK_SERVER_NIGHTLY }} - run: python $GITHUB_WORKSPACE/.github/utils/save_version.py $GITHUB_WORKSPACE - - - name: Distribute to App Distribution - uses: wzieba/Firebase-Distribution-Github-Action@v1 - with: - appId: ${{ secrets.FIREBASE_APP_ID }} - token: ${{ secrets.FIREBASE_TOKEN }} - groups: ${{ secrets.FIREBASE_GROUPS_RELEASE }} - file: ${{ needs.sign.outputs.signedReleaseFile }} - releaseNotesFile: ${{ steps.changelog.outputs.changelogPlainTitledFile }} - - name: Release on GitHub - uses: softprops/action-gh-release@v1 - with: - name: ${{ steps.changelog.outputs.changelogTitle }} - body_path: ${{ steps.changelog.outputs.changelogMarkdownFile }} - files: ${{ needs.sign.outputs.signedReleaseFile }} - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - - name: Post Discord webhook - env: - APK_FILE: ${{ needs.sign.outputs.signedReleaseFile }} - APK_SERVER_RELEASE: ${{ secrets.APK_SERVER_RELEASE }} - APK_SERVER_NIGHTLY: ${{ secrets.APK_SERVER_NIGHTLY }} - WEBHOOK_RELEASE: ${{ secrets.WEBHOOK_RELEASE }} - WEBHOOK_TESTING: ${{ secrets.WEBHOOK_TESTING }} - run: python $GITHUB_WORKSPACE/.github/utils/webhook_discord.py $GITHUB_WORKSPACE - - - name: Upload workflow artifact - uses: actions/upload-artifact@v2 - if: true - with: - name: ${{ steps.changelog.outputs.appVersionName }} - path: | - app/release/whatsnew*/ - app/release/*.apk - app/release/*.aab - app/release/*.json - app/release/*.txt diff --git a/.github/workflows/push-master.yml b/.github/workflows/push-master.yml new file mode 100644 index 00000000..f8452a25 --- /dev/null +++ b/.github/workflows/push-master.yml @@ -0,0 +1,13 @@ +name: Push (master) +on: + push: + branches: ["master"] +jobs: + build: + name: Build for Google Play (AAB) + uses: szkolny-eu/szkolny-android/.github/workflows/_build.yml@develop + with: + build-aab: true + release-ssh: true + release-google-play: true + secrets: inherit diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 00000000..9227110c --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,15 @@ +name: Release +on: + push: + tags: ["v*.*.*"] +jobs: + build: + name: Build release (APK) + uses: szkolny-eu/szkolny-android/.github/workflows/_build.yml@develop + with: + build-apk: true + release-ssh: true + release-github: true + release-firebase: true + release-discord: true + secrets: inherit diff --git a/.github/workflows/schedule-dispatch.yml b/.github/workflows/schedule-dispatch.yml new file mode 100644 index 00000000..9b2ca12e --- /dev/null +++ b/.github/workflows/schedule-dispatch.yml @@ -0,0 +1,42 @@ +name: Schedule/dispatch +on: + schedule: + # 23:30 UTC, 0:30 or 1:30 CET/CEST + - cron: "30 23 * * *" + workflow_dispatch: +jobs: + check: + name: Check new changes + runs-on: ubuntu-latest + outputs: + hasNewChanges: ${{ steps.nightly.outputs.hasNewChanges }} + steps: + - name: Checkout repository + uses: actions/checkout@v3 + with: + fetch-depth: 0 + clean: false + - name: Setup Python + uses: actions/setup-python@v4 + - name: Install packages + uses: BSFishy/pip-action@v1 + with: + packages: | + requests + - name: Check new changes + id: nightly + run: python $GITHUB_WORKSPACE/.github/utils/check_nightly.py $GITHUB_WORKSPACE >> $GITHUB_OUTPUT + + build: + name: Build nightly release (APK) + needs: + - check + if: ${{ needs.check.outputs.hasNewChanges == 'true' }} + uses: szkolny-eu/szkolny-android/.github/workflows/_build.yml@develop + with: + nightly: true + build-apk: true + release-ssh: true + release-firebase: true + release-discord: true + secrets: inherit diff --git a/app/build.gradle b/app/build.gradle index 0ceae1a1..cf7b500b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -104,7 +104,6 @@ android { externalNativeBuild { cmake { path "src/main/cpp/CMakeLists.txt" - version "3.10.2" } } lint { @@ -113,8 +112,9 @@ android { } tasks.whenTaskAdded { task -> - if (!task.name.endsWith("Release") && !task.name.endsWith("ReleaseWithR8")) + if (!(task.name == "assembleUnofficialRelease" || task.name == "assembleOfficialRelease" || task.name == "signPlayReleaseBundle")) return + def renameTaskName = "rename${task.name.capitalize()}" def flavor = "" @@ -124,17 +124,22 @@ tasks.whenTaskAdded { task -> flavor = task.name.substring("assemble".length(), task.name.indexOf("Release")).uncapitalize() if (task.name.startsWith("minify")) flavor = task.name.substring("minify".length(), task.name.indexOf("Release")).uncapitalize() + if (task.name.startsWith("sign")) + flavor = task.name.substring("sign".length(), task.name.indexOf("Release")).uncapitalize() if (flavor != "") { - tasks.create(renameTaskName, Copy) { + tasks.register(renameTaskName, Copy) { + dependsOn(task.name) + duplicatesStrategy DuplicatesStrategy.FAIL from file("${projectDir}/${flavor}/release/"), - file("${buildDir}/outputs/mapping/${flavor}Release/"), - file("${buildDir}/outputs/apk/${flavor}/release/"), - file("${buildDir}/outputs/bundle/${flavor}Release/") - include "*.aab", "*.apk", "mapping.txt", "output-metadata.json" + file("${projectDir}/build/outputs/apk/${flavor}/release/"), + file("${projectDir}/build/outputs/mapping/${flavor}Release/"), + file("${projectDir}/build/outputs/bundle/${flavor}Release/") + include "*-release.aab", "*-release.apk", "mapping.txt", "output-metadata.json" destinationDir file("${projectDir}/release/") rename ".+?\\.(.+)", "Edziennik_${android.defaultConfig.versionName}_${flavor}." + '$1' } + task.finalizedBy(renameTaskName) } } diff --git a/app/src/main/cpp/CMakeLists.txt b/app/src/main/cpp/CMakeLists.txt index e8096e62..eea75650 100644 --- a/app/src/main/cpp/CMakeLists.txt +++ b/app/src/main/cpp/CMakeLists.txt @@ -5,6 +5,8 @@ cmake_minimum_required(VERSION 3.4.1) +project(szkolny-signing) + # Creates and names a library, sets it as either STATIC # or SHARED, and provides the relative paths to its source code. # You can define multiple libraries, and CMake builds them for you. @@ -41,4 +43,4 @@ target_link_libraries( # Specifies the target library. # Links the target library to the log library # included in the NDK. - ${log-lib} ) \ No newline at end of file + ${log-lib} )