func createMainVendored()

in cmd/go/functions_framework/main.go [326:415]


func createMainVendored(ctx *gcp.Context, fn fnInfo) error {
	l, err := ctx.Layer(gopathLayerName, gcp.BuildLayer)
	if err != nil {
		return fmt.Errorf("creating %v layer: %w", gopathLayerName, err)
	}
	gopath := ctx.ApplicationRoot()
	gopathSrc := filepath.Join(gopath, "src")
	if err := ctx.MkdirAll(gopathSrc, 0755); err != nil {
		return err
	}
	l.BuildEnvironment.Override(env.Buildable, appModule+"/main")
	l.BuildEnvironment.Override("GOPATH", gopath)
	l.BuildEnvironment.Override("GO111MODULE", "auto")
	if err := ctx.Setenv("GOPATH", gopath); err != nil {
		return err
	}

	appPath := filepath.Join(gopathSrc, appModule, "main")
	if err := ctx.MkdirAll(appPath, 0755); err != nil {
		return err
	}

	// We move the function source (including any vendored deps) into GOPATH.
	if err := ctx.Rename(fn.Source, filepath.Join(gopathSrc, fn.Package)); err != nil {
		return err
	}

	fnVendoredPath := filepath.Join(gopathSrc, fn.Package, "vendor")
	fnFrameworkVendoredPath := filepath.Join(fnVendoredPath, functionsFrameworkPackage)

	fnFrameworkVendoredPathExists, err := ctx.FileExists(fnFrameworkVendoredPath)
	if err != nil {
		return err
	}
	// Use v0.0.0 as the requested version for go.mod-less vendored builds, since we don't know and
	// can't really tell. This won't matter for Go 1.14+, since for those we'll have a go.mod file
	// regardless.
	requestedFrameworkVersion := "v0.0.0"
	injected := false
	if fnFrameworkVendoredPathExists {
		ctx.Logf("Found function with vendored dependencies including functions-framework")
		if _, err := ctx.Exec([]string{"cp", "-r", fnVendoredPath, appPath}, gcp.WithUserTimingAttribution); err != nil {
			return err
		}
	} else {
		// If the framework isn't in the user-provided vendor directory, we need to fetch it ourselves.
		ctx.Logf("Found function with vendored dependencies excluding functions-framework")
		if err := cloudfunctions.AssertFrameworkInjectionAllowed(); err != nil {
			return err
		}

		// Install the functions framework. Use `go mod vendor` to do this because that allows the
		// versions of all of the framework's dependencies to be pinned as specified in the framework's
		// go.mod. Using `go get` -- the usual way to install packages in GOPATH -- downloads each
		// repository at HEAD, which can lead to breakages.
		ctx.Warnf("Your vendored dependencies don't contain the functions-framework (%s) so a version will be auto-injected. Versioning conflicts might cause unexpected issues or crashes with your function. Fix this by adding a dependency on functions-framework (%s) and vendoring again.", functionsFrameworkPackage, functionsFrameworkPackage)
		ffDepsDir, err := ctx.TempDir("ffdeps")
		if err != nil {
			return fmt.Errorf("creating temp directory: %w", err)
		}

		cvt := filepath.Join(ctx.BuildpackRoot(), "converter", "without-framework")
		cmd := []string{
			fmt.Sprintf("cp --archive %s/. %s", cvt, ffDepsDir),
			// The only dependency is the functions framework.
			fmt.Sprintf("go mod edit -require %s@%s", functionsFrameworkModule, functionsFrameworkVersion),
			// Download dependencies and generate the go.sum file.
			"go mod tidy",
			// Prepare the vendor folder.
			"go mod vendor",
			// Copy the contents of the vendor dir into GOPATH/src.
			fmt.Sprintf("cp --archive vendor/. %s", gopathSrc),
		}
		if _, err := golang.ExecWithGoproxyFallback(ctx, []string{"/bin/bash", "-c", strings.Join(cmd, " && ")}, gcp.WithWorkDir(ffDepsDir), gcp.WithUserAttribution); err != nil {
			return fmt.Errorf("running command chain: %w", err)
		}

		// Since the user didn't pin it, we want the current version of the framework.
		requestedFrameworkVersion = functionsFrameworkVersion
		injected = true
	}

	cloudfunctions.AddFrameworkVersionLabel(ctx, &cloudfunctions.FrameworkVersionInfo{
		Runtime:  "go",
		Version:  requestedFrameworkVersion,
		Injected: injected,
	})

	return createMainGoFile(ctx, fn, filepath.Join(appPath, "main.go"), requestedFrameworkVersion)
}