CI integration, docker, GitHub actions (#1369)

* Update Dockerfile
* Update GitHub Actions
This commit is contained in:
Catfriend1 2025-05-06 02:53:57 +02:00 committed by GitHub
parent f9584ba8c0
commit ebe144452b
14 changed files with 237 additions and 47 deletions

52
.dockerignore Normal file
View File

@ -0,0 +1,52 @@
# docker specific
.git/
# built application files
*.apk
*.ap_
# files for the dex VM
*.dex
# Java class files
*.class
# generated files
.gradle/
app/build/
app/src/main/jniLibs
# gradle-play-publisher
.android/
*.keystore
*.jks
keys.json
# Local configuration file (sdk path, etc)
local.properties
project.properties
# Intellij project files
*.iml
*.ipr
*.iws
.idea/
# Gradle wrapper
gradle/wrapper/gradle/
gradle/wrapper/gradlew*
# Go modules
syncthing/pkg/mod/
syncthing/pkg/sumdb/
# External build artifacts
ext/
# files generated by the debug scripts
debug_scripts/*.xml
# Unsupported translations
app/src/main/play/listings/nb
app/src/main/play/listings/nl-BE
app/src/main/play/listings/nn

9
.gitattributes vendored
View File

@ -1,2 +1,9 @@
*.cmd text eol=crlf docker/* eol=lf
*.bash text eol=lf
*.bat text eol=crlf *.bat text eol=crlf
*.cmd text eol=crlf
*.dockerignore eol=lf
*.sh text eol=lf
gradlew eol=lf

42
.github/workflows/actions-setup.txt vendored Normal file
View File

@ -0,0 +1,42 @@
#
# https://github.com/settings/tokens/new
## Token name
### docker-push
## Expiration
### 30 days
## Permissions
### write:packages
### read:packages
### delete:packages
#
# Login
echo %GHP% | docker login ghcr.io -u catfriend1 --password-stdin
#
# Tag
docker tag syncthing-android-builder ghcr.io/catfriend1/syncthing-android-builder:latest
#
# Push container
docker push ghcr.io/catfriend1/syncthing-android-builder:latest
#
# Verify
## https://github.com/Catfriend1?tab=packages
#
# https://github.com/Catfriend1/syncthing-android/pkgs/container/syncthing-android-builder
## Link image to repository "Catfriend1/syncthing-android"
#
# https://github.com/users/Catfriend1/packages/container/syncthing-android-builder/settings
## Manage Actions access
### + Catfriend1/syncthing-android
#
# Setup actions
## https://github.com/Catfriend1/syncthing-android/settings/actions
### Allow GitHub Actions to use actions created by GitHub
### Allow actions created by Marketplace
#
# Add repository strings: https://github.com/Catfriend1/syncthing-android/settings/secrets/actions
## DEBUG_KEYSTORE_B64
### powershell "[Convert]::ToBase64String([IO.File]::ReadAllBytes(${env:USERPROFILE} + '\.android\debug.keystore'))" > "X:\debug.keystore.b64"
## SIGNING_KEYSTORE_JKS_BASE64
### powershell "[Convert]::ToBase64String([IO.File]::ReadAllBytes(${env:USERPROFILE} + '\.android\catfriend1.jks'))" > "X:\catfriend1.jks.b64"
## SIGNING_PASSWORD
### [PWD]

View File

@ -16,25 +16,28 @@ jobs:
build: build:
name: Debug Build name: Debug Build
runs-on: ubuntu-latest runs-on: ubuntu-latest
container: ghcr.io/syncthing/syncthing-android-builder container: ghcr.io/catfriend1/syncthing-android-builder
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
with: with:
submodules: true submodules: true
fetch-depth: 0 fetch-depth: 0
- name: build - name: build
run: | run: |
set -eu
mkdir -p ~/.android
echo '${{ secrets.DEBUG_KEYSTORE_B64 }}' | base64 -d > ~/.android/debug.keystore
git config --system --add safe.directory '*' git config --system --add safe.directory '*'
java -version java -version
./gradlew --no-daemon buildNative lint assembleDebug ./gradlew --no-daemon buildNative lintDebug assembleDebug
- uses: actions/upload-artifact@v3 - uses: actions/upload-artifact@v4
with: with:
name: syncthing-android-debug.apk name: syncthing-android-debug.apk
path: app/build/outputs/apk/debug/app-debug.apk path: app/build/outputs/apk/debug/app-debug.apk
- uses: actions/upload-artifact@v3 - uses: actions/upload-artifact@v4
with: with:
name: reports-and-libs name: reports-and-libs
path: | path: |

View File

@ -12,21 +12,21 @@ env:
BUILD_USER: android-builder BUILD_USER: android-builder
BUILD_HOST: github.syncthing.net BUILD_HOST: github.syncthing.net
# template var # template var
image: ghcr.io/syncthing/syncthing-android-builder image: ghcr.io/catfriend1/syncthing-android-builder
jobs: jobs:
build-image: build-image:
name: Build Builder Docker name: Build Builder Docker
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
with: with:
submodules: true submodules: true
fetch-depth: 0 fetch-depth: 0
- uses: docker/setup-buildx-action@v2 - uses: docker/setup-buildx-action@v2
- uses: docker/login-action@v2 - uses: docker/login-action@v3
if: ${{ inputs.push }} if: ${{ inputs.push }}
with: with:
registry: ghcr.io registry: ghcr.io

View File

@ -4,10 +4,10 @@ on:
push: push:
# Cannot filter on both branches (release) and tags - it's ORed # Cannot filter on both branches (release) and tags - it's ORed
tags: tags:
- '[0-9]+.[0-9]+.[0-9]+' - 'v[0-9]+.[0-9]+.[0-9]+'
- '[0-9]+.[0-9]+.[0-9]+.[0-9]+' - 'v[0-9]+.[0-9]+.[0-9]+.[0-9]+'
- '[0-9]+.[0-9]+.[0-9]+-rc\.[0-9]+' - 'v[0-9]+.[0-9]+.[0-9]+-rc\.[0-9]+'
- '[0-9]+.[0-9]+.[0-9]+-rc\.[0-9]+\.[0-9]+' - 'v[0-9]+.[0-9]+.[0-9]+-rc\.[0-9]+\.[0-9]+'
env: env:
# Our build metadata # Our build metadata
@ -18,9 +18,9 @@ jobs:
release: release:
name: Release Build and Publish name: Release Build and Publish
runs-on: ubuntu-latest runs-on: ubuntu-latest
container: ghcr.io/syncthing/syncthing-android-builder container: ghcr.io/catfriend1/syncthing-android-builder
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
with: with:
submodules: true submodules: true
fetch-depth: 0 fetch-depth: 0
@ -35,29 +35,30 @@ jobs:
- name: build_release - name: build_release
env: env:
SYNCTHING_RELEASE_KEY_ALIAS: android SYNCTHING_RELEASE_KEY_ALIAS: Syncthing-Fork
SIGNING_PASSWORD: '${{ secrets.SIGNING_PASSWORD }}' SIGNING_PASSWORD: '${{ secrets.SIGNING_PASSWORD }}'
SYNCTHING_RELEASE_STORE_FILE: '${{ runner.temp }}/signing-keystore.jks' SYNCTHING_RELEASE_STORE_FILE: '${{ runner.temp }}/signing-keystore.jks'
SYNCTHING_RELEASE_PLAY_ACCOUNT_CONFIG_FILE: '${{ runner.temp }}/google-play-secrets.json' # SYNCTHING_RELEASE_PLAY_ACCOUNT_CONFIG_FILE: '${{ runner.temp }}/google-play-secrets.json'
shell: bash shell: bash
run: | run: |
set -eu -o pipefail set -eu
echo '${{ secrets.SIGNING_KEYSTORE_JKS_BASE64 }}' | base64 -d > "$SYNCTHING_RELEASE_STORE_FILE" 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" # echo '${{ secrets.GOOGLE_PLAY_SECRETS_BASE64 }}' | base64 -d > "$SYNCTHING_RELEASE_PLAY_ACCOUNT_CONFIG_FILE"
java -version java -version
# TODO: Readd publishReleaseBundle if google play works again, or # TODO: Readd publishReleaseBundle if google play works again, or
# remove everything related to publishing to google play. # remove everything related to publishing to google play.
./gradlew --no-daemon buildNative lint assembleRelease bundleRelease ./gradlew --no-daemon buildNative lintRelease assembleRelease bundleRelease
rm "$SYNCTHING_RELEASE_STORE_FILE" "$SYNCTHING_RELEASE_PLAY_ACCOUNT_CONFIG_FILE" # rm "$SYNCTHING_RELEASE_STORE_FILE" "$SYNCTHING_RELEASE_PLAY_ACCOUNT_CONFIG_FILE"
echo '${{ secrets.GNUPG_SIGNING_KEY_BASE64 }}' | base64 -d | gpg --import # echo '${{ secrets.GNUPG_SIGNING_KEY_BASE64 }}' | base64 -d | gpg --import
cd app/build/outputs/apk/release # cd app/build/outputs/apk/release
sha256sum app-release.apk | gpg --clearsign > sha256sum.txt.asc # sha256sum app-release.apk | gpg --clearsign > sha256sum.txt.asc
- uses: ncipollo/release-action@v1 - uses: ncipollo/release-action@v1
with: with:
artifacts: "app/build/outputs/apk/release/*.apk,app/build/outputs/apk/release/*.asc" # TODO: Readd ,app/build/outputs/apk/release/*.asc
artifacts: "app/build/outputs/apk/release/*.apk"
artifactErrorsFailBuild: true artifactErrorsFailBuild: true
bodyFile: "app/src/main/play/release-notes/en-GB/default.txt" bodyFile: "app/src/main/play/release-notes/en-US/default.txt"
prerelease: ${{ contains('-rc.', github.ref_name) }} prerelease: ${{ contains('-rc.', github.ref_name) }}
draft: true draft: true

9
.gitignore vendored
View File

@ -9,8 +9,15 @@
*.class *.class
# generated files # generated files
build/
.gradle/ .gradle/
app/build/
app/src/main/jniLibs
# gradle-play-publisher
.android/
*.keystore
*.jks
keys.json
# Local configuration file (sdk path, etc) # Local configuration file (sdk path, etc)
local.properties local.properties

6
app/.gitignore vendored
View File

@ -1,6 +0,0 @@
# generated files
/build
/src/main/jniLibs
# gradle-play-publisher
keys.json

View File

@ -108,6 +108,8 @@ android {
packaging { packaging {
jniLibs { jniLibs {
// Otherwise libsyncthing.so doesn't appear where it should in installs
// based on app bundles, and thus nothing works.
useLegacyPackaging = true useLegacyPackaging = true
} }
} }

View File

@ -1,10 +1,10 @@
FROM eclipse-temurin:17-jdk-jammy FROM eclipse-temurin:17-jdk-jammy
ENV GO_VERSION 1.22.7 ENV GO_VERSION=1.24.1
# Can be found scrolling down on this page: # Can be found scrolling down on this page:
# https://developer.android.com/studio/index.html#command-tools # https://developer.android.com/studio/index.html#command-tools
ARG ANDROID_SDK_FILENAME=commandlinetools-linux-9123335_latest.zip ARG ANDROID_SDK_FILENAME=commandlinetools-linux-11076708_latest.zip
WORKDIR /opt WORKDIR /opt
# The '--reinstall' combined with 'build-essentials' is necessary for cgo # The '--reinstall' combined with 'build-essentials' is necessary for cgo
@ -16,15 +16,15 @@ RUN apt-get update && apt-get install --reinstall --no-install-recommends -y bui
RUN wget -nv 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 && \ tar -zxf go${GO_VERSION}.linux-amd64.tar.gz && \
rm go${GO_VERSION}.linux-amd64.tar.gz rm go${GO_VERSION}.linux-amd64.tar.gz
ENV GOROOT /opt/go ENV GOROOT=/opt/go
ENV PATH /opt/go/bin:${PATH} ENV PATH=/opt/go/bin:${PATH}
# Install Android SDK manager # Install Android SDK manager
RUN mkdir -p /opt/android-sdk && cd /opt/android-sdk && \ RUN mkdir -p /opt/android-sdk && cd /opt/android-sdk && \
wget -q https://dl.google.com/android/repository/${ANDROID_SDK_FILENAME} && \ wget -q https://dl.google.com/android/repository/${ANDROID_SDK_FILENAME} && \
unzip -q ${ANDROID_SDK_FILENAME} && \ unzip -q ${ANDROID_SDK_FILENAME} && \
rm ${ANDROID_SDK_FILENAME} rm ${ANDROID_SDK_FILENAME}
ENV ANDROID_HOME /opt/android-sdk ENV ANDROID_HOME=/opt/android-sdk
ARG SDKMANAGER="${ANDROID_HOME}/cmdline-tools/bin/sdkmanager --sdk_root=${ANDROID_HOME}" ARG SDKMANAGER="${ANDROID_HOME}/cmdline-tools/bin/sdkmanager --sdk_root=${ANDROID_HOME}"
@ -32,8 +32,8 @@ ARG SDKMANAGER="${ANDROID_HOME}/cmdline-tools/bin/sdkmanager --sdk_root=${ANDROI
RUN yes | $SDKMANAGER --licenses > /dev/null RUN yes | $SDKMANAGER --licenses > /dev/null
# NDK version # NDK version
ENV NDK_VERSION 27.0.12077973 ENV NDK_VERSION=28.0.13004108
ENV TARGET_SDK_VERSION 35 ENV TARGET_SDK_VERSION=35
# Install other android packages, including NDK # Install other android packages, including NDK
RUN $SDKMANAGER tools platform-tools "build-tools;${TARGET_SDK_VERSION}.0.0" "platforms;android-${TARGET_SDK_VERSION}" "extras;android;m2repository" "ndk;${NDK_VERSION}" RUN $SDKMANAGER tools platform-tools "build-tools;${TARGET_SDK_VERSION}.0.0" "platforms;android-${TARGET_SDK_VERSION}" "extras;android;m2repository" "ndk;${NDK_VERSION}"
@ -42,16 +42,20 @@ RUN $SDKMANAGER tools platform-tools "build-tools;${TARGET_SDK_VERSION}.0.0" "pl
RUN yes | $SDKMANAGER --licenses RUN yes | $SDKMANAGER --licenses
# Enable prebuild mode # Enable prebuild mode
ENV SYNCTHING_ANDROID_PREBUILT 1 ENV SYNCTHING_ANDROID_PREBUILT=1
# Set location of go cache # Set location of go cache
ENV GOCACHE /opt/gocache ENV GOCACHE=/opt/gocache
# Set location of GOPATH to persist packages for module builds in GOPATH/pkg/mod # Set location of GOPATH to persist packages for module builds in GOPATH/pkg/mod
ENV GOPATH /opt/gopath ENV GOPATH=/opt/gopath
# Run prebuild script (will prebuild stuff into the image if env var is set) # Run prebuild script (will prebuild stuff into the image if env var is set)
ADD . /opt/syncthing-android ADD . /opt/syncthing-android
RUN find /opt/syncthing-android -name "*.sh" -exec sed -i 's/\r$//' {} \;
RUN find /opt/syncthing-android -name "gradlew" -exec sed -i 's/\r$//' {} \;
RUN /opt/syncthing-android/docker/prebuild.sh RUN /opt/syncthing-android/docker/prebuild.sh
WORKDIR /mnt WORKDIR /mnt

View File

@ -1,3 +1,72 @@
# Fresh howto to build with Docker Desktop under WSL 2
## Add WSL feature
```
dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart
dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart
```
## Reboot
```
shutdown -r -t 0
```
## Set WSL version 2
```
wsl --set-default-version 2
```
## Install Debian Linux
```
wsl.exe --install debian
wsl.exe -l -v
```
## Install Docker Desktop
- Download https://desktop.docker.com/win/main/amd64/Docker%20Desktop%20Installer.exe
- Install
- logoff
- Relogon
## Docker Desktop
- Settings
- Resources
- Resources / Advanced
- Resources / Advanced / Disk image location
```
%LocalAppData%\docker\wsl
```
- Resources / Advanced / WSL integration
Enable integration with my default WSL distro
```
Debian
```
## Docker build step
- Open "cmd"
```
cd /d "syncthing-android"
docker build -t syncthing-android-builder:latest -f docker/Dockerfile .
docker run --rm -v "%userprofile%/.android/debug.keystore:/root/.android/debug.keystore:ro" -v .:/mnt syncthing-android-builder:latest ./gradlew buildNative assembleDebug
```
## Container insight
```
docker run -it --rm syncthing-android-builder bash
du -h -d 1 /
du -h -d 1 /opt
du -h -d 1 /root
```
## Destroy docker container
```
docker images
docker rmi syncthing-android-builder:latest
```
# How to use this # How to use this
## Create the builder image ## Create the builder image

View File

@ -1,4 +1,4 @@
#!/bin/bash -e #!/bin/bash
if [ -z "$SYNCTHING_ANDROID_PREBUILT" ]; then if [ -z "$SYNCTHING_ANDROID_PREBUILT" ]; then
echo "Prebuild disabled" echo "Prebuild disabled"

View File

@ -2,3 +2,4 @@ android.enableJetifier=false
android.nonFinalResIds=false android.nonFinalResIds=false
android.nonTransitiveRClass=false android.nonTransitiveRClass=false
android.useAndroidX=true android.useAndroidX=true
org.gradle.jvmargs=-Xmx4096M

View File

@ -29,6 +29,7 @@ NDK_VERSION = 'r28'
NDK_EXPECTED_SHASUM_LINUX = '894f469c5192a116d21f412de27966140a530ebc' NDK_EXPECTED_SHASUM_LINUX = '894f469c5192a116d21f412de27966140a530ebc'
NDK_EXPECTED_SHASUM_WINDOWS = 'f79a00c721dc5c15b2bf093d7bb2af96496a42b2' NDK_EXPECTED_SHASUM_WINDOWS = 'f79a00c721dc5c15b2bf093d7bb2af96496a42b2'
# The values here must correspond with those in ../docker/prebuild.sh
BUILD_TARGETS = [ BUILD_TARGETS = [
{ {
'arch': 'arm', 'arch': 'arm',
@ -226,11 +227,18 @@ def write_file(fullfn, text):
def get_ndk_ready(): def get_ndk_ready():
if os.environ.get('ANDROID_NDK_HOME', ''): if os.environ.get('ANDROID_NDK_HOME', ''):
return return
if not (os.environ.get('NDK_VERSION', '') and os.environ.get('ANDROID_SDK_ROOT', '')): ndk_env_vars_defined = True
print('ANDROID_NDK_HOME env var is not defined. Then, NDK_VERSION and ANDROID_SDK_ROOT env vars must be defined.') if not os.environ.get('NDK_VERSION', ''):
print('NDK_VERSION is NOT defined.')
ndk_env_vars_defined = False
if not os.environ.get('ANDROID_HOME', ''):
print('ANDROID_HOME is NOT defined.')
ndk_env_vars_defined = False
if not ndk_env_vars_defined:
print('ANDROID_NDK_HOME or NDK_VERSION and ANDROID_HOME environment variable must be defined.')
install_ndk() install_ndk()
return return
os.environ["ANDROID_NDK_HOME"] = os.path.join(os.environ['ANDROID_SDK_ROOT'], 'ndk', os.environ['NDK_VERSION']) os.environ["ANDROID_NDK_HOME"] = os.path.join(os.environ['ANDROID_HOME'], 'ndk', os.environ['NDK_VERSION'])
return return