Skip to content

Commit da85045

Browse files
Warn when legacy .s2i/bin/assemble scaffolding is detected (#3584)
* Warn when legacy .s2i/bin/assemble scaffolding is detected Prior to #3436, func wrote S2I scaffolding for go/python to <func-root>/.s2i/bin/assemble. It now lives at .func/build/bin/assemble. The stale file can interfere with other builders (e.g. pack erroneously detects the assemble script). Add WarnIfLegacyS2IScaffolding helper in pkg/s2i that checks only scaffolded runtimes (go/python) and only the exact file func generated, so user-managed .s2i directories are not flagged. Call it from both the local Build() path and the remote PipelinesProvider.Run() path so the warning is emitted regardless of how the function is built. Fixes #3452 * Move legacy .s2i warning into Client.Build Per review feedback on #3584, the warning helper now lives in pkg/functions as a standalone WarnIfLegacyS2IScaffolding and is invoked from Client.Build, so it fires for every build (and therefore every local deploy) regardless of which builder the user switched to. The Tekton pipelines provider keeps its own call for remote deploys (which don't go through Client.Build) and no longer needs to import pkg/s2i. The s2i builder's redundant call is removed. The test moves to pkg/functions and exercises the helper directly. * Update pkg/functions/client.go Co-authored-by: David Fridrich <49119790+gauron99@users.noreply.github.com> * Update pkg/functions/function.go Co-authored-by: David Fridrich <49119790+gauron99@users.noreply.github.com> * Update pkg/functions/function_unit_test.go Co-authored-by: David Fridrich <49119790+gauron99@users.noreply.github.com> * Fix govet/staticcheck: drop unused Fprintf args in legacy s2i warning * Update pkg/functions/function.go Co-authored-by: David Fridrich <49119790+gauron99@users.noreply.github.com> * Update pkg/functions/function.go Co-authored-by: David Fridrich <49119790+gauron99@users.noreply.github.com> * Update pkg/functions/function.go Co-authored-by: David Fridrich <49119790+gauron99@users.noreply.github.com> * Update pkg/functions/function.go --------- Co-authored-by: David Fridrich <49119790+gauron99@users.noreply.github.com>
1 parent 07bdeaf commit da85045

File tree

4 files changed

+91
-0
lines changed

4 files changed

+91
-0
lines changed

pkg/functions/client.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -692,6 +692,11 @@ func BuildWithPlatforms(pp []Platform) BuildOption {
692692
// not contain a populated Image.
693693
func (c *Client) Build(ctx context.Context, f Function, options ...BuildOption) (Function, error) {
694694
fmt.Fprintf(os.Stderr, "Building function image\n")
695+
696+
// Warn if a func-generated legacy .s2i/bin/assemble file is left at the
697+
// function root (pre-1.21.2)
698+
WarnIfLegacyS2IScaffolding(f, os.Stderr)
699+
695700
ctx, cancel := context.WithCancel(ctx)
696701
defer cancel()
697702

pkg/functions/function.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package functions
33
import (
44
"errors"
55
"fmt"
6+
"io"
67
"os"
78
"path/filepath"
89
"reflect"
@@ -601,6 +602,24 @@ func (f Function) HasScaffolding() bool {
601602
return f.Runtime == "go" || f.Runtime == "python"
602603
}
603604

605+
// WarnIfLegacyS2IScaffolding writes a warning to 'w' when a legacy
606+
// .s2i/bin/assemble file is present at the function root of a scaffolded
607+
// runtime (go/python). This file was previously generated by func (see
608+
// https://github.com/knative/func/pull/3436) and can interfere with other
609+
// builders (mostly just pack).
610+
func WarnIfLegacyS2IScaffolding(f Function, w io.Writer) {
611+
if !f.HasScaffolding() {
612+
return
613+
}
614+
legacyAssemble := filepath.Join(f.Root, ".s2i", "bin", "assemble")
615+
if _, err := os.Stat(legacyAssemble); err == nil {
616+
fmt.Fprint(w, "Warning: a '.s2i/bin/assemble' file was detected at the function root. "+
617+
"This appears to be leftover func-generated scaffolding from older cli builds. "+
618+
"It may interfere with newer builds. "+
619+
"Please remove the '.s2i/' directory from your function root.\n")
620+
}
621+
}
622+
604623
// LabelsMap combines default labels with the labels slice provided.
605624
// It will the resulting slice with ValidateLabels and return a key/value map.
606625
// - key: EXAMPLE1 # Label directly from a value

pkg/functions/function_unit_test.go

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
package functions_test
22

33
import (
4+
"bytes"
45
"os"
56
"path/filepath"
67
"reflect"
8+
"strings"
79
"testing"
810

911
"gopkg.in/yaml.v2"
@@ -296,3 +298,63 @@ func expectedDefaultLabels(f fn.Function) map[string]string {
296298
fnlabels.FunctionRuntimeKey: f.Runtime,
297299
}
298300
}
301+
302+
// TestWarnIfLegacyS2IScaffolding ensures the warning is emitted only when a
303+
// func-generated legacy .s2i/bin/assemble file is present at the function root
304+
// for a scaffolded runtime (go/python).
305+
func Test_WarnIfLegacyS2IScaffolding(t *testing.T) {
306+
tests := []struct {
307+
name string
308+
runtime string
309+
createFile bool
310+
wantWarning bool
311+
}{
312+
{
313+
name: "scaffolded runtime with legacy assemble warns",
314+
runtime: "go",
315+
createFile: true,
316+
wantWarning: true,
317+
},
318+
{
319+
name: "non-scaffolded runtime with .s2i/bin/assemble does not warn",
320+
runtime: "node",
321+
createFile: true,
322+
wantWarning: false,
323+
},
324+
{
325+
name: "scaffolded runtime without legacy assemble does not warn",
326+
runtime: "go",
327+
createFile: false,
328+
wantWarning: false,
329+
},
330+
}
331+
332+
for _, tt := range tests {
333+
t.Run(tt.name, func(t *testing.T) {
334+
root, cleanup := Mktemp(t)
335+
t.Cleanup(cleanup)
336+
337+
if tt.createFile {
338+
binDir := filepath.Join(root, ".s2i", "bin")
339+
if err := os.MkdirAll(binDir, 0755); err != nil {
340+
t.Fatal(err)
341+
}
342+
if err := os.WriteFile(filepath.Join(binDir, "assemble"), []byte("#!/bin/bash"), 0700); err != nil {
343+
t.Fatal(err)
344+
}
345+
}
346+
347+
f := fn.Function{Root: root, Runtime: tt.runtime}
348+
var buf bytes.Buffer
349+
fn.WarnIfLegacyS2IScaffolding(f, &buf)
350+
351+
warned := strings.Contains(buf.String(), ".s2i/bin/assemble")
352+
if tt.wantWarning && !warned {
353+
t.Fatalf("expected a warning about .s2i/bin/assemble, got: %q", buf.String())
354+
}
355+
if !tt.wantWarning && warned {
356+
t.Fatalf("unexpected warning about .s2i/bin/assemble: %q", buf.String())
357+
}
358+
})
359+
}
360+
}

pkg/pipelines/tekton/pipelines_provider.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,11 @@ func (pp *PipelinesProvider) Run(ctx context.Context, f fn.Function) (string, fn
114114
return "", f, err
115115
}
116116

117+
// Warn if the func-generated legacy .s2i/bin/assemble exists; it will be
118+
// uploaded to the PVC and can interfere with the in-cluster build.
119+
// Remote deploy doesn't go through Client.Build, so we re-check here.
120+
fn.WarnIfLegacyS2IScaffolding(f, os.Stderr)
121+
117122
// Namespace is either a new namespace, specified as f.Namespace, or
118123
// the currently deployed namespace, recorded on f.Deploy.Namespace.
119124
// If neither exist, an error is returned (namespace is required)

0 commit comments

Comments
 (0)