End-to-end local deployment loop for Gitea-hosted projects. Use when the user wants to commit on dev, push to remote, monitor the golden CI/build/deploy workflow, validate prod on the configured prod host, and fix lint/test/pipeline failures until deployment is healthy.
Instal·la
npx skillscat add saajunaid/caddis-plugin/deploy-local Instal·la des del registre de SkillsCat.
Deploy Local Skill
Run reliable local-to-prod delivery for repositories hosted on a self-hosted Gitea.
When To Use
Use this skill when requests include any of:
- "commit and deploy"
- "commit and push"
- "push and monitor pipeline"
- "watch prod deploy"
- "monitor deployment in prod"
- "fix CI failures"
- "lint/test failing in pipeline"
- "stuck in queue"
Required Companion Skills
Load these first when they exist (your org may ship private deploy skills):
- your org's
golden-workflowskill (CI/CD workflow contract) - your org's
windows-deploymentskill (NSSM + reverse proxy) .github/skills/devops/ci-cd-pipeline/SKILL.md.github/skills/devops/git-commit/SKILL.md
Optional:
.github/skills/devops/gh-cli/SKILL.mdfor issue/PR linking.github/skills/workflow/verification-loop/SKILL.mdfor stricter local validation loops
Local Platform Defaults (configure per project)
Resolve these from your project config (e.g. a repo-local config/.env.gitea) — do not hardcode:
- Gitea UI / API base:
$env:GITEA_BASE_URL(e.g.http://gitea.example:8090, API at.../api/v1) - Repo org/owner:
<org> - Expected non-prod runner label:
dev - Expected prod runner label:
prod - Prod host:
$env:PROD_HOST - Prod checkout root:
<prod-checkout-root>\<repo>
Golden Deploy Model
The deploy-critical path is SHA-driven:
- A push to
maintriggers the canonical.gitea/workflows/ci.yml. lint_and_testand any repo-relevant frontend checks run ondev.deploy_prodruns onprodonly after gates pass.- Prod fetches, resets, and verifies the expected commit SHA.
- Prod installs/builds/restarts app-owned NSSM services.
- Prod health and version endpoints are verified.
release_metadatacreates/pushes the CalVer Git tag only after deploy success.- A tag-triggered workflow run may occur, but deploy/release jobs must be skipped for tag refs.
CalVer is release metadata, not the deploy identity. Do not reintroduce tag-first deploy logic.
Phase 1: Preflight
- Confirm repo root and current branch.
- Run
git status --short. - Identify the repo's actual gates from
.gitea/workflows/ci.yml; do not invent database or frontend gates. - Run local quality gates that mirror CI where feasible before any commit:
- Backend repos:
ruff check .(required), then format/tests as configured. - Frontend repos: lint/typecheck/build as configured.
- Full-stack repos: run both backend and frontend gates.
- Repo-specific data/database checks only when the repo declares that capability.
- If a gate fails, fix source code first before changing workflow logic.
Phase 2: Commit + Push
- Confirm preflight quality gates are green (no failing
ruff/lint checks). - Stage only intended files.
- Commit with a conventional message.
- Push to the target branch, normally
mainfor prod deploy. - Capture commit SHA and remote ack.
Example:
git status --short
git add <files>
git commit -m "fix(ci): resolve deploy health check"
git push origin main
git rev-parse HEADPhase 3: CI and Deploy Monitoring
Before calling the Gitea API, normalize token variables from the repo-localconfig/.env.gitea file when it exists. The shell environment can be stale even
when the repo has a valid token file.
$envFile = Join-Path (Get-Location) "config/.env.gitea"
if (Test-Path $envFile) {
Get-Content $envFile | ForEach-Object {
$line = $_.Trim()
if (-not $line -or $line.StartsWith("#") -or $line -notmatch "=") { return }
$key, $value = $line -split "=", 2
if ($key -in @("GITEA_TOKEN", "REPO_API", "GITEA_BASE_URL")) {
Set-Item -Path "Env:$($key.Trim())" -Value $value.Trim().Trim('"').Trim("'")
}
}
}Monitor the run lifecycle in Gitea:
- Find the latest
ci.yml@refs/heads/mainrun for the pushed SHA. - Track jobs in order:
lint_and_testfrontend_checkswhen presentdeploy_prodrelease_metadatanotify
- If a tag-triggered run appears after release metadata, verify
deploy_prodandrelease_metadataare skipped. - If a gate fails:
- classify as lint, format, test, build, workflow-runtime, deploy-script, prod-env, release-metadata, or infra-runner.
- patch the smallest safe fix.
- rerun from commit/push.
Gitea API shape:
$headers = @{ Authorization = "token $env:GITEA_TOKEN" }
$runs = Invoke-RestMethod -Uri "$env:GITEA_BASE_URL/api/v1/repos/<org>/<repo>/actions/runs?limit=10" -Headers $headers
$run = $runs.workflow_runs |
Where-Object { $_.head_sha -eq "<expected-sha>" -and $_.path -like "ci.yml@refs/heads/main" } |
Select-Object -First 1
$jobs = Invoke-RestMethod -Uri "$env:GITEA_BASE_URL/api/v1/repos/<org>/<repo>/actions/runs/$($run.id)/jobs" -Headers $headers
$jobs.jobs | Select-Object name,status,conclusion,started_at,completed_atPhase 4: Prod Validation
For Windows prod flow, validate:
- Prod checkout reached the expected SHA.
- App-owned NSSM services are running.
- App ports are listening and owned by the app, not another project.
- Health endpoint returns success.
- Version endpoint returns the expected SHA/CalVer metadata when the repo exposes it.
- Post-deploy git dirtiness contains only allowed generated files.
Example:
Invoke-Command -ComputerName $env:PROD_HOST -ScriptBlock {
$root = "<prod-checkout-root>\<repo>"
Set-Location $root
[pscustomobject]@{
Head = (git rev-parse HEAD)
Branch = (git branch --show-current)
Status = ((git status --short) -join '; ')
Services = Get-Service -Name "app-<short>-*" -ErrorAction SilentlyContinue |
Select-Object Name,Status,DisplayName
ApiPort = Get-NetTCPConnection -LocalPort <api-port> -State Listen -ErrorAction SilentlyContinue |
Select-Object LocalAddress,LocalPort,OwningProcess
Health = Invoke-RestMethod -Uri "http://127.0.0.1:<api-port>/health" -TimeoutSec 5
Version = Invoke-RestMethod -Uri "http://127.0.0.1:<api-port>/api/version" -TimeoutSec 5
}
}Use windows-deployment skill patterns for NSSM and reverse proxy checks.
Phase 4.5: Release Metadata Validation
Validate release metadata after prod health is confirmed:
- The main push run's
release_metadatajob succeeded or was intentionally skipped by policy. - A CalVer tag points at the deployed SHA.
- A tag-triggered run, if created, did not redeploy.
Do not mark production unhealthy solely because a release tag failed after a successful deploy. Report it as a release metadata failure and fix it separately unless it affects service health.
git fetch --tags --force
git tag --points-at <deployed-sha> | Where-Object { $_ -match '^v\d{4}\.\d{2}\.\d{2}\.\d+$' }Phase 5: Queue / Runner Triage
If a run is stuck waiting:
- Verify workflow
runs-onlabels match available runners. - Check runner service health on the correct host.
- Check workflow
concurrencygroups for blocking in-progress jobs. - Cancel stale runs only if policy allows.
Do not change runner labels or re-register runners from an app repo.
Phase 6: Failure Auto-Remediation Rules
Lint/Format Failures
- Fix code directly and keep style-consistent.
- Rerun local lint before push.
Test Failures
- Fix failing code/tests according to project policy.
- Keep behavior-preserving unless feature changes are requested.
Workflow Runtime Failures
- Fix parser/shell/exit-code handling in workflow YAML.
- Ensure native command failures are fatal in PowerShell steps.
- Preserve the golden job graph unless the repo has a justified exception.
Build/Deploy Failures
- Fix config or script with minimal blast radius.
- Verify prod expected SHA, NSSM service state, port ownership, health, and version endpoint.
- Do not restart or relabel the shared prod runner to fix an app deploy.
Release Metadata Failures
- Fix
release_metadataseparately after confirming prod is healthy. - Do not make deploy depend on pre-deploy tags or workflow output plumbing.
Exit Criteria
All must be true:
- Local applicable lint/test/build checks pass.
- Push succeeded and commit SHA is recorded.
- The relevant
ci.yml@refs/heads/mainrun completed. - Required jobs completed with expected conclusions.
- Prod checkout matches the pushed SHA when deploy was expected.
- Prod health endpoint is green when deploy was expected.
- Release metadata is created or accurately reported as a separate non-health failure.
- Notify emitted the real success/failure signal.
Report Template
## Deploy Local Report
- Repo:
- Branch:
- Commit:
- CI Run:
- Gate Results:
- lint/test:
- frontend:
- deploy:
- release_metadata:
- notify:
- Prod Validation:
- host:
- SHA:
- services:
- health:
- version:
- Fixes Applied:
- Final Status:
- Follow-ups:Anti-Patterns
- Treating stale terminal output as current truth.
- Changing workflow orchestration before fixing clear source-code lint/test failures.
- Making quality gates non-blocking to force deployment.
- Declaring queue issues fixed without verifying runner availability and label alignment.
- Reintroducing tag-first deploy logic.
- Treating tag-triggered skipped deploy jobs as failures.
- Changing shared runner services from an app repo.