mirror of
https://github.com/golang/go.git
synced 2025-05-16 21:04:38 +00:00
misc/makerelease: upload files to Google Cloud Storage
LGTM=bradfitz R=jasonhall, bradfitz CC=golang-codereviews https://golang.org/cl/91700047
This commit is contained in:
parent
c038c38ac1
commit
0627fa84b7
@ -12,13 +12,11 @@ import (
|
|||||||
"bufio"
|
"bufio"
|
||||||
"bytes"
|
"bytes"
|
||||||
"compress/gzip"
|
"compress/gzip"
|
||||||
"encoding/base64"
|
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"log"
|
"log"
|
||||||
"mime/multipart"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
@ -27,6 +25,9 @@ import (
|
|||||||
"regexp"
|
"regexp"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"code.google.com/p/goauth2/oauth"
|
||||||
|
"code.google.com/p/google-api-go-client/storage/v1beta2"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -40,8 +41,10 @@ var (
|
|||||||
includeRace = flag.Bool("race", true, "build race detector packages")
|
includeRace = flag.Bool("race", true, "build race detector packages")
|
||||||
versionOverride = flag.String("version", "", "override version name")
|
versionOverride = flag.String("version", "", "override version name")
|
||||||
staticToolchain = flag.Bool("static", true, "try to build statically linked toolchain (only supported on ELF targets)")
|
staticToolchain = flag.Bool("static", true, "try to build statically linked toolchain (only supported on ELF targets)")
|
||||||
|
tokenCache = flag.String("token", defaultCacheFile, "Authentication token cache file")
|
||||||
|
storageBucket = flag.String("bucket", "golang", "Cloud Storage Bucket")
|
||||||
|
|
||||||
username, password string // for Google Code upload
|
defaultCacheFile = filepath.Join(os.Getenv("HOME"), ".makerelease-request-token")
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -119,6 +122,12 @@ var staticLinkAvailable = []string{
|
|||||||
|
|
||||||
var fileRe = regexp.MustCompile(`^(go[a-z0-9-.]+)\.(src|([a-z0-9]+)-([a-z0-9]+)(?:-([a-z0-9.]+))?)\.(tar\.gz|zip|pkg|msi)$`)
|
var fileRe = regexp.MustCompile(`^(go[a-z0-9-.]+)\.(src|([a-z0-9]+)-([a-z0-9]+)(?:-([a-z0-9.]+))?)\.(tar\.gz|zip|pkg|msi)$`)
|
||||||
|
|
||||||
|
// OAuth2-authenticated HTTP client used to make calls to Cloud Storage.
|
||||||
|
var oauthClient *http.Client
|
||||||
|
|
||||||
|
// Builder key as specified in ~/.gobuildkey
|
||||||
|
var builderKey string
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
flag.Usage = func() {
|
flag.Usage = func() {
|
||||||
fmt.Fprintf(os.Stderr, "usage: %s [flags] targets...\n", os.Args[0])
|
fmt.Fprintf(os.Stderr, "usage: %s [flags] targets...\n", os.Args[0])
|
||||||
@ -135,7 +144,10 @@ func main() {
|
|||||||
|
|
||||||
if *upload {
|
if *upload {
|
||||||
if err := readCredentials(); err != nil {
|
if err := readCredentials(); err != nil {
|
||||||
log.Println("readCredentials:", err)
|
log.Fatalln("readCredentials:", err)
|
||||||
|
}
|
||||||
|
if err := setupOAuthClient(); err != nil {
|
||||||
|
log.Fatalln("setupOAuthClient:", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, targ := range flag.Args() {
|
for _, targ := range flag.Args() {
|
||||||
@ -641,121 +653,56 @@ func (b *Build) env() []string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (b *Build) Upload(version string, filename string) error {
|
func (b *Build) Upload(version string, filename string) error {
|
||||||
// Prepare upload metadata.
|
svc, err := storage.New(oauthClient)
|
||||||
var labels []string
|
if err != nil {
|
||||||
os_, arch := b.OS, b.Arch
|
return err
|
||||||
switch b.Arch {
|
|
||||||
case "386":
|
|
||||||
arch = "x86 32-bit"
|
|
||||||
case "amd64":
|
|
||||||
arch = "x86 64-bit"
|
|
||||||
}
|
|
||||||
if arch != "" {
|
|
||||||
labels = append(labels, "Arch-"+b.Arch)
|
|
||||||
}
|
|
||||||
var opsys, ftype string // labels
|
|
||||||
switch b.OS {
|
|
||||||
case "linux":
|
|
||||||
os_ = "Linux"
|
|
||||||
opsys = "Linux"
|
|
||||||
case "freebsd":
|
|
||||||
os_ = "FreeBSD"
|
|
||||||
opsys = "FreeBSD"
|
|
||||||
case "darwin":
|
|
||||||
os_ = "Mac OS X"
|
|
||||||
opsys = "OSX"
|
|
||||||
case "netbsd":
|
|
||||||
os_ = "NetBSD"
|
|
||||||
opsys = "NetBSD"
|
|
||||||
case "windows":
|
|
||||||
os_ = "Windows"
|
|
||||||
opsys = "Windows"
|
|
||||||
}
|
|
||||||
summary := fmt.Sprintf("%s %s (%s)", version, os_, arch)
|
|
||||||
switch {
|
|
||||||
case strings.HasSuffix(filename, ".msi"):
|
|
||||||
ftype = "Installer"
|
|
||||||
summary += " MSI installer"
|
|
||||||
case strings.HasSuffix(filename, ".pkg"):
|
|
||||||
ftype = "Installer"
|
|
||||||
summary += " PKG installer"
|
|
||||||
case strings.HasSuffix(filename, ".zip"):
|
|
||||||
ftype = "Archive"
|
|
||||||
summary += " ZIP archive"
|
|
||||||
case strings.HasSuffix(filename, ".tar.gz"):
|
|
||||||
ftype = "Archive"
|
|
||||||
summary += " tarball"
|
|
||||||
}
|
|
||||||
if b.Source {
|
|
||||||
ftype = "Source"
|
|
||||||
summary = fmt.Sprintf("%s (source only)", version)
|
|
||||||
}
|
|
||||||
if opsys != "" {
|
|
||||||
labels = append(labels, "OpSys-"+opsys)
|
|
||||||
}
|
|
||||||
if ftype != "" {
|
|
||||||
labels = append(labels, "Type-"+ftype)
|
|
||||||
}
|
|
||||||
if b.Label != "" {
|
|
||||||
labels = append(labels, b.Label)
|
|
||||||
}
|
|
||||||
if *addLabel != "" {
|
|
||||||
labels = append(labels, *addLabel)
|
|
||||||
}
|
|
||||||
// Put "Go" prefix on summary when it doesn't already begin with "go".
|
|
||||||
if !strings.HasPrefix(strings.ToLower(summary), "go") {
|
|
||||||
summary = "Go " + summary
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Open file to upload.
|
obj := &storage.Object{
|
||||||
|
Acl: []*storage.ObjectAccessControl{{Entity: "allUsers", Role: "READER"}},
|
||||||
|
Name: filename,
|
||||||
|
}
|
||||||
f, err := os.Open(filename)
|
f, err := os.Open(filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
|
_, err = svc.Objects.Insert(*storageBucket, obj).Media(f).Do()
|
||||||
// Prepare multipart payload.
|
|
||||||
body := new(bytes.Buffer)
|
|
||||||
w := multipart.NewWriter(body)
|
|
||||||
if err := w.WriteField("summary", summary); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
for _, l := range labels {
|
|
||||||
if err := w.WriteField("label", l); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fw, err := w.CreateFormFile("filename", filename)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if _, err = io.Copy(fw, f); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := w.Close(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send the file to Google Code.
|
return nil
|
||||||
req, err := http.NewRequest("POST", uploadURL, body)
|
}
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
token := fmt.Sprintf("%s:%s", username, password)
|
|
||||||
token = base64.StdEncoding.EncodeToString([]byte(token))
|
|
||||||
req.Header.Set("Authorization", "Basic "+token)
|
|
||||||
req.Header.Set("Content-type", w.FormDataContentType())
|
|
||||||
|
|
||||||
resp, err := http.DefaultTransport.RoundTrip(req)
|
func setupOAuthClient() error {
|
||||||
if err != nil {
|
config := &oauth.Config{
|
||||||
|
ClientId: "999119582588-h7kpj5pcm6d9solh5lgrbusmvvk4m9dn.apps.googleusercontent.com",
|
||||||
|
ClientSecret: "8YLFgOhXIELWbO",
|
||||||
|
Scope: storage.DevstorageRead_writeScope,
|
||||||
|
AuthURL: "https://accounts.google.com/o/oauth2/auth",
|
||||||
|
TokenURL: "https://accounts.google.com/o/oauth2/token",
|
||||||
|
TokenCache: oauth.CacheFile(*tokenCache),
|
||||||
|
RedirectURL: "oob",
|
||||||
|
}
|
||||||
|
transport := &oauth.Transport{Config: config}
|
||||||
|
if token, err := config.TokenCache.Token(); err != nil {
|
||||||
|
url := transport.Config.AuthCodeURL("")
|
||||||
|
fmt.Println("Visit the following URL, obtain an authentication" +
|
||||||
|
"code, and enter it below.")
|
||||||
|
fmt.Println(url)
|
||||||
|
fmt.Print("Enter authentication code: ")
|
||||||
|
code := ""
|
||||||
|
if _, err := fmt.Scan(&code); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if resp.StatusCode/100 != 2 {
|
if _, err := transport.Exchange(code); err != nil {
|
||||||
fmt.Fprintln(os.Stderr, "upload failed")
|
return err
|
||||||
defer resp.Body.Close()
|
|
||||||
io.Copy(os.Stderr, resp.Body)
|
|
||||||
return fmt.Errorf("upload: %s", resp.Status)
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
transport.Token = token
|
||||||
|
}
|
||||||
|
oauthClient = transport.Client()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -785,21 +732,11 @@ func readCredentials() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
r := bufio.NewReader(f)
|
s := bufio.NewScanner(f)
|
||||||
for i := 0; i < 3; i++ {
|
if s.Scan() {
|
||||||
b, _, err := r.ReadLine()
|
builderKey = s.Text()
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
b = bytes.TrimSpace(b)
|
return s.Err()
|
||||||
switch i {
|
|
||||||
case 1:
|
|
||||||
username = string(b)
|
|
||||||
case 2:
|
|
||||||
password = string(b)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func cp(dst, src string) error {
|
func cp(dst, src string) error {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user