Push Workflow

The CLI-based path from code to marketplace listing.

Prefer the GitHub App? The recommended way to ship on Kyper is to connect the GitHub App and push a semver tag — no CLI needed for releases. This page covers the manual kyper push path, which is fully supported and useful for initial setup and local testing.

Overview

kyper push is a single command that handles the entire deployment pipeline: validating your config, archiving your source, syncing metadata, uploading your version, and streaming the build log.

Before you push

Three commands let you gain confidence at increasing levels of fidelity before submitting for review.

kyper check Validates kyper.yml and confirms the Dockerfile exists. No Docker required — instant feedback.
kyper build Runs docker build locally using the same Dockerfile as the remote pipeline. Catches build failures in seconds instead of minutes. Add --scan to also run the Trivy security gate.
kyper test Deploys your app on Kyper's real K8s infrastructure with full dep support. Gives you a live HTTPS URL for end-to-end verification. Auto-destroys after 1 hour. If you're using the GitHub App, push a pre-release tag instead (v1.0.0-rc.1) — same result, no CLI needed.
bash
# Quick sanity check (no Docker needed)
kyper check

# Full local build test
kyper build

# Build + security scan (same gate as remote pipeline)
kyper build --scan

# End-to-end test on real infrastructure
kyper test

Build pipeline

  1. 1
    Validate — the CLI runs a full validation of your kyper.yml locally. If there are errors, push stops immediately. Warnings are shown but don't block the push.
  2. 2
    Archive — your source code is zipped, respecting .kyperignore and .dockerignore patterns. Default excludes: .git/, *.log, tmp/, node_modules/.
  3. 3
    Sync metadata — the CLI creates your app on Kyper (first push) or updates its metadata (subsequent pushes). Title, description, category, pricing, and tech stack are synced.
  4. 4
    Upload — the archive and raw kyper.yml are uploaded as a new version via multipart form to the API.
  5. 5
    Docker build — Kyper extracts your source and builds the Docker image from your Dockerfile.
  6. 6
    Port validation — the built image is inspected for EXPOSE 3000. If missing, a prominent warning is shown in the build log (the build still succeeds). Kyper routes all traffic to port 3000, so your web process must listen on $PORT.
  7. 7
    Security scan — Trivy scans the image for known vulnerabilities. Results are stored and displayed in your developer portal.
  8. 8
    Submit for review — after a successful build, the CLI prints a link to your submission page. Visit it to provide demo credentials (for apps with required env vars) and any review notes — test accounts, known limitations, or setup instructions. Click "Submit for review" to send your version to the review queue. The Kyper team is notified only after you submit. Credentials are stored encrypted and never shared.
  9. 9
    Review — the Kyper team reviews your submission. Reviewers may deploy a live test instance using your demo credentials to verify everything works. You'll receive an email when it's approved or if changes are needed.

Version status lifecycle

pending → building → built → in_review → published
↘ build_failed
↘ rejected

Tailing build logs

After uploading, the CLI automatically streams your build log in real-time. If you disconnect, you can resume with:

bash
kyper push logs

The log uses cursor-based polling (every 2 seconds) with a 30-minute timeout. In --json mode, a spinner replaces the log output.

Debugging build failures

Reproduce the failure locally with kyper build — it runs the same docker build command as the remote pipeline, so you can iterate on fixes in seconds instead of waiting for a remote build.

bash
# Reproduce locally
kyper build

Common causes of build failures:

  • Dockerfile syntax errors or missing dependencies
  • Missing files referenced in COPY/ADD instructions (check your .kyperignore)
  • Build commands that require network access (e.g., npm install should run during the build, not after)
  • Out-of-memory during build (contact support if this happens)

To retry after a failure:

bash
# Retry the same build without changes
kyper push retry

# Fix your code and push again (same version number is fine)
kyper push

The security gate

Kyper scans every image with Trivy for HIGH and CRITICAL vulnerabilities in your app's dependencies (gems, npm packages, pip packages, go modules, etc.). Only CRITICAL library vulnerabilities with an available fix will block your build.

Blocking CRITICAL library vulnerabilities with an available fix. These fail your build — upgrade the affected dependency in your Gemfile, package.json, etc. to pick up the patch.
Advisory HIGH library vulnerabilities (fixable or not), any CRITICAL with no upstream patch, and all OS-level packages from your base image. These are logged but never block your build. OS advisories appear as a collapsible section in the build tracker — upgrading your base image tag will resolve them when a fix is available.

You can scan locally before pushing with kyper build --scan to see exactly what the build gate will flag:

bash
# Build + security scan — same gate logic as the remote pipeline
kyper build --scan

# Show only CRITICAL blocking vulnerabilities (hides HIGH advisory)
kyper build --scan --fix

Ignoring a CRITICAL CVE

In rare cases, a CRITICAL fixable CVE may not apply to your app (e.g., a library you ship but never call). You can declare it as accepted risk in kyper.yml:

