Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pull Request automation in krel release-notes #1304

Merged
merged 2 commits into from
May 20, 2020
Merged
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
146 changes: 139 additions & 7 deletions cmd/krel/cmd/release_notes.go
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,11 @@ func runReleaseNotes() (err error) {
return errors.Wrap(err, "validating PR command line options")
}

// Verify the repository
if err = validateWebsitePRRepository(); err != nil {
return errors.Wrapf(err, "while checking %s/%s fork", defaultKubernetesSigsOrg, defaultKubernetesSigsRepo)
}

// Generate the release notes for ust the current tag
jsonStr, err := releaseNotesJSON(tag)
if err != nil {
Expand All @@ -221,18 +226,21 @@ func runReleaseNotes() (err error) {

// Run the website PR process
if err := createWebsitePR(tag, jsonStr); err != nil {
return errors.Wrapf(err, "generating releasenotes for tag %s", tag)
return errors.Wrapf(err, "generating release notes for tag %s", tag)
}
return nil
}

// Create the PR for the Release Notes Draft in k/sig-release
if releaseNotesOpts.createDraftPR {
// Check cmd line options
if releaseNotesOpts.createDraftPR {
if err = validateDraftPROptions(); err != nil {
return errors.Wrap(err, "validating PR command line options")
}
if err = validateDraftPROptions(); err != nil {
return errors.Wrap(err, "validating PR command line options")
}

// Verify the repository
if err = validateDraftPRRepository(); err != nil {
return errors.Wrapf(err, "while checking %s/%s fork", git.DefaultGithubOrg, git.DefaultGithubReleaseRepo)
}

// Generate the notes for the current version
Expand Down Expand Up @@ -272,9 +280,70 @@ func runReleaseNotes() (err error) {
return nil
}

// validateDraftPRRepository checks if a repo is fit to create a PR
func validateDraftPRRepository() error {
gh := github.New()

isrepo, err := gh.RepoIsForkOf(
releaseNotesOpts.draftOrg, releaseNotesOpts.draftRepo,
git.DefaultGithubOrg, git.DefaultGithubReleaseRepo,
)
if err != nil {
return errors.Wrapf(
err, "while checking if repository is a fork of %s/%s",
git.DefaultGithubOrg, git.DefaultGithubReleaseRepo,
)
}

if !isrepo {
return errors.New(
fmt.Sprintf(
"Cannot create PR, %s/%s is not a fork of %s/%s",
releaseNotesOpts.draftOrg, releaseNotesOpts.draftRepo,
git.DefaultGithubOrg, git.DefaultGithubReleaseRepo,
),
)
}

return nil
}

// validateWebsitePRRepository checks if a repo is fit to create a PR
func validateWebsitePRRepository() error {
gh := github.New()

isrepo, err := gh.RepoIsForkOf(
releaseNotesOpts.websiteOrg, releaseNotesOpts.websiteRepo,
defaultKubernetesSigsOrg, defaultKubernetesSigsRepo,
)
if err != nil {
return errors.Wrapf(
err, "while checking if repository is a fork of %s/%s",
defaultKubernetesSigsOrg, defaultKubernetesSigsRepo,
)
}

if !isrepo {
return errors.New(
fmt.Sprintf(
"Cannot create PR, %s/%s is not a fork of %s/%s",
releaseNotesOpts.websiteOrg, releaseNotesOpts.websiteRepo,
defaultKubernetesSigsOrg, defaultKubernetesSigsRepo,
),
)
}

return nil
}

// validateDraftPROptions checks if we have all needed parameters to create the Release Notes PR
func validateDraftPROptions() error {
if releaseNotesOpts.createDraftPR {
token, isset := os.LookupEnv(github.TokenEnvKey)
if !isset || token == "" {
return errors.New("Cannot create release notes draft if GitHub token is not set")
}

// Check if --create-website-pr is set
if releaseNotesOpts.createWebsitePR {
return errors.New("Cannot create release notes draft if --create-website-pr is set")
Expand All @@ -301,6 +370,15 @@ func validateDraftPROptions() error {
// validateWebsitePROptions checks if we have all needed parameters to create the Release Notes PR
func validateWebsitePROptions() error {
if releaseNotesOpts.createWebsitePR {
token, isset := os.LookupEnv(github.TokenEnvKey)
if !isset || token == "" {
return errors.New("Cannot create release notes json file if GitHub token is not set")
}

if releaseNotesOpts.createDraftPR {
return errors.New("Cannot creare Website PR if --create-draft-pr is defined")
}

// Check if --website-org is set
if releaseNotesOpts.websiteOrg == "" {
logrus.Warn("cannot generate the Website PR without --website-org")
Expand Down Expand Up @@ -365,7 +443,39 @@ func createDraftPR(tag string, result *releaseNotesResult) (err error) {
return errors.Wrapf(err, "pushing %v to remote", userForkName)
}

// TODO: Call github API and create PR against k/sig-release
// Create a PR against k/sig-release using the github API
gh := github.New()

// TODO: Maybe read and parse the PR template from sig-release?
prBody := fmt.Sprintln(
"**What type of PR is this?**",
"/kind documentation",
"**What this PR does / why we need it**:",
fmt.Sprintf("This PR updates the release notes draft to k/k %s", tag),
"**Which issue(s) this PR fixes**:",
"**Special notes for your reviewer**:",
"This is an automated PR generated from `krel The Kubernetes Release Toolbox`",
)

// Create the pull request
logrus.Debugf(
"PR params: org: %s, repo: %s, headBranch: %s baseBranch: %s",
git.DefaultGithubOrg, git.DefaultGithubReleaseRepo, "master",
fmt.Sprintf("%s:%s", releaseNotesOpts.draftOrg, branchname),
)
pr, err := gh.CreatePullRequest(
git.DefaultGithubOrg, git.DefaultGithubReleaseRepo, "master",
fmt.Sprintf("%s:%s", releaseNotesOpts.draftOrg, branchname),
fmt.Sprintf("Update release notes draft to version %s", tag), prBody,
)

if err != nil {
logrus.Warnf("An error has occurred while creating the pull request for %s", tag)
logrus.Warn("While the PR failed, the release notes draft was generated and submitted to your fork")
return errors.Wrap(err, "creating the pull request")
}

logrus.Infof("Successfully created PR #%d", pr.GetNumber())
return nil
}

Expand Down Expand Up @@ -530,7 +640,29 @@ func createWebsitePR(tag, jsonStr string) (err error) {
return errors.Wrapf(err, "pushing %v to %v/%v", userForkName, releaseNotesOpts.websiteOrg, releaseNotesOpts.websiteRepo)
}

// TODO: Call github API and create PR against k/sig-release
// Create a PR against k/sig-release using the github API
gh := github.New()

// Create the pull request
logrus.Debugf(
"PR params: org: %s, repo: %s, headBranch: %s baseBranch: %s",
defaultKubernetesSigsOrg, defaultKubernetesSigsRepo, "master",
fmt.Sprintf("%s:%s", releaseNotesOpts.websiteOrg, branchname),
)
pr, err := gh.CreatePullRequest(
defaultKubernetesSigsOrg, defaultKubernetesSigsRepo, "master",
fmt.Sprintf("%s:%s", releaseNotesOpts.websiteOrg, branchname),
fmt.Sprintf("Patch relnotes.k8s.io to release %s", tag),
fmt.Sprintf("Automated patch to update relnotes.k8s.io to k/k version `%s` ", tag),
)

if err != nil {
logrus.Warnf("An error has occurred while creating the pull request for %s", tag)
logrus.Warn("While the PR failed, the release notes where generated and submitted to your fork")
return errors.Wrap(err, "creating the pull request")
}

logrus.Infof("Successfully created PR #%d", pr.GetNumber())
return nil
}

Expand Down