Step 2 of 4 (50% complete)
Deploy Your Application & Set Up CI/CD
๐ Deploy Your Application & Set Up CI/CD
This guide shows you how to deploy your application using Optimizely Frontend Hosting, both manually and via CI/CD automation.
๐งช Manual Deployment (Recommended for First-Time Setup)
Follow these steps to deploy manually using PowerShell.
1. Install the Required PowerShell Module
Install-Module -Name EpiCloud -Scope CurrentUser -Force Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser Import-Module EpiCloud
2. Set Your Credentials and Target Environment
$projectId = "<your_project_id>" $clientKey = "<your_client_key>" $clientSecret = "<your_client_secret>" $targetEnvironment = "Test1" # Or "Production" or "Test2"
3. Zip Your Next.js Application
Use this naming format:
<name>.head.app.<version>.zip
Example:
optimizely-one.head.app.20250714.zip
โ ๏ธ If the filename does not contain ".head.app.", the system will treat it as a .NET NuGet package!
4. Connect and Deploy
Connect-EpiCloud -ProjectId $projectId -ClientKey $clientKey -ClientSecret $clientSecret $sasUrl = Get-EpiDeploymentPackageLocation Add-EpiDeploymentPackage -SasUrl $sasUrl -Path .\optimizely-one.head.app.20250714.zip Start-EpiDeployment ` -DeploymentPackage "optimizely-one.head.app.20250714.zip" ` -TargetEnvironment $targetEnvironment ` -DirectDeploy ` -Wait ` -Verbose
๐ค Automating Deployment (PowerShell Script)
Once youโve done a few manual deployments, automate the process via script:
1. .zipignore Support
Add a .zipignore file to your project root to exclude unnecessary files.
Example .zipignore:
.next node_modules .env .git .vscode .DS_Store
Customize the Script
Update:
- $sourcePath โ your Next.js project path
- $targetEnvironment โ "Test1", "Test2", or "Production"
3. Set Required Environment Variables
Youโll need:
- OPTI_PROJECT_ID
- OPTI_CLIENT_KEY
- OPTI_CLIENT_SECRET
Set them in PowerShell like so:
$env:OPTI_PROJECT_ID = "<your_project_id>" $env:OPTI_CLIENT_KEY = "<your_client_key>" $env:OPTI_CLIENT_SECRET = "<your_client_secret>"
Or add them to your system environment variables.
4. Run the Script
Save the script as deploy-optimizely.ps1 and run:
.\deploy-optimizely.ps1
5. Full Deployment Script (PowerShell)
if (-not $env:OPTI_PROJECT_ID -or -not $env:OPTI_CLIENT_KEY -or -not $env:OPTI_CLIENT_SECRET) { Write-Host "Missing environment variables." -ForegroundColor Red exit 1 } Install-Module -Name EpiCloud -Scope CurrentUser -Force -ErrorAction SilentlyContinue Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser -Force Import-Module EpiCloud $projectId = $env:OPTI_PROJECT_ID $clientKey = $env:OPTI_CLIENT_KEY $clientSecret = $env:OPTI_CLIENT_SECRET $targetEnvironment = "Test1" $sourcePath = "C:\Workspace\Personal\optimizely-one" $timestamp = Get-Date -Format "yyyyMMdd-HHmmss" $zipName = "optimizely-one.head.app.$timestamp.zip" $zipPath = ".\$zipName" if (Test-Path $zipPath) { Remove-Item $zipPath } $zipIgnorePath = Join-Path $sourcePath ".zipignore" $excludeRoot = @() if (Test-Path $zipIgnorePath) { $excludeRoot = Get-Content $zipIgnorePath | Where-Object { $_ -and $_ -notmatch "^#" } } $rootExcludes = $excludeRoot | ForEach-Object { Join-Path $sourcePath $_ } $includeFiles = Get-ChildItem -Path $sourcePath -Recurse -File | Where-Object { foreach ($ex in $rootExcludes) { if ($_.FullName -like "$ex\*" -or $_.FullName -eq $ex) { return $false } } return $true } if ($includeFiles.Count -eq 0) { Write-Host "ERROR: No files to archive." -ForegroundColor Red exit 1 } $tempPath = Join-Path $env:TEMP "nextjs-build-zip" if (Test-Path $tempPath) { Remove-Item -Recurse -Force $tempPath } New-Item -ItemType Directory -Path $tempPath | Out-Null foreach ($file in $includeFiles) { $relativePath = $file.FullName.Substring($sourcePath.Length).TrimStart('\') $destPath = Join-Path $tempPath $relativePath $destDir = Split-Path -Path $destPath -Parent if (-not (Test-Path -LiteralPath $destDir)) { New-Item -ItemType Directory -Path $destDir -Force | Out-Null } Copy-Item -LiteralPath $file.FullName -Destination $destPath -Force } Compress-Archive -Path "$tempPath\*" -DestinationPath $zipPath Remove-Item -Recurse -Force $tempPath Connect-EpiCloud -ProjectId $projectId -ClientKey $clientKey -ClientSecret $clientSecret $sasUrl = Get-EpiDeploymentPackageLocation Add-EpiDeploymentPackage -SasUrl $sasUrl -Path $zipPath Start-EpiDeployment ` -DeploymentPackage $zipName ` -TargetEnvironment $targetEnvironment ` -DirectDeploy ` -Wait ` -Verbose
๐ CI/CD with GitHub Actions
Step 1: Add Secrets
Go to GitHub โ Repo โ Settings โ Secrets โ Actions โ New Repository Secret
Name | Value |
---|---|
OPTI_PROJECT_ID | Your Optimizely Project ID |
OPTI_CLIENT_KEY | Your Optimizely Client Key |
OPTI_CLIENT_SECRET | Your Optimizely Client Secret |
Step 2: PowerShell Script for GitHub
Save this as scripts/deploy.ps1
in your repo:
if (-not $env:OPTI_PROJECT_ID -or -not $env:OPTI_CLIENT_KEY -or -not $env:OPTI_CLIENT_SECRET) { Write-Host "Missing required environment variables." -ForegroundColor Red exit 1 } Install-Module -Name EpiCloud -Scope CurrentUser -Force -ErrorAction SilentlyContinue Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser -Force Import-Module EpiCloud $projectId = $env:OPTI_PROJECT_ID $clientKey = $env:OPTI_CLIENT_KEY $clientSecret = $env:OPTI_CLIENT_SECRET $targetEnvironment = "Test1" $timestamp = Get-Date -Format "yyyyMMdd-HHmmss" $zipName = "optimizely-one-github.head.app.$timestamp.zip" $zipPath = ".\$zipName" Compress-Archive -Path * -DestinationPath $zipPath if (-not (Test-Path $zipPath)) { Write-Host "Failed to create ZIP file." -ForegroundColor Red exit 1 } Connect-EpiCloud -ProjectId $projectId -ClientKey $clientKey -ClientSecret $clientSecret $sasUrl = Get-EpiDeploymentPackageLocation Add-EpiDeploymentPackage -SasUrl $sasUrl -Path $zipPath Start-EpiDeployment ` -DeploymentPackage $zipName ` -TargetEnvironment $targetEnvironment ` -Wait
Step 3: GitHub Actions Workflow
Create a file .github/workflows/deploy.yml
:
name: Deploy to Optimizely on: push: branches: - main jobs: deploy: runs-on: windows-latest steps: - name: Checkout code uses: actions/checkout@v3 - name: Run deployment script shell: pwsh run: ./scripts/deploy.ps1 env: OPTI_PROJECT_ID: ${{ secrets.OPTI_PROJECT_ID }} OPTI_CLIENT_KEY: ${{ secrets.OPTI_CLIENT_KEY }} OPTI_CLIENT_SECRET: ${{ secrets.OPTI_CLIENT_SECRET }}
Summary
Deployment Type | Tools Used | Recommended For |
---|---|---|
Manual | PowerShell | First-time deployments, debugging |
Automated | GitHub CI/CD + PowerShell | Production deployments, automation |
Once you're confident with manual deployments, switch to CI/CD for consistency and speed ๐
Have questions? I'm here to help!