diff --git a/build/azure.go b/build/azure.go
new file mode 100644
index 0000000000..0f917e39a7
--- /dev/null
+++ b/build/azure.go
@@ -0,0 +1,305 @@
+// Copyright 2017 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+// +build none
+
+/*
+The azure command signs and uploads release binaries to a Microsoft Azure bucket and is called from
+Continuous Integration scripts.
+
+Usage: go run build/azure.go
+
+Available commands are:
+
+ upload [ -store s ] [ -signer key-var ] [ file... ] -- uploads build artefacts
+ purge [ -store s ] [ -days threshold ] -- purges old archives from the blobstore
+ list [ -store s ] -- lists contents of the blobstore
+
+For all commands, -n prevents the actual upload/download (dry run mode).
+*/
+package main
+
+import (
+ "bytes"
+ "encoding/base64"
+ "flag"
+ "fmt"
+ "log"
+ "os"
+ "path/filepath"
+ "strings"
+ "time"
+
+ storage "github.com/Azure/azure-storage-go"
+ "github.com/ethereum/go-ethereum/internal/build"
+ "golang.org/x/crypto/openpgp"
+)
+
+const defaultStore = "gethstore/builds"
+
+func main() {
+ log.SetFlags(log.Lshortfile)
+
+ if _, err := os.Stat(filepath.Join("build", "azure.go")); os.IsNotExist(err) {
+ log.Fatal("this script must be run from the root of the repository")
+ }
+ if len(os.Args) < 2 {
+ log.Fatal("need subcommand as first argument")
+ }
+ switch os.Args[1] {
+ case "upload":
+ doUpload(os.Args[2:])
+ case "purge":
+ doPurge(os.Args[2:])
+ case "list":
+ doList(os.Args[2:])
+ default:
+ log.Fatal("unknown command ", os.Args[1])
+ }
+}
+
+func doUpload(cmdline []string) {
+ var (
+ signer = flag.String("signer", "", `Environment variable holding the signing key (e.g. LINUX_SIGNING_KEY)`)
+ store = flag.String("store", defaultStore, `Destination to upload the archives to`)
+ )
+ flag.CommandLine.Parse(cmdline)
+ build.MaybeSkipArchive(build.Env())
+
+ for _, archive := range flag.Args() {
+ uploadArchive(archive, *store, *signer)
+ }
+}
+
+func doPurge(cmdline []string) {
+ var (
+ store = flag.String("store", defaultStore, `Destination from where to purge archives`)
+ limit = flag.Int("days", 30, `Age threshold above which to delete unstalbe archives`)
+ )
+ flag.CommandLine.Parse(cmdline)
+
+ if env := build.Env(); !env.IsCronJob {
+ log.Printf("skipping because not a cron job")
+ os.Exit(0)
+ }
+ // Create the azure authentication and list the current archives
+ auth := newConfig(*store)
+ blobs, err := blobstoreList(auth)
+ if err != nil {
+ log.Fatal(err)
+ }
+ // Iterate over the blobs, collect and sort all unstable builds
+ for i := 0; i < len(blobs); i++ {
+ if !strings.Contains(blobs[i].Name, "unstable") {
+ blobs = append(blobs[:i], blobs[i+1:]...)
+ i--
+ }
+ }
+ for i := 0; i < len(blobs); i++ {
+ for j := i + 1; j < len(blobs); j++ {
+ iTime, err := time.Parse(time.RFC1123, blobs[i].Properties.LastModified)
+ if err != nil {
+ log.Fatal(err)
+ }
+ jTime, err := time.Parse(time.RFC1123, blobs[j].Properties.LastModified)
+ if err != nil {
+ log.Fatal(err)
+ }
+ if iTime.After(jTime) {
+ blobs[i], blobs[j] = blobs[j], blobs[i]
+ }
+ }
+ }
+ // Filter out all archives more recent that the given threshold
+ for i, blob := range blobs {
+ timestamp, _ := time.Parse(time.RFC1123, blob.Properties.LastModified)
+ if time.Since(timestamp) < time.Duration(*limit)*24*time.Hour {
+ blobs = blobs[:i]
+ break
+ }
+ }
+ // Delete all marked as such and return
+ if err := blobstoreDelete(auth, blobs); err != nil {
+ log.Fatal(err)
+ }
+}
+
+func doList(cmdline []string) {
+ var store = flag.String("store", defaultStore, `Blobstore to list`)
+ flag.CommandLine.Parse(cmdline)
+ auth := newConfig(*store)
+
+ blobs, err := blobstoreList(auth)
+ if err != nil {
+ log.Fatal(err)
+ }
+ namelen := 0
+ for _, b := range blobs {
+ if len(b.Name) > namelen {
+ namelen = len(b.Name)
+ }
+ }
+ for _, b := range blobs {
+ name := b.Name + strings.Repeat(" ", namelen-len(b.Name))
+ fmt.Printf("%s size: %v, last-modified: %v\n", name, b.Properties.ContentLength, b.Properties.LastModified)
+ }
+}
+
+func newConfig(store string) Config {
+ return Config{
+ Account: strings.Split(store, "/")[0],
+ Token: os.Getenv("AZURE_BLOBSTORE_TOKEN"),
+ Container: strings.SplitN(store, "/", 2)[1],
+ }
+}
+
+// uploadArchive uploads the given file to the blobstore.
+func uploadArchive(archive, blobstore, signer string) {
+ // If signing was requested, generate the signature files
+ if signer != "" {
+ pgpkey, err := base64.StdEncoding.DecodeString(os.Getenv(signer))
+ if err != nil {
+ log.Fatalf("invalid base64 in variable %s", signer)
+ }
+ if err := signFile(archive, archive+".asc", string(pgpkey)); err != nil {
+ log.Fatalf("can't sign: %v", err)
+ }
+ }
+ // If uploading to Azure was requested, push the archive possibly with its signature
+ auth := newConfig(blobstore)
+ if err := blobstoreUpload(archive, filepath.Base(archive), auth); err != nil {
+ log.Fatal(err)
+ }
+ if signer != "" {
+ if err := blobstoreUpload(archive+".asc", filepath.Base(archive+".asc"), auth); err != nil {
+ log.Fatal(err)
+ }
+ }
+}
+
+// signFile parses a PGP private key from the specified string and creates a signature file
+// into the output parameter of the input file.
+// pgpkey should be a single key in armored format.
+func signFile(input string, output string, pgpkey string) error {
+ // Parse the keyring and make sure we only have a single private key in it
+ keys, err := openpgp.ReadArmoredKeyRing(bytes.NewBufferString(pgpkey))
+ if err != nil {
+ return err
+ }
+ if len(keys) != 1 {
+ return fmt.Errorf("key count mismatch: have %d, want %d", len(keys), 1)
+ }
+ // Create the input and output streams for signing
+ in, err := os.Open(input)
+ if err != nil {
+ return err
+ }
+ defer in.Close()
+
+ out, err := os.Create(output)
+ if err != nil {
+ return err
+ }
+ defer out.Close()
+
+ // Generate the signature and return
+ return openpgp.ArmoredDetachSign(out, keys[0], in, nil)
+}
+
+// Config is an authentication and configuration struct containing the data needed by the
+// Azure SDK to interact with a speicifc container in the blobstore.
+type Config struct {
+ Account string // Account name to authorize API requests with
+ Token string // Access token for the above account
+ Container string // Blob container to upload files into
+}
+
+// blobstoreUpload uploads a local file to the Azure Blob Storage. Note, this method
+// assumes a max file size of 64MB (Azure limitation). Larger files will need a multi API
+// call approach implemented.
+//
+// See: https://msdn.microsoft.com/en-us/library/azure/dd179451.aspx#Anchor_3
+func blobstoreUpload(path string, name string, config Config) error {
+ if *build.DryRunFlag {
+ fmt.Printf("would upload %q to %s/%s/%s\n", path, config.Account, config.Container, name)
+ return nil
+ }
+ // Create an authenticated client against the Azure cloud
+ rawClient, err := storage.NewBasicClient(config.Account, config.Token)
+ if err != nil {
+ return err
+ }
+ client := rawClient.GetBlobService()
+
+ // Stream the file to upload into the designated blobstore container
+ in, err := os.Open(path)
+ if err != nil {
+ return err
+ }
+ defer in.Close()
+
+ info, err := in.Stat()
+ if err != nil {
+ return err
+ }
+ return client.CreateBlockBlobFromReader(config.Container, name, uint64(info.Size()), in, nil)
+}
+
+// blobstoreList lists all the files contained within an azure blobstore.
+func blobstoreList(config Config) ([]storage.Blob, error) {
+ // Create an authenticated client against the Azure cloud
+ rawClient, err := storage.NewBasicClient(config.Account, config.Token)
+ if err != nil {
+ return nil, err
+ }
+ client := rawClient.GetBlobService()
+
+ // List all the blobs from the container and return them
+ container := client.GetContainerReference(config.Container)
+
+ blobs, err := container.ListBlobs(storage.ListBlobsParameters{
+ MaxResults: 1024 * 1024 * 1024, // Yes, fetch all of them
+ Timeout: 3600, // Yes, wait for all of them
+ })
+ if err != nil {
+ return nil, err
+ }
+ return blobs.Blobs, nil
+}
+
+// blobstoreDelete iterates over a list of files to delete and removes them.
+func blobstoreDelete(config Config, blobs []storage.Blob) error {
+ if *build.DryRunFlag {
+ for _, blob := range blobs {
+ fmt.Printf("would delete %s (%s) from %s/%s\n", blob.Name, blob.Properties.LastModified, config.Account, config.Container)
+ }
+ return nil
+ }
+ // Create an authenticated client against the Azure cloud
+ rawClient, err := storage.NewBasicClient(config.Account, config.Token)
+ if err != nil {
+ return err
+ }
+ client := rawClient.GetBlobService()
+
+ // Iterate over the blobs and delete them
+ for _, blob := range blobs {
+ if err := client.DeleteBlob(config.Container, blob.Name, nil); err != nil {
+ return err
+ }
+ }
+ return nil
+}
diff --git a/build/ci.go b/build/ci.go
index e631d70efd..c44c89873d 100644
--- a/build/ci.go
+++ b/build/ci.go
@@ -19,23 +19,21 @@
/*
The ci command is called from Continuous Integration scripts.
-Usage: go run ci.go
+Usage: go run build/ci.go
Available commands are:
- install [ -arch architecture ] [ packages... ] -- builds packages and executables
- test [ -coverage ] [ -misspell ] [ packages... ] -- runs the tests
- archive [ -arch architecture ] [ -type zip|tar ] [ -signer key-envvar ] [ -upload dest ] -- archives build artefacts
- importkeys -- imports signing keys from env
- debsrc [ -signer key-id ] [ -upload dest ] -- creates a debian source package
- nsis -- creates a Windows NSIS installer
- aar [ -local ] [ -sign key-id ] [-deploy repo] [ -upload dest ] -- creates an Android archive
- xcode [ -local ] [ -sign key-id ] [-deploy repo] [ -upload dest ] -- creates an iOS XCode framework
- xgo [ -alltools ] [ options ] -- cross builds according to options
- purge [ -store blobstore ] [ -days threshold ] -- purges old archives from the blobstore
+ install [ -arch architecture ] [ packages... ] -- builds packages and executables
+ test [ -coverage ] [ -misspell ] [ packages... ] -- runs the tests
+ archive [ -arch architecture ] [ -type zip|tar ] -- archives build artefacts
+ importkeys -- imports PGP signing keys from env
+ debsrc [ -signer key-id ] [ -upload dest ] -- creates a debian source package
+ nsis -- creates a Windows NSIS installer
+ aar [ -local ] [ -signer key-id ] [-deploy repo] -- creates an Android archive
+ xcode [ -local ] [ -signer key-id ] [-deploy repo] -- creates an iOS XCode framework
+ xgo [ -alltools ] [ options ] -- cross builds according to options
For all commands, -n prevents execution of external programs (dry run mode).
-
*/
package main
@@ -158,8 +156,6 @@ func main() {
doXCodeFramework(os.Args[2:])
case "xgo":
doXgo(os.Args[2:])
- case "purge":
- doPurge(os.Args[2:])
default:
log.Fatal("unknown command ", os.Args[1])
}
@@ -345,11 +341,9 @@ func spellcheck(packages []string) {
func doArchive(cmdline []string) {
var (
- arch = flag.String("arch", runtime.GOARCH, "Architecture cross packaging")
- atype = flag.String("type", "zip", "Type of archive to write (zip|tar)")
- signer = flag.String("signer", "", `Environment variable holding the signing key (e.g. LINUX_SIGNING_KEY)`)
- upload = flag.String("upload", "", `Destination to upload the archives (usually "gethstore/builds")`)
- ext string
+ arch = flag.String("arch", runtime.GOARCH, "Architecture cross packaging")
+ atype = flag.String("type", "zip", "Type of archive to write (zip|tar)")
+ ext string
)
flag.CommandLine.Parse(cmdline)
switch *atype {
@@ -367,18 +361,13 @@ func doArchive(cmdline []string) {
geth = "geth-" + base + ext
alltools = "geth-alltools-" + base + ext
)
- maybeSkipArchive(env)
+ build.MaybeSkipArchive(env)
if err := build.WriteArchive(geth, gethArchiveFiles); err != nil {
log.Fatal(err)
}
if err := build.WriteArchive(alltools, allToolsArchiveFiles); err != nil {
log.Fatal(err)
}
- for _, archive := range []string{geth, alltools} {
- if err := archiveUpload(archive, *upload, *signer); err != nil {
- log.Fatal(err)
- }
- }
}
func archiveBasename(arch string, env build.Environment) string {
@@ -406,52 +395,6 @@ func archiveVersion(env build.Environment) string {
return version
}
-func archiveUpload(archive string, blobstore string, signer string) error {
- // If signing was requested, generate the signature files
- if signer != "" {
- pgpkey, err := base64.StdEncoding.DecodeString(os.Getenv(signer))
- if err != nil {
- return fmt.Errorf("invalid base64 %s", signer)
- }
- if err := build.PGPSignFile(archive, archive+".asc", string(pgpkey)); err != nil {
- return err
- }
- }
- // If uploading to Azure was requested, push the archive possibly with its signature
- if blobstore != "" {
- auth := build.AzureBlobstoreConfig{
- Account: strings.Split(blobstore, "/")[0],
- Token: os.Getenv("AZURE_BLOBSTORE_TOKEN"),
- Container: strings.SplitN(blobstore, "/", 2)[1],
- }
- if err := build.AzureBlobstoreUpload(archive, filepath.Base(archive), auth); err != nil {
- return err
- }
- if signer != "" {
- if err := build.AzureBlobstoreUpload(archive+".asc", filepath.Base(archive+".asc"), auth); err != nil {
- return err
- }
- }
- }
- return nil
-}
-
-// skips archiving for some build configurations.
-func maybeSkipArchive(env build.Environment) {
- if env.IsPullRequest {
- log.Printf("skipping because this is a PR build")
- os.Exit(0)
- }
- if env.IsCronJob {
- log.Printf("skipping because this is a cron job")
- os.Exit(0)
- }
- if env.Branch != "master" && !strings.HasPrefix(env.Tag, "v1.") {
- log.Printf("skipping because branch %q, tag %q is not on the whitelist", env.Branch, env.Tag)
- os.Exit(0)
- }
-}
-
// Debian Packaging
func doDebianSource(cmdline []string) {
@@ -464,7 +407,7 @@ func doDebianSource(cmdline []string) {
flag.CommandLine.Parse(cmdline)
*workdir = makeWorkdir(*workdir)
env := build.Env()
- maybeSkipArchive(env)
+ build.MaybeSkipArchive(env)
// Import the signing key.
if b64key := os.Getenv("PPA_SIGNING_KEY"); b64key != "" {
@@ -637,14 +580,12 @@ func doWindowsInstaller(cmdline []string) {
// Parse the flags and make skip installer generation on PRs
var (
arch = flag.String("arch", runtime.GOARCH, "Architecture for cross build packaging")
- signer = flag.String("signer", "", `Environment variable holding the signing key (e.g. WINDOWS_SIGNING_KEY)`)
- upload = flag.String("upload", "", `Destination to upload the archives (usually "gethstore/builds")`)
workdir = flag.String("workdir", "", `Output directory for packages (uses temp dir if unset)`)
)
flag.CommandLine.Parse(cmdline)
*workdir = makeWorkdir(*workdir)
env := build.Env()
- maybeSkipArchive(env)
+ build.MaybeSkipArchive(env)
// Aggregate binaries that are included in the installer
var (
@@ -695,11 +636,6 @@ func doWindowsInstaller(cmdline []string) {
"/DARCH="+*arch,
filepath.Join(*workdir, "geth.nsi"),
)
-
- // Sign and publish installer.
- if err := archiveUpload(installer, *upload, *signer); err != nil {
- log.Fatal(err)
- }
}
// Android archives
@@ -709,7 +645,6 @@ func doAndroidArchive(cmdline []string) {
local = flag.Bool("local", false, `Flag whether we're only doing a local build (skip Maven artifacts)`)
signer = flag.String("signer", "", `Environment variable holding the signing key (e.g. ANDROID_SIGNING_KEY)`)
deploy = flag.String("deploy", "", `Destination to deploy the archive (usually "https://oss.sonatype.org")`)
- upload = flag.String("upload", "", `Destination to upload the archive (usually "gethstore/builds")`)
)
flag.CommandLine.Parse(cmdline)
env := build.Env()
@@ -735,15 +670,12 @@ func doAndroidArchive(cmdline []string) {
build.Render("build/mvn.pom", meta.Package+".pom", 0755, meta)
// Skip Maven deploy and Azure upload for PR builds
- maybeSkipArchive(env)
+ build.MaybeSkipArchive(env)
// Sign and upload the archive to Azure
archive := "geth-" + archiveBasename("android", env) + ".aar"
os.Rename("geth.aar", archive)
- if err := archiveUpload(archive, *upload, *signer); err != nil {
- log.Fatal(err)
- }
// Sign and upload all the artifacts to Maven Central
os.Rename(archive, meta.Package+".aar")
if *signer != "" && *deploy != "" {
@@ -834,9 +766,7 @@ func newMavenMetadata(env build.Environment) mavenMetadata {
func doXCodeFramework(cmdline []string) {
var (
local = flag.Bool("local", false, `Flag whether we're only doing a local build (skip Maven artifacts)`)
- signer = flag.String("signer", "", `Environment variable holding the signing key (e.g. IOS_SIGNING_KEY)`)
deploy = flag.String("deploy", "", `Destination to deploy the archive (usually "trunk")`)
- upload = flag.String("upload", "", `Destination to upload the archives (usually "gethstore/builds")`)
)
flag.CommandLine.Parse(cmdline)
env := build.Env()
@@ -860,14 +790,8 @@ func doXCodeFramework(cmdline []string) {
build.MustRun(bind)
build.MustRunCommand("tar", "-zcvf", archive+".tar.gz", archive)
- // Skip CocoaPods deploy and Azure upload for PR builds
- maybeSkipArchive(env)
-
- // Sign and upload the framework to Azure
- if err := archiveUpload(archive+".tar.gz", *upload, *signer); err != nil {
- log.Fatal(err)
- }
- // Prepare and upload a PodSpec to CocoaPods
+ // Deploy to CocoaPods.
+ build.MaybeSkipArchive(env)
if *deploy != "" {
meta := newPodMetadata(env, archive)
build.Render("build/pod.podspec", "Geth.podspec", 0755, meta)
@@ -971,62 +895,3 @@ func xgoTool(args []string) *exec.Cmd {
}
return cmd
}
-
-// Binary distribution cleanups
-
-func doPurge(cmdline []string) {
- var (
- store = flag.String("store", "", `Destination from where to purge archives (usually "gethstore/builds")`)
- limit = flag.Int("days", 30, `Age threshold above which to delete unstalbe archives`)
- )
- flag.CommandLine.Parse(cmdline)
-
- if env := build.Env(); !env.IsCronJob {
- log.Printf("skipping because not a cron job")
- os.Exit(0)
- }
- // Create the azure authentication and list the current archives
- auth := build.AzureBlobstoreConfig{
- Account: strings.Split(*store, "/")[0],
- Token: os.Getenv("AZURE_BLOBSTORE_TOKEN"),
- Container: strings.SplitN(*store, "/", 2)[1],
- }
- blobs, err := build.AzureBlobstoreList(auth)
- if err != nil {
- log.Fatal(err)
- }
- // Iterate over the blobs, collect and sort all unstable builds
- for i := 0; i < len(blobs); i++ {
- if !strings.Contains(blobs[i].Name, "unstable") {
- blobs = append(blobs[:i], blobs[i+1:]...)
- i--
- }
- }
- for i := 0; i < len(blobs); i++ {
- for j := i + 1; j < len(blobs); j++ {
- iTime, err := time.Parse(time.RFC1123, blobs[i].Properties.LastModified)
- if err != nil {
- log.Fatal(err)
- }
- jTime, err := time.Parse(time.RFC1123, blobs[j].Properties.LastModified)
- if err != nil {
- log.Fatal(err)
- }
- if iTime.After(jTime) {
- blobs[i], blobs[j] = blobs[j], blobs[i]
- }
- }
- }
- // Filter out all archives more recent that the given threshold
- for i, blob := range blobs {
- timestamp, _ := time.Parse(time.RFC1123, blob.Properties.LastModified)
- if time.Since(timestamp) < time.Duration(*limit)*24*time.Hour {
- blobs = blobs[:i]
- break
- }
- }
- // Delete all marked as such and return
- if err := build.AzureBlobstoreDelete(auth, blobs); err != nil {
- log.Fatal(err)
- }
-}
diff --git a/internal/build/azure.go b/internal/build/azure.go
deleted file mode 100644
index 2081a9a0b1..0000000000
--- a/internal/build/azure.go
+++ /dev/null
@@ -1,111 +0,0 @@
-// Copyright 2016 The go-ethereum Authors
-// This file is part of the go-ethereum library.
-//
-// The go-ethereum library is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Lesser General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// The go-ethereum library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with the go-ethereum library. If not, see .
-
-package build
-
-import (
- "fmt"
- "os"
-
- storage "github.com/Azure/azure-storage-go"
-)
-
-// AzureBlobstoreConfig is an authentication and configuration struct containing
-// the data needed by the Azure SDK to interact with a speicifc container in the
-// blobstore.
-type AzureBlobstoreConfig struct {
- Account string // Account name to authorize API requests with
- Token string // Access token for the above account
- Container string // Blob container to upload files into
-}
-
-// AzureBlobstoreUpload uploads a local file to the Azure Blob Storage. Note, this
-// method assumes a max file size of 64MB (Azure limitation). Larger files will
-// need a multi API call approach implemented.
-//
-// See: https://msdn.microsoft.com/en-us/library/azure/dd179451.aspx#Anchor_3
-func AzureBlobstoreUpload(path string, name string, config AzureBlobstoreConfig) error {
- if *DryRunFlag {
- fmt.Printf("would upload %q to %s/%s/%s\n", path, config.Account, config.Container, name)
- return nil
- }
- // Create an authenticated client against the Azure cloud
- rawClient, err := storage.NewBasicClient(config.Account, config.Token)
- if err != nil {
- return err
- }
- client := rawClient.GetBlobService()
-
- // Stream the file to upload into the designated blobstore container
- in, err := os.Open(path)
- if err != nil {
- return err
- }
- defer in.Close()
-
- info, err := in.Stat()
- if err != nil {
- return err
- }
- return client.CreateBlockBlobFromReader(config.Container, name, uint64(info.Size()), in, nil)
-}
-
-// AzureBlobstoreList lists all the files contained within an azure blobstore.
-func AzureBlobstoreList(config AzureBlobstoreConfig) ([]storage.Blob, error) {
- // Create an authenticated client against the Azure cloud
- rawClient, err := storage.NewBasicClient(config.Account, config.Token)
- if err != nil {
- return nil, err
- }
- client := rawClient.GetBlobService()
-
- // List all the blobs from the container and return them
- container := client.GetContainerReference(config.Container)
-
- blobs, err := container.ListBlobs(storage.ListBlobsParameters{
- MaxResults: 1024 * 1024 * 1024, // Yes, fetch all of them
- Timeout: 3600, // Yes, wait for all of them
- })
- if err != nil {
- return nil, err
- }
- return blobs.Blobs, nil
-}
-
-// AzureBlobstoreDelete iterates over a list of files to delete and removes them
-// from the blobstore.
-func AzureBlobstoreDelete(config AzureBlobstoreConfig, blobs []storage.Blob) error {
- if *DryRunFlag {
- for _, blob := range blobs {
- fmt.Printf("would delete %s (%s) from %s/%s\n", blob.Name, blob.Properties.LastModified, config.Account, config.Container)
- }
- return nil
- }
- // Create an authenticated client against the Azure cloud
- rawClient, err := storage.NewBasicClient(config.Account, config.Token)
- if err != nil {
- return err
- }
- client := rawClient.GetBlobService()
-
- // Iterate over the blobs and delete them
- for _, blob := range blobs {
- if err := client.DeleteBlob(config.Container, blob.Name, nil); err != nil {
- return err
- }
- }
- return nil
-}
diff --git a/internal/build/env.go b/internal/build/env.go
index c47681ebed..3ca1fcc43c 100644
--- a/internal/build/env.go
+++ b/internal/build/env.go
@@ -19,6 +19,7 @@ package build
import (
"flag"
"fmt"
+ "log"
"os"
"strings"
)
@@ -127,3 +128,20 @@ func applyEnvFlags(env Environment) Environment {
}
return env
}
+
+// MaybeSkipArchive exits the process when build results of the given env should
+// not be archived and uploaded.
+func MaybeSkipArchive(env Environment) {
+ if env.IsPullRequest {
+ log.Printf("skipping archive because this is a PR build")
+ os.Exit(0)
+ }
+ if env.IsCronJob {
+ log.Printf("skipping archive because this is a cron job")
+ os.Exit(0)
+ }
+ if env.Branch != "master" && !strings.HasPrefix(env.Tag, "v1.") {
+ log.Printf("skipping archive because branch %q, tag %q is not on the whitelist", env.Branch, env.Tag)
+ os.Exit(0)
+ }
+}
diff --git a/internal/build/pgp.go b/internal/build/pgp.go
deleted file mode 100644
index 79ab9c06f1..0000000000
--- a/internal/build/pgp.go
+++ /dev/null
@@ -1,59 +0,0 @@
-// Copyright 2016 The go-ethereum Authors
-// This file is part of the go-ethereum library.
-//
-// The go-ethereum library is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Lesser General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// The go-ethereum library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with the go-ethereum library. If not, see .
-
-// signFile reads the contents of an input file and signs it (in armored format)
-// with the key provided, placing the signature into the output file.
-
-package build
-
-import (
- "bytes"
- "fmt"
- "os"
-
- "golang.org/x/crypto/openpgp"
-)
-
-// PGPSignFile parses a PGP private key from the specified string and creates a
-// signature file into the output parameter of the input file.
-//
-// Note, this method assumes a single key will be container in the pgpkey arg,
-// furthermore that it is in armored format.
-func PGPSignFile(input string, output string, pgpkey string) error {
- // Parse the keyring and make sure we only have a single private key in it
- keys, err := openpgp.ReadArmoredKeyRing(bytes.NewBufferString(pgpkey))
- if err != nil {
- return err
- }
- if len(keys) != 1 {
- return fmt.Errorf("key count mismatch: have %d, want %d", len(keys), 1)
- }
- // Create the input and output streams for signing
- in, err := os.Open(input)
- if err != nil {
- return err
- }
- defer in.Close()
-
- out, err := os.Create(output)
- if err != nil {
- return err
- }
- defer out.Close()
-
- // Generate the signature and return
- return openpgp.ArmoredDetachSign(out, keys[0], in, nil)
-}