Example #1
0
// Once update set has been tested, we must send the result to Gemnasium,
// in order to update statitics.
func pushUpdateSetResult(rs *UpdateSetResult) error {
	fmt.Printf("Pushing result (status='%s'): ", rs.State)

	if rs.UpdateSetID == 0 || rs.State == "" {
		return errors.New("Missing updateSet ID and/or State args")
	}

	revision, err := getRevision()
	if err != nil {
		return err
	}

	opts := &gemnasium.APIRequestOptions{
		Method: "PATCH",
		URI:    fmt.Sprintf("/projects/%s/revisions/%s/auto_update_steps/%d", rs.ProjectSlug, revision, rs.UpdateSetID),
		Body:   rs,
	}
	err = gemnasium.APIRequest(opts)
	if err != nil {
		return err
	}

	fmt.Printf("done\n")
	return nil
}
Example #2
0
// Update project details
// http://docs.gemnasium.apiary.io/#patch-%2Fprojects%2F%7Bslug%7D
func (p *Project) Update(name, desc *string, monitored *bool) error {
	if name == nil && desc == nil && monitored == nil {
		return errors.New("Please specify at least one thing to update (name, desc, or monitored")
	}

	update := make(map[string]interface{})
	if name != nil {
		update["name"] = *name
	}
	if desc != nil {
		update["desc"] = *desc
	}
	if monitored != nil {
		update["monitored"] = *monitored
	}
	opts := &gemnasium.APIRequestOptions{
		Method: "PATCH",
		URI:    fmt.Sprintf("/projects/%s", p.Slug),
		Body:   update,
	}
	err := gemnasium.APIRequest(opts)
	if err != nil {
		return err
	}

	color.Printf("@gProject %s updated succesfully\n", p.Slug)
	return nil
}
Example #3
0
func (p *Project) Fetch() error {
	opts := &gemnasium.APIRequestOptions{
		Method: "GET",
		URI:    fmt.Sprintf("/projects/%s", p.Slug),
		Result: p,
	}
	return gemnasium.APIRequest(opts)
}
Example #4
0
// Fetch and return the dependency files ([]DependecyFile) for the current project
func (p *Project) DependencyFiles() (dfiles []DependencyFile, err error) {
	opts := &gemnasium.APIRequestOptions{
		Method: "GET",
		URI:    fmt.Sprintf("/projects/%s/dependency_files", p.Slug),
		Result: &dfiles,
	}
	err = gemnasium.APIRequest(opts)
	return dfiles, err
}
Example #5
0
// Start project synchronization
// http://docs.gemnasium.apiary.io/#post-%2Fprojects%2F%7Bslug%7D%2Fsync
func (p *Project) Sync() error {
	opts := &gemnasium.APIRequestOptions{
		Method: "POST",
		URI:    fmt.Sprintf("/projects/%s/sync", p.Slug),
	}
	err := gemnasium.APIRequest(opts)
	if err != nil {
		return err
	}

	color.Printf("@gSynchronization started for project %s\n", p.Slug)
	return nil
}
Example #6
0
// Fetch the best dependency files that have been found so far
func fetchDependencyFiles(projectSlug string) (dfiles []models.DependencyFile, err error) {
	revision, err := getRevision()
	if err != nil {
		return nil, err
	}

	opts := &gemnasium.APIRequestOptions{
		Method: "GET",
		URI:    fmt.Sprintf("/projects/%s/revisions/%s/auto_update_steps/best", projectSlug, revision),
		Result: &dfiles,
	}
	err = gemnasium.APIRequest(opts)
	return dfiles, err
}
Example #7
0
func fetchUpdateSet(projectSlug string) (*UpdateSet, error) {
	revision, err := getRevision()
	if err != nil {
		return nil, err
	}

	var updateSet *UpdateSet
	opts := &gemnasium.APIRequestOptions{
		Method: "POST",
		URI:    fmt.Sprintf("/projects/%s/revisions/%s/auto_update_steps/next", projectSlug, revision),
		Result: &updateSet,
	}
	err = gemnasium.APIRequest(opts)
	return updateSet, err
}
Example #8
0
// Push project dependencies
// The current path will be scanned for supported dependency files (SUPPORTED_DEPENDENCY_FILES)
func PushDependencyFiles(projectSlug string, files []string) error {
	dfiles, err := LookupDependencyFiles(files)
	if err != nil {
		return err
	}

	fmt.Printf("Sending files to Gemnasium: ")
	var jsonResp map[string][]DependencyFile

	opts := &gemnasium.APIRequestOptions{
		Method: "POST",
		URI:    fmt.Sprintf("/projects/%s/dependency_files", projectSlug),
		Body:   dfiles,
		Result: &jsonResp,
	}
	err = gemnasium.APIRequest(opts)
	if err != nil {
		return err
	}

	added := []string{}
	for _, df := range jsonResp["added"] {
		added = append(added, df.Path)
	}
	updated := []string{}
	for _, df := range jsonResp["updated"] {
		updated = append(updated, df.Path)
	}
	unchanged := []string{}
	for _, df := range jsonResp["unchanged"] {
		unchanged = append(unchanged, df.Path)
	}
	unsupported := []string{}
	for _, df := range jsonResp["unsupported"] {
		unsupported = append(unsupported, df.Path)
	}
	fmt.Printf("done.\n\n")
	fmt.Printf("Added: %s\n", strings.Join(added, ", "))
	fmt.Printf("Updated: %s\n", strings.Join(updated, ", "))
	fmt.Printf("Unchanged: %s\n", strings.Join(unchanged, ", "))
	fmt.Printf("Unsupported: %s\n", strings.Join(unsupported, ", "))
	return nil
}
Example #9
0
func ListDependencyAlerts(project *Project) error {
	var alerts []Alert
	opts := &gemnasium.APIRequestOptions{
		Method: "GET",
		URI:    fmt.Sprintf("/projects/%s/alerts", project.Slug),
		Result: &alerts,
	}
	err := gemnasium.APIRequest(opts)
	if err != nil {
		return err
	}

	table := tablewriter.NewWriter(os.Stdout)
	table.SetHeader([]string{"Advisory", "Date", "Status"})

	table.SetAlignment(tablewriter.ALIGN_LEFT) // table is lost when ID have 2 or 3 digits...
	for _, alert := range alerts {
		table.Append([]string{strconv.Itoa(alert.Advisory.ID), alert.OpenAt.Format(time.RFC822), alert.Status})
	}
	table.Render() // Send output
	return nil
}
Example #10
0
// List projects on gemnasium
// TODO: Add a flag to display unmonitored projects too
func ListProjects(privateProjectsOnly bool) error {
	var projects map[string][]Project
	opts := &gemnasium.APIRequestOptions{
		Method: "GET",
		URI:    LIST_PROJECTS_PATH,
		Result: &projects,
	}
	err := gemnasium.APIRequest(opts)
	if err != nil {
		return err
	}

	for owner, _ := range projects {
		MonitoredProjectsCount := 0
		if owner != "owned" {
			fmt.Printf("\nShared by: %s\n\n", owner)
		}
		table := tablewriter.NewWriter(os.Stdout)
		table.SetHeader([]string{"Name", "Slug", "Private"})
		for _, project := range projects[owner] {
			if !project.Monitored || (!project.Private && privateProjectsOnly) {
				continue
			}

			var private string
			if project.Private {
				private = "private"
			} else {
				private = ""
			}
			table.Append([]string{project.Name, project.Slug, private})
			MonitoredProjectsCount += 1
		}
		table.Render()
		color.Printf("@{g!}Found %d projects (%d unmonitored are hidden)\n\n", MonitoredProjectsCount, len(projects[owner])-MonitoredProjectsCount)
	}
	return nil
}
Example #11
0
// Live evaluation of dependency files Several files can be sent, not only from
// the same language (ie: package.json + Gemfile + Gemfile.lock) LiveEvaluation
// will return 2 stases (color for Runtime / Dev.) and the list of deps with
// their color.
func LiveEvaluation(files []string) error {

	dfiles, err := models.LookupDependencyFiles(files)
	if err != nil {
		return err
	}

	requestDeps := map[string][]*models.DependencyFile{"dependency_files": dfiles}
	var jsonResp map[string]interface{}

	opts := &gemnasium.APIRequestOptions{
		Method: "POST",
		URI:    LIVE_EVAL_PATH,
		Body:   requestDeps,
		Result: &jsonResp,
	}
	err = gemnasium.APIRequest(opts)
	if err != nil {
		return err
	}

	// Wait until job is done
	url := fmt.Sprintf("%s%s/%s", config.APIEndpoint, LIVE_EVAL_PATH, jsonResp["job_id"])
	req, err := http.NewRequest("GET", url, nil)
	if err != nil {
		return err
	}
	req.SetBasicAuth("x", config.APIKey)
	req.Header.Add("Content-Type", "application/json")
	var response struct {
		Status string `json:"status"`
		Result struct {
			RuntimeStatus     string              `json:"runtime_status"`
			DevelopmentStatus string              `json:"development_status"`
			Dependencies      []models.Dependency `json:"dependencies"`
		} `json:"result"`
	}
	var iter int // used to display the little dots for each loop bellow
	client := &http.Client{}
	for {
		// use the same request again and again
		resp, err := client.Do(req)
		if err != nil {
			return err
		}
		defer resp.Body.Close()
		body, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			return err
		}

		if resp.StatusCode != http.StatusOK {
			response.Status = "error"
		}

		if err = json.Unmarshal(body, &response); err != nil {
			return err
		}

		if !config.RawFormat { // don't display status if RawFormat
			iter += 1
			fmt.Printf("\rJob Status: %s%s", response.Status, strings.Repeat(".", iter))
		}
		if response.Status != "working" && response.Status != "queued" { // Job has completed or failed or whatever
			if config.RawFormat {
				fmt.Printf("%s\n", body)
				return nil
			}
			break
		}
		// Wait 1s before trying again
		time.Sleep(time.Second * 1)
	}

	color.Println(fmt.Sprintf("\n\n%-12.12s %s", "Run. Status", utils.StatusDots(response.Result.RuntimeStatus)))
	color.Println(fmt.Sprintf("%-12.12s %s\n\n", "Dev. Status", utils.StatusDots(response.Result.DevelopmentStatus)))

	// Display deps in an ascii table
	models.RenderDepsAsTable(response.Result.Dependencies, os.Stdout)

	if response.Result.RuntimeStatus == "red" {
		return fmt.Errorf("There are important updates available.\n")
	}

	return nil
}