Skip to content

Part 6: Branch Deployments

Deploy a feature branch alongside your main deployment for side-by-side testing.

What you'll learn

  • Building and deploying from a feature branch
  • Comparing branch deployments with the main deployment
  • Setting branch-specific environment variables
  • Promoting a branch build to main
  • Cleaning up branch deployments

What you'll need


Step 1: Create a feature branch

Add a due_date field to the Todo model. Create the branch and make the changes:

git checkout -b feature/due-dates

Update backend/core/models.py:

from django.db import models


class Todo(models.Model):
    title = models.CharField(max_length=255)
    done = models.BooleanField(default=False)
    due_date = models.DateField(null=True, blank=True)
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        ordering = ["-created_at"]

    def __str__(self):
        return self.title

Update backend/core/serializers.py:

from rest_framework import serializers
from .models import Todo


class TodoSerializer(serializers.ModelSerializer):
    class Meta:
        model = Todo
        fields = ["id", "title", "done", "due_date", "created_at"]
        read_only_fields = ["id", "created_at"]

Update the frontend to show due dates. In frontend/src/App.jsx, add a date input to the form and display due dates in the list:

const [dueDate, setDueDate] = useState("");

// In the form:
<input
  type="date"
  value={dueDate}
  onChange={(e) => setDueDate(e.target.value)}
/>

// In the POST body:
body: JSON.stringify({ title, due_date: dueDate || null })

// In the list item:
<span style={{ color: "#888", fontSize: "0.8em" }}>
  {todo.due_date && ` (due: ${todo.due_date})`}
</span>

Commit and push:

git add -A
git commit -m "feat: add due_date field to todos"
git push origin feature/due-dates

Step 2: Build and deploy the branch

Build from the feature branch. A deploy is queued automatically after a successful build, so this one command does both:

mecca build trigger -e dev \
  -g git@github.com:yourorg/todo-app.git \
  -b feature/due-dates

Or build and deploy as separate steps:

mecca build trigger -e dev \
  -g git@github.com:yourorg/todo-app.git \
  -b feature/due-dates --no-deploy

mecca app deploy todo-app -b feature/due-dates -e dev

Separate URLs

Branch deployments get their own hostnames. The sanitised branch name is inserted between the app slug and the service name (/ becomes -), and main contributes no segment at all:

  • Main: https://todo-app-frontend-yourgroup.dev.yourdomain.com
  • Branch: https://todo-app-feature-due-dates-frontend-yourgroup.dev.yourdomain.com

Step 3: Compare the deployments

mecca queue status takes the action ID each build or deploy printed — not an app name. To see everything currently in flight for the app, use mecca queue list:

mecca queue list -a todo-app -e dev
mecca queue status ACTION_ID -e dev

mecca app show lists the branches the app is registered on:

mecca app show todo-app -e dev

Open both URLs in your browser. The main deployment has the original todo list. The branch deployment has the new due date field.

Step 4: Set branch-specific environment variables

mecca var set writes to every branch unless you narrow it. Pass -b to override a variable for the branch deployment only:

mecca var set todo-app PUBLIC_APP_TITLE="Todo App (Due Dates Preview)" \
  -b feature/due-dates -e dev

Redeploy the branch to pick up the change:

mecca app deploy todo-app -b feature/due-dates --no-build -e dev

The main deployment title remains unchanged.

Branch isolation

Every branch gets its own, initially empty database — the name is derived per branch, so main and feature/due-dates never share data. Your entrypoint's migrate step builds the schema on the branch's first deploy; no data is copied from main. Drives and buckets are per-branch too.

Step 5: Test the new feature

Create a todo with a due date on the branch deployment:

BRANCH_URL="https://todo-app-feature-due-dates-backend-yourgroup.dev.yourdomain.com"

curl -X POST "$BRANCH_URL/api/todos/" \
  -H "Content-Type: application/json" \
  -d '{"title": "Review PR", "due_date": "2026-03-15"}'

curl "$BRANCH_URL/api/todos/"

Verify the main deployment still works without the due_date field:

MAIN_URL="https://todo-app-backend-yourgroup.dev.yourdomain.com"

curl -X POST "$MAIN_URL/api/todos/" \
  -H "Content-Type: application/json" \
  -d '{"title": "Main branch todo"}'

Step 6: Promote and clean up

Once the feature is reviewed and merged to main:

git checkout main
git merge feature/due-dates
git push origin main

Build and deploy from main:

mecca build trigger -e dev -g git@github.com:yourorg/todo-app.git

Remove the branch deployment:

mecca app undeploy todo-app -b feature/due-dates --force -e dev

Purge option

Add --purge to also delete the branch's built images and build history. Without it, the registry data is preserved for future reference:

mecca app undeploy todo-app -b feature/due-dates --force --purge -e dev

Workflow summary

Step Command
Build branch mecca build trigger -g URL -b BRANCH -e dev
List in-flight actions mecca queue list -a APP -e dev
Check one action mecca queue status ACTION_ID -e dev
Set env vars (one branch) mecca var set APP KEY=VALUE -b BRANCH -e dev
Undeploy branch mecca app undeploy APP -b BRANCH --force -e dev
Purge branch data mecca app undeploy APP -b BRANCH --force --purge -e dev

What's next

Branch deployments communicate via public URLs. In Part 7: Internal Service Discovery, you will look at how services address each other inside AppMecca's private network.