<commit_before>package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"log"
	"net/http"
	"os"
	"os/exec"
	"path/filepath"
	"sort"
	"time"

	"github.com/Songmu/retry"
	"github.com/github/hub/github"
	"github.com/mitchellh/go-homedir"
	"github.com/octokit/go-octokit/octokit"
	"github.com/pkg/errors"
)

const (
	exitOK = iota
	exitError
)

const version = "0.0.0"

func main() {
	os.Exit(run(os.Args[1:]))
}

func run(argv []string) int {
	remotes, err := github.Remotes()
	if err != nil || len(remotes) < 1 {
		log.Printf("can't detect remote repository: %+v\n", err)
		return exitError
	}
	proj, err := remotes[0].Project()
	if err != nil {
		log.Printf("failed to retrieve project: %+v\n", err)
		return exitError
	}
	fs := flag.NewFlagSet("mackerel-github-release", flag.ContinueOnError)
	var (
		dryRun  = fs.Bool("dry-run", false, "dry-run mode")
		staging = fs.Bool("staging", false, "staging release")
	)
	err = fs.Parse(argv)
	if err != nil {
		if err == flag.ErrHelp {
			return exitOK

		}
		return exitError
	}

	out, err := exec.Command("gobump", "show").Output()
	if err != nil {
		log.Printf("failed to `gobump show`: %+v\n", err)
		return exitError
	}

	var v struct {
		Version string `json:"version"`
	}
	err = json.Unmarshal(out, &v)
	if err != nil {
		log.Printf("failed to unmarshal `gobump show`'s output: %+v\n", err)
		return exitError
	}
	log.Printf("Start uploading files to GitHub Releases. version: %s, staging: %t, dry-run: %t\n", v.Version, *staging, *dryRun)
	err = uploadToGithubRelease(proj, v.Version, *staging, *dryRun)
	if err != nil {
		log.Printf("error occured while uploading artifacts to github: %+v\n", err)
		return exitError
	}
	return exitOK
}

var errAlreadyReleased = fmt.Errorf("the release of this version has already existed at GitHub Releases, so skip the process")

func uploadToGithubRelease(proj *github.Project, releaseVer string, staging, dryRun bool) error {
	tag := "staging"
	if !staging {
		tag = "v" + releaseVer
	}
	repo, owner := proj.Name, proj.Owner
	octoCli := getOctoCli()

	pr, err := getReleasePullRequest(octoCli, owner, repo, releaseVer)
	if err != nil {
		return err
	}

	err = handleOldRelease(octoCli, owner, repo, tag, staging, dryRun)
	if err != nil {
		if err == errAlreadyReleased {
			log.Printf("%s. version: %s\n", err, tag)
			return nil
		}
		return err
	}

	body := pr.Body
	assets, err := collectAssets()
	if err != nil {
		return errors.Wrap(err, "error occured while collecting releasing assets")
	}
	sort.Strings(assets)
	log.Println("uploading following files:")
	for _, f := range assets {
		log.Printf("- %s\n", f)
	}

	host, err := github.CurrentConfig().PromptForHost(proj.Host)
	if err != nil {
		return errors.Wrap(err, "failed to detect github config")
	}
	gh := github.NewClientWithHost(host)

	if !dryRun {
		params := &github.Release{
			TagName:    tag,
			Name:       tag,
			Body:       body,
			Prerelease: true,
		}
		release, err := gh.CreateRelease(proj, params)
		if err != nil {
			return errors.Wrap(err, "failed to create release")
		}

		err = uploadAssets(gh, release, assets)
		if err != nil {
			return err
		}
		if !staging {
			release, err = gh.EditRelease(release, map[string]interface{}{
				"prerelease": false,
			})
		}
	}
	log.Printf("Upload done. version: %s, staging: %t, dry-run: %t\n", releaseVer, staging, dryRun)
	return nil
}

func getOctoCli() *octokit.Client {<commit_msg>[mackerel-github-release] enhance logs when failed to update prerelease status<commit_after>package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"log"
	"net/http"
	"os"
	"os/exec"
	"path/filepath"
	"sort"
	"time"

	"github.com/Songmu/retry"
	"github.com/github/hub/github"
	"github.com/mitchellh/go-homedir"
	"github.com/octokit/go-octokit/octokit"
	"github.com/pkg/errors"
)

