name: Validate & Build Artifacts on: push: branches: [main, develop] paths: - 'provisioning/schemas/**' - 'provisioning/scripts/**' - '.github/workflows/validate-and-build.yml' pull_request: branches: [main, develop] paths: - 'provisioning/schemas/**' - 'provisioning/scripts/**' workflow_dispatch: inputs: mode: description: 'Deployment mode to validate' required: true default: 'all' type: choice options: - solo - multiuser - enterprise - all env: ARTIFACTS_DIR: provisioning/artifacts LOG_DIR: provisioning/logs jobs: validate-configs: name: Validate Configurations runs-on: ubuntu-latest strategy: matrix: mode: [solo, multiuser, enterprise] steps: - name: Checkout code uses: actions/checkout@v4 - name: Install Nushell run: | cargo install nu --locked nu --version - name: Install dependencies run: | sudo apt-get update sudo apt-get install -y nickel jinja2-cli yq curl nickel --version jinja2 --version yq --version - name: Create logs directory run: mkdir -p ${{ env.LOG_DIR }} - name: Validate ${{ matrix.mode }} configuration run: | cd provisioning nu scripts/validate-config.nu --mode ${{ matrix.mode }} 2>&1 | tee ${{ env.LOG_DIR }}/validate-${{ matrix.mode }}.log continue-on-error: false - name: Upload validation logs if: always() uses: actions/upload-artifact@v4 with: name: validation-logs-${{ matrix.mode }} path: ${{ env.LOG_DIR }}/validate-${{ matrix.mode }}.log retention-days: 30 build-artifacts: name: Build Deployment Artifacts needs: validate-configs runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v4 - name: Install Nushell run: | cargo install nu --locked nu --version - name: Install dependencies run: | sudo apt-get update sudo apt-get install -y nickel jinja2-cli yq nickel --version jinja2 --version yq --version - name: Create artifacts directory run: mkdir -p ${{ env.ARTIFACTS_DIR }} - name: Run CI/CD pipeline run: | cd provisioning nu scripts/ci-pipeline.nu \ --artifact-dir ../artifacts \ --mode multiuser \ --test-deploy 2>&1 | tee ${{ env.LOG_DIR }}/build.log continue-on-error: false - name: Generate artifact manifest if: success() run: | cat > ${{ env.ARTIFACTS_DIR }}/README.md << 'EOF' # VAPORA Deployment Artifacts Generated: $(date -u +'%Y-%m-%dT%H:%M:%SZ') Commit: ${{ github.sha }} Workflow: ${{ github.workflow }} ## Files ### Configurations (JSON) - `config-solo.json` - Solo mode raw configuration - `config-multiuser.json` - Multiuser mode raw configuration - `config-enterprise.json` - Enterprise mode raw configuration ### Configuration Formats - `vapora-solo.toml` - TOML format (backend config) - `vapora-solo.yaml` - YAML format (K8s ConfigMap data) - `vapora-multiuser.toml` - Multiuser TOML - `vapora-multiuser.yaml` - Multiuser YAML - `vapora-enterprise.toml` - Enterprise TOML - `vapora-enterprise.yaml` - Enterprise YAML ### Kubernetes Manifests - `configmap.yaml` - Kubernetes ConfigMap - `deployment.yaml` - Kubernetes Deployments (backend, agents, llm-router) ### Docker Compose - `docker-compose.yml` - Docker Compose stack ### Reports - `MANIFEST.md` - Generated artifact manifest ## Usage ### Local Development (Docker) ```bash docker compose -f docker-compose.yml up -d ``` ### Kubernetes Deployment ```bash kubectl apply -f configmap.yaml kubectl apply -f deployment.yaml kubectl rollout status deployment/vapora-backend -n vapora ``` ### Manual Configuration ```bash # Use generated TOML or YAML cp vapora-solo.toml /etc/vapora/config.toml # Or for K8s kubectl create configmap vapora-config --from-file=vapora-solo.yaml ``` ## Validation All artifacts have been: - Generated from validated Nickel configurations - Validated for syntax and structure - Tested with Kubernetes dry-run - Generated with consistent templates ## Build Metadata - Build Time: $(date -u +'%Y-%m-%dT%H:%M:%SZ') - Commit: ${{ github.sha }} - Branch: ${{ github.ref }} - Workflow Run: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} EOF cat ${{ env.ARTIFACTS_DIR }}/README.md - name: Upload all artifacts if: success() uses: actions/upload-artifact@v4 with: name: deployment-artifacts path: ${{ env.ARTIFACTS_DIR }}/ retention-days: 90 - name: Upload build logs if: always() uses: actions/upload-artifact@v4 with: name: build-logs path: ${{ env.LOG_DIR }}/ retention-days: 30 - name: Comment PR with artifact info if: github.event_name == 'pull_request' && success() uses: actions/github-script@v7 with: script: | github.rest.issues.createComment({ issue_number: context.issue.number, owner: context.repo.owner, repo: context.repo.repo, body: `✅ **Deployment artifacts built successfully!**\n\nArtifacts available for download:\n- **deployment-artifacts** - All configuration and manifest files\n- **build-logs** - Build pipeline logs\n- **validation-logs-*** - Per-mode validation logs\n\nReady for deployment to Docker or Kubernetes.` }) - name: Notify Slack on failure if: failure() uses: 8398a7/action-slack@v3 with: status: ${{ job.status }} text: 'VAPORA provisioning build failed' webhook_url: ${{ secrets.SLACK_WEBHOOK }} fields: repo,message,commit,author continue-on-error: true