From 1258ecf89920435cb981f368b2c7c6a046d677db Mon Sep 17 00:00:00 2001 From: rameen Date: Sun, 23 Aug 2026 11:10:28 +0330 Subject: [PATCH] Enable Gitea Actions staging deploy on master push --- .gitea/workflows/registry-build-deploy.yml | 339 +++++++++------------ AGENTS.md | 2 +- README.md | 99 +----- infrastructure/deploy.registry.env.example | 7 +- 4 files changed, 158 insertions(+), 289 deletions(-) diff --git a/.gitea/workflows/registry-build-deploy.yml b/.gitea/workflows/registry-build-deploy.yml index 1ca249e..1f5fd2e 100644 --- a/.gitea/workflows/registry-build-deploy.yml +++ b/.gitea/workflows/registry-build-deploy.yml @@ -1,30 +1,25 @@ -# Build backend/frontend images, push to Gitea Container Registry, deploy with pull-only compose. +# Staging: build backend/frontend images, push to Gitea Container Registry, deploy on self-hosted runner. # -# Repository Variables (Settings → Actions → Variables) — non-secret: +# Triggers: push to master/main, or manual workflow_dispatch. +# +# Repository Variables (Settings → Actions → Variables): # REGISTRY_HOST e.g. 178.131.50.201:3000 (no http/https) -# REGISTRY_OWNER Gitea user or org that owns the packages (same as image namespace) +# REGISTRY_OWNER Gitea user or org that owns the packages # PUBLIC_BASE_URL URL users open in browser, e.g. http://178.131.50.201:8088 (no trailing slash) +# DEPLOY_SECRETS_DIR absolute path on runner, e.g. C:/dyolink/secrets +# +# Optional: +# STAGING_HTTP_PORT host port for nginx (default 8088) +# CLONE_HOST when runner is on the same host as Gitea and public IP fails locally, +# set to 127.0.0.1:3000 (no http:// — same style as REGISTRY_HOST) # # Repository Secrets (Settings → Actions → Secrets): # REGISTRY_USERNAME Gitea username for docker login # REGISTRY_PASSWORD Gitea access token (packages:read/write) or account password # -# HTTP registry (typical self-hosted Gitea): Docker defaults to HTTPS. If login/push fails with -# "server gave HTTP response to HTTPS client", add REGISTRY_HOST (e.g. 192.168.1.100:3000) to the -# Docker daemon "insecure-registries" on the RUNNER machine, then restart Docker (Docker Desktop -# → Settings → Docker Engine → JSON → "insecure-registries": ["host:port"]). +# Docker on runner: add REGISTRY_HOST to insecure-registries (HTTP registry), then restart Docker. # -# Optional: -# STAGING_HTTP_PORT host port for nginx (default 8088) -# -# Required for deploy job (absolute path on the runner host): -# DEPLOY_SECRETS_DIR folder containing database.staging.env + backend.staging.env -# -# Runner: self-hosted with Docker. Default shell is powershell (Windows act_runner often has no WSL bash). -# For a Linux runner, change defaults.run.shell to bash and restore bash syntax if needed. -# -# We do NOT use gitea.com/actions/checkout — many restricted networks cannot reach gitea.com. -# Checkout is a plain git clone from the same Gitea host. +# Runner: self-hosted with Docker + git. Default shell is powershell (Windows act_runner). name: Registry — build, push, deploy @@ -38,189 +33,149 @@ defaults: shell: powershell jobs: - temp-success: + build-and-push: runs-on: self-hosted + outputs: + image_tag: ${{ steps.meta.outputs.image_tag }} steps: - - name: Temporary placeholder (always success) + - name: Checkout (clone from this Gitea — no gitea.com) run: | $ErrorActionPreference = 'Stop' - Write-Host "Temporary workflow is active." - Write-Host "Trigger: ${{ github.event_name }}" - Write-Host "Branch: ${{ github.ref_name }}" - Write-Host "Commit: ${{ github.sha }}" - Write-Host "Production build/push/deploy steps are intentionally commented." - exit 0 + $cloneHost = '${{ vars.CLONE_HOST }}'.Trim() + if ([string]::IsNullOrWhiteSpace($cloneHost)) { + $Server = "${{ github.server_url }}".TrimEnd('/') + } elseif ($cloneHost -match '^https?://') { + $Server = $cloneHost.TrimEnd('/') + } else { + $Server = 'http://' + $cloneHost + } + $Repo = "${{ github.repository }}" + $Branch = "${{ github.ref_name }}" + $Token = "${{ github.token }}" + $Actor = "${{ github.actor }}" + $hp = $Server -replace '^https?://', '' + if ($Server.StartsWith('https')) { + $cloneUrl = 'https://' + $Actor + ':' + $Token + '@' + $hp + '/' + $Repo + '.git' + } else { + $cloneUrl = 'http://' + $Actor + ':' + $Token + '@' + $hp + '/' + $Repo + '.git' + } + $env:GIT_TERMINAL_PROMPT = '0' + git clone --depth 1 --branch $Branch $cloneUrl . - # --------------------------------------------------------------------------- - # Production pipeline is temporarily disabled. - # Uncomment these jobs after split-DNS / registry reachability is fixed. - # --------------------------------------------------------------------------- - # - # build-and-push: - # runs-on: self-hosted - # outputs: - # image_tag: ${{ steps.meta.outputs.image_tag }} - # steps: - # - name: Checkout (clone from this Gitea — no gitea.com) - # - name: Image tag and registry prefix - # - name: Log in to container registry - # - name: Build and push backend - # - name: Build and push frontend - # - # deploy: - # needs: build-and-push - # runs-on: self-hosted - # steps: - # - name: Checkout (shallow clone from this Gitea — no gitea.com) - # - name: Write deploy.registry.env and validate secrets path - # - name: Log in to container registry (for pull) - # - name: Pull and start stack + - name: Image tag and registry prefix + id: meta + run: | + $ErrorActionPreference = 'Stop' + $short = (git rev-parse --short HEAD).Trim() + $utf8 = New-Object System.Text.UTF8Encoding $false + [System.IO.File]::AppendAllText($env:GITHUB_OUTPUT, "image_tag=$short`n", $utf8) + $prefix = "${{ vars.REGISTRY_HOST }}/${{ vars.REGISTRY_OWNER }}" + [System.IO.File]::AppendAllText($env:GITHUB_ENV, "REGISTRY_PREFIX=$prefix`n", $utf8) + - name: Log in to container registry + run: | + $ErrorActionPreference = 'Stop' + $pass = @' + ${{ secrets.REGISTRY_PASSWORD }} + '@ + $pass.Trim() | docker login "${{ vars.REGISTRY_HOST }}" -u "${{ secrets.REGISTRY_USERNAME }}" --password-stdin + - name: Build and push backend + run: | + $ErrorActionPreference = 'Stop' + $tag = "${{ steps.meta.outputs.image_tag }}" + docker build ` + -t "$env:REGISTRY_PREFIX/dyolink-backend:$tag" ` + -t "$env:REGISTRY_PREFIX/dyolink-backend:latest" ` + ./backend + docker push "$env:REGISTRY_PREFIX/dyolink-backend:$tag" + docker push "$env:REGISTRY_PREFIX/dyolink-backend:latest" - ####SAMPLE - # name: Registry — build, push, deploy + - name: Build and push frontend + env: + PUBLIC_BASE_URL: ${{ vars.PUBLIC_BASE_URL }} + run: | + $ErrorActionPreference = 'Stop' + $tag = "${{ steps.meta.outputs.image_tag }}" + $base = $env:PUBLIC_BASE_URL + docker build ` + --build-arg "NEXT_PUBLIC_API_URL=$base/api" ` + --build-arg "NEXT_PUBLIC_APP_URL=$base" ` + --build-arg "NEXT_PUBLIC_APP_NAME=Dyolink" ` + -t "$env:REGISTRY_PREFIX/dyolink-frontend:$tag" ` + -t "$env:REGISTRY_PREFIX/dyolink-frontend:latest" ` + ./frontend + docker push "$env:REGISTRY_PREFIX/dyolink-frontend:$tag" + docker push "$env:REGISTRY_PREFIX/dyolink-frontend:latest" - # on: - # push: - # branches: [main, master] - # workflow_dispatch: + deploy: + needs: build-and-push + runs-on: self-hosted + steps: + - name: Checkout (shallow clone from this Gitea — no gitea.com) + run: | + $ErrorActionPreference = 'Stop' + $cloneHost = '${{ vars.CLONE_HOST }}'.Trim() + if ([string]::IsNullOrWhiteSpace($cloneHost)) { + $Server = "${{ github.server_url }}".TrimEnd('/') + } elseif ($cloneHost -match '^https?://') { + $Server = $cloneHost.TrimEnd('/') + } else { + $Server = 'http://' + $cloneHost + } + $Repo = "${{ github.repository }}" + $Branch = "${{ github.ref_name }}" + $Token = "${{ github.token }}" + $Actor = "${{ github.actor }}" + $hp = $Server -replace '^https?://', '' + if ($Server.StartsWith('https')) { + $cloneUrl = 'https://' + $Actor + ':' + $Token + '@' + $hp + '/' + $Repo + '.git' + } else { + $cloneUrl = 'http://' + $Actor + ':' + $Token + '@' + $hp + '/' + $Repo + '.git' + } + $env:GIT_TERMINAL_PROMPT = '0' + git clone --depth 1 --branch $Branch $cloneUrl . - # defaults: - # run: - # shell: powershell + - name: Write deploy.registry.env and validate secrets path + run: | + $ErrorActionPreference = 'Stop' + $SD = '${{ vars.DEPLOY_SECRETS_DIR }}'.Trim() + if ([string]::IsNullOrWhiteSpace($SD)) { + Write-Host "Set repository variable DEPLOY_SECRETS_DIR to the absolute path on this runner" + Write-Host "where database.staging.env and backend.staging.env live (not in git)." + exit 1 + } + if (-not (Test-Path (Join-Path $SD "database.staging.env"))) { + Write-Host "Missing $(Join-Path $SD 'database.staging.env')" + exit 1 + } + if (-not (Test-Path (Join-Path $SD "backend.staging.env"))) { + Write-Host "Missing $(Join-Path $SD 'backend.staging.env')" + exit 1 + } + $stagingPort = '${{ vars.STAGING_HTTP_PORT }}'.Trim() + if ([string]::IsNullOrWhiteSpace($stagingPort)) { $stagingPort = '8088' } + $imageTag = "${{ needs.build-and-push.outputs.image_tag }}" + $lines = @( + "REGISTRY_PREFIX=${{ vars.REGISTRY_HOST }}/${{ vars.REGISTRY_OWNER }}", + "IMAGE_TAG=$imageTag", + "STAGING_HTTP_PORT=$stagingPort", + "DEPLOY_SECRETS_DIR=$SD" + ) + Set-Location infrastructure + $lines | Set-Content -Path deploy.registry.env -Encoding utf8 - # jobs: - # build-and-push: - # runs-on: self-hosted - # outputs: - # image_tag: ${{ steps.meta.outputs.image_tag }} - # steps: - # - name: Checkout (clone from this Gitea — no gitea.com) - # run: | - # $ErrorActionPreference = 'Stop' - # $Server = "${{ github.server_url }}".TrimEnd('/') - # $Repo = "${{ github.repository }}" - # $Branch = "${{ github.ref_name }}" - # $Token = "${{ github.token }}" - # $Actor = "${{ github.actor }}" - # $hp = $Server -replace '^https?://', '' - # if ($Server.StartsWith('https')) { - # $cloneUrl = 'https://' + $Actor + ':' + $Token + '@' + $hp + '/' + $Repo + '.git' - # } else { - # $cloneUrl = 'http://' + $Actor + ':' + $Token + '@' + $hp + '/' + $Repo + '.git' - # } - # $env:GIT_TERMINAL_PROMPT = '0' - # git clone --depth 1 --branch $Branch $cloneUrl . - - # - name: Image tag and registry prefix - # id: meta - # run: | - # $ErrorActionPreference = 'Stop' - # $short = (git rev-parse --short HEAD).Trim() - # $utf8 = New-Object System.Text.UTF8Encoding $false - # [System.IO.File]::AppendAllText($env:GITHUB_OUTPUT, "image_tag=$short`n", $utf8) - # $prefix = "${{ vars.REGISTRY_HOST }}/${{ vars.REGISTRY_OWNER }}" - # [System.IO.File]::AppendAllText($env:GITHUB_ENV, "REGISTRY_PREFIX=$prefix`n", $utf8) - - # - name: Log in to container registry - # run: | - # $ErrorActionPreference = 'Stop' - # $pass = @' - # ${{ secrets.REGISTRY_PASSWORD }} - # '@ - # $pass.Trim() | docker login "${{ vars.REGISTRY_HOST }}" -u "${{ secrets.REGISTRY_USERNAME }}" --password-stdin - - # - name: Build and push backend - # run: | - # $ErrorActionPreference = 'Stop' - # $tag = "${{ steps.meta.outputs.image_tag }}" - # docker build ` - # -t "$env:REGISTRY_PREFIX/dyolink-backend:$tag" ` - # -t "$env:REGISTRY_PREFIX/dyolink-backend:latest" ` - # ./backend - # docker push "$env:REGISTRY_PREFIX/dyolink-backend:$tag" - # docker push "$env:REGISTRY_PREFIX/dyolink-backend:latest" - - # - name: Build and push frontend - # env: - # PUBLIC_BASE_URL: ${{ vars.PUBLIC_BASE_URL }} - # run: | - # $ErrorActionPreference = 'Stop' - # $tag = "${{ steps.meta.outputs.image_tag }}" - # $base = $env:PUBLIC_BASE_URL - # docker build ` - # --build-arg "NEXT_PUBLIC_API_URL=$base/api" ` - # --build-arg "NEXT_PUBLIC_APP_URL=$base" ` - # --build-arg "NEXT_PUBLIC_APP_NAME=Dyolink" ` - # -t "$env:REGISTRY_PREFIX/dyolink-frontend:$tag" ` - # -t "$env:REGISTRY_PREFIX/dyolink-frontend:latest" ` - # ./frontend - # docker push "$env:REGISTRY_PREFIX/dyolink-frontend:$tag" - # docker push "$env:REGISTRY_PREFIX/dyolink-frontend:latest" - - # deploy: - # needs: build-and-push - # runs-on: self-hosted - # steps: - # - name: Checkout (shallow clone from this Gitea — no gitea.com) - # run: | - # $ErrorActionPreference = 'Stop' - # $Server = "${{ github.server_url }}".TrimEnd('/') - # $Repo = "${{ github.repository }}" - # $Branch = "${{ github.ref_name }}" - # $Token = "${{ github.token }}" - # $Actor = "${{ github.actor }}" - # $hp = $Server -replace '^https?://', '' - # if ($Server.StartsWith('https')) { - # $cloneUrl = 'https://' + $Actor + ':' + $Token + '@' + $hp + '/' + $Repo + '.git' - # } else { - # $cloneUrl = 'http://' + $Actor + ':' + $Token + '@' + $hp + '/' + $Repo + '.git' - # } - # $env:GIT_TERMINAL_PROMPT = '0' - # git clone --depth 1 --branch $Branch $cloneUrl . - - # - name: Write deploy.registry.env and validate secrets path - # run: | - # $ErrorActionPreference = 'Stop' - # $SD = '${{ vars.DEPLOY_SECRETS_DIR }}'.Trim() - # if ([string]::IsNullOrWhiteSpace($SD)) { - # Write-Host "Set repository variable DEPLOY_SECRETS_DIR to the absolute path on this runner" - # Write-Host "where database.staging.env and backend.staging.env live (not in git)." - # exit 1 - # } - # if (-not (Test-Path (Join-Path $SD "database.staging.env"))) { - # Write-Host "Missing $(Join-Path $SD 'database.staging.env')" - # exit 1 - # } - # if (-not (Test-Path (Join-Path $SD "backend.staging.env"))) { - # Write-Host "Missing $(Join-Path $SD 'backend.staging.env')" - # exit 1 - # } - # $stagingPort = '${{ vars.STAGING_HTTP_PORT }}'.Trim() - # if ([string]::IsNullOrWhiteSpace($stagingPort)) { $stagingPort = '8088' } - # $imageTag = "${{ needs.build-and-push.outputs.image_tag }}" - # $lines = @( - # "REGISTRY_PREFIX=${{ vars.REGISTRY_HOST }}/${{ vars.REGISTRY_OWNER }}", - # "IMAGE_TAG=$imageTag", - # "STAGING_HTTP_PORT=$stagingPort", - # "DEPLOY_SECRETS_DIR=$SD" - # ) - # Set-Location infrastructure - # $lines | Set-Content -Path deploy.registry.env -Encoding utf8 - - # - name: Log in to container registry (for pull) - # run: | - # $ErrorActionPreference = 'Stop' - # $pass = @' - # ${{ secrets.REGISTRY_PASSWORD }} - # '@ - # $pass.Trim() | docker login "${{ vars.REGISTRY_HOST }}" -u "${{ secrets.REGISTRY_USERNAME }}" --password-stdin - - # - name: Pull and start stack - # run: | - # $ErrorActionPreference = 'Stop' - # Set-Location infrastructure - # docker compose -f docker-compose.registry.yml --env-file deploy.registry.env pull backend frontend - # docker compose -f docker-compose.registry.yml --env-file deploy.registry.env up -d + - name: Log in to container registry (for pull) + run: | + $ErrorActionPreference = 'Stop' + $pass = @' + ${{ secrets.REGISTRY_PASSWORD }} + '@ + $pass.Trim() | docker login "${{ vars.REGISTRY_HOST }}" -u "${{ secrets.REGISTRY_USERNAME }}" --password-stdin + - name: Pull and start stack + run: | + $ErrorActionPreference = 'Stop' + Set-Location infrastructure + docker compose -f docker-compose.registry.yml --env-file deploy.registry.env pull backend frontend + docker compose -f docker-compose.registry.yml --env-file deploy.registry.env up -d diff --git a/AGENTS.md b/AGENTS.md index 8416eaa..89aa04a 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -10,7 +10,7 @@ Dental clinic ↔ lab platform (monorepo): |------|--------| | `backend/` | NestJS, Prisma, PostgreSQL | | `frontend/` | Next.js 16, React 19, next-intl, Tailwind | -| `infrastructure/` | Docker, nginx, deploy scripts | +| `infrastructure/` | Docker, nginx, deploy scripts — prod: `DEPLOY.md`, staging: `STAGING-DEPLOY.md` | **Organization types:** `CLINIC` (patients, appointments, treatment) and `LAB` (cases, tasks). Many features are org-type-specific. Permissions use `TAB_*_READ` / `TAB_*_EDIT` codes — see `backend/src/common/permissions.ts`. diff --git a/README.md b/README.md index a412280..2302c2f 100644 --- a/README.md +++ b/README.md @@ -42,103 +42,13 @@ SSL is issued automatically via **Certbot** (`scripts/init-letsencrypt.sh`). Ngi --- -## Deploy on your own server (Docker + Gitea) +## Staging deploy (Gitea Actions + Windows) -High level: **build container images → push to a registry → server pulls images and runs Compose**. Optionally **Gitea Actions** automates that on every merge to `main` / `master`. +**Full guide:** [`infrastructure/STAGING-DEPLOY.md`](infrastructure/STAGING-DEPLOY.md) -### 1. One-time server preparation +Merge or push to **`master`** → Gitea Actions builds images → deploys to `http://:8088`. -1. Install **Docker** and **Docker Compose** on the server. -2. Run **Gitea** with the **container registry** enabled (same host/port you use for `docker login`, e.g. `178.131.50.201:3000`). -3. Copy the repo (or deploy only `infrastructure/` + secrets). You need at least: - - - `infrastructure/docker-compose.registry.yml` - - `infrastructure/nginx/` configs referenced by that compose file - - `infrastructure/database/init.sql` if used by your Postgres service - -4. **Secrets on the server** (never commit real values): - - - Copy `infrastructure/database.staging.env.example` → **`database.staging.env`** (Postgres user/password/db). - - Copy `infrastructure/backend.staging.env.example` → **`backend.staging.env`** (e.g. `DATABASE_URL`, JWT, pointing at the compose Postgres service name). - - Put both files in one directory on the server, e.g. `/opt/dyolink/secrets/`. - -5. **Registry login from the server** (same credentials you use for `docker push`): - - ```bash - docker login : -u - ``` - - For HTTP registries, Docker may require **`insecure-registries`** on the daemon. - -### 2. Manual deploy (build images elsewhere, run on server) - -On your **dev machine** (after successful local builds): - -```powershell -$REG = ":" -$OWN = "" -$TAG = "manual" - -docker build -t "${REG}/${OWN}/dyolink-backend:${TAG}" -t "${REG}/${OWN}/dyolink-backend:latest" ./backend - -docker build ` - --build-arg NEXT_PUBLIC_API_URL="http://:/api" ` - --build-arg NEXT_PUBLIC_APP_URL="http://:" ` - --build-arg NEXT_PUBLIC_APP_NAME="Dyolink" ` - -t "${REG}/${OWN}/dyolink-frontend:${TAG}" ` - -t "${REG}/${OWN}/dyolink-frontend:latest" ` - ./frontend - -docker push "${REG}/${OWN}/dyolink-backend:${TAG}" -docker push "${REG}/${OWN}/dyolink-backend:latest" -docker push "${REG}/${OWN}/dyolink-frontend:${TAG}" -docker push "${REG}/${OWN}/dyolink-frontend:latest" -``` - -On the **server**, from `infrastructure/`: - -1. Create **`deploy.registry.env`** (see `infrastructure/deploy.registry.env.example`): - - - `REGISTRY_PREFIX=:/` (no `http://`, no trailing slash) - - `IMAGE_TAG=latest` or the tag you pushed - - `STAGING_HTTP_PORT=` (e.g. `8088` — browser uses `http://:8088`) - -2. Set **`DEPLOY_SECRETS_DIR`** to the absolute path of the folder containing `database.staging.env` and `backend.staging.env` (you can export it in the shell or add it to `deploy.registry.env` if your Compose setup expects it). - -3. Pull and start: - - ```bash - docker compose -f docker-compose.registry.yml --env-file deploy.registry.env pull backend frontend - docker compose -f docker-compose.registry.yml --env-file deploy.registry.env up -d - ``` - -The backend container runs **`prisma migrate deploy`** on startup (via entrypoint) when `NODE_ENV=production`, so schema updates apply after you deploy a new image that includes new migrations. - -### 3. Automatic deploy (Gitea Actions) - -Workflow file: **`.gitea/workflows/registry-build-deploy.yml`**. - -**Requirements:** - -- **Gitea Actions** enabled for the repository. -- A **self-hosted runner** (with Docker) registered to Gitea — the workflow uses `runs-on: self-hosted`. -- **Windows runners:** the workflow uses **PowerShell** (not Bash). Gitea’s runner was failing with `execvpe(/bin/bash) failed` when Bash was routed through WSL without a real `/bin/bash`. If your runner is **Linux**, switch `.gitea/workflows/registry-build-deploy.yml` to `defaults.run.shell: bash` and use Bash syntax instead. -- **Repository → Actions → Variables** (examples): - - - `REGISTRY_HOST` — e.g. `178.131.50.201:3000` - - `REGISTRY_OWNER` — image namespace (same as Docker image path after the host), e.g. `admin` - - `PUBLIC_BASE_URL` — URL users open in the browser, e.g. `http://178.131.50.201:8088` (no trailing slash) - - `DEPLOY_SECRETS_DIR` — **absolute path on the runner machine** to the folder containing `database.staging.env` and `backend.staging.env` - - Optional: `STAGING_HTTP_PORT` (defaults to `8088`) - -- **Repository → Actions → Secrets:** - - - `REGISTRY_USERNAME` - - `REGISTRY_PASSWORD` — access token with package read/write (or equivalent) - -**Trigger:** push to **`main`** or **`master`**, or run the workflow manually (**workflow_dispatch**). - -The pipeline clones from your Gitea instance, builds and pushes backend/frontend images, then on the runner runs **`docker compose pull`** and **`up -d`** using `infrastructure/docker-compose.registry.yml`. +Workflow: [`.gitea/workflows/registry-build-deploy.yml`](.gitea/workflows/registry-build-deploy.yml) --- @@ -148,5 +58,6 @@ The pipeline clones from your Gitea instance, builds and pushes backend/frontend |------|------| | `backend/Dockerfile` | API image | | `frontend/Dockerfile` | Web image | +| `infrastructure/STAGING-DEPLOY.md` | Staging setup, CI variables, testing | | `infrastructure/docker-compose.registry.yml` | Pull-only staging stack (registry images + nginx + postgres) | | `infrastructure/deploy.registry.env.example` | Template for `deploy.registry.env` | diff --git a/infrastructure/deploy.registry.env.example b/infrastructure/deploy.registry.env.example index 4e8eb3b..87f1add 100644 --- a/infrastructure/deploy.registry.env.example +++ b/infrastructure/deploy.registry.env.example @@ -15,5 +15,8 @@ IMAGE_TAG=latest STAGING_HTTP_PORT=8088 # Absolute path on the server where database.staging.env and backend.staging.env live. -# Use forward slashes on Windows. Same variable as Gitea Actions → DEPLOY_SECRETS_DIR. -# DEPLOY_SECRETS_DIR=D:/dyolink/secrets +# Use forward slashes on Windows. Same path as Gitea Actions variable DEPLOY_SECRETS_DIR. +# DEPLOY_SECRETS_DIR=C:/dyolink/secrets +# +# Gitea Actions also needs CLONE_HOST=127.0.0.1:3000 when runner and Gitea share one Windows host. +# See STAGING-DEPLOY.md (do not use GITEA_* variable names — Gitea rejects them).