Skip to content

Commit

Permalink
feat: add job build and wait log with exit code
Browse files Browse the repository at this point in the history
add job build and wait log with exit code and fix test error

Log:
Change-Id: I8ae90c8649cbbb817e339119f75db54caa6fd0e3
  • Loading branch information
feiguoL committed Jan 16, 2025
1 parent 8616825 commit 9319fcc
Show file tree
Hide file tree
Showing 23 changed files with 334 additions and 62 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
# Output of the go coverage tool, specifically when used with LiteIDE
*.out

bin/
bin/**/jcli
release/
jcli

Expand Down
12 changes: 12 additions & 0 deletions .jenkins-cli.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
current: test
jenkins_servers:
- name: yourServer
url: http://localhost:8080/jenkins
username: test
token: 211e3a2f0231198856dceaff96f2v75ce3
insecureSkipVerify: true
#mirrors:
#- name: default
# url: http://mirrors.jenkins.io/
# Language context is accept-language for HTTP header, It contains zh-CN/zh-TW/en/en-US/ja and so on
# Goto 'http://localhost:8080/jenkins/me/configure', then you can generate your token.
6 changes: 4 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ COPY . .
RUN CGO_ENABLED=0 go build -v -a -o jcli .

FROM alpine:3.10
COPY --from=builder /work/jcli /usr/bin/jcli
COPY --from=builder /work/bin/linux/jcli /usr/bin/jcli
RUN jcli config generate -i=false > ~/.jenkins-cli.yaml
COPY bin/build.sh /usr/bin/jclih
RUN chmod +x /usr/bin/jclih

ENTRYPOINT ["jcli"]
ENTRYPOINT ["jclih"]
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ gen-data-darwin: go-bindata-download-darwin

verify: dep tools lint

pre-build:
pre-build: fmt vet
export GO111MODULE=on
export GOPROXY=https://goproxy.io
go mod tidy
Expand Down
8 changes: 4 additions & 4 deletions app/cmd/backup.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (
"github.com/spf13/cobra"
)

