Procházet zdrojové kódy

Merge branch 'beta.3.create-image-repo-ci' of https://github.com/porter-dev/porter into beta.3.frontend-integration

jusrhee před 5 roky
rodič
revize
1dec04ae5d

+ 13 - 9
internal/forms/git_action.go

@@ -7,11 +7,13 @@ import (
 // CreateGitAction represents the accepted values for creating a
 // github action integration
 type CreateGitAction struct {
-	ReleaseID      uint   `json:"release_id" form:"required"`
-	GitRepo        string `json:"git_repo" form:"required"`
-	ImageRepoURI   string `json:"image_repo_uri" form:"required"`
-	DockerfilePath string `json:"dockerfile_path" form:"required"`
-	GitRepoID      uint   `json:"git_repo_id" form:"required"`
+	ReleaseID      uint              `json:"release_id" form:"required"`
+	GitRepo        string            `json:"git_repo" form:"required"`
+	ImageRepoURI   string            `json:"image_repo_uri" form:"required"`
+	DockerfilePath string            `json:"dockerfile_path" form:"required"`
+	GitRepoID      uint              `json:"git_repo_id" form:"required"`
+	BuildEnv       map[string]string `json:"env"`
+	RegistryID     uint              `json:"registry_id"`
 }
 
 // ToGitActionConfig converts the form to a gorm git action config model
@@ -26,8 +28,10 @@ func (ca *CreateGitAction) ToGitActionConfig() (*models.GitActionConfig, error)
 }
 
 type CreateGitActionOptional struct {
-	GitRepo        string `json:"git_repo"`
-	ImageRepoURI   string `json:"image_repo_uri"`
-	DockerfilePath string `json:"dockerfile_path"`
-	GitRepoID      uint   `json:"git_repo_id"`
+	GitRepo        string            `json:"git_repo"`
+	ImageRepoURI   string            `json:"image_repo_uri"`
+	DockerfilePath string            `json:"dockerfile_path"`
+	GitRepoID      uint              `json:"git_repo_id"`
+	BuildEnv       map[string]string `json:"env"`
+	RegistryID     uint              `json:"registry_id"`
 }

+ 28 - 1
internal/integrations/ci/actions/actions.go

