Automation & CI
Continuous Integration
Run validation, drift review, secret scanning, and application tests in CI with explicit flags, structured output, and narrowly scoped credentials.
CI principles
- Pass all selections as flags; CI has no interactive prompt session.
- Prefer
--json,--format github, or--sarifover parsing human output. - Use one scoped automation credential per trust boundary.
- Do not enable
--show-valuesor echoGHOSTABLE_CI_TOKEN. - Keep production credentials out of untrusted pull-request jobs.
Create CI access
From an owner device:
$ ghostable access create --name github-actions --kind ci --grant staging:reader
Store the returned token in the CI platform as GHOSTABLE_CI_TOKEN and commit the generated public device, policy, and access-grant changes. A reader grant is sufficient for validation, review, and test-time decryption.
Validation and review
$ ghostable validate --env staging --json
$ ghostable review --base origin/main --head HEAD --format github
$ ghostable hygiene report --env staging --sarif
Pass an explicit base in CI so comparisons do not depend on checkout tracking configuration. Validation, review, and scan exit non-zero when actionable findings remain. Hygiene reports findings in its payload but exits successfully unless execution itself fails, so enforce hygiene thresholds through the SARIF consumer or a separate policy step.
Run tests with values
Inject values into the test process without writing a persistent env file:
$ ghostable env run --env staging --no-inherit --mask-output --strict -- npm test
--no-inherit reduces ambient runner variables, --mask-output replaces exact injected values found in child stdout and stderr, and --strict fails when requested configuration is missing or invalid. Masking is best effort: encoded, transformed, split, or file-written values can still escape. The runner can access decrypted process memory, so use an isolated CI environment.
Pull-request safety
Run repository-only secret scanning without credentials on untrusted changes, and reserve decryption for protected branches or reviewed deployment jobs.
Automation contract
-
stdout - Automation-oriented output is written here when --json, --format github, or --sarif is supported and selected.
-
stderr - Usage, verification, runtime, and final failure messages are written here. A failing JSON command may still emit a complete JSON result on stdout.
-
Exit 0 - The command completed and its checks passed.
-
Exit 1 - Invalid usage, a runtime or verification error, or findings from commands that fail checks such as validate, review, and scan. Hygiene reports findings without failing by default.
-
Exit 130 - An interactive prompt was canceled.
-
env run - Returns the child process exit code when that process starts and exits unsuccessfully.
Structured formats are available only when the command's --help lists them. Version-lock the CLI, ignore unknown JSON fields, and never assume structured output is secret-free: credential creation intentionally returns its token, while value-reading commands remain redacted unless plaintext output is explicitly requested.
See the command reference automation contract for the supported formats and a validation payload example.
Example pipeline
This GitHub Actions workflow scans pull requests without a credential and limits decryption to pushes on the protected main branch. Store GHOSTABLE_CI_TOKEN as a repository or environment secret available only to the protected job.
name: Ghostable
on:
pull_request:
push:
branches: [main]
permissions:
contents: read
jobs:
scan-untrusted:
if: ${{ github.event_name == 'pull_request' }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: actions/setup-node@v4
with:
node-version: 22
cache: npm
- run: npm ci
- run: npx ghostable review --base "origin/${{ github.base_ref }}" --head HEAD --secrets-only --format github
protected-checks:
if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }}
runs-on: ubuntu-latest
env:
GHOSTABLE_CI_TOKEN: ${{ secrets.GHOSTABLE_CI_TOKEN }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: actions/setup-node@v4
with:
node-version: 22
cache: npm
- run: npm ci
- run: npx ghostable validate --env staging --json
- run: npx ghostable review --base "${{ github.event.before }}" --head "${{ github.sha }}" --format github
- run: npx ghostable env run --env staging --no-inherit --mask-output --strict -- npm test
Pin @ghostable/cli and commit the lockfile so CI and developers execute the same 3.x release.