//BackupOption is an option for backup
// BackupOption is an option for backup
type BackupOption struct {
RoundTripper http.RoundTripper
BackupDir string
Expand All @@ -38,7 +38,7 @@ var backupCmd = &cobra.Command{
RunE: backupOption.Backup,
}

//Check will find out whether Thin Backup Plugin installed or not
// Check will find out whether Thin Backup Plugin installed or not
func (o *BackupOption) Check() (err error) {
opt := PluginOptions{
Option: common.Option{RoundTripper: o.RoundTripper},
Expand All @@ -47,7 +47,7 @@ func (o *BackupOption) Check() (err error) {
return
}

//Backup will trigger thinBackup plugin to make a backup
// Backup will trigger thinBackup plugin to make a backup
func (o *BackupOption) Backup(cmd *cobra.Command, _ []string) (err error) {
jClient := &client.CoreClient{
JenkinsCore: client.JenkinsCore{
Expand Down Expand Up @@ -88,7 +88,7 @@ func (o *BackupOption) Backup(cmd *cobra.Command, _ []string) (err error) {
return
}

//ThinBackupAPI requests backupManual api
// ThinBackupAPI requests backupManual api
func ThinBackupAPI(client *client.CoreClient) (err error) {
_, err = client.RequestWithoutData(http.MethodGet, "/thinBackup/backupManual", nil, nil, 200)
return err
Expand Down
14 changes: 7 additions & 7 deletions app/cmd/center_list.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,31 +14,31 @@ import (
"github.com/spf13/cobra"
)

//LtsURL is the URL of stable Jenkins RSS
// LtsURL is the URL of stable Jenkins RSS
const LtsURL = "https://www.jenkins.io/changelog-stable/rss.xml"

//WidthOfDescription is the width of the description column
// WidthOfDescription is the width of the description column
const WidthOfDescription = 60

//ASCIIOfLineFeed is the ASCII of line feed
// ASCIIOfLineFeed is the ASCII of line feed
const ASCIIOfLineFeed = 10

//ASCIIOfSpace is the ASCII of space
// ASCIIOfSpace is the ASCII of space
const ASCIIOfSpace = 32

//CenterListOption as options for Jenkins RSS
// CenterListOption as options for Jenkins RSS
type CenterListOption struct {
Channel Channel `xml:"channel"`
// RoundTripper http.RoundTripper
}

//Channel as part of CenterListOption
// Channel as part of CenterListOption
type Channel struct {
Title string `xml:"title"`
Items []Item `xml:"item"`
}

//Item as a option for information of newly-released Jenkins
// Item as a option for information of newly-released Jenkins
type Item struct {
Title string `xml:"title"`
Description string `xml:"description"`
Expand Down
2 changes: 1 addition & 1 deletion app/cmd/common/plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package common

import "fmt"

//GetJCLIPluginPath returns the path of a jcli plugin
// GetJCLIPluginPath returns the path of a jcli plugin
func GetJCLIPluginPath(userHome, name string, binary bool) string {
suffix := ".yaml"
if binary {
Expand Down
2 changes: 1 addition & 1 deletion app/cmd/condition/plugin_dep.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ type PluginDepCheck struct {
pluginName, targetVersion string
}

//NewChecker returns a plugin dep checker
// NewChecker returns a plugin dep checker
func NewChecker(jenkins *appCfg.JenkinsServer, roundTripper http.RoundTripper, pluginName, targetVersion string) (
checker *PluginDepCheck) {
checker = &PluginDepCheck{
Expand Down
62 changes: 45 additions & 17 deletions app/cmd/job_build.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"encoding/json"
"fmt"
"strings"
"time"

"github.com/jenkins-zh/jenkins-cli/app/cmd/common"
"github.com/jenkins-zh/jenkins-cli/app/i18n"
Expand All @@ -18,15 +19,18 @@ type JobBuildOption struct {
common.Option
cobra_ext.OutputOption

Param string
ParamArray []string
Param string
ParamArray []string
ParamJsonString string

ParamFilePathArray []string

Wait bool
WaitTime int
Delay int
Cause string
Wait bool
WaitTime int
WaitInterval int
Delay int
Cause string
LogConsole bool
}

var jobBuildOption JobBuildOption
Expand All @@ -40,23 +44,28 @@ func init() {
jobCmd.AddCommand(jobBuildCmd)
jobBuildCmd.Flags().BoolVarP(&jobBuildOption.Batch, "batch", "b", false, "Batch mode, no need confirm")
jobBuildCmd.Flags().StringVarP(&jobBuildOption.Param, "param", "", "",
i18n.T("Parameters of the job which is JSON format"))
i18n.T("Parameters of the job which is JSON format, for example: --param '{\"limit\":\"2\",\"timeoutLimit\":\"10\"}'"))
jobBuildCmd.Flags().StringArrayVar(&jobBuildOption.ParamArray, "param-entry", nil,
i18n.T("Parameters of the job which are the entry format, for example: --param-entry name=value"))
i18n.T("Parameters of the job which are the entry format, for example: --param-entry name1=value1, --param-entry name2=value2"))
jobBuildCmd.Flags().StringArrayVar(&jobBuildOption.ParamFilePathArray, "param-file", nil,
i18n.T("Parameters of the job which is file path, for example: --param-file name=filename"))
jobBuildCmd.Flags().BoolVarP(&jobBuildOption.Wait, "wait", "", false,
i18n.T("If you want to wait for the build ID from Jenkins. You need to install plugin pipeline-restful-api first"))
jobBuildCmd.Flags().IntVarP(&jobBuildOption.WaitTime, "wait-timeout", "", 30,
jobBuildCmd.Flags().IntVarP(&jobBuildOption.WaitTime, "wait-timeout", "", 60,
i18n.T("The timeout of seconds when you wait for the build ID"))
jobBuildCmd.Flags().IntVarP(&jobBuildOption.WaitInterval, "wait-interval", "", 10,
i18n.T("The interval of seconds when you want to wait for buildID... query, use with wait"))
jobBuildCmd.Flags().IntVarP(&jobBuildOption.Delay, "delay", "", 0,
i18n.T("Delay when trigger a Jenkins job"))
jobBuildCmd.Flags().StringVarP(&jobBuildOption.Cause, "cause", "", "triggered by jcli",
i18n.T("The cause of a job build"))
jobBuildCmd.Flags().BoolVarP(&jobBuildOption.LogConsole, "log", "l", false,
i18n.T("If you want to wait for build log and wait log output end"))

jobBuildOption.SetFlagWithHeaders(jobBuildCmd, "Number,URL")
jobBuildOption.BatchOption.Stdio = common.GetSystemStdio()
jobBuildOption.Option.Stdio = common.GetSystemStdio()

}

var jobBuildCmd = &cobra.Command{
Expand All @@ -66,15 +75,28 @@ var jobBuildCmd = &cobra.Command{
You need to give the parameters if your pipeline has them. Learn more about it from https://jenkins.io/doc/book/pipeline/syntax/#parameters.`),
Args: cobra.MinimumNArgs(1),
PreRunE: func(_ *cobra.Command, _ []string) (err error) {
if jobBuildOption.ParamArray == nil && jobBuildOption.ParamFilePathArray == nil {
if jobBuildOption.ParamArray == nil && jobBuildOption.ParamFilePathArray == nil && jobBuildOption.Param == "" {
return
}

paramDefs := make([]client.ParameterDefinition, 0)
if jobBuildOption.Param != "" {
if err = json.Unmarshal([]byte(jobBuildOption.Param), &paramDefs); err != nil {
paramMap := make(map[string]interface{})
if err = json.Unmarshal([]byte(jobBuildOption.Param), &paramMap); err != nil {
logger.Error(fmt.Sprintf("build param unmarshal error %v", err.Error()))
return
}
for key, value := range paramMap {
if key == "" || value == nil {
logger.Error("build param key or value empty")
return
}
paramDefs = append(paramDefs, client.ParameterDefinition{
Name: key,
Value: fmt.Sprintf("%v", value),
Type: client.StringParameterDefinition,
})
}
}

for _, paramEntry := range jobBuildOption.ParamArray {
Expand Down Expand Up @@ -113,6 +135,7 @@ You need to give the parameters if your pipeline has them. Learn more about it f
jclient := &client.JobClient{
JenkinsCore: client.JenkinsCore{
RoundTripper: jobBuildOption.RoundTripper,
Timeout: time.Duration(jobBuildOption.WaitTime) * time.Second,
},
}
getCurrentJenkinsAndClient(&(jclient.JenkinsCore))
Expand Down Expand Up @@ -150,13 +173,18 @@ You need to give the parameters if your pipeline has them. Learn more about it f
}

if err == nil {
options := client.JobCmdOptionsCommon{
Wait: jobBuildOption.Wait,
WaitTime: jobBuildOption.WaitTime,
WaitInterval: jobBuildOption.WaitInterval,
LogConsole: jobBuildOption.LogConsole,
}

if hasParam {
err = jclient.BuildWithParams(name, paramDefs)
} else if jobBuildOption.Wait {
var build client.IdentityBuild
if build, err = jclient.BuildAndReturn(name, jobBuildOption.Cause, jobBuildOption.WaitTime, jobBuildOption.Delay); err == nil {
jobBuildOption.Writer = cmd.OutOrStdout()
err = jobBuildOption.OutputV2([1]client.SimpleJobBuild{build.Build.SimpleJobBuild})
var jobState client.JenkinsBuildState
jobState, err = jclient.BuildWithParamsGetResponse(name, paramDefs, options)
if err == nil && jobBuildOption.LogConsole && jobState.RunId > 0 {
err = printLogRunFunc(name, JobLogOptionGetDefault(int(jobState.RunId)), cmd)
}
} else {
err = jclient.Build(name)
Expand Down
5 changes: 2 additions & 3 deletions app/cmd/job_delete_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import (

"github.com/AlecAivazis/survey/v2/terminal"
"github.com/golang/mock/gomock"
"github.com/hinshun/vt10x"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/stretchr/testify/require"
Expand Down Expand Up @@ -180,9 +179,9 @@ func RunTest(t *testing.T, test func(terminal.Stdio) error, procedures ...func(*
// Multiplex output to a buffer as well for the raw bytes.
buf := new(bytes.Buffer)

//c, err := expect.NewConsole(expect.WithStdout(buf))
c, err := expect.NewConsole(expect.WithStdout(buf))
//c, err := expect.NewConsole(expect.WithStdout(os.Stdout))
c, _, err := vt10x.NewVT10XConsole(expect.WithStdout(buf))
//c, _, err := vt10x.New(expect.WithStdout(buf))

require.Nil(t, err)
defer c.Close()
Expand Down
2 changes: 1 addition & 1 deletion app/cmd/job_edit.go
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ func (j *JobEditOption) getSampleJenkinsfile() string {
`
}

//func getPipeline(name string) (script string, err error) {
// func getPipeline(name string) (script string, err error) {
func (j *JobEditOption) getPipeline(jClient *client.JobClient, name string) (script string, err error) {
script = j.Script //we take the script from input firstly
if script != "" {
Expand Down
20 changes: 17 additions & 3 deletions app/cmd/job_log.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,16 +142,16 @@ func printLogRunFunc(jobName string, jobLogOption JobLogOption, cmd *cobra.Comma

if lastBuildID != jobLogOption.LastBuildID {
lastBuildID = jobLogOption.LastBuildID
cmd.Println("Current build number:", jobLogOption.LastBuildID)
cmd.Println("Current build url:", jobLogOption.LastBuildURL)
cmd.Println("[INFO] Current build number:", jobLogOption.LastBuildID)
cmd.Printf("[INFO] Current build url: %sconsole\n", jobLogOption.LastBuildURL)

err = printLog(jclient, cmd, name, jobLogOption.History, 0, jobLogOption.NumberOfLines)
}

if err != nil || !jobLogOption.Watch {
if err.Error() == LogFinishMsg {
err = nil
cmd.Println("[INFO] current log finish output")
cmd.Println("[INFO] current log finish output... exit")
if jobLogOption.ExitCode {
if jobBuild, err = jclient.GetBuild(name, jobLogOption.History); err == nil {
if jobBuild.Result == JobResultFailed {
Expand All @@ -169,3 +169,17 @@ func printLogRunFunc(jobName string, jobLogOption JobLogOption, cmd *cobra.Comma
}
return
}

// JobLogOptionGetDefault get default config for job log
func JobLogOptionGetDefault(runId int) JobLogOption {
return JobLogOption{
History: runId,
WatchOption: common.WatchOption{
Watch: true,
Interval: jobBuildOption.WaitInterval,
Count: 9999,
},
NumberOfLines: 9999,
ExitCode: true,
}
}
2 changes: 1 addition & 1 deletion app/cmd/plugin_apitest.go
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ func (o *pluginAPITestOption) test(cmd *cobra.Command, args []string) (err error
return err
}

//CheckFileExists returns true if exits and returns false if not
// CheckFileExists returns true if exits and returns false if not
func CheckFileExists(path string) (exist bool, err error) {
_, err = os.Stat(path)
if err == nil {
Expand Down
2 changes: 1 addition & 1 deletion app/cmd/plugin_center.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import (
"github.com/spf13/cobra"
)

//NewPluginOption consists of four options
// NewPluginOption consists of four options
type NewPluginOption struct {
Name string `json:"name"`
Version string `json:"gav"`
Expand Down
12 changes: 7 additions & 5 deletions app/i18n/bindata.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 15 additions & 0 deletions bin/build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#!/bin/sh

set -e

BIN_PATH=/usr/bin/jcli

# If we run make directly, any files created on the bind mount
# will have awkward ownership. So we switch to a user with the
# same user and group IDs as source directory. We have to set a
# few things up so that sudo works without complaining later on.
${BIN_PATH} job build ${JOB_NAME} \
-b --url https://xxxx.com \
--config-load false \
--wait -l \
--logger-level info $*
Loading

0 comments on commit 9319fcc

Please sign in to comment.