custom-targets/git-ops/git-deployer/params.go (126 lines of code) (raw):
// Copyright 2023 Google LLC
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// https://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package main
import (
"fmt"
"os"
"strconv"
"time"
)
// Environment variable keys whose values determine the behavior of the Git deployer.
// Cloud Deploy transforms a deploy parameter "customTarget/gitRepo" into an
// environment variable of the form "CLOUD_DEPLOY_customTarget_gitRepo".
const (
gitRepoEnvKey = "CLOUD_DEPLOY_customTarget_gitRepo"
gitPathEnvKey = "CLOUD_DEPLOY_customTarget_gitPath"
gitSourceBranchEnvKey = "CLOUD_DEPLOY_customTarget_gitSourceBranch"
gitSecretEnvKey = "CLOUD_DEPLOY_customTarget_gitSecret"
gitUsernameEnvKey = "CLOUD_DEPLOY_customTarget_gitUsername"
gitEmailEnvKey = "CLOUD_DEPLOY_customTarget_gitEmail"
gitCommitMessageEnvKey = "CLOUD_DEPLOY_customTarget_gitCommitMessage"
gitDestinationBranchEnvKey = "CLOUD_DEPLOY_customTarget_gitDestinationBranch"
gitPullRequestTitleEnvKey = "CLOUD_DEPLOY_customTarget_gitPullRequestTitle"
gitPullRequestBodyEnvKey = "CLOUD_DEPLOY_customTarget_gitPullRequestBody"
gitEnablePullRequestMergeEnvKey = "CLOUD_DEPLOY_customTarget_gitEnablePullRequestMerge"
gitEnableArgoSyncPollEnvKey = "CLOUD_DEPLOY_customTarget_gitEnableArgoSyncPoll"
gitGKEClusterEnvKey = "CLOUD_DEPLOY_customTarget_gitGKECluster"
gitArgoAppEnvKey = "CLOUD_DEPLOY_customTarget_gitArgoApplication"
gitArgoNamespaceEnvKey = "CLOUD_DEPLOY_customTarget_gitArgoNamespace"
gitArgoSyncTimeoutEnvKey = "CLOUD_DEPLOY_customTarget_gitArgoSyncTimeout"
)
const (
// Default timeout to use when polling the sync status of the Argo application.
defaultSyncTimeout = 30 * time.Minute
// Default committer username when not provided.
defaultUsername = "Cloud Deploy"
)
type params struct {
// The URI of the Git repository, e.g. "github.com/{owner}/{repository}".
gitRepo string
// Relative path from the repository root where the manifest will be written. If not provided
// then defaults to the root of the repository with file name "manifest.yaml".
gitPath string
// The branch used for committing changes.
gitSourceBranch string
// The name of the Secret Manager SecretVersion resource used for cloning the Git repository
// and optionally opening pull requests.
gitSecret string
// The committer username. If not provided then defaults to "Cloud Deploy".
gitUsername string
// The commiter email. If not provided then the email address is left empty.
gitEmail string
// The commit message to use. If not provided then defaults to:
// "Delivery Pipeline: {pipeline-id} Release: {release-id} Rollout: {rollout-id}"
gitCommitMessage string
// The branch a pull request will be opened against. If not provided then no pull request is
// opened and the deploy completes upon the commit and push to the git source branch.
gitDestinationBranch string
// The title of the pull request. If not provided then defaults to:
// "Cloud Deploy: Release {release-id}, Rollout {rollout-id}"
gitPullRequestTitle string
// The body of the pull request. If not provided then defaults to:
// "Project: {project-num}
// Location: {location}
// Delivery Pipeline: {pipeline-id}
// Target: {target-id}
// Release: {release-id}
// Rollout: {rollout-id}"
gitPullRequestBody string
// Whether to merge the pull request opened against the gitDestintionBranch.
enablePullRequestMerge bool
// Whether to poll the sync status of an Argo Application. If enabled then the deploy only
// succeeds if the Argo Application is synced with the committed changes.
enableArgoSyncPoll bool
// The name of the GKE cluster hosting the Argo Application resource.
gkeCluster string
// The name of the Argo Application resource associated with the Git repository.
argoApp string
// The namespace the Argo Application resource resides in.
argoNamespace string
// Duration to poll the sync status of the Argo application. If not provided then defaults to
// 30 minutes.
argoSyncTimeout time.Duration
}
// determineParams returns the params provided in the execution environment via environment variables.
func determineParams() (*params, error) {
params := ¶ms{}
// Required parameters:
repo := os.Getenv(gitRepoEnvKey)
if len(repo) == 0 {
return nil, fmt.Errorf("parameter %q is required", gitRepoEnvKey)
}
params.gitRepo = repo
secret := os.Getenv(gitSecretEnvKey)
if len(secret) == 0 {
return nil, fmt.Errorf("parameter %q is required", gitSecretEnvKey)
}
params.gitSecret = secret
srcBranch := os.Getenv(gitSourceBranchEnvKey)
if len(srcBranch) == 0 {
return nil, fmt.Errorf("parameter %q is required", gitSourceBranchEnvKey)
}
params.gitSourceBranch = srcBranch
// Optional parameters:
params.gitPath = os.Getenv(gitPathEnvKey)
params.gitUsername = os.Getenv(gitUsernameEnvKey)
if len(params.gitUsername) == 0 {
params.gitUsername = defaultUsername
}
params.gitEmail = os.Getenv(gitEmailEnvKey)
params.gitCommitMessage = os.Getenv(gitCommitMessageEnvKey)
params.gitDestinationBranch = os.Getenv(gitDestinationBranchEnvKey)
params.gitPullRequestTitle = os.Getenv(gitPullRequestTitleEnvKey)
params.gitPullRequestBody = os.Getenv(gitPullRequestBodyEnvKey)
enablePRMerge := false
prm, ok := os.LookupEnv(gitEnablePullRequestMergeEnvKey)
if ok {
var err error
enablePRMerge, err = strconv.ParseBool(prm)
if err != nil {
return nil, fmt.Errorf("failed to parse parameter %q: %v", gitEnablePullRequestMergeEnvKey, err)
}
}
params.enablePullRequestMerge = enablePRMerge
enableSync := false
es, ok := os.LookupEnv(gitEnableArgoSyncPollEnvKey)
if ok {
var err error
enableSync, err = strconv.ParseBool(es)
if err != nil {
return nil, fmt.Errorf("failed to parse parameter %q: %v", gitEnableArgoSyncPollEnvKey, err)
}
}
params.enableArgoSyncPoll = enableSync
if enableSync {
// The pull request needs to be merged in order to poll the Argo Application status.
if !enablePRMerge {
return nil, fmt.Errorf("parameter %q must be true when Argo sync polling is enabled", gitEnablePullRequestMergeEnvKey)
}
// If Argo sync is enabled then some additional parameters become required:
gkeCluster := os.Getenv(gitGKEClusterEnvKey)
if len(gkeCluster) == 0 {
return nil, fmt.Errorf("parameter %q is required when Argo sync polling is enabled", gitGKEClusterEnvKey)
}
params.gkeCluster = gkeCluster
argoApp := os.Getenv(gitArgoAppEnvKey)
if len(argoApp) == 0 {
return nil, fmt.Errorf("parameter %q is required when Argo sync polling is enabled", gitArgoAppEnvKey)
}
params.argoApp = argoApp
argoNamespace := os.Getenv(gitArgoNamespaceEnvKey)
if len(argoNamespace) == 0 {
return nil, fmt.Errorf("parameter %q is required when Argo sync polling is enabled", gitArgoNamespaceEnvKey)
}
params.argoNamespace = argoNamespace
// Optional Argo sync parameters:
syncTimeout := defaultSyncTimeout
st := os.Getenv(gitArgoSyncTimeoutEnvKey)
if len(st) != 0 {
var err error
syncTimeout, err = time.ParseDuration(st)
if err != nil {
return nil, fmt.Errorf("failed to parse parameter %q: %v", gitArgoSyncTimeoutEnvKey, err)
}
}
params.argoSyncTimeout = syncTimeout
}
return params, nil
}