# Xyvenra Cloud CI deploys

Xyvenra Cloud can accept a built, self-contained HTML app or a static-site ZIP from GitHub Actions or another CI service. Cloud stores and serves the result; your CI provider runs the build. A ZIP can contain up to 10 linked HTML pages and supported local CSS, classic JavaScript, and assets. Cloud embeds them into one static site no larger than 180,000 bytes. The uploaded ZIP is capped at 4 MB and may expand to at most 8 MB. Cloud does not run your build commands; framework projects must be built first, and module-script bundles are not supported yet.

## Create a site key

1. Sign in at [Xyvenra](https://xyvenra.com/app/cloud) and select the site.
2. Under **Automated deploys**, create a key. Copy it immediately; Xyvenra stores only its SHA-256 digest and cannot show the secret again.
3. For GitHub Actions, add a repository secret named `XYVENRA_CLOUD_DEPLOY_TOKEN` containing the key. Set a repository variable named `XYVENRA_CLOUD_SITE_ID` to the site's UUID. The endpoint shown in Cloud contains that same UUID.
4. Keep the secret out of the repository, build artifacts, client-side apps, and logs. Revoke it in Cloud immediately if it is exposed.

The key can update one site only. It cannot publish or unpublish it. The current publication setting remains in force, and each successful update is captured in Cloud's existing five-version history. The API permits up to 30 accepted deployments per minute per key.

## Deploy endpoint

```http
POST https://xyvenra.com/api/cloud/v1/{site-id}
Authorization: Bearer XYVENRA_CLOUD_DEPLOY_TOKEN
Content-Type: application/zip
```

Send the raw ZIP bytes in the request body. The archive must contain `index.html` at its root or in one top-level folder.

The existing JSON form remains available for a single self-contained page:

```http
Content-Type: application/json

{"html":"<!doctype html><html>…</html>"}
```

Success returns the site address, its current publication status, the update time, and a `deploymentId`. Invalid or revoked keys return `401`, invalid or oversized uploads return `400` or `413`, and a rate-limited key returns `429` with `Retry-After`.

## Create a CI preview without changing the site

Send the same HTML JSON or static-site ZIP to `POST /api/cloud/v1/{site-id}?preview=1` with the site key. Cloud compiles and validates the upload under the same limits, then returns a seven-day preview URL. The site content and publication setting remain unchanged. The preview shares the account's limit of five active preview links; revoke one in Cloud or wait for one to expire if the endpoint returns `429`. The key's 30 requests per minute limit also applies. Preview uploads do not appear in Deployment activity.

The response includes `preview` metadata, `path`, and the full `url`. Anyone with that URL can view the snapshot until it expires or its owner revokes it. Keep CI logs and pull-request comments containing the URL limited to intended reviewers. The preview is an opaque-origin sandbox with Cloud's normal network restrictions.

Use the helper with `--preview` to print the temporary review URL without publishing or updating the site:

```sh
node scripts/xyvenra-cloud-deploy.mjs --preview ./cloud-site.zip
```

Preview uploads authenticate with the same site-scoped key. They do not run build commands in Xyvenra; your CI provider still builds the site.

The signed-in site owner can review the resulting snapshot under **Share a preview** and choose **Apply to site** after confirmation. Applying keeps the site's published/private setting and saves the replaced state in version history. A key alone cannot promote a preview; see [the preview guide](xyvenra-cloud-preview-links.md).

In Cloud, select the site and open **Deployment activity**. Refresh it to see the last 20 recorded automated uploads, including successful deploys and supported upload or compilation rejections. Match the response's `deploymentId` to the activity row. Rows show the upload format, timestamp, result, and publication status for a successful deploy. Cloud stores no request bodies, deploy keys, or CI output in this history. Authentication and rate-limit errors, unsupported content types, requests blocked upstream, and uploads Cloud cannot record are outside the history. If Cloud returns `503` because it could not confirm the deploy, check activity and site state before retrying.

## GitHub Actions example

Save `scripts/xyvenra-cloud-deploy.mjs` from this project in your repository (or copy it into your deployment tooling). Replace the build command and output path with the commands your project uses. ZIP deployment embeds compatible CSS, classic JavaScript, images, fonts, and local page links. It does not build framework source, run module scripts, or accept more than 10 HTML pages.

```yaml
name: Deploy to Xyvenra Cloud

on:
  push:
    branches: [main]

permissions:
  contents: read

jobs:
  build-and-deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
        with:
          persist-credentials: false
      - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
        with:
          node-version: 22
      - run: npm ci && npm run build
      # Package the built static site, not its framework source.
      - run: zip -r cloud-site.zip dist
      - run: node scripts/xyvenra-cloud-deploy.mjs cloud-site.zip
        env:
          XYVENRA_CLOUD_SITE_ID: ${{ vars.XYVENRA_CLOUD_SITE_ID }}
          XYVENRA_CLOUD_DEPLOY_TOKEN: ${{ secrets.XYVENRA_CLOUD_DEPLOY_TOKEN }}
```

Pin third-party actions to reviewed commit SHAs and update those pins deliberately. Restrict the production environment to the intended deployment branch and add required reviewers if repository collaborators can change the workflow. The deploy token is scoped to one Cloud site and is only available in the final step.

For a one-off deployment, set the two environment variables in a trusted terminal and run:

```sh
node scripts/xyvenra-cloud-deploy.mjs ./dist/index.html
# Or upload a built multi-page static site:
node scripts/xyvenra-cloud-deploy.mjs ./cloud-site.zip
```

The helper checks the site ID, token format, ZIP size, and (for HTML input) UTF-8 encoding and 180 KB limit before making a request. It does not print the token, ZIP, or HTML. GitHub Actions execution time and usage are provided by GitHub under the repository owner's GitHub plan; this deployment API adds no Xyvenra build worker or paid compute resource.
