Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 47 additions & 0 deletions core/core.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,10 @@ func GenerateBuildPlan(app *app.App, env *app.Environment, options *GenerateBuil
return &BuildResult{Success: false, Logs: logger.Logs}
}

if err := addAdditionalMiseToolsToPackages(ctx, ctx.GetMiseStepBuilder(), resolvedPackages); err != nil {
logger.LogWarn("Failed to include additional tools from mise.toml in package output: %s", err.Error())
}

if providerToUse != nil {
providerToUse.CleansePlan(buildPlan)
}
Expand Down Expand Up @@ -311,3 +315,46 @@ func getProviders(ctx *generate.GenerateContext, config *c.Config) (providers.Pr

return providerToUse, detectedProvider
}

// Adds app-local mise.toml tools to the package output table.
func addAdditionalMiseToolsToPackages(
ctx *generate.GenerateContext,
miseStep *generate.MiseStepBuilder,
resolvedPackages map[string]*resolver.ResolvedPackage,
) error {
misePackages, err := miseStep.GetMisePackageVersionsCached(ctx)
if err != nil {
return err
}

addAdditionalMiseToolsFromPackages(misePackages, resolvedPackages)
return nil
}

// Merges non-provider mise.toml tools into resolved package rows.
func addAdditionalMiseToolsFromPackages(
misePackages map[string]*generate.MisePackageInfo,
resolvedPackages map[string]*resolver.ResolvedPackage,
) {
for _, name := range slices.Sorted(maps.Keys(misePackages)) {
pkg := misePackages[name]
if pkg == nil || pkg.Source != "mise.toml" {
continue
}
if _, exists := resolvedPackages[name]; exists {
continue
}

version := pkg.Version
var requestedVersion *string
if pkg.RequestedVersion != "" {
requestedVersion = &pkg.RequestedVersion
}
resolvedPackages[name] = &resolver.ResolvedPackage{
Name: name,
RequestedVersion: requestedVersion,
ResolvedVersion: &version,
Source: "mise.toml",
}
}
}
41 changes: 41 additions & 0 deletions core/core_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ import (

"github.com/gkampitakis/go-snaps/snaps"
"github.com/railwayapp/railpack/core/app"
"github.com/railwayapp/railpack/core/generate"
"github.com/railwayapp/railpack/core/logger"
"github.com/railwayapp/railpack/core/resolver"
"github.com/stretchr/testify/require"
)

Expand Down Expand Up @@ -105,3 +107,42 @@ func TestGenerateBuildPlan_DockerignoreMetadata(t *testing.T) {
require.NotNil(t, buildResult.Metadata)
require.Equal(t, "true", buildResult.Metadata["dockerIgnore"])
}

func TestAddAdditionalMiseToolsToPackages(t *testing.T) {
nodeVersion := "24.0.0"
bunVersion := "1.3.10"

// Simulate what provider already resolved (node + bun already in table)
resolvedPackages := map[string]*resolver.ResolvedPackage{
"node": {Name: "node", ResolvedVersion: &nodeVersion, Source: "mise.toml"},
"bun": {Name: "bun", ResolvedVersion: &bunVersion, Source: "mise.toml"},
}

// Simulate what mise returns from app mise.toml
misePackages := map[string]*generate.MisePackageInfo{
"node": {Version: "24.0.0", RequestedVersion: "24", Source: "mise.toml"},
"bun": {Version: "1.3.10", RequestedVersion: "latest", Source: "mise.toml"},
"python": {Version: "3.13.0", RequestedVersion: "3.13", Source: "mise.toml"},
"go": {Version: "1.23.0", RequestedVersion: "1.23", Source: "mise.toml"},
}

addAdditionalMiseToolsFromPackages(misePackages, resolvedPackages)

// node and bun should remain unchanged
require.Equal(t, "mise.toml", resolvedPackages["node"].Source)
require.Equal(t, "mise.toml", resolvedPackages["bun"].Source)

// python and go should be added with requested versions from app mise.toml
require.Contains(t, resolvedPackages, "python")
require.Equal(t, "mise.toml", resolvedPackages["python"].Source)
require.Equal(t, "3.13.0", *resolvedPackages["python"].ResolvedVersion)
require.Equal(t, "3.13", *resolvedPackages["python"].RequestedVersion)

require.Contains(t, resolvedPackages, "go")
require.Equal(t, "mise.toml", resolvedPackages["go"].Source)
require.Equal(t, "1.23.0", *resolvedPackages["go"].ResolvedVersion)
require.Equal(t, "1.23", *resolvedPackages["go"].RequestedVersion)

// total should now be 4
require.Len(t, resolvedPackages, 4)
}
26 changes: 22 additions & 4 deletions core/generate/mise_step_builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,9 @@ var (

// represents a app-local mise package
type MisePackageInfo struct {
Version string
Source string
Version string
RequestedVersion string

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

why did we need this?

Source string
}

// MiseListSource represents the source of a mise tool installation
Expand Down Expand Up @@ -61,6 +62,7 @@ type MiseStepBuilder struct {
Variables map[string]string
app *a.App
env *a.Environment
cachedMisePackages map[string]*MisePackageInfo
}

func (c *GenerateContext) NewMiseStepBuilder(displayName string) *MiseStepBuilder {
Expand Down Expand Up @@ -161,7 +163,8 @@ func (b *MiseStepBuilder) GetMisePackageVersions(ctx *GenerateContext) (map[stri
if len(appDirTools) > 0 {
firstTool := appDirTools[0]
packages[toolName] = &MisePackageInfo{
Version: firstTool.Version,
Version: firstTool.Version,
RequestedVersion: firstTool.RequestedVersion,
// include the source so we can surface this to the user so they understand where the package version came from
Source: firstTool.Source.Type,
}
Expand All @@ -171,9 +174,24 @@ func (b *MiseStepBuilder) GetMisePackageVersions(ctx *GenerateContext) (map[stri
return packages, nil
}

// Reuses the mise package list to avoid duplicate mise invocations.
func (b *MiseStepBuilder) GetMisePackageVersionsCached(ctx *GenerateContext) (map[string]*MisePackageInfo, error) {
if b.cachedMisePackages != nil {
return b.cachedMisePackages, nil
}

misePackages, err := b.GetMisePackageVersions(ctx)
if err != nil {
return nil, err
}

b.cachedMisePackages = misePackages
return misePackages, nil
}

// Use mise-specified versions for all packages in the input list
func (b *MiseStepBuilder) UseMiseVersions(ctx *GenerateContext, packages []string) {
miseVersions, err := b.GetMisePackageVersions(ctx)
miseVersions, err := b.GetMisePackageVersionsCached(ctx)
if err != nil {
ctx.Logger.LogWarn("Failed to get package versions from mise: %s", err.Error())
return
Expand Down
Loading