Skip to content

Conversation

@ehdr
Copy link
Contributor

@ehdr ehdr commented Dec 12, 2025

Note

Adds force-build support (via MODAL_FORCE_BUILD and modal.toml force_build) and new optional forceBuild params across image APIs in JS/Go; deprecates JS secret arg; breaking: Go image methods now take Params structs.

  • Config/Profile
    • Read global force-build from MODAL_FORCE_BUILD env and force_build in ~/.modal.toml (modal-go/config.go, modal-js/src/config.ts).
  • Go SDK
    • Image APIs accept new params:
      • Images.FromRegistry(tag, *ImageFromRegistryParams) (adds ForceBuild and optional Secret).
      • Images.FromAwsEcr(tag, secret, *ImageFromAwsEcrParams) and Images.FromGcpArtifactRegistry(tag, secret, *ImageFromGcpArtifactRegistryParams) (add ForceBuild).
      • Image.Build(ctx, app, *ImageBuildParams) (adds ForceBuild).
    • Force-build is computed from profile/env, image-level, layer-level, and build params; propagates across layers.
    • Call sites updated (Sandbox.Create, examples, tests).
  • JS SDK
    • Add optional forceBuild to images.fromRegistry, images.fromAwsEcr, images.fromGcpArtifactRegistry, and Image.build.
    • Add secret to ImageFromRegistryParams; deprecate separate secret arg in fromRegistry(); update App.imageFromRegistry()/static helpers.
    • Implement force-build aggregation/propagation (profile/env → image → layers → build param).
    • Expose new types in index.ts.
  • Tests/Examples
    • Add/adjust tests to cover force-build from params, env, and propagation; update examples to new method signatures.
  • Changelog
    • Document new env/config options, JS additions, deprecation, and Go breaking changes.

Written by Cursor Bugbot for commit 65e541c. This will update automatically on new commits. Configure here.

@freider
Copy link
Contributor

freider commented Jan 21, 2026

Hmm.So annoying with the non-optionality of arguments in Go, feels like this isn't something that should have to be expressed in 99% of cases. Is the idea that nil should mean "defer to global setting" as opposed to false which is "don't force build even if global setting says to?"?

@ehdr
Copy link
Contributor Author

ehdr commented Jan 22, 2026

Yes, it would be the following:

  • Images.FromRegistry("alpine:3.21", nil) - will use an empty ImageFromRegistryParams, where all fields are initialized to their zero values, so ForceBuild: false
  • Images.FromRegistry("alpine:3.21", &modal.ImageFromRegistryParams{ForceBuild: false}) - equivalent but more explicitly ForceBuild: false.
  • Images.FromRegistry("alpine:3.21", &modal.ImageFromRegistryParams{ForceBuild: true}) - ForceBuild: true, obvs.

Copy link
Contributor

@thomasjpfan thomasjpfan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Besides the merge conflicts, I'm okay with this for a breaking 0.7 update.


// Build eagerly builds an Image on Modal.
func (image *Image) Build(ctx context.Context, app *App) (*Image, error) {
func (image *Image) Build(ctx context.Context, app *App, params *ImageBuildParams) (*Image, error) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Being able to force build everything feels like a DevX gotcha, that I'm not sure how to resolve.

If a developer force builds a registry image, then sandbox in production using that image with DockerfileCommands will run into higher latency because that image will be rebuilt.

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.

3 participants