Skip to content

Support pre-built function runtime images in control plane projects #21

@negz

Description

@negz

What problem are you facing?

Per crossplane/crossplane#6840, Upbound is contributing the control plane project tooling to Crossplane. Part of this tooling is function building: taking function source code and producing OCI runtime images. The built-in builders work well for simple projects, but become limiting as projects grow in complexity.

For example, the Python builder detects main.py, tars the directory, and injects it into a base image. This is great for getting started, but it produces an on-disk layout that standard Python tools don't understand: type checkers can't resolve imports, pytest can't import function code, and there's no way to declare third-party dependencies. These limitations don't matter for simple projects, but they block standard development practices for complex ones.

More broadly, a complex Crossplane project may include components beyond composition functions — Go services, TypeScript frontends, or other tooling. The project already needs a build system (make, nix, CI pipelines) for these components. Having the Crossplane CLI also act as the function build tool means coordinating two build systems that may have conflicting opinions about project layout.

How could Crossplane help solve your problem?

I'd like control plane projects to support pre-built function runtime images as inputs, alongside the existing source-directory-based building. Something like:

spec:
  functions:
    # Source-based: the CLI builds the runtime image (today's behavior)
    - path: functions/function-a

    # Pre-built: the user provides the runtime image, the CLI packages it
    - image: build/function-b.oci.tar

For functions declared with image:, the CLI would skip the build step and use the provided OCI image as the function runtime. It would still add the Crossplane package metadata layer (crossplane.yaml) to produce a complete function package — the user provides the runtime, the CLI handles the packaging.

One consideration is multi-platform support. The built-in builders produce runtime images for multiple architectures (e.g. amd64, arm64). Pre-built images would need to support this too, either as a multi-arch OCI image index or as separate per-platform images.

This lets projects that outgrow the CLI's built-in builders use whatever build system they prefer (Docker, Nix, Bazel) while keeping the CLI's packaging, testing, and registry management. It also opens the door to function runtimes in languages the CLI doesn't have a built-in builder for.

The simple experience stays simple — path: functions are built by the CLI as today. Pre-built runtime images are the escape hatch for when you need full control over the build.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions