Files
stack/packages/mosaic/framework/skills/mosaic-deploy/SKILL.md
T
fargo c8f46341cc
ci/woodpecker/pr/ci Pipeline was successful
fix(#1320): placeholder-ize private-network topology, drop raw-curl force-merge recipe
Implements the rev-security-01 verdict on #1320 (comment 23282):

Should Fix (first, per tasking): mosaic-deploy's branch-protected-repos
section shipped a working recipe for both failure modes the estate removes
identity that is not the actor's (a legacy shared credential path,
~/.config/mosaic/credentials/gitea.env, which no longer exists in the
credential system) and a quality gate routed around (raw curl +
force_merge:true, no queue guard, no head pin). Replaced with wrapper-only
merge guidance: protection blocks are signals to fix, not to bypass.

Placeholder-ized estate RFC1918 topology and hostnames (six carriers, one
more than the verdict's five — the original scan missed guides/):
- skills/mosaic-portainer: Portainer URL, Docker host
- skills/mosaic-gitea: SSH resolution target
- skills/mosaic-deploy: Docker node, stack-name map (now generic example
  shape; estate mappings belong in skills-local overrides, which link with
  precedence)
- tools/coolify/README: base URL
- guides/INFRASTRUCTURE: cloudflare example moved from 10.0.0.5 to the
  RFC 5737 documentation range (192.0.2.5), the unambiguous example form

Left as-is per the verdict's split: estate DNS endpoints (e.g.
git.mosaicstack.dev, ci.mosaicstack.dev) pass as examples.

Rescan of the whole shipped framework tree for RFC1918, estate hosts, and
stack-name patterns: zero remaining hits. The gate defect itself is filed
separately as #1321 (cross-referenced on #1320, comment 23285).
2026-08-19 15:54:44 -05:00

2.7 KiB

name, description
name description
mosaic-deploy 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

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

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

If CI fails, check:

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

Step 3: Merge

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

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

Check deployment:

~/.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>