yaml
security:
  ignore_cves:
    - id: "CVE-2025-68121"
      reason: "Affects OpenSSL DTLS which this app does not use"

Guidelines

  • Each id must match the format CVE-YYYY-NNNNN
  • Each reason must be at least 10 characters — explain why the CVE is acceptable
  • Maximum 25 ignored CVEs per app
  • ignore_cves is for CRITICAL fixable library CVEs — HIGH vulns, unfixed CVEs, and OS-level base image packages are automatically advisory and never need to be ignored
  • Reviewers may reject submissions with poorly justified or excessive ignores
  • Remove entries once they're no longer needed — stale ignores look bad in review

Test on Kyper's infrastructure

Once your Dockerfile builds cleanly, kyper test lets you deploy your app to Kyper's real K8s infrastructure before submitting for review. Your declared deps (Postgres, Redis, etc.) are provisioned alongside your app, and you get a live HTTPS URL to poke around in.

bash
kyper test

The deployment auto-destroys after 1 hour. Tear it down early with:

bash
kyper test destroy

Check status at any time (useful if you disconnected mid-provision):

bash
kyper test status

Limits

  • 1 active test deploy at a time (a new kyper test automatically destroys the previous one for the same app)
  • 3 test builds per day across all your apps

See the Best Practices guide for a full pre-submission checklist and common gotchas caught by kyper test.

Using the GitHub integration?

You can set test env vars directly on the repo link instead of passing them via the CLI — they're encrypted, scoped to test deploys only, and visible in your GitHub Check Run if anything goes wrong. See GitHub integration → Env vars for test deploys.

Submission details

After a successful build, the CLI will print a submission URL. Visit it to provide:

  • Demo environment variables — if your app declares required env vars in kyper.yml, provide demo values so the reviewer can test your app. These are stored encrypted and never shared.
  • Review notes — test accounts, demo data instructions, known limitations, or anything else the reviewer should know.

When you click Submit for review, your version moves from built to in_review and the Kyper team is notified. You can also access the submission form from the "Submit for review" link on your version in the developer portal. After submission, you can still update your details via the "Edit submission" link.

Migrations & the release hook

Most webapps need their database schema in place before the web process can start. Kyper provides hooks.release for this: a one-shot command that runs after your declared deps (postgres, redis, etc.) are ready, and before your app pods are created. It's the standard "release migration" pattern, modelled on Helm's pre-install hooks.

The release hook runs as a dedicated Kubernetes Job using the same image, the same env vars, and the same registry credentials as your web process. If it fails, the deploy is marked failed with the Job's pod logs attached, and your app pods never start. On a version update the release hook runs against the new image before the rolling update begins, so a failing release leaves the previous version untouched.

Write temporary files through your framework's standard temp-file APIs or TMPDIR. App pods and release hooks run with a read-only image filesystem, so paths baked into your image, such as /rails, are not safe places to write runtime data. Put durable uploads, SQLite databases, and other persistent files in storage paths declared in kyper.yml.

yaml
# kyper.yml — Rails
hooks:
  release: "bundle exec rails db:prepare"

# kyper.yml — Prisma / Node
hooks:
  release: "prisma migrate deploy"

# kyper.yml — Drizzle
hooks:
  release: "npm run db:migrate"

# kyper.yml — Goose / Atlas / etc.
hooks:
  release: "/usr/local/bin/migrate"

Don't put migrations in hooks.on_deploy. on_deploy runs after your pods are healthy by exec'ing into a running web pod. If your app crashes on first boot waiting for its schema, your web pod will never become healthy and the hook can never fire. hooks.release exists specifically for this case.

Don't inline secrets in your hook command. The hook command string is logged verbatim into the deployment's provision log, which the consumer can view in their dashboard. If you do release: API_KEY=xxx prisma migrate deploy, the key lands in the visible log. Put secrets in env: instead — they're encrypted at rest and injected as env vars into the release Job's container, never logged.

Why this matters for kyper test: every kyper test deploy starts with a brand-new, empty database — even if your app has deployed successfully before as a subscription. Subscription deploys keep their database between version updates; test deploys do not. So an app whose web process needs schema-at-boot will reliably fail under kyper test until hooks.release is set, even after months of healthy production deploys.

Review process

Every version goes through manual review. Reviewers check:

  • Dockerfile builds correctly and follows best practices
  • No critical vulnerabilities flagged by Trivy
  • App functions as described in the listing (reviewers may spin up a live test instance)
  • No prohibited content (malware, illegal activity, license violations)
  • Environment variables are properly documented

You'll receive an email notification when your version is approved or rejected. Rejected versions include reviewer notes explaining what needs to change.

Need to fix something while in review? Just push again with the same version number — Kyper automatically replaces the in-review submission with your new build and restarts the review queue. No need to withdraw first.

bash
# Fix an issue flagged in review — no withdraw needed
# edit your code...
kyper push   # same version number is fine