@@ -26,6 +26,7 @@ type GithubActions struct {
 
 	WebhookToken string
 	PorterToken  string
+	BuildEnv     map[string]string
 	ProjectID    uint
 	ReleaseName  string
 
@@ -69,6 +70,13 @@ func (g *GithubActions) Setup() (string, error) {
 		return "", err
 	}
 
+	// create a new secret with the build variables
+	err = g.createEnvSecret(client)
+
+	if err != nil {
+		return "", err
+	}
+
 	fileBytes, err := g.GetGithubActionYAML()
 
 	if err != nil {
@@ -123,7 +131,7 @@ func (g *GithubActions) GetGithubActionYAML() ([]byte, error) {
 					getCheckoutCodeStep(),
 					getDownloadPorterStep(),
 					getConfigurePorterStep(g.getPorterTokenSecretName()),
-					getDockerBuildPushStep(g.DockerFilePath, g.ImageRepoURL),
+					getDockerBuildPushStep(g.getBuildEnvSecretName(), g.DockerFilePath, g.ImageRepoURL),
 					deployPorterWebhookStep(g.getWebhookSecretName(), g.ImageRepoURL),
 				},
 			},
@@ -195,12 +203,31 @@ func (g *GithubActions) createGithubSecret(
 	return nil
 }
 
+func (g *GithubActions) createEnvSecret(client *github.Client) error {
+	// convert the env object to a string
+	lines := make([]string, 0)
+
+	for key, val := range g.BuildEnv {
+		lines = append(lines, fmt.Sprintf(`%s=%s`, key, val))
+	}
+
+	secretName := g.getBuildEnvSecretName()
+
+	return g.createGithubSecret(client, secretName, strings.Join(lines, "\n"))
+}
+
 func (g *GithubActions) getWebhookSecretName() string {
 	return fmt.Sprintf("WEBHOOK_%s", strings.Replace(
 		strings.ToUpper(g.ReleaseName), "-", "_", -1),
 	)
 }
 
+func (g *GithubActions) getBuildEnvSecretName() string {
+	return fmt.Sprintf("ENV_%s", strings.Replace(
+		strings.ToUpper(g.ReleaseName), "-", "_", -1),
+	)
+}
+
 func (g *GithubActions) getPorterYMLFileName() string {
 	return fmt.Sprintf("porter_%s.yml", strings.Replace(
 		strings.ToLower(g.ReleaseName), "-", "_", -1),

+ 3 - 2
internal/integrations/ci/actions/steps.go

@@ -41,15 +41,16 @@ func getConfigurePorterStep(porterTokenSecretName string) GithubActionYAMLStep {
 }
 
 const dockerBuildPush string = `
+export $(echo "${{secrets.%s}}" | xargs)
 docker build . --file %s -t %s:$(git rev-parse --short HEAD)
 docker push %s:$(git rev-parse --short HEAD)
 `
 
-func getDockerBuildPushStep(dockerFilePath, repoURL string) GithubActionYAMLStep {
+func getDockerBuildPushStep(envSecretName, dockerFilePath, repoURL string) GithubActionYAMLStep {
 	return GithubActionYAMLStep{
 		Name: "Docker build, push",
 		ID:   "docker_build_push",
-		Run:  fmt.Sprintf(dockerBuildPush, dockerFilePath, repoURL, repoURL),
+		Run:  fmt.Sprintf(envSecretName, dockerBuildPush, dockerFilePath, repoURL, repoURL),
 	}
 }
 

+ 42 - 0
internal/registry/registry.go

@@ -373,6 +373,48 @@ func (r *Registry) setTokenCacheFunc(
 	}
 }
 
+// CreateRepository creates a repository for a registry, if needed
+// (currently only required for ECR)
+func (r *Registry) CreateRepository(
+	repo repository.Repository,
+	name string,
+) error {
+	// if aws, create repository
+	if r.AWSIntegrationID != 0 {
+		return r.createECRRepository(repo, name)
+	}
+
+	// otherwise, no-op
+	return nil
+}
+
+func (r *Registry) createECRRepository(
+	repo repository.Repository,
+	name string,
+) error {
+	aws, err := repo.AWSIntegration.ReadAWSIntegration(
+		r.AWSIntegrationID,
+	)
+
+	if err != nil {
+		return err
+	}
+
+	sess, err := aws.GetSession()
+
+	if err != nil {
+		return err
+	}
+
+	svc := ecr.New(sess)
+
+	_, err = svc.CreateRepository(&ecr.CreateRepositoryInput{
+		RepositoryName: &name,
+	})
+
+	return err
+}
+
 // ListImages lists the images for an image repository
 func (r *Registry) ListImages(
 	repoName string,

+ 2 - 0
server/api/deploy_handler.go

@@ -146,6 +146,8 @@ func (app *App) HandleDeployTemplate(w http.ResponseWriter, r *http.Request) {
 			ImageRepoURI:   form.GithubActionConfig.ImageRepoURI,
 			DockerfilePath: form.GithubActionConfig.DockerfilePath,
 			GitRepoID:      form.GithubActionConfig.GitRepoID,
+			BuildEnv:       form.GithubActionConfig.BuildEnv,
+			RegistryID:     form.GithubActionConfig.RegistryID,
 		}
 
 		// validate the form

+ 29 - 0
server/api/git_action_handler.go

@@ -13,6 +13,7 @@ import (
 	"github.com/porter-dev/porter/internal/forms"
 	"github.com/porter-dev/porter/internal/integrations/ci/actions"
 	"github.com/porter-dev/porter/internal/models"
+	"github.com/porter-dev/porter/internal/registry"
 )
 
 // HandleCreateGitAction creates a new Github action in a repository for a given
@@ -81,6 +82,33 @@ func (app *App) createGitActionFromForm(
 		return nil
 	}
 
+	// if the registry was provisioned through Porter, create a repository if necessary
+	if form.RegistryID != 0 {
+		// read the registry
+		reg, err := app.Repo.Registry.ReadRegistry(form.RegistryID)
+
+		if err != nil {
+			app.handleErrorDataRead(err, w)
+			return nil
+		}
+
+		if reg.InfraID != 0 {
+			_reg := registry.Registry(*reg)
+			regAPI := &_reg
+
+			// parse the name from the registry
+			nameSpl := strings.Split(form.ImageRepoURI, "/")
+			repoName := nameSpl[len(nameSpl)-1]
+
+			err := regAPI.CreateRepository(*app.Repo, repoName)
+
+			if err != nil {
+				app.handleErrorInternal(err, w)
+				return nil
+			}
+		}
+	}
+
 	// convert the form to a git action config
 	gitAction, err := form.ToGitActionConfig()
 
@@ -138,6 +166,7 @@ func (app *App) createGitActionFromForm(
 		DockerFilePath: gitAction.DockerfilePath,
 		ImageRepoURL:   gitAction.ImageRepoURI,
 		PorterToken:    encoded,
+		BuildEnv:       form.BuildEnv,
 	}
 
 	_, err = gaRunner.Setup()