Skip to content

feat: make flyte build the supported CI image build path#792

Draft
jeevb wants to merge 17 commits intomainfrom
jeev/flyte-build
Draft

feat: make flyte build the supported CI image build path#792
jeevb wants to merge 17 commits intomainfrom
jeev/flyte-build

Conversation

@jeevb
Copy link
Copy Markdown
Contributor

@jeevb jeevb commented Mar 13, 2026

Summary

  • Add tag: Optional[str] = None to Image.clone(), from_dockerfile(), from_debian_base(), and from_uv_script() — placed immediately after name in every signature, consistent with registry and name
  • Replace the private Image._tag field with a public Image.tag attribute, consistent with registry and name; constructors now pass tag= directly to _new() instead of using post-construction object.__setattr__
  • Thread force: bool = False through build_images_build_images_build_image_bgbuild.aio so the existing ImageBuildEngine.build(force=) param is reachable from the public API
  • Add --force flag to flyte build CLI via BuildArguments, wired into BuildEnvCommand.invoke
  • Deprecate examples/image/ci_build_image.py with a comment pointing to flyte build

Usage

Pattern A — retag + rebuild via remote builder:

# images.py
env = flyte.Environment(
    name="my_image",
    image=flyte.Image.from_base("ghcr.io/flyteorg/flyte:py3.12-v2.0.0b56").clone(
        registry="123456789.dkr.ecr.us-west-2.amazonaws.com/myorg",
        name="my-image",
        tag=os.environ.get("VERSION"),
    ),
)

Pattern B — Dockerfile-based build:

env = flyte.Environment(
    name="my_image",
    image=flyte.Image.from_dockerfile(
        Path(__file__).parent / "Dockerfile",
        registry="123456789.dkr.ecr.us-west-2.amazonaws.com/myorg",
        name="my-image",
        tag=os.environ.get("VERSION"),
    ),
)
# CI step — always rebuild and push
flyte build images.py my_image --force

Test Plan

  • uv run pytest tests/flyte/test_image.py tests/flyte/test_deploy.py tests/cli/test_build.py -v — 70 tests, all pass
  • uv run flyte build --help--force appears in output

@jeevb jeevb marked this pull request as draft March 13, 2026 17:55
jeevb added 10 commits March 13, 2026 19:08
Add tag: Optional[str] = None parameter to clone() method, allowing users to override the content-hash-based tag with an explicit tag. Empty strings are normalized to None to fall back to content-hash-based tagging.

Signed-off-by: Jeev B <[email protected]>
Adds a --force group-level option to the `flyte build` command that is
forwarded to `flyte.build_images` to skip image existence checks and
always rebuild. Tests verify the flag is passed correctly when set and
defaults to False when omitted.

Signed-off-by: Jeev B <[email protected]>
@jeevb jeevb force-pushed the jeev/flyte-build branch from 5ea38c4 to 6bc897f Compare March 14, 2026 02:08
…osition

The *-separator changes made tag and other parameters keyword-only,
which risks breaking existing user code. Roll back those changes and
instead append tag= as the last positional argument in each factory
method and clone() for consistency without imposing keyword-only
constraints on callers.

from_uv_script retains its pre-existing *-separator (it was keyword-only
on main already); tag= is appended after secret_mounts.

Signed-off-by: Jeev B <[email protected]>
@jeevb
Copy link
Copy Markdown
Contributor Author

jeevb commented Mar 14, 2026

Thinking we should support bare images, not wrapped in Environment as well. Environment feels extraneous for this purpose.

jeevb added 3 commits March 16, 2026 09:08
Remove the deprecation header and rewrite the module docstring to clearly
describe when to use this script (re-tagging a pre-built image) versus
`flyte build` (building images from Environment definitions).

Also replace the fragile object.__setattr__(image, "tag", tag) mutation
with clone(tag=tag), using the proper public API.

Signed-off-by: Jeev B <[email protected]>
…ample

Replace the argparse CLI with a minimal Environment definition that users
can build and push with `flyte build examples/image/ci_build_image.py env`.

Signed-off-by: Jeev B <[email protected]>
@pingsutw
Copy link
Copy Markdown
Member

pingsutw commented Mar 16, 2026

Thinking we should support bare images, not wrapped in Environment as well

+1

jeevb added 3 commits March 16, 2026 10:58
When a user derives from Image.from_debian_base() — via .clone(name=...)
or any with_*() chain — the clone inherited _BASE_REGISTRY
("ghcr.io/flyteorg"), a registry the user doesn't own. The clone should
have registry=None: a user-owned derivative whose push target is
determined by the build system, not by the SDK's registry constant.

clone() rule (condition 3 only):
  parent_registry = None if self.registry == _BASE_REGISTRY else self.registry
  registry = registry or parent_registry

This is clean because _get_default_image_for() now builds the base image
with registry=None during construction (so internal clone() calls never
trigger the strip), then stamps _BASE_REGISTRY explicitly at the end —
consistent with the existing object.__setattr__ pattern used for `tag`.

Result:
  from_debian_base()                  → registry=_BASE_REGISTRY (unchanged)
  from_debian_base().with_pip_packages() → registry=None
  from_debian_base().clone(name="ci") → registry=None
  .clone(registry="myreg", name="x")  → registry="myreg" (explicit wins)
Signed-off-by: Jeev B <[email protected]>
Remove tag= from from_debian_base(), from_dockerfile(), and
from_uv_script() — clone(tag=...) covers all cases and is the
cleaner, consistent API for pinning an explicit tag.
Dockerfile-based images are non-extendable so clone(tag=...) feels
awkward as the only way to pin a tag. Restore tag= directly on
from_dockerfile() as the natural place to set it.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants