1
0
mirror of https://github.com/SAP/jenkins-library.git synced 2025-01-16 05:16:08 +02:00

Update githubPublishRelease

This commit is contained in:
OliverNocon 2019-11-04 16:07:30 +01:00
parent d24644c0c2
commit 6256a0b9aa
14 changed files with 579 additions and 17 deletions

148
cmd/githubPublishRelease.go Normal file
View File

@ -0,0 +1,148 @@
package cmd
import (
"context"
"fmt"
"strings"
"github.com/google/go-github/v28/github"
"github.com/pkg/errors"
piperGithub "github.com/SAP/jenkins-library/pkg/github"
)
type githubRepoClient interface {
GetLatestRelease(ctx context.Context, owner string, repo string) (*github.RepositoryRelease, *github.Response, error)
CreateRelease(ctx context.Context, owner string, repo string, release *github.RepositoryRelease) (*github.RepositoryRelease, *github.Response, error)
}
type githubIssueClient interface {
ListByRepo(ctx context.Context, owner string, repo string, opt *github.IssueListByRepoOptions) ([]*github.Issue, *github.Response, error)
}
func githubPublishRelease(myGithubPublishReleaseOptions githubPublishReleaseOptions) error {
ctx, client, err := piperGithub.NewClient(myGithubPublishReleaseOptions.GithubToken, myGithubPublishReleaseOptions.GithubAPIURL, myGithubPublishReleaseOptions.GithubAPIURL)
if err != nil {
return err
}
err = runGithubPublishRelease(ctx, &myGithubPublishReleaseOptions, client.Repositories, client.Issues)
if err != nil {
return err
}
return nil
}
func runGithubPublishRelease(ctx context.Context, myGithubPublishReleaseOptions *githubPublishReleaseOptions, ghRepoClient githubRepoClient, ghIssueClient githubIssueClient) error {
var publishedAt github.Timestamp
lastRelease, resp, err := ghRepoClient.GetLatestRelease(ctx, myGithubPublishReleaseOptions.GithubOrg, myGithubPublishReleaseOptions.GithubRepo)
if err != nil {
if resp.StatusCode == 404 {
//first release
myGithubPublishReleaseOptions.AddDeltaToLastRelease = false
publishedAt = lastRelease.GetPublishedAt()
} else {
return errors.Wrap(err, "Error occured when retrieving latest GitHub releass")
}
}
releaseBody := ""
if len(myGithubPublishReleaseOptions.ReleaseBodyHeader) > 0 {
releaseBody += myGithubPublishReleaseOptions.ReleaseBodyHeader + "<br /\n>"
}
if myGithubPublishReleaseOptions.AddClosedIssues {
releaseBody += getClosedIssuesText(ctx, publishedAt, myGithubPublishReleaseOptions, ghIssueClient)
}
if myGithubPublishReleaseOptions.AddDeltaToLastRelease {
releaseBody += getReleaseDeltaText(myGithubPublishReleaseOptions, lastRelease)
}
release := github.RepositoryRelease{
TagName: &myGithubPublishReleaseOptions.Version,
TargetCommitish: &myGithubPublishReleaseOptions.Commitish,
Name: &myGithubPublishReleaseOptions.Version,
Body: &releaseBody,
}
//create release
createdRelease, _, err := ghRepoClient.CreateRelease(ctx, myGithubPublishReleaseOptions.GithubOrg, myGithubPublishReleaseOptions.GithubRepo, &release)
if err != nil {
return errors.Wrapf(err, "creation of release '%v' failed", release.TagName)
}
// todo switch to logging
fmt.Printf("Release %v created on %v/%v", *createdRelease.TagName, myGithubPublishReleaseOptions.GithubOrg, myGithubPublishReleaseOptions.GithubRepo)
return nil
}
func getClosedIssuesText(ctx context.Context, publishedAt github.Timestamp, myGithubPublishReleaseOptions *githubPublishReleaseOptions, ghIssueClient githubIssueClient) string {
closedIssuesText := ""
options := github.IssueListByRepoOptions{
State: "closed",
Direction: "asc",
Since: publishedAt.Time,
}
if len(myGithubPublishReleaseOptions.Labels) > 0 {
options.Labels = myGithubPublishReleaseOptions.Labels
}
ghIssues, _, err := ghIssueClient.ListByRepo(ctx, myGithubPublishReleaseOptions.GithubOrg, myGithubPublishReleaseOptions.GithubRepo, &options)
if err != nil {
//log error
}
prTexts := []string{"<br />**List of closed pull-requests since last release**"}
issueTexts := []string{"<br />**List of closed issues since last release**"}
for _, issue := range ghIssues {
if issue.IsPullRequest() && !isExcluded(issue, myGithubPublishReleaseOptions.ExcludeLabels) {
prTexts = append(prTexts, fmt.Sprintf("[#%v](%v): %v", issue.GetNumber(), issue.GetHTMLURL(), issue.GetTitle()))
} else if !issue.IsPullRequest() && !isExcluded(issue, myGithubPublishReleaseOptions.ExcludeLabels) {
issueTexts = append(issueTexts, fmt.Sprintf("[#%v](%v): %v", issue.GetNumber(), issue.GetHTMLURL(), issue.GetTitle()))
}
}
if len(prTexts) > 1 {
closedIssuesText += strings.Join(prTexts, "\n") + "\n"
}
if len(issueTexts) > 1 {
closedIssuesText += strings.Join(issueTexts, "\n") + "\n"
}
return closedIssuesText
}
func getReleaseDeltaText(myGithubPublishReleaseOptions *githubPublishReleaseOptions, lastRelease *github.RepositoryRelease) string {
releaseDeltaText := ""
//add delta link to previous release
releaseDeltaText += "<br />**Changes**<br />"
releaseDeltaText += fmt.Sprintf(
"[%v...%v](%v/%v/%v/compare/%v...%v) <br />",
lastRelease.GetTagName(),
myGithubPublishReleaseOptions.Version,
myGithubPublishReleaseOptions.GithubServerURL,
myGithubPublishReleaseOptions.GithubOrg,
myGithubPublishReleaseOptions.GithubRepo,
lastRelease.GetTagName(), myGithubPublishReleaseOptions.Version,
)
return releaseDeltaText
}
func isExcluded(issue *github.Issue, excludeLabels []string) bool {
//issue.Labels[0].GetName()
for _, ex := range excludeLabels {
for _, l := range issue.Labels {
if ex == l.GetName() {
return true
}
}
}
return false
}

