Skip to content

Commit c9858ff

Browse files
committed
Initial project
1 parent 1efa603 commit c9858ff

File tree

78 files changed

+5638
-1233
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

78 files changed

+5638
-1233
lines changed

.editorconfig

Lines changed: 555 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 248 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,248 @@
1+
name: Build and Release APK
2+
3+
on:
4+
push:
5+
tags:
6+
- "v*"
7+
pull_request:
8+
branches: [main]
9+
workflow_dispatch:
10+
11+
env:
12+
GRADLE_OPTS: -Dorg.gradle.jvmargs="-Xmx4g -XX:+HeapDumpOnOutOfMemoryError"
13+
14+
jobs:
15+
build-arm64:
16+
runs-on: ubuntu-latest
17+
strategy:
18+
matrix:
19+
arch: [arm64]
20+
21+
steps:
22+
- name: Checkout code
23+
uses: actions/checkout@v4
24+
25+
- name: Set up JDK 17
26+
uses: actions/setup-java@v4
27+
with:
28+
java-version: "17"
29+
distribution: "temurin"
30+
31+
- name: Cache Gradle dependencies
32+
uses: actions/cache@v4
33+
with:
34+
path: |
35+
~/.gradle/caches
36+
~/.gradle/wrapper
37+
key: ${{ runner.os }}-gradle-${{ matrix.arch }}-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
38+
restore-keys: |
39+
${{ runner.os }}-gradle-${{ matrix.arch }}-
40+
${{ runner.os }}-gradle-
41+
42+
- name: Make gradlew executable
43+
run: chmod +x gradlew
44+
45+
- name: Make download script executable
46+
run: chmod +x download-agent.sh
47+
48+
- name: Download ARM64 Nezha agent binary
49+
run: |
50+
echo "Downloading ARM64 binary..."
51+
./download-agent.sh arm64
52+
53+
- name: Build release APK for ARM64 (if signed)
54+
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/')
55+
env:
56+
KEYSTORE_FILE: ${{ secrets.KEYSTORE_FILE }}
57+
KEYSTORE_PASSWORD: ${{ secrets.KEYSTORE_PASSWORD }}
58+
KEY_ALIAS: ${{ secrets.KEY_ALIAS }}
59+
KEY_PASSWORD: ${{ secrets.KEY_PASSWORD }}
60+
run: |
61+
if [ -n "$KEYSTORE_FILE" ]; then
62+
echo "Keystore found, building signed release APK for ARM64..."
63+
echo "$KEYSTORE_FILE" | base64 -d > keystore.jks
64+
./gradlew assembleRelease --stacktrace
65+
else
66+
echo "No keystore configured, skipping signed release build"
67+
fi
68+
mv app/build/outputs/apk/release/app-release.apk app/build/outputs/apk/release/app-arm64-v8a-release.apk
69+
70+
- name: Upload ARM64 release APK
71+
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/')
72+
uses: actions/upload-artifact@v4
73+
with:
74+
name: app-release-arm64
75+
path: app/build/outputs/apk/release/app-arm64-v8a-release.apk
76+
77+
build-arm:
78+
runs-on: ubuntu-latest
79+
strategy:
80+
matrix:
81+
arch: [arm]
82+
83+
steps:
84+
- name: Checkout code
85+
uses: actions/checkout@v4
86+
87+
- name: Set up JDK 17
88+
uses: actions/setup-java@v4
89+
with:
90+
java-version: "17"
91+
distribution: "temurin"
92+
93+
- name: Cache Gradle dependencies
94+
uses: actions/cache@v4
95+
with:
96+
path: |
97+
~/.gradle/caches
98+
~/.gradle/wrapper
99+
key: ${{ runner.os }}-gradle-${{ matrix.arch }}-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
100+
restore-keys: |
101+
${{ runner.os }}-gradle-${{ matrix.arch }}-
102+
${{ runner.os }}-gradle-
103+
104+
- name: Make gradlew executable
105+
run: chmod +x gradlew
106+
107+
- name: Make download script executable
108+
run: chmod +x download-agent.sh
109+
110+
- name: Download ARM Nezha agent binary
111+
run: |
112+
echo "Downloading ARM binary..."
113+
./download-agent.sh arm
114+
115+
- name: Build release APK for ARM (if signed)
116+
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/')
117+
env:
118+
KEYSTORE_FILE: ${{ secrets.KEYSTORE_FILE }}
119+
KEYSTORE_PASSWORD: ${{ secrets.KEYSTORE_PASSWORD }}
120+
KEY_ALIAS: ${{ secrets.KEY_ALIAS }}
121+
KEY_PASSWORD: ${{ secrets.KEY_PASSWORD }}
122+
run: |
123+
if [ -n "$KEYSTORE_FILE" ]; then
124+
echo "Keystore found, building signed release APK for ARM..."
125+
echo "$KEYSTORE_FILE" | base64 -d > keystore.jks
126+
./gradlew assembleRelease --stacktrace
127+
else
128+
echo "No keystore configured, skipping signed release build"
129+
fi
130+
mv app/build/outputs/apk/release/app-release.apk app/build/outputs/apk/release/app-armeabi-v7a-release.apk
131+
132+
- name: Upload ARM release APK
133+
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/')
134+
uses: actions/upload-artifact@v4
135+
with:
136+
name: app-release-arm
137+
path: app/build/outputs/apk/release/app-armeabi-v7a-release.apk
138+
139+
release:
140+
needs: [build-arm64, build-arm]
141+
runs-on: ubuntu-latest
142+
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/')
143+
144+
steps:
145+
- name: Checkout code
146+
uses: actions/checkout@v4
147+
148+
- name: Download ARM64 release APK (if available)
149+
continue-on-error: true
150+
uses: actions/download-artifact@v4
151+
with:
152+
name: app-release-arm64
153+
path: ./artifacts/arm64/
154+
155+
- name: Download ARM release APK (if available)
156+
continue-on-error: true
157+
uses: actions/download-artifact@v4
158+
with:
159+
name: app-release-arm
160+
path: ./artifacts/arm/
161+
162+
- name: Get version from tag
163+
id: version
164+
run: echo "VERSION=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT
165+
166+
- name: Prepare release files
167+
run: |
168+
mkdir -p release-files
169+
170+
# Copy ARM64 release APK with version name
171+
if [ -f "./artifacts/arm64/app-arm64-v8a-release.apk" ]; then
172+
cp "./artifacts/arm64/app-arm64-v8a-release.apk" "release-files/Ulmaridae-${{ steps.version.outputs.VERSION }}-arm64-release.apk"
173+
fi
174+
175+
# Copy ARM release APK with version name
176+
if [ -f "./artifacts/arm/app-armeabi-v7a-release.apk" ]; then
177+
cp "./artifacts/arm/app-armeabi-v7a-release.apk" "release-files/Ulmaridae-${{ steps.version.outputs.VERSION }}-arm-release.apk"
178+
fi
179+
180+
# List files for verification
181+
ls
182+
ls -la release-files/
183+
184+
- name: Generate release notes
185+
id: release_notes
186+
run: |
187+
RELEASE_NOTES="
188+
189+
## 🚀 **Ulmaridae ${{ steps.version.outputs.VERSION }}**
190+
191+
A lightweight Android wrapper for the Nezha monitoring agent, designed to run on Android devices with or without root privileges.
192+
193+
### Installation
194+
1. Download the appropriate APK for your device architecture
195+
2. Install the APK (enable \"Install from unknown sources\" if needed)
196+
3. Open the app and configure your Nezha server details
197+
4. Grant necessary permissions when prompted
198+
5. Toggle the \"Enable Nezha Agent\" switch to start monitoring
199+
200+
### APK Variants
201+
202+
#### ARM64 (arm64) - Recommended for modern devices
203+
#### ARM (armeabi-v7a) - For older devices
204+
205+
### Requirements
206+
- Android 7.0 (API level 24) or higher
207+
- ARM or ARM64 device architecture
208+
- Internet connection for server communication"
209+
210+
- name: Create GitHub Release
211+
uses: softprops/action-gh-release@v2
212+
with:
213+
tag_name: ${{ steps.version.outputs.VERSION }}
214+
name: "Ulmaridae ${{ steps.version.outputs.VERSION }}"
215+
body: ${{ steps.release_notes.outputs.RELEASE_NOTES }}
216+
files: release-files/*
217+
draft: false
218+
prerelease: ${{ contains(steps.version.outputs.VERSION, '-') }}
219+
generate_release_notes: true
220+
env:
221+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
222+
223+
security-scan:
224+
runs-on: ubuntu-latest
225+
if: github.event_name == 'pull_request'
226+
227+
steps:
228+
- name: Checkout code
229+
uses: actions/checkout@v4
230+
231+
- name: Set up JDK 17
232+
uses: actions/setup-java@v4
233+
with:
234+
java-version: "17"
235+
distribution: "temurin"
236+
237+
- name: Cache Gradle dependencies
238+
uses: actions/cache@v4
239+
with:
240+
path: |
241+
~/.gradle/caches
242+
~/.gradle/wrapper
243+
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
244+
restore-keys: |
245+
${{ runner.os }}-gradle-
246+
247+
- name: Make gradlew executable
248+
run: chmod +x gradlew

.github/workflows/ci.yml

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: [main, develop]
6+
pull_request:
7+
branches: [main, develop]
8+
9+
env:
10+
GRADLE_OPTS: -Dorg.gradle.jvmargs="-Xmx4g -XX:+HeapDumpOnOutOfMemoryError"
11+
12+
jobs:
13+
test:
14+
runs-on: ubuntu-latest
15+
16+
steps:
17+
- name: Checkout code
18+
uses: actions/checkout@v4
19+
20+
- name: Set up JDK 17
21+
uses: actions/setup-java@v4
22+
with:
23+
java-version: "17"
24+
distribution: "temurin"
25+
26+
- name: Cache Gradle dependencies
27+
uses: actions/cache@v4
28+
with:
29+
path: |
30+
~/.gradle/caches
31+
~/.gradle/wrapper
32+
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
33+
restore-keys: |
34+
${{ runner.os }}-gradle-
35+
36+
- name: Make gradlew executable
37+
run: chmod +x gradlew
38+
39+
- name: Make download script executable
40+
run: chmod +x download-agent.sh
41+
42+
- name: Download Nezha agent binaries for testing
43+
run: |
44+
echo "Downloading ARM64 binary for CI testing..."
45+
./download-agent.sh arm64
46+
47+
- name: Run unit tests
48+
run: ./gradlew testDebugUnitTest --stacktrace
49+
50+
- name: Run lint checks
51+
run: ./gradlew lintDebug --stacktrace
52+
53+
- name: Build debug APK
54+
run: ./gradlew assembleDebug --stacktrace
55+
56+
- name: Upload test results
57+
if: always()
58+
uses: actions/upload-artifact@v4
59+
with:
60+
name: test-results
61+
path: |
62+
app/build/reports/tests/
63+
app/build/test-results/
64+
65+
- name: Upload lint results
66+
if: always()
67+
uses: actions/upload-artifact@v4
68+
with:
69+
name: lint-results
70+
path: app/build/reports/lint-results-debug.html
71+
72+
- name: Upload debug APK
73+
uses: actions/upload-artifact@v4
74+
with:
75+
name: debug-apk
76+
path: app/build/outputs/apk/debug/app-debug.apk
77+
78+
code-quality:
79+
runs-on: ubuntu-latest
80+
81+
steps:
82+
- name: Checkout code
83+
uses: actions/checkout@v4
84+
85+
- name: Set up JDK 17
86+
uses: actions/setup-java@v4
87+
with:
88+
java-version: "17"
89+
distribution: "temurin"
90+
91+
- name: Cache Gradle dependencies
92+
uses: actions/cache@v4
93+
with:
94+
path: |
95+
~/.gradle/caches
96+
~/.gradle/wrapper
97+
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
98+
restore-keys: |
99+
${{ runner.os }}-gradle-
100+
101+
- name: Make gradlew executable
102+
run: chmod +x gradlew
103+
104+
- name: Check code formatting
105+
run: ./gradlew ktlintCheck || true
106+
107+
- name: Run dependency vulnerability check
108+
run: ./gradlew dependencyCheckAnalyze || true
109+
110+
- name: Generate dependency report
111+
run: ./gradlew dependencies > dependencies.txt || true
112+
113+
- name: Upload dependency report
114+
if: always()
115+
uses: actions/upload-artifact@v4
116+
with:
117+
name: dependency-report
118+
path: dependencies.txt

0 commit comments

Comments
 (0)