# ๐Ÿš€ 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/ git pull npm install npm run build pm2 reload ``` --- # 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. ---