diff --git a/.gitea/workflows/beta.yaml b/.gitea/workflows/beta.yaml deleted file mode 100644 index aef0465..0000000 --- a/.gitea/workflows/beta.yaml +++ /dev/null @@ -1,16 +0,0 @@ -name: Beta Release - -on: - push: - tags: - - 'v*-beta*' - - 'v*-test*' - - 'dev-*' - -jobs: - deploy: - if: "contains(gitea.ref_name, 'beta') || contains(gitea.ref_name, 'test') || startsWith(gitea.ref_name, 'dev-')" - uses: ./.gitea/workflows/deploy_call.yaml - with: - prerelease: true - secrets: inherit \ No newline at end of file diff --git a/.gitea/workflows/build_dashboard.yaml b/.gitea/workflows/build_dashboard.yaml new file mode 100644 index 0000000..5dd4c07 --- /dev/null +++ b/.gitea/workflows/build_dashboard.yaml @@ -0,0 +1,32 @@ +name: Build Dashboard UI + +on: + workflow_call: + +jobs: + build: + runs-on: ubuntu-latest + defaults: + run: + working-directory: apps/dashboard-ui + steps: + - uses: actions/checkout@v4 + with: + submodules: true + fetch-depth: 0 + + - uses: actions/setup-node@v4 + with: + node-version: '24' + + - name: Install + run: npm ci || npm install + + - name: Build + run: npm run build + + - name: Upload artifact + uses: actions/upload-artifact@v4 + with: + name: dashboard-ui-dist + path: apps/dashboard-ui/dist/ diff --git a/.gitea/workflows/build_device_agent.yaml b/.gitea/workflows/build_device_agent.yaml new file mode 100644 index 0000000..cea67fd --- /dev/null +++ b/.gitea/workflows/build_device_agent.yaml @@ -0,0 +1,43 @@ +name: Build Device Agent + +on: + workflow_call: + +jobs: + cross-build: + runs-on: ubuntu-latest + strategy: + matrix: + goos: [linux, windows] + goarch: [amd64, arm64] + exclude: + - goos: windows + goarch: arm64 + defaults: + run: + working-directory: apps/device-agent + steps: + - uses: actions/checkout@v4 + with: + submodules: true + fetch-depth: 0 + + - uses: actions/setup-go@v5 + with: + go-version: '1.26' + + - name: Build + env: + CGO_ENABLED: '0' + GOOS: ${{ matrix.goos }} + GOARCH: ${{ matrix.goarch }} + run: | + EXT="" + if [ "${{ matrix.goos }}" = "windows" ]; then EXT=".exe"; fi + go build -o bin/nexus-device-agent-${{ matrix.goos }}-${{ matrix.goarch }}${EXT} . + + - name: Upload artifact + uses: actions/upload-artifact@v4 + with: + name: nexus-device-agent-${{ matrix.goos }}-${{ matrix.goarch }} + path: apps/device-agent/bin/nexus-device-agent-* diff --git a/.gitea/workflows/build_server_core.yaml b/.gitea/workflows/build_server_core.yaml new file mode 100644 index 0000000..51f39c4 --- /dev/null +++ b/.gitea/workflows/build_server_core.yaml @@ -0,0 +1,37 @@ +name: Build Server Core + +on: + workflow_call: + +jobs: + build: + runs-on: ubuntu-latest + defaults: + run: + working-directory: apps/server-core + steps: + - uses: actions/checkout@v4 + with: + submodules: true + fetch-depth: 0 + + - uses: actions/setup-go@v5 + with: + go-version: '1.26' + + - name: Download Go modules + run: go mod download + + - name: Generate Swagger docs + run: | + go install github.com/swaggo/swag/cmd/swag@v1.16.6 + swag init -g main.go --parseDependency --parseInternal + + - name: Build + run: go build -o bin/server-core . + + - name: Upload artifact + uses: actions/upload-artifact@v4 + with: + name: server-core-linux-amd64 + path: apps/server-core/bin/server-core diff --git a/.gitea/workflows/ci.yml b/.gitea/workflows/ci.yml index 589cad3..83d64c0 100644 --- a/.gitea/workflows/ci.yml +++ b/.gitea/workflows/ci.yml @@ -1,19 +1,19 @@ -name: NexusGuard CI +name: CI on: push: - branches: - - main + branches: [main] + tags: + - 'dev-*' + - 'v*-beta*' + - 'v*-test*' + - 'v[0-9]*.[0-9]*.[0-9]' pull_request: - branches: - - main - -env: - BUILD_TOKEN: ${{ secrets.BUILD_TOKEN }} + branches: [main] jobs: # ────────────────────────────────────────────── - # TEST — all 3 components in parallel + # TEST — all 3 components in parallel (always) # ────────────────────────────────────────────── server-core-test: runs-on: ubuntu-latest @@ -25,12 +25,9 @@ jobs: with: submodules: true fetch-depth: 0 - token: ${{ secrets.BUILD_TOKEN }} - persist-credentials: true - github-server-url: 'https://git.datadunia.com' - uses: actions/setup-go@v5 with: - go-version: '1.25' + go-version: '1.26' - name: Test run: go test ./... -tags dev -cover @@ -44,12 +41,9 @@ jobs: with: submodules: true fetch-depth: 0 - token: ${{ secrets.BUILD_TOKEN }} - persist-credentials: true - github-server-url: 'https://git.datadunia.com' - uses: actions/setup-go@v5 with: - go-version: '1.25' + go-version: '1.26' - name: Test run: go test ./... -cover @@ -63,9 +57,6 @@ jobs: with: submodules: true fetch-depth: 0 - token: ${{ secrets.BUILD_TOKEN }} - persist-credentials: true - github-server-url: 'https://git.datadunia.com' - uses: actions/setup-node@v4 with: node-version: '24' @@ -75,93 +66,34 @@ jobs: run: npm run build # ────────────────────────────────────────────── - # BUILD — binaries + frontend dist + # BUILD — only on tag push, parallel per component # ────────────────────────────────────────────── - server-core-build: - runs-on: ubuntu-latest - needs: server-core-test - defaults: - run: - working-directory: apps/server-core - steps: - - uses: actions/checkout@v4 - with: - submodules: true - token: ${{ secrets.BUILD_TOKEN }} - persist-credentials: true - github-server-url: 'https://git.datadunia.com' - - uses: actions/setup-go@v5 - with: - go-version: '1.25' - - name: Build - run: go build -o bin/server-core . - - name: Upload binary - uses: actions/upload-artifact@v4 - with: - name: server-core-linux-amd64 - path: apps/server-core/bin/server-core + build-server-core: + if: startsWith(gitea.ref, 'refs/tags/') + needs: [server-core-test] + uses: ./.gitea/workflows/build_server_core.yaml - device-agent-cross-build: - runs-on: ubuntu-latest - needs: device-agent-test - strategy: - matrix: - goos: [linux, windows] - goarch: [amd64, arm64] - exclude: - - goos: windows - goarch: arm64 - defaults: - run: - working-directory: apps/device-agent - steps: - - uses: actions/checkout@v4 - with: - submodules: true - token: ${{ secrets.BUILD_TOKEN }} - persist-credentials: true - github-server-url: 'https://git.datadunia.com' - - uses: actions/setup-go@v5 - with: - go-version: '1.25' - - name: Build - env: - CGO_ENABLED: 0 - GOOS: ${{ matrix.goos }} - GOARCH: ${{ matrix.goarch }} - run: | - EXT="" - if [ "${{ matrix.goos }}" = "windows" ]; then EXT=".exe"; fi - go build -o bin/nexus-device-agent-${{ matrix.goos }}-${{ matrix.goarch }}${EXT} . - - name: Upload artifact - uses: actions/upload-artifact@v4 - with: - name: nexus-device-agent-${{ matrix.goos }}-${{ matrix.goarch }} - path: apps/device-agent/bin/nexus-device-agent-* + build-device-agent: + if: startsWith(gitea.ref, 'refs/tags/') + needs: [device-agent-test] + uses: ./.gitea/workflows/build_device_agent.yaml - dashboard-dist: - runs-on: ubuntu-latest - needs: dashboard-test - defaults: - run: - working-directory: apps/dashboard-ui - steps: - - uses: actions/checkout@v4 - with: - submodules: true - token: ${{ secrets.BUILD_TOKEN }} - github-server-url: 'https://git.datadunia.com' - - uses: actions/setup-node@v4 - with: - node-version: '24' - - name: Install - run: npm ci || npm install - - name: Build - run: npm run build - - name: Upload dist - uses: actions/upload-artifact@v4 - with: - name: dashboard-ui-dist - path: apps/dashboard-ui/dist/ + build-dashboard: + if: startsWith(gitea.ref, 'refs/tags/') + needs: [dashboard-test] + uses: ./.gitea/workflows/build_dashboard.yaml + build-docs: + if: startsWith(gitea.ref, 'refs/tags/') + uses: ./.gitea/workflows/docs_call.yaml + # ────────────────────────────────────────────── + # RELEASE — after all builds complete + # ────────────────────────────────────────────── + release: + if: startsWith(gitea.ref, 'refs/tags/') + needs: [build-server-core, build-device-agent, build-dashboard, build-docs] + uses: ./.gitea/workflows/release_call.yaml + with: + prerelease: ${{ contains(gitea.ref_name, 'dev-') || contains(gitea.ref_name, 'beta') || contains(gitea.ref_name, 'test') }} + secrets: inherit diff --git a/.gitea/workflows/deploy_call.yaml b/.gitea/workflows/deploy_call.yaml deleted file mode 100644 index 96cba9f..0000000 --- a/.gitea/workflows/deploy_call.yaml +++ /dev/null @@ -1,207 +0,0 @@ -name: Deploy - -on: - workflow_call: - inputs: - prerelease: - description: 'Mark as prerelease' - required: false - type: boolean - default: false - -permissions: - contents: write - -jobs: - build-and-release: - runs-on: ubuntu-latest - steps: - - name: Clone main repository - run: | - git config --global --remove-section http || true - git config --global --unset-all core.askPass || true - TOKEN="${{ secrets.BUILD_TOKEN }}" - git clone -c credential.helper="" \ - https://token:$TOKEN@git.datadunia.com/nexusguard/Nexus-Guard-Suite.git . - - name: Clone submodules - run: | - TOKEN="${{ secrets.BUILD_TOKEN }}" - # Server Core - git clone -c credential.helper="" \ - https://token:$TOKEN@git.datadunia.com/nexusguard/nexus-server-core.git apps/server-core - # Device Agent - git clone -c credential.helper="" \ - https://token:$TOKEN@git.datadunia.com/nexusguard/nexus-device-agent.git apps/device-agent - # Dashboard UI - git clone -c credential.helper="" \ - https://token:$TOKEN@git.datadunia.com/nexusguard/nexus-dashboard-ui.git apps/dashboard-ui - - name: Setup Go - uses: actions/setup-go@v5 - with: - go-version: '1.25' - - name: Setup Node.js - uses: actions/setup-node@v4 - with: - node-version: '24' - - name: Download Go modules - run: | - cd apps/server-core - go mod download - - name: Generate Swagger docs - run: | - go install github.com/swaggo/swag/cmd/swag@v1.16.6 - cd apps/server-core - swag init -g main.go --parseDependency --parseInternal - - name: Build Server Core - run: | - cd apps/server-core - go build -o bin/server-core . - - name: Build Device Agent Cross-platform - run: | - cd apps/device-agent - # Linux amd64 - CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o bin/nexus-device-agent-linux-amd64 . - # Linux arm64 - CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -o bin/nexus-device-agent-linux-arm64 . - # Windows amd64 - CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -o bin/nexus-device-agent-windows-amd64.exe . - - name: Build Dashboard UI - run: | - cd apps/dashboard-ui - npm ci || npm install - npm run build - - name: Generate latest.json - run: | - VERSION="${{ gitea.ref_name }}" - RELEASE_DATE="$(date -u +'%Y-%m-%dT%H:%M:%SZ')" - REPO="${{ gitea.repository }}" - SERVER="${{ gitea.server_url }}" - cat > latest.json << ENDJSON - { - "version": "$VERSION", - "release_date": "$RELEASE_DATE", - "download_urls": { - "server-core": "${SERVER}/${REPO}/releases/download/${VERSION}/server-core-linux-amd64", - "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" - } - } - ENDJSON - - name: Create Release and upload assets - env: - TOKEN: ${{ secrets.BUILD_TOKEN }} - run: | - if [ -z "$TOKEN" ]; then - echo "Value: [EMPTY]" - exit 1 - else - echo "Length: ${#TOKEN} characters" - fi - - REPO="${{ gitea.repository }}" - TAG="${{ gitea.ref_name }}" - API="${{ gitea.server_url }}/api/v1" - - # 0. Check & Delete Existing Release - echo "=== 0. Check & Delete Existing Release ===" - EXISTING_RESP=$(curl -s -H "Authorization: token $TOKEN" "$API/repos/$REPO/releases/tags/$TAG") - EXISTING_ID=$(echo "$EXISTING_RESP" | grep -o '"id":[0-9]*' | head -n 1 | cut -d':' -f2 || true) - - if [ -n "$EXISTING_ID" ] && [ "$EXISTING_ID" != "null" ]; then - echo "⚠️ Found existing release for tag $TAG with ID: $EXISTING_ID. Deleting..." - DELETE_RESP=$(curl -s -w "\n%{http_code}" -X DELETE -H "Authorization: token $TOKEN" "$API/repos/$REPO/releases/$EXISTING_ID") - echo "✅ Delete response: $DELETE_RESP" - else - echo "No existing release found for $TAG. Proceeding..." - fi - - # 1. Create Release - echo "=== 1. Create New Release ===" - JSON_BODY=$(printf '{"tag_name":"%s","name":"%s","body":"Release %s","draft":false,"prerelease":%s}' "$TAG" "$TAG" "$TAG" "${{ inputs.prerelease }}") - - RELEASE_RESP=$(curl -s -X POST \ - -H "Authorization: token $TOKEN" \ - -H "Content-Type: application/json" \ - -d "$JSON_BODY" \ - "$API/repos/$REPO/releases") - - # Ambil ID dengan lebih teliti - # Tambahkan || true agar grep tidak membuat script crash (karena set -e) jika id tidak ditemukan - RELEASE_ID=$(echo "$RELEASE_RESP" | grep -o '"id":[0-9]*' | head -n 1 | cut -d':' -f2 || true) - - if [ -z "$RELEASE_ID" ] || [ "$RELEASE_ID" = "null" ]; then - echo "Gagal membuat release. Response: $RELEASE_RESP" - exit 1 - fi - - echo "Release ID: $RELEASE_ID" - - # 2. Upload Assets - # Server Core - if [ -f "apps/server-core/bin/server-core" ]; then - echo "Uploading server-core-linux-amd64..." - curl -s -X POST \ - -H "Authorization: token $TOKEN" \ - -F "attachment=@apps/server-core/bin/server-core" \ - "$API/repos/$REPO/releases/$RELEASE_ID/assets?name=server-core-linux-amd64" - fi - - # Device Agent Linux amd64 - if [ -f "apps/device-agent/bin/nexus-device-agent-linux-amd64" ]; then - echo "Uploading nexus-device-agent-linux-amd64..." - curl -s -X POST \ - -H "Authorization: token $TOKEN" \ - -F "attachment=@apps/device-agent/bin/nexus-device-agent-linux-amd64" \ - "$API/repos/$REPO/releases/$RELEASE_ID/assets?name=nexus-device-agent-linux-amd64" - fi - - # Device Agent Linux arm64 - if [ -f "apps/device-agent/bin/nexus-device-agent-linux-arm64" ]; then - echo "Uploading nexus-device-agent-linux-arm64..." - curl -s -X POST \ - -H "Authorization: token $TOKEN" \ - -F "attachment=@apps/device-agent/bin/nexus-device-agent-linux-arm64" \ - "$API/repos/$REPO/releases/$RELEASE_ID/assets?name=nexus-device-agent-linux-arm64" - fi - - # Device Agent Windows amd64 - if [ -f "apps/device-agent/bin/nexus-device-agent-windows-amd64.exe" ]; then - echo "Uploading nexus-device-agent-windows-amd64.exe..." - curl -s -X POST \ - -H "Authorization: token $TOKEN" \ - -F "attachment=@apps/device-agent/bin/nexus-device-agent-windows-amd64.exe" \ - "$API/repos/$REPO/releases/$RELEASE_ID/assets?name=nexus-device-agent-windows-amd64.exe" - fi - - # Dashboard UI dist - if [ -d "apps/dashboard-ui/dist" ]; then - echo "Creating dashboard-ui-dist.tar.gz..." - cd apps/dashboard-ui - tar -czf ../dashboard-ui-dist.tar.gz dist/ - cd .. - - echo "Uploading dashboard-ui-dist.tar.gz..." - curl -s -X POST \ - -H "Authorization: token $TOKEN" \ - -F "attachment=@dashboard-ui-dist.tar.gz" \ - "$API/repos/$REPO/releases/$RELEASE_ID/assets?name=dashboard-ui-dist.tar.gz" - fi - - # latest.json - if [ -f "latest.json" ]; then - echo "Uploading latest.json..." - curl -s -X POST \ - -H "Authorization: token $TOKEN" \ - -F "attachment=@latest.json" \ - "$API/repos/$REPO/releases/$RELEASE_ID/assets?name=latest.json" - fi - - name: Cleanup build artifacts - if: always() - run: | - git config --global --remove-section http || true - git config --global --unset-all core.askPass || true - rm -f latest.json dashboard-ui-dist.tar.gz - rm -rf apps/server-core/bin apps/device-agent/bin apps/dashboard-ui/node_modules apps/dashboard-ui/dist - echo "Cleanup done" \ No newline at end of file diff --git a/.gitea/workflows/docs_call.yaml b/.gitea/workflows/docs_call.yaml new file mode 100644 index 0000000..42acc28 --- /dev/null +++ b/.gitea/workflows/docs_call.yaml @@ -0,0 +1,32 @@ +name: Build Docs + +on: + workflow_call: + +jobs: + build: + runs-on: ubuntu-latest + defaults: + run: + working-directory: apps/docs + steps: + - uses: actions/checkout@v4 + with: + submodules: true + fetch-depth: 0 + + - uses: actions/setup-node@v4 + with: + node-version: '24' + + - name: Install + run: npm ci || npm install + + - name: Build + run: npm run docs:build + + - name: Upload artifact + uses: actions/upload-artifact@v4 + with: + name: docs-dist + path: apps/docs/.vitepress/dist/ diff --git a/.gitea/workflows/release.yaml b/.gitea/workflows/release.yaml deleted file mode 100644 index 2dadcc1..0000000 --- a/.gitea/workflows/release.yaml +++ /dev/null @@ -1,14 +0,0 @@ -name: Release - -on: - push: - tags: - - 'v[0-9]*.[0-9]*.[0-9]' - -jobs: - deploy: - if: "!contains(gitea.ref_name, 'beta') && !contains(gitea.ref_name, 'test')" - uses: ./.gitea/workflows/deploy_call.yaml - with: - prerelease: false - secrets: inherit \ No newline at end of file diff --git a/.gitea/workflows/release_call.yaml b/.gitea/workflows/release_call.yaml new file mode 100644 index 0000000..9e986bc --- /dev/null +++ b/.gitea/workflows/release_call.yaml @@ -0,0 +1,122 @@ +name: Release + +on: + workflow_call: + inputs: + prerelease: + description: 'Mark as prerelease' + required: false + type: boolean + default: false + +permissions: + contents: write + +jobs: + release: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Download all artifacts + uses: actions/download-artifact@v4 + with: + path: ./artifacts + + - name: Generate latest.json + run: | + VERSION="${{ gitea.ref_name }}" + RELEASE_DATE="$(date -u +'%Y-%m-%dT%H:%M:%SZ')" + REPO="${{ gitea.repository }}" + SERVER="${{ gitea.server_url }}" + cat > latest.json << ENDJSON + { + "version": "$VERSION", + "release_date": "$RELEASE_DATE", + "download_urls": { + "server-core": "${SERVER}/${REPO}/releases/download/${VERSION}/server-core-linux-amd64", + "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" + } + } + ENDJSON + + - name: Create Release and upload assets + env: + TOKEN: ${{ secrets.BUILD_TOKEN }} + run: | + REPO="${{ gitea.repository }}" + TAG="${{ gitea.ref_name }}" + API="${{ gitea.server_url }}/api/v1" + + # Delete existing release if present + EXISTING_ID=$(curl -s -H "Authorization: token $TOKEN" "$API/repos/$REPO/releases/tags/$TAG" | grep -o '"id":[0-9]*' | head -n 1 | cut -d':' -f2 || true) + if [ -n "$EXISTING_ID" ] && [ "$EXISTING_ID" != "null" ]; then + echo "Deleting existing release $EXISTING_ID..." + curl -s -X DELETE -H "Authorization: token $TOKEN" "$API/repos/$REPO/releases/$EXISTING_ID" + fi + + # Create release + JSON_BODY=$(printf '{"tag_name":"%s","name":"%s","body":"Release %s","draft":false,"prerelease":%s}' "$TAG" "$TAG" "$TAG" "${{ inputs.prerelease }}") + RELEASE_RESP=$(curl -s -X POST \ + -H "Authorization: token $TOKEN" \ + -H "Content-Type: application/json" \ + -d "$JSON_BODY" \ + "$API/repos/$REPO/releases") + + RELEASE_ID=$(echo "$RELEASE_RESP" | grep -o '"id":[0-9]*' | head -n 1 | cut -d':' -f2 || true) + if [ -z "$RELEASE_ID" ] || [ "$RELEASE_ID" = "null" ]; then + echo "Failed to create release. Response: $RELEASE_RESP" + exit 1 + fi + echo "Release ID: $RELEASE_ID" + + # Upload assets + upload_asset() { + local file="$1" + local name="$2" + if [ -f "$file" ]; then + echo "Uploading $name..." + curl -s -X POST \ + -H "Authorization: token $TOKEN" \ + -F "attachment=@$file" \ + "$API/repos/$REPO/releases/$RELEASE_ID/assets?name=$name" + fi + } + + # Server Core + upload_asset "artifacts/server-core-linux-amd64/server-core" "server-core-linux-amd64" + + # Device Agent (all platforms) + for platform in linux-amd64 linux-arm64 windows-amd64; do + EXT="" + if [ "$platform" = "windows-amd64" ]; then EXT=".exe"; fi + upload_asset "artifacts/nexus-device-agent-${platform}/nexus-device-agent-${platform}${EXT}" "nexus-device-agent-${platform}${EXT}" + done + + # Dashboard UI tar.gz + if [ -d "artifacts/dashboard-ui-dist/dist" ]; then + cd artifacts/dashboard-ui-dist + tar -czf ../../dashboard-ui-dist.tar.gz dist/ + cd ../.. + upload_asset "dashboard-ui-dist.tar.gz" "dashboard-ui-dist.tar.gz" + fi + + # Docs tar.gz + if [ -d "artifacts/docs-dist" ]; then + cd artifacts/docs-dist + tar -czf ../../docs-dist.tar.gz ./ + cd ../.. + upload_asset "docs-dist.tar.gz" "docs-dist.tar.gz" + fi + + # latest.json + upload_asset "latest.json" "latest.json" + + - name: Cleanup + if: always() + run: rm -rf artifacts/ latest.json dashboard-ui-dist.tar.gz docs-dist.tar.gz