View File

@ -0,0 +1,177 @@
package cmd
import (
"os"
"github.com/SAP/jenkins-library/pkg/config"
"github.com/spf13/cobra"
)
type githubPublishReleaseOptions struct {
AddClosedIssues bool `json:"addClosedIssues,omitempty"`
AddDeltaToLastRelease bool `json:"addDeltaToLastRelease,omitempty"`
AssetPath string `json:"assetPath,omitempty"`
Commitish string `json:"commitish,omitempty"`
ExcludeLabels []string `json:"excludeLabels,omitempty"`
GithubAPIURL string `json:"githubApiUrl,omitempty"`
GithubOrg string `json:"githubOrg,omitempty"`
GithubRepo string `json:"githubRepo,omitempty"`
GithubServerURL string `json:"githubServerUrl,omitempty"`
GithubToken string `json:"githubToken,omitempty"`
Labels []string `json:"labels,omitempty"`
ReleaseBodyHeader string `json:"releaseBodyHeader,omitempty"`
Update bool `json:"update,omitempty"`
Version string `json:"version,omitempty"`
}
var myGithubPublishReleaseOptions githubPublishReleaseOptions
var githubPublishReleaseStepConfigJSON string
// GithubPublishReleaseCommand Publish a release in GitHub
func GithubPublishReleaseCommand() *cobra.Command {
metadata := githubPublishReleaseMetadata()
var createGithubPublishReleaseCmd = &cobra.Command{
Use: "githubPublishRelease",
Short: "Publish a release in GitHub",
Long: `This step creates a tag in your GitHub repository together with a release.
The release can be filled with text plus additional information like:
* Closed pull request since last release
* Closed issues since last release
* Link to delta information showing all commits since last release
The result looks like
![Example release](../images/githubRelease.png)`,
PreRunE: func(cmd *cobra.Command, args []string) error {
return PrepareConfig(cmd, &metadata, "githubPublishRelease", &myGithubPublishReleaseOptions, openPiperFile)
},
RunE: func(cmd *cobra.Command, args []string) error {
return githubPublishRelease(myGithubPublishReleaseOptions)
},
}
addGithubPublishReleaseFlags(createGithubPublishReleaseCmd)
return createGithubPublishReleaseCmd
}
func addGithubPublishReleaseFlags(cmd *cobra.Command) {
cmd.Flags().BoolVar(&myGithubPublishReleaseOptions.AddClosedIssues, "addClosedIssues", false, "If set to `true`, closed issues and merged pull-requests since the last release will added below the `releaseBodyHeader`")
cmd.Flags().BoolVar(&myGithubPublishReleaseOptions.AddDeltaToLastRelease, "addDeltaToLastRelease", false, "If set to `true`, a link will be added to the relese information that brings up all commits since the last release.")
cmd.Flags().StringVar(&myGithubPublishReleaseOptions.AssetPath, "assetPath", os.Getenv("PIPER_assetPath"), "Path to a release asset which should be uploaded to the list of release assets.")
cmd.Flags().StringVar(&myGithubPublishReleaseOptions.Commitish, "commitish", "master", "Target git commitish for the release")
cmd.Flags().StringSliceVar(&myGithubPublishReleaseOptions.ExcludeLabels, "excludeLabels", []string{}, "Allows to exclude issues with dedicated list of labels.")
cmd.Flags().StringVar(&myGithubPublishReleaseOptions.GithubAPIURL, "githubApiUrl", "https://api.github.com", "Set the GitHub API url.")
cmd.Flags().StringVar(&myGithubPublishReleaseOptions.GithubOrg, "githubOrg", os.Getenv("PIPER_githubOrg"), "Set the GitHub organization.")
cmd.Flags().StringVar(&myGithubPublishReleaseOptions.GithubRepo, "githubRepo", os.Getenv("PIPER_githubRepo"), "Set the GitHub repository.")
cmd.Flags().StringVar(&myGithubPublishReleaseOptions.GithubServerURL, "githubServerUrl", "https://github.com", "GitHub server url for end-user access.")
cmd.Flags().StringVar(&myGithubPublishReleaseOptions.GithubToken, "githubToken", os.Getenv("PIPER_githubToken"), "GitHub personal access token as per https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line")
cmd.Flags().StringSliceVar(&myGithubPublishReleaseOptions.Labels, "labels", []string{}, "Labels to include in issue search.")
cmd.Flags().StringVar(&myGithubPublishReleaseOptions.ReleaseBodyHeader, "releaseBodyHeader", os.Getenv("PIPER_releaseBodyHeader"), "Content which will appear for the release.")
cmd.Flags().BoolVar(&myGithubPublishReleaseOptions.Update, "update", false, "Specify if the release should be updated in case it already exists")
cmd.Flags().StringVar(&myGithubPublishReleaseOptions.Version, "version", os.Getenv("PIPER_version"), "Define the version number which will be written as tag as well as release name.")
cmd.MarkFlagRequired("githubApiUrl")
cmd.MarkFlagRequired("githubOrg")
cmd.MarkFlagRequired("githubRepo")
cmd.MarkFlagRequired("githubServerUrl")
cmd.MarkFlagRequired("githubToken")
cmd.MarkFlagRequired("version")
}
// retrieve step metadata
func githubPublishReleaseMetadata() config.StepData {
var theMetaData = config.StepData{
Spec: config.StepSpec{
Inputs: config.StepInputs{
Parameters: []config.StepParameters{
{
Name: "addClosedIssues",
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
Type: "bool",
Mandatory: false,
},
{
Name: "addDeltaToLastRelease",
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
Type: "bool",
Mandatory: false,
},
{
Name: "assetPath",
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
Type: "string",
Mandatory: false,
},
{
Name: "commitish",
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
Type: "string",
Mandatory: false,
},
{
Name: "excludeLabels",
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
Type: "[]string",
Mandatory: false,
},
{
Name: "githubApiUrl",
Scope: []string{"GENERAL", "PARAMETERS", "STAGES", "STEPS"},
Type: "string",
Mandatory: true,
},
{
Name: "githubOrg",
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
Type: "string",
Mandatory: true,
},
{
Name: "githubRepo",
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
Type: "string",
Mandatory: true,
},
{
Name: "githubServerUrl",
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
Type: "string",
Mandatory: true,
},
{
Name: "githubToken",
Scope: []string{"GENERAL", "PARAMETERS", "STAGES", "STEPS"},
Type: "string",
Mandatory: true,
},
{
Name: "labels",
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
Type: "[]string",
Mandatory: false,
},
{
Name: "releaseBodyHeader",
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
Type: "string",
Mandatory: false,
},
{
Name: "update",
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
Type: "bool",
Mandatory: false,
},
{
Name: "version",
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
Type: "string",
Mandatory: true,
},
},
},
},
}
return theMetaData
}

