217 lines
6.7 KiB
Markdown
217 lines
6.7 KiB
Markdown
# 🚀 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:
|
||
# Prefer a commit SHA from wdipl-actions @main (see "stale reusable workflows" above).
|
||
uses: http://git.wdipl.com/Rajendra.Reddy/wdipl-actions/.gitea/workflows/ci.yml@main
|
||
|
||
with:
|
||
tech_stack: node
|
||
|
||
# Comma-separated: build, sonar, deploy (WDIPL-Runner only forwards one “flag” string reliably).
|
||
ci_steps: 'build,sonar,deploy'
|
||
wait_for_quality_gate: 'false'
|
||
|
||
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:
|
||
SONARQUBE_HOST: ${{ secrets.SONARQUBE_HOST }}
|
||
SONARQUBE_TOKEN: ${{ secrets.SONARQUBE_TOKEN }}
|
||
|
||
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
|
||
|
||
| Name | Value |
|
||
| ---------------- | ------------------------ |
|
||
| SONARQUBE_HOST | http://your-sonar-server |
|
||
| SONARQUBE_TOKEN | your sonar token |
|
||
|
||
---
|
||
|
||
## 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 |
|
||
| ci_steps | e.g. `build,sonar,deploy` — **no spaces** (runner has no `replace()`) |
|
||
| wait_for_quality_gate | `'true'` / `'false'` (quoted) |
|
||
| 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>
|
||
```
|
||
|
||
---
|
||
|
||
# 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`).
|
||
|
||
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.
|
||
|
||
**Fix one of:**
|
||
|
||
1. Pin **`uses:` to a commit SHA** from `wdipl-actions`, e.g.
|
||
`uses: .../ci.yml@08e779fe5701557b6a589308816be97c20d78dbb`
|
||
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.
|
||
|
||
---
|
||
|
||
# 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.
|
||
|
||
---
|
||
|
||
# ⚠️ Notes
|
||
|
||
* Use **either password OR SSH key**
|
||
* Ensure server has:
|
||
|
||
* Node.js
|
||
* PM2
|
||
* Paths must exist on server
|
||
* Deployment runs only if `ci_steps` includes `deploy` (comma‑bounded token)
|
||
|
||
---
|
||
|
||
# ✅ Summary
|
||
|
||
1. Add `ci.yml`
|
||
2. Add secrets
|
||
3. Set paths
|
||
|
||
Done.
|
||
|
||
---
|