Creating Packages

Create, push content to, render, and publish a package using the CRD-based architecture.

Overview

This guide walks through the full lifecycle of a PackageRevision managed by the PR Controller: creating a package, pushing content, observing rendering, and publishing.

All operations use standard kubectl commands against the PackageRevision CRD (porch.kpt.dev/v1alpha2).

Create a Package (Init)

Create a new package by applying a PackageRevision with spec.source.init:

apiVersion: porch.kpt.dev/v1alpha2
kind: PackageRevision
metadata:
  name: my-repo-my-package-v1
  namespace: default
spec:
  repository: my-repo
  packageName: my-package
  workspaceName: v1
  lifecycle: Draft
  source:
    init:
      description: "My first CRD-based package"
      keywords:
        - example
kubectl apply -f packagerevision.yaml

The CRD is created immediately in etcd. The PR Controller picks it up and executes the init source operation in the background.

Watch for Ready

The controller reports progress via status conditions. Wait for the package to become ready:

kubectl wait packagerevision my-repo-my-package-v1 \
  --for=condition=Ready \
  --timeout=30s

Or inspect the conditions directly:

kubectl get packagerevision my-repo-my-package-v1 -o jsonpath='{.status.conditions}'

When both Ready and Rendered conditions are True, the package has been created and rendered successfully.

Push Content

Edit the package contents through PackageRevisionResources (PRR). This is an aggregated API served by the Porch API Server:

# Get current resources
kubectl get packagerevisionresources my-repo-my-package-v1 -o yaml > prr.yaml

# Edit prr.yaml to add/modify resources in spec.resources
# Then apply
kubectl apply -f prr.yaml

After pushing content, the API Server patches the porch.kpt.dev/render-request annotation on the PackageRevision CRD. This triggers the PR Controller to render the updated content.

Observe Rendering

After a content push, the Rendered condition temporarily transitions to Unknown (rendering in progress) and then back to True when complete:

kubectl get packagerevision my-repo-my-package-v1 \
  -o jsonpath='{.status.conditions[?(@.type=="Rendered")]}'

If rendering fails (e.g. a KRM function error), the Rendered condition is set to False with an error message in the message field.

Publish

When you are satisfied with the package content, transition it to Published:

kubectl patch packagerevision my-repo-my-package-v1 \
  --type=merge \
  -p '{"spec": {"lifecycle": "Published"}}'

The controller transitions the package in Git (typically from a branch to a tag), assigns a revision number, and updates the porch.kpt.dev/latest-revision label.

kubectl get packagerevision my-repo-my-package-v1 \
  -o jsonpath='{.status.revision}'

Create a New Revision (Copy)

To edit a published package, create a new revision by copying from the existing one:

apiVersion: porch.kpt.dev/v1alpha2
kind: PackageRevision
metadata:
  name: my-repo-my-package-v2
  namespace: default
spec:
  repository: my-repo
  packageName: my-package
  workspaceName: v2
  lifecycle: Draft
  source:
    copyFrom:
      name: my-repo-my-package-v1

This creates a new draft workspace with the content of the published revision, ready for editing.

Clone from Upstream

To create a downstream package from an upstream source:

apiVersion: porch.kpt.dev/v1alpha2
kind: PackageRevision
metadata:
  name: my-repo-downstream-pkg-v1
  namespace: default
spec:
  repository: my-repo
  packageName: downstream-pkg
  workspaceName: v1
  lifecycle: Draft
  source:
    cloneFrom:
      upstreamRef:
        name: upstream-repo-upstream-pkg-v1

The controller clones the upstream content and sets up the Kptfile upstream/upstreamLock tracking.

Delete a Package

Draft packages can be deleted directly:

kubectl delete packagerevision my-repo-my-package-v2

Published packages are protected by a finalizer. To delete a published package, first transition it to DeletionProposed:

kubectl patch packagerevision my-repo-my-package-v1 \
  --type=merge \
  -p '{"spec": {"lifecycle": "DeletionProposed"}}'

kubectl delete packagerevision my-repo-my-package-v1

Using porchctl

All operations in this guide can also be performed using the porchctl CLI with the --api-version=v1alpha2 flag. See the User-Facing Differences page for CLI examples targeting the CRD-based architecture.

Summary

OperationHow
Create (init)kubectl apply with spec.source.init
Create (clone)kubectl apply with spec.source.cloneFrom
Create (copy)kubectl apply with spec.source.copyFrom
Push contentEdit and apply PackageRevisionResources
Check statuskubectl get packagerevision -o jsonpath='{.status.conditions}'
PublishPatch spec.lifecycle to Published
Delete draftkubectl delete packagerevision
Delete publishedPatch lifecycle to DeletionProposed, then delete
Last modified July 21, 2026: Address review comments (490a956)