Getting Started with PreviewKit
Get preview environments for your Pull Requests in under 5 minutes.
What You'll Get
When you open a PR, PreviewKit will automatically:
- Build your Docker image
- Deploy it to Azure Container Apps
- Post a comment with the preview URL
When you close the PR, it cleans up everything automatically.
Prerequisites Checklist
Before you start, make sure you have:
- A GitHub repository with a
Dockerfile - An Azure account with active subscription
- Azure CLI installed (install guide)
- Logged into Azure CLI (
az login) - Owner or Contributor role on your Azure subscription
5-Minute Setup
Step 1: Configure Azure Infrastructure
1.1 Set Your Variables
First, set your configuration. Change the values in the top section:
# ========== CHANGE THESE ==========
RESOURCE_GROUP="my-previews"
ACR_NAME="myregistry123" # Must be globally unique
ENVIRONMENT_NAME="preview-env"
GITHUB_REPO="myorg/myrepo" # Format: owner/repo
LOCATION="eastus"
IDENTITY_NAME="previewkit-acr-pull"
APP_NAME="previewkit-github"
# ==================================
1.2 Create Resource Group
Creates a container for all your Azure resources.
az group create --name $RESOURCE_GROUP --location $LOCATION
1.3 Create Container Apps Environment
Creates the environment where your preview apps will run.
az containerapp env create \
--name $ENVIRONMENT_NAME \
--resource-group $RESOURCE_GROUP \
--location $LOCATION
1.4 Create Container Registry
Creates a private registry to store your Docker images.
az acr create \
--name $ACR_NAME \
--resource-group $RESOURCE_GROUP \
--sku Basic \
--location $LOCATION
1.5 Create Managed Identity
Creates an identity that your apps will use to pull images from the registry.
az identity create \
--name $IDENTITY_NAME \
--resource-group $RESOURCE_GROUP \
--location $LOCATION
1.6 Grant Registry Pull Permission
Allows the managed identity to pull images from your container registry.
IDENTITY_PRINCIPAL=$(az identity show --name $IDENTITY_NAME --resource-group $RESOURCE_GROUP --query principalId -o tsv)
ACR_ID=$(az acr show --name $ACR_NAME --query id -o tsv)
az role assignment create \
--assignee $IDENTITY_PRINCIPAL \
--role AcrPull \
--scope $ACR_ID
1.7 Create Azure AD App Registration
Creates an app registration for GitHub to authenticate with Azure using OIDC.
az ad app create --display-name $APP_NAME
1.8 Get App Credentials
Retrieves the app ID and object ID for the next steps.
APP_ID=$(az ad app list --display-name $APP_NAME --query "[0].appId" -o tsv)
OBJECT_ID=$(az ad app list --display-name $APP_NAME --query "[0].id" -o tsv)
1.9 Create Service Principal
Creates a service principal (the actual identity that GitHub will use).
az ad sp create --id $APP_ID
SP_OBJECT_ID=$(az ad sp list --filter "appId eq '$APP_ID'" --query "[0].id" -o tsv)
SUBSCRIPTION_ID=$(az account show --query id -o tsv)
1.10 Grant Contributor Permission
Allows GitHub to create and manage container apps in your resource group.
az role assignment create \
--assignee $SP_OBJECT_ID \
--role Contributor \
--scope /subscriptions/$SUBSCRIPTION_ID/resourceGroups/$RESOURCE_GROUP
1.11 Configure GitHub OIDC Trust
Establishes trust so GitHub Actions can authenticate without secrets.
az ad app federated-credential create \
--id $OBJECT_ID \
--parameters "{
\"name\": \"github-pr\",
\"issuer\": \"https://token.actions.githubusercontent.com\",
\"subject\": \"repo:${GITHUB_REPO}:pull_request\",
\"audiences\": [\"api://AzureADTokenExchange\"]
}"
1.12 Collect Configuration Values
Retrieves all the values you'll need for GitHub configuration.
IDENTITY_ID=$(az identity show --name $IDENTITY_NAME --resource-group $RESOURCE_GROUP --query id -o tsv)
TENANT_ID=$(az account show --query tenantId -o tsv)
echo ""
echo "=========================================="
echo "✅ Azure setup complete!"
echo "=========================================="
echo ""
echo "Add these to GitHub Secrets:"
echo "----------------------------"
echo "AZURE_CLIENT_ID: $APP_ID"
echo "AZURE_TENANT_ID: $TENANT_ID"
echo "AZURE_SUBSCRIPTION_ID: $SUBSCRIPTION_ID"
echo ""
echo "Add these to GitHub Variables:"
echo "------------------------------"
echo "AZURE_RESOURCE_GROUP: $RESOURCE_GROUP"
echo "AZURE_LOCATION: $LOCATION"
echo "AZURE_CONTAINER_REGISTRY: ${ACR_NAME}.azurecr.io"
echo "AZURE_REGISTRY_IDENTITY: $IDENTITY_ID"
echo "AZURE_ENVIRONMENT_NAME: $ENVIRONMENT_NAME"
echo ""
Step 2: Configure GitHub Repository
-
Go to your repository → Settings → Secrets and variables → Actions
-
Click New repository secret and add these Secrets:
AZURE_CLIENT_IDAZURE_TENANT_IDAZURE_SUBSCRIPTION_ID
-
Click the Variables tab and add these Variables:
AZURE_RESOURCE_GROUPAZURE_LOCATIONAZURE_CONTAINER_REGISTRYAZURE_REGISTRY_IDENTITYAZURE_ENVIRONMENT_NAME
Step 3: Add Workflow File
Create .github/workflows/preview.yml in your repository:
name: PR Preview
on:
pull_request:
types: [opened, synchronize, reopened, closed]
permissions:
id-token: write
contents: read
pull-requests: write
env:
AZURE_CONTAINER_REGISTRY: ${{ vars.AZURE_CONTAINER_REGISTRY }}
IMAGE_NAME: my-app # Change this to your app name
jobs:
preview:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Login to Azure
uses: azure/login@v2
with:
client-id: ${{ secrets.AZURE_CLIENT_ID }}
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
- name: Build and push image
if: github.event.action != 'closed'
run: |
az acr login --name ${{ env.AZURE_CONTAINER_REGISTRY }}
docker build -t ${{ env.AZURE_CONTAINER_REGISTRY }}/${{ env.IMAGE_NAME }}:pr-${{ github.event.pull_request.number }} .
docker push ${{ env.AZURE_CONTAINER_REGISTRY }}/${{ env.IMAGE_NAME }}:pr-${{ github.event.pull_request.number }}
- name: Deploy Preview
uses: krav4enkodm/previewkit/action@main
with:
service-name: ${{ env.IMAGE_NAME }}
port: 3000 # Change this to your app's port
cloud: azure
azure-subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
azure-resource-group: ${{ vars.AZURE_RESOURCE_GROUP }}
azure-location: ${{ vars.AZURE_LOCATION }}
azure-container-app-environment: ${{ vars.AZURE_ENVIRONMENT_NAME }}
azure-registry-server: ${{ env.AZURE_CONTAINER_REGISTRY }}
azure-registry-identity: ${{ vars.AZURE_REGISTRY_IDENTITY }}
image: ${{ env.AZURE_CONTAINER_REGISTRY }}/${{ env.IMAGE_NAME }}:pr-${{ github.event.pull_request.number }}
github-token: ${{ secrets.GITHUB_TOKEN }}
Important: Update these values in the workflow:
IMAGE_NAME: Your application nameport: The port your app listens on (e.g., 3000, 8080)
Step 4: Test It
- Commit and push the workflow file to your repository
- Create a new Pull Request
- Watch the Actions tab - you should see the workflow running
- Once complete, check your PR for a comment with the preview URL
Troubleshooting Common Setup Issues
"Environment not found"
The Container Apps Environment name is wrong or doesn't exist.
# List all environments in your resource group
az containerapp env list --resource-group YOUR_RESOURCE_GROUP --query "[].name" -o tsv
Update the AZURE_ENVIRONMENT_NAME variable in GitHub with the correct name.
"OIDC authentication failed"
GitHub can't authenticate to Azure. Verify the federated credential subject matches your repo:
az ad app federated-credential list --id YOUR_APP_OBJECT_ID
The subject should be: repo:YOUR_ORG/YOUR_REPO:pull_request
"Failed to pull image"
The managed identity doesn't have AcrPull permissions. Re-run the role assignment command from Step 1.6.
Need more help? See the comprehensive Troubleshooting Guide for detailed solutions to all common issues.
What's Next?
Now that you have PreviewKit running, explore advanced features:
- Multiple services? See User Guide - Multiple Services
- Custom environment variables? See User Guide - Advanced Configuration
- Different authentication method? See User Guide - Authentication Options
- Complete reference? See the full User Guide
- Need help? Open an issue
Quick Reference
Repository Secrets:
AZURE_CLIENT_IDAZURE_TENANT_IDAZURE_SUBSCRIPTION_ID
Repository Variables:
AZURE_RESOURCE_GROUPAZURE_LOCATIONAZURE_CONTAINER_REGISTRYAZURE_REGISTRY_IDENTITYAZURE_ENVIRONMENT_NAME
Workflow must change:
IMAGE_NAME- your app nameport- your app's port number