Commit 92768d5a by Marcus Efraimsson

Merge branch 'master' into dashboard-acl-ux2

parents a01e6fc9 ac5836f8
[run] [run]
init_cmds = [ init_cmds = [
["go", "build", "-o", "./bin/grafana-server", "./pkg/cmd/grafana-server"], ["go", "run", "build.go", "build"],
["./bin/grafana-server", "cfg:app_mode=development"] ["./bin/grafana-server", "cfg:app_mode=development"]
] ]
watch_all = true watch_all = true
...@@ -12,6 +12,6 @@ watch_dirs = [ ...@@ -12,6 +12,6 @@ watch_dirs = [
watch_exts = [".go", ".ini", ".toml"] watch_exts = [".go", ".ini", ".toml"]
build_delay = 1500 build_delay = 1500
cmds = [ cmds = [
["go", "build", "-o", "./bin/grafana-server", "./pkg/cmd/grafana-server"], ["go", "run", "build.go", "build"],
["./bin/grafana-server", "cfg:app_mode=development"] ["./bin/grafana-server", "cfg:app_mode=development"]
] ]
...@@ -49,6 +49,7 @@ ...@@ -49,6 +49,7 @@
* **Prometheus**: tooltip for legend format not showing properly [#11516](https://github.com/grafana/grafana/issues/11516), thx [@svenklemm](https://github.com/svenklemm) * **Prometheus**: tooltip for legend format not showing properly [#11516](https://github.com/grafana/grafana/issues/11516), thx [@svenklemm](https://github.com/svenklemm)
* **Playlist**: Empty playlists cannot be deleted [#11133](https://github.com/grafana/grafana/issues/11133), thx [@kichristensen](https://github.com/kichristensen) * **Playlist**: Empty playlists cannot be deleted [#11133](https://github.com/grafana/grafana/issues/11133), thx [@kichristensen](https://github.com/kichristensen)
* **Switch Orgs**: Alphabetic order in Switch Organization modal [#11556](https://github.com/grafana/grafana/issues/11556) * **Switch Orgs**: Alphabetic order in Switch Organization modal [#11556](https://github.com/grafana/grafana/issues/11556)
* **Postgres**: improve `$__timeFilter` macro [#11578](https://github.com/grafana/grafana/issues/11578), thx [@svenklemm](https://github.com/svenklemm)
### Tech ### Tech
* Migrated JavaScript files to TypeScript * Migrated JavaScript files to TypeScript
......
...@@ -22,6 +22,7 @@ module.exports = function (grunt) { ...@@ -22,6 +22,7 @@ module.exports = function (grunt) {
} }
} }
config.coverage = grunt.option('coverage');
config.phjs = grunt.option('phjsToRelease'); config.phjs = grunt.option('phjsToRelease');
config.pkg.version = grunt.option('pkgVer') || config.pkg.version; config.pkg.version = grunt.option('pkgVer') || config.pkg.version;
......
coverage:
precision: 2
round: down
range: "50...100"
status:
project: yes
patch: yes
changes: no
comment:
layout: "diff"
behavior: "once"
...@@ -102,6 +102,7 @@ ...@@ -102,6 +102,7 @@
"watch": "webpack --progress --colors --watch --config scripts/webpack/webpack.dev.js", "watch": "webpack --progress --colors --watch --config scripts/webpack/webpack.dev.js",
"build": "grunt build", "build": "grunt build",
"test": "grunt test", "test": "grunt test",
"test:coverage": "grunt test --coverage=true",
"lint": "tslint -c tslint.json --project tsconfig.json --type-check", "lint": "tslint -c tslint.json --project tsconfig.json --type-check",
"karma": "grunt karma:dev", "karma": "grunt karma:dev",
"jest": "jest --notify --watch", "jest": "jest --notify --watch",
......
...@@ -42,7 +42,7 @@ func Init(version string, skipTLSVerify bool) { ...@@ -42,7 +42,7 @@ func Init(version string, skipTLSVerify bool) {
} }
HttpClient = http.Client{ HttpClient = http.Client{
Timeout: time.Duration(10 * time.Second), Timeout: 10 * time.Second,
Transport: tr, Transport: tr,
} }
} }
......
...@@ -33,7 +33,7 @@ func New(orgId int64, name string) KeyGenResult { ...@@ -33,7 +33,7 @@ func New(orgId int64, name string) KeyGenResult {
jsonString, _ := json.Marshal(jsonKey) jsonString, _ := json.Marshal(jsonKey)
result.ClientSecret = base64.StdEncoding.EncodeToString([]byte(jsonString)) result.ClientSecret = base64.StdEncoding.EncodeToString(jsonString)
return result return result
} }
...@@ -44,7 +44,7 @@ func Decode(keyString string) (*ApiKeyJson, error) { ...@@ -44,7 +44,7 @@ func Decode(keyString string) (*ApiKeyJson, error) {
} }
var keyObj ApiKeyJson var keyObj ApiKeyJson
err = json.Unmarshal([]byte(jsonString), &keyObj) err = json.Unmarshal(jsonString, &keyObj)
if err != nil { if err != nil {
return nil, ErrInvalidApiKey return nil, ErrInvalidApiKey
} }
......
...@@ -225,7 +225,7 @@ func (a *Auth) SignRequest(req *http.Request) { ...@@ -225,7 +225,7 @@ func (a *Auth) SignRequest(req *http.Request) {
) )
decodedKey, _ := base64.StdEncoding.DecodeString(a.Key) decodedKey, _ := base64.StdEncoding.DecodeString(a.Key)
sha256 := hmac.New(sha256.New, []byte(decodedKey)) sha256 := hmac.New(sha256.New, decodedKey)
sha256.Write([]byte(strToSign)) sha256.Write([]byte(strToSign))
signature := base64.StdEncoding.EncodeToString(sha256.Sum(nil)) signature := base64.StdEncoding.EncodeToString(sha256.Sum(nil))
......
...@@ -50,7 +50,7 @@ func (f *Float) UnmarshalJSON(data []byte) error { ...@@ -50,7 +50,7 @@ func (f *Float) UnmarshalJSON(data []byte) error {
} }
switch x := v.(type) { switch x := v.(type) {
case float64: case float64:
f.Float64 = float64(x) f.Float64 = x
case map[string]interface{}: case map[string]interface{}:
err = json.Unmarshal(data, &f.NullFloat64) err = json.Unmarshal(data, &f.NullFloat64)
case nil: case nil:
......
...@@ -403,6 +403,6 @@ func sendUsageStats() { ...@@ -403,6 +403,6 @@ func sendUsageStats() {
out, _ := json.MarshalIndent(report, "", " ") out, _ := json.MarshalIndent(report, "", " ")
data := bytes.NewBuffer(out) data := bytes.NewBuffer(out)
client := http.Client{Timeout: time.Duration(5 * time.Second)} client := http.Client{Timeout: 5 * time.Second}
go client.Post("https://stats.grafana.org/grafana-usage-report", "application/json", data) go client.Post("https://stats.grafana.org/grafana-usage-report", "application/json", data)
} }
...@@ -33,7 +33,7 @@ func (ds *DataSource) GetHttpClient() (*http.Client, error) { ...@@ -33,7 +33,7 @@ func (ds *DataSource) GetHttpClient() (*http.Client, error) {
} }
return &http.Client{ return &http.Client{
Timeout: time.Duration(30 * time.Second), Timeout: 30 * time.Second,
Transport: transport, Transport: transport,
}, nil }, nil
} }
......
...@@ -69,7 +69,7 @@ func (pb *PluginBase) registerPlugin(pluginDir string) error { ...@@ -69,7 +69,7 @@ func (pb *PluginBase) registerPlugin(pluginDir string) error {
for _, include := range pb.Includes { for _, include := range pb.Includes {
if include.Role == "" { if include.Role == "" {
include.Role = m.RoleType(m.ROLE_VIEWER) include.Role = m.ROLE_VIEWER
} }
} }
......
...@@ -13,7 +13,7 @@ import ( ...@@ -13,7 +13,7 @@ import (
) )
var ( var (
httpClient http.Client = http.Client{Timeout: time.Duration(10 * time.Second)} httpClient http.Client = http.Client{Timeout: 10 * time.Second}
) )
type GrafanaNetPlugin struct { type GrafanaNetPlugin struct {
......
...@@ -90,7 +90,7 @@ func (this *LineNotifier) createAlert(evalContext *alerting.EvalContext) error { ...@@ -90,7 +90,7 @@ func (this *LineNotifier) createAlert(evalContext *alerting.EvalContext) error {
} }
if err := bus.DispatchCtx(evalContext.Ctx, cmd); err != nil { if err := bus.DispatchCtx(evalContext.Ctx, cmd); err != nil {
this.log.Error("Failed to send notification to LINE", "error", err, "body", string(body)) this.log.Error("Failed to send notification to LINE", "error", err, "body", body)
return err return err
} }
......
...@@ -72,7 +72,7 @@ func (e *CloudWatchExecutor) executeAnnotationQuery(ctx context.Context, queryCo ...@@ -72,7 +72,7 @@ func (e *CloudWatchExecutor) executeAnnotationQuery(ctx context.Context, queryCo
MetricName: aws.String(metricName), MetricName: aws.String(metricName),
Dimensions: qd, Dimensions: qd,
Statistic: aws.String(s), Statistic: aws.String(s),
Period: aws.Int64(int64(period)), Period: aws.Int64(period),
} }
resp, err := svc.DescribeAlarmsForMetric(params) resp, err := svc.DescribeAlarmsForMetric(params)
if err != nil { if err != nil {
...@@ -88,7 +88,7 @@ func (e *CloudWatchExecutor) executeAnnotationQuery(ctx context.Context, queryCo ...@@ -88,7 +88,7 @@ func (e *CloudWatchExecutor) executeAnnotationQuery(ctx context.Context, queryCo
MetricName: aws.String(metricName), MetricName: aws.String(metricName),
Dimensions: qd, Dimensions: qd,
ExtendedStatistic: aws.String(s), ExtendedStatistic: aws.String(s),
Period: aws.Int64(int64(period)), Period: aws.Int64(period),
} }
resp, err := svc.DescribeAlarmsForMetric(params) resp, err := svc.DescribeAlarmsForMetric(params)
if err != nil { if err != nil {
......
...@@ -79,15 +79,15 @@ func (m *PostgresMacroEngine) evaluateMacro(name string, args []string) (string, ...@@ -79,15 +79,15 @@ func (m *PostgresMacroEngine) evaluateMacro(name string, args []string) (string,
} }
return fmt.Sprintf("extract(epoch from %s) as \"time\"", args[0]), nil return fmt.Sprintf("extract(epoch from %s) as \"time\"", args[0]), nil
case "__timeFilter": case "__timeFilter":
// don't use to_timestamp in this macro for redshift compatibility #9566
if len(args) == 0 { if len(args) == 0 {
return "", fmt.Errorf("missing time column argument for macro %v", name) return "", fmt.Errorf("missing time column argument for macro %v", name)
} }
return fmt.Sprintf("extract(epoch from %s) BETWEEN %d AND %d", args[0], m.TimeRange.GetFromAsSecondsEpoch(), m.TimeRange.GetToAsSecondsEpoch()), nil
return fmt.Sprintf("%s BETWEEN '%s' AND '%s'", args[0], m.TimeRange.GetFromAsTimeUTC().Format(time.RFC3339), m.TimeRange.GetToAsTimeUTC().Format(time.RFC3339)), nil
case "__timeFrom": case "__timeFrom":
return fmt.Sprintf("to_timestamp(%d)", m.TimeRange.GetFromAsSecondsEpoch()), nil return fmt.Sprintf("'%s'", m.TimeRange.GetFromAsTimeUTC().Format(time.RFC3339)), nil
case "__timeTo": case "__timeTo":
return fmt.Sprintf("to_timestamp(%d)", m.TimeRange.GetToAsSecondsEpoch()), nil return fmt.Sprintf("'%s'", m.TimeRange.GetToAsTimeUTC().Format(time.RFC3339)), nil
case "__timeGroup": case "__timeGroup":
if len(args) < 2 { if len(args) < 2 {
return "", fmt.Errorf("macro %v needs time column and interval and optional fill value", name) return "", fmt.Errorf("macro %v needs time column and interval and optional fill value", name)
......
...@@ -12,7 +12,7 @@ import ( ...@@ -12,7 +12,7 @@ import (
func TestMacroEngine(t *testing.T) { func TestMacroEngine(t *testing.T) {
Convey("MacroEngine", t, func() { Convey("MacroEngine", t, func() {
engine := &PostgresMacroEngine{} engine := NewPostgresMacroEngine()
query := &tsdb.Query{} query := &tsdb.Query{}
Convey("Given a time range between 2018-04-12 00:00 and 2018-04-12 00:05", func() { Convey("Given a time range between 2018-04-12 00:00 and 2018-04-12 00:05", func() {
...@@ -38,14 +38,14 @@ func TestMacroEngine(t *testing.T) { ...@@ -38,14 +38,14 @@ func TestMacroEngine(t *testing.T) {
sql, err := engine.Interpolate(query, timeRange, "WHERE $__timeFilter(time_column)") sql, err := engine.Interpolate(query, timeRange, "WHERE $__timeFilter(time_column)")
So(err, ShouldBeNil) So(err, ShouldBeNil)
So(sql, ShouldEqual, fmt.Sprintf("WHERE extract(epoch from time_column) BETWEEN %d AND %d", from.Unix(), to.Unix())) So(sql, ShouldEqual, fmt.Sprintf("WHERE time_column BETWEEN '%s' AND '%s'", from.Format(time.RFC3339), to.Format(time.RFC3339)))
}) })
Convey("interpolate __timeFrom function", func() { Convey("interpolate __timeFrom function", func() {
sql, err := engine.Interpolate(query, timeRange, "select $__timeFrom(time_column)") sql, err := engine.Interpolate(query, timeRange, "select $__timeFrom(time_column)")
So(err, ShouldBeNil) So(err, ShouldBeNil)
So(sql, ShouldEqual, fmt.Sprintf("select to_timestamp(%d)", from.Unix())) So(sql, ShouldEqual, fmt.Sprintf("select '%s'", from.Format(time.RFC3339)))
}) })
Convey("interpolate __timeGroup function", func() { Convey("interpolate __timeGroup function", func() {
...@@ -68,7 +68,7 @@ func TestMacroEngine(t *testing.T) { ...@@ -68,7 +68,7 @@ func TestMacroEngine(t *testing.T) {
sql, err := engine.Interpolate(query, timeRange, "select $__timeTo(time_column)") sql, err := engine.Interpolate(query, timeRange, "select $__timeTo(time_column)")
So(err, ShouldBeNil) So(err, ShouldBeNil)
So(sql, ShouldEqual, fmt.Sprintf("select to_timestamp(%d)", to.Unix())) So(sql, ShouldEqual, fmt.Sprintf("select '%s'", to.Format(time.RFC3339)))
}) })
Convey("interpolate __unixEpochFilter function", func() { Convey("interpolate __unixEpochFilter function", func() {
...@@ -102,21 +102,21 @@ func TestMacroEngine(t *testing.T) { ...@@ -102,21 +102,21 @@ func TestMacroEngine(t *testing.T) {
sql, err := engine.Interpolate(query, timeRange, "WHERE $__timeFilter(time_column)") sql, err := engine.Interpolate(query, timeRange, "WHERE $__timeFilter(time_column)")
So(err, ShouldBeNil) So(err, ShouldBeNil)
So(sql, ShouldEqual, fmt.Sprintf("WHERE extract(epoch from time_column) BETWEEN %d AND %d", from.Unix(), to.Unix())) So(sql, ShouldEqual, fmt.Sprintf("WHERE time_column BETWEEN '%s' AND '%s'", from.Format(time.RFC3339), to.Format(time.RFC3339)))
}) })
Convey("interpolate __timeFrom function", func() { Convey("interpolate __timeFrom function", func() {
sql, err := engine.Interpolate(query, timeRange, "select $__timeFrom(time_column)") sql, err := engine.Interpolate(query, timeRange, "select $__timeFrom(time_column)")
So(err, ShouldBeNil) So(err, ShouldBeNil)
So(sql, ShouldEqual, fmt.Sprintf("select to_timestamp(%d)", from.Unix())) So(sql, ShouldEqual, fmt.Sprintf("select '%s'", from.Format(time.RFC3339)))
}) })
Convey("interpolate __timeTo function", func() { Convey("interpolate __timeTo function", func() {
sql, err := engine.Interpolate(query, timeRange, "select $__timeTo(time_column)") sql, err := engine.Interpolate(query, timeRange, "select $__timeTo(time_column)")
So(err, ShouldBeNil) So(err, ShouldBeNil)
So(sql, ShouldEqual, fmt.Sprintf("select to_timestamp(%d)", to.Unix())) So(sql, ShouldEqual, fmt.Sprintf("select '%s'", to.Format(time.RFC3339)))
}) })
Convey("interpolate __unixEpochFilter function", func() { Convey("interpolate __unixEpochFilter function", func() {
...@@ -150,21 +150,21 @@ func TestMacroEngine(t *testing.T) { ...@@ -150,21 +150,21 @@ func TestMacroEngine(t *testing.T) {
sql, err := engine.Interpolate(query, timeRange, "WHERE $__timeFilter(time_column)") sql, err := engine.Interpolate(query, timeRange, "WHERE $__timeFilter(time_column)")
So(err, ShouldBeNil) So(err, ShouldBeNil)
So(sql, ShouldEqual, fmt.Sprintf("WHERE extract(epoch from time_column) BETWEEN %d AND %d", from.Unix(), to.Unix())) So(sql, ShouldEqual, fmt.Sprintf("WHERE time_column BETWEEN '%s' AND '%s'", from.Format(time.RFC3339), to.Format(time.RFC3339)))
}) })
Convey("interpolate __timeFrom function", func() { Convey("interpolate __timeFrom function", func() {
sql, err := engine.Interpolate(query, timeRange, "select $__timeFrom(time_column)") sql, err := engine.Interpolate(query, timeRange, "select $__timeFrom(time_column)")
So(err, ShouldBeNil) So(err, ShouldBeNil)
So(sql, ShouldEqual, fmt.Sprintf("select to_timestamp(%d)", from.Unix())) So(sql, ShouldEqual, fmt.Sprintf("select '%s'", from.Format(time.RFC3339)))
}) })
Convey("interpolate __timeTo function", func() { Convey("interpolate __timeTo function", func() {
sql, err := engine.Interpolate(query, timeRange, "select $__timeTo(time_column)") sql, err := engine.Interpolate(query, timeRange, "select $__timeTo(time_column)")
So(err, ShouldBeNil) So(err, ShouldBeNil)
So(sql, ShouldEqual, fmt.Sprintf("select to_timestamp(%d)", to.Unix())) So(sql, ShouldEqual, fmt.Sprintf("select '%s'", to.Format(time.RFC3339)))
}) })
Convey("interpolate __unixEpochFilter function", func() { Convey("interpolate __unixEpochFilter function", func() {
......
...@@ -108,8 +108,8 @@ func (e *PrometheusExecutor) Query(ctx context.Context, dsInfo *models.DataSourc ...@@ -108,8 +108,8 @@ func (e *PrometheusExecutor) Query(ctx context.Context, dsInfo *models.DataSourc
span, ctx := opentracing.StartSpanFromContext(ctx, "alerting.prometheus") span, ctx := opentracing.StartSpanFromContext(ctx, "alerting.prometheus")
span.SetTag("expr", query.Expr) span.SetTag("expr", query.Expr)
span.SetTag("start_unixnano", int64(query.Start.UnixNano())) span.SetTag("start_unixnano", query.Start.UnixNano())
span.SetTag("stop_unixnano", int64(query.End.UnixNano())) span.SetTag("stop_unixnano", query.End.UnixNano())
defer span.Finish() defer span.Finish()
value, err := client.QueryRange(ctx, query.Expr, timeRange) value, err := client.QueryRange(ctx, query.Expr, timeRange)
......
...@@ -37,6 +37,10 @@ func (tr *TimeRange) GetFromAsSecondsEpoch() int64 { ...@@ -37,6 +37,10 @@ func (tr *TimeRange) GetFromAsSecondsEpoch() int64 {
return tr.GetFromAsMsEpoch() / 1000 return tr.GetFromAsMsEpoch() / 1000
} }
func (tr *TimeRange) GetFromAsTimeUTC() time.Time {
return tr.MustGetFrom().UTC()
}
func (tr *TimeRange) GetToAsMsEpoch() int64 { func (tr *TimeRange) GetToAsMsEpoch() int64 {
return tr.MustGetTo().UnixNano() / int64(time.Millisecond) return tr.MustGetTo().UnixNano() / int64(time.Millisecond)
} }
...@@ -45,6 +49,10 @@ func (tr *TimeRange) GetToAsSecondsEpoch() int64 { ...@@ -45,6 +49,10 @@ func (tr *TimeRange) GetToAsSecondsEpoch() int64 {
return tr.GetToAsMsEpoch() / 1000 return tr.GetToAsMsEpoch() / 1000
} }
func (tr *TimeRange) GetToAsTimeUTC() time.Time {
return tr.MustGetTo().UTC()
}
func (tr *TimeRange) MustGetFrom() time.Time { func (tr *TimeRange) MustGetFrom() time.Time {
if res, err := tr.ParseFrom(); err != nil { if res, err := tr.ParseFrom(); err != nil {
return time.Unix(0, 0) return time.Unix(0, 0)
......
...@@ -8,7 +8,7 @@ class PostgresConfigCtrl { ...@@ -8,7 +8,7 @@ class PostgresConfigCtrl {
/** @ngInject **/ /** @ngInject **/
constructor($scope) { constructor($scope) {
this.current.jsonData.sslmode = this.current.jsonData.sslmode || 'require'; this.current.jsonData.sslmode = this.current.jsonData.sslmode || 'verify-full';
} }
} }
......
...@@ -28,12 +28,12 @@ An annotation is an event that is overlaid on top of graphs. The query can have ...@@ -28,12 +28,12 @@ An annotation is an event that is overlaid on top of graphs. The query can have
Macros: Macros:
- $__time(column) -&gt; column as "time" - $__time(column) -&gt; column as "time"
- $__timeEpoch -&gt; extract(epoch from column) as "time" - $__timeEpoch -&gt; extract(epoch from column) as "time"
- $__timeFilter(column) -&gt; column &ge; to_timestamp(1492750877) AND column &le; to_timestamp(1492750877) - $__timeFilter(column) -&gt; column BETWEEN '2017-04-21T05:01:17Z' AND '2017-04-21T05:01:17Z'
- $__unixEpochFilter(column) -&gt; column &gt; 1492750877 AND column &lt; 1492750877 - $__unixEpochFilter(column) -&gt; column &gt;= 1492750877 AND column &lt;= 1492750877
Or build your own conditionals using these macros which just return the values: Or build your own conditionals using these macros which just return the values:
- $__timeFrom() -&gt; to_timestamp(1492750877) - $__timeFrom() -&gt; '2017-04-21T05:01:17Z'
- $__timeTo() -&gt; to_timestamp(1492750877) - $__timeTo() -&gt; '2017-04-21T05:01:17Z'
- $__unixEpochFrom() -&gt; 1492750877 - $__unixEpochFrom() -&gt; 1492750877
- $__unixEpochTo() -&gt; 1492750877 - $__unixEpochTo() -&gt; 1492750877
</pre> </pre>
......
...@@ -48,8 +48,8 @@ Table: ...@@ -48,8 +48,8 @@ Table:
Macros: Macros:
- $__time(column) -&gt; column as "time" - $__time(column) -&gt; column as "time"
- $__timeEpoch -&gt; extract(epoch from column) as "time" - $__timeEpoch -&gt; extract(epoch from column) as "time"
- $__timeFilter(column) -&gt; extract(epoch from column) BETWEEN 1492750877 AND 1492750877 - $__timeFilter(column) -&gt; column BETWEEN '2017-04-21T05:01:17Z' AND '2017-04-21T05:01:17Z'
- $__unixEpochFilter(column) -&gt; column &gt; 1492750877 AND column &lt; 1492750877 - $__unixEpochFilter(column) -&gt; column &gt;= 1492750877 AND column &lt;= 1492750877
- $__timeGroup(column,'5m') -&gt; (extract(epoch from column)/300)::bigint*300 AS time - $__timeGroup(column,'5m') -&gt; (extract(epoch from column)/300)::bigint*300 AS time
Example of group by and order by with $__timeGroup: Example of group by and order by with $__timeGroup:
...@@ -61,8 +61,8 @@ GROUP BY time ...@@ -61,8 +61,8 @@ GROUP BY time
ORDER BY time ORDER BY time
Or build your own conditionals using these macros which just return the values: Or build your own conditionals using these macros which just return the values:
- $__timeFrom() -&gt; to_timestamp(1492750877) - $__timeFrom() -&gt; '2017-04-21T05:01:17Z'
- $__timeTo() -&gt; to_timestamp(1492750877) - $__timeTo() -&gt; '2017-04-21T05:01:17Z'
- $__unixEpochFrom() -&gt; 1492750877 - $__unixEpochFrom() -&gt; 1492750877
- $__unixEpochTo() -&gt; 1492750877 - $__unixEpochTo() -&gt; 1492750877
</pre> </pre>
......
...@@ -20,4 +20,17 @@ echo "building backend with install to cache pkgs" ...@@ -20,4 +20,17 @@ echo "building backend with install to cache pkgs"
exit_if_fail time go install ./pkg/cmd/grafana-server exit_if_fail time go install ./pkg/cmd/grafana-server
echo "running go test" echo "running go test"
go test ./pkg/...
set -e
echo "" > coverage.txt
time for d in $(go list ./pkg/...); do
exit_if_fail go test -coverprofile=profile.out -covermode=atomic $d
if [ -f profile.out ]; then
cat profile.out >> coverage.txt
rm profile.out
fi
done
echo "Publishing go code coverage"
bash <(curl -s https://codecov.io/bash) -cF go
...@@ -10,5 +10,10 @@ function exit_if_fail { ...@@ -10,5 +10,10 @@ function exit_if_fail {
fi fi
} }
exit_if_fail npm run test exit_if_fail npm run test:coverage
exit_if_fail npm run build exit_if_fail npm run build
\ No newline at end of file
# publish code coverage
echo "Publishing javascript code coverage"
bash <(curl -s https://codecov.io/bash) -cF javascript
rm -rf coverage
module.exports = function(config, grunt) { module.exports = function(config, grunt) {
'use strict'; 'use strict';
var coverage = '';
if (config.coverage) {
coverage = '--coverage --maxWorkers 2';
}
return { return {
tslint: 'node ./node_modules/tslint/lib/tslint-cli.js -c tslint.json --project ./tsconfig.json', tslint: 'node ./node_modules/tslint/lib/tslint-cli.js -c tslint.json --project ./tsconfig.json',
jest: 'node ./node_modules/jest-cli/bin/jest.js --maxWorkers 2', jest: 'node ./node_modules/jest-cli/bin/jest.js ' + coverage,
webpack: 'node ./node_modules/webpack/bin/webpack.js --config scripts/webpack/webpack.prod.js', webpack: 'node ./node_modules/webpack/bin/webpack.js --config scripts/webpack/webpack.prod.js',
}; };
}; };
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment