Skip to content

Instantly share code, notes, and snippets.

@jhinrichsen
Created April 12, 2018 12:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jhinrichsen/7bf7282b6d1cb077575d5adca4bdca95 to your computer and use it in GitHub Desktop.
Save jhinrichsen/7bf7282b6d1cb077575d5adca4bdca95 to your computer and use it in GitHub Desktop.
Jenkins: commandline utility that downloads artifacts a Maven build has deployed to a Maven repository. Useful because Nexus does not offer a build brace.
package main
import (
"bufio"
"flag"
"fmt"
"io"
"log"
"net/http"
"net/url"
"os"
"path"
"regexp"
"sync"
"time"
)
func main() {
var match = flag.String("match", `\.ear`,
"regexp for matching artifacts")
var todir = flag.String("todir", "out",
"output directory for artifacts")
flag.Usage = func() {
fmt.Fprintf(os.Stderr,
"Usage: %s [options] <Jenkins build URL>\n"+
"Downloads artifacts that a Jenkins Maven build"+
" has uploaded\n",
path.Base(os.Args[0]))
flag.PrintDefaults()
}
flag.Parse()
// Expect URL parameter
if flag.NArg() != 1 {
flag.Usage()
os.Exit(1)
}
buildURL, err := url.Parse(flag.Arg(0))
if err != nil {
log.Fatal(err)
}
rel, _ := url.Parse("consoleText")
consoleURL := buildURL.ResolveReference(rel)
log.Printf("Fetching console for %v\n", consoleURL)
res, err := http.Get(consoleURL.String())
if err != nil {
log.Fatal(err)
}
c := make(chan string)
go parse(res.Body, *match, c)
ensureDir(*todir)
// Make sure not to exit before all fetches are done
var wg sync.WaitGroup
for url := range c {
go func(u string) {
wg.Add(1)
fetch(u, *todir)
wg.Done()
}(url)
}
log.Println("Waiting for downloads to finish")
wg.Wait()
log.Println("Done.")
}
func parse(buf io.ReadCloser, match string, urls chan<- string) {
defer buf.Close()
scanner := bufio.NewScanner(buf)
re := regexp.MustCompile("Uploaded: (.+?) ")
for scanner.Scan() {
t := scanner.Text()
groups := re.FindStringSubmatch(t)
if len(groups) == 0 {
continue
}
if len(groups) > 2 {
log.Fatalf("Expected to find one group but found %q\n",
groups)
}
group := groups[1]
matched, err := regexp.MatchString(match, group)
if err != nil {
log.Fatal(err)
}
if matched {
urls <- group
}
}
close(urls)
if err := scanner.Err(); err != nil {
log.Fatal(err)
}
}
func ensureDir(dir string) {
if _, err := os.Stat(dir); os.IsNotExist(err) {
os.MkdirAll(dir, os.ModePerm)
}
}
func fetch(url string, todir string) {
filename := path.Base(url)
p := path.Join(todir, filename)
out, err := os.Create(p)
if err != nil {
log.Fatal(err)
}
defer out.Close()
res, err := http.Get(url)
if err != nil {
log.Fatal(err)
}
if res.StatusCode != http.StatusOK {
log.Fatalf("%v: expected status code 200 but got %v\n",
url, res.StatusCode)
}
defer res.Body.Close()
log.Printf("Creating %v\n", p)
start := time.Now()
n, err := io.Copy(out, res.Body)
if err != nil {
log.Fatal(err)
}
elapsed := time.Since(start)
log.Printf("Created %v (%v bytes) in %v\n", filename, n, elapsed)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment