Merge branch 'master' into davkal/babel-7
This commit is contained in:
@@ -1,43 +0,0 @@
|
||||
FROM centos:6.6
|
||||
|
||||
RUN yum install -y yum-plugin-ovl initscripts curl tar gcc libc6-dev git gcc-c++ openssl-devel && \
|
||||
yum install -y g++ make automake autoconf curl-devel zlib-devel httpd-devel apr-devel apr-util-devel sqlite-devel && \
|
||||
yum install -y wget yum-utils bzip2 bzip2-devel && \
|
||||
yum install -y fontconfig freetype freetype-devel fontconfig-devel libstdc++ && \
|
||||
yum install -y rpm-build patch readline readline-devel libtool bison lzma && \
|
||||
yum install -y which tar
|
||||
|
||||
# Install RUBY 1.9.3
|
||||
# install necessary utilities
|
||||
# RUN yum install -y which tar
|
||||
RUN gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 && \
|
||||
curl -sSl https://raw.githubusercontent.com/rvm/rvm/master/binscripts/rvm-installer | bash -s stable && \
|
||||
source /etc/profile.d/rvm.sh && \
|
||||
/bin/bash -l -c "rvm requirements" && \
|
||||
/bin/bash -l -c "rvm install 2.1.9" && \
|
||||
/bin/bash -l -c "rvm use 2.1.9 --default"
|
||||
|
||||
# install nodejs
|
||||
RUN curl --silent --location https://rpm.nodesource.com/setup_6.x | bash - && \
|
||||
yum install -y nodejs --nogpgcheck
|
||||
|
||||
ENV GOLANG_VERSION 1.11
|
||||
|
||||
RUN wget https://dl.yarnpkg.com/rpm/yarn.repo -O /etc/yum.repos.d/yarn.repo && \
|
||||
yum install -y yarn --nogpgcheck && \
|
||||
wget https://storage.googleapis.com/golang/go${GOLANG_VERSION}.linux-amd64.tar.gz && \
|
||||
tar -C /usr/local -xzf go${GOLANG_VERSION}.linux-amd64.tar.gz
|
||||
|
||||
|
||||
ENV PATH /usr/local/go/bin:$PATH
|
||||
|
||||
RUN mkdir -p /go/src /go/bin && chmod -R 777 /go
|
||||
|
||||
ENV GOPATH /go
|
||||
ENV PATH /go/bin:$PATH
|
||||
|
||||
ADD ./build.sh /tmp/
|
||||
|
||||
WORKDIR /tmp/
|
||||
|
||||
CMD ["./build.sh"]
|
||||
@@ -22,19 +22,17 @@ echo "current dir: $(pwd)"
|
||||
|
||||
if [ "$CIRCLE_TAG" != "" ]; then
|
||||
echo "Building releases from tag $CIRCLE_TAG"
|
||||
OPT="-includeBuildNumber=false ${EXTRA_OPTS}"
|
||||
OPT="-includeBuildId=false ${EXTRA_OPTS}"
|
||||
else
|
||||
echo "Building incremental build for $CIRCLE_BRANCH"
|
||||
OPT="-buildNumber=${CIRCLE_BUILD_NUM} ${EXTRA_OPTS}"
|
||||
OPT="-buildId=${CIRCLE_WORKFLOW_ID} ${EXTRA_OPTS}"
|
||||
fi
|
||||
|
||||
echo "Build arguments: $OPT"
|
||||
|
||||
go run build.go -goarch armv7 -cc ${CCARMV7} ${OPT} build
|
||||
go run build.go -goarch arm64 -cc ${CCARM64} ${OPT} build
|
||||
|
||||
# MacOS build is broken atm. See Issue #13763
|
||||
#go run build.go -goos darwin -cc ${CCOSX64} ${OPT} build
|
||||
go run build.go -goos darwin -cc ${CCOSX64} ${OPT} build
|
||||
|
||||
go run build.go -goos windows -cc ${CCWIN64} ${OPT} build
|
||||
CC=${CCX64} go run build.go ${OPT} build
|
||||
|
||||
@@ -18,10 +18,10 @@ echo "current dir: $(pwd)"
|
||||
|
||||
if [ "$CIRCLE_TAG" != "" ]; then
|
||||
echo "Building releases from tag $CIRCLE_TAG"
|
||||
OPT="-includeBuildNumber=false ${EXTRA_OPTS}"
|
||||
OPT="-includeBuildId=false ${EXTRA_OPTS}"
|
||||
else
|
||||
echo "Building incremental build for $CIRCLE_BRANCH"
|
||||
OPT="-buildNumber=${CIRCLE_BUILD_NUM} ${EXTRA_OPTS}"
|
||||
OPT="-buildId=${CIRCLE_WORKFLOW_ID} ${EXTRA_OPTS}"
|
||||
fi
|
||||
|
||||
echo "Build arguments: $OPT"
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
docker info && docker version
|
||||
mkdir -p ~/docker
|
||||
|
||||
echo "Circle branch: ${CIRCLE_BRANCH}"
|
||||
echo "Circle tag: ${CIRCLE_TAG}"
|
||||
|
||||
# try to load docker container from cache
|
||||
if [[ -e ~/docker/centos.tar ]]; then
|
||||
docker load -i ~/docker/centos.tar;
|
||||
else
|
||||
docker build --rm=false --tag "grafana/buildcontainer" ./scripts/build/
|
||||
|
||||
# save docker container so we don't have to recreate it next run
|
||||
docker save grafana/buildcontainer > ~/docker/centos.tar;
|
||||
fi
|
||||
@@ -0,0 +1,5 @@
|
||||
FROM circleci/python:2.7-stretch
|
||||
|
||||
RUN sudo pip install awscli && \
|
||||
curl https://dl.google.com/dl/cloudsdk/channels/rapid/downloads/google-cloud-sdk-222.0.0-linux-x86_64.tar.gz | \
|
||||
sudo tar xvzf - -C /opt
|
||||
Executable
+7
@@ -0,0 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
_version="1.0.0"
|
||||
_tag="grafana/grafana-ci-deploy:${_version}"
|
||||
|
||||
docker build -t $_tag .
|
||||
docker push $_tag
|
||||
@@ -1,14 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
mkdir -p dist
|
||||
|
||||
echo "Circle branch: ${CIRCLE_BRANCH}"
|
||||
echo "Circle tag: ${CIRCLE_TAG}"
|
||||
docker run -i -t --name gfbuild \
|
||||
-v $(pwd):/go/src/github.com/grafana/grafana \
|
||||
-e "CIRCLE_BRANCH=${CIRCLE_BRANCH}" \
|
||||
-e "CIRCLE_TAG=${CIRCLE_TAG}" \
|
||||
-e "CIRCLE_BUILD_NUM=${CIRCLE_BUILD_NUM}" \
|
||||
grafana/buildcontainer
|
||||
|
||||
sudo chown -R ${USER:=$(/usr/bin/id -run)}:$USER dist
|
||||
@@ -1,14 +1,16 @@
|
||||
#/bin/sh
|
||||
#!/bin/sh
|
||||
|
||||
# no relation to publish.go
|
||||
|
||||
# Right now we hack this in into the publish script.
|
||||
EXTRA_OPTS="$@"
|
||||
|
||||
# Right now we hack this in into the publish script.
|
||||
# Eventually we might want to keep a list of all previous releases somewhere.
|
||||
_releaseNoteUrl="https://community.grafana.com/t/release-notes-v5-3-x/10244"
|
||||
_whatsNewUrl="http://docs.grafana.org/guides/whats-new-in-v5-3/"
|
||||
_releaseNoteUrl="https://community.grafana.com/t/release-notes-v5-4-x/12215"
|
||||
_whatsNewUrl="http://docs.grafana.org/guides/whats-new-in-v5-4/"
|
||||
|
||||
./scripts/build/release_publisher/release_publisher \
|
||||
--wn ${_whatsNewUrl} \
|
||||
--rn ${_releaseNoteUrl} \
|
||||
--version ${CIRCLE_TAG} \
|
||||
--apikey ${GRAFANA_COM_API_KEY}
|
||||
--apikey ${GRAFANA_COM_API_KEY} ${EXTRA_OPTS}
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
type releaseFromExternalContent struct {
|
||||
getter urlGetter
|
||||
rawVersion string
|
||||
artifactConfigurations []buildArtifact
|
||||
}
|
||||
|
||||
func (re releaseFromExternalContent) prepareRelease(baseArchiveUrl, whatsNewUrl string, releaseNotesUrl string, nightly bool) (*release, error) {
|
||||
version := re.rawVersion[1:]
|
||||
beta := strings.Contains(version, "beta")
|
||||
var rt ReleaseType
|
||||
if beta {
|
||||
rt = BETA
|
||||
} else if nightly {
|
||||
rt = NIGHTLY
|
||||
} else {
|
||||
rt = STABLE
|
||||
}
|
||||
|
||||
builds := []build{}
|
||||
for _, ba := range re.artifactConfigurations {
|
||||
sha256, err := re.getter.getContents(fmt.Sprintf("%s.sha256", ba.getUrl(baseArchiveUrl, version, rt)))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
builds = append(builds, newBuild(baseArchiveUrl, ba, version, rt, sha256))
|
||||
}
|
||||
|
||||
r := release{
|
||||
Version: version,
|
||||
ReleaseDate: time.Now().UTC(),
|
||||
Stable: rt.stable(),
|
||||
Beta: rt.beta(),
|
||||
Nightly: rt.nightly(),
|
||||
WhatsNewUrl: whatsNewUrl,
|
||||
ReleaseNotesUrl: releaseNotesUrl,
|
||||
Builds: builds,
|
||||
}
|
||||
return &r, nil
|
||||
}
|
||||
|
||||
type urlGetter interface {
|
||||
getContents(url string) (string, error)
|
||||
}
|
||||
|
||||
type getHttpContents struct{}
|
||||
|
||||
func (getHttpContents) getContents(url string) (string, error) {
|
||||
response, err := http.Get(url)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
defer response.Body.Close()
|
||||
all, err := ioutil.ReadAll(response.Body)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return string(all), nil
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/pkg/errors"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
type releaseLocalSources struct {
|
||||
path string
|
||||
artifactConfigurations []buildArtifact
|
||||
}
|
||||
|
||||
func (r releaseLocalSources) prepareRelease(baseArchiveUrl, whatsNewUrl string, releaseNotesUrl string, nightly bool) (*release, error) {
|
||||
if !nightly {
|
||||
return nil, errors.New("Local releases only supported for nightly builds.")
|
||||
}
|
||||
buildData := r.findBuilds(baseArchiveUrl)
|
||||
|
||||
rel := release{
|
||||
Version: buildData.version,
|
||||
ReleaseDate: time.Now().UTC(),
|
||||
Stable: false,
|
||||
Beta: false,
|
||||
Nightly: nightly,
|
||||
WhatsNewUrl: whatsNewUrl,
|
||||
ReleaseNotesUrl: releaseNotesUrl,
|
||||
Builds: buildData.builds,
|
||||
}
|
||||
|
||||
return &rel, nil
|
||||
}
|
||||
|
||||
type buildData struct {
|
||||
version string
|
||||
builds []build
|
||||
}
|
||||
|
||||
func (r releaseLocalSources) findBuilds(baseArchiveUrl string) buildData {
|
||||
data := buildData{}
|
||||
filepath.Walk(r.path, createBuildWalker(r.path, &data, r.artifactConfigurations, baseArchiveUrl))
|
||||
return data
|
||||
}
|
||||
|
||||
func createBuildWalker(path string, data *buildData, archiveTypes []buildArtifact, baseArchiveUrl string) func(path string, f os.FileInfo, err error) error {
|
||||
return func(path string, f os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
log.Printf("error: %v", err)
|
||||
}
|
||||
|
||||
if f.Name() == path || strings.HasSuffix(f.Name(), ".sha256") {
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, archive := range archiveTypes {
|
||||
if strings.HasSuffix(f.Name(), archive.urlPostfix) {
|
||||
shaBytes, err := ioutil.ReadFile(path + ".sha256")
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to read sha256 file %v", err)
|
||||
}
|
||||
|
||||
version, err := grabVersion(f.Name(), archive.urlPostfix)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
continue
|
||||
}
|
||||
data.version = version
|
||||
data.builds = append(data.builds, build{
|
||||
Os: archive.os,
|
||||
Url: archive.getUrl(baseArchiveUrl, version, NIGHTLY),
|
||||
Sha256: string(shaBytes),
|
||||
Arch: archive.arch,
|
||||
})
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
}
|
||||
func grabVersion(name string, suffix string) (string, error) {
|
||||
match := regexp.MustCompile(fmt.Sprintf(`grafana(-enterprise)?[-_](.*)%s`, suffix)).FindSubmatch([]byte(name))
|
||||
if len(match) > 0 {
|
||||
return string(match[2]), nil
|
||||
}
|
||||
|
||||
return "", errors.New("No version found.")
|
||||
}
|
||||
@@ -7,13 +7,14 @@ import (
|
||||
"os"
|
||||
)
|
||||
|
||||
var baseUri string = "https://grafana.com/api"
|
||||
|
||||
func main() {
|
||||
var version string
|
||||
var whatsNewUrl string
|
||||
var releaseNotesUrl string
|
||||
var dryRun bool
|
||||
var enterprise bool
|
||||
var fromLocal bool
|
||||
var nightly bool
|
||||
var apiKey string
|
||||
|
||||
flag.StringVar(&version, "version", "", "Grafana version (ex: --version v5.2.0-beta1)")
|
||||
@@ -21,20 +22,82 @@ func main() {
|
||||
flag.StringVar(&releaseNotesUrl, "rn", "", "Grafana version (ex: --rn https://community.grafana.com/t/release-notes-v5-2-x/7894)")
|
||||
flag.StringVar(&apiKey, "apikey", "", "Grafana.com API key (ex: --apikey ABCDEF)")
|
||||
flag.BoolVar(&dryRun, "dry-run", false, "--dry-run")
|
||||
flag.BoolVar(&enterprise, "enterprise", false, "--enterprise")
|
||||
flag.BoolVar(&fromLocal, "from-local", false, "--from-local (builds will be tagged as nightly)")
|
||||
flag.Parse()
|
||||
|
||||
nightly = fromLocal
|
||||
|
||||
if len(os.Args) == 1 {
|
||||
fmt.Println("Usage: go run publisher.go main.go --version <v> --wn <what's new url> --rn <release notes url> --apikey <api key> --dry-run false")
|
||||
fmt.Println("example: go run publisher.go main.go --version v5.2.0-beta2 --wn http://docs.grafana.org/guides/whats-new-in-v5-2/ --rn https://community.grafana.com/t/release-notes-v5-2-x/7894 --apikey ASDF123 --dry-run true")
|
||||
fmt.Println("Usage: go run publisher.go main.go --version <v> --wn <what's new url> --rn <release notes url> --apikey <api key> --dry-run false --enterprise false --nightly false")
|
||||
fmt.Println("example: go run publisher.go main.go --version v5.2.0-beta2 --wn http://docs.grafana.org/guides/whats-new-in-v5-2/ --rn https://community.grafana.com/t/release-notes-v5-2-x/7894 --apikey ASDF123 --dry-run --enterprise")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if dryRun {
|
||||
log.Println("Dry-run has been enabled.")
|
||||
}
|
||||
var baseUrl string
|
||||
var builder releaseBuilder
|
||||
var product string
|
||||
|
||||
p := publisher{apiKey: apiKey}
|
||||
if err := p.doRelease(version, whatsNewUrl, releaseNotesUrl, dryRun); err != nil {
|
||||
archiveProviderRoot := "https://s3-us-west-2.amazonaws.com"
|
||||
buildArtifacts := completeBuildArtifactConfigurations
|
||||
|
||||
if enterprise {
|
||||
product = "grafana-enterprise"
|
||||
baseUrl = createBaseUrl(archiveProviderRoot, "grafana-enterprise-releases", product, nightly)
|
||||
var err error
|
||||
buildArtifacts, err = filterBuildArtifacts([]artifactFilter{
|
||||
{os: "deb", arch: "amd64"},
|
||||
{os: "rhel", arch: "amd64"},
|
||||
{os: "linux", arch: "amd64"},
|
||||
{os: "win", arch: "amd64"},
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
log.Fatalf("Could not filter to the selected build artifacts, err=%v", err)
|
||||
}
|
||||
|
||||
} else {
|
||||
product = "grafana"
|
||||
baseUrl = createBaseUrl(archiveProviderRoot, "grafana-releases", product, nightly)
|
||||
}
|
||||
|
||||
if fromLocal {
|
||||
path, _ := os.Getwd()
|
||||
builder = releaseLocalSources{
|
||||
path: path,
|
||||
artifactConfigurations: buildArtifacts,
|
||||
}
|
||||
} else {
|
||||
builder = releaseFromExternalContent{
|
||||
getter: getHttpContents{},
|
||||
rawVersion: version,
|
||||
artifactConfigurations: buildArtifacts,
|
||||
}
|
||||
}
|
||||
|
||||
p := publisher{
|
||||
apiKey: apiKey,
|
||||
apiUri: "https://grafana.com/api",
|
||||
product: product,
|
||||
dryRun: dryRun,
|
||||
enterprise: enterprise,
|
||||
baseArchiveUrl: baseUrl,
|
||||
builder: builder,
|
||||
}
|
||||
if err := p.doRelease(whatsNewUrl, releaseNotesUrl, nightly); err != nil {
|
||||
log.Fatalf("error: %v", err)
|
||||
}
|
||||
}
|
||||
func createBaseUrl(root string, bucketName string, product string, nightly bool) string {
|
||||
var subPath string
|
||||
if nightly {
|
||||
subPath = "master"
|
||||
} else {
|
||||
subPath = "release"
|
||||
}
|
||||
|
||||
return fmt.Sprintf("%s/%s/%s/%s", root, bucketName, subPath, product)
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/pkg/errors"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/http"
|
||||
@@ -12,53 +13,47 @@ import (
|
||||
)
|
||||
|
||||
type publisher struct {
|
||||
apiKey string
|
||||
apiKey string
|
||||
apiUri string
|
||||
product string
|
||||
dryRun bool
|
||||
enterprise bool
|
||||
baseArchiveUrl string
|
||||
builder releaseBuilder
|
||||
}
|
||||
|
||||
func (p *publisher) doRelease(version string, whatsNewUrl string, releaseNotesUrl string, dryRun bool) error {
|
||||
currentRelease, err := newRelease(version, whatsNewUrl, releaseNotesUrl, buildArtifactConfigurations, getHttpContents{})
|
||||
type releaseBuilder interface {
|
||||
prepareRelease(baseArchiveUrl, whatsNewUrl string, releaseNotesUrl string, nightly bool) (*release, error)
|
||||
}
|
||||
|
||||
func (p *publisher) doRelease(whatsNewUrl string, releaseNotesUrl string, nightly bool) error {
|
||||
currentRelease, err := p.builder.prepareRelease(p.baseArchiveUrl, whatsNewUrl, releaseNotesUrl, nightly)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if dryRun {
|
||||
relJson, err := json.Marshal(currentRelease)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
log.Println(string(relJson))
|
||||
|
||||
for _, b := range currentRelease.Builds {
|
||||
artifactJson, err := json.Marshal(b)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
log.Println(string(artifactJson))
|
||||
}
|
||||
} else {
|
||||
if err := p.postRelease(currentRelease); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := p.postRelease(currentRelease); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *publisher) postRelease(r *release) error {
|
||||
err := p.postRequest("/grafana/versions", r, fmt.Sprintf("Create Release %s", r.Version))
|
||||
err := p.postRequest("/versions", r, fmt.Sprintf("Create Release %s", r.Version))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = p.postRequest("/grafana/versions/"+r.Version, r, fmt.Sprintf("Update Release %s", r.Version))
|
||||
err = p.postRequest("/versions/"+r.Version, r, fmt.Sprintf("Update Release %s", r.Version))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, b := range r.Builds {
|
||||
err = p.postRequest(fmt.Sprintf("/grafana/versions/%s/packages", r.Version), b, fmt.Sprintf("Create Build %s %s", b.Os, b.Arch))
|
||||
err = p.postRequest(fmt.Sprintf("/versions/%s/packages", r.Version), b, fmt.Sprintf("Create Build %s %s", b.Os, b.Arch))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = p.postRequest(fmt.Sprintf("/grafana/versions/%s/packages/%s/%s", r.Version, b.Arch, b.Os), b, fmt.Sprintf("Update Build %s %s", b.Os, b.Arch))
|
||||
err = p.postRequest(fmt.Sprintf("/versions/%s/packages/%s/%s", r.Version, b.Arch, b.Os), b, fmt.Sprintf("Update Build %s %s", b.Os, b.Arch))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -67,7 +62,25 @@ func (p *publisher) postRelease(r *release) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
const baseArhiveUrl = "https://s3-us-west-2.amazonaws.com/grafana-releases/release/grafana"
|
||||
type ReleaseType int
|
||||
|
||||
const (
|
||||
STABLE ReleaseType = iota + 1
|
||||
BETA
|
||||
NIGHTLY
|
||||
)
|
||||
|
||||
func (rt ReleaseType) beta() bool {
|
||||
return rt == BETA
|
||||
}
|
||||
|
||||
func (rt ReleaseType) stable() bool {
|
||||
return rt == STABLE
|
||||
}
|
||||
|
||||
func (rt ReleaseType) nightly() bool {
|
||||
return rt == NIGHTLY
|
||||
}
|
||||
|
||||
type buildArtifact struct {
|
||||
os string
|
||||
@@ -75,7 +88,7 @@ type buildArtifact struct {
|
||||
urlPostfix string
|
||||
}
|
||||
|
||||
func (t buildArtifact) getUrl(version string, isBeta bool) string {
|
||||
func (t buildArtifact) getUrl(baseArchiveUrl, version string, releaseType ReleaseType) string {
|
||||
prefix := "-"
|
||||
rhelReleaseExtra := ""
|
||||
|
||||
@@ -83,15 +96,15 @@ func (t buildArtifact) getUrl(version string, isBeta bool) string {
|
||||
prefix = "_"
|
||||
}
|
||||
|
||||
if !isBeta && t.os == "rhel" {
|
||||
if releaseType.stable() && t.os == "rhel" {
|
||||
rhelReleaseExtra = "-1"
|
||||
}
|
||||
|
||||
url := strings.Join([]string{baseArhiveUrl, prefix, version, rhelReleaseExtra, t.urlPostfix}, "")
|
||||
url := strings.Join([]string{baseArchiveUrl, prefix, version, rhelReleaseExtra, t.urlPostfix}, "")
|
||||
return url
|
||||
}
|
||||
|
||||
var buildArtifactConfigurations = []buildArtifact{
|
||||
var completeBuildArtifactConfigurations = []buildArtifact{
|
||||
{
|
||||
os: "deb",
|
||||
arch: "arm64",
|
||||
@@ -149,48 +162,57 @@ var buildArtifactConfigurations = []buildArtifact{
|
||||
},
|
||||
}
|
||||
|
||||
func newRelease(rawVersion string, whatsNewUrl string, releaseNotesUrl string, artifactConfigurations []buildArtifact, getter urlGetter) (*release, error) {
|
||||
version := rawVersion[1:]
|
||||
now := time.Now()
|
||||
isBeta := strings.Contains(version, "beta")
|
||||
|
||||
builds := []build{}
|
||||
for _, ba := range artifactConfigurations {
|
||||
sha256, err := getter.getContents(fmt.Sprintf("%s.sha256", ba.getUrl(version, isBeta)))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
builds = append(builds, newBuild(ba, version, isBeta, sha256))
|
||||
}
|
||||
|
||||
r := release{
|
||||
Version: version,
|
||||
ReleaseDate: time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, time.Local),
|
||||
Stable: !isBeta,
|
||||
Beta: isBeta,
|
||||
Nightly: false,
|
||||
WhatsNewUrl: whatsNewUrl,
|
||||
ReleaseNotesUrl: releaseNotesUrl,
|
||||
Builds: builds,
|
||||
}
|
||||
return &r, nil
|
||||
type artifactFilter struct {
|
||||
os string
|
||||
arch string
|
||||
}
|
||||
|
||||
func newBuild(ba buildArtifact, version string, isBeta bool, sha256 string) build {
|
||||
func filterBuildArtifacts(filters []artifactFilter) ([]buildArtifact, error) {
|
||||
var artifacts []buildArtifact
|
||||
for _, f := range filters {
|
||||
matched := false
|
||||
|
||||
for _, a := range completeBuildArtifactConfigurations {
|
||||
if f.os == a.os && f.arch == a.arch {
|
||||
artifacts = append(artifacts, a)
|
||||
matched = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !matched {
|
||||
return nil, errors.New(fmt.Sprintf("No buildArtifact for os=%v, arch=%v", f.os, f.arch))
|
||||
}
|
||||
}
|
||||
return artifacts, nil
|
||||
}
|
||||
|
||||
func newBuild(baseArchiveUrl string, ba buildArtifact, version string, rt ReleaseType, sha256 string) build {
|
||||
return build{
|
||||
Os: ba.os,
|
||||
Url: ba.getUrl(version, isBeta),
|
||||
Url: ba.getUrl(baseArchiveUrl, version, rt),
|
||||
Sha256: sha256,
|
||||
Arch: ba.arch,
|
||||
}
|
||||
}
|
||||
|
||||
func (p *publisher) apiUrl(url string) string {
|
||||
return fmt.Sprintf("%s/%s%s", p.apiUri, p.product, url)
|
||||
}
|
||||
|
||||
func (p *publisher) postRequest(url string, obj interface{}, desc string) error {
|
||||
jsonBytes, err := json.Marshal(obj)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
req, err := http.NewRequest(http.MethodPost, baseUri+url, bytes.NewReader(jsonBytes))
|
||||
|
||||
if p.dryRun {
|
||||
log.Println(fmt.Sprintf("POST to %s:", p.apiUrl(url)))
|
||||
log.Println(string(jsonBytes))
|
||||
return nil
|
||||
}
|
||||
|
||||
req, err := http.NewRequest(http.MethodPost, p.apiUrl(url), bytes.NewReader(jsonBytes))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -243,24 +265,3 @@ type build struct {
|
||||
Sha256 string `json:"sha256"`
|
||||
Arch string `json:"arch"`
|
||||
}
|
||||
|
||||
type urlGetter interface {
|
||||
getContents(url string) (string, error)
|
||||
}
|
||||
|
||||
type getHttpContents struct{}
|
||||
|
||||
func (getHttpContents) getContents(url string) (string, error) {
|
||||
response, err := http.Get(url)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
defer response.Body.Close()
|
||||
all, err := ioutil.ReadAll(response.Body)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return string(all), nil
|
||||
}
|
||||
|
||||
@@ -2,37 +2,100 @@ package main
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestNewRelease(t *testing.T) {
|
||||
versionIn := "v5.2.0-beta1"
|
||||
expectedVersion := "5.2.0-beta1"
|
||||
whatsNewUrl := "https://whatsnews.foo/"
|
||||
relNotesUrl := "https://relnotes.foo/"
|
||||
expectedArch := "amd64"
|
||||
expectedOs := "linux"
|
||||
buildArtifacts := []buildArtifact{{expectedOs, expectedArch, ".linux-amd64.tar.gz"}}
|
||||
func TestPreparingReleaseFromRemote(t *testing.T) {
|
||||
|
||||
rel, _ := newRelease(versionIn, whatsNewUrl, relNotesUrl, buildArtifacts, mockHttpGetter{})
|
||||
|
||||
if !rel.Beta || rel.Stable {
|
||||
t.Errorf("%s should have been tagged as beta (not stable), but wasn't .", versionIn)
|
||||
cases := []struct {
|
||||
version string
|
||||
expectedVersion string
|
||||
whatsNewUrl string
|
||||
relNotesUrl string
|
||||
nightly bool
|
||||
expectedBeta bool
|
||||
expectedStable bool
|
||||
expectedArch string
|
||||
expectedOs string
|
||||
expectedUrl string
|
||||
baseArchiveUrl string
|
||||
buildArtifacts []buildArtifact
|
||||
}{
|
||||
{
|
||||
version: "v5.2.0-beta1",
|
||||
expectedVersion: "5.2.0-beta1",
|
||||
whatsNewUrl: "https://whatsnews.foo/",
|
||||
relNotesUrl: "https://relnotes.foo/",
|
||||
nightly: false,
|
||||
expectedBeta: true,
|
||||
expectedStable: false,
|
||||
expectedArch: "amd64",
|
||||
expectedOs: "linux",
|
||||
expectedUrl: "https://s3-us-west-2.amazonaws.com/grafana-releases/release/grafana-5.2.0-beta1.linux-amd64.tar.gz",
|
||||
baseArchiveUrl: "https://s3-us-west-2.amazonaws.com/grafana-releases/release/grafana",
|
||||
buildArtifacts: []buildArtifact{{"linux", "amd64", ".linux-amd64.tar.gz"}},
|
||||
},
|
||||
{
|
||||
version: "v5.2.3",
|
||||
expectedVersion: "5.2.3",
|
||||
whatsNewUrl: "https://whatsnews.foo/",
|
||||
relNotesUrl: "https://relnotes.foo/",
|
||||
nightly: false,
|
||||
expectedBeta: false,
|
||||
expectedStable: true,
|
||||
expectedArch: "amd64",
|
||||
expectedOs: "rhel",
|
||||
expectedUrl: "https://s3-us-west-2.amazonaws.com/grafana-releases/release/grafana-5.2.3-1.x86_64.rpm",
|
||||
baseArchiveUrl: "https://s3-us-west-2.amazonaws.com/grafana-releases/release/grafana",
|
||||
buildArtifacts: []buildArtifact{{"rhel", "amd64", ".x86_64.rpm"}},
|
||||
},
|
||||
{
|
||||
version: "v5.4.0-pre1asdf",
|
||||
expectedVersion: "5.4.0-pre1asdf",
|
||||
whatsNewUrl: "https://whatsnews.foo/",
|
||||
relNotesUrl: "https://relnotes.foo/",
|
||||
nightly: true,
|
||||
expectedBeta: false,
|
||||
expectedStable: false,
|
||||
expectedArch: "amd64",
|
||||
expectedOs: "rhel",
|
||||
expectedUrl: "https://s3-us-west-2.amazonaws.com/grafana-releases/release/grafana-5.4.0-pre1asdf.x86_64.rpm",
|
||||
baseArchiveUrl: "https://s3-us-west-2.amazonaws.com/grafana-releases/release/grafana",
|
||||
buildArtifacts: []buildArtifact{{"rhel", "amd64", ".x86_64.rpm"}},
|
||||
},
|
||||
}
|
||||
|
||||
if rel.Version != expectedVersion {
|
||||
t.Errorf("Expected version to be %s, but it was %s.", expectedVersion, rel.Version)
|
||||
}
|
||||
for _, test := range cases {
|
||||
builder := releaseFromExternalContent{
|
||||
getter: mockHttpGetter{},
|
||||
rawVersion: test.version,
|
||||
artifactConfigurations: test.buildArtifacts,
|
||||
}
|
||||
|
||||
expectedBuilds := len(buildArtifacts)
|
||||
if len(rel.Builds) != expectedBuilds {
|
||||
t.Errorf("Expected %v builds, but got %v.", expectedBuilds, len(rel.Builds))
|
||||
}
|
||||
rel, _ := builder.prepareRelease(test.baseArchiveUrl, test.whatsNewUrl, test.relNotesUrl, test.nightly)
|
||||
|
||||
build := rel.Builds[0]
|
||||
if build.Arch != expectedArch {
|
||||
t.Errorf("Expected arch to be %v, but it was %v", expectedArch, build.Arch)
|
||||
}
|
||||
if rel.Beta != test.expectedBeta || rel.Stable != test.expectedStable {
|
||||
t.Errorf("%s should have been tagged as beta=%v, stable=%v.", test.version, test.expectedBeta, test.expectedStable)
|
||||
}
|
||||
|
||||
if build.Os != expectedOs {
|
||||
t.Errorf("Expected arch to be %v, but it was %v", expectedOs, build.Os)
|
||||
if rel.Version != test.expectedVersion {
|
||||
t.Errorf("Expected version to be %s, but it was %s.", test.expectedVersion, rel.Version)
|
||||
}
|
||||
|
||||
expectedBuilds := len(test.buildArtifacts)
|
||||
if len(rel.Builds) != expectedBuilds {
|
||||
t.Errorf("Expected %v builds, but got %v.", expectedBuilds, len(rel.Builds))
|
||||
}
|
||||
|
||||
build := rel.Builds[0]
|
||||
if build.Arch != test.expectedArch {
|
||||
t.Errorf("Expected arch to be %v, but it was %v", test.expectedArch, build.Arch)
|
||||
}
|
||||
|
||||
if build.Os != test.expectedOs {
|
||||
t.Errorf("Expected os to be %v, but it was %v", test.expectedOs, build.Os)
|
||||
}
|
||||
|
||||
if build.Url != test.expectedUrl {
|
||||
t.Errorf("Expected url to be %v, but it was %v", test.expectedUrl, build.Url)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,3 +104,97 @@ type mockHttpGetter struct{}
|
||||
func (mockHttpGetter) getContents(url string) (string, error) {
|
||||
return url, nil
|
||||
}
|
||||
|
||||
func TestPreparingReleaseFromLocal(t *testing.T) {
|
||||
whatsNewUrl := "https://whatsnews.foo/"
|
||||
relNotesUrl := "https://relnotes.foo/"
|
||||
expectedVersion := "5.4.0-123pre1"
|
||||
expectedBuilds := 4
|
||||
|
||||
var builder releaseBuilder
|
||||
testDataPath := "testdata"
|
||||
builder = releaseLocalSources{
|
||||
path: testDataPath,
|
||||
artifactConfigurations: completeBuildArtifactConfigurations,
|
||||
}
|
||||
|
||||
relAll, _ := builder.prepareRelease("https://s3-us-west-2.amazonaws.com/grafana-enterprise-releases/master/grafana-enterprise", whatsNewUrl, relNotesUrl, true)
|
||||
|
||||
if relAll.Stable || !relAll.Nightly {
|
||||
t.Error("Expected a nightly release but wasn't.")
|
||||
}
|
||||
|
||||
if relAll.ReleaseNotesUrl != relNotesUrl {
|
||||
t.Errorf("expected releaseNotesUrl to be %s, but it was %s", relNotesUrl, relAll.ReleaseNotesUrl)
|
||||
}
|
||||
if relAll.WhatsNewUrl != whatsNewUrl {
|
||||
t.Errorf("expected whatsNewUrl to be %s, but it was %s", whatsNewUrl, relAll.WhatsNewUrl)
|
||||
}
|
||||
|
||||
if relAll.Beta {
|
||||
t.Errorf("Expected release to be nightly, not beta.")
|
||||
}
|
||||
|
||||
if relAll.Version != expectedVersion {
|
||||
t.Errorf("Expected version=%s, but got=%s", expectedVersion, relAll.Version)
|
||||
}
|
||||
|
||||
if len(relAll.Builds) != expectedBuilds {
|
||||
t.Errorf("Expected %v builds, but was %v", expectedBuilds, len(relAll.Builds))
|
||||
}
|
||||
|
||||
expectedArch := "amd64"
|
||||
expectedOs := "win"
|
||||
|
||||
builder = releaseLocalSources{
|
||||
path: testDataPath,
|
||||
artifactConfigurations: []buildArtifact{{
|
||||
os: expectedOs,
|
||||
arch: expectedArch,
|
||||
urlPostfix: ".windows-amd64.zip",
|
||||
}},
|
||||
}
|
||||
|
||||
relOne, _ := builder.prepareRelease("https://s3-us-west-2.amazonaws.com/grafana-enterprise-releases/master/grafana-enterprise", whatsNewUrl, relNotesUrl, true)
|
||||
|
||||
if len(relOne.Builds) != 1 {
|
||||
t.Errorf("Expected 1 artifact, but was %v", len(relOne.Builds))
|
||||
}
|
||||
|
||||
build := relOne.Builds[0]
|
||||
|
||||
if build.Arch != expectedArch {
|
||||
t.Fatalf("Expected arch to be %s, but was %s", expectedArch, build.Arch)
|
||||
}
|
||||
|
||||
if build.Os != expectedOs {
|
||||
t.Fatalf("Expected os to be %s, but was %s", expectedOs, build.Os)
|
||||
}
|
||||
|
||||
_, err := builder.prepareRelease("", "", "", false)
|
||||
if err == nil {
|
||||
t.Error("Error was nil, but expected an error as the local releaser only supports nightly builds.")
|
||||
}
|
||||
}
|
||||
|
||||
func TestFilterBuildArtifacts(t *testing.T) {
|
||||
buildArtifacts, _ := filterBuildArtifacts([]artifactFilter{
|
||||
{os: "deb", arch: "amd64"},
|
||||
{os: "rhel", arch: "amd64"},
|
||||
{os: "linux", arch: "amd64"},
|
||||
{os: "win", arch: "amd64"},
|
||||
})
|
||||
|
||||
if len(buildArtifacts) != 4 {
|
||||
t.Errorf("Expected 4 build artifacts after filtering, but was %v", len(buildArtifacts))
|
||||
}
|
||||
|
||||
_, err := filterBuildArtifacts([]artifactFilter{
|
||||
{os: "foobar", arch: "amd64"},
|
||||
})
|
||||
|
||||
if err == nil {
|
||||
t.Errorf("Expected an error as a we tried to filter on a nonexiststant os.")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Vendored
Vendored
+1
@@ -0,0 +1 @@
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
|
||||
Vendored
Vendored
+1
@@ -0,0 +1 @@
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
|
||||
+1
@@ -0,0 +1 @@
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
|
||||
@@ -17,8 +17,8 @@ module.exports = function (grunt) {
|
||||
|
||||
grunt.registerTask('precommit', [
|
||||
'sasslint',
|
||||
'exec:tslint',
|
||||
'exec:tsc',
|
||||
'newer:exec:tslint',
|
||||
'newer:exec:tsc',
|
||||
'no-only-tests'
|
||||
]);
|
||||
|
||||
|
||||
@@ -2,8 +2,14 @@ module.exports = function (config, grunt) {
|
||||
'use strict';
|
||||
|
||||
return {
|
||||
tslint: 'node ./node_modules/tslint/lib/tslintCli.js -c tslint.json --project ./tsconfig.json',
|
||||
tsc: 'yarn tsc --noEmit',
|
||||
tslint: {
|
||||
command: 'node ./node_modules/tslint/lib/tslintCli.js -c tslint.json --project ./tsconfig.json',
|
||||
src: ['public/app/**/*.ts*'],
|
||||
},
|
||||
tsc: {
|
||||
command: 'yarn tsc --noEmit',
|
||||
src: ['public/app/**/*.ts*'],
|
||||
},
|
||||
jest: 'node ./node_modules/jest-cli/bin/jest.js --maxWorkers 2',
|
||||
webpack: 'node ./node_modules/webpack/bin/webpack.js --config scripts/webpack/webpack.prod.js',
|
||||
};
|
||||
|
||||
@@ -16,7 +16,7 @@ module.exports = {
|
||||
publicPath: "public/build/",
|
||||
},
|
||||
resolve: {
|
||||
extensions: ['.ts', '.tsx', '.es6', '.js', '.json'],
|
||||
extensions: ['.ts', '.tsx', '.es6', '.js', '.json', '.svg'],
|
||||
alias: {
|
||||
},
|
||||
modules: [
|
||||
@@ -47,7 +47,7 @@ module.exports = {
|
||||
},
|
||||
{
|
||||
test: /\.html$/,
|
||||
exclude: /index\.template.html/,
|
||||
exclude: /(index|error)\-template\.html/,
|
||||
use: [
|
||||
{ loader: 'ngtemplate-loader?relativeTo=' + (path.resolve(__dirname, '../../public')) + '&prefix=public' },
|
||||
{
|
||||
|
||||
@@ -80,11 +80,16 @@ module.exports = merge(common, {
|
||||
plugins: [
|
||||
new CleanWebpackPlugin('../../public/build', { allowExternal: true }),
|
||||
new MiniCssExtractPlugin({
|
||||
filename: "grafana.[name].css"
|
||||
filename: "grafana.[name].[hash].css"
|
||||
}),
|
||||
new HtmlWebpackPlugin({
|
||||
filename: path.resolve(__dirname, '../../public/views/error.html'),
|
||||
template: path.resolve(__dirname, '../../public/views/error-template.html'),
|
||||
inject: false,
|
||||
}),
|
||||
new HtmlWebpackPlugin({
|
||||
filename: path.resolve(__dirname, '../../public/views/index.html'),
|
||||
template: path.resolve(__dirname, '../../public/views/index.template.html'),
|
||||
template: path.resolve(__dirname, '../../public/views/index-template.html'),
|
||||
inject: 'body',
|
||||
chunks: ['manifest', 'vendor', 'app'],
|
||||
}),
|
||||
|
||||
@@ -93,7 +93,7 @@ module.exports = merge(common, {
|
||||
new CleanWebpackPlugin('../public/build', { allowExternal: true }),
|
||||
new HtmlWebpackPlugin({
|
||||
filename: path.resolve(__dirname, '../../public/views/index.html'),
|
||||
template: path.resolve(__dirname, '../../public/views/index.template.html'),
|
||||
template: path.resolve(__dirname, '../../public/views/index-template.html'),
|
||||
inject: 'body',
|
||||
alwaysWriteToDisk: true
|
||||
}),
|
||||
|
||||
@@ -71,12 +71,17 @@ module.exports = merge(common, {
|
||||
|
||||
plugins: [
|
||||
new MiniCssExtractPlugin({
|
||||
filename: "grafana.[name].css"
|
||||
filename: "grafana.[name].[hash].css"
|
||||
}),
|
||||
new ngAnnotatePlugin(),
|
||||
new HtmlWebpackPlugin({
|
||||
filename: path.resolve(__dirname, '../../public/views/error.html'),
|
||||
template: path.resolve(__dirname, '../../public/views/error-template.html'),
|
||||
inject: false,
|
||||
}),
|
||||
new HtmlWebpackPlugin({
|
||||
filename: path.resolve(__dirname, '../../public/views/index.html'),
|
||||
template: path.resolve(__dirname, '../../public/views/index.template.html'),
|
||||
template: path.resolve(__dirname, '../../public/views/index-template.html'),
|
||||
inject: 'body',
|
||||
chunks: ['vendor', 'app'],
|
||||
}),
|
||||
|
||||
Reference in New Issue
Block a user