Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
N
nexpie-grafana-theme
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Registry
Registry
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Kornkitt Poolsup
nexpie-grafana-theme
Commits
fd06e517
Commit
fd06e517
authored
Jan 28, 2019
by
Torkel Ödegaard
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'master' into fix/explore-do-not-clear-results
parents
d947748d
50b140f6
Hide whitespace changes
Inline
Side-by-side
Showing
22 changed files
with
562 additions
and
466 deletions
+562
-466
.circleci/config.yml
+1
-5
conf/defaults.ini
+1
-1
conf/sample.ini
+1
-1
pkg/api/dashboard.go
+1
-1
pkg/setting/setting.go
+1
-1
public/app/core/actions/location.ts
+6
-2
public/app/core/reducers/location.ts
+3
-5
public/app/features/dashboard/services/DashboardViewStateSrv.test.ts
+0
-1
public/app/features/dashboard/services/DashboardViewStateSrv.ts
+11
-2
public/app/features/explore/Explore.tsx
+2
-103
public/app/features/explore/ExploreToolbar.tsx
+191
-0
public/app/features/explore/QueryField.tsx
+12
-7
public/app/features/explore/TimePicker.tsx
+1
-0
public/app/features/explore/Wrapper.tsx
+7
-1
public/app/features/explore/state/actionTypes.ts
+9
-2
public/app/features/explore/state/actions.ts
+11
-2
public/app/features/explore/state/reducers.ts
+7
-13
public/app/plugins/datasource/loki/language_provider.ts
+2
-1
public/dashboards/home.json
+19
-2
public/sass/pages/_explore.scss
+266
-122
scripts/build/publish.go
+0
-194
scripts/build/release_publisher/publisher.go
+10
-0
No files found.
.circleci/config.yml
View file @
fd06e517
...
...
@@ -148,9 +148,6 @@ jobs:
name
:
sha-sum packages
command
:
'
go
run
build.go
sha-dist'
-
run
:
name
:
Build Grafana.com master publisher
command
:
'
go
build
-o
scripts/publish
scripts/build/publish.go'
-
run
:
name
:
Test and build Grafana.com release publisher
command
:
'
cd
scripts/build/release_publisher
&&
go
test
.
&&
go
build
-o
release_publisher
.'
-
persist_to_workspace
:
...
...
@@ -158,7 +155,6 @@ jobs:
paths
:
-
dist/grafana*
-
scripts/*.sh
-
scripts/publish
-
scripts/build/release_publisher/release_publisher
-
scripts/build/publish.sh
...
...
@@ -393,7 +389,7 @@ jobs:
name
:
Publish to Grafana.com
command
:
|
rm dist/grafana-master-$(echo "${CIRCLE_SHA1}" | cut -b1-7).linux-x64.tar.gz
./scripts/publish -apiKey ${GRAFANA_COM_API_KEY}
cd dist && ../scripts/build/release_publisher/release_publisher -apikey ${GRAFANA_COM_API_KEY} -from-local
deploy-release
:
docker
:
...
...
conf/defaults.ini
View file @
fd06e517
...
...
@@ -504,7 +504,7 @@ concurrent_render_limit = 5
#################################### Explore #############################
[explore]
# Enable the Explore section
enabled
=
fals
e
enabled
=
tru
e
#################################### Internal Grafana Metrics ############
# Metrics available at HTTP API Url /metrics
...
...
conf/sample.ini
View file @
fd06e517
...
...
@@ -429,7 +429,7 @@ log_queries =
#################################### Explore #############################
[explore]
# Enable the Explore section
;enabled =
fals
e
;enabled =
tru
e
#################################### Internal Grafana Metrics ##########################
# Metrics available at HTTP API Url /metrics
...
...
pkg/api/dashboard.go
View file @
fd06e517
...
...
@@ -336,7 +336,7 @@ func addGettingStartedPanelToHomeDashboard(dash *simplejson.Json) {
"id"
:
123123
,
"gridPos"
:
map
[
string
]
interface
{}{
"x"
:
0
,
"y"
:
0
,
"y"
:
3
,
"w"
:
24
,
"h"
:
4
,
},
...
...
pkg/setting/setting.go
View file @
fd06e517
...
...
@@ -718,7 +718,7 @@ func (cfg *Cfg) Load(args *CommandLineArgs) error {
AlertingNoDataOrNullValues
=
alerting
.
Key
(
"nodata_or_nullvalues"
)
.
MustString
(
"no_data"
)
explore
:=
iniFile
.
Section
(
"explore"
)
ExploreEnabled
=
explore
.
Key
(
"enabled"
)
.
MustBool
(
fals
e
)
ExploreEnabled
=
explore
.
Key
(
"enabled"
)
.
MustBool
(
tru
e
)
panels
:=
iniFile
.
Section
(
"panels"
)
cfg
.
EnableAlphaPanels
=
panels
.
Key
(
"enable_alpha"
)
.
MustBool
(
false
)
...
...
public/app/core/actions/location.ts
View file @
fd06e517
import
{
LocationUpdate
}
from
'app/types'
;
export
enum
CoreActionTypes
{
UpdateLocation
=
'UPDATE_LOCATION'
,
}
export
type
Action
=
UpdateLocationAction
;
export
interface
UpdateLocationAction
{
type
:
'UPDATE_LOCATION'
;
type
:
CoreActionTypes
.
UpdateLocation
;
payload
:
LocationUpdate
;
}
export
const
updateLocation
=
(
location
:
LocationUpdate
):
UpdateLocationAction
=>
({
type
:
'UPDATE_LOCATION'
,
type
:
CoreActionTypes
.
UpdateLocation
,
payload
:
location
,
});
public/app/core/reducers/location.ts
View file @
fd06e517
import
{
Action
}
from
'app/core/actions/location'
;
import
{
Action
,
CoreActionTypes
}
from
'app/core/actions/location'
;
import
{
LocationState
}
from
'app/types'
;
import
{
renderUrl
}
from
'app/core/utils/url'
;
import
_
from
'lodash'
;
...
...
@@ -12,7 +12,7 @@ export const initialState: LocationState = {
export
const
locationReducer
=
(
state
=
initialState
,
action
:
Action
):
LocationState
=>
{
switch
(
action
.
type
)
{
case
'UPDATE_LOCATION'
:
{
case
CoreActionTypes
.
UpdateLocation
:
{
const
{
path
,
routeParams
}
=
action
.
payload
;
let
query
=
action
.
payload
.
query
||
state
.
query
;
...
...
@@ -24,9 +24,7 @@ export const locationReducer = (state = initialState, action: Action): LocationS
return
{
url
:
renderUrl
(
path
||
state
.
path
,
query
),
path
:
path
||
state
.
path
,
query
:
{
...
query
,
},
query
:
{
...
query
},
routeParams
:
routeParams
||
state
.
routeParams
,
};
}
...
...
public/app/features/dashboard/services/DashboardViewStateSrv.test.ts
View file @
fd06e517
...
...
@@ -58,7 +58,6 @@ describe('when updating view state', () => {
it
(
'should remove params from query string'
,
()
=>
{
viewState
.
update
({
fullscreen
:
true
,
panelId
:
1
,
edit
:
true
});
viewState
.
update
({
fullscreen
:
false
});
expect
(
viewState
.
dashboard
.
meta
.
fullscreen
).
toBe
(
false
);
expect
(
viewState
.
state
.
fullscreen
).
toBe
(
null
);
});
});
...
...
public/app/features/dashboard/services/DashboardViewStateSrv.ts
View file @
fd06e517
...
...
@@ -72,7 +72,6 @@ export class DashboardViewStateSrv {
}
_
.
extend
(
this
.
state
,
state
);
this
.
dashboard
.
meta
.
fullscreen
=
this
.
state
.
fullscreen
;
if
(
!
this
.
state
.
fullscreen
)
{
this
.
state
.
fullscreen
=
null
;
...
...
@@ -117,10 +116,20 @@ export class DashboardViewStateSrv {
}
syncState
()
{
if
(
this
.
dashboard
.
meta
.
fullscreen
)
{
if
(
this
.
state
.
fullscreen
)
{
const
panel
=
this
.
dashboard
.
getPanelById
(
this
.
state
.
panelId
);
if
(
!
panel
)
{
this
.
state
.
fullscreen
=
null
;
this
.
state
.
panelId
=
null
;
this
.
state
.
edit
=
null
;
this
.
update
(
this
.
state
);
setTimeout
(()
=>
{
appEvents
.
emit
(
'alert-error'
,
[
'Error'
,
'Panel not found'
]);
},
100
);
return
;
}
...
...
public/app/features/explore/Explore.tsx
View file @
fd06e517
...
...
@@ -9,8 +9,6 @@ import { AutoSizer } from 'react-virtualized';
import
store
from
'app/core/store'
;
// Components
import
{
DataSourceSelectItem
}
from
'@grafana/ui/src/types'
;
import
{
DataSourcePicker
}
from
'app/core/components/Select/DataSourcePicker'
;
import
{
Alert
}
from
'./Error'
;
import
ErrorBoundary
from
'./ErrorBoundary'
;
import
GraphContainer
from
'./GraphContainer'
;
...
...
@@ -21,18 +19,13 @@ import TimePicker, { parseTime } from './TimePicker';
// Actions
import
{
changeDatasource
,
changeSize
,
changeTime
,
clearQueries
,
initializeExplore
,
modifyQueries
,
runQueries
,
scanStart
,
scanStop
,
setQueries
,
splitClose
,
splitOpen
,
}
from
'./state/actions'
;
// Types
...
...
@@ -41,27 +34,23 @@ import { ExploreItemState, ExploreUrlState, RangeScanner, ExploreId } from 'app/
import
{
StoreState
}
from
'app/types'
;
import
{
LAST_USED_DATASOURCE_KEY
,
ensureQueries
,
DEFAULT_RANGE
}
from
'app/core/utils/explore'
;
import
{
Emitter
}
from
'app/core/utils/emitter'
;
import
{
ExploreToolbar
}
from
'./ExploreToolbar'
;
interface
ExploreProps
{
StartPage
?:
any
;
changeDatasource
:
typeof
changeDatasource
;
changeSize
:
typeof
changeSize
;
changeTime
:
typeof
changeTime
;
clearQueries
:
typeof
clearQueries
;
datasourceError
:
string
;
datasourceInstance
:
any
;
datasourceLoading
:
boolean
|
null
;
datasourceMissing
:
boolean
;
exploreDatasources
:
DataSourceSelectItem
[];
exploreId
:
ExploreId
;
initialDatasource
?:
string
;
initialQueries
:
DataQuery
[];
initializeExplore
:
typeof
initializeExplore
;
initialized
:
boolean
;
loading
:
boolean
;
modifyQueries
:
typeof
modifyQueries
;
range
:
RawTimeRange
;
runQueries
:
typeof
runQueries
;
scanner
?:
RangeScanner
;
scanning
?:
boolean
;
scanRange
?:
RawTimeRange
;
...
...
@@ -69,8 +58,6 @@ interface ExploreProps {
scanStop
:
typeof
scanStop
;
setQueries
:
typeof
setQueries
;
split
:
boolean
;
splitClose
:
typeof
splitClose
;
splitOpen
:
typeof
splitOpen
;
showingStartPage
?:
boolean
;
supportsGraph
:
boolean
|
null
;
supportsLogs
:
boolean
|
null
;
...
...
@@ -145,10 +132,6 @@ export class Explore extends React.PureComponent<ExploreProps> {
this
.
el
=
el
;
};
onChangeDatasource
=
async
option
=>
{
this
.
props
.
changeDatasource
(
this
.
props
.
exploreId
,
option
.
value
);
};
onChangeTime
=
(
range
:
TimeRange
,
changedByScanner
?:
boolean
)
=>
{
if
(
this
.
props
.
scanning
&&
!
changedByScanner
)
{
this
.
onStopScanning
();
...
...
@@ -156,23 +139,11 @@ export class Explore extends React.PureComponent<ExploreProps> {
this
.
props
.
changeTime
(
this
.
props
.
exploreId
,
range
);
};
onClickClear
=
()
=>
{
this
.
props
.
clearQueries
(
this
.
props
.
exploreId
);
};
onClickCloseSplit
=
()
=>
{
this
.
props
.
splitClose
();
};
// Use this in help pages to set page to a single query
onClickExample
=
(
query
:
DataQuery
)
=>
{
this
.
props
.
setQueries
(
this
.
props
.
exploreId
,
[
query
]);
};
onClickSplit
=
()
=>
{
this
.
props
.
splitOpen
();
};
onClickLabel
=
(
key
:
string
,
value
:
string
)
=>
{
this
.
onModifyQueries
({
type
:
'ADD_FILTER'
,
key
,
value
});
};
...
...
@@ -204,10 +175,6 @@ export class Explore extends React.PureComponent<ExploreProps> {
this
.
props
.
scanStop
(
this
.
props
.
exploreId
);
};
onSubmit
=
()
=>
{
this
.
props
.
runQueries
(
this
.
props
.
exploreId
);
};
render
()
{
const
{
StartPage
,
...
...
@@ -215,11 +182,8 @@ export class Explore extends React.PureComponent<ExploreProps> {
datasourceError
,
datasourceLoading
,
datasourceMissing
,
exploreDatasources
,
exploreId
,
loading
,
initialQueries
,
range
,
showingStartPage
,
split
,
supportsGraph
,
...
...
@@ -227,64 +191,10 @@ export class Explore extends React.PureComponent<ExploreProps> {
supportsTable
,
}
=
this
.
props
;
const
exploreClass
=
split
?
'explore explore-split'
:
'explore'
;
const
selectedDatasource
=
datasourceInstance
?
exploreDatasources
.
find
(
d
=>
d
.
name
===
datasourceInstance
.
name
)
:
undefined
;
return
(
<
div
className=
{
exploreClass
}
ref=
{
this
.
getRef
}
>
<
div
className=
"navbar"
>
{
exploreId
===
'left'
?
(
<
div
>
<
a
className=
"navbar-page-btn"
>
<
i
className=
"fa fa-rocket"
/>
Explore
</
a
>
</
div
>
)
:
(
<>
<
div
className=
"navbar-page-btn"
/>
<
div
className=
"navbar-buttons explore-first-button"
>
<
button
className=
"btn navbar-button"
onClick=
{
this
.
onClickCloseSplit
}
>
Close Split
</
button
>
</
div
>
</>
)
}
{
!
datasourceMissing
?
(
<
div
className=
"navbar-buttons"
>
<
DataSourcePicker
onChange=
{
this
.
onChangeDatasource
}
datasources=
{
exploreDatasources
}
current=
{
selectedDatasource
}
/>
</
div
>
)
:
null
}
<
div
className=
"navbar__spacer"
/>
{
exploreId
===
'left'
&&
!
split
?
(
<
div
className=
"navbar-buttons"
>
<
button
className=
"btn navbar-button"
onClick=
{
this
.
onClickSplit
}
>
Split
</
button
>
</
div
>
)
:
null
}
<
TimePicker
ref=
{
this
.
timepickerRef
}
range=
{
range
}
onChangeTime=
{
this
.
onChangeTime
}
/>
<
div
className=
"navbar-buttons"
>
<
button
className=
"btn navbar-button navbar-button--no-icon"
onClick=
{
this
.
onClickClear
}
>
Clear All
</
button
>
</
div
>
<
div
className=
"navbar-buttons relative"
>
<
button
className=
"btn navbar-button navbar-button--primary"
onClick=
{
this
.
onSubmit
}
>
Run Query
{
' '
}
{
loading
?
(
<
i
className=
"fa fa-spinner fa-fw fa-spin run-icon"
/>
)
:
(
<
i
className=
"fa fa-level-down fa-fw run-icon"
/>
)
}
</
button
>
</
div
>
</
div
>
<
ExploreToolbar
exploreId=
{
exploreId
}
timepickerRef=
{
this
.
timepickerRef
}
onChangeTime=
{
this
.
onChangeTime
}
/>
{
datasourceLoading
?
<
div
className=
"explore-container"
>
Loading datasource...
</
div
>
:
null
}
{
datasourceMissing
?
(
<
div
className=
"explore-container"
>
Please add a datasource that supports Explore (e.g., Prometheus).
</
div
>
...
...
@@ -341,30 +251,24 @@ function mapStateToProps(state: StoreState, { exploreId }) {
datasourceInstance
,
datasourceLoading
,
datasourceMissing
,
exploreDatasources
,
initialDatasource
,
initialQueries
,
initialized
,
queryTransactions
,
range
,
showingStartPage
,
supportsGraph
,
supportsLogs
,
supportsTable
,
}
=
item
;
const
loading
=
queryTransactions
.
some
(
qt
=>
!
qt
.
done
);
return
{
StartPage
,
datasourceError
,
datasourceInstance
,
datasourceLoading
,
datasourceMissing
,
exploreDatasources
,
initialDatasource
,
initialQueries
,
initialized
,
loading
,
queryTransactions
,
range
,
showingStartPage
,
split
,
...
...
@@ -375,18 +279,13 @@ function mapStateToProps(state: StoreState, { exploreId }) {
}
const
mapDispatchToProps
=
{
changeDatasource
,
changeSize
,
changeTime
,
clearQueries
,
initializeExplore
,
modifyQueries
,
runQueries
,
scanStart
,
scanStop
,
setQueries
,
splitClose
,
splitOpen
,
};
export
default
hot
(
module
)(
connect
(
mapStateToProps
,
mapDispatchToProps
)(
Explore
));
public/app/features/explore/ExploreToolbar.tsx
0 → 100644
View file @
fd06e517
import
React
,
{
PureComponent
}
from
'react'
;
import
{
connect
}
from
'react-redux'
;
import
{
hot
}
from
'react-hot-loader'
;
import
{
ExploreId
}
from
'app/types/explore'
;
import
{
DataSourceSelectItem
,
RawTimeRange
,
TimeRange
}
from
'@grafana/ui'
;
import
{
DataSourcePicker
}
from
'app/core/components/Select/DataSourcePicker'
;
import
{
StoreState
}
from
'app/types/store'
;
import
{
changeDatasource
,
clearQueries
,
splitClose
,
runQueries
,
splitOpen
}
from
'./state/actions'
;
import
TimePicker
from
'./TimePicker'
;
enum
IconSide
{
left
=
'left'
,
right
=
'right'
,
}
const
createResponsiveButton
=
(
options
:
{
splitted
:
boolean
;
title
:
string
;
onClick
:
()
=>
void
;
buttonClassName
?:
string
;
iconClassName
?:
string
;
iconSide
?:
IconSide
;
})
=>
{
const
defaultOptions
=
{
iconSide
:
IconSide
.
left
,
};
const
props
=
{
...
options
,
defaultOptions
};
const
{
title
,
onClick
,
buttonClassName
,
iconClassName
,
splitted
,
iconSide
}
=
props
;
return
(
<
button
className=
{
`btn navbar-button ${buttonClassName ? buttonClassName : ''}`
}
onClick=
{
onClick
}
>
{
iconClassName
&&
iconSide
===
IconSide
.
left
?
<
i
className=
{
`${iconClassName} icon-margin-right`
}
/>
:
null
}
<
span
className=
"btn-title"
>
{
!
splitted
?
title
:
''
}
</
span
>
{
iconClassName
&&
iconSide
===
IconSide
.
right
?
<
i
className=
{
`${iconClassName} icon-margin-left`
}
/>
:
null
}
</
button
>
);
};
interface
OwnProps
{
exploreId
:
ExploreId
;
timepickerRef
:
React
.
RefObject
<
TimePicker
>
;
onChangeTime
:
(
range
:
TimeRange
,
changedByScanner
?:
boolean
)
=>
void
;
}
interface
StateProps
{
datasourceMissing
:
boolean
;
exploreDatasources
:
DataSourceSelectItem
[];
loading
:
boolean
;
range
:
RawTimeRange
;
selectedDatasource
:
DataSourceSelectItem
;
splitted
:
boolean
;
}
interface
DispatchProps
{
changeDatasource
:
typeof
changeDatasource
;
clearAll
:
typeof
clearQueries
;
runQuery
:
typeof
runQueries
;
closeSplit
:
typeof
splitClose
;
split
:
typeof
splitOpen
;
}
type
Props
=
StateProps
&
DispatchProps
&
OwnProps
;
export
class
UnConnectedExploreToolbar
extends
PureComponent
<
Props
,
{}
>
{
constructor
(
props
)
{
super
(
props
);
}
onChangeDatasource
=
async
option
=>
{
this
.
props
.
changeDatasource
(
this
.
props
.
exploreId
,
option
.
value
);
};
onClearAll
=
()
=>
{
this
.
props
.
clearAll
(
this
.
props
.
exploreId
);
};
onRunQuery
=
()
=>
{
this
.
props
.
runQuery
(
this
.
props
.
exploreId
);
};
render
()
{
const
{
datasourceMissing
,
exploreDatasources
,
exploreId
,
loading
,
range
,
selectedDatasource
,
splitted
,
timepickerRef
,
}
=
this
.
props
;
return
(
<
div
className=
{
splitted
?
'explore-toolbar splitted'
:
'explore-toolbar'
}
>
<
div
className=
"explore-toolbar-item"
>
<
div
className=
"explore-toolbar-header"
>
<
div
className=
"explore-toolbar-header-title"
>
{
exploreId
===
'left'
&&
(
<
a
className=
"navbar-page-btn"
>
<
i
className=
"fa fa-rocket fa-fw"
/>
Explore
</
a
>
)
}
</
div
>
<
div
className=
"explore-toolbar-header-close"
>
{
exploreId
===
'right'
&&
(
<
a
onClick=
{
this
.
props
.
closeSplit
}
>
<
i
className=
"fa fa-times fa-fw"
/>
</
a
>
)
}
</
div
>
</
div
>
</
div
>
<
div
className=
"explore-toolbar-item"
>
<
div
className=
"explore-toolbar-content"
>
{
!
datasourceMissing
?
(
<
div
className=
"explore-toolbar-content-item"
>
<
div
className=
"datasource-picker"
>
<
DataSourcePicker
onChange=
{
this
.
onChangeDatasource
}
datasources=
{
exploreDatasources
}
current=
{
selectedDatasource
}
/>
</
div
>
</
div
>
)
:
null
}
{
exploreId
===
'left'
&&
!
splitted
?
(
<
div
className=
"explore-toolbar-content-item"
>
{
createResponsiveButton
({
splitted
,
title
:
'Split'
,
onClick
:
this
.
props
.
split
,
iconClassName
:
'fa fa-fw fa-columns icon-margin-right'
,
iconSide
:
IconSide
.
left
,
})
}
</
div
>
)
:
null
}
<
div
className=
"explore-toolbar-content-item timepicker"
>
<
TimePicker
ref=
{
timepickerRef
}
range=
{
range
}
onChangeTime=
{
this
.
props
.
onChangeTime
}
/>
</
div
>
<
div
className=
"explore-toolbar-content-item"
>
<
button
className=
"btn navbar-button navbar-button--no-icon"
onClick=
{
this
.
onClearAll
}
>
Clear All
</
button
>
</
div
>
<
div
className=
"explore-toolbar-content-item"
>
{
createResponsiveButton
({
splitted
,
title
:
'Run Query'
,
onClick
:
this
.
onRunQuery
,
buttonClassName
:
'navbar-button--primary'
,
iconClassName
:
loading
?
'fa fa-spinner fa-fw fa-spin run-icon'
:
'fa fa-level-down fa-fw run-icon'
,
iconSide
:
IconSide
.
right
,
})
}
</
div
>
</
div
>
</
div
>
</
div
>
);
}
}
const
mapStateToProps
=
(
state
:
StoreState
,
{
exploreId
}:
OwnProps
):
StateProps
=>
{
const
splitted
=
state
.
explore
.
split
;
const
exploreItem
=
state
.
explore
[
exploreId
];
const
{
datasourceInstance
,
datasourceMissing
,
exploreDatasources
,
queryTransactions
,
range
}
=
exploreItem
;
const
selectedDatasource
=
datasourceInstance
?
exploreDatasources
.
find
(
datasource
=>
datasource
.
name
===
datasourceInstance
.
name
)
:
undefined
;
const
loading
=
queryTransactions
.
some
(
qt
=>
!
qt
.
done
);
return
{
datasourceMissing
,
exploreDatasources
,
loading
,
range
,
selectedDatasource
,
splitted
,
};
};
const
mapDispatchToProps
:
DispatchProps
=
{
changeDatasource
,
clearAll
:
clearQueries
,
runQuery
:
runQueries
,
closeSplit
:
splitClose
,
split
:
splitOpen
,
};
export
const
ExploreToolbar
=
hot
(
module
)(
connect
(
mapStateToProps
,
mapDispatchToProps
)(
UnConnectedExploreToolbar
));
public/app/features/explore/QueryField.tsx
View file @
fd06e517
...
...
@@ -73,6 +73,7 @@ export class QueryField extends React.PureComponent<QueryFieldProps, QueryFieldS
placeholdersBuffer
:
PlaceholdersBuffer
;
plugins
:
any
[];
resetTimer
:
any
;
mounted
:
boolean
;
constructor
(
props
:
QueryFieldProps
,
context
)
{
super
(
props
,
context
);
...
...
@@ -93,10 +94,12 @@ export class QueryField extends React.PureComponent<QueryFieldProps, QueryFieldS
}
componentDidMount
()
{
this
.
mounted
=
true
;
this
.
updateMenu
();
}
componentWillUnmount
()
{
this
.
mounted
=
false
;
clearTimeout
(
this
.
resetTimer
);
}
...
...
@@ -347,13 +350,15 @@ export class QueryField extends React.PureComponent<QueryFieldProps, QueryFieldS
};
resetTypeahead
=
()
=>
{
this
.
setState
({
suggestions
:
[],
typeaheadIndex
:
0
,
typeaheadPrefix
:
''
,
typeaheadContext
:
null
,
});
this
.
resetTimer
=
null
;
if
(
this
.
mounted
)
{
this
.
setState
({
suggestions
:
[],
typeaheadIndex
:
0
,
typeaheadPrefix
:
''
,
typeaheadContext
:
null
,
});
this
.
resetTimer
=
null
;
}
};
handleBlur
=
()
=>
{
...
...
public/app/features/explore/TimePicker.tsx
View file @
fd06e517
...
...
@@ -293,6 +293,7 @@ export default class TimePicker extends PureComponent<TimePickerProps, TimePicke
render
()
{
const
{
isUtc
,
rangeString
,
refreshInterval
}
=
this
.
state
;
return
(
<
div
className=
"timepicker"
>
<
div
className=
"navbar-buttons"
>
...
...
public/app/features/explore/Wrapper.tsx
View file @
fd06e517
...
...
@@ -7,7 +7,7 @@ import { StoreState } from 'app/types';
import
{
ExploreId
,
ExploreUrlState
}
from
'app/types/explore'
;
import
{
parseUrlState
}
from
'app/core/utils/explore'
;
import
{
initializeExploreSplit
}
from
'./state/actions'
;
import
{
initializeExploreSplit
,
resetExplore
}
from
'./state/actions'
;
import
ErrorBoundary
from
'./ErrorBoundary'
;
import
Explore
from
'./Explore'
;
import
{
CustomScrollbar
}
from
'@grafana/ui'
;
...
...
@@ -16,6 +16,7 @@ interface WrapperProps {
initializeExploreSplit
:
typeof
initializeExploreSplit
;
split
:
boolean
;
updateLocation
:
typeof
updateLocation
;
resetExplore
:
typeof
resetExplore
;
urlStates
:
{
[
key
:
string
]:
string
};
}
...
...
@@ -42,6 +43,10 @@ export class Wrapper extends Component<WrapperProps> {
}
}
componentWillUnmount
()
{
this
.
props
.
resetExplore
();
}
render
()
{
const
{
split
}
=
this
.
props
;
const
{
leftState
,
rightState
}
=
this
.
urlStates
;
...
...
@@ -74,6 +79,7 @@ const mapStateToProps = (state: StoreState) => {
const
mapDispatchToProps
=
{
initializeExploreSplit
,
updateLocation
,
resetExplore
,
};
export
default
hot
(
module
)(
connect
(
mapStateToProps
,
mapDispatchToProps
)(
Wrapper
));
public/app/features/explore/state/actionTypes.ts
View file @
fd06e517
// Types
import
{
Emitter
}
from
'app/core/core'
;
import
{
RawTimeRange
,
TimeRange
,
DataQuery
,
DataSourceSelectItem
}
from
'@grafana/ui/src/types'
;
import
{
RawTimeRange
,
TimeRange
,
DataQuery
,
DataSourceSelectItem
}
from
'@grafana/ui/src/types'
;
import
{
ExploreId
,
ExploreItemState
,
...
...
@@ -41,6 +41,7 @@ export enum ActionTypes {
ToggleGraph
=
'explore/TOGGLE_GRAPH'
,
ToggleLogs
=
'explore/TOGGLE_LOGS'
,
ToggleTable
=
'explore/TOGGLE_TABLE'
,
ResetExplore
=
'explore/RESET_EXPLORE'
,
}
export
interface
AddQueryRowAction
{
...
...
@@ -270,6 +271,11 @@ export interface ToggleLogsAction {
};
}
export
interface
ResetExploreAction
{
type
:
ActionTypes
.
ResetExplore
;
payload
:
{};
}
export
type
Action
=
|
AddQueryRowAction
|
ChangeQueryAction
...
...
@@ -297,4 +303,5 @@ export type Action =
|
SplitOpenAction
|
ToggleGraphAction
|
ToggleLogsAction
|
ToggleTableAction
;
|
ToggleTableAction
|
ResetExploreAction
;
public/app/features/explore/state/actions.ts
View file @
fd06e517
...
...
@@ -21,7 +21,7 @@ import { updateLocation } from 'app/core/actions';
// Types
import
{
StoreState
}
from
'app/types'
;
import
{
DataQuery
,
DataSourceSelectItem
,
QueryHint
}
from
'@grafana/ui/src/types'
;
import
{
DataQuery
,
DataSourceSelectItem
,
QueryHint
}
from
'@grafana/ui/src/types'
;
import
{
getDatasourceSrv
}
from
'app/features/plugins/datasource_srv'
;
import
{
ExploreId
,
...
...
@@ -48,7 +48,6 @@ import {
ScanStopAction
,
}
from
'./actionTypes'
;
type
ThunkResult
<
R
>
=
ThunkAction
<
R
,
StoreState
,
undefined
,
ThunkableAction
>
;
/**
...
...
@@ -539,6 +538,7 @@ export function runQueries(exploreId: ExploreId) {
if
(
!
hasNonEmptyQuery
(
modifiedQueries
))
{
dispatch
({
type
:
ActionTypes
.
RunQueriesEmpty
,
payload
:
{
exploreId
}
});
dispatch
(
stateSave
());
// Remember to saves to state and update location
return
;
}
...
...
@@ -766,3 +766,12 @@ export function toggleTable(exploreId: ExploreId): ThunkResult<void> {
}
};
}
/**
* Resets state for explore.
*/
export
function
resetExplore
():
ThunkResult
<
void
>
{
return
dispatch
=>
{
dispatch
({
type
:
ActionTypes
.
ResetExplore
,
payload
:
{}
});
};
}
public/app/features/explore/state/reducers.ts
View file @
fd06e517
...
...
@@ -422,25 +422,19 @@ export const itemReducer = (state, action: Action): ExploreItemState => {
export
const
exploreReducer
=
(
state
=
initialExploreState
,
action
:
Action
):
ExploreState
=>
{
switch
(
action
.
type
)
{
case
ActionTypes
.
SplitClose
:
{
return
{
...
state
,
split
:
false
,
};
return
{
...
state
,
split
:
false
};
}
case
ActionTypes
.
SplitOpen
:
{
return
{
...
state
,
split
:
true
,
right
:
action
.
payload
.
itemState
,
};
return
{
...
state
,
split
:
true
,
right
:
action
.
payload
.
itemState
};
}
case
ActionTypes
.
InitializeExploreSplit
:
{
return
{
...
state
,
split
:
true
,
};
return
{
...
state
,
split
:
true
};
}
case
ActionTypes
.
ResetExplore
:
{
return
initialExploreState
;
}
}
...
...
public/app/plugins/datasource/loki/language_provider.ts
View file @
fd06e517
...
...
@@ -173,8 +173,9 @@ export default class LokiLanguageProvider extends LanguageProvider {
})
);
}
// Return a cleaned LokiQuery
return
queries
.
map
(
query
=>
({
...
query
,
refId
:
query
.
refId
,
expr
:
''
,
}));
}
...
...
public/dashboards/home.json
View file @
fd06e517
...
...
@@ -11,6 +11,23 @@
"links"
:
[],
"panels"
:
[
{
"content"
:
"<div class=
\"
text-center dashboard-header
\"
>
\n
<span>Home Dashboard</span>
\n
</div>"
,
"editable"
:
true
,
"id"
:
1
,
"links"
:
[],
"mode"
:
"html"
,
"style"
:
{},
"title"
:
""
,
"transparent"
:
true
,
"type"
:
"text"
,
"gridPos"
:
{
"w"
:
24
,
"h"
:
3
,
"x"
:
0
,
"y"
:
0
}
},
{
"folderId"
:
0
,
"headings"
:
true
,
"id"
:
3
,
...
...
@@ -28,7 +45,7 @@
"w"
:
12
,
"h"
:
17
,
"x"
:
0
,
"y"
:
1
"y"
:
6
}
},
{
...
...
@@ -43,7 +60,7 @@
"w"
:
12
,
"h"
:
17
,
"x"
:
12
,
"y"
:
1
"y"
:
6
}
}
],
...
...
public/sass/pages/_explore.scss
View file @
fd06e517
.explore
{
flex
:
1
1
auto
;
.icon-margin-right
{
margin-right
:
0
.25em
;
}
&
-container
{
padding
:
$dashboard-padding
;
}
.icon-margin-left
{
margin-left
:
0
.25em
;
}
&
-wrapper
{
display
:
flex
;
.run-icon
{
transform
:
rotate
(
90deg
);
}
>
.explore-split
{
width
:
50%
;
}
}
.timepicker
{
display
:
flex
;
}
// Push split button a bit
.explore-first-button
{
margin-left
:
15px
;
.timepicker-rangestring
{
margin-left
:
0
.5em
;
}
.datasource-picker
{
.ds-picker
{
min-width
:
200px
;
max-width
:
200px
;
}
}
.explore-panel
{
margin-top
:
$panel-margin
;
.sidemenu-open
{
.explore-toolbar-header
{
padding
:
0
;
margin-left
:
0
;
}
.explore-panel__body
{
padding
:
$panel-padding
;
.explore-toolbar-header-title
{
.navbar-page-btn
{
padding-left
:
0
;
}
}
}
.explore-panel__header
{
padding
:
$panel-padding
;
padding-top
:
5px
;
padding-bottom
:
0
;
display
:
flex
;
cursor
:
pointer
;
margin-bottom
:
5px
;
transition
:
all
0
.1s
linear
;
.explore-toolbar
{
background
:
inherit
;
display
:
flex
;
flex-flow
:
row
wrap
;
justify-content
:
flex-start
;
height
:
auto
;
padding
:
0px
$dashboard-padding
;
border-bottom
:
1px
solid
#0000
;
transition-duration
:
0
.35s
;
transition-timing-function
:
ease-in-out
;
transition-property
:
box-shadow
,
border-bottom
;
}
.explore-toolbar-item
{
position
:
relative
;
align-self
:
center
;
}
.explore-toolbar.splitted
{
.explore-toolbar-item
{
flex
:
1
1
100%
;
}
.explore-panel__header-label
{
font-weight
:
500
;
margin-right
:
$panel-margin
;
font-size
:
$font-size-h6
;
box-shadow
:
$text-shadow-faint
;
.explore-toolbar-content-item
:first-child
{
padding-left
:
0
;
margin-right
:
auto
;
}
}
.explore-toolbar-item
:last-child
{
flex
:
auto
;
}
.explore-panel__header-buttons
{
margin-right
:
$panel-margin
;
font-size
:
$font-size-lg
;
line-height
:
$font-size-h6
;
.explore-toolbar-header
{
display
:
flex
;
flex
:
1
1
0
;
flex-flow
:
row
nowrap
;
font-size
:
18px
;
min-height
:
55px
;
line-height
:
55px
;
justify-content
:
space-between
;
margin-left
:
$panel-margin
*
3
;
}
.explore-toolbar-header
{
justify-content
:
space-between
;
align-items
:
center
;
}
.explore-toolbar-header-title
{
color
:
darken
(
$link-color
,
5%
);
.navbar-page-btn
{
padding-left
:
$dashboard-padding
;
}
// Make sure wrap buttons around on small screens
.navbar
{
flex-wrap
:
wrap
;
height
:
auto
;
.fa
{
font-size
:
100%
;
opacity
:
0
.75
;
margin-right
:
0
.5em
;
}
}
.navbar-page-btn
{
margin-right
:
1rem
;
.explore-toolbar-header-close
{
margin-left
:
auto
;
}
.explore-toolbar-content
{
display
:
flex
;
flex-flow
:
row
wrap
;
align-items
:
center
;
justify-content
:
space-between
;
}
.explore-toolbar-content-item
{
padding
:
10px
2px
;
}
.explore-toolbar-content-item
:first-child
{
padding-left
:
$dashboard-padding
;
margin-right
:
auto
;
}
// Explore icon in header
.fa
{
font-size
:
100%
;
opacity
:
0
.75
;
margin-right
:
0
.5em
;
@media
only
screen
and
(
max-width
:
1545px
)
{
.explore-toolbar.splitted
{
.timepicker-rangestring
{
display
:
none
;
}
}
}
// Toggle mode
.navbar-button.active
{
color
:
$btn-active-text-color
;
background-color
:
$btn-active-bg
;
@media
only
screen
and
(
max-width
:
1070px
)
{
.timepicker
{
.timepicker-rangestring
{
display
:
none
;
}
}
.
navbar-button--no-icon
{
line-height
:
18px
;
.
explore-toolbar-content
{
justify-content
:
flex-start
;
}
.result-options
{
margin
:
2
*
$panel-margin
0
;
.explore-toolbar.splitted
{
.explore-toolbar-content-item
{
padding
:
2px
0
;
margin
:
0
;
}
}
.time-series-disclaimer
{
width
:
300px
;
margin
:
$panel-margin
auto
;
padding
:
10px
0
;
border-radius
:
$border-radius
;
text-align
:
center
;
background-color
:
$panel-bg
;
.disclaimer-icon
{
color
:
$yellow
;
margin-right
:
$panel-margin
/
2
;
}
.explore-toolbar-content-item
{
padding
:
2px
2px
;
}
}
.show-all-time-series
{
cursor
:
pointer
;
color
:
$external-link-color
;
@media
only
screen
and
(
max-width
:
803px
)
{
.sidemenu-open
{
.explore-toolbar-header-title
{
.navbar-page-btn
{
padding-left
:
0
;
margin-left
:
0
;
}
}
}
.navbar
.elapsed-time
{
position
:
absolute
;
left
:
0
;
right
:
0
;
top
:
3
.5rem
;
text-align
:
center
;
font-size
:
0
.8rem
;
.explore-toolbar-header-title
{
.navbar-page-btn
{
padding-left
:
0
;
margin-left
:
$dashboard-padding
;
}
}
.
graph-legend
{
flex-wrap
:
wrap
;
.
btn-title
{
display
:
none
;
}
}
.explore-panel__loader
{
height
:
2px
;
position
:
relative
;
overflow
:
hidden
;
background
:
none
;
margin
:
$panel-margin
/
2
;
@media
only
screen
and
(
max-width
:
702px
)
{
.explore-toolbar-content-item
:first-child
{
padding-left
:
2px
;
margin-right
:
0
;
}
}
.explore-panel__loader--active
:after
{
content
:
' '
;
display
:
block
;
width
:
25%
;
top
:
0
;
top
:
-50%
;
height
:
250%
;
position
:
absolute
;
animation
:
loader
2s
cubic-bezier
(
0
.17
,
0
.67
,
0
.83
,
0
.67
)
500ms
;
animation-iteration-count
:
100
;
left
:
-25%
;
background
:
$blue
;
@media
only
screen
and
(
max-width
:
544px
)
{
.sidemenu-open
{
.explore-toolbar-header-title
{
.navbar-page-btn
{
padding-left
:
0
;
margin-left
:
$dashboard-padding
;
}
}
}
@keyframes
loader
{
from
{
left
:
-25%
;
opacity
:
.1
;
}
to
{
opacity
:
1
;
left
:
100%
;
.explore-toolbar-header-title
{
.navbar-page-btn
{
padding-left
:
0
;
margin-left
:
$dashboard-padding
;
}
}
}
.datasource-picker
{
min-width
:
200px
;
}
.explore
{
flex
:
1
1
auto
;
}
.timepicker
{
display
:
flex
;
.explore
+
.explore
{
border-left
:
1px
dotted
$table-border
;
}
&
-rangestring
{
margin-left
:
0
.5em
;
}
}
.explore-container
{
padding
:
$dashboard-padding
;
}
.explore-wrapper
{
display
:
flex
;
.run-icon
{
margin-left
:
0
.25em
;
transform
:
rotate
(
90deg
);
>
.explore-split
{
width
:
50%
;
}
}
.explore-panel
{
margin-top
:
$panel-margin
;
}
.explore-panel__body
{
padding
:
$panel-padding
;
}
.explore-panel__header
{
padding
:
$panel-padding
;
padding-top
:
5px
;
padding-bottom
:
0
;
display
:
flex
;
cursor
:
pointer
;
margin-bottom
:
5px
;
transition
:
all
0
.1s
linear
;
}
.relative
{
position
:
relative
;
.explore-panel__header-label
{
font-weight
:
500
;
margin-right
:
$panel-margin
;
font-size
:
$font-size-h6
;
box-shadow
:
$text-shadow-faint
;
}
.explore-panel__header-buttons
{
margin-right
:
$panel-margin
;
font-size
:
$font-size-lg
;
line-height
:
$font-size-h6
;
}
.result-options
{
margin
:
2
*
$panel-margin
0
;
}
.time-series-disclaimer
{
width
:
300px
;
margin
:
$panel-margin
auto
;
padding
:
10px
0
;
border-radius
:
$border-radius
;
text-align
:
center
;
background-color
:
$panel-bg
;
.disclaimer-icon
{
color
:
$yellow
;
margin-right
:
$panel-margin
/
2
;
}
.link
{
text-decoration
:
underline
;
.show-all-time-series
{
cursor
:
pointer
;
color
:
$external-link-color
;
}
}
.explore
+
.explore
{
border-left
:
1px
dotted
$table-border
;
.navbar
.elapsed-time
{
position
:
absolute
;
left
:
0
;
right
:
0
;
top
:
3
.5rem
;
text-align
:
center
;
font-size
:
0
.8rem
;
}
.graph-legend
{
flex-wrap
:
wrap
;
}
.explore-panel__loader
{
height
:
2px
;
position
:
relative
;
overflow
:
hidden
;
background
:
none
;
margin
:
$panel-margin
/
2
;
}
.explore-panel__loader--active
:after
{
content
:
' '
;
display
:
block
;
width
:
25%
;
top
:
0
;
top
:
-50%
;
height
:
250%
;
position
:
absolute
;
animation
:
loader
2s
cubic-bezier
(
0
.17
,
0
.67
,
0
.83
,
0
.67
)
500ms
;
animation-iteration-count
:
100
;
left
:
-25%
;
background
:
$blue
;
}
@keyframes
loader
{
from
{
left
:
-25%
;
opacity
:
0
.1
;
}
to
{
left
:
100%
;
opacity
:
1
;
}
}
.query-row
{
...
...
scripts/build/publish.go
deleted
100644 → 0
View file @
d947748d
package
main
import
(
"bytes"
"encoding/json"
"flag"
"fmt"
"io/ioutil"
"log"
"net/http"
"os"
"path/filepath"
"regexp"
"strings"
"time"
)
var
apiURL
=
flag
.
String
(
"apiUrl"
,
"https://grafana.com/api"
,
"api url"
)
var
apiKey
=
flag
.
String
(
"apiKey"
,
""
,
"api key"
)
var
version
=
""
var
versionRe
=
regexp
.
MustCompile
(
`grafana-(.*)(\.|_)(arm64|armhfp|aarch64|armv7|darwin|linux|windows|x86_64)`
)
var
debVersionRe
=
regexp
.
MustCompile
(
`grafana_(.*)_(arm64|armv7|armhf|amd64)\.deb`
)
var
builds
=
[]
build
{}
var
architectureMapping
=
map
[
string
]
string
{
"armv7"
:
"armv7"
,
"armhfp"
:
"armv7"
,
"armhf"
:
"armv7"
,
"arm64"
:
"arm64"
,
"aarch64"
:
"arm64"
,
"amd64"
:
"amd64"
,
"x86_64"
:
"amd64"
,
}
func
main
()
{
flag
.
Parse
()
if
*
apiKey
==
""
{
log
.
Fatalf
(
"Require apiKey command line parameters"
)
}
err
:=
filepath
.
Walk
(
"dist"
,
packageWalker
)
if
err
!=
nil
{
log
.
Fatalf
(
"Cannot find any packages to publish, %v"
,
err
)
}
if
version
==
""
{
log
.
Fatalf
(
"No version found"
)
}
if
len
(
builds
)
==
0
{
log
.
Fatalf
(
"No builds found"
)
}
nightly
:=
release
{
Version
:
version
,
ReleaseDate
:
time
.
Now
(),
Stable
:
false
,
Nightly
:
true
,
Beta
:
false
,
WhatsNewURL
:
""
,
ReleaseNotesURL
:
""
,
Builds
:
builds
,
}
postRequest
(
"/grafana/versions"
,
nightly
,
fmt
.
Sprintf
(
"Create Release %s"
,
nightly
.
Version
))
postRequest
(
"/grafana/versions/"
+
nightly
.
Version
,
nightly
,
fmt
.
Sprintf
(
"Update Release %s"
,
nightly
.
Version
))
for
_
,
b
:=
range
nightly
.
Builds
{
postRequest
(
fmt
.
Sprintf
(
"/grafana/versions/%s/packages"
,
nightly
.
Version
),
b
,
fmt
.
Sprintf
(
"Create Build %s %s"
,
b
.
Os
,
b
.
Arch
))
postRequest
(
fmt
.
Sprintf
(
"/grafana/versions/%s/packages/%s/%s"
,
nightly
.
Version
,
b
.
Arch
,
b
.
Os
),
b
,
fmt
.
Sprintf
(
"Update Build %s %s"
,
b
.
Os
,
b
.
Arch
))
}
}
func
mapPackage
(
path
string
,
name
string
,
shaBytes
[]
byte
)
(
build
,
error
)
{
log
.
Printf
(
"Finding package file %s"
,
name
)
result
:=
versionRe
.
FindSubmatch
([]
byte
(
name
))
debResult
:=
debVersionRe
.
FindSubmatch
([]
byte
(
name
))
if
len
(
result
)
>
0
{
version
=
string
(
result
[
1
])
log
.
Printf
(
"Version detected: %v"
,
version
)
}
else
if
len
(
debResult
)
>
0
{
version
=
string
(
debResult
[
1
])
}
else
{
return
build
{},
fmt
.
Errorf
(
"Unable to figure out version from '%v'"
,
name
)
}
os
:=
""
if
strings
.
Contains
(
name
,
"linux"
)
{
os
=
"linux"
}
if
strings
.
HasSuffix
(
name
,
"windows-amd64.zip"
)
{
os
=
"win"
}
if
strings
.
HasSuffix
(
name
,
"darwin-amd64.tar.gz"
)
{
os
=
"darwin"
}
if
strings
.
HasSuffix
(
name
,
".rpm"
)
{
os
=
"rhel"
}
if
strings
.
HasSuffix
(
name
,
".deb"
)
{
os
=
"deb"
}
if
os
==
""
{
return
build
{},
fmt
.
Errorf
(
"Unable to figure out os from '%v'"
,
name
)
}
arch
:=
""
for
archListed
,
archReal
:=
range
architectureMapping
{
if
strings
.
Contains
(
name
,
archListed
)
{
arch
=
archReal
break
}
}
if
arch
==
""
{
return
build
{},
fmt
.
Errorf
(
"Unable to figure out arch from '%v'"
,
name
)
}
return
build
{
Os
:
os
,
Arch
:
arch
,
URL
:
"https://s3-us-west-2.amazonaws.com/grafana-releases/master/"
+
name
,
Sha256
:
string
(
shaBytes
),
},
nil
}
func
packageWalker
(
path
string
,
f
os
.
FileInfo
,
err
error
)
error
{
if
err
!=
nil
{
log
.
Printf
(
"error: %v"
,
err
)
}
if
f
.
Name
()
==
"dist"
||
strings
.
Contains
(
f
.
Name
(),
"sha256"
)
||
strings
.
Contains
(
f
.
Name
(),
"latest"
)
{
return
nil
}
shaBytes
,
err
:=
ioutil
.
ReadFile
(
path
+
".sha256"
)
if
err
!=
nil
{
log
.
Fatalf
(
"Failed to read sha256 file %v"
,
err
)
}
build
,
err
:=
mapPackage
(
path
,
f
.
Name
(),
shaBytes
)
if
err
!=
nil
{
log
.
Printf
(
"Could not map metadata from package: %v"
,
err
)
return
nil
}
builds
=
append
(
builds
,
build
)
return
nil
}
func
postRequest
(
url
string
,
obj
interface
{},
desc
string
)
{
jsonBytes
,
_
:=
json
.
Marshal
(
obj
)
req
,
_
:=
http
.
NewRequest
(
http
.
MethodPost
,
(
*
apiURL
)
+
url
,
bytes
.
NewReader
(
jsonBytes
))
req
.
Header
.
Add
(
"Authorization"
,
"Bearer "
+
(
*
apiKey
))
req
.
Header
.
Add
(
"Content-Type"
,
"application/json"
)
res
,
err
:=
http
.
DefaultClient
.
Do
(
req
)
if
err
!=
nil
{
log
.
Fatalf
(
"error: %v"
,
err
)
}
if
res
.
StatusCode
==
http
.
StatusOK
{
log
.
Printf
(
"Action: %s
\t
OK"
,
desc
)
}
else
{
if
res
.
Body
!=
nil
{
defer
res
.
Body
.
Close
()
body
,
_
:=
ioutil
.
ReadAll
(
res
.
Body
)
if
strings
.
Contains
(
string
(
body
),
"already exists"
)
||
strings
.
Contains
(
string
(
body
),
"Nothing to update"
)
{
log
.
Printf
(
"Action: %s
\t
Already exists"
,
desc
)
}
else
{
log
.
Printf
(
"Action: %s
\t
Failed - Status: %v"
,
desc
,
res
.
Status
)
log
.
Printf
(
"Resp: %s"
,
body
)
log
.
Fatalf
(
"Quitting"
)
}
}
}
}
type
release
struct
{
Version
string
`json:"version"`
ReleaseDate
time
.
Time
`json:"releaseDate"`
Stable
bool
`json:"stable"`
Beta
bool
`json:"beta"`
Nightly
bool
`json:"nightly"`
WhatsNewURL
string
`json:"whatsNewUrl"`
ReleaseNotesURL
string
`json:"releaseNotesUrl"`
Builds
[]
build
`json:"-"`
}
type
build
struct
{
Os
string
`json:"os"`
URL
string
`json:"url"`
Sha256
string
`json:"sha256"`
Arch
string
`json:"arch"`
}
scripts/build/release_publisher/publisher.go
View file @
fd06e517
...
...
@@ -128,12 +128,22 @@ var completeBuildArtifactConfigurations = []buildArtifact{
urlPostfix
:
"_armhf.deb"
,
},
{
os
:
"deb"
,
arch
:
"armv6"
,
urlPostfix
:
"_armel.deb"
,
},
{
os
:
"rhel"
,
arch
:
"armv7"
,
urlPostfix
:
".armhfp.rpm"
,
},
{
os
:
"linux"
,
arch
:
"armv6"
,
urlPostfix
:
".linux-armv6.tar.gz"
,
},
{
os
:
"linux"
,
arch
:
"armv7"
,
urlPostfix
:
".linux-armv7.tar.gz"
,
},
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment