Example #1
0
//LoadLastUpdate loads the last update
func LoadLastUpdate(fname string) (Update, error) {
	file, err := ioutil.ReadFile(fname)
	log.Infof("opening file: \"%s\"...", fname)
	if err != nil {
		log.Warnf("error occured opening file: \"%s\" ...", fname)
		log.Warnf(err.Error())
		log.Warnf("continue the process with the new settings")
		update := Update{
			Time:      time.Date(1970, time.November, 10, 15, 0, 0, 0, time.Local),
			Succeeded: true,
			Status:    "inprogress"}
		return update, nil
	}

	log.Infof("loading last update form \"%s\"\n", string(file))
	var update Update
	if err := json.Unmarshal(file, &update); err != nil {
		log.Warnf("failed to load \"%s\" ...", fname)
		log.Warnf(err.Error())
		log.Warnf("continue the process with the new settings")
		update := Update{
			Time:      time.Now(),
			Succeeded: true,
			Status:    "inprogress"}
		return update, nil
	}

	if update.Status == "inprogress" {
		return Update{}, errors.New("update is currently run in another process")
	}

	log.Info("setting update status into \"inprogress\"...")
	return update, nil
}
Example #2
0
func (e *Walter) runService() bool {
	// load .walter-update
	log.Infof("Loading update file... \"%s\"", e.Engine.Resources.RepoService.GetUpdateFilePath())
	update, err := services.LoadLastUpdate(e.Engine.Resources.RepoService.GetUpdateFilePath())
	log.Infof("Succeeded loading update file")

	log.Info("Updating status...")
	update.Status = "inprogress"
	result := services.SaveLastUpdate(e.Engine.Resources.RepoService.GetUpdateFilePath(), update)
	if result == false {
		log.Error("Failed to save status update")
		return false
	}
	log.Info("Succeeded updating status")

	// get latest commit and pull requests
	log.Info("downloading commits and pull requests...")
	commits, err := e.Engine.Resources.RepoService.GetCommits(update)
	if err != nil {
		log.Errorf("Failed getting commits: %s", err)
		return false
	}

	log.Info("Succeeded getting commits")
	log.Info("Size of commits: " + strconv.Itoa(commits.Len()))
	hasFailedProcess := false
	for commit := commits.Front(); commit != nil; commit = commit.Next() {
		commitType := reflect.TypeOf(commit.Value)
		if commitType.Name() == "RepositoryCommit" {
			log.Info("Found new repository commit")
			trunkCommit := commit.Value.(github.RepositoryCommit)
			if result := e.processTrunkCommit(trunkCommit); result == false {
				hasFailedProcess = true
			}
		} else if commitType.Name() == "PullRequest" {
			log.Info("Found new pull request commit")
			pullreq := commit.Value.(github.PullRequest)
			if result := e.processPullRequest(pullreq); result == false {
				hasFailedProcess = true
			}
		} else {
			log.Errorf("Nothing commit type: %s", commitType)
			hasFailedProcess = true
		}
	}

	// save .walter-update
	log.Info("Saving update file...")
	update.Status = "finished"
	update.Time = time.Now()
	result = services.SaveLastUpdate(e.Engine.Resources.RepoService.GetUpdateFilePath(), update)
	if result == false {
		log.Error("Failed to save update")
		return false
	}
	return !hasFailedProcess
}
Example #3
0
func (e *Engine) executePipeline(pipeline *pipelines.Pipeline, name string) stages.Mediator {
	log.Infof("Preparing to run %s process...", name)
	var mediator stages.Mediator
	for stageItem := pipeline.Stages.Front(); stageItem != nil; stageItem = stageItem.Next() {
		log.Debugf("Executing planned stage: %s\n", stageItem.Value)
		mediator = e.Execute(stageItem.Value.(stages.Stage), mediator)
	}
	log.Infof("Finished running %s process...", name)
	return mediator
}
Example #4
0
// Run exectues specified shell script.
func (shellScriptStage *ShellScriptStage) Run() bool {
	log.Infof("[shell] exec: %s", shellScriptStage.BaseStage.StageName)
	log.Debugf("[shell] specified file: %s\n", shellScriptStage.File)
	if shellScriptStage.preCheck() == false {
		log.Infof("failed preCheck before running script...")
		return false
	}
	shellScriptStage.AddCommand("sh " + shellScriptStage.File)
	return shellScriptStage.CommandStage.Run()
}
Example #5
0
func (commandStage *CommandStage) runOnlyIf() bool {
	if commandStage.OnlyIf == "" {
		return true
	}
	log.Infof("[command] only_if: found \"only_if\" attribute in stage \"%s\"", commandStage.BaseStage.StageName)
	cmd := exec.Command("sh", "-c", commandStage.OnlyIf)
	log.Infof("[command] only_if: %s", commandStage.BaseStage.StageName)
	log.Debugf("[command] only_if literal: %s", commandStage.OnlyIf)
	cmd.Dir = commandStage.Directory
	result, _, _ := execCommand(cmd, "only_if", commandStage.BaseStage.StageName)
	return result
}
Example #6
0
//Post posts a message to slack
func (slack *Slack) Post(message string, c ...string) bool {
	if slack.Channel[0] != '#' {
		log.Infof("Add # to channel name: %s", slack.Channel)
		slack.Channel = "#" + slack.Channel
	}

	var color string
	if len(c) > 0 {
		color = c[0]
	}

	if strings.Contains(message, "[RESULT] Failed") {
		color = "danger"
	} else if strings.Contains(message, "[RESULT] Skipped") {
		color = "warning"
	} else if strings.Contains(message, "[RESULT] Succeeded") {
		color = "good"
	}

	attachment := map[string]string{
		"text":  message,
		"color": color,
	}

	attachments := []map[string]string{attachment}

	params, _ := json.Marshal(struct {
		FakeSlack
		Attachments []map[string]string `json:"attachments"`
	}{
		FakeSlack:   FakeSlack(*slack),
		Attachments: attachments,
	})

	resp, err := http.PostForm(
		slack.IncomingURL,
		url.Values{"payload": {string(params)}},
	)
	if err != nil {
		log.Errorf("Failed post message to Slack...: %s", message)
		return false
	}
	defer resp.Body.Close()

	if body, err := ioutil.ReadAll(resp.Body); err == nil {
		log.Infof("Slack post result...: %s", body)
		return true
	}
	log.Errorf("Failed to read result from Slack...")
	return false
}
Example #7
0
//GetCommits get a list of all the commits for the current update
func (githubClient *GitHubClient) GetCommits(update Update) (*list.List, error) {
	log.Info("getting commits\n")
	commits := list.New()
	ts := oauth2.StaticTokenSource(
		&oauth2.Token{AccessToken: githubClient.Token},
	)
	tc := oauth2.NewClient(oauth2.NoContext, ts)
	client := github.NewClient(tc)

	// get a list of pull requests with Pull Request API
	pullreqs, _, err := client.PullRequests.List(
		githubClient.From, githubClient.Repo,
		&github.PullRequestListOptions{})
	if err != nil {
		log.Errorf("Failed to get pull requests")
		return list.New(), err
	}

	re, err := regexp.Compile(githubClient.TargetBranch)
	if err != nil {
		log.Error("Failed to compile branch pattern...")
		return list.New(), err
	}

	log.Infof("Size of pull reqests: %d", len(pullreqs))
	for _, pullreq := range pullreqs {
		log.Infof("Branch name is \"%s\"", *pullreq.Head.Ref)

		if githubClient.TargetBranch != "" {
			matched := re.Match([]byte(*pullreq.Head.Ref))
			if matched != true {
				log.Infof("Not add a branch, \"%s\" since this branch name is not match the filtering pattern", *pullreq.Head.Ref)
				continue
			}
		}

		if *pullreq.State == "open" && pullreq.UpdatedAt.After(update.Time) {
			log.Infof("Adding pullrequest %d", *pullreq.Number)
			commits.PushBack(pullreq)
		}
	}

	// get the latest commit with Commit API if the commit is newer than last update
	masterCommits, _, _ := client.Repositories.ListCommits(
		githubClient.From, githubClient.Repo, &github.CommitsListOptions{})
	if masterCommits[0].Commit.Author.Date.After(update.Time) {
		commits.PushBack(masterCommits[0])
	}
	return commits, nil
}
Example #8
0
// New creates a Walter instance.
func New(opts *config.Opts) (*Walter, error) {
	log.Infof("Pipeline file path: \"%s\"", opts.PipelineFilePath)
	configData, err := config.ReadConfig(opts.PipelineFilePath)
	if err != nil {
		log.Warn("failed to read the configuration file")
		return nil, err
	}

	envs := config.NewEnvVariables()
	parser := &config.Parser{ConfigData: configData, EnvVariables: envs}
	resources, err := parser.Parse()
	if err != nil {
		log.Warn("failed to parse the configuration")
		return nil, err
	}
	monitorCh := make(chan stages.Mediator)
	engine := &engine.Engine{
		Resources:    resources,
		Opts:         opts,
		MonitorCh:    &monitorCh,
		EnvVariables: envs,
	}
	return &Walter{
		Opts:   opts,
		Engine: engine,
	}, nil
}
Example #9
0
//RegisterResult registers the supplied result
func (githubClient *GitHubClient) RegisterResult(result Result) error {
	ts := oauth2.StaticTokenSource(
		&oauth2.Token{AccessToken: githubClient.Token},
	)
	tc := oauth2.NewClient(oauth2.NoContext, ts)
	client := github.NewClient(tc)

	if githubClient.BaseUrl != nil {
		client.BaseURL = githubClient.BaseUrl
	}

	log.Info("Submitting result")
	repositories := client.Repositories
	status, _, err := repositories.CreateStatus(
		githubClient.From,
		githubClient.Repo,
		result.SHA,
		&github.RepoStatus{
			State:       github.String(result.State),
			TargetURL:   github.String(result.Url),
			Description: github.String(result.Message),
			Context:     github.String("continuous-integraion/walter"),
		})
	log.Infof("Submit status: %s", status)
	if err != nil {
		log.Errorf("Failed to register result: %s", err)
	}
	return err
}
Example #10
0
func printOutput(r io.Reader, prefix string, name string, out chan string, done chan bool) {
	scanner := bufio.NewScanner(r)
	for scanner.Scan() {
		log.Infof("[%s][command] %s output: %s", name, prefix, scanner.Text())
		out <- fmt.Sprintf("%s\n", scanner.Text())
	}
	done <- true
}
Example #11
0
func (commandStage *CommandStage) runCommand() bool {
	cmd := exec.Command("sh", "-c", commandStage.Command)
	log.Infof("[command] exec: %s", commandStage.BaseStage.StageName)
	log.Debugf("[command] exec command literal: %s", commandStage.Command)
	cmd.Dir = commandStage.Directory
	result, outResult, errResult := execCommand(cmd, "exec", commandStage.BaseStage.StageName)
	commandStage.SetOutResult(*outResult)
	commandStage.SetErrResult(*errResult)
	return result
}
Example #12
0
func (e *Walter) processTrunkCommit(commit github.RepositoryCommit) bool {
	log.Infof("Checkout master branch")
	_, err := exec.Command("git", "checkout", "master", "-f").Output()
	if err != nil {
		log.Errorf("Failed to checkout master branch: %s", err)
		return false
	}
	log.Infof("Downloading new commit from master")
	_, err = exec.Command("git", "pull", "origin", "master").Output()
	if err != nil {
		log.Errorf("Failed to download new commit from master: %s", err)
		return false
	}
	log.Infof("Running the latest commit in master")
	w, err := New(e.Opts)
	if err != nil {
		log.Errorf("Failed to create Walter object...: %s", err)
		log.Error("Skip execution...")
		return false
	}
	result := w.Engine.RunOnce()

	// register the result to hosting service
	if result.IsSucceeded() {
		log.Info("Succeeded.")
		e.Engine.Resources.RepoService.RegisterResult(
			services.Result{
				State:   "success",
				Message: "Succeeded running pipeline...",
				SHA:     *commit.SHA})
		return true
	}
	log.Error("Error reported...")
	e.Engine.Resources.RepoService.RegisterResult(
		services.Result{
			State:   "failure",
			Message: "Failed running pipleline ...",
			SHA:     *commit.SHA})
	return false

}
Example #13
0
func (commandStage *CommandStage) runCommand() bool {
	cmd := exec.Command("sh", "-c", commandStage.Command)
	log.Infof("[command] exec: %s", commandStage.BaseStage.StageName)
	log.Debugf("[command] exec command literal: %s", commandStage.Command)
	cmd.Dir = commandStage.Directory
	commandStage.SetStart(time.Now().Unix())
	result, outResult, errResult, combinedResult := execCommand(cmd, "exec", commandStage.BaseStage.StageName)
	commandStage.SetEnd(time.Now().Unix())
	commandStage.SetOutResult(*outResult)
	commandStage.SetErrResult(*errResult)
	commandStage.SetCombinedResult(*combinedResult)
	commandStage.SetReturnValue(result)
	return result
}
Example #14
0
//SaveLastUpdate saves the supplied update to the filename
func SaveLastUpdate(fname string, update Update) bool {
	log.Infof("writing down new update: \"%s\"\n", string(fname))
	bytes, err := json.Marshal(update)
	if err != nil {
		log.Errorf("failed to convert update to string...: %s\n", err)
		return false
	}

	if exist := fileExists(fname); exist == true {
		log.Infof("file exist: \"%s\"", fname)
		if err := os.Remove(fname); err != nil {
			log.Errorf("failed to remove \"%s\" with error: \"%s\"", fname, err)
			return false
		}
		log.Infof("succeeded to remove: \"%s\"", fname)
	}

	if err := ioutil.WriteFile(fname, bytes, 0644); err != nil {
		log.Errorf("failed to write update to file...: \"%s\"\n", err)
		return false
	}
	log.Infof("succeeded to write update file: \"%s\"", fname)
	return true
}
Example #15
0
func printOutput(r io.Reader, prefix string, name string, out chan string, done chan bool) {
	reader := bufio.NewReaderSize(r, 1048576)
	for {
		line, _, err := reader.ReadLine()

		if err == io.EOF {
			break
		} else if err != nil {
			log.Error(err.Error())
			os.Exit(1)
		}

		log.Infof("[%s][command] %s output: %s", name, prefix, string(line))
		out <- fmt.Sprintf("%s\n", string(line))
	}
	done <- true
}
Example #16
0
func copyStream(reader io.Reader, prefix string, name string) string {
	var err error
	var n int
	var buffer bytes.Buffer
	tmpBuf := make([]byte, 1024)
	for {
		if n, err = reader.Read(tmpBuf); err != nil {
			break
		}
		buffer.Write(tmpBuf[0:n])
		log.Infof("[%s][command] %s output: %s", name, prefix, tmpBuf[0:n])
	}
	if err == io.EOF {
		err = nil
	} else {
		log.Error("ERROR: " + err.Error())
	}
	return buffer.String()
}
Example #17
0
//RegisterResult registers the supplied result
func (githubClient *GitHubClient) RegisterResult(result Result) error {
	t := &oauth.Transport{
		Token: &oauth.Token{AccessToken: githubClient.Token},
	}
	client := github.NewClient(t.Client())

	log.Info("Submitting result")
	repositories := client.Repositories
	status, _, err := repositories.CreateStatus(
		githubClient.From,
		githubClient.Repo,
		result.SHA,
		&github.RepoStatus{
			State:       github.String(result.State),
			TargetURL:   github.String(result.Url),
			Description: github.String(result.Message),
			Context:     github.String("continuous-integraion/walter"),
		})
	log.Infof("Submit status: %s", status)
	if err != nil {
		log.Errorf("Failed to register result: %s", err)
	}
	return err
}