-
Notifications
You must be signed in to change notification settings - Fork 784
/
step_collect.go
218 lines (194 loc) · 7.31 KB
/
step_collect.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
package cmd
import (
"fmt"
"github.com/jenkins-x/jx/pkg/collector"
"github.com/jenkins-x/jx/pkg/gits"
"io"
"os"
"path/filepath"
"strings"
jenkinsv1 "github.com/jenkins-x/jx/pkg/apis/jenkins.io/v1"
"github.com/jenkins-x/jx/pkg/kube"
"github.com/jenkins-x/jx/pkg/log"
"github.com/jenkins-x/jx/pkg/util"
"github.com/pkg/errors"
"github.com/jenkins-x/jx/pkg/jx/cmd/templates"
"github.com/spf13/cobra"
"gopkg.in/AlecAivazis/survey.v1/terminal"
)
// StepCollect contains the command line flags
type StepCollectOptions struct {
StepOptions
Pattern []string
Dir string
Basedir string
StorageLocation jenkinsv1.StorageLocation
ProjectGitURL string
ProjectBranch string
}
const (
envVarBranchName = "BRANCH_NAME"
envVarSourceUrl = "SOURCE_URL"
)
var (
StepCollectLong = templates.LongDesc(`
This pipeline step collects the specified files that need storing from the build into some stable storage location
`)
StepCollectExample = templates.Examples(`
# lets collect some files to the team's default storage location (which if not specified using the current git repository's gh-pages branch)
jx step collect -c tests -p "target/test-reports/*"
# lets collect some files to a specific Git URL
jx step collect -c tests -p "target/test-reports/*" --git-url https://github.com/myuser/myrepo.git
# lets collect some files with the file names relative to the 'target/test-reports' folder and store in a Git URL
jx step collect -c tests -p "target/test-reports/*" --basedir target/test-reports --git-url https://github.com/myuser/myrepo.git
# lets collect some files to a specific HTTP URL
jx step collect -c coverage -p "build/coverage/*" --http-url https://myserver.cheese/
`)
)
func NewCmdStepCollect(f Factory, in terminal.FileReader, out terminal.FileWriter, errOut io.Writer) *cobra.Command {
options := StepCollectOptions{
StepOptions: StepOptions{
CommonOptions: CommonOptions{
Factory: f,
In: in,
Out: out,
Err: errOut,
},
},
}
cmd := &cobra.Command{
Use: "collect",
Short: "Collects the specified files that need storing from the build",
Long: StepCollectLong,
Example: StepCollectExample,
Run: func(cmd *cobra.Command, args []string) {
options.Cmd = cmd
options.Args = args
err := options.Run()
CheckErr(err)
},
}
cmd.Flags().StringArrayVarP(&options.Pattern, "pattern", "p", nil, "Specify the pattern to use to look for files")
cmd.Flags().StringVarP(&options.Dir, "dir", "", "", "The source directory to try detect the current git repository or branch. Defaults to using the current directory")
cmd.Flags().StringVarP(&options.Basedir, "basedir", "", "", "The base directory to use to create relative output file names. e.g. if you specify '--pattern \"target/*.xml\" then you may want to supply '--basedir target' to strip the 'target/' prefix from all collected files")
cmd.Flags().StringVarP(&options.StorageLocation.BucketURL, "bucket-url", "", "", "Specify the cloud storage bucket URL to send each file to")
cmd.Flags().StringVarP(&options.ProjectGitURL, "project-git-url", "", "", "The project git URL to collect for. Used to default the organisation and repository folders in the storage. If not specified its discovered from the local '.git' folder")
cmd.Flags().StringVarP(&options.ProjectBranch, "project-branch", "", "", "The project git branch of the project to collect for. Used to default the branch folder in the storage. If not specified its discovered from the local '.git' folder")
cmd.Flags().StringVarP(&options.StorageLocation.Classifier, "classifier", "c", "", "A name which classifies this type of file. Example values: "+kube.ClassificationValues)
return cmd
}
func (o *StepCollectOptions) Run() error {
if len(o.Pattern) == 0 {
return util.MissingOption("pattern")
}
classifier := o.StorageLocation.Classifier
if classifier == "" {
return util.MissingOption("classifier")
}
var err error
if o.Dir == "" {
o.Dir, err = os.Getwd()
if err != nil {
return err
}
}
settings, err := o.TeamSettings()
if err != nil {
return err
}
if o.StorageLocation.IsEmpty() {
// lets try get the location from the team settings
o.StorageLocation = *settings.StorageLocationOrDefault(classifier)
if o.StorageLocation.IsEmpty() {
// we have no team settings so lets try detect the git repository using an env var or local file system
sourceURL := os.Getenv(envVarSourceUrl)
if sourceURL == "" {
_, gitConf, err := o.Git().FindGitConfigDir(o.Dir)
if err != nil {
log.Warnf("Could not find a .git directory: %s\n", err)
} else {
sourceURL, err = o.discoverGitURL(gitConf)
}
}
if sourceURL == "" {
return fmt.Errorf("Missing option --git-url and we could not detect the current git repository URL")
}
o.StorageLocation.GitURL = sourceURL
}
}
if o.StorageLocation.IsEmpty() {
return fmt.Errorf("Missing option --git-url and we could not detect the current git repository URL")
}
coll, err := collector.NewCollector(&o.StorageLocation, settings, o.Git())
if err != nil {
return errors.Wrapf(err, "failed to create the collector for storage settings %s", o.StorageLocation.Description())
}
client, ns, err := o.CreateJXClient()
if err != nil {
return errors.Wrap(err, "cannot create the JX client")
}
buildNo := o.getBuildNumber()
var projectGitInfo *gits.GitRepository
if o.ProjectGitURL != "" {
projectGitInfo, err = gits.ParseGitURL(o.ProjectGitURL)
if err != nil {
return errors.Wrapf(err, "failed to parse the git URL %s", o.ProjectGitURL)
}
} else {
dir := ""
projectGitInfo, err = o.FindGitInfo(dir)
if err != nil {
return errors.Wrapf(err, "failed to find the git information in the directory %s", dir)
}
}
projectOrg := projectGitInfo.Organisation
projectRepoName := projectGitInfo.Name
projectBranchName := o.ProjectBranch
if projectBranchName == "" {
projectBranchName = os.Getenv(envVarBranchName)
}
if projectBranchName == "" {
// lets try find the branch name via git
projectBranchName, err = o.Git().Branch(o.Dir)
if err != nil {
return err
}
}
if projectBranchName == "" {
return fmt.Errorf("Environment variable %s is empty", envVarBranchName)
}
repoPath := filepath.Join("jenkins-x", classifier, projectOrg, projectRepoName, projectBranchName, buildNo)
urls, err := coll.CollectFiles(o.Pattern, repoPath, o.Basedir)
if err != nil {
return errors.Wrapf(err, "failed to collect patterns %s to path %s", strings.Join(o.Pattern, ", "), repoPath)
}
for _, u := range urls {
log.Infof("Cpllected: %s\n", util.ColorInfo(u))
}
// TODO this pipeline name construction needs moving to a shared lib, and other things refactoring to use it
pipeline := fmt.Sprintf("%s-%s-%s-%s", projectOrg, projectRepoName, projectBranchName, buildNo)
activities := client.JenkinsV1().PipelineActivities(ns)
if pipeline != "" && buildNo != "" {
name := kube.ToValidName(pipeline)
key := &kube.PromoteStepActivityKey{
PipelineActivityKey: kube.PipelineActivityKey{
Name: name,
Pipeline: pipeline,
Build: buildNo,
},
}
a, _, err := key.GetOrCreate(activities)
if err != nil {
return err
}
a.Spec.Attachments = append(a.Spec.Attachments, jenkinsv1.Attachment{
Name: classifier,
URLs: urls,
})
_, err = client.JenkinsV1().PipelineActivities(ns).Update(a)
if err != nil {
return err
}
}
return nil
}