const (
	exitOK = iota
	exitError
)

const version = "0.0.0"

func main() {
	os.Exit(run(os.Args[1:]))
}

func run(argv []string) int {
	remotes, err := github.Remotes()
	if err != nil || len(remotes) < 1 {
		log.Printf("can't detect remote repository: %+v\n", err)
		return exitError
	}
	proj, err := remotes[0].Project()
	if err != nil {
		log.Printf("failed to retrieve project: %+v\n", err)
		return exitError
	}
	fs := flag.NewFlagSet("mackerel-github-release", flag.ContinueOnError)
	var (
		dryRun  = fs.Bool("dry-run", false, "dry-run mode")
		staging = fs.Bool("staging", false, "staging release")
	)
	err = fs.Parse(argv)
	if err != nil {
		if err == flag.ErrHelp {
			return exitOK

		}
		return exitError
	}

	out, err := exec.Command("gobump", "show").Output()
	if err != nil {
		log.Printf("failed to `gobump show`: %+v\n", err)
		return exitError
	}

	var v struct {
		Version string `json:"version"`
	}
	err = json.Unmarshal(out, &v)
	if err != nil {
		log.Printf("failed to unmarshal `gobump show`'s output: %+v\n", err)
		return exitError
	}
	log.Printf("Start uploading files to GitHub Releases. version: %s, staging: %t, dry-run: %t\n", v.Version, *staging, *dryRun)
	err = uploadToGithubRelease(proj, v.Version, *staging, *dryRun)
	if err != nil {
		log.Printf("error occured while uploading artifacts to github: %+v\n", err)
		return exitError
	}
	return exitOK
}

var errAlreadyReleased = fmt.Errorf("the release of this version has already existed at GitHub Releases, so skip the process")

func uploadToGithubRelease(proj *github.Project, releaseVer string, staging, dryRun bool) error {
	tag := "staging"
	if !staging {
		tag = "v" + releaseVer
	}
	repo, owner := proj.Name, proj.Owner
	octoCli := getOctoCli()

	pr, err := getReleasePullRequest(octoCli, owner, repo, releaseVer)
	if err != nil {
		return err
	}

	err = handleOldRelease(octoCli, owner, repo, tag, staging, dryRun)
	if err != nil {
		if err == errAlreadyReleased {
			log.Printf("%s. version: %s\n", err, tag)
			return nil
		}
		return err
	}

	body := pr.Body
	assets, err := collectAssets()
	if err != nil {
		return errors.Wrap(err, "error occured while collecting releasing assets")
	}
	sort.Strings(assets)
	log.Println("uploading following files:")
	for _, f := range assets {
		log.Printf("- %s\n", f)
	}

	host, err := github.CurrentConfig().PromptForHost(proj.Host)
	if err != nil {
		return errors.Wrap(err, "failed to detect github config")
	}
	gh := github.NewClientWithHost(host)

	if !dryRun {
		params := &github.Release{
			TagName:    tag,
			Name:       tag,
			Body:       body,
			Prerelease: true,
		}
		release, err := gh.CreateRelease(proj, params)
		if err != nil {
			return errors.Wrap(err, "failed to create release")
		}

		err = uploadAssets(gh, release, assets)
		if err != nil {
			return err
		}
		if !staging {
			err = retry.Retry(3, 3*time.Second, func() error {
				_, err := gh.EditRelease(release, map[string]interface{}{
					"prerelease": false,
				})
				if err != nil {
					log.Println(err)
				}
				return err
			})
			if err != nil {
				return errors.Wrapf(
					err,
					"Upload done, but failed to update prerelease status from true to false. You can check the status and update manually. version: %s",
					releaseVer)
			}
		}
	}
	log.Printf("Upload done. version: %s, staging: %t, dry-run: %t\n", releaseVer, staging, dryRun)
	return nil
}

func getOctoCli() *octokit.Client {
{'fraction_non_alphanumeric': 0.14844617092119866, 'fraction_numerical': 0.001942286348501665, 'mean_word_length': 3.6005105296745374, 'pattern_counts': {'":': 2, '<': 5, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '347157', 'n_tokens_mistral': 2914, 'n_tokens_neox': 2659, 'n_words': 713}