func buildFn()

in cmd/go/gomod/main.go [42:102]


func buildFn(ctx *gcp.Context) error {
	l, err := golang.NewGoWorkspaceLayer(ctx)
	if err != nil {
		return fmt.Errorf("creating GOPATH layer: %w", err)
	}

	vendorExists, err := ctx.FileExists("vendor")
	if err != nil {
		return err
	}
	// When there's a vendor folder and go is 1.14+, we shouldn't download the modules
	// and let go build use the vendored dependencies.
	if vendorExists {
		avSupport, err := golang.SupportsAutoVendor(ctx)
		if err != nil {
			return fmt.Errorf("checking for auto vendor support: %w", err)
		}
		if avSupport {
			ctx.Logf("Not downloading modules because there's a `vendor` directory")
			return nil
		}

		ctx.Warnf(`Ignoring "vendor" directory: To use vendor directory, the Go runtime must be 1.14+ and go.mod must contain a "go 1.14"+ entry. See https://cloud.google.com/appengine/docs/standard/go/specifying-dependencies#vendoring_dependencies.`)
	}

	goModIsWriteable, err := ctx.IsWritable("go.mod")
	if err != nil {
		return err
	}
	if !goModIsWriteable {
		// 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")
	}
	env := []string{"GOPATH=" + l.Path, "GO111MODULE=on"}

	// BuildDirEnv should only be set by App Engine buildpacks.
	workdir := os.Getenv(golang.BuildDirEnv)
	if workdir == "" {
		workdir = ctx.ApplicationRoot()
	}

	goSumExists, err := ctx.FileExists("go.sum")
	if err != nil {
		return err
	}
	// Go 1.16+ requires a go.sum file. If one does not exist, generate it.
	// go build -mod=readonly requires a complete graph of modules which `go mod download` does not produce in all cases (https://golang.org/issue/35832).
	if !goSumExists {
		ctx.Logf(`go.sum not found, generating using "go mod tidy"`)
		if _, err := golang.ExecWithGoproxyFallback(ctx, []string{"go", "mod", "tidy"}, gcp.WithEnv(env...), gcp.WithWorkDir(workdir), gcp.WithUserAttribution); err != nil {
			return fmt.Errorf("running go mod tidy: %w", err)
		}
	}

	if _, err := golang.ExecWithGoproxyFallback(ctx, []string{"go", "mod", "download"}, gcp.WithEnv(env...), gcp.WithUserAttribution); err != nil {
		return fmt.Errorf("running go mod download: %w", err)
	}

	return nil
}