Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion tool/actions-plan-preview/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ RUN go mod download
COPY . ./
RUN go build -o /plan-preview .

FROM ghcr.io/pipe-cd/pipectl:v0.43.1
FROM ghcr.io/pipe-cd/pipectl:v0.53.0
COPY --from=builder /plan-preview /
ENV PATH=$PATH:/app/cmd/pipectl
RUN chmod +x /plan-preview
Expand Down
9 changes: 7 additions & 2 deletions tool/actions-plan-preview/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,22 @@ go 1.24.1

require (
github.com/google/go-github/v36 v36.0.0
github.com/pipe-cd/pipecd v0.53.0
github.com/shurcooL/githubv4 v0.0.0-20220115235240-a14260e6f8a2
github.com/stretchr/testify v1.7.0
github.com/stretchr/testify v1.10.0
golang.org/x/oauth2 v0.27.0
)

require (
github.com/davecgh/go-spew v1.1.0 // indirect
github.com/coreos/go-oidc/v3 v3.11.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/envoyproxy/protoc-gen-validate v1.0.4 // indirect
github.com/go-jose/go-jose/v4 v4.0.5 // indirect
github.com/google/go-querystring v1.0.0 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/shurcooL/graphql v0.0.0-20200928012149-18c5c3165e3a // indirect
golang.org/x/crypto v0.36.0 // indirect
golang.org/x/net v0.38.0 // indirect
google.golang.org/protobuf v1.34.2 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
24 changes: 16 additions & 8 deletions tool/actions-plan-preview/go.sum
Original file line number Diff line number Diff line change
@@ -1,22 +1,29 @@
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/coreos/go-oidc/v3 v3.11.0 h1:Ia3MxdwpSw702YW0xgfmP1GVCMA9aEFWu12XUZ3/OtI=
github.com/coreos/go-oidc/v3 v3.11.0/go.mod h1:gE3LgjOgFoHi9a4ce4/tJczr0Ai2/BoDhf0r5lltWI0=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/envoyproxy/protoc-gen-validate v1.0.4 h1:gVPz/FMfvh57HdSJQyvBtF00j8JU4zdyUgIUNhlgg0A=
github.com/envoyproxy/protoc-gen-validate v1.0.4/go.mod h1:qys6tmnRsYrQqIhm2bvKZH4Blx/1gTIZ2UKVY1M+Yew=
github.com/go-jose/go-jose/v4 v4.0.5 h1:M6T8+mKZl/+fNNuFHvGIzDz7BTLQPIounk/b9dw3AaE=
github.com/go-jose/go-jose/v4 v4.0.5/go.mod h1:s3P1lRrkT8igV8D9OjyL4WRyHvjB6a4JSllnOrmmBOA=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/go-github/v36 v36.0.0 h1:ndCzM616/oijwufI7nBRa+5eZHLldT+4yIB68ib5ogs=
github.com/google/go-github/v36 v36.0.0/go.mod h1:LFlKC047IOqiglRGNqNb9s/iAPTnnjtlshm+bxp+kwk=
github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk=
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
github.com/pipe-cd/pipecd v0.53.0 h1:q6AiDhPFsS0enAehvn2UTVJMKfdnLDPB1BNo6Pr+FgQ=
github.com/pipe-cd/pipecd v0.53.0/go.mod h1:BI0uxrpeuxcjFykL5+tnLc5DRd8v24Hm/it7fBOth6Y=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/shurcooL/githubv4 v0.0.0-20220115235240-a14260e6f8a2 h1:82EIpiGB79OIPgSGa63Oj4Ipf+YAX1c6A9qjmEYoRXc=
github.com/shurcooL/githubv4 v0.0.0-20220115235240-a14260e6f8a2/go.mod h1:hAF0iLZy4td2EX+/8Tw+4nodhlMrwN3HupfaXj3zkGo=
github.com/shurcooL/graphql v0.0.0-20200928012149-18c5c3165e3a h1:KikTa6HtAK8cS1qjvUvvq4QO21QnwC+EfvB+OAuZ/ZU=
github.com/shurcooL/graphql v0.0.0-20200928012149-18c5c3165e3a/go.mod h1:AuYgA5Kyo4c7HfUmvRGs/6rGlMMV/6B1bVnB9JxJEEg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34=
golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc=
Expand All @@ -30,8 +37,9 @@ golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5h
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
160 changes: 116 additions & 44 deletions tool/actions-plan-preview/planpreview.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ import (
"unicode/utf8"

"github.com/shurcooL/githubv4"

"github.com/pipe-cd/pipecd/pkg/model"
)

type PlanPreviewResult struct {
Expand All @@ -47,9 +49,13 @@ func (r *PlanPreviewResult) NoChange() bool {
type ApplicationResult struct {
ApplicationInfo
SyncStrategy string // QUICK_SYNC, PIPELINE
PlanSummary string
PlanDetails string
NoChange bool
// Deprecated: Use PluginPlanResults in pipedv1
PlanSummary string
// Deprecated: Use PluginPlanResults in pipedv1
PlanDetails string
NoChange bool

PluginPlanResults []*model.PluginPlanPreviewResult
}

type FailurePiped struct {
Expand All @@ -59,8 +65,11 @@ type FailurePiped struct {

type FailureApplication struct {
ApplicationInfo
Reason string
Reason string
// Deprecated: Use PluginPlanResults in pipedv1
PlanDetails string

PluginPlanResults []*model.PluginPlanPreviewResult
}

type PipedInfo struct {
Expand All @@ -69,12 +78,16 @@ type PipedInfo struct {
}

type ApplicationInfo struct {
ApplicationID string
ApplicationName string
ApplicationURL string
Env string
ApplicationID string
ApplicationName string
ApplicationURL string
Env string
// Deprecated: Use PluginNames in pipedv1
ApplicationKind string // KUBERNETES, TERRAFORM, CLOUDRUN, LAMBDA, ECS
ApplicationDirectory string

PlannedPluginNames string
AllPluginNames string
}

func retrievePlanPreview(
Expand Down Expand Up @@ -133,12 +146,14 @@ const (
failureBadgeURL = `[![PLAN_PREVIEW](https://img.shields.io/static/v1?label=PipeCD&message=Plan_Preview&color=orange&style=flat)](https://pipecd.dev/docs/user-guide/plan-preview/)`
actionBadgeURLFormat = "[![ACTIONS](https://img.shields.io/static/v1?label=PipeCD&message=Action_Log&style=flat)](%s)"

noChangeTitleFormat = "Ran plan-preview against head commit %s of this pull request. PipeCD detected `0` updated application. It means no deployment will be triggered once this pull request got merged.\n"
hasChangeTitleFormat = "Ran plan-preview against head commit %s of this pull request. PipeCD detected `%d` updated applications and here are their plan results. Once this pull request got merged their deployments will be triggered to run as these estimations.\n"
detailsFormat = "<details>\n<summary>Details (Click me)</summary>\n<p>\n\n``` %s\n%s\n```\n</p>\n</details>\n\n"
detailsOmittedMessage = "The details are too long to display. Please check the actions log to see full details."
appInfoWithEnvFormat = "app: [%s](%s), env: %s, kind: %s"
appInfoWithoutEnvFormat = "app: [%s](%s), kind: %s"
noChangeTitleFormat = "Ran plan-preview against head commit %s of this pull request. PipeCD detected `0` updated application. It means no deployment will be triggered once this pull request got merged.\n"
hasChangeTitleFormat = "Ran plan-preview against head commit %s of this pull request. PipeCD detected `%d` updated applications and here are their plan results. Once this pull request got merged their deployments will be triggered to run as these estimations.\n"
detailsFormat = "<details>\n<summary>Details (Click me)</summary>\n<p>\n\n``` %s\n%s\n```\n</p>\n</details>\n\n"
detailsOmittedMessage = "The details are too long to display. Please check the actions log to see full details."
appInfoWithEnvFormat = "app: [%s](%s), env: %s, kind: %s"
appInfoWithoutEnvFormat = "app: [%s](%s), kind: %s"
appInfoWithEnvFormatV1 = "app: [%s](%s), env: %s, planned plugin(s): %s"
appInfoWithoutEnvFormatV1 = "app: [%s](%s), planned plugin(s): %s"

ghMessageLenLimit = 65536

Expand Down Expand Up @@ -196,30 +211,67 @@ func makeCommentBody(event *githubEvent, r *PlanPreviewResult, title string) str
for _, app := range changedApps {
fmt.Fprintf(&b, "### %s\n", makeTitleText(&app.ApplicationInfo))
fmt.Fprintf(&b, "Sync strategy: %s\n", app.SyncStrategy)
fmt.Fprintf(&b, "Summary: %s\n\n", app.PlanSummary)

var (
lang = "diff"
details = app.PlanDetails
)
if app.ApplicationKind == "TERRAFORM" {
lang = "hcl"
if shortened, err := generateTerraformShortPlanDetails(details); err == nil {
details = shortened

if app.AllPluginNames == "" {
// pipedv0
fmt.Fprintf(&b, "Summary: %s\n\n", app.PlanSummary)
var (
lang = "diff"
details = app.PlanDetails
)
if app.ApplicationKind == "TERRAFORM" {
lang = "hcl"
if shortened, err := generateTerraformShortPlanDetails(details); err == nil {
details = shortened
}
}
}

l := utf8.RuneCountInString(details)
if detailLen+l > detailsLenLimit {
fmt.Fprintf(&b, detailsFormat, lang, detailsOmittedMessage)
detailLen += utf8.RuneCountInString(detailsOmittedMessage)
continue
}
l := utf8.RuneCountInString(details)
if detailLen+l > detailsLenLimit {
fmt.Fprintf(&b, detailsFormat, lang, detailsOmittedMessage)
detailLen += utf8.RuneCountInString(detailsOmittedMessage)
continue
}

if l > 0 {
detailLen += l
fmt.Fprintf(&b, detailsFormat, lang, details)
if l > 0 {
detailLen += l
fmt.Fprintf(&b, detailsFormat, lang, details)
}
} else {
// pipedv1
fmt.Fprintf(&b, " Plugin(s): %s\n", app.AllPluginNames)
fmt.Fprintf(&b, " Summary:\n")
for _, ppr := range app.PluginPlanResults {
fmt.Fprintf(&b, " - %s(%s): %s\n", ppr.PluginName, ppr.DeployTarget, ppr.PlanSummary)
}
fmt.Fprint(&b, " Details:\n")
for _, ppr := range app.PluginPlanResults {
fmt.Fprintf(&b, " - %s(%s):\n", ppr.PluginName, ppr.DeployTarget)

details := string(ppr.PlanDetails)
switch ppr.DiffLanguage {
case "":
ppr.DiffLanguage = "diff" // Use diff by default
case "hcl":
if shortened, err := generateTerraformShortPlanDetails(details); err == nil {
details = shortened
}
}

l := utf8.RuneCountInString(details)
if detailLen+l > detailsLenLimit {
fmt.Fprintf(&b, detailsFormat, ppr.DiffLanguage, detailsOmittedMessage)
detailLen += utf8.RuneCountInString(detailsOmittedMessage)
continue
}

if l > 0 {
detailLen += l
fmt.Fprintf(&b, detailsFormat, ppr.DiffLanguage, details)
}
}
}

}

if len(pipelineApps)+len(quickSyncApps) > 0 {
Expand Down Expand Up @@ -253,13 +305,24 @@ func makeCommentBody(event *githubEvent, r *PlanPreviewResult, title string) str
fmt.Fprintf(&b, "\n### %s\n", makeTitleText(&app.ApplicationInfo))
fmt.Fprintf(&b, "Reason: %s\n\n", app.Reason)

var lang = "diff"
if app.ApplicationKind == "TERRAFORM" {
lang = "hcl"
}

if len(app.PlanDetails) > 0 {
fmt.Fprintf(&b, detailsFormat, lang, app.PlanDetails)
if app.AllPluginNames == "" {
// pipedv0
var lang = "diff"
if app.ApplicationKind == "TERRAFORM" {
lang = "hcl"
}

if len(app.PlanDetails) > 0 {
fmt.Fprintf(&b, detailsFormat, lang, app.PlanDetails)
}
} else {
// pipedv1
for _, ppr := range app.PluginPlanResults {
fmt.Fprintf(&b, " - %s(%s):\n", ppr.PluginName, ppr.DeployTarget)
if len(ppr.PlanDetails) > 0 {
fmt.Fprintf(&b, detailsFormat, ppr.DiffLanguage, ppr.PlanDetails)
}
}
}
}
}
Expand Down Expand Up @@ -311,10 +374,19 @@ func makeActionLogURL() string {
}

func makeTitleText(app *ApplicationInfo) string {
if app.Env == "" {
return fmt.Sprintf(appInfoWithoutEnvFormat, app.ApplicationName, app.ApplicationURL, strings.ToLower(app.ApplicationKind))
if app.AllPluginNames == "" {
// pipedv0
if app.Env == "" {
return fmt.Sprintf(appInfoWithoutEnvFormat, app.ApplicationName, app.ApplicationURL, strings.ToLower(app.ApplicationKind))
}
return fmt.Sprintf(appInfoWithEnvFormat, app.ApplicationName, app.ApplicationURL, app.Env, strings.ToLower(app.ApplicationKind))
} else {
// pipedv1
if app.Env == "" {
return fmt.Sprintf(appInfoWithoutEnvFormatV1, app.ApplicationName, app.ApplicationURL, app.PlannedPluginNames)
}
return fmt.Sprintf(appInfoWithEnvFormatV1, app.ApplicationName, app.ApplicationURL, app.Env, app.PlannedPluginNames)
}
return fmt.Sprintf(appInfoWithEnvFormat, app.ApplicationName, app.ApplicationURL, app.Env, strings.ToLower(app.ApplicationKind))
}

func generateTerraformShortPlanDetails(details string) (string, error) {
Expand Down
Loading