diff --git a/configure/secrets.mdx b/configure/secrets.mdx index 32cf7f1..e5f9d80 100644 --- a/configure/secrets.mdx +++ b/configure/secrets.mdx @@ -14,7 +14,19 @@ secrets: from: LOCAL_APP_TOKEN ``` -A missing required value fails deployment before release submission. Use `optional: true` only if the application handles an absent value. Resolved secrets override matching `env` entries. Never paste actual credentials into documentation, command history, or source control. +`name` is the variable the app sees. `from` names where its value comes from; without it, the value comes from `name`. A missing required value fails deployment before release submission. Use `optional: true` only if the application handles an absent value: an optional secret without a value is left out. Resolved secrets override matching `env` entries. Never paste actual credentials into documentation, command history, or source control. + +## Where values come from + +The same declaration resolves in different places, depending on what deploys the app: + +| Deployed by | Where `secrets` values come from | +| --- | --- | +| `rig deploy` on your machine | Your environment and `.env` files, in [this precedence](/configure/environment#load-local-values-for-deployment) | +| A GitHub connection (pushes) | The connection's [runtime secrets](/guides/github#runtime-secrets), stored encrypted in Rigbox. Your `.env` files are never read. | +| A GitHub Actions workflow | The deploy step's `env`; see [GitHub Actions](/guides/github-actions#application-environment-values) | + +Each app is deployed by one of these at a time; see [release ownership](/deploy/release-ownership). ## Generate an application credential @@ -33,6 +45,6 @@ Without `envVar`, the injected name is `CRED_ADMIN_TOKEN`. Incremental deploymen Run `rig deploy --workspace my-project` locally. Confirm the app accepts its credential through its normal authenticated flow. Do not print the value to prove injection succeeded. -The `secrets` declaration prevents storing a value in `rig.yaml`; it does not make app environment metadata an encrypted vault. Authorized environment/API readers can access stored values. Rotate a disclosed credential and redeploy, then revoke the old value at its provider if applicable. +If a GitHub connection deploys the workspace's apps, `rig deploy` does not deploy them. It stores the values it resolved in the connection's runtime secrets, for the names rig.yaml on the connected branch declares, reports which names it stored, and exits with an error saying that pushes deploy the apps. Push to the connected branch to deploy with the stored values. `rig ci status` lists which of each connection's declared secrets have a value. -For Actions, map a GitHub repository secret into the deployment step's `env`; see [GitHub Actions](/guides/github-actions#application-environment-values). +The `secrets` declaration prevents storing a value in `rig.yaml`; it does not make app environment metadata an encrypted vault. Authorized environment/API readers can access stored values. Rotate a disclosed credential and redeploy, then revoke the old value at its provider if applicable. diff --git a/deploy/multi-app.mdx b/deploy/multi-app.mdx index 03ecd1a..3df56bb 100644 --- a/deploy/multi-app.mdx +++ b/deploy/multi-app.mdx @@ -47,7 +47,7 @@ Check every app's health and the frontend's connection to the API. A successful ## Ownership and changes -A full incremental deploy replaces the managed application set within its deployment scope. Removing a managed app from that project's manifest can remove it from the active set. An unrelated project's apps are not part of that set. Existing unmanaged apps or apps owned by another scope cannot be silently adopted: resolve the name/port conflict or deploy to a new workspace. +A full incremental deploy replaces the managed application set within its deployment scope. Removing a managed app from that project's manifest can remove it from the active set. An unrelated project's apps are not part of that set. Existing unmanaged apps or apps owned by another scope cannot be silently adopted: resolve the name/port conflict or deploy to a new workspace. See [release ownership](/deploy/release-ownership) for which deployment can take over an app. Preserve `.rig.lock` for local project identity. Git projects derive identity from repository and project path when no scope is stored. Use [deploy one app](/deploy/single-app) for a partial update; do not delete other entries merely to skip them. diff --git a/deploy/release-ownership.mdx b/deploy/release-ownership.mdx new file mode 100644 index 0000000..b278f06 --- /dev/null +++ b/deploy/release-ownership.mdx @@ -0,0 +1,50 @@ +--- +title: "Release ownership" +description: "Which deployment owns an app, why another deployment is refused, and how an app moves between rig deploy and a GitHub connection." +--- + +Every app deployed as an incremental app release belongs to one deployment: the one whose releases it runs. Only that deployment can release it again. Ownership is per app, so several deployments can share a workspace as long as they deploy different apps. + +## Who can own an app + +| Owner | Deploys through | +| --- | --- | +| A local project | `rig deploy` from the project directory. The project's identity is stored in `.rig.lock`; a Git checkout derives it from the repository and the manifest's path, so another clone of the same repository is the same project. | +| A GitHub connection | Pushes to the connected branch, set up in the console. See [Deploy from GitHub](/guides/github). | +| A GitHub Actions binding | The repository's workflow, linked with `rig ci link`. See [GitHub Actions](/guides/github-actions). | + +## Who can take an app over + +| The app belongs to | Who can deploy it | +| --- | --- | +| A local project | That project. Connecting the app's repository in the console, or linking it for Actions, takes it over on the first deployment. Another local project cannot. | +| A GitHub connection or Actions binding that still exists | Only that connection or binding. | +| A GitHub connection or binding that was disconnected or unlinked | Whichever deployment releases it next. | +| No release yet, from an image-strategy or catalog `rig deploy` | A GitHub connection or Actions binding, on its first deployment. | +| Nothing: created another way, such as in the console | No deployment. Deploy under a different app name, or to another workspace. | + +Taking an app over keeps its identity: the app ID, URL, volumes, and data stay. The previous owner's retained releases can no longer be activated for that app; [roll back](/deploy/app-rollback) through the new owner instead. + +## When a deployment is refused + +A release that would take over an app it may not is refused before anything changes. When a GitHub connection or binding owns the app, the error names it: + +```text +App web is deployed by pushes to owner/repo@main through a GitHub connection, so only that connection can deploy it. Push to main to deploy it, or disconnect the repository in the workspace's GitHub deployment settings to deploy it another way. +``` + +Any other owner gives `App web belongs to another active deployment`: another local project, or an app no deployment can take over. Deploy under a different name or to another workspace, and keep `.rig.lock` so your project keeps its identity. + +When `rig deploy` from your machine is refused because a GitHub connection deploys the apps, it deploys nothing and exits with a `conflict` error. First it stores the values it resolved for the manifest's `secrets` - from your environment and `.env` files - in the connection's [runtime secrets](/guides/github#runtime-secrets), for the names that rig.yaml on the connected branch declares, and lists the names it stored. The next push deploys with them. + +## Move apps to a GitHub connection + +1. Connect the repository to the workspace in the console and choose incremental deployment. In the review, enter the manifest's secrets under **Runtime secrets**: a push never reads your `.env` files. See [Deploy from GitHub](/guides/github#runtime-secrets). +2. Save the configuration. Its first deployment takes over the apps with the same names. +3. Run `rig ci status --repo OWNER/REPO` and check that every declared secret shows `set`. + +If that first deployment fails because a required secret has no value, the apps still belong to your local project and `rig deploy` still deploys them. Open the connection's configuration, add the value under **Runtime secrets**, and save again; saving redeploys the branch head. Once the connection owns the apps, `rig deploy` from the project directory updates its runtime secrets from your `.env` files instead of deploying. + +## Move apps back to rig deploy + +Disconnect the repository in the workspace's GitHub deployment settings, or run `rig ci unlink --repo OWNER/REPO --workspace WORKSPACE` for a GitHub Actions binding. The next `rig deploy` from the project directory takes the apps back, and reads `secrets` from your environment and `.env` files again. Rigbox keeps the disconnected connection's runtime secrets for that workspace and repository, so reconnecting restores them. diff --git a/docs.json b/docs.json index f4ec690..def567c 100644 --- a/docs.json +++ b/docs.json @@ -52,6 +52,7 @@ "deploy/development-loop", "deploy/stage-and-activate", "deploy/app-rollback", + "deploy/release-ownership", { "group": "Reproducible builds", "pages": [ diff --git a/guides/github.mdx b/guides/github.mdx index a3aa333..49c9f9f 100644 --- a/guides/github.mdx +++ b/guides/github.mdx @@ -24,13 +24,47 @@ Choose how you want GitHub to trigger a deployment: 3. Create a workspace and select its GitHub repository, or open an existing workspace's **GitHub deployments** settings. 4. Select the correct GitHub account and repository. Review the branch, project subdirectory, manifest, and deployment strategy. New connections default to incremental; existing connections retain their reviewed choice. 5. If the repository has a `rig.yaml`, review the imported app settings. Otherwise, enter the app name, port, install/build/start commands, and memory settings, then review the generated YAML. -6. Choose automatic GitHub App deployments and save the configuration directly or through a pull request. Protected branches require a pull request. -7. Follow build and deployment progress in the workspace. Open the resulting app URL after the deployment succeeds. +6. Choose automatic GitHub App deployments. If the manifest declares `secrets`, enter their values under **Runtime secrets**; see [Runtime secrets](#runtime-secrets). +7. Save the configuration directly or through a pull request. Protected branches require a pull request. +8. Follow build and deployment progress in the workspace. Open the resulting app URL after the deployment succeeds. A manifest `workspace.deployment.strategy` must match the reviewed repository setting. For image strategy, every Git app must declare `reproducible: true`. Changing strategy requires a fresh review and confirmation; editing YAML alone does not approve replacing the workspace filesystem. The repository's manifest remains the source of truth. Changes made in Rigbox are saved back to Git; review configuration changes before saving them. See [deployment configuration](/guides/deploying#the-rig-yaml-contract) for the manifest fields. +Once the connection deploys the workspace's apps, it owns them, and `rig deploy` from your machine no longer deploys them. See [release ownership](/deploy/release-ownership). + +## Runtime secrets + +A push deploys in Rigbox, not on your machine, so it never reads your shell or `.env` files. It resolves the manifest's `secrets` from the connection's **runtime secrets**: values stored encrypted in Rigbox for this connection and never committed to Git. + +The rig.yaml at the pushed commit decides what each entry looks up: + +```yaml +secrets: + - name: TMDB_API_KEY # the variable the app sees + from: TMDB_READ_API # the runtime secret that holds its value + - name: SENTRY_DSN + optional: true +``` + +A value is stored under the entry's `from` name, or under its `name` when there is no `from`. A required secret without a value fails the push, and the deployment's status names it. An optional secret without a value is left out: the app deploys without that variable, and the deployment's status names the optional secrets it went without. + +Set runtime secrets in either place: + +- **Console**: open the connection's configuration and enter `NAME=value` lines under **Runtime secrets**, using each secret's `from` name. Values you enter replace saved ones; leave the field blank to keep them. Saving redeploys the branch head, unless the save opens a pull request. +- **CLI**: run `rig deploy` in the project directory. For apps the connection deploys, it deploys nothing. It stores the values it resolves from your environment and `.env` files, for the names that rig.yaml on the connected branch declares, lists the names it stored and any still missing, and exits with an error saying that pushes deploy the apps. The next push deploys with the stored values. + +`rig deploy` stores only secrets that rig.yaml on the connected branch declares. To add a secret, push the rig.yaml that declares it, then store its value. If it is required, that push fails until the value is stored; push again or retry the deployment afterwards. To avoid the failed push, declare it `optional: true` until its value is stored, or add both in the console, where saving commits the manifest and stores the value together. + +Check which declared secrets have a value, without showing any values: + +```bash +rig ci status --repo OWNER/REPO +``` + +Each connection lists every secret declared in rig.yaml on its branch as `set`, `missing`, or `missing (optional)`. Stored values are encrypted; once deployed, each is an ordinary environment variable of the app inside the workspace. + ## Deploy through your own CI workflow Follow [GitHub Actions](/guides/github-actions) to prepare Git sources, bind an existing workspace with `rig ci link`, and add the deploy Action. This flow uses short-lived OIDC credentials rather than a saved account API key. @@ -48,5 +82,8 @@ A [Deploy to Rigbox button](/guides/deploy-button) opens a guided flow for choos | A push does not deploy | Confirm the connected branch and selected deployment method. | | Strategy mismatch | Match the manifest and reviewed connection strategy, then review the change again. | | Deployment fails | Inspect build and app logs in the workspace; verify the start command, port, and health path. | +| Required secret has no value in this connection's runtime secrets | Store it as described in [Runtime secrets](#runtime-secrets), then retry the deployment. | +| Optional secret was left out | The connection has no value for it. Store one, then push again. | +| `rig deploy` says pushes deploy the apps | The connection owns them. Push to deploy; to deploy them with `rig deploy` again, see [release ownership](/deploy/release-ownership). | Automatic pull-request preview environments are not yet supported. diff --git a/operate/deployment.mdx b/operate/deployment.mdx index d88a128..0a61310 100644 --- a/operate/deployment.mdx +++ b/operate/deployment.mdx @@ -20,7 +20,7 @@ Check whether the failure happened before submission, during preparation, or dur | Error category | Recovery | | --- | --- | | Unknown field or removed build shape | Compare with the [v0.13 manifest reference](/reference/rig-yaml) | -| Existing app or port owned by another deployment | Choose a new target or explicitly plan migration; do not overwrite unrelated apps | +| Existing app or port owned by another deployment | See [release ownership](/deploy/release-ownership): push when a GitHub connection deploys the app; otherwise choose a new target or explicitly plan migration, and do not overwrite unrelated apps | | App requires system packages | Provision the workspace image; incremental installers are unprivileged | | Invalid working directory | Use release-relative paths and move mutable data to a persistent volume | | Source exceeds upload limits | Remove generated output, caches, or large assets from deployment input | diff --git a/operate/github.mdx b/operate/github.mdx index b07c971..900e79e 100644 --- a/operate/github.mdx +++ b/operate/github.mdx @@ -11,6 +11,8 @@ The console GitHub integration reacts to repository events using a reviewed proj Check repository installation access, branch selection, manifest path, target workspace, and deployment strategy in the console. Verify that the commit belongs to the configured repository and that private source access is still available. A strategy change may require explicit review; image deployment requires root-disk replacement consent. +A push resolves `secrets` only from the connection's [runtime secrets](/guides/github#runtime-secrets), never from `.env` files. The deployment's status names a required secret with no value, and any optional secrets it left out. Run `rig ci status --repo OWNER/REPO` to see which declared secrets have a value. + ## GitHub Actions Check the workflow's `contents: read` and `id-token: write` permissions, the Rigbox repository binding, and the Action's working directory. The initial repository claim has a limited window; inspect the binding before retrying. Never solve an OIDC failure by copying personal credentials into the manifest. diff --git a/scripts/build-navigation.py b/scripts/build-navigation.py index 5f33003..78450be 100644 --- a/scripts/build-navigation.py +++ b/scripts/build-navigation.py @@ -23,7 +23,7 @@ def area(label,pages): area('Start here',[group('Get started',['introduction','quickstart','guides/install-cli','concepts/core'])]), area('Deploy applications',[ group('Deploy',['deploy/overview','guides/deploying',group('GitHub',['guides/github-actions','guides/deploy-button'],'guides/github'),group('Multi-app projects',['deploy/dependencies','deploy/single-app'],'deploy/multi-app')]), - group('App releases',['deploy/development-loop','deploy/stage-and-activate','deploy/app-rollback']), + group('App releases',['deploy/development-loop','deploy/stage-and-activate','deploy/app-rollback','deploy/release-ownership']), group('Workspace images',[group('Reproducible builds',['deploy/build-cache','deploy/reimage','guides/releases-and-rollback'],'deploy/reproducible-builds'),'guides/bluegreen'])]), area('Configure applications',[ group('Configuration',['configure/overview','configure/environment','configure/secrets','configure/parameters','configure/commands','configure/health']),