2026-04-07 10:20:05 +00:00
# 🚀 CI/CD Setup Guide (For Developers)
This project uses a centralized CI/CD system.
You only need to configure **1 workflow file + secrets** .
---
# 📁 1. Add Workflow File
Create:
```
.gitea/workflows/ci.yml
```
Paste:
```yaml
name: CI
on:
push:
branches: [main, beta, staging, testing]
pull_request:
jobs:
ci:
2026-04-07 23:57:49 +05:30
# Prefer a commit SHA from wdipl-actions @main (see "stale reusable workflows" above).
2026-04-07 10:20:05 +00:00
uses: http://git.wdipl.com/Rajendra.Reddy/wdipl-actions/.gitea/workflows/ci.yml@main
with:
tech_stack: node
2026-04-07 23:55:48 +05:30
# Comma-separated: build, sonar, deploy (WDIPL-Runner only forwards one “flag” string reliably).
ci_steps: 'build,sonar,deploy'
2026-04-07 22:45:18 +05:30
wait_for_quality_gate: 'false'
2026-04-07 10:20:05 +00:00
app_path_beta: /var/www/app-beta
app_path_staging: /var/www/app-staging
app_path_prod: /var/www/app-prod
pm2_id: app
secrets:
2026-04-08 00:15:37 +05:30
SONARQUBE_HOST: ${{ secrets.SONARQUBE_HOST }}
SONARQUBE_TOKEN: ${{ secrets.SONARQUBE_TOKEN }}
2026-04-07 10:20:05 +00:00
BETA_SERVER_HOST: ${{ secrets.BETA_SERVER_HOST }}
BETA_SERVER_PORT: ${{ secrets.BETA_SERVER_PORT }}
BETA_SERVER_USERNAME: ${{ secrets.BETA_SERVER_USERNAME }}
BETA_SERVER_PASSWORD: ${{ secrets.BETA_SERVER_PASSWORD }}
BETA_SERVER_KEY: ${{ secrets.BETA_SERVER_KEY }}
STAGING_SERVER_HOST: ${{ secrets.STAGING_SERVER_HOST }}
STAGING_SERVER_PORT: ${{ secrets.STAGING_SERVER_PORT }}
STAGING_SERVER_USERNAME: ${{ secrets.STAGING_SERVER_USERNAME }}
STAGING_SERVER_PASSWORD: ${{ secrets.STAGING_SERVER_PASSWORD }}
STAGING_SERVER_KEY: ${{ secrets.STAGING_SERVER_KEY }}
PROD_SERVER_HOST: ${{ secrets.PROD_SERVER_HOST }}
PROD_SERVER_PORT: ${{ secrets.PROD_SERVER_PORT }}
PROD_SERVER_USERNAME: ${{ secrets.PROD_SERVER_USERNAME }}
PROD_SERVER_PASSWORD: ${{ secrets.PROD_SERVER_PASSWORD }}
PROD_SERVER_KEY: ${{ secrets.PROD_SERVER_KEY }}
```
---
# 🔐 2. Add Secrets (Repo → Settings → Secrets)
## SonarQube
2026-04-08 00:15:37 +05:30
| Name | Value |
| ---------------- | ------------------------ |
| SONARQUBE_HOST | http://your-sonar-server |
| SONARQUBE_TOKEN | your sonar token |
2026-04-07 10:20:05 +00:00
---
## Beta / Testing Server
| Name | Value |
| -------------------- | -------------------------- |
| BETA_SERVER_HOST | server IP/domain |
| BETA_SERVER_PORT | 22 |
| BETA_SERVER_USERNAME | ssh user (ubuntu/root) |
| BETA_SERVER_PASSWORD | password (optional) |
| BETA_SERVER_KEY | private ssh key (optional) |
---
## Staging Server
| Name | Value |
| ----------------------- | ------------------- |
| STAGING_SERVER_HOST | server IP/domain |
| STAGING_SERVER_PORT | 22 |
| STAGING_SERVER_USERNAME | ssh user |
| STAGING_SERVER_PASSWORD | password (optional) |
| STAGING_SERVER_KEY | ssh key (optional) |
---
## Production Server
| Name | Value |
| -------------------- | ------------------- |
| PROD_SERVER_HOST | server IP/domain |
| PROD_SERVER_PORT | 22 |
| PROD_SERVER_USERNAME | ssh user |
| PROD_SERVER_PASSWORD | password (optional) |
| PROD_SERVER_KEY | ssh key (optional) |
---
# ⚙️ 3. Variables (Edit in ci.yml)
| Variable | What to set |
| --------------------- | ---------------------- |
| tech_stack | node / react / nestjs |
2026-04-07 23:59:29 +05:30
| ci_steps | e.g. `build,sonar,deploy` — **no spaces** (runner has no `replace()` ) |
2026-04-07 23:47:30 +05:30
| wait_for_quality_gate | `'true'` / `'false'` (quoted) |
2026-04-07 10:20:05 +00:00
| app_path_beta | path on beta server |
| app_path_staging | path on staging server |
| app_path_prod | path on prod server |
| pm2_id | pm2 app name |
---
# 🌿 4. Branch Behavior
| Branch | Action |
| ----------- | -------------------- |
| feature/* | Build + Sonar |
| develop | Build + Sonar |
| testing | Deploy to Beta |
| beta | Deploy to Beta |
| staging | Deploy to Staging |
| main / prod | Deploy to Production |
---
# ⚙️ 5. What Happens on Deploy
```bash
git fetch
git reset --hard origin/< branch >
git pull
npm install
npm run build
pm2 reload < pm2_id >
```
---
2026-04-07 23:57:49 +05:30
# WDIPL-Runner: stale reusable workflows (`uses: ...@main`)
The runner caches clones under ** `/root/.cache/act/` ** (e.g. `Rajendra.Reddy-wdipl-actions@main` ). After you change ** `wdipl-actions` **, consumers may still execute an **old `ci.yml`** (wrong `if:` / missing `ci_steps` ).
2026-04-08 00:03:26 +05:30
Central ** `ci.yml` ** includes a ** `meta` job** that writes `ci_steps` to ** `$GITHUB_OUTPUT` ** so ** `needs.meta.outputs.cs` ** stays available for Sonar/Deploy: WDIPL-Runner clears ** `inputs.ci_steps` ** after the Build reusable workflow runs.
2026-04-07 23:57:49 +05:30
**Fix one of:**
1. Pin ** `uses:` to a commit SHA** from `wdipl-actions` , e.g.
2026-04-08 00:03:42 +05:30
`uses: .../ci.yml@08e779fe5701557b6a589308816be97c20d78dbb`
2026-04-07 23:57:49 +05:30
Bump the SHA whenever you change central CI.
2. On the runner host, delete that cache folder and re-run the workflow.
3. Upgrade the runner if a newer release fixes cache invalidation.
---
2026-04-07 23:42:42 +05:30
# Gitea MCP + Actions API (Cursor)
Official **gitea-mcp** (and the Go SDK it uses) calls ** `GET /api/v1/repos/{owner}/{repo}/actions/runs` ** to list workflow runs and job logs.
- **Gitea 1.24.x** exposes ** `/actions/tasks` ** for the same data but **does not** register ** `/actions/runs` ** (returns `404 page not found` ). Tools like `actions_run_read` → `list_runs` / `list_jobs` will fail until the server is updated or a proxy workaround is applied.
- **Gitea 1.25+** includes ** `ListWorkflowRuns` ** at ** `/actions/runs` ** — upgrade ** `git.wdipl.com` ** to **1.25 or newer** so MCP can list runs and fetch logs without hacks.
**Reverse-proxy workaround (until upgrade):** map list-runs requests to tasks (response shape is compatible for listing):
```nginx
# Only for the repository runs list endpoint (no trailing /{run})
location ~ ^/api/v1/repos/([^/]+)/([^/]+)/actions/runs$ {
proxy_pass http://127.0.0.1:3000/api/v1/repos/$1/$2/actions/tasks$is_args$args;
# ... usual proxy headers to your Gitea backend
}
```
Adjust `proxy_pass` to your Gitea HTTP upstream. Redeploy/reload nginx, then restart Cursor.
**Cursor:** set a user or system environment variable ** `GITEA_ACCESS_TOKEN` ** (PAT with repo + Actions read scope) and use ** `${env:GITEA_ACCESS_TOKEN}` ** in `~/.cursor/mcp.json` — do not store tokens in that file.
---
2026-04-07 10:20:05 +00:00
# ⚠️ Notes
* Use **either password OR SSH key**
* Ensure server has:
* Node.js
* PM2
* Paths must exist on server
2026-04-07 23:55:48 +05:30
* Deployment runs only if `ci_steps` includes `deploy` (comma‑ bounded token)
2026-04-07 10:20:05 +00:00
---
# ✅ Summary
1. Add `ci.yml`
2. Add secrets
3. Set paths
Done.
---