keytec-ai-cli
v0.5.0
Published
keytec-ai: one CLI for .keytec-ai.yml operations (deploy, env) — used by GitLab CI, the DDEV addon and the deploy skill
Readme
keytec-ai
One CLI for .keytec-ai.yml operations, used by GitLab CI, the DDEV addon, and the
keytec-drupal-deploy skill — so the logic lives in one tested, versioned place instead of
being copied into each project.
Komodo registry-deploy model: stacks are declared in git as Komodo Resource Sync TOML
(komodo/*.toml, one stack per branch) and created by Komodo; keytec-ai deployer deploy
triggers DeployStack for the branch's stack and polls until it completes.
Run it
Run it with npx — a self-contained JS bundle on the public npm registry, no
install, no .npmrc, no auth:
npx keytec-ai-cli config to-env
npx [email protected] deployer deploy develop # pin a versionIn CI, call it the same way (any node image):
# .gitlab-ci.yml in a consumer project
deploy:
image: node:22-alpine
script:
- npx keytec-ai-cli deployer deploy "$CI_COMMIT_REF_NAME"For repeated local use, install once: npm i -g keytec-ai-cli, then keytec-ai ….
Commands
keytec-ai config to-env [--config <path>] [--to-file <path>] Export the config as env vars
keytec-ai deployer deploy [<branch>] Deploy the branch's Komodo stack
keytec-ai deployer destroy [<branch>] Tear down the branch's Komodo stack
keytec-ai deployer provision-secrets Create the per-env secret Komodo Variables
keytec-ai deployer is-deployed --mr <iid> Is an MR live on its environment?
keytec-ai deployer release-mrs List the MRs a deploy shippedconfig to-envrenders the whole.keytec-ai.ymlas flatUPPER_SNAKEenv vars (nested keys joined with_, arrays comma-joined, empty objects skipped). Writes to stdout, or to a file with--to-file=.env. The config is located by walking from the current directory up to the filesystem root, so it works from any project subdirectory.deployer deployresolves the branch's stack, ensures its secrets exist, triggersDeployStack, and polls until the on-node deploy completes (fails with Komodo logs on error). Stacks are declared in git and created by a Komodo Resource Sync; the CLI never creates stacks or sets image tags.
Deploy model
Deploy state lives in git as Komodo Resource Sync TOML under komodo/*.toml — not in
.keytec-ai.yml. Each environment is one [[stack]] block keyed by its branch; secrets
are referenced with [[NAME]] and provisioned as per-env Komodo Variables.
# komodo/stacks.toml
[[stack]]
name = "lumora-cms-develop"
[stack.config]
branch = "develop"
environment = """
DB_PASSWORD=[[LUMORA_DEVELOP_DB_PASSWORD]]
"""- one
[[stack]]per branch — the branch name is the environment; 0 or >1 matches errors. deployer provision-secretscreates every[[…]]secret as a Komodo Variable (idempotent).
deploy env vars
- deploy / destroy:
KOMODO_URL,KOMODO_API_KEY,KOMODO_API_SECRET(+CI_COMMIT_REF_NAMEas the default branch in CI). - is-deployed / release-mrs:
GITLAB_TOKEN,GITLAB_API_URL(orCI_API_V4_URL),GITLAB_PROJECT_ID(orCI_PROJECT_ID),CI_COMMIT_SHA.
Develop
bun install
bun test
bun run dev -- env develop # run from a dir with .keytec-ai.yml
bun run build # -> ./dist/cli.js (node bundle, what npm publishes)Releasing
Merge to 1.x = a new version on npm. Every push to the 1.x branch runs
publish:npm, which publishes package.json version to the public npm registry.
That's the whole release: nothing to tag, no manual publish step.
# 1. work on a feature branch, bump the version, MR into next
git checkout next && git pull
git checkout -b feat/my-change
npm version patch --no-git-tag-version # bump package.json (patch|minor|major)
# ... commit, push, open MR, merge into next ...
# 2. release: merge next into 1.x
git checkout 1.x && git merge next && git push
# -> CI publishes keytec-ai-cli@<version> to npmThe version is the gate: if package.json version is already on npm,
--tolerate-republish makes the job a no-op, so pushes to 1.x without a bump
publish nothing. Bump version in the MR for the release to actually ship.
Under the hood publish:npm (on 1.x) runs prepublishOnly to bundle src into
dist/cli.js, writes an ephemeral .npmrc from the masked NPM_TOKEN (never
committed), and runs bun publish --access public. 1.x is a protected branch so
the protected NPM_TOKEN is exposed there.
CI variables
| Variable | Purpose | Flags |
|----------|---------|-------|
| NPM_TOKEN | npm automation token for publish:npm | masked, protected |
