From 42c86a09ed872791b6085cd70d3e91c67c626ebd Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Mon, 7 Aug 2017 17:05:40 +0200 Subject: [PATCH] build: move sign/upload out of ci.go This removes ci.go dependencies on vendored packages and speeds up the build. --- build/azure.go | 305 ++++++++++++++++++++++++++++++++++++++++ build/ci.go | 173 +++-------------------- internal/build/azure.go | 111 --------------- internal/build/env.go | 18 +++ internal/build/pgp.go | 59 -------- 5 files changed, 342 insertions(+), 324 deletions(-) create mode 100644 build/azure.go delete mode 100644 internal/build/azure.go delete mode 100644 internal/build/pgp.go 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) -}