in cmd/go/functions_framework/main.go [80:149]
func buildFn(ctx *gcp.Context) error {
l, err := ctx.Layer(layerName, gcp.LaunchLayer)
if err != nil {
return fmt.Errorf("creating %v layer: %w", layerName, err)
}
if err := ctx.SetFunctionsEnvVars(l); err != nil {
return err
}
ctx.AddWebProcess([]string{golang.OutBin})
fnTarget := os.Getenv(env.FunctionTarget)
// Move the function source code into a subdirectory.
if err := ctx.RemoveAll(fnSourceDir); err != nil {
return err
}
if err := ctx.MkdirAll(fnSourceDir, 0755); err != nil {
return err
}
wd, err := os.Getwd()
if err != nil {
return gcp.InternalErrorf("getting current directory: %w", err)
}
if err := fileutil.MaybeMovePathContents(fnSourceDir, wd, func(path string, d fs.DirEntry) (bool, error) {
name := filepath.Base(path)
// Exclude serverless_function_source_code and .google* dir e.g. .googlebuild, .googleconfig
return name != fnSourceDir && !strings.HasPrefix(name, ".google"), nil
}); err != nil {
return gcp.InternalErrorf("unable to move source code to build directory: %v", err)
}
fnSource := filepath.Join(ctx.ApplicationRoot(), fnSourceDir)
pkg, err := extractPackageNameInDir(ctx, fnSource)
if err != nil {
return gcp.UserErrorf("error extracting package name: %v", err)
}
fn := fnInfo{
Source: fnSource,
Target: fnTarget,
Package: pkg.Name,
Imports: pkg.Imports,
}
goMod := filepath.Join(fn.Source, "go.mod")
goModExists, err := ctx.FileExists(goMod)
if err != nil {
return err
}
if !goModExists {
return createMainVendored(ctx, fn)
}
isWriteable, err := ctx.IsWritable(goMod)
if err != nil {
return err
}
if !isWriteable {
// Preempt an obscure failure mode: if go.mod is not writable then `go list -m` can fail saying:
// go: updates to go.sum needed, disabled by -mod=readonly
return gcp.UserErrorf("go.mod exists but is not writable")
}
vendorExists, err := ctx.FileExists(fn.Source, "vendor")
if err != nil {
return err
}
if vendorExists {
return createMainGoModVendored(ctx, fn)
}
return createMainGoMod(ctx, fn)
}