Applications connect to GitHub repositories and use a GitHub credential. By default the generated CI/CD pipeline pushes the container image to your organisation’s private Ankra registry; if you already run your own registry, declare it and Ankra publishes to and reads from it instead.
How it works
1
Connect a repository
Provide a name and a GitHub credential, then pick the repository and a branch from the repository’s own branch list - the default branch is preselected, and Enter a different branch lets you type one that does not exist yet.
2
Analyze and generate
Ankra inspects the repository, detects the language and framework, and generates the artifacts it needs: a Dockerfile, Kubernetes manifests, and a CI/CD workflow.
3
Merge the pull request
Review and merge the PR. Merging activates the CI/CD pipeline in your repository.
4
Build and publish
CI builds and pushes the container image to the organisation’s private Ankra registry. Ankra surfaces the image URL and scans the published image.
5
Deploy
Deploy the application onto a cluster. Ankra verifies that the image was published and tracks the rollout.
What Ankra tracks
For each application you see:- State and analysis status - where the application is in the connect/analyze/generate/build lifecycle, with an error message if something needs attention.
- Repository - owner, name, branch, and URL.
- Components - the repository’s deployable apps. An ordinary repository has one; a monorepo has one per app.
- Artifacts - the private container image URL and the latest published build, per component.
- Pull request - a link to the generated PR.
- Jobs - the underlying platform jobs for the application, so you can follow analysis and generation as it runs.
Monorepos
A repository that builds more than one deployable app is onboarded as a monorepo: Ankra records one component per app, and each component gets its own packaging and its own image.
Ankra decides the components from, in order: the per-component workflows the repository already carries (so re-running analysis never renames a component and orphans the images it has published), the apps the analysis proposed, then the repository’s structure - two or more Dockerfiles in subdirectories and no Dockerfile at the root, or a workspace marker (
nx.json, turbo.json, lerna.json, pnpm-workspace.yaml, go.work) plus two or more subdirectories with their own dependency manifest. A Dockerfile at the repository root always means a single app, whatever else the repository contains.
Build state, published images, deploys, demos, and container scanning are all reported per component, so an application whose API component built and whose frontend did not says exactly that.
Using your own registry
An application publishes to your organisation’s private Ankra registry unless you say otherwise. If you already operate a registry - the same Harbor whose OCI charts Ankra indexes, for instance - declare it on the application and Ankra publishes there, reads the published tags back from there, and pulls from there. Declare it on an existing application from Settings → Image registry, from the CLI, or withimage_registry when you create the application. The settings panel also reports the host and project the declaration resolved to and the image repository each component is expected to publish to, so you can compare them against where your builds actually push.
Ankra does not mint robots for a registry you operate. With a declared registry, setup names the two Actions secrets the workflow reads and leaves them to you, rather than writing a credential Ankra happens to hold over a push robot you administer. Publish readiness reports whether those secrets exist and names them. Set
manage_actions_secrets: true to have Ankra write the declared credential into them instead.
On a monorepo, a component may declare its own
image_registry to publish into a different project of the same registry - useful when each app has its own robot accounts and retention rules. A component’s declaration wins over the application’s; the application’s applies to every component that declares none.Security scanning
Applications include code and container security insights, so vulnerabilities surface alongside the build rather than in a separate tool. On a monorepo, the image tags and the scanned image reference follow the component you select; code and IaC findings cover the whole repository, because that is where those scanners run. Pair this with AI Insights for proactive analysis.Preview demos
Before you merge, you can spin up a throwaway demo of a pull request or branch build to see it running. Each demo is deployed into its own isolated namespace (ankra-demo-pr-<n> or ankra-demo-br-<branch>) on the organisation’s staging cluster, PodSecurity-hardened and quota-bounded, and is automatically torn down when its TTL expires - so it can never affect existing workloads.
1
Configure a staging cluster
An admin sets the organisation’s staging cluster under AI → Settings → Workspaces. Optionally set a demo base domain (with an ingress class and TLS secret) there too - this is what gives demos a public URL.
2
Deploy a demo
Deploy a branch or PR demo from the application’s Demos tab, from the CLI, or by asking the AI assistant. The demo pulls the image tag the PR/branch build pushed.
3
Open the preview
When a public host is available, Ankra returns a preview URL you can open directly. Otherwise the demo stays reachable in-cluster (service DNS + a
kubectl port-forward command).The preview URL
Ankra resolves the demo’s public hostname automatically, and every surface (portal, CLI, MCP, and automatic PR previews) uses the same rule:- An organisation demo base domain, if configured, wins outright - the host is
<namespace>.<demo-base-domain>, served with your configured ingress class and TLS secret. - Otherwise, the staging cluster’s own delegated DNS zone, but only when that zone is active - giving
<namespace>.<cluster-id>.<org-id>.<ankra-domain>, a hostname theexternal-dnsrunning on that cluster can resolve. - Otherwise the demo stays in-cluster-only - no ingress is created, and you reach it with the returned service DNS name and
kubectl port-forward.
A demo only gets a resolvable public URL when the organisation has a demo base domain configured or the staging cluster has an active Ankra DNS zone. Without either, the demo still deploys - it just stays in-cluster-only.
ankra.cc by default. An organisation can register its own custom domain - dedicated to that organisation alone - in the Custom Ankra domain field under AI → Settings → Workspaces. The domain must be a bare domain the organisation owns, its NS records must already point at Ankra’s nameservers (the ones serving ankra.cc), and no other organisation may hold it. Zones already provisioned keep the domain they were minted under, so the switch is refused while any cluster DNS zone or DNS record still lives under the old domain: remove each cluster’s zone first (ankra cluster domain <cluster> --remove, or DELETE /api/v1/clusters/{cluster_id}/dns-zone) and delete the records, then save the new domain. Ankra tears the organisation zone down and re-creates it under the new domain; re-enable each cluster’s zone afterwards (ankra cluster domain <cluster>) - the staging cluster’s zone comes back on its own - and the cluster’s external-dns picks up the new zone on its next cloud-provider stack pass.
Deploying a demo
A demo deploys every component of the application by default. A single-app application runs its one image; a monorepo runs one pod per component — the frontend and the API of a two-app repository both come up, wired together, instead of half an application answering where the other half belonged. You can still deselect components or demo a single one.- Portal
- CLI
- AI / MCP
Open the application’s Demos tab, pick a branch or enter a pull request number, and deploy. The tab shows active demos, the preview URL, and the remaining TTL. Each demo links to its own detail page - live provisioning progress read from the staging cluster, the namespace’s bill of materials with manifests (grouped per component), Kubernetes events, and pod logs, plus the preview URL or port-forward command to reach it. On a monorepo the launch dialog lists every component with its own build status and tag, lets you include or exclude each, and marks the web entry — the component that owns the demo URL.
Monorepo demos: every component, one URL
A monorepo demo deploys each component as its own Deployment and Service inside the demo namespace, and the demo only reports ready once every component accepts connections:-
The web entry owns the demo URL. Ankra picks the frontend-shaped component (a name or directory like
frontend,web,ui,portal) as the entry serving/on the demo host; you can move the entry in the launch dialog or withentry_componenton the API. -
API components share the host under a path. The single API-shaped component (
api,backend,server) is published under/apion the same demo host, routed straight to its Service — so a browser calling/api/...reaches the API even when the frontend’s own proxy target was baked for another environment. Override per component withingress_path. -
Save the routing when the guess is wrong. The entry and the
/apipath above are heuristics, and the lanes with no human in the loop — the automatic PR previews and the MCP demo tools — have no launch dialog to correct them in. Declare the routing once in the demo configuration and every lane follows it:A declaration is authoritative: the/apiguess stops running, so a component you leave out ofcomponentsstays reachable in-cluster only rather than picking up a path it never asked for. Per-launchingress_pathoverrides still win over the declaration. Clear it with"routing": nullto return every lane to the heuristics. -
Components reach each other by name. Every component’s Service is named after it, so in-namespace URLs like
http://crm-api:8090resolve. Env values can also use placeholders that resolve at deploy time:
The saved migration command runs once per deploy, inside the image of the component that owns the schema (the primary component - usually the backend). Demo environment defaults and the throwaway database are shared by every component of the demo.
Existing demos and single-app applications are unaffected: a demo recorded before multi-component support (or of an application with one component) keeps exactly the previous single-pod shape.
Environment variables and a throwaway database
Most real applications need configuration to boot — a database name, an API key, an SMTP host. Demos support both per-application defaults and per-launch overrides, so any codebase can run as a demo without changes:- Defaults live behind the gear button on the Demos tab (Demo settings). Every demo of the application inherits them — manual launches, CLI/MCP deploys, and the automatic PR previews.
- Overrides are set per launch in the Environment & database section of the launch dialog (or via the
envargument ofdeploy_pr_demo). Overrides win by name.
The throwaway database is ephemeral by design: it starts empty on every deploy and is wiped with the namespace. The database runs a pgvector-capable Postgres, so migrations using
CREATE EXTENSION vector work. .url and .password references are always delivered through a Kubernetes Secret, never as plain env text.migrate_command) — for example pnpm run db:migrate or alembic upgrade head. It runs inside your application image (sh -c) as an init container, after the database accepts connections and with the same environment the app sees, so a fresh demo database provisions its schema before the first request. Because every deploy starts the database empty, the command re-runs on every deploy — write migrations to be idempotent (every standard migration tool is).
The command runs with your image’s
WORKDIR as the working directory and on PYTHONPATH. Python puts the script’s directory on sys.path, not the working directory, so a migration entrypoint that is a script rather than a console script — python scripts/bootstrap_database.py — could not import the application package sitting beside it and died at import with ModuleNotFoundError. Setting PYTHONPATH yourself in the command still wins.database_extensions (for example ["vector"]) and the demo database creates them at initdb, before your migrations run.
Ankra detects both automatically when it analyses a repository: a Postgres client dependency, an ORM configuration, or a composed database marks the application as database-needing, its referenced connection variables are wired to the ${{ ankra.demo_database.* }} placeholders, and a recognised migration script becomes the migration command — so the first demo of a database-backed application works without any manual configuration. Detection only ever seeds an application that has no demo configuration yet; it never overwrites what you or the pre-setup agent saved.
The demo container port
The demo’s readiness probe, Service, and preview route all target one container port, resolved in this order: the component’s recorded port, the generated runtime Dockerfile’sEXPOSE, the generated Deployment manifest’s containerPort, the analysed target_port parameter, and only then the platform default. The launch dialog shows the resolved port and where it came from; a port you did not edit is left to the platform to resolve.
When the resolved port is still wrong — stale analysis, a hand-edited Dockerfile — the platform corrects itself at runtime: a demo whose container runs cleanly but never accepts connections has its logs read for the port the server actually announces (Accepting connections at…, Listening on…, and the other common startup banners). If the evidence is unambiguous, the demo is repointed at the announced port on the fly, the correction is recorded on the application so the next launch resolves it statically, and the demo detail page shows the correction. Ambiguous evidence never auto-corrects; it flows into the failure message (“Nothing accepted connections on port 3000. The container’s logs say it listens on port 8001.”) and dispatches the pre-setup agent instead.
Automatic pre-setup when a demo crashes
An image that validates its environment on boot — refusing to start without a database URL, an auth secret, an API key — crash-loops when demoed with no configuration. Ankra now detects this and fixes it with an agent:- When a demo fails with a startup crash (CrashLoopBackOff or a container configuration error), a failed migration command, or a port-evidence timeout (the container announced a different port than the demo probed), Ankra dispatches a one-shot pre-setup agent for it automatically. The run appears on the AI agents page like any other mission.
- The agent reads the crashed container’s logs, works out which environment variables the application demands, and generates a pre-setup: missing database URLs become
${{ ankra.demo_database.* }}references with the throwaway Postgres enabled, secrets get fresh random values, and mode flags get the value that avoids external side effects. - It saves the pre-setup as the application’s demo defaults — so every future demo inherits it — and redeploys the failed demo to prove it boots.
CREATE EXTENSION failures. It never weakens the application’s own validation, never reuses values found in logs, and merges with existing demo settings rather than replacing what you configured. Dispatch is bounded to one run per demo per day; image-pull failures and provisioning timeouts never dispatch (no environment can fix those). You can also trigger it on demand with POST /org/applications/{application_id}/demos/{workspace_id}/fix, or just ask the AI assistant to fix the failed demo — the chat has the same get_demo_diagnostics, update_application_demo_config, and redeploy_demo tools the mission uses.
Managing applications
Which Ankra AI lanes run on the application’s repository - the pull request review, the organisation skills review, the automatic preview URL - is set per application under Settings → Ankra AI. See Application AI settings.
Prerequisites
1
Connect GitHub
Add a GitHub credential with access to the application’s repository. The Ankra GitHub App needs permission to open pull requests, commit workflow files, and manage Actions secrets. Ankra installs the Ankra registry credentials on the repository automatically; for your own registry you set the login secrets yourself.
API
Applications are available over the API for CLI and scripted use, under/api/v1/org/applications (bearer-token authenticated) - create, list, inspect, retry, reconcile, and delete. See the API Reference for endpoints and schemas.
The same lifecycle is available through Ankra’s AI and MCP clients - connect, deploy, retry, reconcile, and delete applications, and follow their CI workflow runs - see the MCP Tool Reference.
See the CI/CD Pipeline guide for how the generated pipeline fits into GitOps.