---
name: mosaic-deploy
description: 'Full end-to-end deploy flow for Mosaic Stack projects: push branch → open PR → wait for CI → merge → redeploy Portainer stack. Use when deploying a feature branch to production or staging, or when asked to ship a completed feature. Orchestrates mosaic-gitea, mosaic-woodpecker, and mosaic-portainer skills.'
---

# mosaic-deploy

End-to-end deployment flow for Mosaic Stack projects.

## Full Deploy Sequence

```
push branch → open PR → CI passes → merge → portainer redeploy
```

### Step 1: Push branch and open PR

```bash
cd ~/src/<repo>-worktrees/<task-slug>
git push -u origin <branch>
~/.config/mosaic/tools/git/pr-create.sh -t "feat: ..." -b "..." -i <issue#>
# Note the PR number from output
```

### Step 2: Wait for CI

```bash
~/.config/mosaic/tools/git/pr-ci-wait.sh -n <pr#>
```

If CI fails, check:

```bash
source ~/.config/mosaic/tools/_lib/credentials.sh && load_credentials woodpecker
~/.config/mosaic/tools/woodpecker/pipeline-status.sh -r <org>/<repo>
```

### Step 3: Merge

```bash
cd ~/src/<repo>
~/.config/mosaic/tools/git/pr-merge.sh -n <pr#> -d
```

Always merge through `pr-merge.sh`: it runs the CI queue guard first and pins
the merge to the reviewed head. If branch protection blocks the merge, that is
a gate telling you something — a failing check, a moved head, or a missing
review. Fix the cause; never route around it with a raw API call, a shared
credential, or `force_merge`. Exceptional cases go to the operator or the
coordinating seat, still merged through the wrapper.

### Step 4: Redeploy Portainer stack

```bash
source ~/.config/mosaic/tools/_lib/credentials.sh && load_credentials portainer
~/.config/mosaic/tools/portainer/stack-redeploy.sh -n <stack-name> -p
```

Check deployment:

```bash
~/.config/mosaic/tools/portainer/stack-status.sh -n <stack-name>
~/.config/mosaic/tools/portainer/stack-logs.sh -n <stack-name> -l 50
```

## Stack Name Map

Maintain your estate's project → stack-name mapping in a skills-local override of
this skill (local copies take precedence over the shipped canonical one). Example
shape:

| Project      | Stack Name        |
| ------------ | ----------------- |
| `sample-app` | `sample-app`      |
| `sample-api` | `sample-api-prod` |

## Notes

- Workers open PRs but **never merge** — orchestrator or Merge Guard handles step 3+
- Docker Swarm image pinning: if `-p` doesn't pull a new image, SSH to the Docker node (e.g. `node-01`) and run `docker pull <image>` manually, then redeploy
- Worktrees: all coding work in `~/src/<repo>-worktrees/<task-slug>`, never in main checkout
- Always clean up worktree after push: `git worktree remove ~/src/<repo>-worktrees/<task-slug>`
