func buildFn()

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)
}