Skip to content

Commit 30b55f3

Browse files
authored
feat: force order of plan entries processing (#59)
From time to time, the build function receives the plan entries out of order. This implementation will ensure that pip is installed before pipenv or poetry.
1 parent 946a868 commit 30b55f3

File tree

2 files changed

+133
-65
lines changed

2 files changed

+133
-65
lines changed

build.go

Lines changed: 71 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -34,72 +34,78 @@ func Build(
3434

3535
var results []packit.BuildResult
3636

37-
for _, entry := range context.Plan.Entries {
38-
logger.Title("Handling %s", entry.Name)
39-
parameters, ok := buildParameters[entry.Name]
40-
41-
if !ok {
42-
return packit.BuildResult{}, packit.Fail.WithMessage("missing parameters for: %s", entry.Name)
43-
}
44-
45-
switch entry.Name {
46-
case pip.Pip:
47-
result, err := pip.Build(
48-
parameters.(pip.PipBuildParameters),
49-
commonBuildParameters,
50-
)(context)
51-
52-
if err != nil {
53-
return packit.BuildResult{}, err
37+
orderedInstallers := []string{pip.Pip, pipenv.Pipenv, poetry.PoetryDependency, miniconda.Conda, uv.Uv}
38+
39+
for _, installer := range orderedInstallers {
40+
for _, entry := range context.Plan.Entries {
41+
if entry.Name == installer {
42+
logger.Title("Handling %s", entry.Name)
43+
parameters, ok := buildParameters[entry.Name]
44+
45+
if !ok {
46+
return packit.BuildResult{}, packit.Fail.WithMessage("missing parameters for: %s", entry.Name)
47+
}
48+
49+
switch entry.Name {
50+
case pip.Pip:
51+
result, err := pip.Build(
52+
parameters.(pip.PipBuildParameters),
53+
commonBuildParameters,
54+
)(context)
55+
56+
if err != nil {
57+
return packit.BuildResult{}, err
58+
}
59+
results = append(results, result)
60+
61+
case pipenv.Pipenv:
62+
result, err := pipenv.Build(
63+
parameters.(pipenv.PipEnvBuildParameters),
64+
commonBuildParameters,
65+
)(context)
66+
67+
if err != nil {
68+
return packit.BuildResult{}, err
69+
}
70+
results = append(results, result)
71+
72+
case poetry.PoetryDependency:
73+
result, err := poetry.Build(
74+
parameters.(poetry.PoetryBuildParameters),
75+
commonBuildParameters,
76+
)(context)
77+
78+
if err != nil {
79+
return packit.BuildResult{}, err
80+
}
81+
results = append(results, result)
82+
83+
case miniconda.Conda:
84+
result, err := miniconda.Build(
85+
parameters.(miniconda.CondaBuildParameters),
86+
commonBuildParameters,
87+
)(context)
88+
89+
if err != nil {
90+
return packit.BuildResult{}, err
91+
}
92+
results = append(results, result)
93+
94+
case uv.Uv:
95+
result, err := uv.Build(
96+
parameters.(uv.UvBuildParameters),
97+
commonBuildParameters,
98+
)(context)
99+
100+
if err != nil {
101+
return packit.BuildResult{}, err
102+
}
103+
results = append(results, result)
104+
105+
default:
106+
return packit.BuildResult{}, packit.Fail.WithMessage("unknown plan: %s", entry.Name)
107+
}
54108
}
55-
results = append(results, result)
56-
57-
case pipenv.Pipenv:
58-
result, err := pipenv.Build(
59-
parameters.(pipenv.PipEnvBuildParameters),
60-
commonBuildParameters,
61-
)(context)
62-
63-
if err != nil {
64-
return packit.BuildResult{}, err
65-
}
66-
results = append(results, result)
67-
68-
case miniconda.Conda:
69-
result, err := miniconda.Build(
70-
parameters.(miniconda.CondaBuildParameters),
71-
commonBuildParameters,
72-
)(context)
73-
74-
if err != nil {
75-
return packit.BuildResult{}, err
76-
}
77-
results = append(results, result)
78-
79-
case poetry.PoetryDependency:
80-
result, err := poetry.Build(
81-
parameters.(poetry.PoetryBuildParameters),
82-
commonBuildParameters,
83-
)(context)
84-
85-
if err != nil {
86-
return packit.BuildResult{}, err
87-
}
88-
results = append(results, result)
89-
90-
case uv.Uv:
91-
result, err := uv.Build(
92-
parameters.(uv.UvBuildParameters),
93-
commonBuildParameters,
94-
)(context)
95-
96-
if err != nil {
97-
return packit.BuildResult{}, err
98-
}
99-
results = append(results, result)
100-
101-
default:
102-
return packit.BuildResult{}, packit.Fail.WithMessage("unknown plan: %s", entry.Name)
103109
}
104110
}
105111

build_test.go

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,32 @@ func testBuild(t *testing.T, context spec.G, it spec.S) {
350350
},
351351
1,
352352
},
353+
{
354+
packit.BuildpackPlan{
355+
Entries: []packit.BuildpackPlanEntry{
356+
{
357+
Name: pip.Pip,
358+
},
359+
{
360+
Name: pipenv.Pipenv,
361+
},
362+
},
363+
},
364+
3,
365+
},
366+
{
367+
packit.BuildpackPlan{
368+
Entries: []packit.BuildpackPlanEntry{
369+
{
370+
Name: pip.Pip,
371+
},
372+
{
373+
Name: poetry.PoetryDependency,
374+
},
375+
},
376+
},
377+
3,
378+
},
353379
}
354380
Expect(os.WriteFile(filepath.Join(workingDir, "x.py"), []byte{}, os.ModePerm)).To(Succeed())
355381
Expect(os.WriteFile(filepath.Join(workingDir, "pyproject.toml"), []byte(""), 0755)).To(Succeed())
@@ -368,6 +394,42 @@ func testBuild(t *testing.T, context spec.G, it spec.S) {
368394
}
369395
})
370396

397+
it("runs the build process and returns layers in expected order", func() {
398+
orderTestPlans := []packit.BuildpackPlan{
399+
{
400+
Entries: []packit.BuildpackPlanEntry{
401+
{
402+
Name: pipenv.Pipenv,
403+
},
404+
{
405+
Name: pip.Pip,
406+
},
407+
},
408+
},
409+
{
410+
Entries: []packit.BuildpackPlanEntry{
411+
{
412+
Name: poetry.PoetryDependency,
413+
},
414+
{
415+
Name: pip.Pip,
416+
},
417+
},
418+
},
419+
}
420+
for _, testPlan := range orderTestPlans {
421+
logger.Detail("Doing: %s", testPlan)
422+
buildContext.Plan = testPlan
423+
result, err := build(buildContext)
424+
Expect(err).NotTo(HaveOccurred())
425+
426+
layers := result.Layers
427+
Expect(layers[0].Name).To(Equal(pip.Pip))
428+
// Pip adds two layers
429+
Expect(layers[2].Name).To(Equal(testPlan.Entries[0].Name))
430+
}
431+
})
432+
371433
it("fails if packager parameters is missing", func() {
372434
packagerParameters := map[string]pythoninstallers.PackagerParameters{}
373435

0 commit comments

Comments
 (0)