You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: create.go
    path of file: ./repos/porter/cli/cmd/deploy
    
    the code of the file until where you have to start completion: package deploy

import (
	"context"
	"fmt"
	"os"
	"path/filepath"
	"strings"

	api "github.com/porter-dev/porter/api/client"
	"github.com/porter-dev/porter/api/types"
	"github.com/porter-dev/porter/cli/cmd/docker"
	"github.com/porter-dev/porter/internal/templater/utils"
)

// CreateAgent handles the creation of a new application on Porter
type CreateAgent struct {
	Client     api.Client
	CreateOpts *CreateOpts
}

// CreateOpts are required options for creating a new application on Porter: the
// "kind" (web, worker, job) and the name of the application.
type CreateOpts struct {
	*SharedOpts

	Kind        string
	ReleaseName string
	RegistryURL string

	// Suffix for the name of the image in the repository. By default the suffix is the
	// target namespace.
	RepoSuffix string
}

// GithubOpts are the options for linking a Github source to the app
type GithubOpts struct {
	Branch string
	Repo   string
}

// CreateFromGithub uses the branch/repo to link the Github source for an application.
// This function attempts to find a matching repository in the list of linked repositories
// on Porter. If one is found, it will use that repository as the app source.
func (c *CreateAgent) CreateFromGithub(
	ctx context.Context,
	ghOpts *GithubOpts,
	overrideValues map[string]interface{},
) (string, error) {
	opts := c.CreateOpts

	// get all linked github repos and find matching repo
	resp, err := c.Client.ListGitInstallationIDs(
		ctx,
		c.CreateOpts.ProjectID,
	)
	if err != nil {
		return "", err
	}

	gitInstal
    
func (c *CreateAgent) CreateSubdomainIfRequired(ctx context.Context, mergedValues map[string]interface{}) (string, error) {
	subdomain := ""

	// check for automatic subdomain creation if web kind
	if c.CreateOpts.Kind == "web" {
		// look for ingress.enabled and no custom domains set
		ingressMap, err := GetNestedMap(mergedValues, "ingress")

		if err == nil {
			enabledVal, enabledExists := ingressMap["enabled"]

			customDomVal, customDomExists := ingressMap["custom_domain"]

			if enabledExists && customDomExists {
				enabled, eOK := enabledVal.(bool)
				customDomain, cOK := customDomVal.(bool)

				if eOK && cOK && enabled {
					if customDomain {
						// return the first custom domain when one exists
						hostsArr, hostsExists := ingressMap["hosts"]

						if hostsExists {
							hostsArrVal, hostsArrOk := hostsArr.([]interface{})

							if hostsArrOk && len(hostsArrVal) > 0 {
								subdomainStr, ok := hostsArrVal[0].(string)

								if ok {
									subdomain = subdomainStr
								}
							}
						}
					} else {
						// in the case of ingress enabled but no custom domain, create subdomain
						dnsRecord, err := c.Client.CreateDNSRecord(
							ctx,
							c.CreateOpts.ProjectID,
							c.CreateOpts.ClusterID,
							c.CreateOpts.Namespace,
							c.CreateOpts.ReleaseName,
						)
						if err != nil {
							return "", fmt.Errorf("Error creating subdomain: %s", err.Error())
						}

						subdomain = dnsRecord.ExternalURL

						if ingressVal, ok := mergedValues["ingress"]; !ok {
							mergedValues["ingress"] = map[string]interface{}{
								"porter_hosts": []string{
									subdomain,
								},
							}
						} else {
							ingressValMap := ingressVal.(map[string]interface{})

							ingressValMap["porter_hosts"] = []string{
								subdomain,
							}
						}
					}
				}
			}
		}
	}

	return subdomain, nil
}