chore: update all submodule refs + CI/CD workflows + AGENTS.md

This commit is contained in:
datadunia
2026-07-07 09:28:06 +07:00
parent 2fb3109b9f
commit 59a8436a45
8 changed files with 385 additions and 13 deletions
+130
View File
@@ -0,0 +1,130 @@
name: Build Android Agent
on:
workflow_call:
inputs:
build_type:
description: 'Build type (debug or release)'
required: false
type: string
default: 'release'
jobs:
build:
runs-on: ubuntu-latest
env:
RUNNER_TOOL_CACHE: /toolcache
steps:
- name: Configure git auth for submodules
run: git config --global url."https://x-access-token:${{ secrets.BUILD_TOKEN }}@git.datadunia.com/".insteadOf "https://git.datadunia.com/"
- uses: actions/checkout@v4
with:
submodules: true
fetch-depth: 0
token: ${{ secrets.BUILD_TOKEN }}
persist-credentials: true
- name: Set up JDK 17
uses: actions/setup-java@v4
with:
java-version: '17'
distribution: 'temurin'
cache: gradle
- name: Setup Android SDK
uses: android-actions/setup-android@v3
- name: Check for signing key
id: check-signing
run: |
if [ -n "${{ secrets.ANDROID_KEYSTORE_BASE64 }}" ]; then
echo "has_key=true" >> "$GITHUB_OUTPUT"
echo "Signing: Using production keystore from secrets"
else
echo "has_key=false" >> "$GITHUB_OUTPUT"
echo "Signing: No keystore found, using debug/self-signed"
fi
- name: Decode keystore
if: steps.check-signing.outputs.has_key == 'true'
run: |
echo "${{ secrets.ANDROID_KEYSTORE_BASE64 }}" | base64 -d > /tmp/release.keystore
- name: Create keystore properties
if: steps.check-signing.outputs.has_key == 'true'
run: |
cat > /tmp/keystore.properties << EOF
storePassword=${{ secrets.ANDROID_KEYSTORE_PASSWORD }}
keyPassword=${{ secrets.ANDROID_KEY_PASSWORD }}
keyAlias=${{ secrets.ANDROID_KEY_ALIAS }}
storeFile=/tmp/release.keystore
EOF
- name: Configure signing (production)
if: steps.check-signing.outputs.has_key == 'true'
working-directory: apps/android-agent
run: |
# Inject signing config into build.gradle.kts
cat >> app/build.gradle.kts << 'GRADLE_EOF'
android {
signingConfigs {
create("release") {
storeFile = file("/tmp/release.keystore")
storePassword = System.getenv("KEYSTORE_PASSWORD") ?: ""
keyAlias = System.getenv("KEY_ALIAS") ?: ""
keyPassword = System.getenv("KEY_PASSWORD") ?: ""
}
}
buildTypes {
release {
signingConfig = signingConfigs.getByName("release")
}
}
}
GRADLE_EOF
env:
KEYSTORE_PASSWORD: ${{ secrets.ANDROID_KEYSTORE_PASSWORD }}
KEY_ALIAS: ${{ secrets.ANDROID_KEY_ALIAS }}
KEY_PASSWORD: ${{ secrets.ANDROID_KEY_PASSWORD }}
- name: Grant execute permission for gradlew
working-directory: apps/android-agent
run: chmod +x gradlew
- name: Build debug APK (no signing key)
if: steps.check-signing.outputs.has_key == 'false'
working-directory: apps/android-agent
run: ./gradlew assembleDebug
- name: Build release APK (with signing key)
if: steps.check-signing.outputs.has_key == 'true'
working-directory: apps/android-agent
run: ./gradlew assembleRelease
- name: Upload debug APK
if: steps.check-signing.outputs.has_key == 'false'
uses: actions/upload-artifact@v3
with:
name: nexusguard-android-debug
path: apps/android-agent/app/build/outputs/apk/debug/app-debug.apk
- name: Upload release APK
if: steps.check-signing.outputs.has_key == 'true'
uses: actions/upload-artifact@v3
with:
name: nexusguard-android-release
path: apps/android-agent/app/build/outputs/apk/release/app-release.apk
- name: Upload mapping file (release only)
if: steps.check-signing.outputs.has_key == 'true'
uses: actions/upload-artifact@v3
with:
name: nexusguard-android-mapping
path: apps/android-agent/app/build/outputs/mapping/release/mapping.txt
if-no-files-found: warn
- name: Cleanup keystore
if: always()
run: rm -f /tmp/release.keystore /tmp/keystore.properties
+68 -8
View File
@@ -8,13 +8,17 @@ on:
- 'v*-beta*'
- 'v*-test*'
- 'v[0-9]*.[0-9]*.[0-9]'
pull_request:
branches:
- main
- develop
jobs:
# ====================================================================
# TESTS — test tags only
# ====================================================================
server-core-test:
if: contains(gitea.ref_name, 'test')
if: contains(gitea.ref_name, 'test') || github.event_name == 'pull_request'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
@@ -35,7 +39,7 @@ jobs:
run: go test $(go list ./... | grep -v internal/firewall) -tags dev -cover -count=1
device-agent-test:
if: contains(gitea.ref_name, 'test')
if: contains(gitea.ref_name, 'test') || github.event_name == 'pull_request'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
@@ -56,7 +60,7 @@ jobs:
run: go test ./... -cover
dashboard-test:
if: contains(gitea.ref_name, 'test')
if: contains(gitea.ref_name, 'test') || github.event_name == 'pull_request'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
@@ -77,36 +81,70 @@ jobs:
working-directory: apps/dashboard-ui
run: npm run build
android-agent-test:
if: contains(gitea.ref_name, 'test') || github.event_name == 'pull_request'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
submodules: true
fetch-depth: 0
token: ${{ secrets.BUILD_TOKEN }}
persist-credentials: true
- name: Configure git auth for submodules
run: git config --global url."https://x-access-token:${{ secrets.BUILD_TOKEN }}@git.datadunia.com/".insteadOf "https://git.datadunia.com/"
- name: Set up JDK 17
uses: actions/setup-java@v4
with:
java-version: '17'
distribution: 'temurin'
cache: gradle
- name: Setup Android SDK
uses: android-actions/setup-android@v3
- name: Grant execute permission for gradlew
working-directory: apps/android-agent
run: chmod +x gradlew
- name: Build debug APK
working-directory: apps/android-agent
run: ./gradlew assembleDebug
# ====================================================================
# BUILD — after tests pass (release) or directly (dev/beta)
# ====================================================================
build-server-core:
if: always() && !contains(gitea.ref_name, 'test') && !failure() && !cancelled()
needs: [server-core-test, device-agent-test, dashboard-test]
needs: [server-core-test, device-agent-test, dashboard-test, android-agent-test]
runs-on: ubuntu-latest
uses: ./.gitea/workflows/build_server_core.yaml
secrets: inherit
build-device-agent:
if: always() && !contains(gitea.ref_name, 'test') && !failure() && !cancelled()
needs: [server-core-test, device-agent-test, dashboard-test]
needs: [server-core-test, device-agent-test, dashboard-test, android-agent-test]
runs-on: ubuntu-latest
uses: ./.gitea/workflows/build_device_agent.yaml
secrets: inherit
build-dashboard:
if: always() && !contains(gitea.ref_name, 'test') && !failure() && !cancelled()
needs: [server-core-test, device-agent-test, dashboard-test]
needs: [server-core-test, device-agent-test, dashboard-test, android-agent-test]
runs-on: ubuntu-latest
uses: ./.gitea/workflows/build_dashboard.yaml
secrets: inherit
build-android-agent:
if: always() && !contains(gitea.ref_name, 'test') && !failure() && !cancelled()
needs: [server-core-test, device-agent-test, dashboard-test, android-agent-test]
runs-on: ubuntu-latest
uses: ./.gitea/workflows/build_android_agent.yaml
secrets: inherit
# ====================================================================
# DOCS — after builds pass, release tags only
# ====================================================================
build-docs:
if: always() && !contains(gitea.ref_name, 'dev') && !contains(gitea.ref_name, 'beta') && !contains(gitea.ref_name, 'test') && !failure() && !cancelled()
needs: [build-server-core, build-device-agent, build-dashboard]
needs: [build-server-core, build-device-agent, build-dashboard, build-android-agent]
runs-on: ubuntu-latest
uses: ./.gitea/workflows/docs_call.yaml
secrets: inherit
@@ -116,9 +154,31 @@ jobs:
# ====================================================================
release:
if: always() && !contains(gitea.ref_name, 'test') && !failure() && !cancelled()
needs: [build-server-core, build-device-agent, build-dashboard, build-docs]
needs: [build-server-core, build-device-agent, build-dashboard, build-android-agent, build-docs]
uses: ./.gitea/workflows/release_call.yaml
with:
prerelease: ${{ contains(gitea.ref_name, 'dev') }}
draft: ${{ contains(gitea.ref_name, 'beta') }}
secrets: inherit
# ====================================================================
# DEPLOY DEV — auto-deploy on dev tags
# ====================================================================
deploy-dev:
if: contains(gitea.ref_name, 'dev') && !failure() && !cancelled()
needs: [build-server-core, build-device-agent, build-dashboard, build-android-agent]
uses: ./.gitea/workflows/deploy_call.yaml
with:
environment: dev
secrets: inherit
# ====================================================================
# DEPLOY PROD — manual trigger after release
# ====================================================================
deploy-prod:
if: startsWith(gitea.ref_name, 'v') && !contains(gitea.ref_name, 'dev') && !contains(gitea.ref_name, 'beta') && !contains(gitea.ref_name, 'test') && !failure() && !cancelled()
needs: [build-server-core, build-device-agent, build-dashboard, build-android-agent, build-docs]
uses: ./.gitea/workflows/deploy_call.yaml
with:
environment: production
secrets: inherit
+89
View File
@@ -0,0 +1,89 @@
name: Deploy
on:
workflow_call:
inputs:
environment:
description: 'Target environment (dev or production)'
required: true
type: string
jobs:
deploy:
runs-on: ubuntu-latest
environment: ${{ inputs.environment }}
steps:
- name: Configure git auth for submodules
run: git config --global url."https://x-access-token:${{ secrets.BUILD_TOKEN }}@git.datadunia.com/".insteadOf "https://git.datadunia.com/"
- uses: actions/checkout@v4
with:
fetch-depth: 0
token: ${{ secrets.BUILD_TOKEN }}
persist-credentials: true
- name: Download all artifacts
uses: actions/download-artifact@v3
with:
path: ./artifacts
- name: Deploy to ${{ inputs.environment }}
env:
SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }}
DEPLOY_HOST: ${{ secrets.DEPLOY_HOST }}
DEPLOY_USER: ${{ secrets.DEPLOY_USER }}
DEPLOY_PATH: ${{ secrets.DEPLOY_PATH }}
run: |
echo "Deploying to ${{ inputs.environment }}..."
echo "Host: $DEPLOY_HOST"
echo "Path: $DEPLOY_PATH"
# Setup SSH
mkdir -p ~/.ssh
echo "$SSH_PRIVATE_KEY" > ~/.ssh/deploy_key
chmod 600 ~/.ssh/deploy_key
ssh-keyscan -H "$DEPLOY_HOST" >> ~/.ssh/known_hosts 2>/dev/null
# Upload artifacts
echo "Uploading server-core..."
scp -i ~/.ssh/deploy_key artifacts/server-core-linux-amd64/server-core \
"${DEPLOY_USER}@${DEPLOY_HOST}:${DEPLOY_PATH}/bin/"
echo "Uploading device-agent..."
for platform in linux-amd64 linux-arm64; do
scp -i ~/.ssh/deploy_key "artifacts/nexus-device-agent-${platform}/nexus-device-agent-${platform}" \
"${DEPLOY_USER}@${DEPLOY_HOST}:${DEPLOY_PATH}/bin/"
done
echo "Uploading dashboard..."
if [ -d "artifacts/dashboard-ui-dist/dist" ]; then
tar -czf /tmp/dashboard-ui.tar.gz -C artifacts/dashboard-ui-dist dist/
scp -i ~/.ssh/deploy_key /tmp/dashboard-ui.tar.gz \
"${DEPLOY_USER}@${DEPLOY_HOST}:${DEPLOY_PATH}/"
fi
# Deploy on server
echo "Running deployment..."
ssh -i ~/.ssh/deploy_key "${DEPLOY_USER}@${DEPLOY_HOST}" << 'DEPLOY_SCRIPT'
cd "${DEPLOY_PATH}" || exit 1
# Stop services
echo "Stopping services..."
docker compose down || true
# Run update script
echo "Running update..."
bash update.sh --force
# Verify services
echo "Verifying services..."
docker compose ps
echo "Deployment complete!"
DEPLOY_SCRIPT
echo "Deployed to ${{ inputs.environment }} successfully!"
- name: Cleanup
if: always()
run: rm -rf ~/.ssh/deploy_key /tmp/dashboard-ui.tar.gz
+9 -1
View File
@@ -49,7 +49,8 @@ jobs:
"device-agent-linux-amd64": "${SERVER}/${REPO}/releases/download/${VERSION}/nexus-device-agent-linux-amd64",
"device-agent-linux-arm64": "${SERVER}/${REPO}/releases/download/${VERSION}/nexus-device-agent-linux-arm64",
"device-agent-windows-amd64": "${SERVER}/${REPO}/releases/download/${VERSION}/nexus-device-agent-windows-amd64.exe",
"dashboard-ui": "${SERVER}/${REPO}/releases/download/${VERSION}/dashboard-ui-dist.tar.gz"
"dashboard-ui": "${SERVER}/${REPO}/releases/download/${VERSION}/dashboard-ui-dist.tar.gz",
"android-agent": "${SERVER}/${REPO}/releases/download/${VERSION}/nexusguard-android.apk"
}
}
ENDJSON
@@ -115,6 +116,13 @@ jobs:
upload_asset "dashboard-ui-dist.tar.gz" "dashboard-ui-dist.tar.gz"
fi
# Android Agent APK
if [ -f "artifacts/nexusguard-android-debug/nexusguard-android-debug.apk" ]; then
upload_asset "artifacts/nexusguard-android-debug/nexusguard-android-debug.apk" "nexusguard-android.apk"
elif [ -f "artifacts/nexusguard-android-release/nexusguard-android-release.apk" ]; then
upload_asset "artifacts/nexusguard-android-release/nexusguard-android-release.apk" "nexusguard-android.apk"
fi
# Docs tar.gz
if [ -d "artifacts/docs-dist" ]; then
cd artifacts/docs-dist