From cf0a370dc9c019fedbdd3f211281f8717e07331a Mon Sep 17 00:00:00 2001 From: Catfriend1 <16361913+Catfriend1@users.noreply.github.com> Date: Tue, 10 Dec 2024 20:55:43 +0100 Subject: [PATCH] Docker, Dependabot and GitHub Workflows (#1198) --- .github/dependabot.yml | 45 +++++++++++++ .github/pull_request_template.md | 17 +++++ .github/workflows/build-app.yaml | 42 +++++++++++++ .github/workflows/build-builder.yaml | 20 ++++++ .github/workflows/image-builder-template.yaml | 41 ++++++++++++ .github/workflows/release-app.yaml | 63 +++++++++++++++++++ docker/Dockerfile | 46 +++++++++----- docker/README.md | 18 ++++-- docker/prebuild.sh | 42 +++---------- 9 files changed, 279 insertions(+), 55 deletions(-) create mode 100644 .github/dependabot.yml create mode 100644 .github/pull_request_template.md create mode 100644 .github/workflows/build-app.yaml create mode 100644 .github/workflows/build-builder.yaml create mode 100644 .github/workflows/image-builder-template.yaml create mode 100644 .github/workflows/release-app.yaml diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 000000000..412a37122 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,45 @@ +version: 2 +updates: +- package-ecosystem: gradle + directory: "/" + schedule: + interval: weekly + open-pull-requests-limit: 10 + groups: + dagger: + patterns: + - "com.google.dagger:dagger*" + ignore: + - dependency-name: androidx.annotation:annotation + versions: + - "> 1.1.0" + - dependency-name: androidx.constraintlayout:constraintlayout + versions: + - "> 1.1.3" + - dependency-name: com.android.tools.build:gradle + versions: + - "> 3.6.3" + - dependency-name: com.github.triplet.play + versions: + - "> 2.8.0" + - dependency-name: com.google.android.material:material + versions: + - "> 1.0.0" + - dependency-name: com.google.zxing:core + versions: + - "> 3.3.0" + - dependency-name: com.google.dagger:dagger-compiler + versions: + - 2.31.2 + - "2.32" + - "2.33" + - "2.34" + - 2.34.1 + - "2.35" + - dependency-name: com.google.dagger:dagger + versions: + - 2.31.2 + - "2.32" + - "2.33" + - "2.34" + - 2.34.1 diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 000000000..57e7714a8 --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,17 @@ +# Description +Describe what this PR is about + +# Changes +What changes are made in this PR +* change 1 +* change 2 + +# Screenshots +In case of UI changes, add before and after screenshots + +| Before | After | +| ------ | ----- | +| ![before][] | ![after][] | + +[before]: before.png +[after]: after.png diff --git a/.github/workflows/build-app.yaml b/.github/workflows/build-app.yaml new file mode 100644 index 000000000..bb28e6332 --- /dev/null +++ b/.github/workflows/build-app.yaml @@ -0,0 +1,42 @@ +name: Build App + +on: + pull_request: + push: + branches: + - main + - release + +env: + # Our build metadata + BUILD_USER: android-builder + BUILD_HOST: github.syncthing.net + +jobs: + build: + name: Debug Build + runs-on: ubuntu-latest + container: ghcr.io/syncthing/syncthing-android-builder + steps: + - uses: actions/checkout@v3 + with: + submodules: true + fetch-depth: 0 + + - name: build + run: | + git config --system --add safe.directory '*' + java -version + ./gradlew --no-daemon buildNative lint assembleDebug + + - uses: actions/upload-artifact@v3 + with: + name: syncthing-android-debug.apk + path: app/build/outputs/apk/debug/app-debug.apk + + - uses: actions/upload-artifact@v3 + with: + name: reports-and-libs + path: | + app/build/reports/** + app/src/main/jniLibs/** diff --git a/.github/workflows/build-builder.yaml b/.github/workflows/build-builder.yaml new file mode 100644 index 000000000..a741f935f --- /dev/null +++ b/.github/workflows/build-builder.yaml @@ -0,0 +1,20 @@ +name: Builder Image + +on: + pull_request: + paths: + - 'docker/**' + workflow_dispatch: + +jobs: + build-image: + if: github.event_name == 'pull_request' + uses: ./.github/workflows/image-builder-template.yaml + with: + push: false + + push-image: + if: github.event_name == 'workflow_dispatch' + uses: ./.github/workflows/image-builder-template.yaml + with: + push: true diff --git a/.github/workflows/image-builder-template.yaml b/.github/workflows/image-builder-template.yaml new file mode 100644 index 000000000..c6e2eda60 --- /dev/null +++ b/.github/workflows/image-builder-template.yaml @@ -0,0 +1,41 @@ +name: Image Builder Template + +on: + workflow_call: + inputs: + push: + required: true + type: boolean + +env: + # Our build metadata + BUILD_USER: android-builder + BUILD_HOST: github.syncthing.net + # template var + image: ghcr.io/syncthing/syncthing-android-builder + +jobs: + build-image: + name: Build Builder Docker + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + with: + submodules: true + fetch-depth: 0 + + - uses: docker/setup-buildx-action@v2 + + - uses: docker/login-action@v2 + if: ${{ inputs.push }} + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - uses: docker/build-push-action@v4 + with: + context: . + file: ./docker/Dockerfile + tags: '${{ env.image }}:latest,${{ env.image }}:${{ github.sha }}' + push: ${{ inputs.push }} diff --git a/.github/workflows/release-app.yaml b/.github/workflows/release-app.yaml new file mode 100644 index 000000000..0c782228c --- /dev/null +++ b/.github/workflows/release-app.yaml @@ -0,0 +1,63 @@ +name: Release App + +on: + push: + # Cannot filter on both branches (release) and tags - it's ORed + tags: + - '[0-9]+.[0-9]+.[0-9]+' + - '[0-9]+.[0-9]+.[0-9]+.[0-9]+' + - '[0-9]+.[0-9]+.[0-9]+-rc\.[0-9]+' + - '[0-9]+.[0-9]+.[0-9]+-rc\.[0-9]+\.[0-9]+' + +env: + # Our build metadata + BUILD_USER: android-builder + BUILD_HOST: github.syncthing.net + +jobs: + release: + name: Release Build and Publish + runs-on: ubuntu-latest + container: ghcr.io/syncthing/syncthing-android-builder + steps: + - uses: actions/checkout@v3 + with: + submodules: true + fetch-depth: 0 + + - name: Ensure release branch + run: | + git config --system --add safe.directory '*' + if ! git branch -a --contains $(git rev-parse HEAD) | grep release >/dev/null; then + echo "Tag is not part of release branch - aborting..." + exit 1 + fi + + - name: build_release + env: + SYNCTHING_RELEASE_KEY_ALIAS: android + SIGNING_PASSWORD: '${{ secrets.SIGNING_PASSWORD }}' + SYNCTHING_RELEASE_STORE_FILE: '${{ runner.temp }}/signing-keystore.jks' + SYNCTHING_RELEASE_PLAY_ACCOUNT_CONFIG_FILE: '${{ runner.temp }}/google-play-secrets.json' + shell: bash + run: | + set -eu -o pipefail + echo '${{ secrets.SIGNING_KEYSTORE_JKS_BASE64 }}' | base64 -d > "$SYNCTHING_RELEASE_STORE_FILE" + echo '${{ secrets.GOOGLE_PLAY_SECRETS_BASE64 }}' | base64 -d > "$SYNCTHING_RELEASE_PLAY_ACCOUNT_CONFIG_FILE" + java -version + # TODO: Readd publishReleaseBundle if google play works again, or + # remove everything related to publishing to google play. + ./gradlew --no-daemon buildNative lint assembleRelease bundleRelease + rm "$SYNCTHING_RELEASE_STORE_FILE" "$SYNCTHING_RELEASE_PLAY_ACCOUNT_CONFIG_FILE" + + echo '${{ secrets.GNUPG_SIGNING_KEY_BASE64 }}' | base64 -d | gpg --import + cd app/build/outputs/apk/release + sha256sum app-release.apk | gpg --clearsign > sha256sum.txt.asc + + - uses: ncipollo/release-action@v1 + with: + artifacts: "app/build/outputs/apk/release/*.apk,app/build/outputs/apk/release/*.asc" + artifactErrorsFailBuild: true + bodyFile: "app/src/main/play/release-notes/en-GB/default.txt" + prerelease: ${{ contains('-rc.', github.ref_name) }} + draft: true diff --git a/docker/Dockerfile b/docker/Dockerfile index d1bf5d65e..556fdd9ba 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -1,12 +1,19 @@ -FROM openjdk:8 +FROM eclipse-temurin:11-jdk-jammy -ENV GO_VERSION 1.11.4 -ENV ANDROID_SDK_VERSION 4333796 +ENV GO_VERSION 1.22.7 +# Can be found scrolling down on this page: +# https://developer.android.com/studio/index.html#command-tools +ARG ANDROID_SDK_FILENAME=commandlinetools-linux-9123335_latest.zip WORKDIR /opt +# The '--reinstall' combined with 'build-essentials' is necessary for cgo +# compilation of go std libs to work. A terrible, arcane hack to solve arkane +# cgo issues - almost fitting. +RUN apt-get update && apt-get install --reinstall --no-install-recommends -y build-essential gcc unzip git gnupg python3 + # Install Go -RUN wget -q https://dl.google.com/go/go${GO_VERSION}.linux-amd64.tar.gz && \ +RUN wget -nv https://dl.google.com/go/go${GO_VERSION}.linux-amd64.tar.gz && \ tar -zxf go${GO_VERSION}.linux-amd64.tar.gz && \ rm go${GO_VERSION}.linux-amd64.tar.gz ENV GOROOT /opt/go @@ -14,28 +21,37 @@ ENV PATH /opt/go/bin:${PATH} # Install Android SDK manager RUN mkdir -p /opt/android-sdk && cd /opt/android-sdk && \ - wget -q https://dl.google.com/android/repository/sdk-tools-linux-${ANDROID_SDK_VERSION}.zip && \ - unzip -q sdk-tools-linux-${ANDROID_SDK_VERSION}.zip && \ - rm sdk-tools-linux-${ANDROID_SDK_VERSION}.zip + wget -q https://dl.google.com/android/repository/${ANDROID_SDK_FILENAME} && \ + unzip -q ${ANDROID_SDK_FILENAME} && \ + rm ${ANDROID_SDK_FILENAME} ENV ANDROID_HOME /opt/android-sdk +ARG SDKMANAGER="${ANDROID_HOME}/cmdline-tools/bin/sdkmanager --sdk_root=${ANDROID_HOME}" + # Accept the SDK license, as we can't install packages otherwise -RUN yes | ${ANDROID_HOME}/tools/bin/sdkmanager --licenses +RUN yes | $SDKMANAGER --licenses > /dev/null + +# NDK version +ENV NDK_VERSION 27.0.12077973 +ENV TARGET_SDK_VERSION 35 # Install other android packages, including NDK -RUN ${ANDROID_HOME}/tools/bin/sdkmanager tools platform-tools "build-tools;28.0.3" "platforms;android-28" "extras;android;m2repository" ndk-bundle +RUN $SDKMANAGER tools platform-tools "build-tools;${TARGET_SDK_VERSION}.0.0" "platforms;android-${TARGET_SDK_VERSION}" "extras;android;m2repository" "ndk;${NDK_VERSION}" # Accept licenses of newly installed packages -RUN yes | ${ANDROID_HOME}/tools/bin/sdkmanager --licenses - -# Setup the NDK path -ENV ANDROID_NDK_HOME ${ANDROID_HOME}/ndk-bundle +RUN yes | $SDKMANAGER --licenses # Enable prebuild mode ENV SYNCTHING_ANDROID_PREBUILT 1 +# Set location of go cache +ENV GOCACHE /opt/gocache + +# Set location of GOPATH to persist packages for module builds in GOPATH/pkg/mod +ENV GOPATH /opt/gopath + # Run prebuild script (will prebuild stuff into the image if env var is set) -ADD prebuild.sh /opt/prebuild.sh -RUN /opt/prebuild.sh +ADD . /opt/syncthing-android +RUN /opt/syncthing-android/docker/prebuild.sh WORKDIR /mnt diff --git a/docker/README.md b/docker/README.md index 99546eb6f..39038d0ff 100644 --- a/docker/README.md +++ b/docker/README.md @@ -1,7 +1,15 @@ # How to use this -1. Build the docker image: `docker build -t syncthing-android-builder:latest .` -2. Checkout syncthing-android somewhere (for the sake of discussion let's say /tmp/syncthing-android) -3. Inside /tmp/syncthing-android, do `git submodule init; git submodule update` -4. Run `docker run --rm -v /tmp/syncthing-android:/mnt syncthing-android-builder ./gradlew buildNative assembleDebug` -5. Retrieve APKs from /tmp/syncthing-android/app/build/outputs +## Create the builder image + +From inside the checked out syncthing-android repository, run: + +`docker build -t syncthing-android-builder:latest -f ./docker/Dockerfile .` + +## Build the app + +1. From inside the checked out syncthing-android repository, run: + `git submodule init; git submodule update` +2. Actual build: + `docker run --rm -v /tmp/syncthing-android:/mnt syncthing-android-builder ./gradlew buildNative assembleDebug` +3. Retrieve APKs from ./app/build/outputs diff --git a/docker/prebuild.sh b/docker/prebuild.sh index e2d8d5d13..117e64dca 100755 --- a/docker/prebuild.sh +++ b/docker/prebuild.sh @@ -1,41 +1,13 @@ #!/bin/bash -e -[ -z "$SYNCTHING_ANDROID_PREBUILT" ] && echo "Prebuild disabled" && exit 0 +if [ -z "$SYNCTHING_ANDROID_PREBUILT" ]; then + echo "Prebuild disabled" + rm -rf syncthing-android + exit 0 +fi -for ARCH in arm x86 arm64; do - GOARCH=${ARCH} - SDK=16 - case ${ARCH} in - arm) - GCC="arm-linux-androideabi-clang" - ;; - arm64) - SDK=21 - GCC="aarch64-linux-android-clang" - ;; - x86) - GOARCH=386 - GCC="i686-linux-android-clang" - ;; - *) - echo "Invalid architecture" - exit 1 - esac - - STANDALONE_NDK_DIR="${ANDROID_NDK_HOME}/standalone-ndk/android-${SDK}-${GOARCH}" - echo "Building standalone NDK - ${STANDALONE_NDK_DIR}" - ${ANDROID_NDK_HOME}/build/tools/make-standalone-toolchain.sh \ - --platform=android-${SDK} --arch=${ARCH} \ - --install-dir=${STANDALONE_NDK_DIR} - - echo "Pre-building Go standard library for $GOARCH" - CGO_ENABLED=1 CC="${STANDALONE_NDK_DIR}/bin/${GCC}" \ - GOOS=android GOARCH=$GOARCH go install -v std -done - -echo "Prepopulating gradle cache" -git clone https://github.com/syncthing/syncthing-android +echo "Prepopulating gradle and go build/pkg cache" cd syncthing-android -./gradlew --no-daemon lint +./gradlew --no-daemon lint buildNative cd .. rm -rf syncthing-android