+
diff --git a/assets/js/app.js b/assets/js/app.js
index d6da99a97..a7147beea 100644
--- a/assets/js/app.js
+++ b/assets/js/app.js
@@ -181,8 +181,14 @@ Vue.component('version', {
data: function () {
return {
state: store.state,
+ notesShown: false,
};
},
+ mounted: function () {
+ $(this.$refs.notes)
+ .on('show.bs.collapse', function () { this.notesShown = true; }.bind(this))
+ .on('hide.bs.collapse', function () { this.notesShown = false; }.bind(this));
+ },
watch: {
"state.availableVersion": function () {
if (this.installed != "<<.Version>>" && // go template parsed?
diff --git a/go.mod b/go.mod
index 80fa724e3..468e85dff 100644
--- a/go.mod
+++ b/go.mod
@@ -11,11 +11,13 @@ require (
github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible
github.com/godbus/dbus/v5 v5.0.3
github.com/golang/mock v1.4.3
+ github.com/google/go-github/v32 v32.1.0
github.com/gorilla/handlers v1.4.2
github.com/gorilla/mux v1.7.4
github.com/gorilla/websocket v1.4.2
github.com/gregdel/pushover v0.0.0-20200416074932-c8ad547caed4
github.com/grid-x/modbus v0.0.0-20200704184817-73c05928caa1
+ github.com/hashicorp/go-version v1.2.1
github.com/influxdata/influxdb-client-go v1.4.0
github.com/itchyny/gojq v0.11.0
github.com/joeshaw/carwings v0.0.0-20191118152321-61b46581307a
@@ -32,6 +34,7 @@ require (
github.com/spf13/viper v1.7.0
github.com/tcnksm/go-latest v0.0.0-20170313132115-e3007ae9052e
github.com/volkszaehler/mbmd v0.0.0-20200717102329-c4d965bd1eac
+ github.com/yuin/goldmark v1.1.32
golang.org/x/net v0.0.0-20200707034311-ab3426394381
golang.org/x/tools v0.0.0-20200717024301-6ddee64345a6
gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c
diff --git a/go.sum b/go.sum
index e7d85aaf5..e6dbb8dae 100644
--- a/go.sum
+++ b/go.sum
@@ -108,6 +108,8 @@ github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5a
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-github v17.0.0+incompatible h1:N0LgJ1j65A7kfXrZnUDaYCs/Sf4rEjNlfyDHW9dolSY=
github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ=
+github.com/google/go-github/v32 v32.1.0 h1:GWkQOdXqviCPx7Q7Fj+KyPoGm4SwHRh8rheoPhd27II=
+github.com/google/go-github/v32 v32.1.0/go.mod h1:rIEpZD9CTDQwDK9GDrtMTycQNA4JU3qBsCizh3q2WCI=
github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk=
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
@@ -349,6 +351,7 @@ github.com/volkszaehler/mbmd v0.0.0-20200717102329-c4d965bd1eac/go.mod h1:sldLyJ
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
+github.com/yuin/goldmark v1.1.32 h1:5tjfNdR2ki3yYQ842+eX2sQHeiwpKJ0RnHO4IYOc4V8=
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
diff --git a/server/assets.go b/server/assets.go
index 376e773d2..8584865c1 100644
--- a/server/assets.go
+++ b/server/assets.go
@@ -3561,144 +3561,147 @@ oJE6K0E084u3ea7ne0X73qsc2P2KOB+ngKecxITsMAgTVJfqMwAA//+21HeD5gEAAA==
"/index.html": {
name: "index.html",
local: "assets/index.html",
- size: 19915,
+ size: 20467,
modtime: 1566640112,
compressed: `
-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
+H4sIAAAAAAAC/9w823LbRpbv+opjeGJKE4OUZDvx0CBTie2dZCf2uiLHqdqtfWgAh2RHjW5sd4OS7LBq
+/2H3cR/zGfOWP5kv2epuNG4EKEqWM7vjB4sETp8+90tfGN1LRaKvcoSVztj8IDJ/gBG+nAXIA/MASTo/
+AIgy1ASSFZEK9Swo9CJ8GtQvOMlwFqwpXuRC6gASwTVyPQsuaKpXsxTXNMHQfnkIlFNNCQtVQhjOTh6C
+WknKz0MtwgXVMy62EKeoEklzTQVv4H75Dp6viFwiPBdcS8EYyq2hpNArIRujCE/pchsszxmGmYgpw/AC
+45DkeZiQnMQMG4OvUO03VGmiCxXGRIZKX7VwxIwk58H8wKBhlJ+DROaxaFEkq5Amhk9F36OaBSdPjy9P
+nh4HsJK4mAU0EZMu7DjnJUc1PofD6HYW0IwscWKAPNJHp5ePTpsoF2RtRoT2xc3xnXxxefJFHz77og9f
+RjhdoNLNQYpqHF9gXL3bGqPOS+E0BpEFkTTMKeeYhprEY7VeGnEzIWfB/SdxTNInXUxqJaROCg1dbCXd
+Y5psW2GmjOBpQowdhm8pw+dmkoZq75/GT77805fXjEwEX9BlY5iZOJbiQqF078aXGdtColeYYZh0p1zY
+f6U9aaoZznGdJNHEfbaP74UhPD87gzCs5eB4TpSaxEJopSXJxxnl40SpoBSSMVy1Qmwqoh62EFyTC1Qi
+w10D/fzf+Fk8Fc6lQclkFvysJj//R4HyKnw0fjw+GStGM4v0ZxXMo4kD7RuVizxHuRdozWZc8JRhzyBP
+69eXVKgBOol5t2PsuwL/+Wxg7LrAvUhdFxhKUeheziy8kbAZCTD5I0hco1QITJCU8iUQTjNravDHiYUZ
+51IsJSoXkNxrTOGDfQk1fJhSiYn5NPVIn1mYjUMTaz5OiI3D1WCRk4TqqymcbIEuqFS6AoyFTFGGWuQh
+w4UOJUlpoaYwPpWYPWsDxUJrkQ3CuTkSkWKF3VhjaKLRFJ5+OX7ymUdo/WUK9/HpI3ya+KcXQqbhhST5
+FGKJ5Dw0D2rc0aQUcDRxCTCKRXo1PziIUroGmtpw7ZyCkzUkjCg1CzhZx0SC+xPiZU54GrKlf8DocqUh
+XroPgdNeRNqjw1gSnvqItNI6V9PJZEn1qojHicgmNn1NjIcH84j6wRovdZhLmhF5BQuiYEFChmQBmQxP
+jfHQMiiQctq40FrwztxaLJcmh5Zh3sEEkBJNynezIBGMkVyhf2zyrwlDDsVrsv6a6VdEnhd54K1LUmJi
+nsnQ1VwtQAfiBIbpLFgQZiawTxmJTUh5a6c3oqRLa6ql/Iwv5GSAEZcrjOvkhJeMTxxX5TejznKoZ8yr
+q2bU6LuH6oqABpJyLCfr6jVA5Fw5tPGzBgypxszM5l7kcXgSgBazYBLMvycp8mjSGNhAZ6JMFEnClwh/
+oOnlQ/iDxTCdwfh7ys/VfF7Gn1vOb76rSRQZ5PN5MI8iO8H4rc0o8910IU8/dv4yQc7/Yv8W0ip8aFZy
+Hco9XGlClSpMaXdW5KaArfzEGExK1952yo/RhJO1C8QmRppoSLnShDFjvVE0fueezufOeEogE3yNNZZf
+HYIMlSJLU80RpdU8mnQeHNTyM+V1LXz77aCk6cBnEOe5JhxMLkONWc6IxjYV1VOLu8cDTBZfzAJL7Zab
+SHEBefjIxLELIjktK7sebwpPThtO8BoLhFIusEa5+O2vy5jIexXAd06CFKWewocPlUA3m3EF864aZ0BM
+jY1jsiaUmTK9RN6Ej2JPT34ZPtozkklkSBSGXGhUAaxDujAljZmrfPXavql5s1bozOx+0ArJJm20AAF+
+cDjAom+9qcN5GcGTFa6l4KEJkY4MO+hsJS64C+r7jU8NPKxDZAq7wxqmbqPjfEh4HXbXYUx5OnVcj3Z7
+Vyk2NdFkORl93q+3awX3QlxwU+Fcw+dNGHRJsJ3tvAEzoRAWTBAdSpuwwdYEpguRS8pNHTOF8DS/bCeq
+52bcnpbWigtNkm1Ks1hXNE2RzwItCwzmDzTNUD1rJrTtpNYfswa92JUl7WzXcQGrY94y+h5fh3W40hnr
+95X+MGo/NCrbPaIYZrFp84ZjGNeEcpSQXYak0AKsOSXINVbhbHXiwVOqckauwseQaxMgnJfZzimYf/hg
+P2w20WR1Ug7N/UiGJO2dwweMIq7Q+M8GU17VfS0PMvnKD7WfK0HTbOlBbXtAs6UHNB9ruIUkGbZB7aMK
+2n3zSvCVoLW1MjY05yz5pNkyXLCCpsEnocIbco8t+FLbJcJa09YviBYZTUq/8J6ZC0Vd80JiJVih8RlY
+N31sOgewbjyF4/ET89WTYKqWN+VAoLqqXNqZGdbhQshZYAsMagAxU5VIzDf3LoCpoXnkB9M0HH1uXoyN
+BKfneOXgzFcvg9ZELWHsndsrFEN+YXGX8SdFRq5mwcnx8fFxxYJ9Y4x5RVP08WYrblg0oemJUDYqcC0F
+rywmkxZPpXDDrV1jvDeDkakZRludS2pqWekbF7xMGCkbUi0p4UvjRiasw0sphTTdmZnwpvPPBucvK5k9
+CPjJQW6TkBHGmjO6BcBg/u3bt29MOVM/M1HAgleDd+WhjIWnkMWhCVl1ZkmpymhDr9sZqJEdbpRNOg1S
+f/pwZuBydMlbaYGGuY8J7xmhfI/o7k1TUV0HG5N2yuzjlZ+UHQSmh6MoGj+vvs7noyPbGVKNDf46cbCb
+Ma/CJ03BtnNgq9xtporVickuT0w7ctpe4AjmP1HGzkWWIYcYKbgmPe/HY1NOrm1DH5f9fDwHqjSkFLmG
+94WEBcNLGjPkYHpIpbFAWfAlrAWHlwzPtRQLspLvsVgiHw/O5aaBlwoUxZUGUqiHQJiCi99+lQgvkHJo
+EsFFsgJOk5WG81LIppIfw49ZC+590arpGrDIQVGeGlZgIdgSeYoczpKVpFrbcvkCTUk5bde8grVJbr21
+i5bzlyW3gLYwaHWVKiUaKWRUw2titBAlInUrqOMrkrFoYr+P4QXFDmqAM014SmR63sTYxJBSpZto4Jxw
+DilZ/PZXaaX5TkhGlmj1hxwOI7I1CezVwMZMxJOMKI1y0p46mPvC2eT8o3GPgFoSgRQl/EQYi8WlpdHx
+k9idFqm8QPZAo+Dlux/hX3/7dcVQKih4CrjWbAwXSDVKlP4dFKZyKifKUN90mteo3xOukhUrlELVQmcc
+vFLid94GzkzcuKAytdy2xhtb2FJCilnLrpE3eYPDBunlZEemyY0LY8TXM2GIUtZh84Kf6w4LRne5oFyr
+LiNZPabkpsdKW3RXmj1sqbUi2jhC2sK7k40zTaS2saXp5A6JBI4FoFQaGTMSa/E8bfgJhAl0Pa7t5RPB
+2j1dJ2zNX1FOM8IQvkGqcoqs7ZPW4RokTrcxHDh6olxilXtd31tIOgUmEsJWQunpl8dfHsN9+DqVqEyL
+aFD/+N0BNRpbEzaFk2MF9+EHXCLzD9mBM+vpQWh3c6aA6yJ878znwOTDKYzHY7gPL1AT2qG+60oVEkZS
+vAmS72t4BYfCLuQTdnTgnbsm78KZyR5Yq2BxYFzNRGfb60zhW5EZY/SMAywlTVuMw/0mWwe1nRs6Siy1
+Id6HgkLZsFkqDwBKwit64b5/1JrZA7YkBvcH5RFNconzbUvctpp3FBmc5cTFjaaJ3TOmCG+kiBmaxGJC
+v9LwooCCKyDFol402m9t8s9Uf1vEJogDSok0WbUT+J212EaPzRos8sja5VBPe5CGXHCENMzS0BQi4JYG
+7J8sDR9Dpt1fwuiS29VaFSJP61aiUTTZztkuJVhT+OWXwFhU0Gyi+6vT9qRP/aS+JswKpmmjeTHcpta0
+VW8pWVaJHqZfwtvigS1hdEq/wZGe0HtNSofEHDORnFcCbi+0DMvkU7Bfua/vlQ+rJw9pemS6ZqfO2s/d
+FpFvotNZYJvkcvoKLIBpvvbLSiaIvEK70DK18mkqNJpUg6r2+Ra2X7La9YGu7Xfl+4UX7yNjco/aS8c1
+3dvKyeLwdBv6jbhACXM4rpT1Db4vlrB7149IKS66K6EDRuHnbfY8LylXOVJleoZ9ZirygXlWpx7lhw+L
+TB92GDvabHzX3JwjKzSmxvMXmf6R075hP7Xa52jiJqot8iZaydc7dVK2Dm1ZOPatCFTBqwWU8u2HUVNW
+o6mfx1IfHT8c1Wx2Xs5nxxsny+vFWA65mRDrQTcQYRVrKGeUYzve9Ik0JlqjvNot128sEMUdJhZUibYr
+4JaVeyGW03oxw6hhoX0wcy/sPQ23OfZmYu+M3Cn7W8WsKubtk7R7kuBwnnjcyF5G02UqfTKcv5ub8auT
+Es5nvG4+r2o7m9Sbm/Q+qexO7Nt5sElkTVQtoGsS3RbgXvTY+Q0lwdDCkSUrjxsbLsPLSAaj9apWpZmJ
+tGpLLsKTxsKteeN9z3wus2W+NhCCT4s8JRrTWeC2nV4ZkHk0yVqlbcP+d5FUGs+KqLcW2Zl43tm4Ekk/
+lUoknkhdDYUpwzUy5d8okXxvH/STbmeLJkokA4TvqID3qc8yu0h35VT1uLmpU6vtutLMi6kdsUqL/WI0
+bYruoX9+cjqa3mu+2dSWZBV/vaqn5bEsvyOyn+p3FIuG3OuVbhV+SxXvQ3JX5XuptfRGQ/1px+uuU1+f
+/31K39tdre8n/t/N364X/r7ybaSXbR/8nbPMLltqdWzb6WZXD3c9747V2P2XpWFd50drXNGE4VCaKl/f
+JFk+HkiWA03xVsH2SqSFagfbplvEmodLKYo8VNnv5R034QwePIB+D9ri1K4JUWRtZhuO1svrJ/S3ofDc
+U//0+t/fpQC6oxnvqjC+o45+qJ35HqnSBV9e30a4dchbdBHtgR/ZAw/x8Wdk7uDpfmykLznK5dVtGKmH
+/rTaxctHMPOCFCh3sHK2ElK/KBeyW8T5hzVjVb05xGAL2Ra3DYQfyWyr1VYiGeT+B1T6PVJ9KwG8VNpe
+EbgzATQQ3nn7a/LFkGNXsRrqqO1O5dkDrCuqEdSKpOKijl+RPUfRwGDHikLb9Q+/QpFSRWKGKfj7EPYC
+wgWaMjOMBUurIwjufakom0fdSqWZZe/5tnoKkmi6RpdjZyOxWIwe2usW03vlhL6HiCjPCy9ASVIqAlgT
+VuAsEItFmYkSRpPzZiI+tCiPgvmZFvnd08vFxWgPArkrKfsJNDgMgWIhpL57EjPK8/Vo49WYr68n1w4Z
+JthhPAqaB++qVTa3vAZpqLLSFF9RDp/Dm3etmrU9qEz/KiuHB24ftMg6A+9YNDeVyy6h3EQiN5TF60L2
+S+F2OwMi+X8TZXwNe0vVl7s3plT1OzeukP0X+QIXpGC6MhD7fBbYP+XZR5q6pduu8ZgSeeaQtiPVgwc0
+ndnF72FDcrOV9lTOtm1SZ+K5I/vIZCX7abP57KNVX/Zb1y2vusTr208lkrdlB/pP5YGroHk6rjHQ386r
+DrKu0B1VPX2cXz5rXG07OT7+7Bk0DqCffJFf9pQAzet+AUhhD8eWz+yjsk2oy4iuw1f5ftS6Oqi0pDmm
+oyk0sjvly4cD8P6q4a4B8bLeLfFQgnNMNKZtMLuGM5rCvcMOGPzySwf/UWOkrVUUJoKnbpKbjN/ULZ7T
+zQd7i30KI6MMk8S8wv1Q+AoCW0YHMIWtmb6CoDpRYwCCJWqJnOvgaLPZ1fXuoVNkCtvlYXk/fg5/+j+j
+4XsdaT14MKT0QdF32Pt81NJD9Xyz+ezjZPkPJLLDjmyi4yP4Co5hSJh30n+707c3OM5rbxAO3c7ov9HR
+uSN4g4sa8xflykSKEnyIDh/640yhPbBYnk1qHXqyh27sPYGDgc2ex92zHvvckLvZ2Ze+3Y5eclZPBqff
+OjGyo/88tTsjrQt9+n15dmraOWves6M7eBjib//zX1vXmXYhsWcVHmQpUautk+u34uPNO6/kG7NRnR74
+uzPh99Nvq5D2pv0nYWfLRvc/JVQVm/5R+3CQvXBTr/WNPrd3a4a3Yoe88xr/3PbQas6BvYZ89z7lAIWr
+HXcM+lz2JnYCzSOP060rhzvspObVregMm8qtjeXabehdfL1ZEYV8P5ZaqsvNQLXZ5HdIzCvKx3Cmpchu
+QVBG+fNCSuR6s/n6Lokilx9BFLnck6hPbdx252PVccztizqPYHU66Od7+Lr554uCzln0Fnl9D3bx3K+1
+LWWVa4XI2LR77H4/hTXaz7/95393tj4HSd+btr+QnLyn+rdf9e3pe07cT8dsNud2E+B68rqmsfvwR//5
+54UQGmXj0tBjdzErLzed87i5PVs+rH+75voitncjuEewrSt6Q7snzR+TgCiiC+AI/hGMn4sso3o+P7SX
+29zno/I3OLq3DHdXFnZS2T2aNEjXg0TkV8/g9Pj0eHie7SbCCb/uHszLRcHtTw6B+2EL+wsmh0flD/tI
+1IXk8G8l8snkul8+8RscFQ/lPYKg8yMmQd1s+evZDaCz8lELjmbLBsh32bL91l5sbgLYBy0Y87wBYUie
+z/1Bx83DJpNWhfbBvz87ANj0tV7VT1Ll+fhn9VUUjd+Spf3BlgbsxP10UTRxP/H3vwEAAP//3ZGSj/NP
+AAA=
`,
},
"/js/app.js": {
name: "app.js",
local: "assets/js/app.js",
- size: 8796,
+ size: 9041,
modtime: 1566640112,
compressed: `
-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
-l6X/BQAA//9E4YQ5XCIAAA==
+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
+AAAA//9Hvxx7USMAAA==
`,
},
diff --git a/server/socket.go b/server/socket.go
index be4e377af..b384854ab 100644
--- a/server/socket.go
+++ b/server/socket.go
@@ -1,6 +1,7 @@
package server
import (
+ "encoding/json"
"fmt"
"net/http"
"strings"
@@ -92,12 +93,13 @@ func encode(v interface{}) (string, error) {
case time.Duration:
// must be before stringer to convert to seconds instead of string
s = fmt.Sprintf("%d", int64(val.Seconds()))
- case fmt.Stringer, string:
- s = fmt.Sprintf("\"%s\"", val)
case float64:
s = fmt.Sprintf("%.3f", val)
default:
- s = fmt.Sprintf("%v", val)
+ // s = fmt.Sprintf("%v", val)
+ if b, err := json.Marshal(v); err == nil {
+ s = string(b)
+ }
}
return s, nil
}
diff --git a/server/updater/updater.go b/server/updater/updater.go
index e53d8afad..172e4d255 100644
--- a/server/updater/updater.go
+++ b/server/updater/updater.go
@@ -1,11 +1,20 @@
package updater
import (
+ "bytes"
+ "context"
+ "fmt"
+ "strings"
"time"
"github.com/andig/evcc/server"
"github.com/andig/evcc/util"
+ "github.com/google/go-github/v32/github"
+ "github.com/hashicorp/go-version"
latest "github.com/tcnksm/go-latest"
+ "github.com/yuin/goldmark"
+ "github.com/yuin/goldmark/extension"
+ "github.com/yuin/goldmark/renderer/html"
)
var instance *updater
@@ -15,6 +24,17 @@ type updater struct {
cache chan<- util.Param
}
+func tag2semver(tag string) string {
+ if strings.Count(tag, ".") < 2 {
+ tag += ".0"
+ }
+ return tag
+}
+
+func semver2tag(ver string) string {
+ return strings.TrimSuffix(ver, ".0")
+}
+
// Run regularly checks version
func Run(log *util.Logger, cache chan<- util.Param) {
instance = &updater{
@@ -31,19 +51,85 @@ func Run(log *util.Logger, cache chan<- util.Param) {
// checkVersion validates if updates are available
func (u *updater) checkVersion() {
githubTag := &latest.GithubTag{
- Owner: "andig",
- Repository: "evcc",
+ Owner: server.Owner,
+ Repository: server.Repository,
}
- if res, err := latest.Check(githubTag, server.Version); err == nil {
+ installed := tag2semver(server.Version)
+ if res, err := latest.Check(githubTag, installed); err == nil {
+ tag := semver2tag(res.Current)
if res.Outdated {
- u.log.INFO.Printf("new version available - please upgrade to %s", res.Current)
+ u.log.INFO.Printf("new version available - please upgrade to %s", tag)
}
+
u.cache <- util.Param{
Key: "availableVersion",
- Val: res.Current,
+ Val: tag,
}
+
+ u.fetchReleaseNotes(res.Current)
} else {
u.log.ERROR.Println("version check failed:", err)
}
}
+
+// fetchReleaseNotes retrieves release notes up to semver and sends to client
+func (u *updater) fetchReleaseNotes(to string) {
+ ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
+ defer cancel()
+
+ if notes, err := releaseNotes(ctx, tag2semver(server.Version), to); err == nil {
+ u.cache <- util.Param{
+ Key: "releaseNotes",
+ Val: notes,
+ }
+ } else {
+ u.log.WARN.Printf("couldn't download release notes: %v", err)
+ }
+}
+
+// releaseNotes returns github release notes for the (from,to] semver interval
+func releaseNotes(ctx context.Context, from, to string) (rendered string, err error) {
+ var fromVersion, toVersion *version.Version
+ if fromVersion, err = version.NewVersion(from); err != nil {
+ return
+ }
+ if toVersion, err = version.NewVersion(to); err != nil {
+ return
+ }
+
+ client := github.NewClient(nil)
+ releases, _, err := client.Repositories.ListReleases(ctx, server.Owner, server.Repository, nil)
+ if err != nil {
+ return
+ }
+
+ notes := bytes.NewBuffer([]byte{})
+ gm := goldmark.New(
+ goldmark.WithExtensions(extension.GFM),
+ goldmark.WithRendererOptions(html.WithHardWraps()),
+ )
+
+ for _, rel := range releases {
+ tag := *rel.TagName
+
+ var ver *version.Version
+ if ver, err = version.NewVersion(tag2semver(tag)); err != nil {
+ return
+ }
+
+ if ver.GreaterThan(fromVersion) && ver.LessThanOrEqual(toVersion) {
+ body := strings.TrimSpace(rel.GetBody())
+ if body == "" {
+ continue
+ }
+
+ notes.WriteString(fmt.Sprintf("
%s
\n", tag))
+ if err = gm.Convert([]byte(body), notes); err != nil {
+ return
+ }
+ }
+ }
+
+ return notes.String(), nil
+}
diff --git a/server/version.go b/server/version.go
index 45605ebff..b8617d805 100644
--- a/server/version.go
+++ b/server/version.go
@@ -1,8 +1,15 @@
package server
var (
+ // Repository name
+ Repository = "evcc"
+
+ // Owner of repository
+ Owner = "andig"
+
// Version of executable
Version = "0.0.1-alpha"
+
// Commit of executable
Commit = "HEAD"
)