View File

@ -0,0 +1,16 @@
package cmd
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestGithubPublishReleaseCommand(t *testing.T) {
testCmd := GithubPublishReleaseCommand()
// only high level testing performed - details are tested in step generation procudure
assert.Equal(t, "githubPublishRelease", testCmd.Use, "command name incorrect")
}

View File

@ -0,0 +1,38 @@
package cmd
import (
"fmt"
"testing"
"github.com/google/go-github/v28/github"
"github.com/stretchr/testify/assert"
)
func TestRunGithubPublishRelease(t *testing.T) {
}
func TestIsExcluded(t *testing.T) {
l1 := "label1"
l2 := "label2"
tt := []struct {
issue *github.Issue
excludeLabels []string
expected bool
}{
{issue: nil, excludeLabels: nil, expected: false},
{issue: &github.Issue{}, excludeLabels: nil, expected: false},
{issue: &github.Issue{Labels: []github.Label{{Name: &l1}}}, excludeLabels: nil, expected: false},
{issue: &github.Issue{Labels: []github.Label{{Name: &l1}}}, excludeLabels: []string{"label0"}, expected: false},
{issue: &github.Issue{Labels: []github.Label{{Name: &l1}}}, excludeLabels: []string{"label1"}, expected: true},
{issue: &github.Issue{Labels: []github.Label{{Name: &l1}, {Name: &l2}}}, excludeLabels: []string{}, expected: false},
{issue: &github.Issue{Labels: []github.Label{{Name: &l1}, {Name: &l2}}}, excludeLabels: []string{"label1"}, expected: true},
}
for k, v := range tt {
assert.Equal(t, v.expected, isExcluded(v.issue, v.excludeLabels), fmt.Sprintf("Run %v failed", k))
}
}

