Deployment and release
Workflow Server can be developed locally or deployed as a self-hosted service. Keep databases, runtime data, and documentation assets in explicit persistent directories. Desktop installers, update feeds, and built-in project resources are uploaded directly to OSS by their release pipelines.
Environmental Division
| Environment | Default usage | Recommended practice |
|---|---|---|
| Development Environment | Local debugging server, Desktop, and workspace examples | Copy a local .env from *.env.example and adjust ports as needed; Git ignores the real .env file. |
| Production environment | Provides management, API, Embed, and Webhook services | GitLab CI uses protected CI/CD Variables scoped to production; manual deployments may use an untracked .env.production on the deployment host. |
Do not commit real .env or .env.production files, database connection strings, or service credentials. Formal tag jobs read the production environment only from protected refs and validate required variable names before building. Validation failures print missing names only, never values. Committed *.env.example files contain variable structure and explicit placeholders only.
Power recovery
After a deployment-host power loss, run pnpm restore:release or pnpm restore:alpha from an authenticated GitLab CLI workspace checkout. The command only creates and runs the corresponding protected GitLab manual recovery job; it does not read, write, or generate a host .env file. Stable recovery starts Workflow PostgreSQL 15 and Sub2API, then verifies that stable metadata matches the Server version on main before rebuilding Server. Docs then rebuilds its exact published commit and switches atomically. Alpha recovery starts the same Docker services and restarts the Alpha release selected by its existing current pointer without generating a new Alpha version. OSS objects do not depend on the deployment host and require no power-loss recovery.
Recovery jobs wait for their pipeline validation job to pass; no recovery action runs when validation fails. They use only docker compose up -d --wait; they never run docker compose down -v, remove data volumes, or clean persistent release directories. A recovery job must run on a Runner configured with the protected variables for its production or alpha environment. When DOCKER_SOCKET_LOCATION is not explicitly set, the job uses the Docker daemon standard path /var/run/docker.sock; set the variable explicitly only when a different mount source is required.
If a power loss leaves a corrupted Sub2API Redis AOF tail, the recovery job first preserves an AOF backup in the same persistent volume, then uses the Redis check tool to repair a truncatable tail and retries Sub2API. Data that cannot be repaired by validation still fails the job; the recovery never clears the data volume or silently resets Redis.
The production environment should use an explicit persistent directory. It is recommended to configure at least:
| Variable | Description |
|---|---|
WORKFLOW_RELEASE_STORAGE_ROOT | Root directory for Server deployments, Docs, and persistent data. |
WORKFLOW_SERVER_DATA_DIR | Workflow Server Run Data Directory; if not set, can be derived from the publication root directory. |
WORKFLOW_DOCS_ROOT | Document static site directory. |
WORKFLOW_PUBLIC_BASE_URL | Workflow Admin public address. |
WORKFLOW_API_PUBLIC_BASE_URL | Public Workflow API HTTP(S) origin. OpenAI access details prefer this value, so production reverse proxies must configure it explicitly. |
WORKFLOW_HOOKS_PUBLIC_BASE_URL | Webhook public address. |
WORKFLOW_EMBED_PUBLIC_BASE_URL | Embed public address. |
WORKFLOW_DOCS_PUBLIC_BASE_URL | Document site address. |
WORKFLOW_DEPENDENCY_FETCH_TIMEOUT_MS | workflow relies on a single download timeout; the default is 3600000 milliseconds. Large platform packages can be adjusted to network conditions when first installed. |
WORKFLOW_DEPENDENCY_INSTALL_TIMEOUT_MS | workflow Overall dependency install timeout; default 3900000 ms. This variable can still be used to override the installation phase separately when WORKFLOW_BUILD_TIMEOUT_MS is set. |
Before starting production, make sure that these directories are writable, the backup strategy is clear, and the reverse proxy certificate covers the corresponding domain name.
When uploading workflow, the server keeps the in-package lockfile and builds the isolated runtime with the pnpm version of the repository declaration. workflow-code and @workflow-code/cli are only used for platform API and development commands, and will not enter version runtime; other business dependencies declared by the project will be converted to a portable layout without symbolic links, and the archive file type will be checked before uploading the object storage. The SDK that contains the platform binary may download a large dependency package when it is uploaded for the first time. Subsequent dependencies reuse the pnpm store and workflow runtime cache. If the installation fails, first check the returned build stderr; When a download timeout occurs, confirm the network quality, disk space, and the above two timeout variables of the server to npm registry.
Database and Storage
Workflow Server connects directly to PostgreSQL 15 without a pooler proxy. The repository's docker/postgres Compose runs only postgres:15-alpine, maps host 127.0.0.1:7125 to container port 5432, and binds production data to ${WORKFLOW_RELEASE_STORAGE_ROOT}/postgres-data. Use WORKFLOW_DATABASE_URL for the application connection and WORKFLOW_POSTGRES_PASSWORD for container initialization.
Passwords are stored with Node.js native scrypt and random salts. Browser cookie sessions last 30 days, access tokens one hour, account invitations 24 hours, and device codes 10 minutes; only SHA-256 hashes of session and invitation tokens are stored. Logout, account disablement, and password changes revoke affected browser sessions. While the account table is empty, the first login using WORKFLOW_BOOTSTRAP_ADMIN_EMAIL and WORKFLOW_BOOTSTRAP_ADMIN_PASSWORD creates the administrator and built-in roles; later logins use the current database password and disabled state. Invitations open /account/invite/:token; a new link invalidates older unused links for the same account, and the invited user sets an initial password on that page. Server does not send email.
Workflow artifacts and avatars are written to Aliyun OSS and read directly from the public WORKFLOW_STORAGE_PUBLIC_BASE_URL, without signed URLs. Writes require protected WORKFLOW_OSS_ACCESS_KEY_ID, WORKFLOW_OSS_ACCESS_KEY_SECRET, WORKFLOW_OSS_BUCKET, and WORKFLOW_OSS_REGION variables. Object keys use storage/workflows/<workflow>/<version>/<hash>/{source,runtime}.tar.gz and storage/avatars/<user-id>/<hash>.<ext>. Uploaded objects are public-read with the correct Content-Type and immutable cache headers. Bucket CORS must support public GET, HEAD, browser OPTIONS preflight, and Range, while exposing length, range, and ETag response headers.
Recommended check items:
- Database connection strings, PostgreSQL passwords, and OSS write credentials are stored only in protected server environment variables.
- Upload files, run attachments, version packages, and KV data all have explicit backup policies.
- Production database migration and data repair are performed through controlled scripts and do not manually modify tables in pages or one-time terminals.
- The read-only analysis tool uses a read-only database account and does not directly write to the workflow running table.
Server and Web management terminal
The management end is hosted statically by Workflow Server. The common deployment process is to build the server and server web first, then start the server process or container, and expose it through the HTTPS reverse proxy:
pnpm install --frozen-lockfile
pnpm build:all
The health check after startup should return to the normal state:
curl -i "$WORKFLOW_PUBLIC_BASE_URL/health"
The response's versions.serverVersion and versions.coreVersion come from immutable build info loaded and verified by the current process, so they identify the running Server and bundled Core versions. Send X-Workflow-Locale: zh-CN|en, or ?locale=zh-CN|en, to choose the language for currentRelease, deployment.*.releaseNotes, and Docs URLs. Older single-language metadata falls back to its original releaseNotes.body. currentRelease includes a summary, complete Markdown, and a version anchor only when stable metadata matches the current Server build. deployment retains the independently stable Server and Server Web versions from release storage, which helps identify a rollback or metadata that has not yet been synchronized.
Server Web displays an update summary and provides a corresponding Docs record entry when a new Server version is detected and currentRelease contains a public description. The displayed Server version is saved in the current browser; subsequent visits to the same version will not repeat the prompt.
Server Web is a separate browser entrypoint that connects only to Server APIs for project, version, run, configuration, and public Embed management. It does not host the Electron Desktop renderer or read and execute local project source in the browser.
Alpha and stable dual deployment
Repositories that maintain main, alpha, and dev explicitly declare one stable SemVer for each branch. Immediately after a stable promotion, initialize a consecutive baseline such as main 0.1.20, alpha 0.1.21, and dev 0.1.22. Every later real Alpha release increments both alpha and dev by one patch, so another release may declare main 0.1.20, alpha 0.1.22, and dev 0.1.23. The steady-state constraint is main < alpha < dev with dev = alpha + 1 patch; an unpromoted Alpha does not have to remain exactly one patch above main. Alpha CI uses the new declared version and appends the Shanghai date plus a three-digit daily sequence, such as 0.1.22-20260826001. Server and Server Web share one version in the Alpha channel. Each repository retains only the newest three usable Alpha tags, GitLab artifacts, and host artifacts.
Alpha Server and stable must use the same WORKFLOW_DATABASE_URL, WORKFLOW_OSS_ACCESS_KEY_ID, WORKFLOW_OSS_ACCESS_KEY_SECRET, WORKFLOW_OSS_BUCKET, WORKFLOW_OSS_REGION, and WORKFLOW_STORAGE_PUBLIC_BASE_URL. Accounts, projects, version records, KV data, and object storage are therefore one business dataset with no dual writes or asynchronous synchronization. Only the following runtime resources are isolated:
| Item | Stable | Alpha |
|---|---|---|
| HTTP port | 7130 | 7140 |
| Release channel | stable | alpha |
| Code and static assets | Stable release directory | deployments/server/alpha/releases/<version> |
| Current-version pointer | Stable pointer | deployments/server/alpha/current |
| PID and logs | Stable run directory | deployments/server/alpha/run |
| Local caches and runtime data | Stable data directory | server-data/alpha |
| Automatic schedule polling | Enabled | Disabled |
The Alpha process overrides these runtime values and inherits the remaining database and storage credentials from stable:
WORKFLOW_RELEASE_CHANNEL=alpha
WORKFLOW_SERVER_PORT=7140
WORKFLOW_SERVER_DATA_DIR=/srv/workflow-release/server-data/alpha
WORKFLOW_SCHEDULE_POLLING_ENABLED=false
Disabling Alpha schedule polling prevents both processes from claiming the same schedule in the shared database. Schedule queries, editing, and manual Run now remain available, while stable remains the only automatic scheduler. Database changes on Alpha relative to main must be expand-only. The pre-deployment gate rejects drops, renames, stricter non-null constraints, and other destructive DDL.
GitLab Alpha environment
Protect the alpha branch and alpha/v* tags in the Core, CLI, Shared, Server, Desktop, and workspace projects. Configure protected, masked variables for the alpha environment:
| Variable | Purpose |
|---|---|
WORKFLOW_ALPHA_SYNC_TOKEN | Push Alpha dependency and workspace snapshot commits, create or prune Alpha tags, and erase old job artifacts across projects. It needs repository write and API access to each target. |
WORKFLOW_SHARED_SYNC_TARGETS | Comma- or newline-separated Core, CLI, Server, and Desktop project paths receiving Shared snapshots. |
NPM_TOKEN | Publish the Core and CLI npm packages under the alpha dist-tag. |
WORKFLOW_RELEASE_STORAGE_ROOT | Absolute release root used by the Server Alpha deployment. |
WORKFLOW_ALPHA_PUBLIC_URL | Public Alpha Server HTTPS URL, such as https://wfalpha.yuhe.space, used for the post-release external health check. |
The alpha environment also needs the database, PostgreSQL, OSS, authentication, and runtime variables required by Server, using the same values as production. Do not scope those variables only to production, or Alpha jobs cannot read them. The cross-project token must be able to push every Alpha repository and workspace. When using CI_JOB_TOKEN, configure each target project's job-token allowlist and protected-branch write permission.
DNS and reverse proxy
Point the Alpha hostname at the same deployment edge as stable, then proxy Alpha Server separately to local port 7140. This Nginx example shows the relevant boundary; keep the existing certificate, logging, and security-header configuration:
server {
listen 443 ssl;
server_name wfalpha.yuhe.space;
location / {
proxy_pass http://127.0.0.1:7140;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
OSS serves the Desktop Alpha feed and installers, so the Server reverse proxy does not need a /desktop/alpha/ location. Run at least these checks during initial rollout and after every release:
dig +short wfalpha.yuhe.space
sudo nginx -t
curl --fail --show-error https://wfalpha.yuhe.space/health
curl --fail --show-error https://wfupdates.yuhe.space/desktop/alpha/latest-mac.yml
curl --fail --show-error https://wfupdates.yuhe.space/desktop/alpha/latest.yml
The health response's Server version must match the current Alpha version, and deployment.server.tag and deployment.serverWeb.tag must use the same alpha/v... tag. On the deployment host, also confirm that exactly one Alpha process owns port 7140, stable remains healthy on 7130, Alpha schedule polling is disabled, and every file referenced by the macOS and Windows feed metadata is downloadable.
Built-in project index.json files and compatibility manifest.json files in OSS are mutable metadata and must return Cache-Control: no-cache, no-transform, must-revalidate. Hash-verified resources below vX.Y.Z/ should return Cache-Control: public, max-age=31536000, immutable. Verify both policies after publishing:
curl -fsSI https://wfupdates.yuhe.space/builtin-projects/conversation/index.json | grep -i '^cache-control:'
curl -fsSI 'https://wfupdates.yuhe.space/builtin-projects/conversation/v0.1.4/conversation-universal.tgz' | grep -i '^cache-control:'
Optional Sub2API service
The warehouse provides a separate Sub2API Compose configuration for deploying Wei-Shaw/sub2api AI API gateways. The service does not share a database or Redis with Workflow Server, and only provides the management interface and API on the local 127.0.0.1:7134 by default:
pnpm deploy:sub2api
curl --fail --show-error http://127.0.0.1:7134/health
For manual development, copy docker/sub2api/.env.example to the ignored docker/sub2api/.env. Formal GitLab jobs inject database, Redis, administrator, JWT, and TOTP settings directly from protected CI/CD Variables in the production environment; they do not generate or commit a production env file. Rotate these keys before production deployment. For external access, keep the native port binding private and expose the service through a reverse proxy with HTTPS and access control. PostgreSQL and Redis should communicate only over the Compose private network, without exposing host ports.
When Workflow Server needs to manage Sub2API users, configure in the Server process environment:
| Variable | Description |
|---|---|
WORKFLOW_SUB2API_BASE_URL | Sub2API service URL. A process on the same host can use http://127.0.0.1:7134. |
WORKFLOW_SUB2API_ADMIN_API_KEY | The admin- prefix management key generated by Sub2API allows only Server processes to read. |
WORKFLOW_SUB2API_PROXY_SECRET | The HMAC-SHA256 signing key for the user AI proxy short credentials. If it is not configured, it will fall back to WORKFLOW_AUTH_COOKIE_SECRET and WORKFLOW_SERVER_ADMIN_KEY in turn. Separate configuration and rotation are recommended for the production environment. |
WORKFLOW_SUB2API_REQUEST_TIMEOUT_MS | Server Timeout for calling Sub2API management interface. Default value: 10000 ms. |
WORKFLOW_SUB2API_GROUP_CACHE_TTL_MS | In-process cache time of Sub2API group reading, default 60000 ms; set to 0 to disable. |
WORKFLOW_SUB2API_SUBSCRIPTION_CACHE_TTL_MS | The in-process cache time for the administrator to subscribe to paged reading, which is 10000 milliseconds by default. Set to 0 to disable. |
WORKFLOW_SUB2API_USER_STATE_CACHE_TTL_MS | The in-process cache time of user binding status, account balance, user subscription, API key and balance group usage, which is 10000 milliseconds by default; set to 0 to disable. |
WORKFLOW_SUB2API_CACHE_STALE_TTL_MS | The temporary fault pocket window after the read-only cache expires, the default is 300000 milliseconds; Set to 0 to close. Only network errors, timeouts, throttling, and 5xx will use the old values, forcing a refresh with 401/403/404 will not degrade. |
When both Server and Sub2API are running in a container, join them to the same managed Docker network and change the service address to the Compose service name and container port of Sub2API. The Admin API Key should not be put into browser configuration, workflow project environment variables, public logs, or client responses.
The short-term cache only exists within the Workflow Server process. After the cache expires, Server will first request Sub2API; When a temporary connection failure occurs, the last successful read-only result can be returned in the stale window. Recharge, refund, subscription cancellation, Key start-stop and other writes are still executed in real time, and the corresponding fresh values and stale values are cleared immediately after success; Restarting Server will also empty all caches.
User workflow is not directly connected to Sub2API. GET /api/auth/sub2api/llm-credentials only issues a one-hour proxy credential to the caller with the user identity,Core saves it in the local closure and refreshes 60 seconds earlier. Model calls can only enter the three fixed paths /api/auth/sub2api/llm-proxy/v1/messages, /v1/responses, or /v1/chat/completions of Workflow Server;Server removes client authentication, cookies, and hop-by-hop headers, and then injects the actual group Key. Normal JSON and SSE are forwarded by stream. When the client is disconnected, the upstream request is canceled, and the upper limit of the request body is 50 MiB.
The Server resolver/run child process does not use the one-hour user token, but instead obtains a wfrt_ capability that is only valid for the duration of the child's survival. Only the account session or the actor corresponding to the account API key can obtain the capability. Anonymous Embed, Webhook and administrator keys without user identity do not have this ability. The capability is immediately revoked when the child process exits.
The above bounded cache is only stored in the current Server process and does not copy Sub2API subscription, balance, quota, usage, binding status, API Key, or grouping details to the Workflow Server database. Concurrent reads of the same cache key will be merged into one upstream request. Explicit binding verification, order payment, group activation and refund still directly read Sub2API, binding, unbinding, recharging, allocation, renewal, revocation and key writing will immediately invalidate the relevant cache. The complete group Key used by the agent also only enters the bounded short cache, and the Sub2API gateway still performs the final Key state check. When multiple instances are deployed, each instance maintains a cache independently. Therefore, the cache is only used to reduce read latency and cannot be used as a source of business status.
To run when the service is stopped but data is retained:
pnpm deploy:sub2api:down
Applications, databases, and Redis use Docker named volumes for persistence. Database and application data backups should be completed before upgrading SUB2API_IMAGE or cleaning up named volumes.
Native Release with Optional Remote Mode
Run the following command from the root directory of the warehouse to update the production working copy and complete the build, restart, and native health check of the specified service:
pnpm release:server
pnpm release:server-web
pnpm release:database
pnpm release:doc
Current production-pipeline Server, Server Web, and Docs jobs run on the same deployment host as their target service with WORKFLOW_SERVER_RELEASE_LOCAL=true. Local mode runs the same transaction script against the production working copy and the candidate checkout's local Git address. It neither resolves SSH credentials nor calls ssh or scp. The tag pipeline still supplies the protected tag and commit. Before building, verify the tag target and check out that commit with detached HEAD so the release cannot read a branch that advances during deployment.
You can also set WORKFLOW_SERVER_RELEASE_LOCAL=true when the deployment host is running manually. When you need to operate from other Windows, macOS, or Linux devices, omit this variable and configure compatible remote modes using WORKFLOW_SERVER_RELEASE_HOST, WORKFLOW_SERVER_RELEASE_PORT, WORKFLOW_SERVER_RELEASE_USER, WORKFLOW_SERVER_RELEASE_REMOTE_ROOT, WORKFLOW_SERVER_RELEASE_REMOTE_REPO, WORKFLOW_SERVER_RELEASE_BRANCH, and WORKFLOW_SERVER_RELEASE_SSH_KEY. Normal execution will continuously output Git, installation, build, and health check progress. Append -- --dry-run only outputs desensitization configuration and scripts to be executed. Both modes only update the Git tracking file and do not clean up the untracked configuration in the production working copy.
Server and Server Web releases use the repository's fixed Node.js version and the exact pnpm version in packageManager. For a paired promotion, finish server/vX.Y.Z first, then create server-web/vX.Y.Z on the same commit. The latter tag pipeline verifies both tag targets before atomically activating the combined Server and Server Web deployment. It builds the new release while the old service remains available, then verifies the local process, both stable metadata records, and the public health endpoint. If build, startup, health, or metadata publication fails, the pipeline restores the previous pointer, metadata, and process. The same version can therefore retry the failed job without a version-only bump.
release:doc regenerates publication overviews, downloads, compatibility relationships, and full update records from persistent release metadata before generating an immutable Docs source that uses a public API address. The new source will start on the independent precheck port and wait for the home page to return to HTTP 200. at this time, the old site will continue to provide services. The official port will not be switched until the precheck is successful. When the official switch or the deployment record write fails, the release command will restore the old site from the source in the previous deployment record. The deployment record is replaced by a temporary file atom and contains commit, branch, tag, source, and deployment time for subsequent release and failure recovery.
Branching and automatic publishing
The repository uses dev for daily integration, alpha for automatic test releases, and main only for Alpha-validated stable releases. Record ordinary feature changes in Dev's localized CHANGELOG.next* files. Before a new Alpha, manually archive each channel's non-empty next notes under that channel's old declared version, then reset the next files to only # Unreleased. Increment both the Alpha and Dev declarations by one patch and skip CI for these preparation commits. Do not use the formal release:prepare command for this rollover because it also prepares stable dependencies and other formal release state.
After version and changelog preparation, merge Dev content into Alpha while preserving the target Alpha version. Resolve changelog conflicts by retaining both the old Alpha and old Dev history entries and keeping the merged next files empty. The newly declared version's next files then contain only changes made after the reservation, rather than repeating the preceding release. Alpha CI appends the dated suffix only in temporary build directories. Desktop release notes for X.Y.Z-YYYYMMDDNNN come from the archived X.Y.Z history entry, not from the empty next files.
To promote an Alpha, create a stable candidate from the exact validated Alpha commit, run release:prepare, replace dated dependencies with stable dependencies, and merge that candidate directly to main; do not route release bookkeeping through dev or trigger another Alpha. Formal preparation archives the candidate's localized notes and resets both next changelogs. After stable publication succeeds, initialize only the branch baselines so alpha = main + 1 patch and dev = alpha + 1 patch, and skip CI for those version-only commits to avoid publishing an empty Alpha. Any failure must restore every affected file.
The GitLab project requires the following protection settings:
- Set
devas the default development branch and disallow direct deletion. - Protect
alpha, allowing updates only throughdev -> alphamerge requests or dependency propagation by the release account. - Set
mainas a protected branch and only allow entry through approved and validated release MRs. - Protect
alpha/v*tags, allowing only the Alpha release account to create them and prune them under the three-version retention policy. - Protect
workflow-code/v*,workflow-code-cli/v*,server/v*,server-web/v*, anddesktop/v*tags respectively; The protection rule covers both the commit fixed candidate tag and the final official tag, and only allows the creation of publishing accounts. - Configure a protected and masked
RELEASE_GITLAB_TOKENCI variable. This token only grants the API permissions for the current project to create tags, read pipeline, and retry pipeline. It is not used for npm, server SSH, or Desktop signatures. - Register the protected runner for the native Windows build machine and configure the
windowstag. If the GitLab instance also hosts other projects, we recommend that you use a project-level runner to limit the scope of use. The runner needs to provide a Node of Git, Windows PowerShell, and a bootable build script; the actual Desktop build still switches to the repository-pinned Node/pnpm toolchain.
main The pipeline first analyzes the impact of this combined path, and then generates a release plan in increments of the package version relative to the stable metadata and the official tag. If the component code changes but the version is not upgraded, the history log lacks the corresponding version, the next log still has unconsumed entries, the CLI peer range does not contain the current Core, or the official tag with the same name points to another commit, the pipeline will fail before the release. The path is only responsible for discovering the affected component, and the official release is always triggered by the version that has been prepared.
When multiple units are involved in the same issue, the pipeline creates only one protected candidate tag at a time, in the order Core, CLI, Server, Server Web, Desktop. The candidate name contains the target version and commit. The build/release, Docs deployment, and official tag finalize use independent tasks that rely on serial. When they fail, only the failed task and its downstream tasks are retried. When the metadata has not been written, the original product version can be retained even if the code needs to be fixed, and a new commit will generate a new candidate. metadata the written version has been bound to the original commit, the pipeline will only retry Docs or finalize and will not generate a new version again. When all is complete, advance the next release unit and synchronize the main fast-forward back to dev.
The Desktop candidate builds Windows x64 and macOS installers on the windows and macmini runners. Both platform jobs upload immutable, versioned OSS objects with size and SHA-256 metadata in parallel and pass only small manifests to the final job. The final job verifies the version and full commit, creates fixed download names through OSS server-side copies, and switches latest*.yml last. Missing or inconsistent platform artifacts fail the release immediately.
Core and CLI npm releases are successful only if the public registry reads back the same SHA-512 integrity as the local tarball. When the client times out or returns a conflict, the pipeline will still perform the same read back first, so the same packet received by the registry can be recovered idempotent. If the content of the same version is different, it will be rejected directly. The version, stable, and aggregate index metadata of all units are stored in the same storage volume before backup switching. If any switching fails, the old files will be restored, and the old candidate cannot be reversed to a lower version.
Docs does not maintain product versions. Only when the docs/** or Docs generator changes and there are no components to be released, the main pipeline will directly deploy Docs and fix the commit of the checkout trigger pipeline. After the deployment is successful, the deployment record will save the commit, branch, tag, source and time. The component release is still metadata and Docs is regenerated and deployed after the successful deployment.
Download and Update Services
Desktop and all five built-in projects publish into a public-read, credential-write OSS bucket. wfdownload.yuhe.space serves manual installers, while wfupdates.yuhe.space serves update feeds and built-in indexes. Both domains may point to the same bucket; neither routes through Server, macmini Nginx, or a local cache directory.
Configure protected, masked WORKFLOW_OSS_ACCESS_KEY_ID and WORKFLOW_OSS_ACCESS_KEY_SECRET variables in the GitLab production environment for Desktop and each built-in project. Desktop also needs them in alpha. CI declares the bucket, region, and public domains through WORKFLOW_OSS_BUCKET, WORKFLOW_OSS_REGION, WORKFLOW_OSS_DOWNLOAD_BASE_URL, and WORKFLOW_OSS_UPDATES_BASE_URL; project variables may override these values. Limit the write key to object access on the target bucket, and never include it in the repository, installers, or runtime configuration.
Versioned installers and resources are immutable and long-lived. Mutable latest*.yml, release.json, manifest.json, and index.json objects require revalidation and are switched only after every resource passes validation. After publishing, verify public HEAD responses, Range downloads, object sizes, and SHA-256 metadata.
macOS automatic updates require that Desktop be in a writable /Applications or ~/Applications and that subsequent versions maintain a consistent code signing identity. Windows x64 automatic update reads latest.yml, NSIS installation program and corresponding blockmap; before enabling, confirm that the installed Desktop can complete the inspection, download and restart the installation. Manual override of the installation path is reserved when restricted by system policy.
Document Site
Before the document is published, the default server address in the source OpenAPI is replaced with the public API address. This way, local development can still use the local address, and the API Playground after the release of the default request your production API.
Recommended check after release:
- Document site home page and navigation page can be opened normally.
- The OpenAPI Playground requests your public API domain name by default.
- Desktop download, Server Web, and API links point to the same deployment environment.