Skip to main content

Deployment

Vertical applications built on the EnterpriseAI platform are deployed to Azure App Service using GitHub Actions CI/CD pipelines. The EAI CLI provides commands to set up deployment configuration, trigger builds, and monitor deployment status.

Deployment Architecture

The deployment pipeline:

  1. Developer pushes code to the main branch (or creates a PR)
  2. GitHub Actions runs the CI/CD workflow (lint, test, build)
  3. On success, the built application is deployed to Azure App Service
  4. Azure App Service serves the Next.js application
  5. The BFF proxy in the deployed app connects to the platform's PublicAPI gateway

Setting Up Deployment

Use the EAI CLI to configure deployment for your vertical:

# Set up deployment configuration (creates GitHub Actions workflow and Azure config)
eai deploy setup

This command:

  1. Creates a GitHub Actions workflow file at .github/workflows/deploy.yml
  2. Configures the Azure App Service deployment target
  3. Sets the APP_BASE_PATH for multi-app deployments
  4. Prompts for required Azure credentials and secrets

Required GitHub Secrets

After running eai deploy setup, configure these secrets in your GitHub repository settings:

SecretDescription
AZURE_WEBAPP_PUBLISH_PROFILEAzure App Service publish profile XML
BASE_URL_PUBLIC_APIPublicAPI gateway URL
ENTRA_TENANT_IDEntra CIAM tenant GUID
ENTRA_CLIENT_IDApp registration client ID
ENTRA_CLIENT_SECRETApp registration client secret
AUTH_SECRETAuth.js session encryption key

GitHub Actions CI/CD Pipeline

The deployment workflow runs on every push to main and on pull requests. Here is a typical workflow structure:

# .github/workflows/deploy.yml
name: Deploy to Azure

on:
push:
branches: [main]
pull_request:
branches: [main]

jobs:
build-and-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'

- run: npm ci
- run: npm run lint
- run: npm run test
- run: npm run build
env:
BASE_URL_PUBLIC_API: ${{ secrets.BASE_URL_PUBLIC_API }}
ENTRA_TENANT_NAME: ${{ secrets.ENTRA_TENANT_NAME }}
ENTRA_TENANT_ID: ${{ secrets.ENTRA_TENANT_ID }}
ENTRA_CLIENT_ID: ${{ secrets.ENTRA_CLIENT_ID }}
ENTRA_CLIENT_SECRET: ${{ secrets.ENTRA_CLIENT_SECRET }}
AUTH_SECRET: ${{ secrets.AUTH_SECRET }}
APP_BASE_PATH: /${{ vars.APP_NAME }}

- uses: actions/upload-artifact@v4
with:
name: build
path: .next/

deploy:
needs: build-and-test
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
environment: production
steps:
- uses: actions/download-artifact@v4
with:
name: build
path: .next/

- uses: azure/webapps-deploy@v3
with:
app-name: ${{ vars.AZURE_WEBAPP_NAME }}
publish-profile: ${{ secrets.AZURE_WEBAPP_PUBLISH_PROFILE }}
package: .

Pipeline Stages

StagePurposeRuns On
LintESLint checks for code qualityAll pushes and PRs
TestJest unit tests and Playwright E2E testsAll pushes and PRs
BuildNext.js production build with environment variablesAll pushes and PRs
DeployDeploy to Azure App ServiceOnly on main branch pushes

Triggering and Monitoring Deployments

# Trigger a deployment manually
eai deploy trigger

# Check deployment status
eai deploy status

# View deployment logs
eai deploy logs

Environment Configuration for Production

Production environment variables are configured in the Azure App Service application settings, not in .env files. Use the Azure Portal or Azure CLI to set them:

# Set environment variables on Azure App Service
az webapp config appsettings set \
--resource-group myResourceGroup \
--name my-vertical-app \
--settings \
BASE_URL_PUBLIC_API="https://publicapi.example.com" \
ENTRA_TENANT_NAME="myorgciam" \
ENTRA_TENANT_ID="<guid>" \
ENTRA_CLIENT_ID="<guid>" \
ENTRA_CLIENT_SECRET="<secret>" \
AUTH_SECRET="<base64-key>" \
TENANT_KEYS="permits,grants" \
APP_BASE_PATH="/my-vertical"

Required Environment Variables

VariableDescriptionExample
BASE_URL_PUBLIC_APIPublicAPI gateway URLhttps://publicapi.example.com
TENANT_KEYSComma-separated list of tenant slugspermits,grants
TENANT_{SLUG}_IDConfigurator tenant ID for each tenant<guid>
WORKFLOW_{SLUG}_IDConfigurator workflow ID for each tenant<guid>
ENTRA_TENANT_NAMEEntra CIAM tenant namemyorgciam
ENTRA_TENANT_IDEntra CIAM tenant GUID<guid>
ENTRA_CLIENT_IDApp registration client ID<guid>
ENTRA_CLIENT_SECRETApp registration client secret<secret>
ENTRA_SCOPESOAuth scopesemail offline_access openid profile
AUTH_SECRETAuth.js session encryption key<base64-key>
NEXT_PUBLIC_APP_NAMEApplication display namePermits Portal
APP_BASE_PATHBase path for multi-app deployments/permits

BasePath Configuration

When multiple vertical applications are deployed to the same domain, each app is served under a unique base path (e.g., example.com/permits, example.com/grants). The APP_BASE_PATH environment variable configures this.

How BasePath Works

  1. Set APP_BASE_PATH=/permits in your environment
  2. Next.js is configured to use this as the basePath in next.config.ts:
// next.config.ts
const nextConfig: NextConfig = {
basePath: process.env.APP_BASE_PATH || '',
// ... other config
};
  1. All routes are automatically prefixed: /dashboard becomes /permits/dashboard
  2. Static assets, API routes, and auth callbacks all respect the base path
  3. The BFF proxy adjusts its paths accordingly

Important Considerations

  • The APP_BASE_PATH must start with / but not end with /
  • Auth.js callback URLs must include the base path (handled automatically)
  • Links within the application should use Next.js <Link> component, which respects the base path
  • External links or hardcoded URLs need manual base path prefixing
import Link from 'next/link';

// Correct -- Link component handles basePath automatically
<Link href="/dashboard">Dashboard</Link>
// Renders as: <a href="/permits/dashboard">Dashboard</a>

// For programmatic navigation
import { useRouter } from 'next/navigation';
const router = useRouter();
router.push('/dashboard'); // Navigates to /permits/dashboard

Verifying Deployment

After deployment, verify that your application is working correctly:

# Check platform connectivity
eai verify --tenant permits

# Or use the built-in verification endpoint
curl https://myapp.example.com/permits/api/eai/config

The verification checks:

  • Next.js application is responding
  • BFF proxy can reach PublicAPI
  • Authentication flow is working
  • Object types are seeded and available
  • ResourceAPI CRUD operations succeed