View File

@ -1,8 +1,6 @@
package cmd
import (
//"os"
"github.com/SAP/jenkins-library/pkg/config"
"github.com/spf13/cobra"
)

View File

@ -40,6 +40,7 @@ func Execute() {
rootCmd.AddCommand(ConfigCommand())
rootCmd.AddCommand(KarmaExecuteTestsCommand())
rootCmd.AddCommand(GithubPublishReleaseCommand())
addRootFlags(rootCmd)
if err := rootCmd.Execute(); err != nil {

View File

@ -13,7 +13,6 @@ import (
"github.com/stretchr/testify/assert"
)
type execMockRunner struct {
dir []string
calls []execCall
@ -42,11 +41,11 @@ func (m *execMockRunner) RunExecutable(e string, p ...string) error {
return nil
}
func(m *shellMockRunner) Dir(d string) {
func (m *shellMockRunner) Dir(d string) {
m.dir = d
}
func(m *shellMockRunner) RunShell(s string, c string) error {
func (m *shellMockRunner) RunShell(s string, c string) error {
m.calls = append(m.calls, c)
return nil
}

2
go.mod
View File

@ -4,8 +4,10 @@ go 1.13
require (
github.com/ghodss/yaml v1.0.0
github.com/google/go-github/v28 v28.1.1
github.com/pkg/errors v0.8.1
github.com/spf13/cobra v0.0.5
github.com/spf13/pflag v1.0.5
github.com/stretchr/testify v1.2.2
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45
)

21
go.sum
View File

@ -1,3 +1,4 @@
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
@ -9,6 +10,12 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/google/go-github v17.0.0+incompatible h1:N0LgJ1j65A7kfXrZnUDaYCs/Sf4rEjNlfyDHW9dolSY=
github.com/google/go-github/v28 v28.1.1 h1:kORf5ekX5qwXO2mGzXXOjMe/g6ap8ahVe0sBEulhSxo=
github.com/google/go-github/v28 v28.1.1/go.mod h1:bsqJWQX05omyWVmc00nEUql9mhQyv38lDZ8kPZcQVoM=
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/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
@ -35,8 +42,22 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a h1:oWX7TPOiFAMXLq8o0ikBYfCJVlRHBcsciT5bXOrH628=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 h1:SVwTIAaPC2U/AvvLNZ2a7OVsmBpC8L5BlwK1whH3hm0=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=

View File

@ -30,7 +30,7 @@ type stepInfo struct {
const stepGoTemplate = `package cmd
import (
//"os"
{{if .OSImport}}"os"{{end}}
"github.com/SAP/jenkins-library/pkg/config"
"github.com/spf13/cobra"
@ -145,10 +145,11 @@ func processMetaFiles(metadataFiles []string, openFile func(s string) (io.ReadCl
fmt.Printf("Step name: %v\n", stepData.Metadata.Name)
err = setDefaultParameters(&stepData)
osImport := false
osImport, err = setDefaultParameters(&stepData)
checkError(err)
myStepInfo := getStepInfo(&stepData)
myStepInfo := getStepInfo(&stepData, osImport)
step := stepTemplate(myStepInfo)
err = writeFile(fmt.Sprintf("cmd/%v_generated.go", stepData.Metadata.Name), step, 0644)
@ -169,14 +170,16 @@ func fileWriter(filename string, data []byte, perm os.FileMode) error {
return ioutil.WriteFile(filename, data, perm)
}
func setDefaultParameters(stepData *config.StepData) error {
func setDefaultParameters(stepData *config.StepData) (bool, error) {
//ToDo: custom function for default handling, support all relevant parameter types
osImportRequired := false
for k, param := range stepData.Spec.Inputs.Parameters {
if param.Default == nil {
switch param.Type {
case "string":
param.Default = fmt.Sprintf("os.Getenv(\"PIPER_%v\")", param.Name)
osImportRequired = true
case "bool":
// ToDo: Check if default should be read from env
param.Default = "false"
@ -184,7 +187,7 @@ func setDefaultParameters(stepData *config.StepData) error {
// ToDo: Check if default should be read from env
param.Default = "[]string{}"
default:
return fmt.Errorf("Meta data type not set or not known: '%v'", param.Type)
return false, fmt.Errorf("Meta data type not set or not known: '%v'", param.Type)
}
} else {
switch param.Type {
@ -199,16 +202,16 @@ func setDefaultParameters(stepData *config.StepData) error {
case "[]string":
param.Default = fmt.Sprintf("[]string{\"%v\"}", strings.Join(param.Default.([]string), "\", \""))
default:
return fmt.Errorf("Meta data type not set or not known: '%v'", param.Type)
return false, fmt.Errorf("Meta data type not set or not known: '%v'", param.Type)
}
}
stepData.Spec.Inputs.Parameters[k] = param
}
return nil
return osImportRequired, nil
}
func getStepInfo(stepData *config.StepData) stepInfo {
func getStepInfo(stepData *config.StepData, osImport bool) stepInfo {
return stepInfo{
StepName: stepData.Metadata.Name,
CobraCmdFuncName: fmt.Sprintf("%vCommand", strings.Title(stepData.Metadata.Name)),
@ -217,6 +220,7 @@ func getStepInfo(stepData *config.StepData) stepInfo {
Long: stepData.Metadata.LongDescription,
Metadata: stepData.Spec.Inputs.Parameters,
FlagsFunc: fmt.Sprintf("add%vFlags", strings.Title(stepData.Metadata.Name)),
OSImport: osImport,
}
}

View File

@ -112,10 +112,12 @@ func TestSetDefaultParameters(t *testing.T) {
"[]string{}",
}
err := setDefaultParameters(&stepData)
osImport, err := setDefaultParameters(&stepData)
assert.NoError(t, err, "error occured but none expected")
assert.Equal(t, true, osImport, "import of os package required")
for k, v := range expected {
assert.Equal(t, v, stepData.Spec.Inputs.Parameters[k].Default, fmt.Sprintf("default not correct for parameter %v", k))
}
@ -145,7 +147,7 @@ func TestSetDefaultParameters(t *testing.T) {
}
for k, v := range stepData {
err := setDefaultParameters(&v)
_, err := setDefaultParameters(&v)
assert.Error(t, err, fmt.Sprintf("error expected but none occured for parameter %v", k))
}
})
@ -168,7 +170,7 @@ func TestGetStepInfo(t *testing.T) {
},
}
myStepInfo := getStepInfo(&stepData)
myStepInfo := getStepInfo(&stepData, true)
assert.Equal(t, "testStep", myStepInfo.StepName, "StepName incorrect")
assert.Equal(t, "TestStepCommand", myStepInfo.CobraCmdFuncName, "CobraCmdFuncName incorrect")
@ -177,6 +179,7 @@ func TestGetStepInfo(t *testing.T) {
assert.Equal(t, "Long Test description", myStepInfo.Long, "Long incorrect")
assert.Equal(t, stepData.Spec.Inputs.Parameters, myStepInfo.Metadata, "Metadata incorrect")
assert.Equal(t, "addTestStepFlags", myStepInfo.FlagsFunc, "FlagsFunc incorrect")
assert.Equal(t, "addTestStepFlags", myStepInfo.FlagsFunc, "FlagsFunc incorrect")
}

View File

@ -1,7 +1,7 @@
package cmd
import (
//"os"
"os"
"github.com/SAP/jenkins-library/pkg/config"
"github.com/spf13/cobra"

23
pkg/github/github.go Normal file
View File

@ -0,0 +1,23 @@
package github
import (
"context"
"github.com/google/go-github/v28/github"
"golang.org/x/oauth2"
)
//NewClient creates a new GitHub client using an OAuth token for authentication
func NewClient(token, apiURL, uploadURL string) (context.Context, *github.Client, error) {
ctx := context.Background()
ts := oauth2.StaticTokenSource(
&oauth2.Token{AccessToken: token},
)
tc := oauth2.NewClient(ctx, ts)
client, err := github.NewEnterpriseClient(apiURL, uploadURL, tc)
if err != nil {
return ctx, nil, err
}
return ctx, client, nil
}

View File

@ -0,0 +1,132 @@
metadata:
name: githubPublishRelease
description: Publish a release in GitHub
longDescription: |
This step creates a tag in your GitHub repository together with a release.
The release can be filled with text plus additional information like:
* Closed pull request since last release
* Closed issues since last release
* Link to delta information showing all commits since last release
The result looks like
![Example release](../images/githubRelease.png)
spec:
inputs:
secrets:
- name: githubTokenCredentialsId
description: Jenkins 'Secret text' credentials ID containing token to authenticate to GitHub.
type: jenkins
params:
- name: addClosedIssues
description: 'If set to `true`, closed issues and merged pull-requests since the last release will added below the `releaseBodyHeader`'
scope:
- PARAMETERS
- STAGES
- STEPS
type: bool
default: false
- name: addDeltaToLastRelease
description: 'If set to `true`, a link will be added to the relese information that brings up all commits since the last release.'
scope:
- PARAMETERS
- STAGES
- STEPS
type: bool
default: false
- name: assetPath
description: Path to a release asset which should be uploaded to the list of release assets.
scope:
- PARAMETERS
- STAGES
- STEPS
type: string
- name: commitish
description: 'Target git commitish for the release'
scope:
- PARAMETERS
- STAGES
- STEPS
type: string
default: "master"
- name: excludeLabels
description: 'Allows to exclude issues with dedicated list of labels.'
scope:
- PARAMETERS
- STAGES
- STEPS
type: '[]string'
- name: githubApiUrl
description: Set the GitHub API url.
scope:
- GENERAL
- PARAMETERS
- STAGES
- STEPS
type: string
default: https://api.github.com
mandatory: true
- name: githubOrg
description: 'Set the GitHub organization.'
scope:
- PARAMETERS
- STAGES
- STEPS
type: string
mandatory: true
- name: githubRepo
description: 'Set the GitHub repository.'
scope:
- PARAMETERS
- STAGES
- STEPS
type: string
mandatory: true
- name: githubServerUrl
description: 'GitHub server url for end-user access.'
scope:
- PARAMETERS
- STAGES
- STEPS
type: string
default: https://github.com
mandatory: true
- name: githubToken
description: 'GitHub personal access token as per https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line'
scope:
- GENERAL
- PARAMETERS
- STAGES
- STEPS
type: string
mandatory: true
- name: labels
description: 'Labels to include in issue search.'
scope:
- PARAMETERS
- STAGES
- STEPS
type: '[]string'
- name: releaseBodyHeader
description: Content which will appear for the release.
scope:
- PARAMETERS
- STAGES
- STEPS
type: string
- name: update
description: Specify if the release should be updated in case it already exists
scope:
- PARAMETERS
- STAGES
- STEPS
type: bool
- name: version
description: 'Define the version number which will be written as tag as well as release name.'
scope:
- PARAMETERS
- STAGES
- STEPS
type: string
mandatory: true