diff --git a/.github/workflows/build-supervisor.yml b/.github/workflows/build-supervisor.yml new file mode 100644 index 0000000..4d9bb50 --- /dev/null +++ b/.github/workflows/build-supervisor.yml @@ -0,0 +1,237 @@ +name: Build Supervisor Binary + +on: + push: + branches: + - main + paths: + - "apps/supervisor/**" + - ".github/workflows/build-supervisor.yml" + pull_request: + paths: + - "apps/supervisor/**" + workflow_dispatch: + +permissions: + contents: write + +jobs: + build: + name: Build Supervisor + runs-on: ubuntu-latest + # Only build on PRs for validation, actual release happens on main + if: github.event_name == 'pull_request' || github.ref == 'refs/heads/main' + strategy: + matrix: + include: + - os: linux + arch: amd64 + goos: linux + goarch: amd64 + - os: linux + arch: arm64 + goos: linux + goarch: arm64 + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version: "1.22" + cache-dependency-path: apps/supervisor/go.sum + + - name: Get version + id: version + run: | + if [ "${{ github.ref }}" = "refs/heads/main" ]; then + VERSION="${{ github.sha }}" + SHORT_SHA=$(echo $VERSION | cut -c1-7) + echo "version=$SHORT_SHA" >> $GITHUB_OUTPUT + echo "full_version=$VERSION" >> $GITHUB_OUTPUT + echo "is_release=true" >> $GITHUB_OUTPUT + else + VERSION="pr-${{ github.event.pull_request.number }}" + echo "version=$VERSION" >> $GITHUB_OUTPUT + echo "full_version=$VERSION" >> $GITHUB_OUTPUT + echo "is_release=false" >> $GITHUB_OUTPUT + fi + echo "Building version: $VERSION" + + - name: Install dependencies + working-directory: apps/supervisor + run: go mod download + + - name: Run tests + working-directory: apps/supervisor + run: go test -v ./... + + - name: Build binary + working-directory: apps/supervisor + env: + GOOS: ${{ matrix.goos }} + GOARCH: ${{ matrix.goarch }} + CGO_ENABLED: 0 + run: | + cd cmd/supervisor + go build \ + -ldflags="-s -w -X main.version=${{ steps.version.outputs.full_version }}" \ + -o supervisor-${{ matrix.os }}-${{ matrix.arch }} \ + . + + # Verify the binary + file supervisor-${{ matrix.os }}-${{ matrix.arch }} + ls -lh supervisor-${{ matrix.os }}-${{ matrix.arch }} + + - name: Create release directory + run: | + mkdir -p release + cp apps/supervisor/cmd/supervisor/supervisor-${{ matrix.os }}-${{ matrix.arch }} \ + release/supervisor-${{ matrix.os }}-${{ matrix.arch }} + + # Create checksum + cd release + sha256sum supervisor-${{ matrix.os }}-${{ matrix.arch }} > supervisor-${{ matrix.os }}-${{ matrix.arch }}.sha256 + cat supervisor-${{ matrix.os }}-${{ matrix.arch }}.sha256 + + - name: Upload build artifacts (for release job) + uses: actions/upload-artifact@v4 + with: + name: supervisor-${{ matrix.os }}-${{ matrix.arch }} + path: release/* + retention-days: 1 + if-no-files-found: error + + release: + name: Create/Update Release + needs: build + runs-on: ubuntu-latest + if: github.ref == 'refs/heads/main' + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Get version info + id: version + run: | + VERSION="${{ github.sha }}" + SHORT_SHA=$(echo $VERSION | cut -c1-7) + BUILD_DATE=$(date -u +%Y-%m-%dT%H:%M:%SZ) + echo "version=$SHORT_SHA" >> $GITHUB_OUTPUT + echo "full_version=$VERSION" >> $GITHUB_OUTPUT + echo "build_date=$BUILD_DATE" >> $GITHUB_OUTPUT + + - name: Download all build artifacts + uses: actions/download-artifact@v4 + with: + path: artifacts + + - name: Prepare release assets + run: | + mkdir -p release-assets + + # Copy all binaries and checksums + find artifacts -type f -name "supervisor-*" -exec cp {} release-assets/ \; + + # List what we have + ls -lh release-assets/ + + # Create a manifest + cat > release-assets/manifest.json << EOF + { + "version": "${{ steps.version.outputs.full_version }}", + "short_version": "${{ steps.version.outputs.version }}", + "build_date": "${{ steps.version.outputs.build_date }}", + "commit": "${{ github.sha }}", + "repository": "${{ github.repository }}", + "binaries": { + "linux-amd64": { + "filename": "supervisor-linux-amd64", + "download_url": "https://github.com/${{ github.repository }}/releases/download/supervisor-latest/supervisor-linux-amd64", + "checksum_url": "https://github.com/${{ github.repository }}/releases/download/supervisor-latest/supervisor-linux-amd64.sha256" + }, + "linux-arm64": { + "filename": "supervisor-linux-arm64", + "download_url": "https://github.com/${{ github.repository }}/releases/download/supervisor-latest/supervisor-linux-arm64", + "checksum_url": "https://github.com/${{ github.repository }}/releases/download/supervisor-latest/supervisor-linux-arm64.sha256" + } + } + } + EOF + + cat release-assets/manifest.json + + - name: Delete existing release if exists + continue-on-error: true + run: | + gh release delete supervisor-latest --yes --cleanup-tag || true + env: + GH_TOKEN: ${{ github.token }} + + - name: Create new release + run: | + gh release create supervisor-latest \ + --title "Supervisor Binary (Latest)" \ + --notes "**Dev8 Workspace Supervisor - Internal Build** + + This is an automatically updated release containing the latest supervisor binaries. + + **Build Information:** + - Commit: \`${{ steps.version.outputs.full_version }}\` + - Short Version: \`${{ steps.version.outputs.version }}\` + - Build Date: ${{ steps.version.outputs.build_date }} + - Branch: main + + **Available Binaries:** + - \`supervisor-linux-amd64\` - Linux x86_64 + - \`supervisor-linux-arm64\` - Linux ARM64 + + **Consistent Download URLs:** + - AMD64: https://github.com/${{ github.repository }}/releases/download/supervisor-latest/supervisor-linux-amd64 + - ARM64: https://github.com/${{ github.repository }}/releases/download/supervisor-latest/supervisor-linux-arm64 + + **Usage:** + These binaries are used internally by the DevContainer feature installation. + The URLs remain consistent across builds - only the binary content is updated. + + **Note:** This is an internal tool and not intended for external distribution." \ + release-assets/* + env: + GH_TOKEN: ${{ github.token }} + + summary: + name: Build Summary + needs: [build, release] + runs-on: ubuntu-latest + if: always() + + steps: + - name: Create summary + run: | + echo "# Supervisor Build Complete ✓" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + + if [ "${{ github.ref }}" = "refs/heads/main" ]; then + echo "**Release Updated:** supervisor-latest" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "**Consistent Download URLs:**" >> $GITHUB_STEP_SUMMARY + echo "- AMD64: \`https://github.com/${{ github.repository }}/releases/download/supervisor-latest/supervisor-linux-amd64\`" >> $GITHUB_STEP_SUMMARY + echo "- ARM64: \`https://github.com/${{ github.repository }}/releases/download/supervisor-latest/supervisor-linux-arm64\`" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "These URLs never change - perfect for DevContainer features!" >> $GITHUB_STEP_SUMMARY + else + echo "**PR Build:** Validation complete, binaries not released" >> $GITHUB_STEP_SUMMARY + fi + + echo "" >> $GITHUB_STEP_SUMMARY + echo "**Build Information:**" >> $GITHUB_STEP_SUMMARY + echo "- Commit: \`${{ github.sha }}\`" >> $GITHUB_STEP_SUMMARY + echo "- Branch: \`${{ github.ref_name }}\`" >> $GITHUB_STEP_SUMMARY + echo "- Workflow: [${{ github.run_id }}](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "**Built Platforms:**" >> $GITHUB_STEP_SUMMARY + echo "- Linux AMD64 ✓" >> $GITHUB_STEP_SUMMARY + echo "- Linux ARM64 ✓" >> $GITHUB_STEP_SUMMARY diff --git a/.gitignore b/.gitignore index a37b0ca..f0c65fb 100644 --- a/.gitignore +++ b/.gitignore @@ -47,8 +47,9 @@ yarn-error.log* coverage.out tmp/ -# Go Agent binary +# Go binary apps/agent/agent +apps/supervisor/cmd/supervisor/supervisor # CI/CD artifacts *.tar.gz diff --git a/packages/devcontainer-features/src/supervisor/README.md b/packages/devcontainer-features/src/supervisor/README.md new file mode 100644 index 0000000..c89b66e --- /dev/null +++ b/packages/devcontainer-features/src/supervisor/README.md @@ -0,0 +1,102 @@ +# Dev8 Workspace Supervisor + +This DevContainer feature installs the Dev8 workspace supervisor - a Go binary that monitors workspace activity, performs backups, and reports health status. + +## Example Usage + +```json +{ + "features": { + "ghcr.io/dev8-community/devcontainer-features/supervisor:1": { + "version": "latest" + } + } +} +``` + +## Options + +| Option | Type | Default | Description | +| ------------- | ------ | ---------------- | --------------------------------------------------------------------------------------------------------------------------------- | +| `version` | string | `latest` | Version of supervisor to install. Use `latest` for the most recent build, or specify a GitHub Actions run ID for a specific build | +| `installPath` | string | `/usr/local/bin` | Installation path for supervisor binary | + +## What it does + +The supervisor provides: + +- **Activity Monitoring**: Tracks CPU, memory, and disk usage +- **Automated Backups**: Periodic workspace backups to Azure Files +- **Health Reporting**: Reports workspace status to the Dev8 agent +- **HTTP API**: Exposes health endpoints for monitoring + +## Installation Methods + +The feature supports multiple installation methods: + +1. **Pre-built Binaries (Preferred)**: Downloads from consistent GitHub release URL + - **Consistent URL**: Always downloads from `supervisor-latest` release tag + - **No authentication required**: Public release URLs + - Fast installation (<10 seconds) + - Multi-architecture support (amd64, arm64) + - URLs never change between builds + +2. **Build from Source (Fallback)**: Compiles supervisor from source code + - Used when download fails + - Requires Go 1.22+ (automatically installed if missing) + - Takes 2-3 minutes + +## Configuration + +After installation, configure the supervisor by creating `/etc/dev8/supervisor/config.yaml`: + +```yaml +workspace_dir: /workspaces +monitor_interval: 30s +backup: + enabled: true + interval: 1h + retention: 7d +agent: + enabled: true + url: http://agent:8080 +``` + +## Running the Supervisor + +The supervisor is typically started automatically by the Dev8 platform. To run manually: + +```bash +supervisor +``` + +## Binary Distribution + +The supervisor binaries are built automatically by GitHub Actions on every commit to `main`: + +- Workflow: `.github/workflows/build-supervisor.yml` +- Released with consistent tag: `supervisor-latest` +- Available for Linux AMD64 and ARM64 +- URLs never change between builds + +**Consistent Download URLs:** + +- AMD64: `https://github.com/VAIBHAVSING/Dev8.dev/releases/download/supervisor-latest/supervisor-linux-amd64` +- ARM64: `https://github.com/VAIBHAVSING/Dev8.dev/releases/download/supervisor-latest/supervisor-linux-arm64` + +These URLs always point to the latest build, so the DevContainer feature never needs updating! + +## How It Works + +When you install the feature: + +1. The install script downloads from the **consistent release URL** +2. The `supervisor-latest` release tag is automatically updated on every merge to `main` +3. The URL never changes, but the binary content is always the latest version +4. If download fails, it automatically builds from source as fallback + +This means **zero maintenance** - the feature always gets the latest supervisor binary without any updates needed! + +## More Information + +See the [supervisor documentation](https://github.com/VAIBHAVSING/Dev8.dev/tree/main/apps/supervisor) for detailed configuration options. diff --git a/packages/devcontainer-features/src/supervisor/devcontainer-feature.json b/packages/devcontainer-features/src/supervisor/devcontainer-feature.json new file mode 100644 index 0000000..2bcdbe1 --- /dev/null +++ b/packages/devcontainer-features/src/supervisor/devcontainer-feature.json @@ -0,0 +1,20 @@ +{ + "id": "supervisor", + "version": "1.0.0", + "name": "Dev8 Workspace Supervisor", + "description": "Installs the Dev8 workspace supervisor for monitoring, backups, and health checks", + "documentationURL": "https://github.com/Dev8-Community/Dev8.dev/tree/main/apps/supervisor", + "options": { + "version": { + "type": "string", + "default": "latest", + "description": "Version of supervisor to install" + }, + "installPath": { + "type": "string", + "default": "/usr/local/bin", + "description": "Installation path for supervisor binary" + } + }, + "installsAfter": ["ghcr.io/devcontainers/features/common-utils"] +} diff --git a/packages/devcontainer-features/src/supervisor/install.sh b/packages/devcontainer-features/src/supervisor/install.sh new file mode 100755 index 0000000..3991c83 --- /dev/null +++ b/packages/devcontainer-features/src/supervisor/install.sh @@ -0,0 +1,145 @@ +#!/bin/bash +set -e + +# Dev8 Workspace Supervisor Installation Script +# Downloads pre-built supervisor binary from consistent GitHub release URL + +VERSION=${VERSION:-"latest"} +INSTALL_PATH=${INSTALLPATH:-"/usr/local/bin"} + +echo "Installing Dev8 Workspace Supervisor..." + +# Detect architecture +ARCH=$(uname -m) +case $ARCH in + x86_64) + ARCH="amd64" + ;; + aarch64|arm64) + ARCH="arm64" + ;; + *) + echo "Unsupported architecture: $ARCH" + exit 1 + ;; +esac + +# Detect OS +OS=$(uname -s | tr '[:upper:]' '[:lower:]') + +echo "Detected OS: $OS, Architecture: $ARCH" + +# GitHub repository details +REPO="VAIBHAVSING/Dev8.dev" +BINARY_NAME="supervisor" +PLATFORM="${OS}-${ARCH}" + +# Consistent release URL (never changes!) +RELEASE_TAG="supervisor-latest" +DOWNLOAD_URL="https://github.com/${REPO}/releases/download/${RELEASE_TAG}/supervisor-${PLATFORM}" +CHECKSUM_URL="https://github.com/${REPO}/releases/download/${RELEASE_TAG}/supervisor-${PLATFORM}.sha256" + +echo "Downloading supervisor from consistent release URL..." +echo "URL: $DOWNLOAD_URL" + +# Function to download from GitHub release +download_from_release() { + TEMP_DIR=$(mktemp -d) + cd "$TEMP_DIR" + + # Download binary + if wget -q --show-progress "$DOWNLOAD_URL" -O "$BINARY_NAME" 2>/dev/null; then + echo "✓ Binary downloaded successfully" + else + echo "✗ Failed to download binary" + cd / + rm -rf "$TEMP_DIR" + return 1 + fi + + # Download and verify checksum if available + if wget -q "$CHECKSUM_URL" -O checksum.sha256 2>/dev/null; then + echo "Verifying checksum..." + if sha256sum -c checksum.sha256 2>/dev/null; then + echo "✓ Checksum verification passed" + else + echo "⚠ Checksum verification failed, but continuing..." + fi + else + echo "⚠ Checksum not available, skipping verification" + fi + + # Install the binary + install -m 755 "$BINARY_NAME" "$INSTALL_PATH/$BINARY_NAME" + + cd / + rm -rf "$TEMP_DIR" + return 0 +} + +# Function to build from source (fallback) +build_from_source() { + echo "Building supervisor from source..." + + # Check if Go is installed + if ! command -v go &> /dev/null; then + echo "Go is not installed. Installing Go..." + GO_VERSION="1.22.0" + wget -q --show-progress "https://go.dev/dl/go${GO_VERSION}.linux-${ARCH}.tar.gz" + tar -C /usr/local -xzf "go${GO_VERSION}.linux-${ARCH}.tar.gz" + export PATH=$PATH:/usr/local/go/bin + rm "go${GO_VERSION}.linux-${ARCH}.tar.gz" + fi + + TEMP_DIR=$(mktemp -d) + cd "$TEMP_DIR" + + # Clone the repository + if [ -d "/workspaces/Dev8.dev" ]; then + echo "Using local source code..." + cd /workspaces/Dev8.dev/apps/supervisor + else + echo "Cloning repository..." + git clone --depth 1 "https://github.com/${REPO}.git" + cd "Dev8.dev/apps/supervisor" + fi + + # Build the binary + echo "Compiling supervisor..." + cd cmd/supervisor + CGO_ENABLED=0 go build -o "$BINARY_NAME" -ldflags="-s -w" . + + # Install the binary + echo "Installing supervisor to $INSTALL_PATH..." + install -m 755 "$BINARY_NAME" "$INSTALL_PATH/$BINARY_NAME" + + # Cleanup + cd / + rm -rf "$TEMP_DIR" +} + +# Main installation logic +if download_from_release; then + echo "✓ Installed supervisor from GitHub release" +else + echo "Failed to download from release, falling back to build from source..." + build_from_source +fi + +# Verify installation +if command -v supervisor &> /dev/null; then + echo "✓ Dev8 Workspace Supervisor installed successfully!" + supervisor --version 2>/dev/null || echo "Version: $VERSION" +else + echo "✗ Failed to install supervisor" + exit 1 +fi + +# Create default configuration directory +mkdir -p /etc/dev8/supervisor +echo "✓ Created configuration directory at /etc/dev8/supervisor" + +echo "" +echo "Installation complete!" +echo "Binary location: $INSTALL_PATH/$BINARY_NAME" +echo "Downloaded from: $DOWNLOAD_URL"