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:

bash
# ========== 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.

bash
az group create --name $RESOURCE_GROUP --location $LOCATION

1.3 Create Container Apps Environment

Creates the environment where your preview apps will run.

bash
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.

bash
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.

bash
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.

bash
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.

bash
az ad app create --display-name $APP_NAME

1.8 Get App Credentials

Retrieves the app ID and object ID for the next steps.

bash
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).

bash
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.

bash
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.

bash
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.

bash
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

  1. Go to your repository → SettingsSecrets and variablesActions

  2. Click New repository secret and add these Secrets:

    • AZURE_CLIENT_ID
    • AZURE_TENANT_ID
    • AZURE_SUBSCRIPTION_ID
  3. Click the Variables tab and add these Variables:

    • AZURE_RESOURCE_GROUP
    • AZURE_LOCATION
    • AZURE_CONTAINER_REGISTRY
    • AZURE_REGISTRY_IDENTITY
    • AZURE_ENVIRONMENT_NAME

Step 3: Add Workflow File

Create .github/workflows/preview.yml in your repository:

yaml
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 name
  • port: The port your app listens on (e.g., 3000, 8080)

Step 4: Test It

  1. Commit and push the workflow file to your repository
  2. Create a new Pull Request
  3. Watch the Actions tab - you should see the workflow running
  4. 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.

bash
# 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:

bash
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:


Quick Reference

Repository Secrets:

  • AZURE_CLIENT_ID
  • AZURE_TENANT_ID
  • AZURE_SUBSCRIPTION_ID

Repository Variables:

  • AZURE_RESOURCE_GROUP
  • AZURE_LOCATION
  • AZURE_CONTAINER_REGISTRY
  • AZURE_REGISTRY_IDENTITY
  • AZURE_ENVIRONMENT_NAME

Workflow must change:

  • IMAGE_NAME - your app name
  • port - your app's port number