Skip to content

Set Up CI/CD for Optimizely Cloud

⏱ 30 minutes advanced
📜Advancedcms

Manual deployments are slow and error-prone. A developer has to remember the right steps, run the right commands, and verify the result. CI/CD automation removes this friction — every push triggers a consistent build, test, and deploy sequence. This gives your team faster feedback, fewer deployment mistakes, and a clear audit trail.


While Optimizely Cloud has a built-in deployment system triggered by Git pushes, many teams prefer external CI/CD for additional control over build steps, test execution, and quality gates. The external pipeline builds the application, runs tests, and then pushes the deployment package to Optimizely Cloud via API.

Code Push → CI Build → Run Tests → Package → Deploy via API → Verify

Add .github/workflows/deploy.yml to your repository:

name: Deploy to Optimizely Cloud
on:
push:
branches: [develop]
env:
DOTNET_VERSION: '8.0.x'
OPTI_PROJECT_ID: ${{ secrets.OPTI_PROJECT_ID }}
OPTI_API_KEY: ${{ secrets.OPTI_API_KEY }}
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: ${{ env.DOTNET_VERSION }}
- name: Restore dependencies
run: dotnet restore
- name: Build
run: dotnet build --configuration Release --no-restore
- name: Run tests
run: dotnet test --no-build --configuration Release
- name: Publish
run: dotnet publish --configuration Release --output ./publish
- name: Package
run: |
cd publish
zip -r ../deploy-package.zip .
- name: Deploy to Integration
run: |
curl -X POST \
"https://paasportal.episerver.net/api/v1.0/projects/$OPTI_PROJECT_ID/deployments" \
-H "Authorization: Bearer $OPTI_API_KEY" \
-H "Content-Type: multipart/form-data" \
-F "file=@deploy-package.zip" \
-F "targetEnvironment=Integration"

In your GitHub repository:

  1. Go to Settings > Secrets and variables > Actions
  2. Add OPTI_PROJECT_ID — Your project identifier from the management portal
  3. Add OPTI_API_KEY — API key generated in the portal under Settings > API Keys

Add azure-pipelines.yml to your repository:

trigger:
branches:
include:
- develop
pool:
vmImage: 'ubuntu-latest'
variables:
dotnetVersion: '8.0.x'
buildConfiguration: 'Release'
stages:
- stage: Build
jobs:
- job: BuildAndTest
steps:
- task: UseDotNet@2
inputs:
version: $(dotnetVersion)
- script: dotnet restore
displayName: 'Restore dependencies'
- script: dotnet build --configuration $(buildConfiguration) --no-restore
displayName: 'Build'
- script: dotnet test --configuration $(buildConfiguration) --no-build
displayName: 'Run tests'
- script: dotnet publish --configuration $(buildConfiguration) --output $(Build.ArtifactStagingDirectory)
displayName: 'Publish'
- task: ArchiveFiles@2
inputs:
rootFolderOrFile: $(Build.ArtifactStagingDirectory)
archiveType: 'zip'
archiveFile: '$(Build.ArtifactStagingDirectory)/deploy-package.zip'
- publish: $(Build.ArtifactStagingDirectory)/deploy-package.zip
artifact: deployment
- stage: Deploy
dependsOn: Build
jobs:
- deployment: DeployIntegration
environment: 'integration'
strategy:
runOnce:
deploy:
steps:
- script: |
curl -X POST \
"https://paasportal.episerver.net/api/v1.0/projects/$(OPTI_PROJECT_ID)/deployments" \
-H "Authorization: Bearer $(OPTI_API_KEY)" \
-H "Content-Type: multipart/form-data" \
-F "file=@$(Pipeline.Workspace)/deployment/deploy-package.zip" \
-F "targetEnvironment=Integration"
displayName: 'Deploy to Integration'

In Azure DevOps:

  1. Go to Pipelines > Library > Variable Groups
  2. Create a variable group named optimizely-cloud
  3. Add OPTI_PROJECT_ID and OPTI_API_KEY (mark the API key as secret)
  4. Link the variable group to your pipeline

Extend your pipeline with additional quality checks:

- name: Run code analysis
run: dotnet format --verify-no-changes
- name: Scan for vulnerabilities
run: dotnet list package --vulnerable --include-transitive
- name: Smoke test
run: |
STATUS=$(curl -s -o /dev/null -w "%{http_code}" https://mysite.inte.optimizely.cloud)
if [ "$STATUS" != "200" ]; then
echo "Smoke test failed with status $STATUS"
exit 1
fi

Add manual approval gates for Preproduction and Production deployments:

  • GitHub Actions — Use environments with required reviewers
  • Azure DevOps — Use environment approvals and gates

This ensures code only reaches Production after a human reviews the Preproduction deployment.