diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index 14d36530..cc8fb7e0 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -8,11 +8,24 @@ name: Android CI on: push: branches: [ "master" ] + paths-ignore: + - 'README.md' + - 'doc/**' + - 'fastlane/**' + - 'assets/**' + - '.github/**/*.md' + - '.github/FUNDING.yml' + - '.github/ISSUE_TEMPLATE/**' pull_request: branches: [ "master" ] - -permissions: - contents: read + paths-ignore: + - 'README.md' + - 'doc/**' + - 'fastlane/**' + - 'assets/**' + - '.github/**/*.md' + - '.github/FUNDING.yml' + - '.github/ISSUE_TEMPLATE/**' jobs: @@ -20,20 +33,30 @@ jobs: runs-on: ubuntu-latest + permissions: + contents: read + steps: - - uses: actions/checkout@v3 - - name: Set up JDK 11 - uses: actions/setup-java@v3 + - uses: actions/checkout@v4 + - name: Set up JDK 17 + uses: actions/setup-java@v4 with: - java-version: '11' + java-version: 17 distribution: 'temurin' + cache: 'gradle' - name: Build with Gradle uses: gradle/gradle-build-action@bd5760595778326ba7f1441bcf7e88b49de61a25 # v2.6.0 with: - arguments: build + arguments: assembleDebug --stacktrace -DskipFormatKtlint #original: #- name: Grant execute permission for gradlew # run: chmod +x gradlew #- name: Build with Gradle # run: ./gradlew build + + - name: Upload APK + uses: actions/upload-artifact@v4 + with: + name: app + path: app/build/outputs/apk/debug/*.apk \ No newline at end of file diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml new file mode 100644 index 00000000..6fe464b2 --- /dev/null +++ b/.github/workflows/codeql.yml @@ -0,0 +1,38 @@ +name: "CodeQL" + +on: + push: + branches: [ "master" ] + pull_request: + branches: [ "master" ] + schedule: + - cron: '19 21 * * 1' + +jobs: + analyze: + name: Analyze + runs-on: 'ubuntu-latest' + timeout-minutes: 360 + permissions: + security-events: write + + strategy: + fail-fast: false + matrix: + language: [ 'java-kotlin' ] + # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v3 + with: + languages: ${{ matrix.language }} + # If you wish to specify custom queries, you can do so here or in a config file. + # By default, queries listed here will override any specified in a config file. + # Prefix the list here with "+" to use these queries and those in the config file. + # For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs + # queries: security-extended,security-and-quality \ No newline at end of file diff --git a/.github/workflows/image-minimizer.js b/.github/workflows/image-minimizer.js new file mode 100644 index 00000000..d099068b --- /dev/null +++ b/.github/workflows/image-minimizer.js @@ -0,0 +1,147 @@ +/* + * Script for minimizing big images (jpg,gif,png) when they are uploaded to GitHub and not edited otherwise + */ +module.exports = async ({github, context}) => { + const IGNORE_KEY = ''; + const IGNORE_ALT_NAME_END = 'ignoreImageMinify'; + // Targeted maximum height + const IMG_MAX_HEIGHT_PX = 600; + // maximum width of GitHub issues/comments + const IMG_MAX_WIDTH_PX = 800; + // all images that have a lower aspect ratio (-> have a smaller width) than this will be minimized + const MIN_ASPECT_RATIO = IMG_MAX_WIDTH_PX / IMG_MAX_HEIGHT_PX + + // Get the body of the image + let initialBody = null; + if (context.eventName == 'issue_comment') { + initialBody = context.payload.comment.body; + } else if (context.eventName == 'issues') { + initialBody = context.payload.issue.body; + } else if (context.eventName == 'pull_request') { + initialBody = context.payload.pull_request.body; + } else { + console.log('Aborting: No body found'); + return; + } + console.log(`Found body: \n${initialBody}\n`); + + // Check if we should ignore the currently processing element + if (initialBody.includes(IGNORE_KEY)) { + console.log('Ignoring: Body contains IGNORE_KEY'); + return; + } + + // Regex for finding images (simple variant) ![ALT_TEXT](https://*.githubusercontent.com//.) + const REGEX_USER_CONTENT_IMAGE_LOOKUP = /\!\[(.*)\]\((https:\/\/[-a-z0-9]+\.githubusercontent\.com\/\d+\/[-0-9a-f]{32,512}\.(jpg|gif|png))\)/gm; + const REGEX_ASSETS_IMAGE_LOCKUP = /\!\[(.*)\]\((https:\/\/github\.com\/[-\w\d]+\/[-\w\d]+\/assets\/\d+\/[\-0-9a-f]{32,512})\)/gm; + + // Check if we found something + let foundSimpleImages = REGEX_USER_CONTENT_IMAGE_LOOKUP.test(initialBody) + || REGEX_ASSETS_IMAGE_LOCKUP.test(initialBody); + if (!foundSimpleImages) { + console.log('Found no simple images to process'); + return; + } + + console.log('Found at least one simple image to process'); + + // Require the probe lib for getting the image dimensions + const probe = require('probe-image-size'); + + var wasMatchModified = false; + + // Try to find and replace the images with minimized ones + let newBody = await replaceAsync(initialBody, REGEX_USER_CONTENT_IMAGE_LOOKUP, minimizeAsync); + newBody = await replaceAsync(newBody, REGEX_ASSETS_IMAGE_LOCKUP, minimizeAsync); + + if (!wasMatchModified) { + console.log('Nothing was modified. Skipping update'); + return; + } + + // Update the corresponding element + if (context.eventName == 'issue_comment') { + console.log('Updating comment with id', context.payload.comment.id); + await github.rest.issues.updateComment({ + comment_id: context.payload.comment.id, + owner: context.repo.owner, + repo: context.repo.repo, + body: newBody + }) + } else if (context.eventName == 'issues') { + console.log('Updating issue', context.payload.issue.number); + await github.rest.issues.update({ + issue_number: context.payload.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + body: newBody + }); + } else if (context.eventName == 'pull_request') { + console.log('Updating pull request', context.payload.pull_request.number); + await github.rest.pulls.update({ + pull_number: context.payload.pull_request.number, + owner: context.repo.owner, + repo: context.repo.repo, + body: newBody + }); + } + + // Async replace function from https://stackoverflow.com/a/48032528 + async function replaceAsync(str, regex, asyncFn) { + const promises = []; + str.replace(regex, (match, ...args) => { + const promise = asyncFn(match, ...args); + promises.push(promise); + }); + const data = await Promise.all(promises); + return str.replace(regex, () => data.shift()); + } + + async function minimizeAsync(match, g1, g2) { + console.log(`Found match '${match}'`); + + if (g1.endsWith(IGNORE_ALT_NAME_END)) { + console.log(`Ignoring match '${match}': IGNORE_ALT_NAME_END`); + return match; + } + + let probeAspectRatio = 0; + let shouldModify = false; + try { + console.log(`Probing ${g2}`); + let probeResult = await probe(g2); + if (probeResult == null) { + throw 'No probeResult'; + } + if (probeResult.hUnits != 'px') { + throw `Unexpected probeResult.hUnits (expected px but got ${probeResult.hUnits})`; + } + if (probeResult.height <= 0) { + throw `Unexpected probeResult.height (height is invalid: ${probeResult.height})`; + } + if (probeResult.wUnits != 'px') { + throw `Unexpected probeResult.wUnits (expected px but got ${probeResult.wUnits})`; + } + if (probeResult.width <= 0) { + throw `Unexpected probeResult.width (width is invalid: ${probeResult.width})`; + } + console.log(`Probing resulted in ${probeResult.width}x${probeResult.height}px`); + + probeAspectRatio = probeResult.width / probeResult.height; + shouldModify = probeResult.height > IMG_MAX_HEIGHT_PX && probeAspectRatio < MIN_ASPECT_RATIO; + } catch(e) { + console.log('Probing failed:', e); + // Immediately abort + return match; + } + + if (shouldModify) { + wasMatchModified = true; + console.log(`Modifying match '${match}'`); + return `${g1}`; + } + + console.log(`Match '${match}' is ok/will not be modified`); + return match; + } +} diff --git a/.github/workflows/image-minimizer.yml b/.github/workflows/image-minimizer.yml new file mode 100644 index 00000000..34553735 --- /dev/null +++ b/.github/workflows/image-minimizer.yml @@ -0,0 +1,35 @@ +name: Image Minimizer + +on: + issue_comment: + types: [created, edited] + issues: + types: [opened, edited] + pull_request: + types: [opened, edited] + +permissions: + issues: write + pull-requests: write + +jobs: + try-minimize: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-node@v4 + with: + node-version: 16 + + - name: Install probe-image-size + run: npm i probe-image-size@7.2.3 --ignore-scripts + + - name: Minimize simple images + uses: actions/github-script@v7 + timeout-minutes: 3 + with: + script: | + const script = require('.github/workflows/image-minimizer.js'); + await script({github, context}); \ No newline at end of file diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml index cc96cf07..20c5fa2a 100644 --- a/app/src/main/res/xml/preferences.xml +++ b/app/src/main/res/xml/preferences.xml @@ -11,7 +11,6 @@ - - + + android:data="https://github.com/mdp43140/LTECleanerFOSS" /> + + + + \ No newline at end of file