From da8a53cb7d3709076b026712777581177ca6772e Mon Sep 17 00:00:00 2001 From: Yohann Bacha Date: Fri, 28 Apr 2023 17:34:22 +0200 Subject: [PATCH 1/3] fix: some display issues --- cmd/integration_link.go | 49 +++++++++++++++++++++------- integrationlink/manual_review_app.go | 7 ++-- integrationlink/pull_request.go | 29 ++++++++++++++++ 3 files changed, 71 insertions(+), 14 deletions(-) create mode 100644 integrationlink/pull_request.go diff --git a/cmd/integration_link.go b/cmd/integration_link.go index e83538f16..5fa37a3e3 100644 --- a/cmd/integration_link.go +++ b/cmd/integration_link.go @@ -180,7 +180,7 @@ List of available integrations: } if deployReviewApps && allowReviewAppsFromForks && !awareOfSecurityRisks { - allowReviewAppsFromForks, err = askForConfirmationToAllowReviewAppsFromForks() + allowReviewAppsFromForks, err = askForConfirmationToAllowReviewAppsFromForks("Allow automatic creation of review apps from forks?") if err != nil { errorQuit(err) } @@ -305,7 +305,7 @@ List of available integrations: params := integrationlink.CheckAndFillParams(c) if allowReviewAppsFromForks && !awareOfSecurityRisks { - stillAllowed, err := askForConfirmationToAllowReviewAppsFromForks() + stillAllowed, err := askForConfirmationToAllowReviewAppsFromForks("Allow automatic creation of review apps from forks?") if err != nil { errorQuit(err) } @@ -390,9 +390,11 @@ List of available integrations: } integrationLinkManualReviewAppCommand = cli.Command{ - Name: "integration-link-manual-review-app", - Category: "Integration Link", - Flags: []cli.Flag{&appFlag}, + Name: "integration-link-manual-review-app", + Category: "Integration Link", + Flags: []cli.Flag{&appFlag, + &cli.BoolFlag{Name: "aware-of-security-risks", Usage: "Bypass the security warning about deploying a review app from a fork repository"}, + }, Usage: "Trigger a review app creation of the pull/merge request ID specified", ArgsUsage: "request-id", Description: CommandDescription{ @@ -401,7 +403,7 @@ List of available integrations: $ scalingo --app my-app integration-link-manual-review-app pull-request-id (for GitHub and GitHub Enterprise) $ scalingo --app my-app integration-link-manual-review-app merge-request-id (for GitLab and GitLab self-hosted) `, - Examples: []string{"scalingo --app my-app integration-link-manual-review-app 42"}, + Examples: []string{"scalingo --app my-app integration-link-manual-review-app --aware-of-security-risks 42"}, SeeAlso: []string{"integration-link", "integration-link-create", "integration-link-update", "integration-link-delete", "integration-link-manual-deploy"}, }.Render(), Action: func(c *cli.Context) error { @@ -414,9 +416,33 @@ List of available integrations: utils.CheckForConsent(c.Context, currentApp, utils.ConsentTypeContainers) - pullRequestID := c.Args().First() + pullRequestID, err := strconv.Atoi(c.Args().First()) + if err != nil { + errorQuit(errgo.Notef(err, "invalid pull request id")) + } + + pullRequest, err := integrationlink.PullRequest(c.Context, currentApp, pullRequestID) + if err != nil { + errorQuit(err) + } + + if pullRequest.OpenedFromAForkedRepo { + awareOfSecurityRisks := c.Bool("aware-of-security-risks") + if !awareOfSecurityRisks { + io.Info("\nYou are about to deploy a Review App from a Pull Request opened from a fork.") + allowReviewAppsFromForks, err := askForConfirmationToAllowReviewAppsFromForks("Deploy this Pull Request coming from a forked repository ?") + if err != nil { + errorQuit(err) + } - err := integrationlink.ManualReviewApp(c.Context, currentApp, pullRequestID) + if !allowReviewAppsFromForks { + io.Info("Manual Review App deploy aborted. Exiting.") + return nil + } + } + } + + err = integrationlink.ManualReviewApp(c.Context, currentApp, pullRequestID) if err != nil { errorQuit(err) } @@ -513,7 +539,7 @@ func interactiveCreate() (scalingo.SCMRepoLinkCreateParams, error) { params.HoursBeforeDeleteStale = &hoursBeforeDestroyOnStale } - forksAllowed, err := askForConfirmationToAllowReviewAppsFromForks() + forksAllowed, err := askForConfirmationToAllowReviewAppsFromForks("Allow automatic creation of review apps from forks?") if err != nil { return params, errgo.Notef(err, "error enquiring about automatic review apps creation from forks") } @@ -537,14 +563,15 @@ func validateHoursBeforeDelete(ans interface{}) error { return nil } -func askForConfirmationToAllowReviewAppsFromForks() (bool, error) { +func askForConfirmationToAllowReviewAppsFromForks(prompt string) (bool, error) { fmt.Println() io.Warning(reviewAppsFromForksSecurityWarning) fmt.Println() var confirmed bool + err := survey.AskOne(&survey.Confirm{ - Message: "Allow automatic creation of review apps from forks?", + Message: prompt, Default: false, }, &confirmed, nil) diff --git a/integrationlink/manual_review_app.go b/integrationlink/manual_review_app.go index 249687c81..1d6f7d374 100644 --- a/integrationlink/manual_review_app.go +++ b/integrationlink/manual_review_app.go @@ -2,6 +2,7 @@ package integrationlink import ( "context" + "strconv" "gopkg.in/errgo.v1" @@ -9,7 +10,7 @@ import ( "github.com/Scalingo/cli/io" ) -func ManualReviewApp(ctx context.Context, app, pullRequestID string) error { +func ManualReviewApp(ctx context.Context, app string, pullRequestID int) error { if app == "" { return errgo.New("no app defined") } @@ -19,11 +20,11 @@ func ManualReviewApp(ctx context.Context, app, pullRequestID string) error { return errgo.Notef(err, "fail to get Scalingo client") } - err = c.SCMRepoLinkManualReviewApp(ctx, app, pullRequestID) + err = c.SCMRepoLinkManualReviewApp(ctx, app, strconv.Itoa(pullRequestID)) if err != nil { return errgo.Notef(err, "fail to manually create a review app") } - io.Statusf("Manual review app created for app '%s' with pull/merge request id '%s'.\n", app, pullRequestID) + io.Statusf("Manual review app created for app '%s' with pull/merge request id '%d'.\n", app, pullRequestID) return nil } diff --git a/integrationlink/pull_request.go b/integrationlink/pull_request.go new file mode 100644 index 000000000..e084ef338 --- /dev/null +++ b/integrationlink/pull_request.go @@ -0,0 +1,29 @@ +package integrationlink + +import ( + "context" + + "gopkg.in/errgo.v1" + + "github.com/Scalingo/cli/config" + "github.com/Scalingo/go-scalingo/v6" +) + +func PullRequest(ctx context.Context, app string, pullRequestID int) (*scalingo.RepoLinkPullRequest, error) { + if app == "" { + return nil, errgo.New("no app defined") + } + + c, err := config.ScalingoClient(ctx) + if err != nil { + return nil, errgo.Notef(err, "fail to get Scalingo client") + } + + pullRequest, err := c.SCMRepoLinkPullRequest(ctx, app, pullRequestID) + + if err != nil { + return nil, errgo.Notef(err, "fail to fetch the pull request status") + } + + return pullRequest, nil +} From 647481bd21ac360f32cdf60b4d92f08cdd2a16ce Mon Sep 17 00:00:00 2001 From: Yohann Bacha Date: Mon, 15 May 2023 16:04:31 +0200 Subject: [PATCH 2/3] fix: upgraded go-scalingo version --- go.mod | 2 +- go.sum | 4 +-- .../Scalingo/go-scalingo/v6/CHANGELOG.md | 4 +++ .../Scalingo/go-scalingo/v6/README.md | 2 +- .../Scalingo/go-scalingo/v6/scm_repo_link.go | 29 +++++++++++++++++++ .../Scalingo/go-scalingo/v6/version.go | 2 +- vendor/modules.txt | 2 +- 7 files changed, 39 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index a5e1e892f..1347ef014 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.20 require ( github.com/AlecAivazis/survey/v2 v2.3.6 - github.com/Scalingo/go-scalingo/v6 v6.5.0 + github.com/Scalingo/go-scalingo/v6 v6.6.0 github.com/Scalingo/go-utils/errors/v2 v2.2.0 github.com/Scalingo/go-utils/logger v1.2.0 github.com/Scalingo/go-utils/retry v1.1.1 diff --git a/go.sum b/go.sum index c073c6d53..2e76db146 100644 --- a/go.sum +++ b/go.sum @@ -7,8 +7,8 @@ github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2 h1:+vx7roKuyA63n github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2/go.mod h1:HBCaDeC1lPdgDeDbhX8XFpy1jqjK0IBG8W5K+xYqA0w= github.com/ProtonMail/go-crypto v0.0.0-20221026131551-cf6655e29de4 h1:ra2OtmuW0AE5csawV4YXMNGNQQXvLRps3z2Z59OPO+I= github.com/ProtonMail/go-crypto v0.0.0-20221026131551-cf6655e29de4/go.mod h1:UBYPn8k0D56RtnR8RFQMjmh4KrZzWJ5o7Z9SYjossQ8= -github.com/Scalingo/go-scalingo/v6 v6.5.0 h1:9dukdLhg36bOTeqEG9IVhC8wLU9DgjnFKcCkrOMQJk0= -github.com/Scalingo/go-scalingo/v6 v6.5.0/go.mod h1:u3ROWLWw78ug4EQaunzOBzSPKy4ukNQTDrCFaKMG938= +github.com/Scalingo/go-scalingo/v6 v6.6.0 h1:w1spshwyJDaudgC7mhC7xp5wtBt1hYFoBTXMR/iempQ= +github.com/Scalingo/go-scalingo/v6 v6.6.0/go.mod h1:u3ROWLWw78ug4EQaunzOBzSPKy4ukNQTDrCFaKMG938= github.com/Scalingo/go-utils/errors/v2 v2.2.0 h1:n93hge0DzfZ3KbI/jdnxKDTRDD+PXsGwNPKyHRzQYEE= github.com/Scalingo/go-utils/errors/v2 v2.2.0/go.mod h1:pkLy6Qz9UNm6FpXtFJGZRC0W5lqbqHpPchrQV80gw5E= github.com/Scalingo/go-utils/logger v1.2.0 h1:E3jtaoRxpIsFcZu/jsvWew8ttUAwKUYQufdPqGYp7EU= diff --git a/vendor/github.com/Scalingo/go-scalingo/v6/CHANGELOG.md b/vendor/github.com/Scalingo/go-scalingo/v6/CHANGELOG.md index 37b1e318a..a8ba77ecc 100644 --- a/vendor/github.com/Scalingo/go-scalingo/v6/CHANGELOG.md +++ b/vendor/github.com/Scalingo/go-scalingo/v6/CHANGELOG.md @@ -2,6 +2,10 @@ ## To Be Released +## 6.6.0 + +* feat(scm-repo-link): fetch a Pull Request data + ## 6.5.0 * feat(scm-repo-link): add ManualDeployResponse diff --git a/vendor/github.com/Scalingo/go-scalingo/v6/README.md b/vendor/github.com/Scalingo/go-scalingo/v6/README.md index bb3a52a9e..841d999ef 100644 --- a/vendor/github.com/Scalingo/go-scalingo/v6/README.md +++ b/vendor/github.com/Scalingo/go-scalingo/v6/README.md @@ -80,7 +80,7 @@ Bump new version number in: Commit, tag and create a new release: ```sh -version="6.5.0" +version="6.6.0" git switch --create release/${version} git add CHANGELOG.md README.md version.go diff --git a/vendor/github.com/Scalingo/go-scalingo/v6/scm_repo_link.go b/vendor/github.com/Scalingo/go-scalingo/v6/scm_repo_link.go index 094fd35a5..9ddc50a45 100644 --- a/vendor/github.com/Scalingo/go-scalingo/v6/scm_repo_link.go +++ b/vendor/github.com/Scalingo/go-scalingo/v6/scm_repo_link.go @@ -2,6 +2,7 @@ package scalingo import ( "context" + "fmt" "time" "gopkg.in/errgo.v1" @@ -15,6 +16,7 @@ type SCMRepoLinkService interface { SCMRepoLinkCreate(ctx context.Context, app string, params SCMRepoLinkCreateParams) (*SCMRepoLink, error) SCMRepoLinkUpdate(ctx context.Context, app string, params SCMRepoLinkUpdateParams) (*SCMRepoLink, error) SCMRepoLinkDelete(ctx context.Context, app string) error + SCMRepoLinkPullRequest(ctx context.Context, app string, number int) (*RepoLinkPullRequest, error) SCMRepoLinkManualDeploy(ctx context.Context, app, branch string) (*Deployment, error) SCMRepoLinkManualReviewApp(ctx context.Context, app, pullRequestID string) error @@ -97,6 +99,20 @@ type SCMRepoLinkReviewAppsResponse struct { ReviewApps []*ReviewApp `json:"review_apps"` } +type SCMRepoLinkPullRequestResponse struct { + Pull RepoLinkPullRequest `json:"pull"` +} + +type RepoLinkPullRequest struct { + ID int `json:"id"` + Number int `json:"number"` + Title string `json:"title"` + HTMLURL string `json:"html_url"` + SourceRepoName string `json:"source_repo_name"` + SourceRepoHTMLURL string `json:"source_repo_html_url"` + OpenedFromAForkedRepo bool `json:"opened_from_a_forked_repo"` +} + var _ SCMRepoLinkService = (*Client)(nil) func (c *Client) SCMRepoLinkList(ctx context.Context, opts PaginationOpts) ([]*SCMRepoLink, PaginationMeta, error) { @@ -165,6 +181,19 @@ func (c *Client) SCMRepoLinkDelete(ctx context.Context, app string) error { return nil } +func (c *Client) SCMRepoLinkPullRequest(ctx context.Context, app string, number int) (*RepoLinkPullRequest, error) { + var res SCMRepoLinkPullRequestResponse + err := c.ScalingoAPI().DoRequest(ctx, &http.APIRequest{ + Method: "GET", + Endpoint: fmt.Sprintf("/apps/%s/scm_repo_link/pulls/%d", app, number), + Expected: http.Statuses{200}, + }, &res) + if err != nil { + return nil, errgo.Notef(err, "fail to get this SCM repo link") + } + return &res.Pull, nil +} + func (c *Client) SCMRepoLinkManualDeploy(ctx context.Context, app, branch string) (*Deployment, error) { var res SCMRepoLinkManualDeployResponse err := c.ScalingoAPI().DoRequest(ctx, &http.APIRequest{ diff --git a/vendor/github.com/Scalingo/go-scalingo/v6/version.go b/vendor/github.com/Scalingo/go-scalingo/v6/version.go index f774886fd..5d41803a8 100644 --- a/vendor/github.com/Scalingo/go-scalingo/v6/version.go +++ b/vendor/github.com/Scalingo/go-scalingo/v6/version.go @@ -1,3 +1,3 @@ package scalingo -var Version = "6.5.0" +var Version = "6.6.0" diff --git a/vendor/modules.txt b/vendor/modules.txt index fb4dc1789..bfa22fdae 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -28,7 +28,7 @@ github.com/ProtonMail/go-crypto/openpgp/internal/ecc github.com/ProtonMail/go-crypto/openpgp/internal/encoding github.com/ProtonMail/go-crypto/openpgp/packet github.com/ProtonMail/go-crypto/openpgp/s2k -# github.com/Scalingo/go-scalingo/v6 v6.5.0 +# github.com/Scalingo/go-scalingo/v6 v6.6.0 ## explicit; go 1.20 github.com/Scalingo/go-scalingo/v6 github.com/Scalingo/go-scalingo/v6/billing From 519607538efc248dba23da60eb965c025ba05a19 Mon Sep 17 00:00:00 2001 From: Yohann Bacha Date: Mon, 15 May 2023 16:25:40 +0200 Subject: [PATCH 3/3] fix: wording nitpicks --- cmd/integration_link.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/integration_link.go b/cmd/integration_link.go index 5fa37a3e3..7db654238 100644 --- a/cmd/integration_link.go +++ b/cmd/integration_link.go @@ -418,7 +418,7 @@ List of available integrations: pullRequestID, err := strconv.Atoi(c.Args().First()) if err != nil { - errorQuit(errgo.Notef(err, "invalid pull request id")) + errorQuit(errgo.Notef(err, "invalid pull / merge request id")) } pullRequest, err := integrationlink.PullRequest(c.Context, currentApp, pullRequestID) @@ -430,7 +430,7 @@ List of available integrations: awareOfSecurityRisks := c.Bool("aware-of-security-risks") if !awareOfSecurityRisks { io.Info("\nYou are about to deploy a Review App from a Pull Request opened from a fork.") - allowReviewAppsFromForks, err := askForConfirmationToAllowReviewAppsFromForks("Deploy this Pull Request coming from a forked repository ?") + allowReviewAppsFromForks, err := askForConfirmationToAllowReviewAppsFromForks("Deploy this Pull Request coming from a forked repository?") if err != nil { errorQuit(err) }