diff --git a/.betterer.results b/.betterer.results index 1dddf6342c4ef..f5f1665442b18 100644 --- a/.betterer.results +++ b/.betterer.results @@ -1069,21 +1069,19 @@ exports[`better eslint`] = { [0, 0, 0, "Unexpected any. Specify a different type.", "0"] ], "packages/grafana-runtime/src/utils/DataSourceWithBackend.ts:5381": [ - [0, 0, 0, "Do not use any type assertions.", "0"], + [0, 0, 0, "Unexpected any. Specify a different type.", "0"], [0, 0, 0, "Unexpected any. Specify a different type.", "1"], - [0, 0, 0, "Unexpected any. Specify a different type.", "2"], - [0, 0, 0, "Unexpected any. Specify a different type.", "3"], - [0, 0, 0, "Do not use any type assertions.", "4"], - [0, 0, 0, "Do not use any type assertions.", "5"], + [0, 0, 0, "Do not use any type assertions.", "2"], + [0, 0, 0, "Do not use any type assertions.", "3"], + [0, 0, 0, "Unexpected any. Specify a different type.", "4"], + [0, 0, 0, "Unexpected any. Specify a different type.", "5"], [0, 0, 0, "Unexpected any. Specify a different type.", "6"], [0, 0, 0, "Unexpected any. Specify a different type.", "7"], [0, 0, 0, "Unexpected any. Specify a different type.", "8"], - [0, 0, 0, "Unexpected any. Specify a different type.", "9"], - [0, 0, 0, "Unexpected any. Specify a different type.", "10"], - [0, 0, 0, "Do not use any type assertions.", "11"], - [0, 0, 0, "Do not use any type assertions.", "12"], - [0, 0, 0, "Unexpected any. Specify a different type.", "13"], - [0, 0, 0, "Do not use any type assertions.", "14"] + [0, 0, 0, "Do not use any type assertions.", "9"], + [0, 0, 0, "Do not use any type assertions.", "10"], + [0, 0, 0, "Unexpected any. Specify a different type.", "11"], + [0, 0, 0, "Do not use any type assertions.", "12"] ], "packages/grafana-runtime/src/utils/analytics.ts:5381": [ [0, 0, 0, "Unexpected any. Specify a different type.", "0"] diff --git a/.bingo/.gitignore b/.bingo/.gitignore index 9efccf683cd81..4f2055b6e4cf5 100644 --- a/.bingo/.gitignore +++ b/.bingo/.gitignore @@ -5,7 +5,6 @@ # But not these files: !.gitignore !*.mod -!*.sum !README.md !Variables.mk !variables.env diff --git a/.bingo/Variables.mk b/.bingo/Variables.mk index 7181d61fe20f6..eaab3864ca8b6 100644 --- a/.bingo/Variables.mk +++ b/.bingo/Variables.mk @@ -1,4 +1,4 @@ -# Auto generated binary variables helper managed by https://github.com/bwplotka/bingo v0.6. DO NOT EDIT. +# Auto generated binary variables helper managed by https://github.com/bwplotka/bingo v0.8. DO NOT EDIT. # All tools are designed to be build inside $GOBIN. BINGO_DIR := $(dir $(lastword $(MAKEFILE_LIST))) GOPATH ?= $(shell go env GOPATH) @@ -29,11 +29,17 @@ $(DRONE): $(BINGO_DIR)/drone.mod @echo "(re)installing $(GOBIN)/drone-v1.5.0" @cd $(BINGO_DIR) && $(GO) build -mod=mod -modfile=drone.mod -o=$(GOBIN)/drone-v1.5.0 "github.com/drone/drone-cli/drone" -GOLANGCI_LINT := $(GOBIN)/golangci-lint-v1.49.0 +GOLANGCI_LINT := $(GOBIN)/golangci-lint-v1.51.2 $(GOLANGCI_LINT): $(BINGO_DIR)/golangci-lint.mod @# Install binary/ries using Go 1.14+ build command. This is using bwplotka/bingo-controlled, separate go module with pinned dependencies. - @echo "(re)installing $(GOBIN)/golangci-lint-v1.49.0" - @cd $(BINGO_DIR) && $(GO) build -mod=mod -modfile=golangci-lint.mod -o=$(GOBIN)/golangci-lint-v1.49.0 "github.com/golangci/golangci-lint/cmd/golangci-lint" + @echo "(re)installing $(GOBIN)/golangci-lint-v1.51.2" + @cd $(BINGO_DIR) && GOWORK=off $(GO) build -mod=mod -modfile=golangci-lint.mod -o=$(GOBIN)/golangci-lint-v1.51.2 "github.com/golangci/golangci-lint/cmd/golangci-lint" + +JB := $(GOBIN)/jb-v0.5.1 +$(JB): $(BINGO_DIR)/jb.mod + @# Install binary/ries using Go 1.14+ build command. This is using bwplotka/bingo-controlled, separate go module with pinned dependencies. + @echo "(re)installing $(GOBIN)/jb-v0.5.1" + @cd $(BINGO_DIR) && GOWORK=off $(GO) build -mod=mod -modfile=jb.mod -o=$(GOBIN)/jb-v0.5.1 "github.com/jsonnet-bundler/jsonnet-bundler/cmd/jb" SWAGGER := $(GOBIN)/swagger-v0.30.2 $(SWAGGER): $(BINGO_DIR)/swagger.mod diff --git a/.bingo/bra.sum b/.bingo/bra.sum deleted file mode 100644 index d4e9da39ec80d..0000000000000 --- a/.bingo/bra.sum +++ /dev/null @@ -1,30 +0,0 @@ -github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY= -github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= -github.com/jtolds/gls v4.2.1+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q= -github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo= -github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= -github.com/smartystreets/assertions v0.0.0-20190116191733-b6c0e53d7304/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= -github.com/smartystreets/goconvey v0.0.0-20181108003508-044398e4856c/go.mod h1:XDJAKZRPZ1CvBcN2aX5YOUTYGHki24fSF0Iv48Ibg0s= -github.com/unknwon/bra v0.0.0-20200517080246-1e3013ecaff8 h1:aVGB3YnaS/JNfOW3tiHIlmNmTDg618va+eT0mVomgyI= -github.com/unknwon/bra v0.0.0-20200517080246-1e3013ecaff8/go.mod h1:fVle4kNr08ydeohzYafr20oZzbAkhQT39gKK/pFQ5M4= -github.com/unknwon/com v1.0.1 h1:3d1LTxD+Lnf3soQiD4Cp/0BRB+Rsa/+RTvz8GMMzIXs= -github.com/unknwon/com v1.0.1/go.mod h1:tOOxU81rwgoCLoOVVPHb6T/wt8HZygqH5id+GNnlCXM= -github.com/unknwon/log v0.0.0-20150304194804-e617c87089d3 h1:4EYQaWAatQokdji3zqZloVIW/Ke1RQjYw2zHULyrHJg= -github.com/unknwon/log v0.0.0-20150304194804-e617c87089d3/go.mod h1:1xEUf2abjfP92w2GZTV+GgaRxXErwRXcClbUwrNJffU= -github.com/urfave/cli v1.22.1 h1:+mkCCcOFKPnCmVYVcURKps1Xe+3zP90gSYGNfRkjoIY= -github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= -golang.org/x/sys v0.0.0-20191020152052-9984515f0562 h1:wOweSabW7qssfcg63CEDHHA4zyoqRlGU6eYV7IUMCq0= -golang.org/x/sys v0.0.0-20191020152052-9984515f0562/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/fsnotify/fsnotify.v1 v1.4.7 h1:XNNYLJHt73EyYiCZi6+xjupS9CpvmiDgjPTAjrBlQbo= -gopkg.in/fsnotify/fsnotify.v1 v1.4.7/go.mod h1:Fyux9zXlo4rWoMSIzpn9fDAYjalPqJ/K1qJ27s+7ltE= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c h1:aFV+BgZ4svzjfabn8ERpuB4JI4N6/rdy1iusx77G3oU= -golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= \ No newline at end of file diff --git a/.bingo/drone.sum b/.bingo/drone.sum deleted file mode 100644 index ba8cbb0be41ae..0000000000000 --- a/.bingo/drone.sum +++ /dev/null @@ -1,1030 +0,0 @@ -bazil.org/fuse v0.0.0-20160811212531-371fbbdaa898/go.mod h1:Xbm+BRKSBEpa4q4hTSxohYNQpsxXPbPry4JJWOB3LB8= -cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= -cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= -cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= -cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= -cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= -cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= -cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= -cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= -cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= -cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= -cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= -cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= -cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= -cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= -cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= -cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= -cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= -cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= -cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= -cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= -dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -docker.io/go-docker v1.0.0/go.mod h1:7tiAn5a0LFmjbPDbyTPOaTTOuG1ZRNXdPA6RvKY+fpY= -github.com/99designs/httpsignatures-go v0.0.0-20170731043157-88528bf4ca7e h1:rl2Aq4ZODqTDkeSqQBy+fzpZPamacO1Srp8zq7jf2Sc= -github.com/99designs/httpsignatures-go v0.0.0-20170731043157-88528bf4ca7e/go.mod h1:Xa6lInWHNQnuWoF0YPSsx+INFA9qk7/7pTjwb3PInkY= -github.com/Azure/azure-sdk-for-go v16.2.1+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= -github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= -github.com/Azure/go-autorest v10.8.1+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= -github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= -github.com/Azure/go-autorest/autorest v0.11.1/go.mod h1:JFgpikqFJ/MleTTxwepExTKnFUKKszPS8UavbQYUMuw= -github.com/Azure/go-autorest/autorest/adal v0.9.0/go.mod h1:/c022QCutn2P7uY+/oQWWNcK9YU+MH96NgK+jErpbcg= -github.com/Azure/go-autorest/autorest/adal v0.9.5/go.mod h1:B7KF7jKIeC9Mct5spmyCB/A8CG/sEz1vwIRGv/bbw7A= -github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74= -github.com/Azure/go-autorest/autorest/mocks v0.4.0/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= -github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= -github.com/Azure/go-autorest/logger v0.2.0/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= -github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA= -github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= -github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw= -github.com/Microsoft/go-winio v0.4.16-0.20201130162521-d1ffc52c7331/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= -github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= -github.com/Microsoft/go-winio v0.4.17-0.20210211115548-6eac466e5fa3/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= -github.com/Microsoft/go-winio v0.4.17-0.20210324224401-5516f17a5958/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= -github.com/Microsoft/go-winio v0.4.17/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= -github.com/Microsoft/hcsshim v0.8.6/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg= -github.com/Microsoft/hcsshim v0.8.7-0.20190325164909-8abdbb8205e4/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg= -github.com/Microsoft/hcsshim v0.8.7/go.mod h1:OHd7sQqRFrYd3RmSgbgji+ctCwkbq2wbEYNSzOYtcBQ= -github.com/Microsoft/hcsshim v0.8.9/go.mod h1:5692vkUqntj1idxauYlpoINNKeqCiG6Sg38RRsjT5y8= -github.com/Microsoft/hcsshim v0.8.14/go.mod h1:NtVKoYxQuTLx6gEq0L96c9Ju4JbRJ4nY2ow3VK6a9Lg= -github.com/Microsoft/hcsshim v0.8.15/go.mod h1:x38A4YbHbdxJtc0sF6oIz+RG0npwSCAvn69iY6URG00= -github.com/Microsoft/hcsshim v0.8.16/go.mod h1:o5/SZqmR7x9JNKsW3pu+nqHm0MF8vbA+VxGOoXdC600= -github.com/Microsoft/hcsshim v0.8.23/go.mod h1:4zegtUJth7lAvFyc6cH2gGQ5B3OFQim01nnU2M8jKDg= -github.com/Microsoft/hcsshim/test v0.0.0-20201218223536-d3e5debf77da/go.mod h1:5hlzMzRKMLyo42nCZ9oml8AdTlq/0cvIaBv6tK1RehU= -github.com/Microsoft/hcsshim/test v0.0.0-20210227013316-43a75bb4edd3/go.mod h1:mw7qgWloBUl75W/gVH3cQszUg1+gUITj7D6NY7ywVnY= -github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= -github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= -github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= -github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= -github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ= -github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae/go.mod h1:CgnQgUtFrFz9mxFNtED3jI5tLDjKlOM+oUF/sTk6ps0= -github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= -github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= -github.com/aws/aws-sdk-go v1.15.11/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0= -github.com/beorn7/perks v0.0.0-20160804104726-4c0e84591b9a/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= -github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= -github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= -github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= -github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA= -github.com/bits-and-blooms/bitset v1.2.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA= -github.com/blang/semver v3.1.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= -github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= -github.com/bmatcuk/doublestar v1.1.1 h1:YroD6BJCZBYx06yYFEWvUuKVWQn3vLLQAVmDmvTSaiQ= -github.com/bmatcuk/doublestar v1.1.1/go.mod h1:UD6OnuiIn0yFxxA2le/rnRU1G4RaI4UvFv1sNto9p6w= -github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4= -github.com/bshuster-repo/logrus-logstash-hook v0.4.1/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk= -github.com/buger/jsonparser v0.0.0-20180808090653-f4dd9f5a6b44/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s= -github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8= -github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b/go.mod h1:obH5gd0BsqsP2LwDJ9aOkm/6J86V6lyAXCoQWGw3K50= -github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE= -github.com/buildkite/yaml v2.1.0+incompatible h1:xirI+ql5GzfikVNDmt+yeiXpf/v1Gt03qXTtT5WXdr8= -github.com/buildkite/yaml v2.1.0+incompatible/go.mod h1:UoU8vbcwu1+vjZq01+KrpSeLBgQQIjL/H7Y6KwikUrI= -github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= -github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= -github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/checkpoint-restore/go-criu/v4 v4.1.0/go.mod h1:xUQBLp4RLc5zJtWY++yjOoMoB5lihDt7fai+75m+rGw= -github.com/checkpoint-restore/go-criu/v5 v5.0.0/go.mod h1:cfwC0EG7HMUenopBsUf9d89JlCLQIfgVcNsNN0t6T2M= -github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= -github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= -github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/cilium/ebpf v0.0.0-20200110133405-4032b1d8aae3/go.mod h1:MA5e5Lr8slmEg9bt0VpxxWqJlO4iwu3FBdHUzV7wQVg= -github.com/cilium/ebpf v0.0.0-20200702112145-1c8d4c9ef775/go.mod h1:7cR51M8ViRLIdUjrmSXlK9pkrsDlLHbO8jiB8X8JnOc= -github.com/cilium/ebpf v0.2.0/go.mod h1:To2CFviqOWL/M0gIMsvSMlqe7em/l1ALkX1PyjrX2Qs= -github.com/cilium/ebpf v0.4.0/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs= -github.com/cilium/ebpf v0.6.2/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs= -github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= -github.com/containerd/aufs v0.0.0-20200908144142-dab0cbea06f4/go.mod h1:nukgQABAEopAHvB6j7cnP5zJ+/3aVcE7hCYqvIwAHyE= -github.com/containerd/aufs v0.0.0-20201003224125-76a6863f2989/go.mod h1:AkGGQs9NM2vtYHaUen+NljV0/baGCAPELGm2q9ZXpWU= -github.com/containerd/aufs v0.0.0-20210316121734-20793ff83c97/go.mod h1:kL5kd6KM5TzQjR79jljyi4olc1Vrx6XBlcyj3gNv2PU= -github.com/containerd/aufs v1.0.0/go.mod h1:kL5kd6KM5TzQjR79jljyi4olc1Vrx6XBlcyj3gNv2PU= -github.com/containerd/btrfs v0.0.0-20201111183144-404b9149801e/go.mod h1:jg2QkJcsabfHugurUvvPhS3E08Oxiuh5W/g1ybB4e0E= -github.com/containerd/btrfs v0.0.0-20210316141732-918d888fb676/go.mod h1:zMcX3qkXTAi9GI50+0HOeuV8LU2ryCE/V2vG/ZBiTss= -github.com/containerd/btrfs v1.0.0/go.mod h1:zMcX3qkXTAi9GI50+0HOeuV8LU2ryCE/V2vG/ZBiTss= -github.com/containerd/cgroups v0.0.0-20190717030353-c4b9ac5c7601/go.mod h1:X9rLEHIqSf/wfK8NsPqxJmeZgW4pcfzdXITDrUSJ6uI= -github.com/containerd/cgroups v0.0.0-20190919134610-bf292b21730f/go.mod h1:OApqhQ4XNSNC13gXIwDjhOQxjWa/NxkwZXJ1EvqT0ko= -github.com/containerd/cgroups v0.0.0-20200531161412-0dbf7f05ba59/go.mod h1:pA0z1pT8KYB3TCXK/ocprsh7MAkoW8bZVzPdih9snmM= -github.com/containerd/cgroups v0.0.0-20200710171044-318312a37340/go.mod h1:s5q4SojHctfxANBDvMeIaIovkq29IP48TKAxnhYRxvo= -github.com/containerd/cgroups v0.0.0-20200824123100-0b889c03f102/go.mod h1:s5q4SojHctfxANBDvMeIaIovkq29IP48TKAxnhYRxvo= -github.com/containerd/cgroups v0.0.0-20210114181951-8a68de567b68/go.mod h1:ZJeTFisyysqgcCdecO57Dj79RfL0LNeGiFUqLYQRYLE= -github.com/containerd/cgroups v1.0.1/go.mod h1:0SJrPIenamHDcZhEcJMNBB85rHcUsw4f25ZfBiPYRkU= -github.com/containerd/console v0.0.0-20180822173158-c12b1e7919c1/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw= -github.com/containerd/console v0.0.0-20181022165439-0650fd9eeb50/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw= -github.com/containerd/console v0.0.0-20191206165004-02ecf6a7291e/go.mod h1:8Pf4gM6VEbTNRIT26AyyU7hxdQU3MvAvxVI0sc00XBE= -github.com/containerd/console v1.0.1/go.mod h1:XUsP6YE/mKtz6bxc+I8UiKKTP04qjQL4qcS3XoQ5xkw= -github.com/containerd/console v1.0.2/go.mod h1:ytZPjGgY2oeTkAONYafi2kSj0aYggsf8acV1PGKCbzQ= -github.com/containerd/containerd v1.2.10/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/containerd/containerd v1.3.0-beta.2.0.20190828155532-0293cbd26c69/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/containerd/containerd v1.3.0/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/containerd/containerd v1.3.1-0.20191213020239-082f7e3aed57/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/containerd/containerd v1.3.2/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/containerd/containerd v1.3.4 h1:3o0smo5SKY7H6AJCmJhsnCjR2/V2T8VmiHt7seN2/kI= -github.com/containerd/containerd v1.3.4/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/containerd/containerd v1.4.0-beta.2.0.20200729163537-40b22ef07410/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/containerd/containerd v1.4.1/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/containerd/containerd v1.4.3/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/containerd/containerd v1.4.9/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/containerd/containerd v1.5.0-beta.1/go.mod h1:5HfvG1V2FsKesEGQ17k5/T7V960Tmcumvqn8Mc+pCYQ= -github.com/containerd/containerd v1.5.0-beta.3/go.mod h1:/wr9AVtEM7x9c+n0+stptlo/uBBoBORwEx6ardVcmKU= -github.com/containerd/containerd v1.5.0-beta.4/go.mod h1:GmdgZd2zA2GYIBZ0w09ZvgqEq8EfBp/m3lcVZIvPHhI= -github.com/containerd/containerd v1.5.0-rc.0/go.mod h1:V/IXoMqNGgBlabz3tHD2TWDoTJseu1FGOKuoA4nNb2s= -github.com/containerd/containerd v1.5.8 h1:NmkCC1/QxyZFBny8JogwLpOy2f+VEbO/f6bV2Mqtwuw= -github.com/containerd/containerd v1.5.8/go.mod h1:YdFSv5bTFLpG2HIYmfqDpSYYTDX+mc5qtSuYx1YUb/s= -github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= -github.com/containerd/continuity v0.0.0-20190815185530-f2a389ac0a02/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= -github.com/containerd/continuity v0.0.0-20191127005431-f65d91d395eb/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= -github.com/containerd/continuity v0.0.0-20200710164510-efbc4488d8fe/go.mod h1:cECdGN1O8G9bgKTlLhuPJimka6Xb/Gg7vYzCTNVxhvo= -github.com/containerd/continuity v0.0.0-20201208142359-180525291bb7/go.mod h1:kR3BEg7bDFaEddKm54WSmrol1fKWDU1nKYkgrcgZT7Y= -github.com/containerd/continuity v0.0.0-20210208174643-50096c924a4e/go.mod h1:EXlVlkqNba9rJe3j7w3Xa924itAMLgZH4UD/Q4PExuQ= -github.com/containerd/continuity v0.1.0/go.mod h1:ICJu0PwR54nI0yPEnJ6jcS+J7CZAUXrLh8lPo2knzsM= -github.com/containerd/fifo v0.0.0-20180307165137-3d5202aec260/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI= -github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI= -github.com/containerd/fifo v0.0.0-20200410184934-f15a3290365b/go.mod h1:jPQ2IAeZRCYxpS/Cm1495vGFww6ecHmMk1YJH2Q5ln0= -github.com/containerd/fifo v0.0.0-20201026212402-0724c46b320c/go.mod h1:jPQ2IAeZRCYxpS/Cm1495vGFww6ecHmMk1YJH2Q5ln0= -github.com/containerd/fifo v0.0.0-20210316144830-115abcc95a1d/go.mod h1:ocF/ME1SX5b1AOlWi9r677YJmCPSwwWnQ9O123vzpE4= -github.com/containerd/fifo v1.0.0/go.mod h1:ocF/ME1SX5b1AOlWi9r677YJmCPSwwWnQ9O123vzpE4= -github.com/containerd/go-cni v1.0.1/go.mod h1:+vUpYxKvAF72G9i1WoDOiPGRtQpqsNW/ZHtSlv++smU= -github.com/containerd/go-cni v1.0.2/go.mod h1:nrNABBHzu0ZwCug9Ije8hL2xBCYh/pjfMb1aZGrrohk= -github.com/containerd/go-runc v0.0.0-20180907222934-5a6d9f37cfa3/go.mod h1:IV7qH3hrUgRmyYrtgEeGWJfWbgcHL9CSRruz2Vqcph0= -github.com/containerd/go-runc v0.0.0-20190911050354-e029b79d8cda/go.mod h1:IV7qH3hrUgRmyYrtgEeGWJfWbgcHL9CSRruz2Vqcph0= -github.com/containerd/go-runc v0.0.0-20200220073739-7016d3ce2328/go.mod h1:PpyHrqVs8FTi9vpyHwPwiNEGaACDxT/N/pLcvMSRA9g= -github.com/containerd/go-runc v0.0.0-20201020171139-16b287bc67d0/go.mod h1:cNU0ZbCgCQVZK4lgG3P+9tn9/PaJNmoDXPpoJhDR+Ok= -github.com/containerd/go-runc v1.0.0/go.mod h1:cNU0ZbCgCQVZK4lgG3P+9tn9/PaJNmoDXPpoJhDR+Ok= -github.com/containerd/imgcrypt v1.0.1/go.mod h1:mdd8cEPW7TPgNG4FpuP3sGBiQ7Yi/zak9TYCG3juvb0= -github.com/containerd/imgcrypt v1.0.4-0.20210301171431-0ae5c75f59ba/go.mod h1:6TNsg0ctmizkrOgXRNQjAPFWpMYRWuiB6dSF4Pfa5SA= -github.com/containerd/imgcrypt v1.1.1-0.20210312161619-7ed62a527887/go.mod h1:5AZJNI6sLHJljKuI9IHnw1pWqo/F0nGDOuR9zgTs7ow= -github.com/containerd/imgcrypt v1.1.1/go.mod h1:xpLnwiQmEUJPvQoAapeb2SNCxz7Xr6PJrXQb0Dpc4ms= -github.com/containerd/nri v0.0.0-20201007170849-eb1350a75164/go.mod h1:+2wGSDGFYfE5+So4M5syatU0N0f0LbWpuqyMi4/BE8c= -github.com/containerd/nri v0.0.0-20210316161719-dbaa18c31c14/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY= -github.com/containerd/nri v0.1.0/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY= -github.com/containerd/ttrpc v0.0.0-20190828154514-0e0f228740de/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o= -github.com/containerd/ttrpc v0.0.0-20190828172938-92c8520ef9f8/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o= -github.com/containerd/ttrpc v0.0.0-20191028202541-4f1b8fe65a5c/go.mod h1:LPm1u0xBw8r8NOKoOdNMeVHSawSsltak+Ihv+etqsE8= -github.com/containerd/ttrpc v1.0.1/go.mod h1:UAxOpgT9ziI0gJrmKvgcZivgxOp8iFPSk8httJEt98Y= -github.com/containerd/ttrpc v1.0.2/go.mod h1:UAxOpgT9ziI0gJrmKvgcZivgxOp8iFPSk8httJEt98Y= -github.com/containerd/ttrpc v1.1.0/go.mod h1:XX4ZTnoOId4HklF4edwc4DcqskFZuvXB1Evzy5KFQpQ= -github.com/containerd/typeurl v0.0.0-20180627222232-a93fcdb778cd/go.mod h1:Cm3kwCdlkCfMSHURc+r6fwoGH6/F1hH3S4sg0rLFWPc= -github.com/containerd/typeurl v0.0.0-20190911142611-5eb25027c9fd/go.mod h1:GeKYzf2pQcqv7tJ0AoCuuhtnqhva5LNU3U+OyKxxJpk= -github.com/containerd/typeurl v1.0.1/go.mod h1:TB1hUtrpaiO88KEK56ijojHS1+NeF0izUACaJW2mdXg= -github.com/containerd/typeurl v1.0.2/go.mod h1:9trJWW2sRlGub4wZJRTW83VtbOLS6hwcDZXTn6oPz9s= -github.com/containerd/zfs v0.0.0-20200918131355-0a33824f23a2/go.mod h1:8IgZOBdv8fAgXddBT4dBXJPtxyRsejFIpXoklgxgEjw= -github.com/containerd/zfs v0.0.0-20210301145711-11e8f1707f62/go.mod h1:A9zfAbMlQwE+/is6hi0Xw8ktpL+6glmqZYtevJgaB8Y= -github.com/containerd/zfs v0.0.0-20210315114300-dde8f0fda960/go.mod h1:m+m51S1DvAP6r3FcmYCp54bQ34pyOwTieQDNRIRHsFY= -github.com/containerd/zfs v0.0.0-20210324211415-d5c4544f0433/go.mod h1:m+m51S1DvAP6r3FcmYCp54bQ34pyOwTieQDNRIRHsFY= -github.com/containerd/zfs v1.0.0/go.mod h1:m+m51S1DvAP6r3FcmYCp54bQ34pyOwTieQDNRIRHsFY= -github.com/containernetworking/cni v0.7.1/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= -github.com/containernetworking/cni v0.8.0/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= -github.com/containernetworking/cni v0.8.1/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= -github.com/containernetworking/plugins v0.8.6/go.mod h1:qnw5mN19D8fIwkqW7oHHYDHVlzhJpcY6TQxn/fUyDDM= -github.com/containernetworking/plugins v0.9.1/go.mod h1:xP/idU2ldlzN6m4p5LmGiwRDjeJr6FLK6vuiUwoH7P8= -github.com/containers/ocicrypt v1.0.1/go.mod h1:MeJDzk1RJHv89LjsH0Sp5KTY3ZYkjXO/C+bKAeWFIrc= -github.com/containers/ocicrypt v1.1.0/go.mod h1:b8AOe0YR67uU8OqfVNcznfFpAzu3rdgUV4GP9qXPfu4= -github.com/containers/ocicrypt v1.1.1/go.mod h1:Dm55fwWm1YZAjYRaJ94z2mfZikIyIN4B0oB3dj3jFxY= -github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= -github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= -github.com/coreos/go-iptables v0.4.5/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU= -github.com/coreos/go-iptables v0.5.0/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU= -github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= -github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= -github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= -github.com/coreos/go-systemd v0.0.0-20161114122254-48702e0da86b/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/go-systemd/v22 v22.0.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk= -github.com/coreos/go-systemd/v22 v22.1.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk= -github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= -github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= -github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= -github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/cpuguy83/go-md2man/v2 v2.0.0 h1:EoUDS0afbrsXAZ9YQ9jdu/mZ2sXgT1/2yyNng4PGlyM= -github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= -github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4= -github.com/d2g/dhcp4 v0.0.0-20170904100407-a1d1b6c41b1c/go.mod h1:Ct2BUK8SB0YC1SMSibvLzxjeJLnrYEVLULFNiHY9YfQ= -github.com/d2g/dhcp4client v1.0.0/go.mod h1:j0hNfjhrt2SxUOw55nL0ATM/z4Yt3t2Kd1mW34z5W5s= -github.com/d2g/dhcp4server v0.0.0-20181031114812-7d4a0a7f59a5/go.mod h1:Eo87+Kg/IX2hfWJfwxMzLyuSZyxSoAug2nGa1G2QAi8= -github.com/d2g/hardwareaddr v0.0.0-20190221164911-e7d9fbe030e4/go.mod h1:bMl4RjIciD2oAxI7DmWRx6gbeqrkoLqv3MV0vzNad+I= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/denverdino/aliyungo v0.0.0-20190125010748-a747050bb1ba/go.mod h1:dV8lFg6daOBZbT6/BDGIz6Y3WFGn8juu6G+CQ6LHtl0= -github.com/dgrijalva/jwt-go v0.0.0-20170104182250-a601269ab70c/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= -github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= -github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= -github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E= -github.com/docker/distribution v0.0.0-20170726174610-edc3ab29cdff/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/distribution v0.0.0-20190905152932-14b96e55d84c/go.mod h1:0+TTO4EOBfRPhZXAeF1Vu+W3hHZ8eLp8PgKVZlcvtFY= -github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/distribution v2.7.1+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BUmsJpcB+cRlLU7cSug= -github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/engine v17.12.0-ce-rc1.0.20200309214505-aa6a9891b09c+incompatible h1:hx8H7MbcmXUXAmphQuA/XB7CfSzX4DRrNuHFvfK9aIQ= -github.com/docker/engine v17.12.0-ce-rc1.0.20200309214505-aa6a9891b09c+incompatible/go.mod h1:3CPr2caMgTHxxIAZgEMd3uLYPDlRvPqCpyeRf6ncPcY= -github.com/docker/go-connections v0.3.0 h1:3lOnM9cSzgGwx8VfK/NGOW5fLQ0GjIlCkaktF+n1M6o= -github.com/docker/go-connections v0.3.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= -github.com/docker/go-events v0.0.0-20170721190031-9461782956ad/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA= -github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA= -github.com/docker/go-metrics v0.0.0-20180209012529-399ea8c73916/go.mod h1:/u0gXw0Gay3ceNrsHubL3BtdOL2fHf93USgMTe0W5dI= -github.com/docker/go-metrics v0.0.1/go.mod h1:cG1hvH2utMXtqgqqYE9plW6lDxS3/5ayHzueweSI3Vw= -github.com/docker/go-units v0.3.3 h1:Xk8S3Xj5sLGlG5g67hJmYMmUgXv5N4PhkjJHHqrwnTk= -github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= -github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw= -github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= -github.com/docker/libtrust v0.0.0-20150114040149-fa567046d9b1/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE= -github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= -github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= -github.com/drone/drone-cli v1.4.0 h1:DahOHhnr0LMW5UNSkBtB0KgpAfDbvKb+75Ar1r8CikY= -github.com/drone/drone-cli v1.4.0/go.mod h1:Wq7lI3ke2jyTUe6fiJyPElnKzFZWJamqRpYw0mYexEw= -github.com/drone/drone-cli v1.5.0 h1:dAoU2YBs7c0XjuDs2ql0W7x0+dOvJ/KLh5UrxUuaOnk= -github.com/drone/drone-cli v1.5.0/go.mod h1:682hzP+pG/nS7Xu6YJy064tUrbG7jTpB3gdy0kdxIOM= -github.com/drone/drone-go v1.6.2 h1:QT7o6Bfe5UCUea4ZU74JfzgkwFYbBNduuSQZTr1fQJE= -github.com/drone/drone-go v1.6.2/go.mod h1:fxCf9jAnXDZV1yDr0ckTuWd1intvcQwfJmTRpTZ1mXg= -github.com/drone/drone-go v1.7.0 h1:oEFWVcagBmAkVuFBpBq9lImZX1caDM+zRsmC4O1vXgQ= -github.com/drone/drone-go v1.7.0/go.mod h1:fxCf9jAnXDZV1yDr0ckTuWd1intvcQwfJmTRpTZ1mXg= -github.com/drone/drone-runtime v1.0.7-0.20190729070836-38f28a11afe8/go.mod h1:+osgwGADc/nyl40J0fdsf8Z09bgcBZXvXXnLOY48zYs= -github.com/drone/drone-runtime v1.1.1-0.20200623162453-61e33e2cab5d h1:P5HI/Y9hARTZ3F3EKs0kYijhjXZWQRQHYn1neTi0pWM= -github.com/drone/drone-runtime v1.1.1-0.20200623162453-61e33e2cab5d/go.mod h1:4/2QToW5+HGD0y1sTw7X35W1f7YINS14UfDY4isggT8= -github.com/drone/drone-yaml v0.0.0-20190729072335-70fa398b3560 h1:3QL4NnDpGtaXpgI9eNd6N2k5WK8W388CzD67ZTuuZQg= -github.com/drone/drone-yaml v0.0.0-20190729072335-70fa398b3560/go.mod h1:rCLISp/rqZ50s6G4nKsm971tRSzolxzqqXfgjDqPYoE= -github.com/drone/envsubst v1.0.3 h1:PCIBwNDYjs50AsLZPYdfhSATKaRg/FJmDc2D6+C2x8g= -github.com/drone/envsubst v1.0.3/go.mod h1:N2jZmlMufstn1KEqvbHjw40h1KyTmnVzHcSc9bFiJ2g= -github.com/drone/funcmap v0.0.0-20190918184546-d4ef6e88376d h1:/IO7UVVu191Jc0DajV4cDVoO+91cuppvgxg2MZl+AXI= -github.com/drone/funcmap v0.0.0-20190918184546-d4ef6e88376d/go.mod h1:Hph0/pT6ZxbujnE1Z6/08p5I0XXuOsppqF6NQlGOK0E= -github.com/drone/signal v1.0.0 h1:NrnM2M/4yAuU/tXs6RP1a1ZfxnaHwYkd0kJurA1p6uI= -github.com/drone/signal v1.0.0/go.mod h1:S8t92eFT0g4WUgEc/LxG+LCuiskpMNsG0ajAMGnyZpc= -github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= -github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= -github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= -github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= -github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= -github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= -github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= -github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/fatih/color v1.9.0 h1:8xPHl4/q1VyqGIPif1F+1V3Y3lSmrq01EabUW3CoW5s= -github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= -github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= -github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k= -github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa/go.mod h1:KnogPXtdwXqoenmZCw6S+25EAm2MkxbG0deNDu4cbSA= -github.com/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY= -github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= -github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-ini/ini v1.25.4/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= -github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= -github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= -github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= -github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= -github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg= -github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= -github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc= -github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8= -github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo= -github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= -github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= -github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/godbus/dbus v0.0.0-20151105175453-c7fdd8b5cd55/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw= -github.com/godbus/dbus v0.0.0-20180201030542-885f9cc04c9c/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw= -github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4= -github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/gogo/googleapis v1.2.0/go.mod h1:Njal3psf3qN6dwBtQfUmBZh2ybovJ0tlu3o/AC7HYjU= -github.com/gogo/googleapis v1.4.0/go.mod h1:5YRNX2z1oM5gXdAkurHa942MDgEJyk02w4OecKY87+c= -github.com/gogo/protobuf v0.0.0-20170307180453-100ba4e88506 h1:zDlw+wgyXdfkRuvFCdEDUiPLmZp2cvf/dWHazY0a5VM= -github.com/gogo/protobuf v0.0.0-20170307180453-100ba4e88506/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= -github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= -github.com/gogo/protobuf v1.3.0/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= -github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= -github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= -github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= -github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.3 h1:gyjaxf+svBWX08ZjK86iN9geUJF0H6gp2IRKX6Nf6/I= -github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= -github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= -github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= -github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= -github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= -github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= -github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.5.0 h1:LUVKkCeviFUMKqHa4tXIIij/lbhnMbP7Fn5wKdKkRh4= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= -github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-jsonnet v0.16.0 h1:Nb4EEOp+rdeGGyB1rQ5eisgSAqrTnhf9ip+X6lzZbY0= -github.com/google/go-jsonnet v0.16.0/go.mod h1:sOcuej3UW1vpPTZOr8L7RQimqai1a57bt5j22LzGZCw= -github.com/google/go-jsonnet v0.17.0 h1:/9NIEfhK1NQRKl3sP2536b2+x5HnZMdql7x3yK/l8JY= -github.com/google/go-jsonnet v0.17.0/go.mod h1:sOcuej3UW1vpPTZOr8L7RQimqai1a57bt5j22LzGZCw= -github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= -github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= -github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= -github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/googleapis/gnostic v0.2.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= -github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg= -github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= -github.com/gorilla/handlers v0.0.0-20150720190736-60c7bfde3e33/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ= -github.com/gorilla/mux v1.7.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= -github.com/gorilla/mux v1.7.4/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= -github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= -github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= -github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= -github.com/gregjones/httpcache v0.0.0-20181110185634-c63ab54fda8f/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= -github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= -github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= -github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= -github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= -github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= -github.com/hashicorp/errwrap v0.0.0-20141028054710-7554cd9344ce/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/go-multierror v0.0.0-20161216184304-ed905158d874/go.mod h1:JMRHfdO9jKNzS/+BTlxCjKNQHg/jZAft8U7LloJvN7I= -github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= -github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= -github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= -github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= -github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= -github.com/imdario/mergo v0.3.10/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= -github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= -github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= -github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= -github.com/j-keck/arping v0.0.0-20160618110441-2cf9dc699c56/go.mod h1:ymszkNOg6tORTn+6F6j+Jc8TOr5osrynvN6ivFWZ2GA= -github.com/jackspirou/syscerts v0.0.0-20160531025014-b68f5469dff1 h1:9Xm8CKtMZIXgcopfdWk/qZ1rt0HjMgfMR9nxxSeK6vk= -github.com/jackspirou/syscerts v0.0.0-20160531025014-b68f5469dff1/go.mod h1:zuHl3Hh+e9P6gmBPvcqR1HjkaWHC/csgyskg6IaFKFo= -github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= -github.com/jmespath/go-jmespath v0.0.0-20160803190731-bd40a432e4c7/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= -github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc= -github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= -github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= -github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= -github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= -github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= -github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= -github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= -github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= -github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= -github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= -github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= -github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.11.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= -github.com/klauspost/compress v1.11.13/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= -github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= -github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs= -github.com/marstr/guid v1.1.0/go.mod h1:74gB1z2wpxxInTG6yaqA7KrtM0NZ+RbrcqDvYHefzho= -github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= -github.com/mattn/go-colorable v0.1.4 h1:snbPLB8fVfU9iwbbo30TPtbLRzwWu6aJS6Xh4eaaviA= -github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= -github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= -github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.11 h1:FxPOTFNqGkuDUGi3H/qkUbQO4ZiBa2brKq5r0l8TGeM= -github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= -github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= -github.com/mattn/go-shellwords v1.0.3/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o= -github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= -github.com/miekg/pkcs11 v1.0.3/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= -github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible/go.mod h1:8AuVvqP/mXw1px98n46wfvcGfQ4ci2FwoAjKYxuo3Z4= -github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f/go.mod h1:OkQIRizQZAeMln+1tSwduZz7+Af5oFlKirV/MSYes2A= -github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc= -github.com/moby/sys/mountinfo v0.4.0/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A= -github.com/moby/sys/mountinfo v0.4.1/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A= -github.com/moby/sys/symlink v0.1.0/go.mod h1:GGDODQmbFOjFsXvfLVn3+ZRxkch54RkSiGqsZeMYowQ= -github.com/moby/term v0.0.0-20200312100748-672ec06f55cd/go.mod h1:DdlQx2hp0Ss5/fLikoLlEeIYiATotOjgB//nb973jeo= -github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= -github.com/mrunalp/fileutils v0.5.0/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ= -github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= -github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= -github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= -github.com/natessilva/dag v0.0.0-20180124060714-7194b8dcc5c4 h1:dnMxwus89s86tI8rcGVp2HwZzlz7c5o92VOy7dSckBQ= -github.com/natessilva/dag v0.0.0-20180124060714-7194b8dcc5c4/go.mod h1:cojhOHk1gbMeklOyDP2oKKLftefXoJreOQGOrXk+Z38= -github.com/ncw/swift v1.0.47/go.mod h1:23YIA4yWVnGwv2dQlN4bB7egfYX6YLn0Yo/S6zZO/ZM= -github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= -github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= -github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= -github.com/onsi/ginkgo v0.0.0-20151202141238-7f8ab55aaf3b/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= -github.com/onsi/gomega v0.0.0-20151007035656-2152b45fa28a/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= -github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= -github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= -github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc= -github.com/opencontainers/go-digest v0.0.0-20170106003457-a6d0ee40d420/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= -github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= -github.com/opencontainers/go-digest v1.0.0-rc1 h1:WzifXhOVOEOuFYOJAW6aQqW0TooG2iki3E3Ii+WN7gQ= -github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= -github.com/opencontainers/go-digest v1.0.0-rc1.0.20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= -github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= -github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= -github.com/opencontainers/image-spec v1.0.0/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= -github.com/opencontainers/image-spec v1.0.1 h1:JMemWkRwHx4Zj+fVxWoMCFm/8sYGGrUVojFA6h/TRcI= -github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= -github.com/opencontainers/image-spec v1.0.2 h1:9yCKha/T5XdGtO0q9Q9a6T5NUCsTn/DrBg0D7ufOcFM= -github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= -github.com/opencontainers/runc v0.0.0-20190115041553-12f6a991201f/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= -github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= -github.com/opencontainers/runc v1.0.0-rc8.0.20190926000215-3e425f80a8c9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= -github.com/opencontainers/runc v1.0.0-rc9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= -github.com/opencontainers/runc v1.0.0-rc93/go.mod h1:3NOsor4w32B2tC0Zbl8Knk4Wg84SM2ImC1fxBuqJ/H0= -github.com/opencontainers/runc v1.0.2/go.mod h1:aTaHFFwQXuA71CiyxOdFFIorAoemI04suvGRQFzWTD0= -github.com/opencontainers/runtime-spec v0.1.2-0.20190507144316-5b71a03e2700/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= -github.com/opencontainers/runtime-spec v1.0.1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= -github.com/opencontainers/runtime-spec v1.0.2-0.20190207185410-29686dbc5559/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= -github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= -github.com/opencontainers/runtime-spec v1.0.3-0.20200929063507-e6143ca7d51d/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= -github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= -github.com/opencontainers/runtime-tools v0.0.0-20181011054405-1d69bd0f9c39/go.mod h1:r3f7wjNzSs2extwzU3Y+6pKfobzPh+kKFJ3ofN+3nfs= -github.com/opencontainers/selinux v1.6.0/go.mod h1:VVGKuOLlE7v4PJyT6h7mNWvq1rzqiriPsEqVhc+svHE= -github.com/opencontainers/selinux v1.8.0/go.mod h1:RScLhm78qiWa2gbVCcGkC7tCGdgk3ogry1nUQF8Evvo= -github.com/opencontainers/selinux v1.8.2/go.mod h1:MUIHuUEvKB1wtJjQdOyYRgOnLD2xAPP8dBsCoU0KuF8= -github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= -github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc= -github.com/petar/GoLLRB v0.0.0-20130427215148-53be0d36a84c/go.mod h1:HUpKUBZnpzkdx0kD/+Yfuft+uD3zHGtXF/XJB14TUr4= -github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= -github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4 h1:49lOXmGaUpV9Fz3gd7TFZY106KVlPVa5jcYD1gaQf98= -github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4/go.mod h1:4OwLy04Bl9Ef3GJJCoec+30X3LQs/0/m4HFRt/2LUSA= -github.com/pkg/errors v0.8.0 h1:WdK/asTD0HN+q6hsWO3/vpuAkAr+tw6aNJNDFFf0+qw= -github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.8.1-0.20171018195549-f15c970de5b7/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA= -github.com/prometheus/client_golang v0.0.0-20180209125602-c332b6f63c06/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= -github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= -github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g= -github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= -github.com/prometheus/client_model v0.0.0-20171117100541-99fa1f4be8e5/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/common v0.0.0-20180110214958-89604d197083/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= -github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= -github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= -github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= -github.com/prometheus/procfs v0.0.0-20180125133057-cb4147076ac7/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.0.0-20190522114515-bc1a522cf7b1/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= -github.com/prometheus/procfs v0.0.5/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= -github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= -github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= -github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= -github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= -github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= -github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q= -github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/safchain/ethtool v0.0.0-20190326074333-42ed695e3de8/go.mod h1:Z0q5wiBQGYcxhMZ6gUqHn6pYNLypFAvaL3UvgZLR0U4= -github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= -github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo= -github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= -github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= -github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo= -github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= -github.com/sirupsen/logrus v1.0.4-0.20170822132746-89742aefa4b2/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= -github.com/sirupsen/logrus v1.0.6/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= -github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= -github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= -github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= -github.com/sirupsen/logrus v1.6.0 h1:UBcNElsrwanuuMsnGSlYmtmgbb23qDR5dG+6X6Oo89I= -github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= -github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= -github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= -github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= -github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= -github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= -github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= -github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cobra v0.0.2-0.20171109065643-2da4a54c5cee/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= -github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= -github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= -github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= -github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/spf13/pflag v1.0.1-0.20171106142849-4c012f6dcd95/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= -github.com/stefanberger/go-pkcs11uri v0.0.0-20201008174630-78d3cae3a980/go.mod h1:AO3tvPzVZ/ayst6UlUKUv6rcPQInYe3IknH3jYhAKu8= -github.com/stretchr/objx v0.0.0-20180129172003-8a3f7159479f/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= -github.com/stretchr/testify v0.0.0-20180303142811-b89eecf5ca5d/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= -github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= -github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= -github.com/tchap/go-patricia v2.2.6+incompatible/go.mod h1:bmLyhP68RS6kStMGxByiQ23RP/odRBOTVjwp2cDyi6I= -github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= -github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= -github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= -github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= -github.com/urfave/cli v1.20.0 h1:fDqGv3UG/4jbVl/QkFwEdddtEDjh/5Ov6X+0B/3bPaw= -github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= -github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= -github.com/urfave/cli v1.22.2 h1:gsqYFH8bb9ekPA12kRo0hfjngWQjkJPlN9R0N78BoUo= -github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= -github.com/vinzenz/yaml v0.0.0-20170920082545-91409cdd725d h1:3wDi6J5APMqaHBVPuVd7RmHD2gRTfqbdcVSpCNoUWtk= -github.com/vinzenz/yaml v0.0.0-20170920082545-91409cdd725d/go.mod h1:mb5taDqMnJiZNRQ3+02W2IFG+oEz1+dTuCXkp4jpkfo= -github.com/vishvananda/netlink v0.0.0-20181108222139-023a6dafdcdf/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk= -github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= -github.com/vishvananda/netlink v1.1.1-0.20201029203352-d40f9887b852/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho= -github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc/go.mod h1:ZjcWmFBXmLKZu9Nxj3WKYEafiSqer2rnvPr0en9UNpI= -github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU= -github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0= -github.com/willf/bitset v1.1.11-0.20200630133818-d5bec3311243/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4= -github.com/willf/bitset v1.1.11/go.mod h1:83CECat5yLh5zVOf4P1ErAgKA5UDvKtgyUABdr3+MjI= -github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= -github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= -github.com/xeipuuv/gojsonschema v0.0.0-20180618132009-1d523034197f/go.mod h1:5yf86TLmAcydyeJq5YvxkGPE2fm/u4myDekKRoLuqhs= -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.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43/go.mod h1:aX5oPXxHm3bOH+xeAttToC8pqch2ScQN/JoXYupl6xs= -github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50/go.mod h1:NUSPSUX/bi6SeDMUh6brw0nXpxHnc96TguQh0+r/ssA= -github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f/go.mod h1:GlGEuHIJweS1mbCqG+7vt2nvWLzLLnRHbXz5JKd/Qbg= -go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= -go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= -go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= -go.etcd.io/etcd v0.5.0-alpha.5.0.20200910180754-dd1b699fc489/go.mod h1:yVHk9ub3CSBatqGNg7GRmsnfLWtoW60w4eDYfh7vHDg= -go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1/go.mod h1:SNgMg+EgDFwmvSmLRTNKC5fegJjB7v23qTQ0XLGUNHk= -go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= -go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= -go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.starlark.net v0.0.0-20201118183435-e55f603d8c79 h1:JPjLPz44y2N9mkzh2N344kTk1Y4/V4yJAjTrXGmzv8I= -go.starlark.net v0.0.0-20201118183435-e55f603d8c79/go.mod h1:5YFcFnRptTN+41758c2bMPiqpGg4zBfYji1IQz8wNFk= -go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= -go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= -go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= -go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= -golang.org/x/crypto v0.0.0-20171113213409-9f005a07e0d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20181009213950-7c1a557ab941/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= -golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= -golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= -golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= -golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= -golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= -golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= -golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= -golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= -golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= -golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= -golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181005035420-146acd28ed58/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= -golang.org/x/net v0.0.0-20190603091049-60506f45cf65 h1:+rhAzEzT3f4JtomfC371qB+0Ola2caSKcY69NUBZrRQ= -golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= -golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190619014844-b5b0513f8c1b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20201006153459-a7d1128ccaa0/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110 h1:qWPm9rbaAMKs8Bq/9LRpbMqxWRVUAQwMI9fVrssnTfw= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890 h1:uESlIz09WIHT2I+pasSXcpLYqYK8wHcdCetU3VuMBJE= -golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d h1:TzXSXBo42m9gQenoE3b9BGiEpg5IG2JkU5FkPIawgtw= -golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201207232520-09787c993a3a h1:DcqTD9SDLc+1P/r1EmRBwnVsrOwW+kk2vWf9n+1sGhs= -golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181005133103-4497e2df6f9e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190514135907-3a4b5fb9f71f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190522044717-8097e1b27ff5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190602015325-4c4f7f33c9ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190812073006-9eafafc0a87e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191022100944-742c48ecaeb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191210023423-ac6580df4449/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200120151820-655fe14d7479/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200622214017-ed371f2e16b4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200728102440-3e129f6d46b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200803210538-64077c9b5642 h1:B6caxRw+hozq68X2MY7jEpZh/cr4/aHLv9xU8Kkadrw= -golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200817155316-9781c653f443/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200916030750-2334cc1a136f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200922070232-aee5d888a860/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201112073958-5cba982894dd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201117170446-d9b008d0a637/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201202213521-69691e467435/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210426230700-d19ff857e887 h1:dXfMednGJh/SUUFjTLsWJz3P+TQt9qnR11GgeI3vWKs= -golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= -golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/api v0.0.0-20160322025152-9bf6e6e569ff/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= -google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= -google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= -google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= -google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/cloud v0.0.0-20151119220103-975617b05ea8/go.mod h1:0H1ncTHf11KCFhTc/+EFRbzSCOZx+VUbRMk55Yv5MYk= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190522204451-c2c4e71fbf69/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= -google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55 h1:gSJIx1SDwno+2ElGhA4+qG2zF97qiUzTM+rQ0klBOcE= -google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= -google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200117163144-32f20d992d24/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= -google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a h1:pOwg4OoaRYScjmR4LlLgdtnyoHYTSAVhhqe5uPdpII8= -google.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= -google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= -google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= -google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= -google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.24.0/go.mod h1:XDChyiUovWa60DnaeDeZmSW86xtLtjtZbwvSiRnRtcA= -google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= -google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.30.0 h1:M5a8xTlYTxwMn5ZFkwhRabsygDY5G8TYLyQDBxJNAxE= -google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.33.2 h1:EQyQC3sa8M+p6Ulc8yy9SWSS2GVwyRc83gAbG8lrl4o= -google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= -google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= -google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= -google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= -google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= -google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ= -google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U= -gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20141024133853-64131543e789/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= -gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= -gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo= -gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= -gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= -gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= -gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= -gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= -gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= -gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= -gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I= -gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= -gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= -gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= -gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8= -honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= -honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -k8s.io/api v0.0.0-20181130031204-d04500c8c3dd/go.mod h1:iuAfoD4hCxJ8Onx9kaTIt30j7jUFS00AXQi6QMi99vA= -k8s.io/api v0.20.1/go.mod h1:KqwcCVogGxQY3nBlRpwt+wpAMF/KjaCc7RpywacvqUo= -k8s.io/api v0.20.4/go.mod h1:++lNL1AJMkDymriNniQsWRkMDzRaX2Y/POTUi8yvqYQ= -k8s.io/api v0.20.6/go.mod h1:X9e8Qag6JV/bL5G6bU8sdVRltWKmdHsFUGS3eVndqE8= -k8s.io/apimachinery v0.0.0-20181201231028-18a5ff3097b4/go.mod h1:ccL7Eh7zubPUSh9A3USN90/OzHNSVN6zxzde07TDCL0= -k8s.io/apimachinery v0.20.1/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU= -k8s.io/apimachinery v0.20.4/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU= -k8s.io/apimachinery v0.20.6/go.mod h1:ejZXtW1Ra6V1O5H8xPBGz+T3+4gfkTCeExAHKU57MAc= -k8s.io/apiserver v0.20.1/go.mod h1:ro5QHeQkgMS7ZGpvf4tSMx6bBOgPfE+f52KwvXfScaU= -k8s.io/apiserver v0.20.4/go.mod h1:Mc80thBKOyy7tbvFtB4kJv1kbdD0eIH8k8vianJcbFM= -k8s.io/apiserver v0.20.6/go.mod h1:QIJXNt6i6JB+0YQRNcS0hdRHJlMhflFmsBDeSgT1r8Q= -k8s.io/client-go v0.20.1/go.mod h1:/zcHdt1TeWSd5HoUe6elJmHSQ6uLLgp4bIJHVEuy+/Y= -k8s.io/client-go v0.20.4/go.mod h1:LiMv25ND1gLUdBeYxBIwKpkSC5IsozMMmOOeSJboP+k= -k8s.io/client-go v0.20.6/go.mod h1:nNQMnOvEUEsOzRRFIIkdmYOjAZrC8bgq0ExboWSU1I0= -k8s.io/client-go v9.0.0+incompatible/go.mod h1:7vJpHMYJwNQCWgzmNV+VYUl1zCObLyodBc8nIyt8L5s= -k8s.io/component-base v0.20.1/go.mod h1:guxkoJnNoh8LNrbtiQOlyp2Y2XFCZQmrcg2n/DeYNLk= -k8s.io/component-base v0.20.4/go.mod h1:t4p9EdiagbVCJKrQ1RsA5/V4rFQNDfRlevJajlGwgjI= -k8s.io/component-base v0.20.6/go.mod h1:6f1MPBAeI+mvuts3sIdtpjljHWBQ2cIy38oBIWMYnrM= -k8s.io/cri-api v0.17.3/go.mod h1:X1sbHmuXhwaHs9xxYffLqJogVsnI+f6cPRcgPel7ywM= -k8s.io/cri-api v0.20.1/go.mod h1:2JRbKt+BFLTjtrILYVqQK5jqhI+XNdF6UiGMgczeBCI= -k8s.io/cri-api v0.20.4/go.mod h1:2JRbKt+BFLTjtrILYVqQK5jqhI+XNdF6UiGMgczeBCI= -k8s.io/cri-api v0.20.6/go.mod h1:ew44AjNXwyn1s0U4xCKGodU7J1HzBeZ1MpGrpa5r8Yc= -k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= -k8s.io/klog v0.1.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= -k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= -k8s.io/klog/v2 v2.4.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= -k8s.io/kube-openapi v0.0.0-20201113171705-d219536bb9fd/go.mod h1:WOJ3KddDSol4tAGcJo0Tvi+dK12EcqSLqcWsryKMpfM= -k8s.io/kubernetes v1.13.0/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk= -k8s.io/utils v0.0.0-20201110183641-67b214c5f920/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= -rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= -rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= -rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= -sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.14/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg= -sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.15/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg= -sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= -sigs.k8s.io/structured-merge-diff/v4 v4.0.3/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= -sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= -sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= diff --git a/.bingo/golangci-lint.mod b/.bingo/golangci-lint.mod index 51153505bf1f1..dcc77d97b9cb1 100644 --- a/.bingo/golangci-lint.mod +++ b/.bingo/golangci-lint.mod @@ -2,173 +2,4 @@ module _ // Auto generated by https://github.com/bwplotka/bingo. DO NOT EDIT go 1.19 -require github.com/golangci/golangci-lint v1.49.0 // cmd/golangci-lint - -require ( - 4d63.com/gochecknoglobals v0.1.0 // indirect - github.com/Antonboom/errname v0.1.7 // indirect - github.com/Antonboom/nilnil v0.1.1 // indirect - github.com/BurntSushi/toml v1.2.0 // indirect - github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24 // indirect - github.com/GaijinEntertainment/go-exhaustruct/v2 v2.3.0 // indirect - github.com/Masterminds/semver v1.5.0 // indirect - github.com/OpenPeeDeeP/depguard v1.1.0 // indirect - github.com/alexkohler/prealloc v1.0.0 // indirect - github.com/alingse/asasalint v0.0.11 // indirect - github.com/ashanbrown/forbidigo v1.3.0 // indirect - github.com/ashanbrown/makezero v1.1.1 // indirect - github.com/beorn7/perks v1.0.1 // indirect - github.com/bkielbasa/cyclop v1.2.0 // indirect - github.com/blizzy78/varnamelen v0.8.0 // indirect - github.com/bombsimon/wsl/v3 v3.3.0 // indirect - github.com/breml/bidichk v0.2.3 // indirect - github.com/breml/errchkjson v0.3.0 // indirect - github.com/butuzov/ireturn v0.1.1 // indirect - github.com/cespare/xxhash/v2 v2.1.2 // indirect - github.com/charithe/durationcheck v0.0.9 // indirect - github.com/chavacava/garif v0.0.0-20220630083739-93517212f375 // indirect - github.com/curioswitch/go-reassign v0.1.2 // indirect - github.com/daixiang0/gci v0.6.3 // indirect - github.com/davecgh/go-spew v1.1.1 // indirect - github.com/denis-tingaikin/go-header v0.4.3 // indirect - github.com/esimonov/ifshort v1.0.4 // indirect - github.com/ettle/strcase v0.1.1 // indirect - github.com/fatih/color v1.13.0 // indirect - github.com/fatih/structtag v1.2.0 // indirect - github.com/firefart/nonamedreturns v1.0.4 // indirect - github.com/fsnotify/fsnotify v1.5.4 // indirect - github.com/fzipp/gocyclo v0.6.0 // indirect - github.com/go-critic/go-critic v0.6.4 // indirect - github.com/go-toolsmith/astcast v1.0.0 // indirect - github.com/go-toolsmith/astcopy v1.0.1 // indirect - github.com/go-toolsmith/astequal v1.0.2 // indirect - github.com/go-toolsmith/astfmt v1.0.0 // indirect - github.com/go-toolsmith/astp v1.0.0 // indirect - github.com/go-toolsmith/strparse v1.0.0 // indirect - github.com/go-toolsmith/typep v1.0.2 // indirect - github.com/go-xmlfmt/xmlfmt v0.0.0-20191208150333-d5b6f63a941b // indirect - github.com/gobwas/glob v0.2.3 // indirect - github.com/gofrs/flock v0.8.1 // indirect - github.com/golang/protobuf v1.5.2 // indirect - github.com/golangci/check v0.0.0-20180506172741-cfe4005ccda2 // indirect - github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a // indirect - github.com/golangci/go-misc v0.0.0-20220329215616-d24fe342adfe // indirect - github.com/golangci/gofmt v0.0.0-20190930125516-244bba706f1a // indirect - github.com/golangci/lint-1 v0.0.0-20191013205115-297bf364a8e0 // indirect - github.com/golangci/maligned v0.0.0-20180506175553-b1d89398deca // indirect - github.com/golangci/misspell v0.3.5 // indirect - github.com/golangci/revgrep v0.0.0-20220804021717-745bb2f7c2e6 // indirect - github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4 // indirect - github.com/google/go-cmp v0.5.8 // indirect - github.com/gordonklaus/ineffassign v0.0.0-20210914165742-4cc7213b9bc8 // indirect - github.com/gostaticanalysis/analysisutil v0.7.1 // indirect - github.com/gostaticanalysis/comment v1.4.2 // indirect - github.com/gostaticanalysis/forcetypeassert v0.1.0 // indirect - github.com/gostaticanalysis/nilerr v0.1.1 // indirect - github.com/hashicorp/errwrap v1.0.0 // indirect - github.com/hashicorp/go-multierror v1.1.1 // indirect - github.com/hashicorp/go-version v1.6.0 // indirect - github.com/hashicorp/hcl v1.0.0 // indirect - github.com/hexops/gotextdiff v1.0.3 // indirect - github.com/inconshreveable/mousetrap v1.0.0 // indirect - github.com/jgautheron/goconst v1.5.1 // indirect - github.com/jingyugao/rowserrcheck v1.1.1 // indirect - github.com/jirfag/go-printf-func-name v0.0.0-20200119135958-7558a9eaa5af // indirect - github.com/julz/importas v0.1.0 // indirect - github.com/kisielk/errcheck v1.6.2 // indirect - github.com/kisielk/gotool v1.0.0 // indirect - github.com/kulti/thelper v0.6.3 // indirect - github.com/kunwardeep/paralleltest v1.0.6 // indirect - github.com/kyoh86/exportloopref v0.1.8 // indirect - github.com/ldez/gomoddirectives v0.2.3 // indirect - github.com/ldez/tagliatelle v0.3.1 // indirect - github.com/leonklingele/grouper v1.1.0 // indirect - github.com/lufeee/execinquery v1.2.1 // indirect - github.com/magiconair/properties v1.8.6 // indirect - github.com/maratori/testpackage v1.1.0 // indirect - github.com/matoous/godox v0.0.0-20210227103229-6504466cf951 // indirect - github.com/mattn/go-colorable v0.1.13 // indirect - github.com/mattn/go-isatty v0.0.16 // indirect - github.com/mattn/go-runewidth v0.0.9 // indirect - github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect - github.com/mbilski/exhaustivestruct v1.2.0 // indirect - github.com/mgechev/revive v1.2.3 // indirect - github.com/mitchellh/go-homedir v1.1.0 // indirect - github.com/mitchellh/mapstructure v1.5.0 // indirect - github.com/moricho/tparallel v0.2.1 // indirect - github.com/nakabonne/nestif v0.3.1 // indirect - github.com/nbutton23/zxcvbn-go v0.0.0-20210217022336-fa2cb2858354 // indirect - github.com/nishanths/exhaustive v0.8.1 // indirect - github.com/nishanths/predeclared v0.2.2 // indirect - github.com/olekukonko/tablewriter v0.0.5 // indirect - github.com/pelletier/go-toml v1.9.5 // indirect - github.com/pelletier/go-toml/v2 v2.0.2 // indirect - github.com/phayes/checkstyle v0.0.0-20170904204023-bfd46e6a821d // indirect - github.com/pkg/errors v0.9.1 // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/polyfloyd/go-errorlint v1.0.2 // indirect - github.com/prometheus/client_golang v1.12.1 // indirect - github.com/prometheus/client_model v0.2.0 // indirect - github.com/prometheus/common v0.32.1 // indirect - github.com/prometheus/procfs v0.7.3 // indirect - github.com/quasilyte/go-ruleguard v0.3.17 // indirect - github.com/quasilyte/gogrep v0.0.0-20220120141003-628d8b3623b5 // indirect - github.com/quasilyte/regex/syntax v0.0.0-20200407221936-30656e2c4a95 // indirect - github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567 // indirect - github.com/ryancurrah/gomodguard v1.2.4 // indirect - github.com/ryanrolds/sqlclosecheck v0.3.0 // indirect - github.com/sanposhiho/wastedassign/v2 v2.0.6 // indirect - github.com/sashamelentyev/interfacebloat v1.1.0 // indirect - github.com/sashamelentyev/usestdlibvars v1.13.0 // indirect - github.com/securego/gosec/v2 v2.13.1 // indirect - github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c // indirect - github.com/sirupsen/logrus v1.9.0 // indirect - github.com/sivchari/containedctx v1.0.2 // indirect - github.com/sivchari/nosnakecase v1.7.0 // indirect - github.com/sivchari/tenv v1.7.0 // indirect - github.com/sonatard/noctx v0.0.1 // indirect - github.com/sourcegraph/go-diff v0.6.1 // indirect - github.com/spf13/afero v1.8.2 // indirect - github.com/spf13/cast v1.5.0 // indirect - github.com/spf13/cobra v1.5.0 // indirect - github.com/spf13/jwalterweatherman v1.1.0 // indirect - github.com/spf13/pflag v1.0.5 // indirect - github.com/spf13/viper v1.12.0 // indirect - github.com/ssgreg/nlreturn/v2 v2.2.1 // indirect - github.com/stbenjam/no-sprintf-host-port v0.1.1 // indirect - github.com/stretchr/objx v0.4.0 // indirect - github.com/stretchr/testify v1.8.0 // indirect - github.com/subosito/gotenv v1.4.0 // indirect - github.com/sylvia7788/contextcheck v1.0.6 // indirect - github.com/tdakkota/asciicheck v0.1.1 // indirect - github.com/tetafro/godot v1.4.11 // indirect - github.com/timakin/bodyclose v0.0.0-20210704033933-f49887972144 // indirect - github.com/timonwong/logrlint v0.1.0 // indirect - github.com/tomarrell/wrapcheck/v2 v2.6.2 // indirect - github.com/tommy-muehle/go-mnd/v2 v2.5.0 // indirect - github.com/ultraware/funlen v0.0.3 // indirect - github.com/ultraware/whitespace v0.0.5 // indirect - github.com/uudashr/gocognit v1.0.6 // indirect - github.com/yagipy/maintidx v1.0.0 // indirect - github.com/yeya24/promlinter v0.2.0 // indirect - gitlab.com/bosi/decorder v0.2.3 // indirect - go.uber.org/atomic v1.7.0 // indirect - go.uber.org/multierr v1.6.0 // indirect - go.uber.org/zap v1.17.0 // indirect - golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e // indirect - golang.org/x/exp/typeparams v0.0.0-20220613132600-b0d781184e0d // indirect - golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect - golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 // indirect - golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab // indirect - golang.org/x/text v0.3.7 // indirect - golang.org/x/tools v0.1.12 // indirect - google.golang.org/protobuf v1.28.0 // indirect - gopkg.in/ini.v1 v1.66.6 // indirect - gopkg.in/yaml.v2 v2.4.0 // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect - honnef.co/go/tools v0.3.3 // indirect - mvdan.cc/gofumpt v0.3.1 // indirect - mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed // indirect - mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b // indirect - mvdan.cc/unparam v0.0.0-20220706161116-678bad134442 // indirect -) +require github.com/golangci/golangci-lint v1.51.2 // cmd/golangci-lint diff --git a/.bingo/golangci-lint.sum b/.bingo/golangci-lint.sum deleted file mode 100644 index 87d8925ae53cd..0000000000000 --- a/.bingo/golangci-lint.sum +++ /dev/null @@ -1,943 +0,0 @@ -4d63.com/gochecknoglobals v0.1.0 h1:zeZSRqj5yCg28tCkIV/z/lWbwvNm5qnKVS15PI8nhD0= -4d63.com/gochecknoglobals v0.1.0/go.mod h1:wfdC5ZjKSPr7CybKEcgJhUOgeAQW1+7WcyK8OvUilfo= -cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= -cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= -cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= -cloud.google.com/go v0.44.3/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= -cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= -cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= -cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= -cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= -cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= -cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= -cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= -cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= -cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= -cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= -cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= -cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= -cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY= -cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= -cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= -cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= -cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= -cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= -cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= -cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= -cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= -cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= -cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= -cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= -cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= -cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= -cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= -cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= -cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= -cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= -cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= -dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -github.com/Antonboom/errname v0.1.7 h1:mBBDKvEYwPl4WFFNwec1CZO096G6vzK9vvDQzAwkako= -github.com/Antonboom/errname v0.1.7/go.mod h1:g0ONh16msHIPgJSGsecu1G/dcF2hlYR/0SddnIAGavU= -github.com/Antonboom/nilnil v0.1.1 h1:PHhrh5ANKFWRBh7TdYmyyq2gyT2lotnvFvvFbylF81Q= -github.com/Antonboom/nilnil v0.1.1/go.mod h1:L1jBqoWM7AOeTD+tSquifKSesRHs4ZdaxvZR+xdJEaI= -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/toml v1.2.0 h1:Rt8g24XnyGTyglgET/PRUNlrUeu9F5L+7FilkXfZgs0= -github.com/BurntSushi/toml v1.2.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= -github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24 h1:sHglBQTwgx+rWPdisA5ynNEsoARbiCBOyGcJM4/OzsM= -github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24/go.mod h1:4UJr5HIiMZrwgkSPdsjy2uOQExX/WEILpIrO9UPGuXs= -github.com/GaijinEntertainment/go-exhaustruct/v2 v2.3.0 h1:+r1rSv4gvYn0wmRjC8X7IAzX8QezqtFV9m0MUHFJgts= -github.com/GaijinEntertainment/go-exhaustruct/v2 v2.3.0/go.mod h1:b3g59n2Y+T5xmcxJL+UEG2f8cQploZm1mR/v6BW0mU0= -github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww= -github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= -github.com/OpenPeeDeeP/depguard v1.1.0 h1:pjK9nLPS1FwQYGGpPxoMYpe7qACHOhAWQMQzV71i49o= -github.com/OpenPeeDeeP/depguard v1.1.0/go.mod h1:JtAMzWkmFEzDPyAd+W0NHl1lvpQKTvT9jnRVsohBKpc= -github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= -github.com/alexkohler/prealloc v1.0.0 h1:Hbq0/3fJPQhNkN0dR95AVrr6R7tou91y0uHG5pOcUuw= -github.com/alexkohler/prealloc v1.0.0/go.mod h1:VetnK3dIgFBBKmg0YnD9F9x6Icjd+9cvfHR56wJVlKE= -github.com/alingse/asasalint v0.0.11 h1:SFwnQXJ49Kx/1GghOFz1XGqHYKp21Kq1nHad/0WQRnw= -github.com/alingse/asasalint v0.0.11/go.mod h1:nCaoMhw7a9kSJObvQyVzNTPBDbNpdocqrSP7t/cW5+I= -github.com/ashanbrown/forbidigo v1.3.0 h1:VkYIwb/xxdireGAdJNZoo24O4lmnEWkactplBlWTShc= -github.com/ashanbrown/forbidigo v1.3.0/go.mod h1:vVW7PEdqEFqapJe95xHkTfB1+XvZXBFg8t0sG2FIxmI= -github.com/ashanbrown/makezero v1.1.1 h1:iCQ87C0V0vSyO+M9E/FZYbu65auqH0lnsOkf5FcB28s= -github.com/ashanbrown/makezero v1.1.1/go.mod h1:i1bJLCRSCHOcOa9Y6MyF2FTfMZMFdHvxKHxgO5Z1axI= -github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= -github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= -github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= -github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/bkielbasa/cyclop v1.2.0 h1:7Jmnh0yL2DjKfw28p86YTd/B4lRGcNuu12sKE35sM7A= -github.com/bkielbasa/cyclop v1.2.0/go.mod h1:qOI0yy6A7dYC4Zgsa72Ppm9kONl0RoIlPbzot9mhmeI= -github.com/blizzy78/varnamelen v0.8.0 h1:oqSblyuQvFsW1hbBHh1zfwrKe3kcSj0rnXkKzsQ089M= -github.com/blizzy78/varnamelen v0.8.0/go.mod h1:V9TzQZ4fLJ1DSrjVDfl89H7aMnTvKkApdHeyESmyR7k= -github.com/bombsimon/wsl/v3 v3.3.0 h1:Mka/+kRLoQJq7g2rggtgQsjuI/K5Efd87WX96EWFxjM= -github.com/bombsimon/wsl/v3 v3.3.0/go.mod h1:st10JtZYLE4D5sC7b8xV4zTKZwAQjCH/Hy2Pm1FNZIc= -github.com/breml/bidichk v0.2.3 h1:qe6ggxpTfA8E75hdjWPZ581sY3a2lnl0IRxLQFelECI= -github.com/breml/bidichk v0.2.3/go.mod h1:8u2C6DnAy0g2cEq+k/A2+tr9O1s+vHGxWn0LTc70T2A= -github.com/breml/errchkjson v0.3.0 h1:YdDqhfqMT+I1vIxPSas44P+9Z9HzJwCeAzjB8PxP1xw= -github.com/breml/errchkjson v0.3.0/go.mod h1:9Cogkyv9gcT8HREpzi3TiqBxCqDzo8awa92zSDFcofU= -github.com/butuzov/ireturn v0.1.1 h1:QvrO2QF2+/Cx1WA/vETCIYBKtRjc30vesdoPUNo1EbY= -github.com/butuzov/ireturn v0.1.1/go.mod h1:Wh6Zl3IMtTpaIKbmwzqi6olnM9ptYQxxVacMsOEFPoc= -github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= -github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/charithe/durationcheck v0.0.9 h1:mPP4ucLrf/rKZiIG/a9IPXHGlh8p4CzgpyTy6EEutYk= -github.com/charithe/durationcheck v0.0.9/go.mod h1:SSbRIBVfMjCi/kEB6K65XEA83D6prSM8ap1UCpNKtgg= -github.com/chavacava/garif v0.0.0-20220630083739-93517212f375 h1:E7LT642ysztPWE0dfz43cWOvMiF42DyTRC+eZIaO4yI= -github.com/chavacava/garif v0.0.0-20220630083739-93517212f375/go.mod h1:4m1Rv7xfuwWPNKXlThldNuJvutYM6J95wNuuVmn55To= -github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= -github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= -github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= -github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/cristalhq/acmd v0.7.0/go.mod h1:LG5oa43pE/BbxtfMoImHCQN++0Su7dzipdgBjMCBVDQ= -github.com/curioswitch/go-reassign v0.1.2 h1:ekM07+z+VFT560Exz4mTv0/s1yU9gem6CJc/tlYpkmI= -github.com/curioswitch/go-reassign v0.1.2/go.mod h1:bFJIHgtTM3hRm2sKXSPkbwNjSFyGURQXyn4IXD2qwfQ= -github.com/daixiang0/gci v0.6.3 h1:wUAqXChk8HbwXn8AfxD9DYSCp9Bpz1L3e6Q4Roe+q9E= -github.com/daixiang0/gci v0.6.3/go.mod h1:EpVfrztufwVgQRXjnX4zuNinEpLj5OmMjtu/+MB0V0c= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/denis-tingaikin/go-header v0.4.3 h1:tEaZKAlqql6SKCY++utLmkPLd6K8IBM20Ha7UVm+mtU= -github.com/denis-tingaikin/go-header v0.4.3/go.mod h1:0wOCWuN71D5qIgE2nz9KrKmuYBAC2Mra5RassOIQ2/c= -github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= -github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= -github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/esimonov/ifshort v1.0.4 h1:6SID4yGWfRae/M7hkVDVVyppy8q/v9OuxNdmjLQStBA= -github.com/esimonov/ifshort v1.0.4/go.mod h1:Pe8zjlRrJ80+q2CxHLfEOfTwxCZ4O+MuhcHcfgNWTk0= -github.com/ettle/strcase v0.1.1 h1:htFueZyVeE1XNnMEfbqp5r67qAN/4r6ya1ysq8Q+Zcw= -github.com/ettle/strcase v0.1.1/go.mod h1:hzDLsPC7/lwKyBOywSHEP89nt2pDgdy+No1NBA9o9VY= -github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= -github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= -github.com/fatih/structtag v1.2.0 h1:/OdNE99OxoI/PqaW/SuSK9uxxT3f/tcSZgon/ssNSx4= -github.com/fatih/structtag v1.2.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4/aAZl94= -github.com/firefart/nonamedreturns v1.0.4 h1:abzI1p7mAEPYuR4A+VLKn4eNDOycjYo2phmY9sfv40Y= -github.com/firefart/nonamedreturns v1.0.4/go.mod h1:TDhe/tjI1BXo48CmYbUduTV7BdIga8MAO/xbKdcVsGI= -github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI= -github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= -github.com/fzipp/gocyclo v0.6.0 h1:lsblElZG7d3ALtGMx9fmxeTKZaLLpU8mET09yN4BBLo= -github.com/fzipp/gocyclo v0.6.0/go.mod h1:rXPyn8fnlpa0R2csP/31uerbiVBugk5whMdlyaLkLoA= -github.com/go-critic/go-critic v0.6.4 h1:tucuG1pvOyYgpBIrVxw0R6gwO42lNa92Aq3VaDoIs+E= -github.com/go-critic/go-critic v0.6.4/go.mod h1:qL5SOlk7NtY6sJPoVCTKDIgzNOxHkkkOCVDyi9wJe1U= -github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= -github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= -github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= -github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= -github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= -github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/go-toolsmith/astcast v1.0.0 h1:JojxlmI6STnFVG9yOImLeGREv8W2ocNUM+iOhR6jE7g= -github.com/go-toolsmith/astcast v1.0.0/go.mod h1:mt2OdQTeAQcY4DQgPSArJjHCcOwlX+Wl/kwN+LbLGQ4= -github.com/go-toolsmith/astcopy v1.0.0/go.mod h1:vrgyG+5Bxrnz4MZWPF+pI4R8h3qKRjjyvV/DSez4WVQ= -github.com/go-toolsmith/astcopy v1.0.1 h1:l09oBhAPyV74kLJ3ZO31iBU8htZGTwr9LTjuMCyL8go= -github.com/go-toolsmith/astcopy v1.0.1/go.mod h1:4TcEdbElGc9twQEYpVo/aieIXfHhiuLh4aLAck6dO7Y= -github.com/go-toolsmith/astequal v1.0.0/go.mod h1:H+xSiq0+LtiDC11+h1G32h7Of5O3CYFJ99GVbS5lDKY= -github.com/go-toolsmith/astequal v1.0.1/go.mod h1:4oGA3EZXTVItV/ipGiOx7NWkY5veFfcsOJVS2YxltLw= -github.com/go-toolsmith/astequal v1.0.2 h1:+XvaV8zNxua+9+Oa4AHmgmpo4RYAbwr/qjNppLfX2yM= -github.com/go-toolsmith/astequal v1.0.2/go.mod h1:9Ai4UglvtR+4up+bAD4+hCj7iTo4m/OXVTSLnCyTAx4= -github.com/go-toolsmith/astfmt v1.0.0 h1:A0vDDXt+vsvLEdbMFJAUBI/uTbRw1ffOPnxsILnFL6k= -github.com/go-toolsmith/astfmt v1.0.0/go.mod h1:cnWmsOAuq4jJY6Ct5YWlVLmcmLMn1JUPuQIHCY7CJDw= -github.com/go-toolsmith/astp v1.0.0 h1:alXE75TXgcmupDsMK1fRAy0YUzLzqPVvBKoyWV+KPXg= -github.com/go-toolsmith/astp v1.0.0/go.mod h1:RSyrtpVlfTFGDYRbrjyWP1pYu//tSFcvdYrA8meBmLI= -github.com/go-toolsmith/pkgload v1.0.2-0.20220101231613-e814995d17c5/go.mod h1:3NAwwmD4uY/yggRxoEjk/S00MIV3A+H7rrE3i87eYxM= -github.com/go-toolsmith/strparse v1.0.0 h1:Vcw78DnpCAKlM20kSbAyO4mPfJn/lyYA4BJUDxe2Jb4= -github.com/go-toolsmith/strparse v1.0.0/go.mod h1:YI2nUKP9YGZnL/L1/DLFBfixrcjslWct4wyljWhSRy8= -github.com/go-toolsmith/typep v1.0.2 h1:8xdsa1+FSIH/RhEkgnD1j2CJOy5mNllW1Q9tRiYwvlk= -github.com/go-toolsmith/typep v1.0.2/go.mod h1:JSQCQMUPdRlMZFswiq3TGpNp1GMktqkR2Ns5AIQkATU= -github.com/go-xmlfmt/xmlfmt v0.0.0-20191208150333-d5b6f63a941b h1:khEcpUM4yFcxg4/FHQWkvVRmgijNXRfzkIDHh23ggEo= -github.com/go-xmlfmt/xmlfmt v0.0.0-20191208150333-d5b6f63a941b/go.mod h1:aUCEOzzezBEjDBbFBoSiya/gduyIiWYRP6CnSFIV8AM= -github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= -github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= -github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= -github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= -github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= -github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= -github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= -github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= -github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= -github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= -github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= -github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= -github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golangci/check v0.0.0-20180506172741-cfe4005ccda2 h1:23T5iq8rbUYlhpt5DB4XJkc6BU31uODLD1o1gKvZmD0= -github.com/golangci/check v0.0.0-20180506172741-cfe4005ccda2/go.mod h1:k9Qvh+8juN+UKMCS/3jFtGICgW8O96FVaZsaxdzDkR4= -github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a h1:w8hkcTqaFpzKqonE9uMCefW1WDie15eSP/4MssdenaM= -github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a/go.mod h1:ryS0uhF+x9jgbj/N71xsEqODy9BN81/GonCZiOzirOk= -github.com/golangci/go-misc v0.0.0-20220329215616-d24fe342adfe h1:6RGUuS7EGotKx6J5HIP8ZtyMdiDscjMLfRBSPuzVVeo= -github.com/golangci/go-misc v0.0.0-20220329215616-d24fe342adfe/go.mod h1:gjqyPShc/m8pEMpk0a3SeagVb0kaqvhscv+i9jI5ZhQ= -github.com/golangci/gofmt v0.0.0-20190930125516-244bba706f1a h1:iR3fYXUjHCR97qWS8ch1y9zPNsgXThGwjKPrYfqMPks= -github.com/golangci/gofmt v0.0.0-20190930125516-244bba706f1a/go.mod h1:9qCChq59u/eW8im404Q2WWTrnBUQKjpNYKMbU4M7EFU= -github.com/golangci/golangci-lint v1.49.0 h1:I8WHOavragDttlLHtSraHn/h39C+R60bEQ5NoGcHQr8= -github.com/golangci/golangci-lint v1.49.0/go.mod h1:+V/7lLv449R6w9mQ3WdV0EKh7Je/jTylMeSwBZcLeWE= -github.com/golangci/lint-1 v0.0.0-20191013205115-297bf364a8e0 h1:MfyDlzVjl1hoaPzPD4Gpb/QgoRfSBR0jdhwGyAWwMSA= -github.com/golangci/lint-1 v0.0.0-20191013205115-297bf364a8e0/go.mod h1:66R6K6P6VWk9I95jvqGxkqJxVWGFy9XlDwLwVz1RCFg= -github.com/golangci/maligned v0.0.0-20180506175553-b1d89398deca h1:kNY3/svz5T29MYHubXix4aDDuE3RWHkPvopM/EDv/MA= -github.com/golangci/maligned v0.0.0-20180506175553-b1d89398deca/go.mod h1:tvlJhZqDe4LMs4ZHD0oMUlt9G2LWuDGoisJTBzLMV9o= -github.com/golangci/misspell v0.3.5 h1:pLzmVdl3VxTOncgzHcvLOKirdvcx/TydsClUQXTehjo= -github.com/golangci/misspell v0.3.5/go.mod h1:dEbvlSfYbMQDtrpRMQU675gSDLDNa8sCPPChZ7PhiVA= -github.com/golangci/revgrep v0.0.0-20220804021717-745bb2f7c2e6 h1:DIPQnGy2Gv2FSA4B/hh8Q7xx3B7AIDk3DAMeHclH1vQ= -github.com/golangci/revgrep v0.0.0-20220804021717-745bb2f7c2e6/go.mod h1:0AKcRCkMoKvUvlf89F6O7H2LYdhr1zBh736mBItOdRs= -github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4 h1:zwtduBRr5SSWhqsYNgcuWO2kFlpdOZbP0+yRjmvPGys= -github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4/go.mod h1:Izgrg8RkN3rCIMLGE9CyYmU9pY2Jer6DgANEnZ/L/cQ= -github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= -github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= -github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= -github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= -github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= -github.com/gordonklaus/ineffassign v0.0.0-20210914165742-4cc7213b9bc8 h1:PVRE9d4AQKmbelZ7emNig1+NT27DUmKZn5qXxfio54U= -github.com/gordonklaus/ineffassign v0.0.0-20210914165742-4cc7213b9bc8/go.mod h1:Qcp2HIAYhR7mNUVSIxZww3Guk4it82ghYcEXIAk+QT0= -github.com/gostaticanalysis/analysisutil v0.0.0-20190318220348-4088753ea4d3/go.mod h1:eEOZF4jCKGi+aprrirO9e7WKB3beBRtWgqGunKl6pKE= -github.com/gostaticanalysis/analysisutil v0.0.3/go.mod h1:eEOZF4jCKGi+aprrirO9e7WKB3beBRtWgqGunKl6pKE= -github.com/gostaticanalysis/analysisutil v0.1.0/go.mod h1:dMhHRU9KTiDcuLGdy87/2gTR8WruwYZrKdRq9m1O6uw= -github.com/gostaticanalysis/analysisutil v0.7.1 h1:ZMCjoue3DtDWQ5WyU16YbjbQEQ3VuzwxALrpYd+HeKk= -github.com/gostaticanalysis/analysisutil v0.7.1/go.mod h1:v21E3hY37WKMGSnbsw2S/ojApNWb6C1//mXO48CXbVc= -github.com/gostaticanalysis/comment v1.3.0/go.mod h1:xMicKDx7XRXYdVwY9f9wQpDJVnqWxw9wCauCMKp+IBI= -github.com/gostaticanalysis/comment v1.4.1/go.mod h1:ih6ZxzTHLdadaiSnF5WY3dxUoXfXAlTaRzuaNDlSado= -github.com/gostaticanalysis/comment v1.4.2 h1:hlnx5+S2fY9Zo9ePo4AhgYsYHbM2+eAv8m/s1JiCd6Q= -github.com/gostaticanalysis/comment v1.4.2/go.mod h1:KLUTGDv6HOCotCH8h2erHKmpci2ZoR8VPu34YA2uzdM= -github.com/gostaticanalysis/forcetypeassert v0.1.0 h1:6eUflI3DiGusXGK6X7cCcIgVCpZ2CiZ1Q7jl6ZxNV70= -github.com/gostaticanalysis/forcetypeassert v0.1.0/go.mod h1:qZEedyP/sY1lTGV1uJ3VhWZ2mqag3IkWsDHVbplHXak= -github.com/gostaticanalysis/nilerr v0.1.1 h1:ThE+hJP0fEp4zWLkWHWcRyI2Od0p7DlgYG3Uqrmrcpk= -github.com/gostaticanalysis/nilerr v0.1.1/go.mod h1:wZYb6YI5YAxxq0i1+VJbY0s2YONW0HU0GPE3+5PWN4A= -github.com/gostaticanalysis/testutil v0.3.1-0.20210208050101-bfb5c8eec0e4/go.mod h1:D+FIZ+7OahH3ePw/izIEeH5I06eKs1IKI4Xr64/Am3M= -github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= -github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= -github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= -github.com/hashicorp/go-version v1.2.1/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= -github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek= -github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= -github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= -github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= -github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM= -github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg= -github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= -github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= -github.com/jgautheron/goconst v1.5.1 h1:HxVbL1MhydKs8R8n/HE5NPvzfaYmQJA3o879lE4+WcM= -github.com/jgautheron/goconst v1.5.1/go.mod h1:aAosetZ5zaeC/2EfMeRswtxUFBpe2Hr7HzkgX4fanO4= -github.com/jingyugao/rowserrcheck v1.1.1 h1:zibz55j/MJtLsjP1OF4bSdgXxwL1b+Vn7Tjzq7gFzUs= -github.com/jingyugao/rowserrcheck v1.1.1/go.mod h1:4yvlZSDb3IyDTUZJUmpZfm2Hwok+Dtp+nu2qOq+er9c= -github.com/jirfag/go-printf-func-name v0.0.0-20200119135958-7558a9eaa5af h1:KA9BjwUk7KlCh6S9EAGWBt1oExIUv9WyNCiRz5amv48= -github.com/jirfag/go-printf-func-name v0.0.0-20200119135958-7558a9eaa5af/go.mod h1:HEWGJkRDzjJY2sqdDwxccsGicWEf9BQOZsq2tV+xzM0= -github.com/jmoiron/sqlx v1.2.0/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhBSsks= -github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= -github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= -github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= -github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= -github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= -github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= -github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= -github.com/julz/importas v0.1.0 h1:F78HnrsjY3cR7j0etXy5+TU1Zuy7Xt08X/1aJnH5xXY= -github.com/julz/importas v0.1.0/go.mod h1:oSFU2R4XK/P7kNBrnL/FEQlDGN1/6WoxXEjSSXO0DV0= -github.com/kisielk/errcheck v1.6.2 h1:uGQ9xI8/pgc9iOoCe7kWQgRE6SBTrCGmTSf0LrEtY7c= -github.com/kisielk/errcheck v1.6.2/go.mod h1:nXw/i/MfnvRHqXa7XXmQMUB0oNFGuBrNI8d8NLy0LPw= -github.com/kisielk/gotool v1.0.0 h1:AV2c/EiW3KqPNT9ZKl07ehoAGi4C5/01Cfbblndcapg= -github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= -github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/kulti/thelper v0.6.3 h1:ElhKf+AlItIu+xGnI990no4cE2+XaSu1ULymV2Yulxs= -github.com/kulti/thelper v0.6.3/go.mod h1:DsqKShOvP40epevkFrvIwkCMNYxMeTNjdWL4dqWHZ6I= -github.com/kunwardeep/paralleltest v1.0.6 h1:FCKYMF1OF2+RveWlABsdnmsvJrei5aoyZoaGS+Ugg8g= -github.com/kunwardeep/paralleltest v1.0.6/go.mod h1:Y0Y0XISdZM5IKm3TREQMZ6iteqn1YuwCsJO/0kL9Zes= -github.com/kyoh86/exportloopref v0.1.8 h1:5Ry/at+eFdkX9Vsdw3qU4YkvGtzuVfzT4X7S77LoN/M= -github.com/kyoh86/exportloopref v0.1.8/go.mod h1:1tUcJeiioIs7VWe5gcOObrux3lb66+sBqGZrRkMwPgg= -github.com/ldez/gomoddirectives v0.2.3 h1:y7MBaisZVDYmKvt9/l1mjNCiSA1BVn34U0ObUcJwlhA= -github.com/ldez/gomoddirectives v0.2.3/go.mod h1:cpgBogWITnCfRq2qGoDkKMEVSaarhdBr6g8G04uz6d0= -github.com/ldez/tagliatelle v0.3.1 h1:3BqVVlReVUZwafJUwQ+oxbx2BEX2vUG4Yu/NOfMiKiM= -github.com/ldez/tagliatelle v0.3.1/go.mod h1:8s6WJQwEYHbKZDsp/LjArytKOG8qaMrKQQ3mFukHs88= -github.com/leonklingele/grouper v1.1.0 h1:tC2y/ygPbMFSBOs3DcyaEMKnnwH7eYKzohOtRrf0SAg= -github.com/leonklingele/grouper v1.1.0/go.mod h1:uk3I3uDfi9B6PeUjsCKi6ndcf63Uy7snXgR4yDYQVDY= -github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= -github.com/lufeee/execinquery v1.2.1 h1:hf0Ems4SHcUGBxpGN7Jz78z1ppVkP/837ZlETPCEtOM= -github.com/lufeee/execinquery v1.2.1/go.mod h1:EC7DrEKView09ocscGHC+apXMIaorh4xqSxS/dy8SbM= -github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamhfG/Qzo= -github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= -github.com/maratori/testpackage v1.1.0 h1:GJY4wlzQhuBusMF1oahQCBtUV/AQ/k69IZ68vxaac2Q= -github.com/maratori/testpackage v1.1.0/go.mod h1:PeAhzU8qkCwdGEMTEupsHJNlQu2gZopMC6RjbhmHeDc= -github.com/matoous/godox v0.0.0-20210227103229-6504466cf951 h1:pWxk9e//NbPwfxat7RXkts09K+dEBJWakUWwICVqYbA= -github.com/matoous/godox v0.0.0-20210227103229-6504466cf951/go.mod h1:1BELzlh859Sh1c6+90blK8lbYy0kwQf1bYlBhBysy1s= -github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU= -github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= -github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= -github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= -github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= -github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ= -github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= -github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= -github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= -github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= -github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/mbilski/exhaustivestruct v1.2.0 h1:wCBmUnSYufAHO6J4AVWY6ff+oxWxsVFrwgOdMUQePUo= -github.com/mbilski/exhaustivestruct v1.2.0/go.mod h1:OeTBVxQWoEmB2J2JCHmXWPJ0aksxSUOUy+nvtVEfzXc= -github.com/mgechev/revive v1.2.3 h1:NzIEEa9+WimQ6q2Ov7OcNeySS/IOcwtkQ8RAh0R5UJ4= -github.com/mgechev/revive v1.2.3/go.mod h1:iAWlQishqCuj4yhV24FTnKSXGpbAA+0SckXB8GQMX/Q= -github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= -github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= -github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= -github.com/moricho/tparallel v0.2.1 h1:95FytivzT6rYzdJLdtfn6m1bfFJylOJK41+lgv/EHf4= -github.com/moricho/tparallel v0.2.1/go.mod h1:fXEIZxG2vdfl0ZF8b42f5a78EhjjD5mX8qUplsoSU4k= -github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/nakabonne/nestif v0.3.1 h1:wm28nZjhQY5HyYPx+weN3Q65k6ilSBxDb8v5S81B81U= -github.com/nakabonne/nestif v0.3.1/go.mod h1:9EtoZochLn5iUprVDmDjqGKPofoUEBL8U4Ngq6aY7OE= -github.com/nbutton23/zxcvbn-go v0.0.0-20210217022336-fa2cb2858354 h1:4kuARK6Y6FxaNu/BnU2OAaLF86eTVhP2hjTB6iMvItA= -github.com/nbutton23/zxcvbn-go v0.0.0-20210217022336-fa2cb2858354/go.mod h1:KSVJerMDfblTH7p5MZaTt+8zaT2iEk3AkVb9PQdZuE8= -github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= -github.com/nishanths/exhaustive v0.8.1 h1:0QKNascWv9qIHY7zRoZSxeRr6kuk5aAT3YXLTiDmjTo= -github.com/nishanths/exhaustive v0.8.1/go.mod h1:qj+zJJUgJ76tR92+25+03oYUhzF4R7/2Wk7fGTfCHmg= -github.com/nishanths/predeclared v0.2.2 h1:V2EPdZPliZymNAn79T8RkNApBjMmVKh5XRpLm/w98Vk= -github.com/nishanths/predeclared v0.2.2/go.mod h1:RROzoN6TnGQupbC+lqggsOlcgysk3LMK/HI84Mp280c= -github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= -github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= -github.com/otiai10/copy v1.2.0/go.mod h1:rrF5dJ5F0t/EWSYODDu4j9/vEeYHMkc8jt0zJChqQWw= -github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE= -github.com/otiai10/curr v1.0.0/go.mod h1:LskTG5wDwr8Rs+nNQ+1LlxRjAtTZZjtJW4rMXl6j4vs= -github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT91xUo= -github.com/otiai10/mint v1.3.1/go.mod h1:/yxELlJQ0ufhjUwhshSj+wFjZ78CnZ48/1wtmBH1OTc= -github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= -github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= -github.com/pelletier/go-toml/v2 v2.0.2 h1:+jQXlF3scKIcSEKkdHzXhCTDLPFi5r1wnK6yPS+49Gw= -github.com/pelletier/go-toml/v2 v2.0.2/go.mod h1:MovirKjgVRESsAvNZlAjtFwV867yGuwRkXbG66OzopI= -github.com/phayes/checkstyle v0.0.0-20170904204023-bfd46e6a821d h1:CdDQnGF8Nq9ocOS/xlSptM1N3BbrA6/kmaep5ggwaIA= -github.com/phayes/checkstyle v0.0.0-20170904204023-bfd46e6a821d/go.mod h1:3OzsM7FXDQlpCiw2j81fOmAwQLnZnLGXVKUzeKQXIAw= -github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/polyfloyd/go-errorlint v1.0.2 h1:kp1yvHflYhTmw5m3MmBy8SCyQkKPjwDthVuMH0ug6Yk= -github.com/polyfloyd/go-errorlint v1.0.2/go.mod h1:APVvOesVSAnne5SClsPxPdfvZTVDojXh1/G3qb5wjGI= -github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= -github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= -github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= -github.com/prometheus/client_golang v1.12.1 h1:ZiaPsmm9uiBeaSMRznKsCDNtPCS0T3JVDGF+06gjBzk= -github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= -github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= -github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= -github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= -github.com/prometheus/common v0.32.1 h1:hWIdL3N2HoUx3B8j3YN9mWor0qhY/NlEKZEaXxuIRh4= -github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= -github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= -github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU= -github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/quasilyte/go-ruleguard v0.3.1-0.20210203134552-1b5a410e1cc8/go.mod h1:KsAh3x0e7Fkpgs+Q9pNLS5XpFSvYCEVl5gP9Pp1xp30= -github.com/quasilyte/go-ruleguard v0.3.17 h1:cDdoaSbQg11LXPDQqiCK54QmQXsEQQCTIgdcpeULGSI= -github.com/quasilyte/go-ruleguard v0.3.17/go.mod h1:sST5PvaR7yb/Az5ksX8oc88usJ4EGjmJv7cK7y3jyig= -github.com/quasilyte/go-ruleguard/dsl v0.3.0/go.mod h1:KeCP03KrjuSO0H1kTuZQCWlQPulDV6YMIXmpQss17rU= -github.com/quasilyte/go-ruleguard/dsl v0.3.21/go.mod h1:KeCP03KrjuSO0H1kTuZQCWlQPulDV6YMIXmpQss17rU= -github.com/quasilyte/go-ruleguard/rules v0.0.0-20201231183845-9e62ed36efe1/go.mod h1:7JTjp89EGyU1d6XfBiXihJNG37wB2VRkd125Q1u7Plc= -github.com/quasilyte/go-ruleguard/rules v0.0.0-20211022131956-028d6511ab71/go.mod h1:4cgAphtvu7Ftv7vOT2ZOYhC6CvBxZixcasr8qIOTA50= -github.com/quasilyte/gogrep v0.0.0-20220120141003-628d8b3623b5 h1:PDWGei+Rf2bBiuZIbZmM20J2ftEy9IeUCHA8HbQqed8= -github.com/quasilyte/gogrep v0.0.0-20220120141003-628d8b3623b5/go.mod h1:wSEyW6O61xRV6zb6My3HxrQ5/8ke7NE2OayqCHa3xRM= -github.com/quasilyte/regex/syntax v0.0.0-20200407221936-30656e2c4a95 h1:L8QM9bvf68pVdQ3bCFZMDmnt9yqcMBro1pC7F+IPYMY= -github.com/quasilyte/regex/syntax v0.0.0-20200407221936-30656e2c4a95/go.mod h1:rlzQ04UMyJXu/aOvhd8qT+hvDrFpiwqp8MRXDY9szc0= -github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567 h1:M8mH9eK4OUR4lu7Gd+PU1fV2/qnDNfzT635KRSObncs= -github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567/go.mod h1:DWNGW8A4Y+GyBgPuaQJuWiy0XYftx4Xm/y5Jqk9I6VQ= -github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/ryancurrah/gomodguard v1.2.4 h1:CpMSDKan0LtNGGhPrvupAoLeObRFjND8/tU1rEOtBp4= -github.com/ryancurrah/gomodguard v1.2.4/go.mod h1:+Kem4VjWwvFpUJRJSwa16s1tBJe+vbv02+naTow2f6M= -github.com/ryanrolds/sqlclosecheck v0.3.0 h1:AZx+Bixh8zdUBxUA1NxbxVAS78vTPq4rCb8OUZI9xFw= -github.com/ryanrolds/sqlclosecheck v0.3.0/go.mod h1:1gREqxyTGR3lVtpngyFo3hZAgk0KCtEdgEkHwDbigdA= -github.com/sanposhiho/wastedassign/v2 v2.0.6 h1:+6/hQIHKNJAUixEj6EmOngGIisyeI+T3335lYTyxRoA= -github.com/sanposhiho/wastedassign/v2 v2.0.6/go.mod h1:KyZ0MWTwxxBmfwn33zh3k1dmsbF2ud9pAAGfoLfjhtI= -github.com/sashamelentyev/interfacebloat v1.1.0 h1:xdRdJp0irL086OyW1H/RTZTr1h/tMEOsumirXcOJqAw= -github.com/sashamelentyev/interfacebloat v1.1.0/go.mod h1:+Y9yU5YdTkrNvoX0xHc84dxiN1iBi9+G8zZIhPVoNjQ= -github.com/sashamelentyev/usestdlibvars v1.13.0 h1:uObNudVEEHf6JbOJy5bgKJloA1bWjxR9fwgNFpPzKnI= -github.com/sashamelentyev/usestdlibvars v1.13.0/go.mod h1:D2Wb7niIYmTB+gB8z7kh8tyP5ccof1dQ+SFk+WW5NtY= -github.com/securego/gosec/v2 v2.13.1 h1:7mU32qn2dyC81MH9L2kefnQyRMUarfDER3iQyMHcjYM= -github.com/securego/gosec/v2 v2.13.1/go.mod h1:EO1sImBMBWFjOTFzMWfTRrZW6M15gm60ljzrmy/wtHo= -github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c h1:W65qqJCIOVP4jpqPQ0YvHYKwcMEMVWIzWC5iNQQfBTU= -github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c/go.mod h1:/PevMnwAxekIXwN8qQyfc5gl2NlkB3CQlkizAbOkeBs= -github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= -github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ= -github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= -github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= -github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= -github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= -github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= -github.com/sivchari/containedctx v1.0.2 h1:0hLQKpgC53OVF1VT7CeoFHk9YKstur1XOgfYIc1yrHI= -github.com/sivchari/containedctx v1.0.2/go.mod h1:PwZOeqm4/DLoJOqMSIJs3aKqXRX4YO+uXww087KZ7Bw= -github.com/sivchari/nosnakecase v1.7.0 h1:7QkpWIRMe8x25gckkFd2A5Pi6Ymo0qgr4JrhGt95do8= -github.com/sivchari/nosnakecase v1.7.0/go.mod h1:CwDzrzPea40/GB6uynrNLiorAlgFRvRbFSgJx2Gs+QY= -github.com/sivchari/tenv v1.7.0 h1:d4laZMBK6jpe5PWepxlV9S+LC0yXqvYHiq8E6ceoVVE= -github.com/sivchari/tenv v1.7.0/go.mod h1:64yStXKSOxDfX47NlhVwND4dHwfZDdbp2Lyl018Icvg= -github.com/sonatard/noctx v0.0.1 h1:VC1Qhl6Oxx9vvWo3UDgrGXYCeKCe3Wbw7qAWL6FrmTY= -github.com/sonatard/noctx v0.0.1/go.mod h1:9D2D/EoULe8Yy2joDHJj7bv3sZoq9AaSb8B4lqBjiZI= -github.com/sourcegraph/go-diff v0.6.1 h1:hmA1LzxW0n1c3Q4YbrFgg4P99GSnebYa3x8gr0HZqLQ= -github.com/sourcegraph/go-diff v0.6.1/go.mod h1:iBszgVvyxdc8SFZ7gm69go2KDdt3ag071iBaWPF6cjs= -github.com/spf13/afero v1.8.2 h1:xehSyVa0YnHWsJ49JFljMpg1HX19V6NDZ1fkm1Xznbo= -github.com/spf13/afero v1.8.2/go.mod h1:CtAatgMJh6bJEIs48Ay/FOnkljP3WeGUG0MC1RfAqwo= -github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w= -github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU= -github.com/spf13/cobra v1.5.0 h1:X+jTBEBqF0bHN+9cSMgmfuvv2VHJ9ezmFNf9Y/XstYU= -github.com/spf13/cobra v1.5.0/go.mod h1:dWXEIy2H428czQCjInthrTRUg7yKbok+2Qi/yBIJoUM= -github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= -github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= -github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= -github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/viper v1.12.0 h1:CZ7eSOd3kZoaYDLbXnmzgQI5RlciuXBMA+18HwHRfZQ= -github.com/spf13/viper v1.12.0/go.mod h1:b6COn30jlNxbm/V2IqWiNWkJ+vZNiMNksliPCiuKtSI= -github.com/ssgreg/nlreturn/v2 v2.2.1 h1:X4XDI7jstt3ySqGU86YGAURbxw3oTDPK9sPEi6YEwQ0= -github.com/ssgreg/nlreturn/v2 v2.2.1/go.mod h1:E/iiPB78hV7Szg2YfRgyIrk1AD6JVMTRkkxBiELzh2I= -github.com/stbenjam/no-sprintf-host-port v0.1.1 h1:tYugd/yrm1O0dV+ThCbaKZh195Dfm07ysF0U6JQXczc= -github.com/stbenjam/no-sprintf-host-port v0.1.1/go.mod h1:TLhvtIvONRzdmkFiio4O8LHsN9N74I+PhRquPsxpL0I= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0 h1:M2gUjqZET1qApGOWNSnZ49BAIMX4F/1plDv3+l31EJ4= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/testify v1.1.4/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= -github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/subosito/gotenv v1.4.0 h1:yAzM1+SmVcz5R4tXGsNMu1jUl2aOJXoiWUCEwwnGrvs= -github.com/subosito/gotenv v1.4.0/go.mod h1:mZd6rFysKEcUhUHXJk0C/08wAgyDBFuwEYL7vWWGaGo= -github.com/sylvia7788/contextcheck v1.0.6 h1:o2EZgVPyMKE/Mtoqym61DInKEjwEbsmyoxg3VrmjNO4= -github.com/sylvia7788/contextcheck v1.0.6/go.mod h1:9XDxwvxyuKD+8N+a7Gs7bfWLityh5t70g/GjdEt2N2M= -github.com/tdakkota/asciicheck v0.1.1 h1:PKzG7JUTUmVspQTDqtkX9eSiLGossXTybutHwTXuO0A= -github.com/tdakkota/asciicheck v0.1.1/go.mod h1:yHp0ai0Z9gUljN3o0xMhYJnH/IcvkdTBOX2fmJ93JEM= -github.com/tenntenn/modver v1.0.1/go.mod h1:bePIyQPb7UeioSRkw3Q0XeMhYZSMx9B8ePqg6SAMGH0= -github.com/tenntenn/text/transform v0.0.0-20200319021203-7eef512accb3/go.mod h1:ON8b8w4BN/kE1EOhwT0o+d62W65a6aPw1nouo9LMgyY= -github.com/tetafro/godot v1.4.11 h1:BVoBIqAf/2QdbFmSwAWnaIqDivZdOV0ZRwEm6jivLKw= -github.com/tetafro/godot v1.4.11/go.mod h1:LR3CJpxDVGlYOWn3ZZg1PgNZdTUvzsZWu8xaEohUpn8= -github.com/timakin/bodyclose v0.0.0-20210704033933-f49887972144 h1:kl4KhGNsJIbDHS9/4U9yQo1UcPQM0kOMJHn29EoH/Ro= -github.com/timakin/bodyclose v0.0.0-20210704033933-f49887972144/go.mod h1:Qimiffbc6q9tBWlVV6x0P9sat/ao1xEkREYPPj9hphk= -github.com/timonwong/logrlint v0.1.0 h1:phZCcypL/vtx6cGxObJgWZ5wexZF5SXFPLOM+ru0e/M= -github.com/timonwong/logrlint v0.1.0/go.mod h1:Zleg4Gw+kRxNej+Ra7o+tEaW5k1qthTaYKU7rSD39LU= -github.com/tomarrell/wrapcheck/v2 v2.6.2 h1:3dI6YNcrJTQ/CJQ6M/DUkc0gnqYSIk6o0rChn9E/D0M= -github.com/tomarrell/wrapcheck/v2 v2.6.2/go.mod h1:ao7l5p0aOlUNJKI0qVwB4Yjlqutd0IvAB9Rdwyilxvg= -github.com/tommy-muehle/go-mnd/v2 v2.5.0 h1:iAj0a8e6+dXSL7Liq0aXPox36FiN1dBbjA6lt9fl65s= -github.com/tommy-muehle/go-mnd/v2 v2.5.0/go.mod h1:WsUAkMJMYww6l/ufffCD3m+P7LEvr8TnZn9lwVDlgzw= -github.com/ultraware/funlen v0.0.3 h1:5ylVWm8wsNwH5aWo9438pwvsK0QiqVuUrt9bn7S/iLA= -github.com/ultraware/funlen v0.0.3/go.mod h1:Dp4UiAus7Wdb9KUZsYWZEWiRzGuM2kXM1lPbfaF6xhA= -github.com/ultraware/whitespace v0.0.5 h1:hh+/cpIcopyMYbZNVov9iSxvJU3OYQg78Sfaqzi/CzI= -github.com/ultraware/whitespace v0.0.5/go.mod h1:aVMh/gQve5Maj9hQ/hg+F75lr/X5A89uZnzAmWSineA= -github.com/uudashr/gocognit v1.0.6 h1:2Cgi6MweCsdB6kpcVQp7EW4U23iBFQWfTXiWlyp842Y= -github.com/uudashr/gocognit v1.0.6/go.mod h1:nAIUuVBnYU7pcninia3BHOvQkpQCeO76Uscky5BOwcY= -github.com/yagipy/maintidx v1.0.0 h1:h5NvIsCz+nRDapQ0exNv4aJ0yXSI0420omVANTv3GJM= -github.com/yagipy/maintidx v1.0.0/go.mod h1:0qNf/I/CCZXSMhsRsrEPDZ+DkekpKLXAJfsTACwgXLk= -github.com/yeya24/promlinter v0.2.0 h1:xFKDQ82orCU5jQujdaD8stOHiv8UN68BSdn2a8u8Y3o= -github.com/yeya24/promlinter v0.2.0/go.mod h1:u54lkmBOZrpEbQQ6gox2zWKKLKu2SGe+2KOiextY+IA= -github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -gitlab.com/bosi/decorder v0.2.3 h1:gX4/RgK16ijY8V+BRQHAySfQAb354T7/xQpDB2n10P0= -gitlab.com/bosi/decorder v0.2.3/go.mod h1:9K1RB5+VPNQYtXtTDAzd2OEftsZb1oV0IrJrzChSdGE= -go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= -go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= -go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= -go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= -go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4= -go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= -go.uber.org/zap v1.17.0 h1:MTjgFu6ZLKvY6Pvaqk97GlxNBuMpV4Hy/3P6tRGlI2U= -go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= -golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= -golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= -golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= -golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= -golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e h1:+WEEuIdZHnUeJJmEUjyYC2gfUMj69yZXw17EnHg/otA= -golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e/go.mod h1:Kr81I6Kryrl9sr8s2FK3vxD90NdsKWRuOIl2O4CvYbA= -golang.org/x/exp/typeparams v0.0.0-20220428152302-39d4317da171/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= -golang.org/x/exp/typeparams v0.0.0-20220613132600-b0d781184e0d h1:+W8Qf4iJtMGKkyAygcKohjxTk4JPsL9DpzApJ22m5Ic= -golang.org/x/exp/typeparams v0.0.0-20220613132600-b0d781184e0d/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= -golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= -golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= -golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= -golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= -golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= -golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= -golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= -golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= -golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 h1:uVc8UZUe6tr40fFVnUP5Oj+veunVezqYl9z7DYw9xzw= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211105183446-c75c47738b0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220702020025-31831981b65f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab h1:2QkjZIsXupsJbJIdSjjUOgWK3aEtzyuh2mPt3l/CkeU= -golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= -golang.org/x/tools v0.0.0-20190307163923-6a08e3108db3/go.mod h1:25r3+/G6/xytQM8iWZKq3Hn0kr0rgFKPUNVEL/dr3z4= -golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190311215038-5c2858a9cfe5/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190321232350-e250d351ecad/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190322203728-c1a832b0ad89/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190910044552-dd2b5c81c578/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190916130336-e45ffcd953cc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200117220505-0cba7a3a9ee9/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200324003944-a576cf524670/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= -golang.org/x/tools v0.0.0-20200329025819-fd4102a86c65/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= -golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= -golang.org/x/tools v0.0.0-20200414032229-332987a829c3/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200622203043-20e05c1c8ffa/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200624225443-88f3c62a19ff/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200625211823-6506e20df31f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200724022722-7017fd6b1305/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200812195022-5ae4c3c160a0/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200820010801-b793a1359eac/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200831203904-5a2aa26beb65/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= -golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= -golang.org/x/tools v0.0.0-20201001104356-43ebab892c4c/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= -golang.org/x/tools v0.0.0-20201002184944-ecd9fd270d5d/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= -golang.org/x/tools v0.0.0-20201023174141-c8cfbd0f21e6/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201230224404-63754364767c/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= -golang.org/x/tools v0.1.1-0.20210205202024-ef80cdb6ec6d/go.mod h1:9bzcO0MWcOuT0tm1iBGzDVPshzfwoVvREIui8C+MHqU= -golang.org/x/tools v0.1.1-0.20210302220138-2ac05c832e1a/go.mod h1:9bzcO0MWcOuT0tm1iBGzDVPshzfwoVvREIui8C+MHqU= -golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.9-0.20211228192929-ee1ca4ffc4da/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= -golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= -golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= -golang.org/x/tools v0.1.11/go.mod h1:SgwaegtQh8clINPpECJMqnxLv9I09HLqnW3RMqW0CA4= -golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU= -golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= -google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= -google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= -google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= -google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= -google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= -google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= -google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= -google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= -google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= -google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= -google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= -google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= -google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= -google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= -google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= -google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= -google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= -google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= -google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= -google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= -google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= -google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= -google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw= -google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/ini.v1 v1.66.6 h1:LATuAqN/shcYAOkv3wl2L4rkaKqkcgTBQjOyYDvcPKI= -gopkg.in/ini.v1 v1.66.6/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= -gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= -honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -honnef.co/go/tools v0.3.3 h1:oDx7VAwstgpYpb3wv0oxiZlxY+foCpRAwY7Vk6XpAgA= -honnef.co/go/tools v0.3.3/go.mod h1:jzwdWgg7Jdq75wlfblQxO4neNaFFSvgc1tD5Wv8U0Yw= -mvdan.cc/gofumpt v0.3.1 h1:avhhrOmv0IuvQVK7fvwV91oFSGAk5/6Po8GXTzICeu8= -mvdan.cc/gofumpt v0.3.1/go.mod h1:w3ymliuxvzVx8DAutBnVyDqYb1Niy/yCJt/lk821YCE= -mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed h1:WX1yoOaKQfddO/mLzdV4wptyWgoH/6hwLs7QHTixo0I= -mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed/go.mod h1:Xkxe497xwlCKkIaQYRfC7CSLworTXY9RMqwhhCm+8Nc= -mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b h1:DxJ5nJdkhDlLok9K6qO+5290kphDJbHOQO1DFFFTeBo= -mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b/go.mod h1:2odslEg/xrtNQqCYg2/jCoyKnw3vv5biOc3JnIcYfL4= -mvdan.cc/unparam v0.0.0-20220706161116-678bad134442 h1:seuXWbRB1qPrS3NQnHmFKLJLtskWyueeIzmLXghMGgk= -mvdan.cc/unparam v0.0.0-20220706161116-678bad134442/go.mod h1:F/Cxw/6mVrNKqrR2YjFf5CaW0Bw4RL8RfbEf4GRggJk= -rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= -rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= -rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/.bingo/swagger.sum b/.bingo/swagger.sum deleted file mode 100644 index 3e3c5ac43852c..0000000000000 --- a/.bingo/swagger.sum +++ /dev/null @@ -1,86 +0,0 @@ -github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI= -github.com/Masterminds/semver/v3 v3.1.1 h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030IGemrRc= -github.com/Masterminds/sprig/v3 v3.2.2 h1:17jRggJu518dr3QaafizSXOjKYp94wKfABxUmyxvxX8= -github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI= -github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M= -github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d h1:Byv0BzEl3/e6D5CLfI0j/7hiIEtvGVFPCZ7Ei2oq8iQ= -github.com/felixge/httpsnoop v1.0.2 h1:+nS9g82KMXccJ/wp0zyRW9ZBHFETmMGtkk+2CTTrW4o= -github.com/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBdXk= -github.com/fsnotify/fsnotify v1.5.1 h1:mZcQUHVQUQWoPXXtuf9yuEXKudkV2sx1E06UadKWpgI= -github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI= -github.com/go-openapi/analysis v0.21.2 h1:hXFrOYFHUAMQdu6zwAiKKJHJQ8kqZs1ux/ru1P1wLJU= -github.com/go-openapi/analysis v0.21.4 h1:ZDFLvSNxpDaomuCueM0BlSXxpANBlFYiBvr+GXrvIHc= -github.com/go-openapi/errors v0.20.2 h1:dxy7PGTqEh94zj2E3h1cUmQQWiM1+aeCROfAr02EmK8= -github.com/go-openapi/errors v0.20.3 h1:rz6kiC84sqNQoqrtulzaL/VERgkoCyB6WdEkc2ujzUc= -github.com/go-openapi/inflect v0.19.0 h1:9jCH9scKIbHeV9m12SmPilScz6krDxKRasNNSNPXu/4= -github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY= -github.com/go-openapi/jsonreference v0.19.6 h1:UBIxjkht+AWIgYzCDSv2GN+E/togfwXUJFRTWhl2Jjs= -github.com/go-openapi/jsonreference v0.20.0 h1:MYlu0sBgChmCfJxxUKZ8g1cPWFOB37YSZqewK7OKeyA= -github.com/go-openapi/loads v0.21.0 h1:jYtUO4wwP7psAweisP/MDoOpdzsYEESdoPcsWjHDR68= -github.com/go-openapi/loads v0.21.2 h1:r2a/xFIYeZ4Qd2TnGpWDIQNcP80dIaZgf704za8enro= -github.com/go-openapi/runtime v0.21.1 h1:/KIG00BzA2x2HRStX2tnhbqbQdPcFlkgsYCiNY20FZs= -github.com/go-openapi/runtime v0.24.1 h1:Sml5cgQKGYQHF+M7yYSHaH1eOjvTykrddTE/KtQVjqo= -github.com/go-openapi/spec v0.20.4 h1:O8hJrt0UMnhHcluhIdUgCLRWyM2x7QkBXRvOs7m+O1M= -github.com/go-openapi/spec v0.20.7 h1:1Rlu/ZrOCCob0n+JKKJAWhNWMPW8bOZRg8FJaY+0SKI= -github.com/go-openapi/strfmt v0.21.1 h1:G6s2t5V5kGCHLVbSdZ/6lI8Wm4OzoPFkc3/cjAsKQrM= -github.com/go-openapi/strfmt v0.21.3 h1:xwhj5X6CjXEZZHMWy1zKJxvW9AfHC9pkyUjLvHtKG7o= -github.com/go-openapi/swag v0.19.15 h1:D2NRCBzS9/pEY3gP9Nl8aDqGUcPFrwG2p+CNFrLyrCM= -github.com/go-openapi/swag v0.22.3 h1:yMBqmnQ0gyZvEb/+KzuWZOXgllrXT4SADYbvDaXHv/g= -github.com/go-openapi/validate v0.20.3 h1:GZPPhhKSZrE8HjB4eEkoYAZmoWA4+tCemSgINH1/vKw= -github.com/go-openapi/validate v0.22.0 h1:b0QecH6VslW/TxtpKgzpO1SNG7GU2FsaqKdP1E2T50Y= -github.com/go-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw= -github.com/go-swagger/go-swagger v0.29.0 h1:z3YoZtLvS1Y8TE/PCat1VypcZxM0IgKLt0NvZxQyNl8= -github.com/go-swagger/go-swagger v0.29.0/go.mod h1:Z4GJzI+bHKKkGB2Ji1rawpi3/ldXX8CkzGIa9HAC5EE= -github.com/go-swagger/go-swagger v0.30.2 h1:23odPUyQZdkNFZZSBJ3mqYYcdh+LnuReEbdWN18OMRo= -github.com/go-swagger/go-swagger v0.30.2/go.mod h1:neDPes8r8PCz2JPvHRDj8BTULLh4VJUt7n6MpQqxhHM= -github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y= -github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4= -github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= -github.com/huandu/xstrings v1.3.2 h1:L18LIDzqlW6xN2rEkpdV8+oL/IXWJ1APd+vsdYy4Wdw= -github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU= -github.com/jessevdk/go-flags v1.5.0 h1:1jKYvbxEjfUl0fmqTCOfonvskHHXMjBySTLW4y9LFvc= -github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= -github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= -github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/magiconair/properties v1.8.5 h1:b6kJs+EmPFMYGkow9GiUyCyOvIwYetYJ3fSaWak/Gls= -github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamhfG/Qzo= -github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= -github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= -github.com/mitchellh/mapstructure v1.4.3 h1:OVowDSCllw/YjdLkam3/sm7wEtOy59d8ndGgCcyj8cs= -github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= -github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= -github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4= -github.com/pelletier/go-toml v1.9.4 h1:tjENF6MfZAg8e4ZmZTeWaWiT2vXtsoO6+iuOjFhECwM= -github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= -github.com/pelletier/go-toml/v2 v2.0.1 h1:8e3L2cCQzLFi2CR4g7vGFuFxX7Jl1kKX8gW+iV0GUKU= -github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= -github.com/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XFkP+Eg= -github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= -github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ= -github.com/spf13/afero v1.8.0 h1:5MmtuhAgYeU6qpa7w7bP0dv6MBYuup0vekhSpSkoq60= -github.com/spf13/afero v1.8.2 h1:xehSyVa0YnHWsJ49JFljMpg1HX19V6NDZ1fkm1Xznbo= -github.com/spf13/cast v1.4.1 h1:s0hze+J0196ZfEMTs80N7UlFt0BDuQ7Q+JDnHiMWKdA= -github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w= -github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= -github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= -github.com/spf13/viper v1.10.1 h1:nuJZuYpG7gTj/XqiUwg8bA0cp1+M2mC3J4g5luUYBKk= -github.com/spf13/viper v1.12.0 h1:CZ7eSOd3kZoaYDLbXnmzgQI5RlciuXBMA+18HwHRfZQ= -github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s= -github.com/subosito/gotenv v1.3.0 h1:mjC+YW8QpAdXibNi+vNWgzmgBH4+5l5dCXv8cNysBLI= -github.com/toqueteos/webbrowser v1.2.0 h1:tVP/gpK69Fx+qMJKsLE7TD8LuGWPnEV71wBN9rrstGQ= -go.mongodb.org/mongo-driver v1.8.2 h1:8ssUXufb90ujcIvR6MyE1SchaNj0SFxsakiZgxIyrMk= -go.mongodb.org/mongo-driver v1.10.1 h1:NujsPveKwHaWuKUer/ceo9DzEe7HIj1SlJ6uvXZG0S4= -golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90 h1:Y/gsMcFOcR+6S6f3YeMKl5g+dZMEWqcz5Czj/GWYbkM= -golang.org/x/mod v0.5.1 h1:OJxoQ/rynoF0dcCdI7cLPktw/hR2cueqYfjm43oqK38= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s= -golang.org/x/net v0.0.0-20220121210141-e204ce36a2ba h1:6u6sik+bn/y7vILcYkK3iwTBWN7WtBvB0+SZswQnbf8= -golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 h1:XfKQ4OlFl8okEOr5UvAqFRVj8pY/4yfcXrddB8qAbU0= -golang.org/x/sys v0.0.0-20220829200755-d48e67d00261 h1:v6hYoSR9T5oet+pMXwUWkbiVqx/63mlHjefrHmxwfeY= -golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= -golang.org/x/tools v0.1.8 h1:P1HhGGuLW4aAclzjtmJdf0mJOjVUZUzOTqkAkWL+l6w= -golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= -gopkg.in/ini.v1 v1.66.3 h1:jRskFVxYaMGAMUbN0UZ7niA9gzL9B49DOqE78vg0k3w= -gopkg.in/ini.v1 v1.66.4 h1:SsAcf+mM7mRZo2nJNGt8mZCjG8ZRaNGMURJw7BsIST4= -gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/.bingo/variables.env b/.bingo/variables.env index 85d262ffe2c6c..55f2b23f67e05 100644 --- a/.bingo/variables.env +++ b/.bingo/variables.env @@ -1,4 +1,4 @@ -# Auto generated binary variables helper managed by https://github.com/bwplotka/bingo v0.6. DO NOT EDIT. +# Auto generated binary variables helper managed by https://github.com/bwplotka/bingo v0.8. DO NOT EDIT. # All tools are designed to be build inside $GOBIN. # Those variables will work only until 'bingo get' was invoked, or if tools were installed via Makefile's Variables.mk. GOBIN=${GOBIN:=$(go env GOBIN)} @@ -12,7 +12,9 @@ BRA="${GOBIN}/bra-v0.0.0-20200517080246-1e3013ecaff8" DRONE="${GOBIN}/drone-v1.5.0" -GOLANGCI_LINT="${GOBIN}/golangci-lint-v1.49.0" +GOLANGCI_LINT="${GOBIN}/golangci-lint-v1.51.2" + +JB="${GOBIN}/jb-v0.5.1" SWAGGER="${GOBIN}/swagger-v0.30.2" diff --git a/.bingo/wire.sum b/.bingo/wire.sum deleted file mode 100644 index 6d4b4b386440f..0000000000000 --- a/.bingo/wire.sum +++ /dev/null @@ -1,13 +0,0 @@ -github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= -github.com/google/subcommands v1.0.1 h1:/eqq+otEXm5vhfBrbREPCSVQbvofip6kIz+mX5TUH7k= -github.com/google/subcommands v1.0.1/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= -github.com/google/wire v0.5.0 h1:I7ELFeVBr3yfPIcc8+MWvrjk+3VjbcSzoXm3JVa+jD8= -github.com/google/wire v0.5.0/go.mod h1:ngWDr9Qvq3yZA10YrxfyGELY/AFWGVpy9c1LTRi1EoU= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/tools v0.0.0-20190422233926-fe54fb35175b h1:NVD8gBK33xpdqCaZVVtd6OFJp+3dxkXuz7+U7KaVN6s= -golang.org/x/tools v0.0.0-20190422233926-fe54fb35175b/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= diff --git a/.bra.toml b/.bra.toml index 7bfb359a7b8fd..52895ad671385 100644 --- a/.bra.toml +++ b/.bra.toml @@ -1,9 +1,8 @@ [run] init_cmds = [ ["make", "gen-go"], - ["GO_BUILD_DEV=1", "make", "build-cli"], - ["GO_BUILD_DEV=1", "make", "build-server"], - ["./bin/grafana-server", "-packaging=dev", "cfg:app_mode=development"] + ["GO_BUILD_DEV=1", "make", "build-go"], + ["./bin/grafana", "server", "-packaging=dev", "cfg:app_mode=development"] ] watch_all = true follow_symlinks = true @@ -17,6 +16,6 @@ ignore_files = [".*_gen.go"] build_delay = 1500 cmds = [ ["make", "gen-go"], - ["GO_BUILD_DEV=1", "make", "build-server"], - ["./bin/grafana-server", "-packaging=dev", "cfg:app_mode=development"] + ["GO_BUILD_DEV=1", "make", "build-go"], + ["./bin/grafana", "server", "-packaging=dev", "cfg:app_mode=development"] ] diff --git a/.dockerignore b/.dockerignore index 7ed8d01615eae..1df915d24611c 100644 --- a/.dockerignore +++ b/.dockerignore @@ -2,7 +2,6 @@ .dockerignore .git .gitignore -.github .vscode bin data* diff --git a/.drone.star b/.drone.star index 9d2a65ebc6390..db76fbd9dee1d 100644 --- a/.drone.star +++ b/.drone.star @@ -3,20 +3,62 @@ # 2. Login to drone and export the env variables (token and server) shown here: https://drone.grafana.net/account # 3. Run `make drone` # More information about this process here: https://github.com/grafana/deployment_tools/blob/master/docs/infrastructure/drone/signing.md +""" +This module returns a Drone configuration including pipelines and secrets. +""" -load('scripts/drone/events/pr.star', 'pr_pipelines') -load('scripts/drone/events/main.star', 'main_pipelines') -load('scripts/drone/pipelines/docs.star', 'docs_pipelines') -load('scripts/drone/events/release.star', 'release_pipelines', 'publish_artifacts_pipelines', 'publish_npm_pipelines', 'publish_packages_pipeline', 'artifacts_page_pipeline') -load('scripts/drone/pipelines/publish_images.star', 'publish_image_pipelines_public', 'publish_image_pipelines_security') -load('scripts/drone/version.star', 'version_branch_pipelines') -load('scripts/drone/events/cron.star', 'cronjobs') -load('scripts/drone/vault.star', 'secrets') +load("scripts/drone/events/pr.star", "pr_pipelines") +load("scripts/drone/events/main.star", "main_pipelines") +load( + "scripts/drone/events/release.star", + "artifacts_page_pipeline", + "enterprise2_pipelines", + "enterprise_pipelines", + "integration_test_pipelines", + "oss_pipelines", + "publish_artifacts_pipelines", + "publish_npm_pipelines", + "publish_packages_pipeline", +) +load( + "scripts/drone/pipelines/publish_images.star", + "publish_image_pipelines_public", + "publish_image_pipelines_security", +) +load( + "scripts/drone/pipelines/ci_images.star", + "publish_ci_windows_test_image_pipeline", +) +load("scripts/drone/pipelines/github.star", "publish_github_pipeline") +load("scripts/drone/pipelines/aws_marketplace.star", "publish_aws_marketplace_pipeline") +load("scripts/drone/version.star", "version_branch_pipelines") +load("scripts/drone/events/cron.star", "cronjobs") +load("scripts/drone/vault.star", "secrets") -def main(ctx): - edition = 'oss' - return pr_pipelines(edition=edition) + main_pipelines(edition=edition) + release_pipelines() + \ - publish_image_pipelines_public() + publish_image_pipelines_security() + \ - publish_artifacts_pipelines('security') + publish_artifacts_pipelines('public') + \ - publish_npm_pipelines('public') + publish_packages_pipeline() + artifacts_page_pipeline() + \ - version_branch_pipelines() + cronjobs(edition=edition) + secrets() +def main(_ctx): + return ( + pr_pipelines() + + main_pipelines() + + oss_pipelines() + + enterprise_pipelines() + + enterprise2_pipelines() + + enterprise2_pipelines( + prefix = "custom-", + trigger = {"event": ["custom"]}, + ) + + publish_image_pipelines_public() + + publish_image_pipelines_security() + + publish_github_pipeline("public") + + publish_github_pipeline("security") + + publish_aws_marketplace_pipeline("public") + + publish_artifacts_pipelines("security") + + publish_artifacts_pipelines("public") + + publish_npm_pipelines() + + publish_packages_pipeline() + + artifacts_page_pipeline() + + version_branch_pipelines() + + integration_test_pipelines() + + publish_ci_windows_test_image_pipeline() + + cronjobs() + + secrets() + ) diff --git a/.drone.yml b/.drone.yml index 0ed90b0cddd59..7e7e84e4ea392 100644 --- a/.drone.yml +++ b/.drone.yml @@ -2,6 +2,8 @@ clone: retries: 3 depends_on: [] +environment: + EDITION: oss image_pull_secrets: - dockerconfigjson kind: pipeline @@ -15,20 +17,14 @@ services: [] steps: - commands: - echo $DRONE_RUNNER_NAME - image: alpine:3.15.6 + image: alpine:3.17.1 name: identify-runner -- commands: - - mkdir -p bin - - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.0.15/grabpl - - chmod +x bin/grabpl - image: byrnedo/alpine-curl:0.1.8 - name: grabpl - commands: - go build -o ./bin/build -ldflags '-extldflags -static' ./pkg/build/cmd depends_on: [] environment: CGO_ENABLED: 0 - image: golang:1.19.4 + image: golang:1.20.4 name: compile-build-cmd - commands: - ./bin/build verify-drone @@ -56,6 +52,57 @@ volumes: clone: retries: 3 depends_on: [] +environment: + EDITION: oss +image_pull_secrets: +- dockerconfigjson +kind: pipeline +name: pr-verify-starlark +node: + type: no-parallel +platform: + arch: amd64 + os: linux +services: [] +steps: +- commands: + - echo $DRONE_RUNNER_NAME + image: alpine:3.17.1 + name: identify-runner +- commands: + - go build -o ./bin/build -ldflags '-extldflags -static' ./pkg/build/cmd + depends_on: [] + environment: + CGO_ENABLED: 0 + image: golang:1.20.4 + name: compile-build-cmd +- commands: + - ./bin/build verify-starlark . + depends_on: + - compile-build-cmd + image: grafana/build-container:1.7.4 + name: lint-starlark +trigger: + event: + - pull_request + paths: + exclude: + - docs/** + - '*.md' + include: + - scripts/drone/** + - .drone.star +type: docker +volumes: +- host: + path: /var/run/docker.sock + name: docker +--- +clone: + retries: 3 +depends_on: [] +environment: + EDITION: oss image_pull_secrets: - dockerconfigjson kind: pipeline @@ -69,33 +116,53 @@ services: [] steps: - commands: - echo $DRONE_RUNNER_NAME - image: alpine:3.15.6 + image: alpine:3.17.1 name: identify-runner - commands: - mkdir -p bin - - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.0.15/grabpl + - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.0.30/grabpl - chmod +x bin/grabpl image: byrnedo/alpine-curl:0.1.8 name: grabpl - commands: - yarn install --immutable depends_on: [] - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: yarn-install - commands: - yarn betterer ci depends_on: - yarn-install - failure: ignore - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: betterer-frontend +- commands: + - is_fork=$(curl "https://$GITHUB_TOKEN@api.github.com/repos/grafana/grafana/pulls/$DRONE_PULL_REQUEST" + | jq .head.repo.fork) + - if [ "$is_fork" != false ]; then return 1; fi + - git clone "https://$${GITHUB_TOKEN}@github.com/grafana/grafana-enterprise.git" + ../grafana-enterprise + - cd ../grafana-enterprise + - if git checkout ${DRONE_SOURCE_BRANCH}; then echo "checked out ${DRONE_SOURCE_BRANCH}"; + elif git checkout ${DRONE_TARGET_BRANCH}; then echo "git checkout ${DRONE_TARGET_BRANCH}"; + else git checkout main; fi + - cd ../ + - ln -s src grafana + - cd ./grafana-enterprise + - ./build.sh + environment: + GITHUB_TOKEN: + from_secret: github_token + failure: ignore + image: grafana/build-container:1.7.4 + name: clone-enterprise - commands: - yarn run ci:test-frontend depends_on: - yarn-install + - clone-enterprise environment: TEST_MAX_WORKERS: 50% - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: test-frontend trigger: event: @@ -118,6 +185,8 @@ volumes: clone: retries: 3 depends_on: [] +environment: + EDITION: oss image_pull_secrets: - dockerconfigjson kind: pipeline @@ -129,14 +198,34 @@ platform: os: linux services: [] steps: +- commands: + - is_fork=$(curl "https://$GITHUB_TOKEN@api.github.com/repos/grafana/grafana/pulls/$DRONE_PULL_REQUEST" + | jq .head.repo.fork) + - if [ "$is_fork" != false ]; then return 1; fi + - git clone "https://$${GITHUB_TOKEN}@github.com/grafana/grafana-enterprise.git" + ../grafana-enterprise + - cd ../grafana-enterprise + - if git checkout ${DRONE_SOURCE_BRANCH}; then echo "checked out ${DRONE_SOURCE_BRANCH}"; + elif git checkout ${DRONE_TARGET_BRANCH}; then echo "git checkout ${DRONE_TARGET_BRANCH}"; + else git checkout main; fi + - cd ../ + - ln -s src grafana + - cd ./grafana-enterprise + - ./build.sh + environment: + GITHUB_TOKEN: + from_secret: github_token + failure: ignore + image: grafana/build-container:1.7.4 + name: clone-enterprise - commands: - echo $DRONE_RUNNER_NAME - image: alpine:3.15.6 + image: alpine:3.17.1 name: identify-runner - commands: - yarn install --immutable depends_on: [] - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: yarn-install - commands: - yarn run prettier:check @@ -145,9 +234,10 @@ steps: - yarn run typecheck depends_on: - yarn-install + - clone-enterprise environment: TEST_MAX_WORKERS: 50% - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: lint-frontend trigger: event: @@ -183,16 +273,36 @@ platform: os: linux services: [] steps: +- commands: + - is_fork=$(curl "https://$GITHUB_TOKEN@api.github.com/repos/grafana/grafana/pulls/$DRONE_PULL_REQUEST" + | jq .head.repo.fork) + - if [ "$is_fork" != false ]; then return 1; fi + - git clone "https://$${GITHUB_TOKEN}@github.com/grafana/grafana-enterprise.git" + ../grafana-enterprise + - cd ../grafana-enterprise + - if git checkout ${DRONE_SOURCE_BRANCH}; then echo "checked out ${DRONE_SOURCE_BRANCH}"; + elif git checkout ${DRONE_TARGET_BRANCH}; then echo "git checkout ${DRONE_TARGET_BRANCH}"; + else git checkout main; fi + - cd ../ + - ln -s src grafana + - cd ./grafana-enterprise + - ./build.sh + environment: + GITHUB_TOKEN: + from_secret: github_token + failure: ignore + image: grafana/build-container:1.7.4 + name: clone-enterprise - commands: - echo $DRONE_RUNNER_NAME - image: alpine:3.15.6 + image: alpine:3.17.1 name: identify-runner - commands: - go build -o ./bin/build -ldflags '-extldflags -static' ./pkg/build/cmd depends_on: [] environment: CGO_ENABLED: 0 - image: golang:1.19.4 + image: golang:1.20.4 name: compile-build-cmd - commands: - '# It is required that code generated from Thema/CUE be committed and in sync @@ -200,26 +310,27 @@ steps: - '# The following command will fail if running code generators produces any diff in output.' - CODEGEN_VERIFY=1 make gen-cue - depends_on: [] - image: grafana/build-container:1.6.6 + depends_on: + - clone-enterprise + image: grafana/build-container:1.7.4 name: verify-gen-cue - commands: - make gen-go depends_on: - verify-gen-cue - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: wire-install - commands: - - go test -short -covermode=atomic -timeout=30m ./pkg/... + - go test -tags requires_buildifer -short -covermode=atomic -timeout=5m ./pkg/... depends_on: - wire-install - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: test-backend - commands: - - go test -run Integration -covermode=atomic -timeout=30m ./pkg/... + - go test -run Integration -covermode=atomic -timeout=5m ./pkg/... depends_on: - wire-install - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: test-backend-integration trigger: event: @@ -246,6 +357,58 @@ volumes: clone: retries: 3 depends_on: [] +environment: + EDITION: oss +image_pull_secrets: +- dockerconfigjson +kind: pipeline +name: pr-oss-test-backend-windows +platform: + arch: amd64 + os: windows + version: "1809" +services: [] +steps: +- commands: [] + image: grafana/grafana-ci-windows-test:0.1.0 + name: windows-init +- commands: + - go install github.com/google/wire/cmd/wire@v0.5.0 + - wire gen -tags oss ./pkg/server + depends_on: + - windows-init + image: grafana/grafana-ci-windows-test:0.1.0 + name: wire-install +- commands: + - go test -tags requires_buildifer -short -covermode=atomic -timeout=5m ./pkg/... + depends_on: + - wire-install + failure: ignore + image: grafana/grafana-ci-windows-test:0.1.0 + name: test-backend +trigger: + event: + - pull_request + paths: + exclude: + - docs/** + - '*.md' + - pkg/** + - packaging/** + - go.sum + - go.mod + include: [] +type: docker +volumes: +- host: + path: //./pipe/docker_engine/ + name: docker +--- +clone: + retries: 3 +depends_on: [] +environment: + EDITION: oss image_pull_secrets: - dockerconfigjson kind: pipeline @@ -259,19 +422,40 @@ services: [] steps: - commands: - echo $DRONE_RUNNER_NAME - image: alpine:3.15.6 + image: alpine:3.17.1 name: identify-runner - commands: - go build -o ./bin/build -ldflags '-extldflags -static' ./pkg/build/cmd depends_on: [] environment: CGO_ENABLED: 0 - image: golang:1.19.4 + image: golang:1.20.4 name: compile-build-cmd +- commands: + - is_fork=$(curl "https://$GITHUB_TOKEN@api.github.com/repos/grafana/grafana/pulls/$DRONE_PULL_REQUEST" + | jq .head.repo.fork) + - if [ "$is_fork" != false ]; then return 1; fi + - git clone "https://$${GITHUB_TOKEN}@github.com/grafana/grafana-enterprise.git" + ../grafana-enterprise + - cd ../grafana-enterprise + - if git checkout ${DRONE_SOURCE_BRANCH}; then echo "checked out ${DRONE_SOURCE_BRANCH}"; + elif git checkout ${DRONE_TARGET_BRANCH}; then echo "git checkout ${DRONE_TARGET_BRANCH}"; + else git checkout main; fi + - cd ../ + - ln -s src grafana + - cd ./grafana-enterprise + - ./build.sh + environment: + GITHUB_TOKEN: + from_secret: github_token + failure: ignore + image: grafana/build-container:1.7.4 + name: clone-enterprise - commands: - make gen-go - depends_on: [] - image: grafana/build-container:1.6.6 + depends_on: + - clone-enterprise + image: grafana/build-container:1.7.4 name: wire-install - commands: - apt-get update && apt-get install make @@ -280,7 +464,7 @@ steps: - wire-install environment: CGO_ENABLED: "1" - image: golang:1.19.4 + image: golang:1.20.4 name: lint-backend trigger: event: @@ -297,6 +481,7 @@ trigger: - go.mod - public/app/plugins/**/plugin.json - devenv/** + - .bingo/** type: docker volumes: - host: @@ -306,6 +491,8 @@ volumes: clone: retries: 3 depends_on: [] +environment: + EDITION: oss image_pull_secrets: - dockerconfigjson kind: pipeline @@ -319,11 +506,11 @@ services: [] steps: - commands: - echo $DRONE_RUNNER_NAME - image: alpine:3.15.6 + image: alpine:3.17.1 name: identify-runner - commands: - mkdir -p bin - - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.0.15/grabpl + - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.0.30/grabpl - chmod +x bin/grabpl image: byrnedo/alpine-curl:0.1.8 name: grabpl @@ -332,7 +519,7 @@ steps: depends_on: [] environment: CGO_ENABLED: 0 - image: golang:1.19.4 + image: golang:1.20.4 name: compile-build-cmd - commands: - '# It is required that code generated from Thema/CUE be committed and in sync @@ -341,19 +528,49 @@ steps: in output.' - CODEGEN_VERIFY=1 make gen-cue depends_on: [] - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: verify-gen-cue - commands: - make gen-go depends_on: - verify-gen-cue - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: wire-install - commands: - yarn install --immutable depends_on: [] - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: yarn-install +- commands: + - git clone "https://$${GITHUB_TOKEN}@github.com/grafana/grafana-enterprise.git" + --depth=1 + - cd grafana-enterprise + - git fetch origin "refs/tags/*:refs/tags/*" --quiet + - if git show-ref --tags $${TEST_TAG} --quiet; then git tag -d $${TEST_TAG} && git + push --delete origin $${TEST_TAG}; fi + - git tag $${TEST_TAG} && git push origin $${TEST_TAG} + - cd - + - git fetch https://$${GITHUB_TOKEN}@github.com/grafana/grafana.git "refs/tags/*:refs/tags/*" + --quiet && git fetch --quiet + - if git show-ref --tags $${TEST_TAG} --quiet; then git tag -d $${TEST_TAG} && git + push --delete https://$${GITHUB_TOKEN}@github.com/grafana/grafana.git $${TEST_TAG}; + fi + - git tag $${TEST_TAG} && git push https://$${GITHUB_TOKEN}@github.com/grafana/grafana.git + $${TEST_TAG} + environment: + GITHUB_TOKEN: + from_secret: github_token_pr + TEST_TAG: v0.0.0-test + failure: ignore + image: grafana/build-container:1.7.4 + name: trigger-test-release + when: + paths: + include: + - .drone.yml + - pkg/build/** + repo: + - grafana/grafana - failure: ignore image: grafana/drone-downstream name: trigger-enterprise-downstream @@ -372,7 +589,7 @@ steps: depends_on: - wire-install - compile-build-cmd - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: build-backend - commands: - ./bin/build build-frontend --jobs 8 --edition oss --build-id ${DRONE_BUILD_NUMBER} @@ -381,7 +598,7 @@ steps: - yarn-install environment: NODE_OPTIONS: --max_old_space_size=8192 - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: build-frontend - commands: - ./bin/build build-frontend-packages --jobs 8 --edition oss --build-id ${DRONE_BUILD_NUMBER} @@ -390,7 +607,7 @@ steps: - yarn-install environment: NODE_OPTIONS: --max_old_space_size=8192 - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: build-frontend-packages - commands: - ./bin/build build-plugins --jobs 8 --edition oss @@ -398,18 +615,18 @@ steps: - compile-build-cmd - yarn-install environment: null - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: build-plugins - commands: - . scripts/build/gpg-test-vars.sh && ./bin/build package --jobs 8 --edition oss - --build-id ${DRONE_BUILD_NUMBER} --variants linux-amd64,linux-amd64-musl,darwin-amd64,windows-amd64 + --build-id ${DRONE_BUILD_NUMBER} depends_on: - build-plugins - build-backend - build-frontend - build-frontend-packages environment: null - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: package - commands: - ./scripts/grafana-server/start-server @@ -422,7 +639,7 @@ steps: environment: ARCH: linux-amd64 PORT: 3001 - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: grafana-server - commands: - apt-get install -y netcat @@ -460,11 +677,35 @@ steps: HOST: grafana-server image: cypress/included:9.5.1-node16.14.0-slim-chrome99-ff97 name: end-to-end-tests-various-suite +- commands: + - cd / + - ./cpp-e2e/scripts/ci-run.sh azure ${DRONE_SOURCE_BRANCH} + depends_on: + - grafana-server + environment: + AZURE_SP_APP_ID: + from_secret: azure_sp_app_id + AZURE_SP_PASSWORD: + from_secret: azure_sp_app_pw + AZURE_TENANT: + from_secret: azure_tenant + CYPRESS_CI: "true" + GITHUB_TOKEN: + from_secret: github_token_pr + HOST: grafana-server + image: us-docker.pkg.dev/grafanalabs-dev/cloud-data-sources/e2e:latest + name: end-to-end-tests-cloud-plugins-suite-azure + when: + paths: + include: + - pkg/tsdb/azuremonitor/** + - public/app/plugins/datasource/grafana-azure-monitor-datasource/** + - e2e/cloud-plugins-suite/azure-monitor.spec.ts + repo: + - grafana/grafana - commands: - apt-get update - apt-get install -yq zip - - ls -lah ./e2e - - find ./e2e -type f -name "*.mp4" - printenv GCP_GRAFANA_UPLOAD_ARTIFACTS_KEY > /tmp/gcpkey_upload_artifacts.json - gcloud auth activate-service-account --key-file=/tmp/gcpkey_upload_artifacts.json - find ./e2e -type f -name "*spec.ts.mp4" | zip e2e/videos.zip -@ @@ -486,7 +727,8 @@ steps: from_secret: gcp_upload_artifacts_key GITHUB_TOKEN: from_secret: github_token - image: google/cloud-sdk:367.0.0 + failure: ignore + image: google/cloud-sdk:406.0.0 name: e2e-tests-artifacts-upload when: status: @@ -494,13 +736,13 @@ steps: - failure - commands: - yarn storybook:build - - ./bin/grabpl verify-storybook + - ./bin/build verify-storybook depends_on: - build-frontend - build-frontend-packages environment: NODE_OPTIONS: --max_old_space_size=4096 - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: build-storybook when: paths: @@ -511,7 +753,7 @@ steps: - cp dist/*.tar.gz* packaging/docker/ depends_on: - package - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: copy-packages-for-docker - commands: - yarn wait-on http://$HOST:$PORT @@ -556,6 +798,8 @@ volumes: clone: retries: 3 depends_on: [] +environment: + EDITION: oss image_pull_secrets: - dockerconfigjson kind: pipeline @@ -587,9 +831,29 @@ services: - name: mysql path: /var/lib/mysql steps: +- commands: + - is_fork=$(curl "https://$GITHUB_TOKEN@api.github.com/repos/grafana/grafana/pulls/$DRONE_PULL_REQUEST" + | jq .head.repo.fork) + - if [ "$is_fork" != false ]; then return 1; fi + - git clone "https://$${GITHUB_TOKEN}@github.com/grafana/grafana-enterprise.git" + ../grafana-enterprise + - cd ../grafana-enterprise + - if git checkout ${DRONE_SOURCE_BRANCH}; then echo "checked out ${DRONE_SOURCE_BRANCH}"; + elif git checkout ${DRONE_TARGET_BRANCH}; then echo "git checkout ${DRONE_TARGET_BRANCH}"; + else git checkout main; fi + - cd ../ + - ln -s src grafana + - cd ./grafana-enterprise + - ./build.sh + environment: + GITHUB_TOKEN: + from_secret: github_token + failure: ignore + image: grafana/build-container:1.7.4 + name: clone-enterprise - commands: - mkdir -p bin - - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.0.15/grabpl + - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.0.30/grabpl - chmod +x bin/grabpl image: byrnedo/alpine-curl:0.1.8 name: grabpl @@ -598,11 +862,11 @@ steps: depends_on: [] environment: CGO_ENABLED: 0 - image: golang:1.19.4 + image: golang:1.20.4 name: compile-build-cmd - commands: - echo $DRONE_RUNNER_NAME - image: alpine:3.15.6 + image: alpine:3.17.1 name: identify-runner - commands: - '# It is required that code generated from Thema/CUE be committed and in sync @@ -610,14 +874,15 @@ steps: - '# The following command will fail if running code generators produces any diff in output.' - CODEGEN_VERIFY=1 make gen-cue - depends_on: [] - image: grafana/build-container:1.6.6 + depends_on: + - clone-enterprise + image: grafana/build-container:1.7.4 name: verify-gen-cue - commands: - make gen-go depends_on: - verify-gen-cue - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: wire-install - commands: - apt-get update @@ -626,14 +891,14 @@ steps: - psql -p 5432 -h postgres -U grafanatest -d grafanatest -f devenv/docker/blocks/postgres_tests/setup.sql - go clean -testcache - go list './pkg/...' | xargs -I {} sh -c 'go test -run Integration -covermode=atomic - -timeout=30m {}' + -timeout=5m {}' depends_on: - wire-install environment: GRAFANA_TEST_DB: postgres PGPASSWORD: grafanatest POSTGRES_HOST: postgres - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: postgres-integration-tests - commands: - apt-get update @@ -643,13 +908,13 @@ steps: -prootpass - go clean -testcache - go list './pkg/...' | xargs -I {} sh -c 'go test -run Integration -covermode=atomic - -timeout=30m {}' + -timeout=5m {}' depends_on: - wire-install environment: GRAFANA_TEST_DB: mysql MYSQL_HOST: mysql - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: mysql-integration-tests trigger: event: @@ -681,6 +946,8 @@ volumes: clone: retries: 3 depends_on: [] +environment: + EDITION: oss image_pull_secrets: - dockerconfigjson kind: pipeline @@ -692,20 +959,14 @@ platform: os: linux services: [] steps: -- commands: - - mkdir -p bin - - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.0.15/grabpl - - chmod +x bin/grabpl - image: byrnedo/alpine-curl:0.1.8 - name: grabpl - commands: - echo $DRONE_RUNNER_NAME - image: alpine:3.15.6 + image: alpine:3.17.1 name: identify-runner - commands: - yarn install --immutable depends_on: [] - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: yarn-install - commands: - |- @@ -717,7 +978,7 @@ steps: wan" > words_to_ignore.txt - codespell -I words_to_ignore.txt docs/ - rm words_to_ignore.txt - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: codespell - commands: - yarn run prettier:checkDocs @@ -725,7 +986,7 @@ steps: - yarn-install environment: NODE_OPTIONS: --max_old_space_size=8192 - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: lint-docs - commands: - mkdir -p /hugo/content/docs/grafana @@ -751,6 +1012,8 @@ volumes: clone: retries: 3 depends_on: [] +environment: + EDITION: oss image_pull_secrets: - dockerconfigjson kind: pipeline @@ -767,13 +1030,13 @@ steps: depends_on: [] environment: CGO_ENABLED: 0 - image: golang:1.19.4 + image: golang:1.20.4 name: compile-build-cmd - commands: - ./bin/build shellcheck depends_on: - compile-build-cmd - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: shellcheck trigger: event: @@ -794,6 +1057,8 @@ volumes: clone: retries: 3 depends_on: [] +environment: + EDITION: oss image_pull_secrets: - dockerconfigjson kind: pipeline @@ -805,20 +1070,14 @@ platform: os: linux services: [] steps: -- commands: - - mkdir -p bin - - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.0.15/grabpl - - chmod +x bin/grabpl - image: byrnedo/alpine-curl:0.1.8 - name: grabpl - commands: - echo $DRONE_RUNNER_NAME - image: alpine:3.15.6 + image: alpine:3.17.1 name: identify-runner - commands: - yarn install --immutable depends_on: [] - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: yarn-install - commands: - |- @@ -830,7 +1089,7 @@ steps: wan" > words_to_ignore.txt - codespell -I words_to_ignore.txt docs/ - rm words_to_ignore.txt - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: codespell - commands: - yarn run prettier:checkDocs @@ -838,7 +1097,7 @@ steps: - yarn-install environment: NODE_OPTIONS: --max_old_space_size=8192 - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: lint-docs - commands: - mkdir -p /hugo/content/docs/grafana @@ -865,6 +1124,8 @@ volumes: clone: retries: 3 depends_on: [] +environment: + EDITION: oss image_pull_secrets: - dockerconfigjson kind: pipeline @@ -878,25 +1139,24 @@ services: [] steps: - commands: - echo $DRONE_RUNNER_NAME - image: alpine:3.15.6 + image: alpine:3.17.1 name: identify-runner - commands: - mkdir -p bin - - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.0.15/grabpl + - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.0.30/grabpl - chmod +x bin/grabpl image: byrnedo/alpine-curl:0.1.8 name: grabpl - commands: - yarn install --immutable depends_on: [] - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: yarn-install - commands: - yarn betterer ci depends_on: - yarn-install - failure: ignore - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: betterer-frontend - commands: - yarn run ci:test-frontend @@ -904,7 +1164,7 @@ steps: - yarn-install environment: TEST_MAX_WORKERS: 50% - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: test-frontend trigger: branch: main @@ -924,6 +1184,8 @@ volumes: clone: retries: 3 depends_on: [] +environment: + EDITION: oss image_pull_secrets: - dockerconfigjson kind: pipeline @@ -937,12 +1199,12 @@ services: [] steps: - commands: - echo $DRONE_RUNNER_NAME - image: alpine:3.15.6 + image: alpine:3.17.1 name: identify-runner - commands: - yarn install --immutable depends_on: [] - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: yarn-install - commands: - yarn run prettier:check @@ -953,7 +1215,7 @@ steps: - yarn-install environment: TEST_MAX_WORKERS: 50% - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: lint-frontend trigger: branch: main @@ -988,14 +1250,14 @@ services: [] steps: - commands: - echo $DRONE_RUNNER_NAME - image: alpine:3.15.6 + image: alpine:3.17.1 name: identify-runner - commands: - go build -o ./bin/build -ldflags '-extldflags -static' ./pkg/build/cmd depends_on: [] environment: CGO_ENABLED: 0 - image: golang:1.19.4 + image: golang:1.20.4 name: compile-build-cmd - commands: - '# It is required that code generated from Thema/CUE be committed and in sync @@ -1004,25 +1266,25 @@ steps: in output.' - CODEGEN_VERIFY=1 make gen-cue depends_on: [] - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: verify-gen-cue - commands: - make gen-go depends_on: - verify-gen-cue - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: wire-install - commands: - - go test -short -covermode=atomic -timeout=30m ./pkg/... + - go test -tags requires_buildifer -short -covermode=atomic -timeout=5m ./pkg/... depends_on: - wire-install - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: test-backend - commands: - - go test -run Integration -covermode=atomic -timeout=30m ./pkg/... + - go test -run Integration -covermode=atomic -timeout=5m ./pkg/... depends_on: - wire-install - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: test-backend-integration trigger: branch: main @@ -1042,6 +1304,8 @@ volumes: clone: retries: 3 depends_on: [] +environment: + EDITION: oss image_pull_secrets: - dockerconfigjson kind: pipeline @@ -1055,19 +1319,19 @@ services: [] steps: - commands: - echo $DRONE_RUNNER_NAME - image: alpine:3.15.6 + image: alpine:3.17.1 name: identify-runner - commands: - go build -o ./bin/build -ldflags '-extldflags -static' ./pkg/build/cmd depends_on: [] environment: CGO_ENABLED: 0 - image: golang:1.19.4 + image: golang:1.20.4 name: compile-build-cmd - commands: - make gen-go depends_on: [] - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: wire-install - commands: - apt-get update && apt-get install make @@ -1076,7 +1340,7 @@ steps: - wire-install environment: CGO_ENABLED: "1" - image: golang:1.19.4 + image: golang:1.20.4 name: lint-backend - commands: - ./bin/build verify-drone @@ -1102,6 +1366,8 @@ volumes: clone: retries: 3 depends_on: [] +environment: + EDITION: oss image_pull_secrets: - dockerconfigjson kind: pipeline @@ -1115,11 +1381,11 @@ services: [] steps: - commands: - echo $DRONE_RUNNER_NAME - image: alpine:3.15.6 + image: alpine:3.17.1 name: identify-runner - commands: - mkdir -p bin - - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.0.15/grabpl + - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.0.30/grabpl - chmod +x bin/grabpl image: byrnedo/alpine-curl:0.1.8 name: grabpl @@ -1128,7 +1394,7 @@ steps: depends_on: [] environment: CGO_ENABLED: 0 - image: golang:1.19.4 + image: golang:1.20.4 name: compile-build-cmd - commands: - '# It is required that code generated from Thema/CUE be committed and in sync @@ -1137,53 +1403,25 @@ steps: in output.' - CODEGEN_VERIFY=1 make gen-cue depends_on: [] - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: verify-gen-cue - commands: - make gen-go depends_on: - verify-gen-cue - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: wire-install - commands: - yarn install --immutable depends_on: [] - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: yarn-install -- commands: - - git clone "https://$${GITHUB_TOKEN}@github.com/grafana/grafana-enterprise.git" - --depth=1 - - cd grafana-enterprise - - git fetch origin "refs/tags/*:refs/tags/*" - - git tag -d $${TEST_TAG} && git push --delete origin $${TEST_TAG} && git tag $${TEST_TAG} - && git push origin $${TEST_TAG} - - cd - - - git fetch origin "refs/tags/*:refs/tags/*" - - git remote add downstream https://$${GITHUB_TOKEN}@github.com/grafana/$${DOWNSTREAM_REPO}.git - - git tag -d $${TEST_TAG} && git push --delete downstream --quiet $${TEST_TAG} && - git tag $${TEST_TAG} && git push downstream $${TEST_TAG} --quiet - environment: - DOWNSTREAM_REPO: - from_secret: downstream - GITHUB_TOKEN: - from_secret: github_token - TEST_TAG: v0.0.0-test - failure: ignore - image: grafana/build-container:1.6.6 - name: trigger-test-release - when: - paths: - include: - - .drone.yml - - pkg/build/** - repo: - - grafana/grafana - commands: - ./bin/build build-backend --jobs 8 --edition oss --build-id ${DRONE_BUILD_NUMBER} depends_on: - wire-install - compile-build-cmd - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: build-backend - commands: - ./bin/build build-frontend --jobs 8 --edition oss --build-id ${DRONE_BUILD_NUMBER} @@ -1192,7 +1430,7 @@ steps: - yarn-install environment: NODE_OPTIONS: --max_old_space_size=8192 - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: build-frontend - commands: - ./bin/build build-frontend-packages --jobs 8 --edition oss --build-id ${DRONE_BUILD_NUMBER} @@ -1201,7 +1439,7 @@ steps: - yarn-install environment: NODE_OPTIONS: --max_old_space_size=8192 - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: build-frontend-packages - commands: - ./bin/build build-plugins --jobs 8 --edition oss @@ -1211,7 +1449,7 @@ steps: environment: GRAFANA_API_KEY: from_secret: grafana_api_key - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: build-plugins - commands: - ./bin/build package --jobs 8 --edition oss --build-id ${DRONE_BUILD_NUMBER} --sign @@ -1229,7 +1467,7 @@ steps: from_secret: packages_gpg_public_key GRAFANA_API_KEY: from_secret: grafana_api_key - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: package - commands: - ./scripts/grafana-server/start-server @@ -1242,7 +1480,7 @@ steps: environment: ARCH: linux-amd64 PORT: 3001 - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: grafana-server - commands: - apt-get install -y netcat @@ -1280,11 +1518,35 @@ steps: HOST: grafana-server image: cypress/included:9.5.1-node16.14.0-slim-chrome99-ff97 name: end-to-end-tests-various-suite +- commands: + - cd / + - ./cpp-e2e/scripts/ci-run.sh azure ${DRONE_SOURCE_BRANCH} + depends_on: + - grafana-server + environment: + AZURE_SP_APP_ID: + from_secret: azure_sp_app_id + AZURE_SP_PASSWORD: + from_secret: azure_sp_app_pw + AZURE_TENANT: + from_secret: azure_tenant + CYPRESS_CI: "true" + GITHUB_TOKEN: + from_secret: github_token_pr + HOST: grafana-server + image: us-docker.pkg.dev/grafanalabs-dev/cloud-data-sources/e2e:latest + name: end-to-end-tests-cloud-plugins-suite-azure + when: + paths: + include: + - pkg/tsdb/azuremonitor/** + - public/app/plugins/datasource/grafana-azure-monitor-datasource/** + - e2e/cloud-plugins-suite/azure-monitor.spec.ts + repo: + - grafana/grafana - commands: - apt-get update - apt-get install -yq zip - - ls -lah ./e2e - - find ./e2e -type f -name "*.mp4" - printenv GCP_GRAFANA_UPLOAD_ARTIFACTS_KEY > /tmp/gcpkey_upload_artifacts.json - gcloud auth activate-service-account --key-file=/tmp/gcpkey_upload_artifacts.json - find ./e2e -type f -name "*spec.ts.mp4" | zip e2e/videos.zip -@ @@ -1306,7 +1568,8 @@ steps: from_secret: gcp_upload_artifacts_key GITHUB_TOKEN: from_secret: github_token - image: google/cloud-sdk:367.0.0 + failure: ignore + image: google/cloud-sdk:406.0.0 name: e2e-tests-artifacts-upload when: status: @@ -1314,13 +1577,13 @@ steps: - failure - commands: - yarn storybook:build - - ./bin/grabpl verify-storybook + - ./bin/build verify-storybook depends_on: - build-frontend - build-frontend-packages environment: NODE_OPTIONS: --max_old_space_size=4096 - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: build-storybook when: paths: @@ -1331,7 +1594,7 @@ steps: - cp dist/*.tar.gz* packaging/docker/ depends_on: - package - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: copy-packages-for-docker - commands: - yarn wait-on http://$HOST:$PORT @@ -1375,7 +1638,7 @@ steps: GRAFANA_MISC_STATS_API_KEY: from_secret: grafana_misc_stats_api_key failure: ignore - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: publish-frontend-metrics when: repo: @@ -1456,13 +1719,13 @@ steps: environment: NPM_TOKEN: from_secret: npm_token - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: release-canary-npm-packages when: repo: - grafana/grafana - commands: - - ./bin/grabpl upload-packages --edition oss + - ./bin/build upload-packages --edition oss depends_on: - end-to-end-tests-dashboards-suite - end-to-end-tests-panels-suite @@ -1479,7 +1742,7 @@ steps: repo: - grafana/grafana - commands: - - ./bin/grabpl upload-cdn --edition oss + - ./bin/build upload-cdn --edition oss depends_on: - grafana-server environment: @@ -1510,6 +1773,8 @@ volumes: clone: retries: 3 depends_on: [] +environment: + EDITION: oss image_pull_secrets: - dockerconfigjson kind: pipeline @@ -1543,7 +1808,7 @@ services: steps: - commands: - mkdir -p bin - - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.0.15/grabpl + - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.0.30/grabpl - chmod +x bin/grabpl image: byrnedo/alpine-curl:0.1.8 name: grabpl @@ -1552,11 +1817,11 @@ steps: depends_on: [] environment: CGO_ENABLED: 0 - image: golang:1.19.4 + image: golang:1.20.4 name: compile-build-cmd - commands: - echo $DRONE_RUNNER_NAME - image: alpine:3.15.6 + image: alpine:3.17.1 name: identify-runner - commands: - '# It is required that code generated from Thema/CUE be committed and in sync @@ -1565,13 +1830,13 @@ steps: in output.' - CODEGEN_VERIFY=1 make gen-cue depends_on: [] - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: verify-gen-cue - commands: - make gen-go depends_on: - verify-gen-cue - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: wire-install - commands: - apt-get update @@ -1580,14 +1845,14 @@ steps: - psql -p 5432 -h postgres -U grafanatest -d grafanatest -f devenv/docker/blocks/postgres_tests/setup.sql - go clean -testcache - go list './pkg/...' | xargs -I {} sh -c 'go test -run Integration -covermode=atomic - -timeout=30m {}' + -timeout=5m {}' depends_on: - wire-install environment: GRAFANA_TEST_DB: postgres PGPASSWORD: grafanatest POSTGRES_HOST: postgres - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: postgres-integration-tests - commands: - apt-get update @@ -1597,13 +1862,13 @@ steps: -prootpass - go clean -testcache - go list './pkg/...' | xargs -I {} sh -c 'go test -run Integration -covermode=atomic - -timeout=30m {}' + -timeout=5m {}' depends_on: - wire-install environment: GRAFANA_TEST_DB: mysql MYSQL_HOST: mysql - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: mysql-integration-tests trigger: branch: main @@ -1633,6 +1898,8 @@ depends_on: - main-test-backend - main-build-e2e-publish - main-integration-tests +environment: + EDITION: oss image_pull_secrets: - dockerconfigjson kind: pipeline @@ -1649,7 +1916,7 @@ steps: name: identify-runner - commands: - $$ProgressPreference = "SilentlyContinue" - - Invoke-WebRequest https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.0.15/windows/grabpl.exe + - Invoke-WebRequest https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.0.30/windows/grabpl.exe -OutFile grabpl.exe image: grafana/ci-wix:0.1.1 name: windows-init @@ -1690,95 +1957,115 @@ trigger: type: docker volumes: - host: - path: /var/run/docker.sock + path: //./pipe/docker_engine/ name: docker --- clone: retries: 3 depends_on: [] +environment: + EDITION: oss +image_pull_secrets: +- dockerconfigjson kind: pipeline -name: notify-drone-changes +name: main-oss-test-backend-windows platform: arch: amd64 - os: linux + os: windows + version: "1809" +services: [] steps: -- image: plugins/slack - name: slack - settings: - channel: slack-webhooks-test - template: "`.drone.yml` and `starlark` files have been changed on the OSS repo, - by: {{build.author}}. \nBranch: \nCommit hash: " - webhook: - from_secret: drone-changes-webhook +- commands: [] + image: grafana/grafana-ci-windows-test:0.1.0 + name: windows-init +- commands: + - go install github.com/google/wire/cmd/wire@v0.5.0 + - wire gen -tags oss ./pkg/server + depends_on: + - windows-init + image: grafana/grafana-ci-windows-test:0.1.0 + name: wire-install +- commands: + - go test -tags requires_buildifer -short -covermode=atomic -timeout=5m ./pkg/... + depends_on: + - wire-install + failure: ignore + image: grafana/grafana-ci-windows-test:0.1.0 + name: test-backend trigger: branch: main event: - push paths: exclude: - - exclude - include: - - .drone.yml - repo: - - grafana/grafana + - '*.md' + - docs/** + - latest.json type: docker +volumes: +- host: + path: //./pipe/docker_engine/ + name: docker --- clone: - retries: 3 -depends_on: -- main-test-frontend -- main-test-backend -- main-build-e2e-publish -- main-integration-tests -- main-windows + disable: true +depends_on: [] +environment: + EDITION: enterprise image_pull_secrets: - dockerconfigjson kind: pipeline -name: main-publish -node: - type: no-parallel +name: main-enterprise-test-backend-windows platform: arch: amd64 - os: linux + os: windows + version: "1809" services: [] steps: - commands: - - mkdir -p bin - - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.0.15/grabpl - - chmod +x bin/grabpl - image: byrnedo/alpine-curl:0.1.8 + - $$ProgressPreference = "SilentlyContinue" + - Invoke-WebRequest https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.0.30/windows/grabpl.exe + -OutFile grabpl.exe + image: grafana/ci-wix:0.1.1 name: grabpl - commands: - - go build -o ./bin/build -ldflags '-extldflags -static' ./pkg/build/cmd - depends_on: [] + - git clone "https://$$env:GITHUB_TOKEN@github.com/grafana/grafana-enterprise.git" + - cd grafana-enterprise + - git checkout main environment: - CGO_ENABLED: 0 - image: golang:1.19.4 - name: compile-build-cmd -- commands: - - echo $DRONE_RUNNER_NAME - image: alpine:3.15.6 - name: identify-runner + GITHUB_TOKEN: + from_secret: github_token + image: grafana/ci-wix:0.1.1 + name: clone - commands: - - ./bin/build publish packages --edition oss --gcp-key /tmp/gcpkey.json --build-id - ${DRONE_BUILD_NUMBER} + - cp -r grafana-enterprise C:\App\grafana-enterprise + - rm -r -force grafana-enterprise + - cp grabpl.exe C:\App\grabpl.exe + - rm -force grabpl.exe + - C:\App\grabpl.exe init-enterprise --github-token $$env:GITHUB_TOKEN C:\App\grafana-enterprise + main + - cp C:\App\grabpl.exe grabpl.exe depends_on: - - compile-build-cmd + - clone environment: - GCP_KEY: - from_secret: gcp_key - GPG_KEY_PASSWORD: - from_secret: packages_gpg_passphrase - GPG_PRIV_KEY: - from_secret: packages_gpg_private_key - GPG_PUB_KEY: - from_secret: packages_gpg_public_key - GRAFANA_COM_API_KEY: - from_secret: grafana_api_key - image: grafana/grafana-ci-deploy:1.3.3 - name: publish-packages-oss + GITHUB_TOKEN: + from_secret: github_token + image: grafana/ci-wix:0.1.1 + name: windows-init +- commands: + - go install github.com/google/wire/cmd/wire@v0.5.0 + - wire gen -tags enterprise ./pkg/server + depends_on: + - windows-init + image: grafana/grafana-ci-windows-test:0.1.0 + name: wire-install +- commands: + - go test -tags requires_buildifer -short -covermode=atomic -timeout=5m ./pkg/... + depends_on: + - wire-install + failure: ignore + image: grafana/grafana-ci-windows-test:0.1.0 + name: test-backend trigger: branch: main event: @@ -1788,18 +2075,51 @@ trigger: - '*.md' - docs/** - latest.json - repo: - - grafana/grafana type: docker volumes: - host: - path: /var/run/docker.sock + path: //./pipe/docker_engine/ name: docker --- +clone: + retries: 3 +depends_on: [] +kind: pipeline +name: notify-drone-changes +platform: + arch: amd64 + os: linux +steps: +- image: plugins/slack + name: slack + settings: + channel: slack-webhooks-test + template: "`.drone.yml` and `starlark` files have been changed on the OSS repo, + by: {{build.author}}. \nBranch: \nCommit hash: " + webhook: + from_secret: drone-changes-webhook +trigger: + branch: main + event: + - push + paths: + exclude: + - exclude + include: + - .drone.yml + repo: + - grafana/grafana +type: docker +--- clone: retries: 3 depends_on: -- main-publish +- main-build-e2e-publish +- main-integration-tests +environment: + EDITION: oss image_pull_secrets: - dockerconfigjson kind: pipeline @@ -1845,7 +2165,6 @@ depends_on: - main-build-e2e-publish - main-integration-tests - main-windows -- main-publish kind: pipeline name: main-notify platform: @@ -1893,11 +2212,11 @@ services: [] steps: - commands: - echo $DRONE_RUNNER_NAME - image: alpine:3.15.6 + image: alpine:3.17.1 name: identify-runner - commands: - mkdir -p bin - - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.0.15/grabpl + - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.0.30/grabpl - chmod +x bin/grabpl image: byrnedo/alpine-curl:0.1.8 name: grabpl @@ -1908,32 +2227,32 @@ steps: in output.' - CODEGEN_VERIFY=1 make gen-cue depends_on: [] - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: verify-gen-cue - commands: - make gen-go depends_on: - verify-gen-cue - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: wire-install - commands: - yarn install --immutable depends_on: [] - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: yarn-install - commands: - go build -o ./bin/build -ldflags '-extldflags -static' ./pkg/build/cmd depends_on: [] environment: CGO_ENABLED: 0 - image: golang:1.19.4 + image: golang:1.20.4 name: compile-build-cmd - commands: - ./bin/build build-backend --jobs 8 --edition oss ${DRONE_TAG} depends_on: - wire-install - compile-build-cmd - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: build-backend - commands: - ./bin/build build-frontend --jobs 8 --edition oss ${DRONE_TAG} @@ -1942,7 +2261,7 @@ steps: - yarn-install environment: NODE_OPTIONS: --max_old_space_size=8192 - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: build-frontend - commands: - ./bin/build build-frontend-packages --jobs 8 --edition oss ${DRONE_TAG} @@ -1951,7 +2270,7 @@ steps: - yarn-install environment: NODE_OPTIONS: --max_old_space_size=8192 - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: build-frontend-packages - commands: - ./bin/build build-plugins --jobs 8 --edition oss @@ -1961,7 +2280,7 @@ steps: environment: GRAFANA_API_KEY: from_secret: grafana_api_key - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: build-plugins - commands: - ./bin/build package --jobs 8 --edition oss --sign ${DRONE_TAG} @@ -1979,14 +2298,14 @@ steps: from_secret: packages_gpg_public_key GRAFANA_API_KEY: from_secret: grafana_api_key - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: package - commands: - ls dist/*.tar.gz* - cp dist/*.tar.gz* packaging/docker/ depends_on: - package - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: copy-packages-for-docker - commands: - ./bin/build build-docker --edition oss --shouldSave @@ -2025,7 +2344,7 @@ steps: environment: ARCH: linux-amd64 PORT: 3001 - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: grafana-server - commands: - apt-get install -y netcat @@ -2066,8 +2385,6 @@ steps: - commands: - apt-get update - apt-get install -yq zip - - ls -lah ./e2e - - find ./e2e -type f -name "*.mp4" - printenv GCP_GRAFANA_UPLOAD_ARTIFACTS_KEY > /tmp/gcpkey_upload_artifacts.json - gcloud auth activate-service-account --key-file=/tmp/gcpkey_upload_artifacts.json - find ./e2e -type f -name "*spec.ts.mp4" | zip e2e/videos.zip -@ @@ -2089,7 +2406,8 @@ steps: from_secret: gcp_upload_artifacts_key GITHUB_TOKEN: from_secret: github_token - image: google/cloud-sdk:367.0.0 + failure: ignore + image: google/cloud-sdk:406.0.0 name: e2e-tests-artifacts-upload when: status: @@ -2097,19 +2415,19 @@ steps: - failure - commands: - yarn storybook:build - - ./bin/grabpl verify-storybook + - ./bin/build verify-storybook depends_on: - build-frontend - build-frontend-packages environment: NODE_OPTIONS: --max_old_space_size=4096 - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: build-storybook when: event: - tag - commands: - - ./bin/grabpl upload-cdn --edition oss + - ./bin/build upload-cdn --edition oss depends_on: - grafana-server environment: @@ -2120,7 +2438,7 @@ steps: image: grafana/grafana-ci-deploy:1.3.3 name: upload-cdn-assets - commands: - - ./bin/grabpl upload-packages --edition oss + - ./bin/build upload-packages --edition oss depends_on: - end-to-end-tests-dashboards-suite - end-to-end-tests-panels-suite @@ -2153,40 +2471,37 @@ steps: event: - tag - commands: - - ./bin/grabpl artifacts npm store --tag ${DRONE_TAG} + - ./bin/build artifacts npm store --tag ${DRONE_TAG} depends_on: + - compile-build-cmd - build-frontend-packages environment: GCP_KEY: from_secret: gcp_key PRERELEASE_BUCKET: from_secret: prerelease_bucket - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: store-npm-packages trigger: event: exclude: - promote ref: - - refs/tags/v* - repo: exclude: - - grafana/grafana + - refs/tags/*-cloud* + include: + - refs/tags/v* type: docker volumes: - host: path: /var/run/docker.sock name: docker -- name: postgres - temp: - medium: memory -- name: mysql - temp: - medium: memory --- clone: retries: 3 depends_on: [] +environment: + EDITION: oss image_pull_secrets: - dockerconfigjson kind: pipeline @@ -2200,25 +2515,24 @@ services: [] steps: - commands: - echo $DRONE_RUNNER_NAME - image: alpine:3.15.6 + image: alpine:3.17.1 name: identify-runner - commands: - mkdir -p bin - - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.0.15/grabpl + - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.0.30/grabpl - chmod +x bin/grabpl image: byrnedo/alpine-curl:0.1.8 name: grabpl - commands: - yarn install --immutable depends_on: [] - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: yarn-install - commands: - yarn betterer ci depends_on: - yarn-install - failure: ignore - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: betterer-frontend - commands: - yarn run ci:test-frontend @@ -2226,17 +2540,17 @@ steps: - yarn-install environment: TEST_MAX_WORKERS: 50% - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: test-frontend trigger: event: exclude: - promote ref: - - refs/tags/v* - repo: exclude: - - grafana/grafana + - refs/tags/*-cloud* + include: + - refs/tags/v* type: docker volumes: - host: @@ -2261,14 +2575,14 @@ services: [] steps: - commands: - echo $DRONE_RUNNER_NAME - image: alpine:3.15.6 + image: alpine:3.17.1 name: identify-runner - commands: - go build -o ./bin/build -ldflags '-extldflags -static' ./pkg/build/cmd depends_on: [] environment: CGO_ENABLED: 0 - image: golang:1.19.4 + image: golang:1.20.4 name: compile-build-cmd - commands: - '# It is required that code generated from Thema/CUE be committed and in sync @@ -2277,35 +2591,35 @@ steps: in output.' - CODEGEN_VERIFY=1 make gen-cue depends_on: [] - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: verify-gen-cue - commands: - make gen-go depends_on: - verify-gen-cue - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: wire-install - commands: - - go test -short -covermode=atomic -timeout=30m ./pkg/... + - go test -tags requires_buildifer -short -covermode=atomic -timeout=5m ./pkg/... depends_on: - wire-install - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: test-backend - commands: - - go test -run Integration -covermode=atomic -timeout=30m ./pkg/... + - go test -run Integration -covermode=atomic -timeout=5m ./pkg/... depends_on: - wire-install - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: test-backend-integration trigger: event: exclude: - promote ref: - - refs/tags/v* - repo: exclude: - - grafana/grafana + - refs/tags/*-cloud* + include: + - refs/tags/v* type: docker volumes: - host: @@ -2320,119 +2634,51 @@ environment: image_pull_secrets: - dockerconfigjson kind: pipeline -name: release-oss-integration-tests -node: - type: no-parallel +name: release-oss-test-backend-windows platform: arch: amd64 - os: linux -services: -- environment: - PGDATA: /var/lib/postgresql/data/pgdata - POSTGRES_DB: grafanatest - POSTGRES_PASSWORD: grafanatest - POSTGRES_USER: grafanatest - image: postgres:12.3-alpine - name: postgres - volumes: - - name: postgres - path: /var/lib/postgresql/data/pgdata -- environment: - MYSQL_DATABASE: grafana_tests - MYSQL_PASSWORD: password - MYSQL_ROOT_PASSWORD: rootpass - MYSQL_USER: grafana - image: mysql:5.7.39 - name: mysql - volumes: - - name: mysql - path: /var/lib/mysql + os: windows + version: "1809" +services: [] steps: +- commands: [] + image: grafana/grafana-ci-windows-test:0.1.0 + name: windows-init - commands: - - mkdir -p bin - - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.0.15/grabpl - - chmod +x bin/grabpl - image: byrnedo/alpine-curl:0.1.8 - name: grabpl -- commands: - - echo $DRONE_RUNNER_NAME - image: alpine:3.15.6 - name: identify-runner -- commands: - - '# It is required that code generated from Thema/CUE be committed and in sync - with its inputs.' - - '# The following command will fail if running code generators produces any diff - in output.' - - CODEGEN_VERIFY=1 make gen-cue - depends_on: [] - image: grafana/build-container:1.6.6 - name: verify-gen-cue -- commands: - - make gen-go + - go install github.com/google/wire/cmd/wire@v0.5.0 + - wire gen -tags oss ./pkg/server depends_on: - - verify-gen-cue - image: grafana/build-container:1.6.6 + - windows-init + image: grafana/grafana-ci-windows-test:0.1.0 name: wire-install - commands: - - apt-get update - - apt-get install -yq postgresql-client - - dockerize -wait tcp://postgres:5432 -timeout 120s - - psql -p 5432 -h postgres -U grafanatest -d grafanatest -f devenv/docker/blocks/postgres_tests/setup.sql - - go clean -testcache - - go list './pkg/...' | xargs -I {} sh -c 'go test -run Integration -covermode=atomic - -timeout=30m {}' - depends_on: - - wire-install - environment: - GRAFANA_TEST_DB: postgres - PGPASSWORD: grafanatest - POSTGRES_HOST: postgres - image: grafana/build-container:1.6.6 - name: postgres-integration-tests -- commands: - - apt-get update - - apt-get install -yq default-mysql-client - - dockerize -wait tcp://mysql:3306 -timeout 120s - - cat devenv/docker/blocks/mysql_tests/setup.sql | mysql -h mysql -P 3306 -u root - -prootpass - - go clean -testcache - - go list './pkg/...' | xargs -I {} sh -c 'go test -run Integration -covermode=atomic - -timeout=30m {}' + - go test -tags requires_buildifer -short -covermode=atomic -timeout=5m ./pkg/... depends_on: - wire-install - environment: - GRAFANA_TEST_DB: mysql - MYSQL_HOST: mysql - image: grafana/build-container:1.6.6 - name: mysql-integration-tests + failure: ignore + image: grafana/grafana-ci-windows-test:0.1.0 + name: test-backend trigger: event: exclude: - promote ref: - - refs/tags/v* - repo: exclude: - - grafana/grafana + - refs/tags/*-cloud* + include: + - refs/tags/v* type: docker volumes: - host: - path: /var/run/docker.sock + path: //./pipe/docker_engine/ name: docker -- name: postgres - temp: - medium: memory -- name: mysql - temp: - medium: memory --- clone: retries: 3 depends_on: - release-oss-build-e2e-publish - release-oss-test-frontend -- release-oss-test-backend -- release-oss-integration-tests +- release-oss-test-backend-windows environment: EDITION: oss image_pull_secrets: @@ -2451,7 +2697,7 @@ steps: name: identify-runner - commands: - $$ProgressPreference = "SilentlyContinue" - - Invoke-WebRequest https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.0.15/windows/grabpl.exe + - Invoke-WebRequest https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.0.30/windows/grabpl.exe -OutFile grabpl.exe image: grafana/ci-wix:0.1.1 name: windows-init @@ -2483,14 +2729,14 @@ trigger: exclude: - promote ref: - - refs/tags/v* - repo: exclude: - - grafana/grafana + - refs/tags/*-cloud* + include: + - refs/tags/v* type: docker volumes: - host: - path: /var/run/docker.sock + path: //./pipe/docker_engine/ name: docker --- clone: @@ -2511,13 +2757,13 @@ services: [] steps: - commands: - mkdir -p bin - - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.0.15/grabpl + - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.0.30/grabpl - chmod +x bin/grabpl image: byrnedo/alpine-curl:0.1.8 name: grabpl - commands: - echo $DRONE_RUNNER_NAME - image: alpine:3.15.6 + image: alpine:3.17.1 name: identify-runner - commands: - git clone "https://$${GITHUB_TOKEN}@github.com/grafana/grafana-enterprise.git" @@ -2526,7 +2772,7 @@ steps: environment: GITHUB_TOKEN: from_secret: github_token - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: clone-enterprise - commands: - mv bin/grabpl /tmp/ @@ -2539,10 +2785,11 @@ steps: - mv /tmp/grabpl bin/ depends_on: - clone-enterprise + - grabpl environment: GITHUB_TOKEN: from_secret: github_token - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: init-enterprise - commands: - go build -o ./bin/build -ldflags '-extldflags -static' ./pkg/build/cmd @@ -2550,19 +2797,19 @@ steps: - init-enterprise environment: CGO_ENABLED: 0 - image: golang:1.19.4 + image: golang:1.20.4 name: compile-build-cmd - commands: - make gen-go depends_on: - init-enterprise - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: wire-install - commands: - yarn install --immutable depends_on: - init-enterprise - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: yarn-install - commands: - '# It is required that code generated from Thema/CUE be committed and in sync @@ -2572,14 +2819,14 @@ steps: - CODEGEN_VERIFY=1 make gen-cue depends_on: - init-enterprise - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: verify-gen-cue - commands: - ./bin/build build-backend --jobs 8 --edition enterprise ${DRONE_TAG} depends_on: - wire-install - compile-build-cmd - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: build-backend - commands: - ./bin/build build-frontend --jobs 8 --edition enterprise ${DRONE_TAG} @@ -2588,7 +2835,7 @@ steps: - yarn-install environment: NODE_OPTIONS: --max_old_space_size=8192 - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: build-frontend - commands: - ./bin/build build-frontend-packages --jobs 8 --edition enterprise ${DRONE_TAG} @@ -2597,7 +2844,7 @@ steps: - yarn-install environment: NODE_OPTIONS: --max_old_space_size=8192 - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: build-frontend-packages - commands: - ./bin/build build-plugins --jobs 8 --edition enterprise @@ -2607,15 +2854,8 @@ steps: environment: GRAFANA_API_KEY: from_secret: grafana_api_key - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: build-plugins -- commands: - - ./bin/build build-backend --jobs 8 --edition enterprise2 ${DRONE_TAG} - depends_on: - - wire-install - - compile-build-cmd - image: grafana/build-container:1.6.6 - name: build-backend-enterprise2 - commands: - ./bin/build package --jobs 8 --edition enterprise --sign ${DRONE_TAG} depends_on: @@ -2623,7 +2863,6 @@ steps: - build-backend - build-frontend - build-frontend-packages - - build-backend-enterprise2 environment: GPG_KEY_PASSWORD: from_secret: packages_gpg_passphrase @@ -2633,14 +2872,14 @@ steps: from_secret: packages_gpg_public_key GRAFANA_API_KEY: from_secret: grafana_api_key - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: package - commands: - ls dist/*.tar.gz* - cp dist/*.tar.gz* packaging/docker/ depends_on: - package - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: copy-packages-for-docker - commands: - ./bin/build build-docker --edition enterprise --shouldSave @@ -2680,7 +2919,7 @@ steps: ARCH: linux-amd64 PORT: 3001 RUNDIR: scripts/grafana-server/tmp-grafana-enterprise - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: grafana-server - commands: - apt-get install -y netcat @@ -2721,8 +2960,6 @@ steps: - commands: - apt-get update - apt-get install -yq zip - - ls -lah ./e2e - - find ./e2e -type f -name "*.mp4" - printenv GCP_GRAFANA_UPLOAD_ARTIFACTS_KEY > /tmp/gcpkey_upload_artifacts.json - gcloud auth activate-service-account --key-file=/tmp/gcpkey_upload_artifacts.json - find ./e2e -type f -name "*spec.ts.mp4" | zip e2e/videos.zip -@ @@ -2744,14 +2981,15 @@ steps: from_secret: gcp_upload_artifacts_key GITHUB_TOKEN: from_secret: github_token - image: google/cloud-sdk:367.0.0 + failure: ignore + image: google/cloud-sdk:406.0.0 name: e2e-tests-artifacts-upload when: status: - success - failure - commands: - - ./bin/grabpl upload-cdn --edition enterprise + - ./bin/build upload-cdn --edition enterprise depends_on: - package environment: @@ -2762,7 +3000,7 @@ steps: image: grafana/grafana-ci-deploy:1.3.3 name: upload-cdn-assets - commands: - - ./bin/grabpl upload-packages --edition enterprise + - ./bin/build upload-packages --edition enterprise depends_on: - package environment: @@ -2772,82 +3010,26 @@ steps: from_secret: prerelease_bucket image: grafana/grafana-ci-deploy:1.3.3 name: upload-packages -- commands: - - ./bin/build package --jobs 8 --edition enterprise2 --sign ${DRONE_TAG} - depends_on: - - build-plugins - - build-backend - - build-frontend - - build-frontend-packages - - build-backend-enterprise2 - environment: - GPG_KEY_PASSWORD: - from_secret: packages_gpg_passphrase - GPG_PRIV_KEY: - from_secret: packages_gpg_private_key - GPG_PUB_KEY: - from_secret: packages_gpg_public_key - GRAFANA_API_KEY: - from_secret: grafana_api_key - image: grafana/build-container:1.6.6 - name: package-enterprise2 -- commands: - - ./bin/grabpl upload-cdn --edition enterprise2 - depends_on: - - package-enterprise2 - environment: - GCP_KEY: - from_secret: gcp_key - PRERELEASE_BUCKET: - from_secret: prerelease_bucket - image: grafana/grafana-ci-deploy:1.3.3 - name: upload-cdn-assets-enterprise2 -- commands: - - ./bin/grabpl artifacts npm store --tag ${DRONE_TAG} - depends_on: - - build-frontend-packages - environment: - GCP_KEY: - from_secret: gcp_key - PRERELEASE_BUCKET: - from_secret: prerelease_bucket - image: grafana/build-container:1.6.6 - name: store-npm-packages -- commands: - - ./bin/grabpl upload-packages --edition enterprise2 - depends_on: - - package-enterprise2 - environment: - GCP_KEY: - from_secret: gcp_key - PRERELEASE_BUCKET: - from_secret: prerelease_bucket - image: grafana/grafana-ci-deploy:1.3.3 - name: upload-packages-enterprise2 trigger: event: exclude: - promote ref: - - refs/tags/v* - repo: exclude: - - grafana/grafana + - refs/tags/*-cloud* + include: + - refs/tags/v* type: docker volumes: - host: path: /var/run/docker.sock name: docker -- name: postgres - temp: - medium: memory -- name: mysql - temp: - medium: memory --- clone: disable: true depends_on: [] +environment: + EDITION: enterprise image_pull_secrets: - dockerconfigjson kind: pipeline @@ -2859,6 +3041,12 @@ platform: os: linux services: [] steps: +- commands: + - mkdir -p bin + - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.0.30/grabpl + - chmod +x bin/grabpl + image: byrnedo/alpine-curl:0.1.8 + name: grabpl - commands: - git clone "https://$${GITHUB_TOKEN}@github.com/grafana/grafana-enterprise.git" - cd grafana-enterprise @@ -2866,7 +3054,7 @@ steps: environment: GITHUB_TOKEN: from_secret: github_token - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: clone-enterprise - commands: - mv bin/grabpl /tmp/ @@ -2879,34 +3067,28 @@ steps: - mv /tmp/grabpl bin/ depends_on: - clone-enterprise + - grabpl environment: GITHUB_TOKEN: from_secret: github_token - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: init-enterprise - commands: - echo $DRONE_RUNNER_NAME - image: alpine:3.15.6 + image: alpine:3.17.1 name: identify-runner -- commands: - - mkdir -p bin - - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.0.15/grabpl - - chmod +x bin/grabpl - image: byrnedo/alpine-curl:0.1.8 - name: grabpl - commands: - yarn install --immutable depends_on: - init-enterprise - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: yarn-install - commands: - yarn betterer ci depends_on: - init-enterprise - yarn-install - failure: ignore - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: betterer-frontend - commands: - yarn run ci:test-frontend @@ -2915,17 +3097,17 @@ steps: - yarn-install environment: TEST_MAX_WORKERS: 50% - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: test-frontend trigger: event: exclude: - promote ref: - - refs/tags/v* - repo: exclude: - - grafana/grafana + - refs/tags/*-cloud* + include: + - refs/tags/v* type: docker volumes: - host: @@ -2955,11 +3137,11 @@ steps: environment: GITHUB_TOKEN: from_secret: github_token - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: clone-enterprise - commands: - mkdir -p bin - - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.0.15/grabpl + - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.0.30/grabpl - chmod +x bin/grabpl image: byrnedo/alpine-curl:0.1.8 name: grabpl @@ -2974,14 +3156,15 @@ steps: - mv /tmp/grabpl bin/ depends_on: - clone-enterprise + - grabpl environment: GITHUB_TOKEN: from_secret: github_token - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: init-enterprise - commands: - echo $DRONE_RUNNER_NAME - image: alpine:3.15.6 + image: alpine:3.17.1 name: identify-runner - commands: - go build -o ./bin/build -ldflags '-extldflags -static' ./pkg/build/cmd @@ -2989,7 +3172,7 @@ steps: - init-enterprise environment: CGO_ENABLED: 0 - image: golang:1.19.4 + image: golang:1.20.4 name: compile-build-cmd - commands: - '# It is required that code generated from Thema/CUE be committed and in sync @@ -2999,35 +3182,35 @@ steps: - CODEGEN_VERIFY=1 make gen-cue depends_on: - init-enterprise - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: verify-gen-cue - commands: - make gen-go depends_on: - verify-gen-cue - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: wire-install - commands: - - go test -short -covermode=atomic -timeout=30m ./pkg/... + - go test -tags requires_buildifer -short -covermode=atomic -timeout=5m ./pkg/... depends_on: - wire-install - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: test-backend - commands: - - go test -run Integration -covermode=atomic -timeout=30m ./pkg/... + - go test -run Integration -covermode=atomic -timeout=5m ./pkg/... depends_on: - wire-install - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: test-backend-integration trigger: event: exclude: - promote ref: - - refs/tags/v* - repo: exclude: - - grafana/grafana + - refs/tags/*-cloud* + include: + - refs/tags/v* type: docker volumes: - host: @@ -3036,157 +3219,116 @@ volumes: --- clone: disable: true -depends_on: [] +depends_on: +- release-enterprise-build-e2e-publish +- release-enterprise-test-frontend +- release-enterprise-test-backend environment: - EDITION: enterprise2 + EDITION: enterprise image_pull_secrets: - dockerconfigjson kind: pipeline -name: release-enterprise2-test-backend -node: - type: no-parallel +name: release-enterprise-windows platform: arch: amd64 - os: linux + os: windows + version: "1809" services: [] steps: - commands: - - git clone "https://$${GITHUB_TOKEN}@github.com/grafana/grafana-enterprise.git" + - echo $env:DRONE_RUNNER_NAME + image: mcr.microsoft.com/windows:1809 + name: identify-runner +- commands: + - $$ProgressPreference = "SilentlyContinue" + - Invoke-WebRequest https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.0.30/windows/grabpl.exe + -OutFile grabpl.exe + - git clone "https://$$env:GITHUB_TOKEN@github.com/grafana/grafana-enterprise.git" - cd grafana-enterprise - git checkout ${DRONE_TAG} environment: GITHUB_TOKEN: from_secret: github_token - image: grafana/build-container:1.6.6 - name: clone-enterprise -- commands: - - mkdir -p bin - - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.0.15/grabpl - - chmod +x bin/grabpl - image: byrnedo/alpine-curl:0.1.8 - name: grabpl + image: grafana/ci-wix:0.1.1 + name: clone - commands: - - mv bin/grabpl /tmp/ - - rmdir bin - - mv grafana-enterprise /tmp/ - - /tmp/grabpl init-enterprise --github-token $${GITHUB_TOKEN} /tmp/grafana-enterprise + - cp -r grafana-enterprise C:\App\grafana-enterprise + - rm -r -force grafana-enterprise + - cp grabpl.exe C:\App\grabpl.exe + - rm -force grabpl.exe + - C:\App\grabpl.exe init-enterprise --github-token $$env:GITHUB_TOKEN C:\App\grafana-enterprise ${DRONE_TAG} - - mv /tmp/grafana-enterprise/deployment_tools_config.json deployment_tools_config.json - - mkdir bin - - mv /tmp/grabpl bin/ + - cp C:\App\grabpl.exe grabpl.exe depends_on: - - clone-enterprise + - clone environment: GITHUB_TOKEN: from_secret: github_token - image: grafana/build-container:1.6.6 - name: init-enterprise -- commands: - - echo $DRONE_RUNNER_NAME - image: alpine:3.15.6 - name: identify-runner + image: grafana/ci-wix:0.1.1 + name: windows-init - commands: - - go build -o ./bin/build -ldflags '-extldflags -static' ./pkg/build/cmd + - $$gcpKey = $$env:GCP_KEY + - '[System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($$gcpKey)) + > gcpkey.json' + - dos2unix gcpkey.json + - gcloud auth activate-service-account --key-file=gcpkey.json + - rm gcpkey.json + - cp C:\App\nssm-2.24.zip . + - .\grabpl.exe windows-installer --edition enterprise ${DRONE_TAG} + - $$fname = ((Get-Childitem grafana*.msi -name) -split "`n")[0] + - gsutil cp $$fname gs://%PRERELEASE_BUCKET%/artifacts/downloads/${DRONE_TAG}/enterprise/release/ + - gsutil cp "$$fname.sha256" gs://%PRERELEASE_BUCKET%/artifacts/downloads/${DRONE_TAG}/enterprise/release/ depends_on: - - init-enterprise + - windows-init environment: - CGO_ENABLED: 0 - image: golang:1.19.4 - name: compile-build-cmd -- commands: - - '# It is required that code generated from Thema/CUE be committed and in sync - with its inputs.' - - '# The following command will fail if running code generators produces any diff - in output.' - - CODEGEN_VERIFY=1 make gen-cue - depends_on: - - init-enterprise - image: grafana/build-container:1.6.6 - name: verify-gen-cue -- commands: - - make gen-go - depends_on: - - verify-gen-cue - image: grafana/build-container:1.6.6 - name: wire-install -- commands: - - go test -tags=pro -covermode=atomic -timeout=30m ./pkg/... - depends_on: - - wire-install - image: grafana/build-container:1.6.6 - name: test-backend-enterprise2 -- commands: - - go test -run Integration -covermode=atomic -timeout=30m ./pkg/... - depends_on: - - wire-install - image: grafana/build-container:1.6.6 - name: test-backend-integration + GCP_KEY: + from_secret: gcp_key + GITHUB_TOKEN: + from_secret: github_token + PRERELEASE_BUCKET: + from_secret: prerelease_bucket + image: grafana/ci-wix:0.1.1 + name: build-windows-installer trigger: event: exclude: - promote ref: - - refs/tags/v* - repo: exclude: - - grafana/grafana + - refs/tags/*-cloud* + include: + - refs/tags/v* type: docker volumes: - host: - path: /var/run/docker.sock + path: //./pipe/docker_engine/ name: docker --- clone: disable: true depends_on: [] environment: - EDITION: enterprise + EDITION: enterprise2 image_pull_secrets: - dockerconfigjson kind: pipeline -name: release-enterprise-integration-tests +name: release-enterprise2-build-e2e-publish node: type: no-parallel platform: arch: amd64 os: linux -services: -- environment: - PGDATA: /var/lib/postgresql/data/pgdata - POSTGRES_DB: grafanatest - POSTGRES_PASSWORD: grafanatest - POSTGRES_USER: grafanatest - image: postgres:12.3-alpine - name: postgres - volumes: - - name: postgres - path: /var/lib/postgresql/data/pgdata -- environment: - MYSQL_DATABASE: grafana_tests - MYSQL_PASSWORD: password - MYSQL_ROOT_PASSWORD: rootpass - MYSQL_USER: grafana - image: mysql:5.7.39 - name: mysql - volumes: - - name: mysql - path: /var/lib/mysql -- environment: {} - image: redis:6.2.1-alpine - name: redis -- environment: {} - image: memcached:1.6.9-alpine - name: memcached +services: [] steps: - commands: - mkdir -p bin - - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.0.15/grabpl + - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.0.30/grabpl - chmod +x bin/grabpl image: byrnedo/alpine-curl:0.1.8 name: grabpl - commands: - echo $DRONE_RUNNER_NAME - image: alpine:3.15.6 + image: alpine:3.17.1 name: identify-runner - commands: - git clone "https://$${GITHUB_TOKEN}@github.com/grafana/grafana-enterprise.git" @@ -3195,7 +3337,7 @@ steps: environment: GITHUB_TOKEN: from_secret: github_token - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: clone-enterprise - commands: - mv bin/grabpl /tmp/ @@ -3208,11 +3350,32 @@ steps: - mv /tmp/grabpl bin/ depends_on: - clone-enterprise + - grabpl environment: GITHUB_TOKEN: from_secret: github_token - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: init-enterprise +- commands: + - go build -o ./bin/build -ldflags '-extldflags -static' ./pkg/build/cmd + depends_on: + - init-enterprise + environment: + CGO_ENABLED: 0 + image: golang:1.20.4 + name: compile-build-cmd +- commands: + - make gen-go + depends_on: + - init-enterprise + image: grafana/build-container:1.7.4 + name: wire-install +- commands: + - yarn install --immutable + depends_on: + - init-enterprise + image: grafana/build-container:1.7.4 + name: yarn-install - commands: - '# It is required that code generated from Thema/CUE be committed and in sync with its inputs.' @@ -3221,238 +3384,119 @@ steps: - CODEGEN_VERIFY=1 make gen-cue depends_on: - init-enterprise - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: verify-gen-cue - commands: - - make gen-go + - ./bin/build build-frontend --jobs 8 --edition enterprise ${DRONE_TAG} depends_on: - - verify-gen-cue - image: grafana/build-container:1.6.6 - name: wire-install + - compile-build-cmd + - yarn-install + environment: + NODE_OPTIONS: --max_old_space_size=8192 + image: grafana/build-container:1.7.4 + name: build-frontend - commands: - - apt-get update - - apt-get install -yq postgresql-client - - dockerize -wait tcp://postgres:5432 -timeout 120s - - psql -p 5432 -h postgres -U grafanatest -d grafanatest -f devenv/docker/blocks/postgres_tests/setup.sql - - go clean -testcache - - go list './pkg/...' | xargs -I {} sh -c 'go test -run Integration -covermode=atomic - -timeout=30m {}' + - ./bin/build build-frontend-packages --jobs 8 --edition enterprise ${DRONE_TAG} depends_on: - - wire-install + - compile-build-cmd + - yarn-install environment: - GRAFANA_TEST_DB: postgres - PGPASSWORD: grafanatest - POSTGRES_HOST: postgres - image: grafana/build-container:1.6.6 - name: postgres-integration-tests + NODE_OPTIONS: --max_old_space_size=8192 + image: grafana/build-container:1.7.4 + name: build-frontend-packages - commands: - - apt-get update - - apt-get install -yq default-mysql-client - - dockerize -wait tcp://mysql:3306 -timeout 120s - - cat devenv/docker/blocks/mysql_tests/setup.sql | mysql -h mysql -P 3306 -u root - -prootpass - - go clean -testcache - - go list './pkg/...' | xargs -I {} sh -c 'go test -run Integration -covermode=atomic - -timeout=30m {}' + - ./bin/build build-plugins --jobs 8 --edition enterprise depends_on: - - wire-install + - compile-build-cmd + - yarn-install environment: - GRAFANA_TEST_DB: mysql - MYSQL_HOST: mysql - image: grafana/build-container:1.6.6 - name: mysql-integration-tests + GRAFANA_API_KEY: + from_secret: grafana_api_key + image: grafana/build-container:1.7.4 + name: build-plugins - commands: - - dockerize -wait tcp://redis:6379/0 -timeout 120s - - ./bin/grabpl integration-tests + - ./bin/build build-backend --jobs 8 --edition enterprise2 ${DRONE_TAG} depends_on: - wire-install - environment: - REDIS_URL: redis://redis:6379/0 - image: grafana/build-container:1.6.6 - name: redis-integration-tests -- commands: - - dockerize -wait tcp://memcached:11211 -timeout 120s - - ./bin/grabpl integration-tests - depends_on: - - wire-install - environment: - MEMCACHED_HOSTS: memcached:11211 - image: grafana/build-container:1.6.6 - name: memcached-integration-tests -trigger: - event: - exclude: - - promote - ref: - - refs/tags/v* - repo: - exclude: - - grafana/grafana -type: docker -volumes: -- host: - path: /var/run/docker.sock - name: docker -- name: postgres - temp: - medium: memory -- name: mysql - temp: - medium: memory ---- -clone: - disable: true -depends_on: -- release-enterprise-build-e2e-publish -- release-enterprise-test-frontend -- release-enterprise-test-backend -- release-enterprise-integration-tests -environment: - EDITION: enterprise -image_pull_secrets: -- dockerconfigjson -kind: pipeline -name: release-enterprise-windows -platform: - arch: amd64 - os: windows - version: "1809" -services: [] -steps: -- commands: - - echo $env:DRONE_RUNNER_NAME - image: mcr.microsoft.com/windows:1809 - name: identify-runner -- commands: - - $$ProgressPreference = "SilentlyContinue" - - Invoke-WebRequest https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.0.15/windows/grabpl.exe - -OutFile grabpl.exe - - git clone "https://$$env:GITHUB_TOKEN@github.com/grafana/grafana-enterprise.git" - - cd grafana-enterprise - - git checkout ${DRONE_TAG} - environment: - GITHUB_TOKEN: - from_secret: github_token - image: grafana/ci-wix:0.1.1 - name: clone + - compile-build-cmd + image: grafana/build-container:1.7.4 + name: build-backend-enterprise2 - commands: - - cp -r grafana-enterprise C:\App\grafana-enterprise - - rm -r -force grafana-enterprise - - cp grabpl.exe C:\App\grabpl.exe - - rm -force grabpl.exe - - C:\App\grabpl.exe init-enterprise --github-token $$env:GITHUB_TOKEN C:\App\grafana-enterprise - - cp C:\App\grabpl.exe grabpl.exe + - ./bin/build package --jobs 8 --edition enterprise2 --sign ${DRONE_TAG} depends_on: - - clone + - build-plugins + - build-backend-enterprise2 + - build-frontend + - build-frontend-packages environment: - GITHUB_TOKEN: - from_secret: github_token - image: grafana/ci-wix:0.1.1 - name: windows-init + GPG_KEY_PASSWORD: + from_secret: packages_gpg_passphrase + GPG_PRIV_KEY: + from_secret: packages_gpg_private_key + GPG_PUB_KEY: + from_secret: packages_gpg_public_key + GRAFANA_API_KEY: + from_secret: grafana_api_key + image: grafana/build-container:1.7.4 + name: package-enterprise2 - commands: - - $$gcpKey = $$env:GCP_KEY - - '[System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($$gcpKey)) - > gcpkey.json' - - dos2unix gcpkey.json - - gcloud auth activate-service-account --key-file=gcpkey.json - - rm gcpkey.json - - cp C:\App\nssm-2.24.zip . - - .\grabpl.exe windows-installer --edition enterprise ${DRONE_TAG} - - $$fname = ((Get-Childitem grafana*.msi -name) -split "`n")[0] - - gsutil cp $$fname gs://%PRERELEASE_BUCKET%/artifacts/downloads/${DRONE_TAG}/enterprise/release/ - - gsutil cp "$$fname.sha256" gs://%PRERELEASE_BUCKET%/artifacts/downloads/${DRONE_TAG}/enterprise/release/ + - ./bin/build upload-cdn --edition enterprise2 depends_on: - - windows-init + - package-enterprise2 environment: + ENTERPRISE2_CDN_PATH: + from_secret: enterprise2-cdn-path GCP_KEY: from_secret: gcp_key - GITHUB_TOKEN: - from_secret: github_token PRERELEASE_BUCKET: from_secret: prerelease_bucket - image: grafana/ci-wix:0.1.1 - name: build-windows-installer -trigger: - event: - exclude: - - promote - ref: - - refs/tags/v* - repo: - exclude: - - grafana/grafana -type: docker -volumes: -- host: - path: /var/run/docker.sock - name: docker ---- -clone: - retries: 3 -depends_on: [] -image_pull_secrets: -- dockerconfigjson -kind: pipeline -name: publish-docker-oss-public -node: - type: no-parallel -platform: - arch: amd64 - os: linux -services: [] -steps: -- commands: - - mkdir -p bin - - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.0.15/grabpl - - chmod +x bin/grabpl - image: byrnedo/alpine-curl:0.1.8 - name: grabpl + image: grafana/grafana-ci-deploy:1.3.3 + name: upload-cdn-assets-enterprise2 - commands: - - go build -o ./bin/build -ldflags '-extldflags -static' ./pkg/build/cmd - depends_on: [] - environment: - CGO_ENABLED: 0 - image: golang:1.19.4 - name: compile-build-cmd + - ls dist/*.tar.gz* + - cp dist/*.tar.gz* packaging/docker/ + depends_on: + - package-enterprise2 + image: grafana/build-container:1.7.4 + name: copy-packages-for-docker - commands: - - ./bin/build artifacts docker fetch --edition oss + - ./bin/build build-docker --edition enterprise2 --shouldSave depends_on: + - copy-packages-for-docker - compile-build-cmd environment: - DOCKER_PASSWORD: - from_secret: docker_password - DOCKER_USER: - from_secret: docker_username + DOCKER_ENTERPRISE2_REPO: + from_secret: docker_enterprise2_repo GCP_KEY: from_secret: gcp_key image: google/cloud-sdk - name: fetch-images-oss + name: build-docker-images volumes: - name: docker path: /var/run/docker.sock - commands: - - ./bin/grabpl artifacts docker publish --dockerhub-repo grafana/grafana --version-tag - ${TAG} + - ./bin/build build-docker --edition enterprise2 --shouldSave --ubuntu depends_on: - - fetch-images-oss + - copy-packages-for-docker + - compile-build-cmd environment: - DOCKER_PASSWORD: - from_secret: docker_password - DOCKER_USER: - from_secret: docker_username + DOCKER_ENTERPRISE2_REPO: + from_secret: docker_enterprise2_repo GCP_KEY: from_secret: gcp_key image: google/cloud-sdk - name: publish-images-grafana/grafana + name: build-docker-images-ubuntu volumes: - name: docker path: /var/run/docker.sock - commands: - - ./bin/grabpl artifacts docker publish --dockerhub-repo grafana/grafana-oss --version-tag - ${TAG} + - ./bin/build artifacts docker fetch --edition enterprise2 depends_on: - - fetch-images-oss + - build-docker-images + - build-docker-images-ubuntu environment: + DOCKER_ENTERPRISE2_REPO: + from_secret: docker_enterprise2_repo DOCKER_PASSWORD: from_secret: docker_password DOCKER_USER: @@ -3460,99 +3504,69 @@ steps: GCP_KEY: from_secret: gcp_key image: google/cloud-sdk - name: publish-images-grafana/grafana-oss + name: fetch-images-enterprise2 volumes: - name: docker path: /var/run/docker.sock -trigger: - event: - - promote - target: - - public -type: docker -volumes: -- host: - path: /var/run/docker.sock - name: docker ---- -clone: - retries: 3 -depends_on: [] -image_pull_secrets: -- dockerconfigjson -kind: pipeline -name: publish-docker-enterprise-public -node: - type: no-parallel -platform: - arch: amd64 - os: linux -services: [] -steps: -- commands: - - mkdir -p bin - - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.0.15/grabpl - - chmod +x bin/grabpl - image: byrnedo/alpine-curl:0.1.8 - name: grabpl -- commands: - - go build -o ./bin/build -ldflags '-extldflags -static' ./pkg/build/cmd - depends_on: [] - environment: - CGO_ENABLED: 0 - image: golang:1.19.4 - name: compile-build-cmd - commands: - - ./bin/build artifacts docker fetch --edition enterprise + - ./bin/build artifacts docker publish-enterprise2 --dockerhub-repo $${DOCKER_ENTERPRISE2_REPO} depends_on: - - compile-build-cmd + - fetch-images-enterprise2 environment: + DOCKER_ENTERPRISE2_REPO: + from_secret: docker_enterprise2_repo DOCKER_PASSWORD: from_secret: docker_password DOCKER_USER: from_secret: docker_username GCP_KEY: - from_secret: gcp_key + from_secret: gcp_key_hg image: google/cloud-sdk - name: fetch-images-enterprise + name: publish-images-enterprise2 volumes: - name: docker path: /var/run/docker.sock - commands: - - ./bin/grabpl artifacts docker publish --dockerhub-repo grafana/grafana-enterprise - --version-tag ${TAG} + - ./bin/build upload-packages --edition enterprise2 depends_on: - - fetch-images-enterprise + - package-enterprise2 environment: - DOCKER_PASSWORD: - from_secret: docker_password - DOCKER_USER: - from_secret: docker_username GCP_KEY: from_secret: gcp_key - image: google/cloud-sdk - name: publish-images-grafana/grafana-enterprise - volumes: - - name: docker - path: /var/run/docker.sock + PRERELEASE_BUCKET: + from_secret: prerelease_bucket + image: grafana/grafana-ci-deploy:1.3.3 + name: upload-packages-enterprise2 trigger: event: - - promote - target: - - public + exclude: + - promote + ref: + exclude: + - refs/tags/*-cloud* + include: + - refs/tags/v* type: docker volumes: - host: path: /var/run/docker.sock name: docker +- name: postgres + temp: + medium: memory +- name: mysql + temp: + medium: memory --- clone: - retries: 3 + disable: true depends_on: [] +environment: + EDITION: enterprise2 image_pull_secrets: - dockerconfigjson kind: pipeline -name: publish-docker-enterprise-security +name: custom-release-enterprise2-build-e2e-publish node: type: no-parallel platform: @@ -3562,22 +3576,181 @@ services: [] steps: - commands: - mkdir -p bin - - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.0.15/grabpl + - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.0.30/grabpl - chmod +x bin/grabpl image: byrnedo/alpine-curl:0.1.8 name: grabpl - commands: - - go build -o ./bin/build -ldflags '-extldflags -static' ./pkg/build/cmd - depends_on: [] - environment: - CGO_ENABLED: 0 - image: golang:1.19.4 - name: compile-build-cmd -- commands: - - ./bin/build artifacts docker fetch --edition enterprise + - echo $DRONE_RUNNER_NAME + image: alpine:3.17.1 + name: identify-runner +- commands: + - git clone "https://$${GITHUB_TOKEN}@github.com/grafana/grafana-enterprise.git" + - cd grafana-enterprise + - git checkout ${DRONE_TARGET_BRANCH} + environment: + GITHUB_TOKEN: + from_secret: github_token + image: grafana/build-container:1.7.4 + name: clone-enterprise +- commands: + - mv bin/grabpl /tmp/ + - rmdir bin + - mv grafana-enterprise /tmp/ + - /tmp/grabpl init-enterprise --github-token $${GITHUB_TOKEN} /tmp/grafana-enterprise + ${DRONE_TAG} + - mv /tmp/grafana-enterprise/deployment_tools_config.json deployment_tools_config.json + - mkdir bin + - mv /tmp/grabpl bin/ + depends_on: + - clone-enterprise + - grabpl + environment: + GITHUB_TOKEN: + from_secret: github_token + image: grafana/build-container:1.7.4 + name: init-enterprise +- commands: + - go build -o ./bin/build -ldflags '-extldflags -static' ./pkg/build/cmd + depends_on: + - init-enterprise + environment: + CGO_ENABLED: 0 + image: golang:1.20.4 + name: compile-build-cmd +- commands: + - make gen-go + depends_on: + - init-enterprise + image: grafana/build-container:1.7.4 + name: wire-install +- commands: + - yarn install --immutable + depends_on: + - init-enterprise + image: grafana/build-container:1.7.4 + name: yarn-install +- commands: + - '# It is required that code generated from Thema/CUE be committed and in sync + with its inputs.' + - '# The following command will fail if running code generators produces any diff + in output.' + - CODEGEN_VERIFY=1 make gen-cue + depends_on: + - init-enterprise + image: grafana/build-container:1.7.4 + name: verify-gen-cue +- commands: + - ./bin/build build-frontend --jobs 8 --edition enterprise ${DRONE_TAG} + depends_on: + - compile-build-cmd + - yarn-install + environment: + NODE_OPTIONS: --max_old_space_size=8192 + image: grafana/build-container:1.7.4 + name: build-frontend +- commands: + - ./bin/build build-frontend-packages --jobs 8 --edition enterprise ${DRONE_TAG} + depends_on: + - compile-build-cmd + - yarn-install + environment: + NODE_OPTIONS: --max_old_space_size=8192 + image: grafana/build-container:1.7.4 + name: build-frontend-packages +- commands: + - ./bin/build build-plugins --jobs 8 --edition enterprise + depends_on: + - compile-build-cmd + - yarn-install + environment: + GRAFANA_API_KEY: + from_secret: grafana_api_key + image: grafana/build-container:1.7.4 + name: build-plugins +- commands: + - ./bin/build build-backend --jobs 8 --edition enterprise2 ${DRONE_TAG} + depends_on: + - wire-install + - compile-build-cmd + image: grafana/build-container:1.7.4 + name: build-backend-enterprise2 +- commands: + - ./bin/build package --jobs 8 --edition enterprise2 --sign ${DRONE_TAG} + depends_on: + - build-plugins + - build-backend-enterprise2 + - build-frontend + - build-frontend-packages + environment: + GPG_KEY_PASSWORD: + from_secret: packages_gpg_passphrase + GPG_PRIV_KEY: + from_secret: packages_gpg_private_key + GPG_PUB_KEY: + from_secret: packages_gpg_public_key + GRAFANA_API_KEY: + from_secret: grafana_api_key + image: grafana/build-container:1.7.4 + name: package-enterprise2 +- commands: + - ./bin/build upload-cdn --edition enterprise2 + depends_on: + - package-enterprise2 + environment: + ENTERPRISE2_CDN_PATH: + from_secret: enterprise2-cdn-path + GCP_KEY: + from_secret: gcp_key + PRERELEASE_BUCKET: + from_secret: prerelease_bucket + image: grafana/grafana-ci-deploy:1.3.3 + name: upload-cdn-assets-enterprise2 +- commands: + - ls dist/*.tar.gz* + - cp dist/*.tar.gz* packaging/docker/ + depends_on: + - package-enterprise2 + image: grafana/build-container:1.7.4 + name: copy-packages-for-docker +- commands: + - ./bin/build build-docker --edition enterprise2 --shouldSave + depends_on: + - copy-packages-for-docker + - compile-build-cmd + environment: + DOCKER_ENTERPRISE2_REPO: + from_secret: docker_enterprise2_repo + GCP_KEY: + from_secret: gcp_key + image: google/cloud-sdk + name: build-docker-images + volumes: + - name: docker + path: /var/run/docker.sock +- commands: + - ./bin/build build-docker --edition enterprise2 --shouldSave --ubuntu depends_on: + - copy-packages-for-docker - compile-build-cmd environment: + DOCKER_ENTERPRISE2_REPO: + from_secret: docker_enterprise2_repo + GCP_KEY: + from_secret: gcp_key + image: google/cloud-sdk + name: build-docker-images-ubuntu + volumes: + - name: docker + path: /var/run/docker.sock +- commands: + - ./bin/build artifacts docker fetch --edition enterprise2 + depends_on: + - build-docker-images + - build-docker-images-ubuntu + environment: + DOCKER_ENTERPRISE2_REPO: + from_secret: docker_enterprise2_repo DOCKER_PASSWORD: from_secret: docker_password DOCKER_USER: @@ -3585,45 +3758,63 @@ steps: GCP_KEY: from_secret: gcp_key image: google/cloud-sdk - name: fetch-images-enterprise + name: fetch-images-enterprise2 volumes: - name: docker path: /var/run/docker.sock - commands: - - ./bin/grabpl artifacts docker publish --security --dockerhub-repo grafana/grafana-enterprise - --version-tag ${TAG} + - ./bin/build artifacts docker publish-enterprise2 --dockerhub-repo $${DOCKER_ENTERPRISE2_REPO} depends_on: - - fetch-images-enterprise + - fetch-images-enterprise2 environment: + DOCKER_ENTERPRISE2_REPO: + from_secret: docker_enterprise2_repo DOCKER_PASSWORD: from_secret: docker_password DOCKER_USER: from_secret: docker_username GCP_KEY: - from_secret: gcp_key + from_secret: gcp_key_hg image: google/cloud-sdk - name: publish-images-grafana/grafana-enterprise + name: publish-images-enterprise2 volumes: - name: docker path: /var/run/docker.sock +- commands: + - ./bin/build upload-packages --edition enterprise2 + depends_on: + - package-enterprise2 + environment: + GCP_KEY: + from_secret: gcp_key + PRERELEASE_BUCKET: + from_secret: prerelease_bucket + image: grafana/grafana-ci-deploy:1.3.3 + name: upload-packages-enterprise2 trigger: event: - - promote - target: - - security + - custom type: docker volumes: - host: path: /var/run/docker.sock name: docker +- name: postgres + temp: + medium: memory +- name: mysql + temp: + medium: memory --- clone: retries: 3 depends_on: [] +environment: + EDITION: oss image_pull_secrets: - dockerconfigjson kind: pipeline -name: publish-artifacts-security +name: publish-docker-oss-public node: type: no-parallel platform: @@ -3631,28 +3822,80 @@ platform: os: linux services: [] steps: +- commands: + - echo $DRONE_RUNNER_NAME + image: alpine:3.17.1 + name: identify-runner - commands: - mkdir -p bin - - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.0.15/grabpl + - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.0.30/grabpl - chmod +x bin/grabpl image: byrnedo/alpine-curl:0.1.8 name: grabpl - commands: - - ./bin/grabpl artifacts publish --security --tag ${TAG} --src-bucket $${PRERELEASE_BUCKET} + - go build -o ./bin/build -ldflags '-extldflags -static' ./pkg/build/cmd + depends_on: [] + environment: + CGO_ENABLED: 0 + image: golang:1.20.4 + name: compile-build-cmd +- commands: + - ./bin/build artifacts docker fetch --edition oss depends_on: - - grabpl + - compile-build-cmd environment: + DOCKER_ENTERPRISE2_REPO: + from_secret: docker_enterprise2_repo + DOCKER_PASSWORD: + from_secret: docker_password + DOCKER_USER: + from_secret: docker_username GCP_KEY: from_secret: gcp_key - PRERELEASE_BUCKET: - from_secret: prerelease_bucket - image: grafana/grafana-ci-deploy:1.3.3 - name: publish-artifacts + image: google/cloud-sdk + name: fetch-images-oss + volumes: + - name: docker + path: /var/run/docker.sock +- commands: + - ./bin/grabpl artifacts docker publish --dockerhub-repo grafana/grafana --version-tag + ${DRONE_TAG} + depends_on: + - fetch-images-oss + environment: + DOCKER_PASSWORD: + from_secret: docker_password + DOCKER_USER: + from_secret: docker_username + GCP_KEY: + from_secret: gcp_key + image: google/cloud-sdk + name: publish-images-grafana/grafana + volumes: + - name: docker + path: /var/run/docker.sock +- commands: + - ./bin/grabpl artifacts docker publish --dockerhub-repo grafana/grafana-oss --version-tag + ${DRONE_TAG} + depends_on: + - fetch-images-oss + environment: + DOCKER_PASSWORD: + from_secret: docker_password + DOCKER_USER: + from_secret: docker_username + GCP_KEY: + from_secret: gcp_key + image: google/cloud-sdk + name: publish-images-grafana/grafana-oss + volumes: + - name: docker + path: /var/run/docker.sock trigger: event: - promote target: - - security + - public type: docker volumes: - host: @@ -3662,10 +3905,12 @@ volumes: clone: retries: 3 depends_on: [] +environment: + EDITION: enterprise image_pull_secrets: - dockerconfigjson kind: pipeline -name: publish-artifacts-public +name: publish-docker-enterprise-public node: type: no-parallel platform: @@ -3673,24 +3918,59 @@ platform: os: linux services: [] steps: +- commands: + - echo $DRONE_RUNNER_NAME + image: alpine:3.17.1 + name: identify-runner - commands: - mkdir -p bin - - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.0.15/grabpl + - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.0.30/grabpl - chmod +x bin/grabpl image: byrnedo/alpine-curl:0.1.8 name: grabpl - commands: - - ./bin/grabpl artifacts publish --tag ${TAG} --src-bucket $${PRERELEASE_BUCKET} + - go build -o ./bin/build -ldflags '-extldflags -static' ./pkg/build/cmd + depends_on: [] + environment: + CGO_ENABLED: 0 + image: golang:1.20.4 + name: compile-build-cmd +- commands: + - ./bin/build artifacts docker fetch --edition enterprise depends_on: - - grabpl + - compile-build-cmd environment: + DOCKER_ENTERPRISE2_REPO: + from_secret: docker_enterprise2_repo + DOCKER_PASSWORD: + from_secret: docker_password + DOCKER_USER: + from_secret: docker_username GCP_KEY: from_secret: gcp_key - PRERELEASE_BUCKET: - from_secret: prerelease_bucket - image: grafana/grafana-ci-deploy:1.3.3 - name: publish-artifacts -trigger: + image: google/cloud-sdk + name: fetch-images-enterprise + volumes: + - name: docker + path: /var/run/docker.sock +- commands: + - ./bin/grabpl artifacts docker publish --dockerhub-repo grafana/grafana-enterprise + --version-tag ${DRONE_TAG} + depends_on: + - fetch-images-enterprise + environment: + DOCKER_PASSWORD: + from_secret: docker_password + DOCKER_USER: + from_secret: docker_username + GCP_KEY: + from_secret: gcp_key + image: google/cloud-sdk + name: publish-images-grafana/grafana-enterprise + volumes: + - name: docker + path: /var/run/docker.sock +trigger: event: - promote target: @@ -3704,10 +3984,12 @@ volumes: clone: retries: 3 depends_on: [] +environment: + EDITION: enterprise image_pull_secrets: - dockerconfigjson kind: pipeline -name: publish-npm-packages-public +name: publish-docker-enterprise-security node: type: no-parallel platform: @@ -3715,44 +3997,63 @@ platform: os: linux services: [] steps: +- commands: + - echo $DRONE_RUNNER_NAME + image: alpine:3.17.1 + name: identify-runner - commands: - mkdir -p bin - - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.0.15/grabpl + - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.0.30/grabpl - chmod +x bin/grabpl image: byrnedo/alpine-curl:0.1.8 name: grabpl - commands: - - yarn install --immutable + - go build -o ./bin/build -ldflags '-extldflags -static' ./pkg/build/cmd depends_on: [] - image: grafana/build-container:1.6.6 - name: yarn-install + environment: + CGO_ENABLED: 0 + image: golang:1.20.4 + name: compile-build-cmd - commands: - - ./bin/grabpl artifacts npm retrieve --tag v${TAG} + - ./bin/build artifacts docker fetch --edition enterprise depends_on: - - yarn-install + - compile-build-cmd environment: + DOCKER_ENTERPRISE2_REPO: + from_secret: docker_enterprise2_repo + DOCKER_PASSWORD: + from_secret: docker_password + DOCKER_USER: + from_secret: docker_username GCP_KEY: from_secret: gcp_key - PRERELEASE_BUCKET: - from_secret: prerelease_bucket - failure: ignore - image: grafana/grafana-ci-deploy:1.3.3 - name: retrieve-npm-packages + image: google/cloud-sdk + name: fetch-images-enterprise + volumes: + - name: docker + path: /var/run/docker.sock - commands: - - ./bin/grabpl artifacts npm release --tag v${TAG} + - ./bin/grabpl artifacts docker publish --security --dockerhub-repo grafana/grafana-enterprise + --version-tag ${DRONE_TAG} depends_on: - - retrieve-npm-packages + - fetch-images-enterprise environment: - NPM_TOKEN: - from_secret: npm_token - failure: ignore - image: grafana/build-container:1.6.6 - name: release-npm-packages + DOCKER_PASSWORD: + from_secret: docker_password + DOCKER_USER: + from_secret: docker_username + GCP_KEY: + from_secret: gcp_key + image: google/cloud-sdk + name: publish-images-grafana/grafana-enterprise + volumes: + - name: docker + path: /var/run/docker.sock trigger: event: - promote target: - - public + - security type: docker volumes: - host: @@ -3761,14 +4062,13 @@ volumes: --- clone: retries: 3 -depends_on: -- publish-artifacts-public -- publish-docker-oss-public -- publish-docker-enterprise-public +depends_on: [] +environment: + EDITION: enterprise2 image_pull_secrets: - dockerconfigjson kind: pipeline -name: publish-packages-oss +name: publish-github-public node: type: no-parallel platform: @@ -3776,91 +4076,42 @@ platform: os: linux services: [] steps: -- commands: - - mkdir -p bin - - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.0.15/grabpl - - chmod +x bin/grabpl - image: byrnedo/alpine-curl:0.1.8 - name: grabpl - commands: - go build -o ./bin/build -ldflags '-extldflags -static' ./pkg/build/cmd depends_on: [] environment: CGO_ENABLED: 0 - image: golang:1.19.4 + image: golang:1.20.4 name: compile-build-cmd - commands: - - ./bin/build publish packages --edition oss --gcp-key /tmp/gcpkey.json ${DRONE_TAG} + - ./bin/build artifacts docker fetch --edition enterprise2 depends_on: - compile-build-cmd environment: + DOCKER_ENTERPRISE2_REPO: + from_secret: docker_enterprise2_repo + DOCKER_PASSWORD: + from_secret: docker_password + DOCKER_USER: + from_secret: docker_username GCP_KEY: from_secret: gcp_key - GPG_KEY_PASSWORD: - from_secret: packages_gpg_passphrase - GPG_PRIV_KEY: - from_secret: packages_gpg_private_key - GPG_PUB_KEY: - from_secret: packages_gpg_public_key - GRAFANA_COM_API_KEY: - from_secret: grafana_api_key - image: grafana/grafana-ci-deploy:1.3.3 - name: publish-packages-oss + image: google/cloud-sdk + name: fetch-images-enterprise2 + volumes: + - name: docker + path: /var/run/docker.sock - commands: - - ./bin/build publish grafana-com --edition oss ${DRONE_TAG} + - ./bin/build publish github --repo $${GH_REGISTRY} --create depends_on: - - publish-packages-oss + - fetch-images-enterprise2 environment: - GCP_KEY: - from_secret: gcp_key - GRAFANA_COM_API_KEY: - from_secret: grafana_api_key + GH_REGISTRY: + from_secret: gh_registry + GH_TOKEN: + from_secret: github_token image: grafana/grafana-ci-deploy:1.3.3 - name: publish-grafanacom-oss -- depends_on: - - grabpl - failure: ignore - image: us.gcr.io/kubernetes-dev/package-publish:latest - name: publish-linux-packages-deb - privileged: true - settings: - access_key_id: - from_secret: packages_access_key_id - deb_distribution: auto - gpg_passphrase: - from_secret: packages_gpg_passphrase - gpg_private_key: - from_secret: packages_gpg_private_key - gpg_public_key: - from_secret: packages_gpg_public_key - package_path: gs://grafana-prerelease/artifacts/downloads/*${DRONE_TAG}/oss/**.deb - secret_access_key: - from_secret: packages_secret_access_key - service_account_json: - from_secret: packages_service_account - target_bucket: grafana-packages -- depends_on: - - grabpl - failure: ignore - image: us.gcr.io/kubernetes-dev/package-publish:latest - name: publish-linux-packages-rpm - privileged: true - settings: - access_key_id: - from_secret: packages_access_key_id - deb_distribution: auto - gpg_passphrase: - from_secret: packages_gpg_passphrase - gpg_private_key: - from_secret: packages_gpg_private_key - gpg_public_key: - from_secret: packages_gpg_public_key - package_path: gs://grafana-prerelease/artifacts/downloads/*${DRONE_TAG}/oss/**.rpm - secret_access_key: - from_secret: packages_secret_access_key - service_account_json: - from_secret: packages_service_account - target_bucket: grafana-packages + name: publish-github trigger: event: - promote @@ -3874,14 +4125,13 @@ volumes: --- clone: retries: 3 -depends_on: -- publish-artifacts-public -- publish-docker-oss-public -- publish-docker-enterprise-public +depends_on: [] +environment: + EDITION: enterprise2 image_pull_secrets: - dockerconfigjson kind: pipeline -name: publish-packages-enterprise +name: publish-github-security node: type: no-parallel platform: @@ -3889,96 +4139,47 @@ platform: os: linux services: [] steps: -- commands: - - mkdir -p bin - - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.0.15/grabpl - - chmod +x bin/grabpl - image: byrnedo/alpine-curl:0.1.8 - name: grabpl - commands: - go build -o ./bin/build -ldflags '-extldflags -static' ./pkg/build/cmd depends_on: [] environment: CGO_ENABLED: 0 - image: golang:1.19.4 + image: golang:1.20.4 name: compile-build-cmd - commands: - - ./bin/build publish packages --edition enterprise --gcp-key /tmp/gcpkey.json ${DRONE_TAG} + - ./bin/build artifacts docker fetch --edition enterprise2 depends_on: - compile-build-cmd environment: + DOCKER_ENTERPRISE2_REPO: + from_secret: docker_enterprise2_repo + DOCKER_PASSWORD: + from_secret: docker_password + DOCKER_USER: + from_secret: docker_username GCP_KEY: from_secret: gcp_key - GPG_KEY_PASSWORD: - from_secret: packages_gpg_passphrase - GPG_PRIV_KEY: - from_secret: packages_gpg_private_key - GPG_PUB_KEY: - from_secret: packages_gpg_public_key - GRAFANA_COM_API_KEY: - from_secret: grafana_api_key - image: grafana/grafana-ci-deploy:1.3.3 - name: publish-packages-enterprise + image: google/cloud-sdk + name: fetch-images-enterprise2 + volumes: + - name: docker + path: /var/run/docker.sock - commands: - - ./bin/build publish grafana-com --edition enterprise ${DRONE_TAG} + - ./bin/build publish github --repo $${GH_REGISTRY} --create depends_on: - - publish-packages-enterprise + - fetch-images-enterprise2 environment: - GCP_KEY: - from_secret: gcp_key - GRAFANA_COM_API_KEY: - from_secret: grafana_api_key + GH_REGISTRY: + from_secret: gh_registry + GH_TOKEN: + from_secret: github_token image: grafana/grafana-ci-deploy:1.3.3 - name: publish-grafanacom-enterprise -- depends_on: - - grabpl - failure: ignore - image: us.gcr.io/kubernetes-dev/package-publish:latest - name: publish-linux-packages-deb - privileged: true - settings: - access_key_id: - from_secret: packages_access_key_id - deb_distribution: auto - gpg_passphrase: - from_secret: packages_gpg_passphrase - gpg_private_key: - from_secret: packages_gpg_private_key - gpg_public_key: - from_secret: packages_gpg_public_key - package_path: gs://grafana-prerelease/artifacts/downloads/*${DRONE_TAG}/enterprise/**.deb - secret_access_key: - from_secret: packages_secret_access_key - service_account_json: - from_secret: packages_service_account - target_bucket: grafana-packages -- depends_on: - - grabpl - failure: ignore - image: us.gcr.io/kubernetes-dev/package-publish:latest - name: publish-linux-packages-rpm - privileged: true - settings: - access_key_id: - from_secret: packages_access_key_id - deb_distribution: auto - gpg_passphrase: - from_secret: packages_gpg_passphrase - gpg_private_key: - from_secret: packages_gpg_private_key - gpg_public_key: - from_secret: packages_gpg_public_key - package_path: gs://grafana-prerelease/artifacts/downloads/*${DRONE_TAG}/enterprise/**.rpm - secret_access_key: - from_secret: packages_secret_access_key - service_account_json: - from_secret: packages_service_account - target_bucket: grafana-packages + name: publish-github trigger: event: - promote target: - - public + - security type: docker volumes: - host: @@ -3987,11 +4188,14 @@ volumes: --- clone: retries: 3 -depends_on: [] +depends_on: +- publish-docker-enterprise-public +environment: + EDITION: enterprise2 image_pull_secrets: - dockerconfigjson kind: pipeline -name: publish-artifacts-page +name: publish-aws-marketplace-public node: type: no-parallel platform: @@ -4000,24 +4204,34 @@ platform: services: [] steps: - commands: - - mkdir -p bin - - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.0.15/grabpl - - chmod +x bin/grabpl - image: byrnedo/alpine-curl:0.1.8 - name: grabpl + - go build -o ./bin/build -ldflags '-extldflags -static' ./pkg/build/cmd + depends_on: [] + environment: + CGO_ENABLED: 0 + image: golang:1.20.4 + name: compile-build-cmd - commands: - - ./bin/grabpl artifacts-page + - ./bin/build publish aws --image grafana/grafana-enterprise --repo grafana-labs/grafanaenterprise + --product 422b46fb-bea6-4f27-8bcc-832117bd627e depends_on: - - grabpl + - compile-build-cmd environment: - GCP_KEY: - from_secret: gcp_key - image: grafana/build-container:1.6.6 - name: artifacts-page + AWS_ACCESS_KEY_ID: + from_secret: aws_access_key_id + AWS_REGION: + from_secret: aws_region + AWS_SECRET_ACCESS_KEY: + from_secret: aws_secret_access_key + image: grafana/grafana-ci-deploy:1.3.3 + name: publish-aws-marketplace + volumes: + - name: docker + path: /var/run/docker.sock trigger: event: - promote - target: security + target: + - public type: docker volumes: - host: @@ -4028,11 +4242,11 @@ clone: retries: 3 depends_on: [] environment: - EDITION: oss + EDITION: all image_pull_secrets: - dockerconfigjson kind: pipeline -name: release-branch-oss-build-e2e-publish +name: publish-artifacts-security node: type: no-parallel platform: @@ -4040,277 +4254,134 @@ platform: os: linux services: [] steps: -- commands: - - echo $DRONE_RUNNER_NAME - image: alpine:3.15.6 - name: identify-runner -- commands: - - mkdir -p bin - - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.0.15/grabpl - - chmod +x bin/grabpl - image: byrnedo/alpine-curl:0.1.8 - name: grabpl -- commands: - - '# It is required that code generated from Thema/CUE be committed and in sync - with its inputs.' - - '# The following command will fail if running code generators produces any diff - in output.' - - CODEGEN_VERIFY=1 make gen-cue - depends_on: [] - image: grafana/build-container:1.6.6 - name: verify-gen-cue -- commands: - - make gen-go - depends_on: - - verify-gen-cue - image: grafana/build-container:1.6.6 - name: wire-install -- commands: - - yarn install --immutable - depends_on: [] - image: grafana/build-container:1.6.6 - name: yarn-install - commands: - go build -o ./bin/build -ldflags '-extldflags -static' ./pkg/build/cmd depends_on: [] environment: CGO_ENABLED: 0 - image: golang:1.19.4 + image: golang:1.20.4 name: compile-build-cmd - commands: - - ./bin/build build-backend --jobs 8 --edition oss --build-id ${DRONE_BUILD_NUMBER} - depends_on: - - wire-install - - compile-build-cmd - image: grafana/build-container:1.6.6 - name: build-backend -- commands: - - ./bin/build build-frontend --jobs 8 --edition oss --build-id ${DRONE_BUILD_NUMBER} - depends_on: - - compile-build-cmd - - yarn-install - environment: - NODE_OPTIONS: --max_old_space_size=8192 - image: grafana/build-container:1.6.6 - name: build-frontend -- commands: - - ./bin/build build-frontend-packages --jobs 8 --edition oss --build-id ${DRONE_BUILD_NUMBER} - depends_on: - - compile-build-cmd - - yarn-install - environment: - NODE_OPTIONS: --max_old_space_size=8192 - image: grafana/build-container:1.6.6 - name: build-frontend-packages -- commands: - - ./bin/build build-plugins --jobs 8 --edition oss - depends_on: - - compile-build-cmd - - yarn-install - environment: - GRAFANA_API_KEY: - from_secret: grafana_api_key - image: grafana/build-container:1.6.6 - name: build-plugins -- commands: - - ./bin/build package --jobs 8 --edition oss --build-id ${DRONE_BUILD_NUMBER} --sign - depends_on: - - build-plugins - - build-backend - - build-frontend - - build-frontend-packages - environment: - GPG_KEY_PASSWORD: - from_secret: packages_gpg_passphrase - GPG_PRIV_KEY: - from_secret: packages_gpg_private_key - GPG_PUB_KEY: - from_secret: packages_gpg_public_key - GRAFANA_API_KEY: - from_secret: grafana_api_key - image: grafana/build-container:1.6.6 - name: package -- commands: - - ls dist/*.tar.gz* - - cp dist/*.tar.gz* packaging/docker/ - depends_on: - - package - image: grafana/build-container:1.6.6 - name: copy-packages-for-docker -- commands: - - ./bin/build build-docker --edition oss --shouldSave + - ./bin/build artifacts packages --security --tag $${DRONE_TAG} --src-bucket $${PRERELEASE_BUCKET} depends_on: - - copy-packages-for-docker - compile-build-cmd environment: + ENTERPRISE2_SECURITY_PREFIX: + from_secret: enterprise2_security_prefix GCP_KEY: from_secret: gcp_key - image: google/cloud-sdk - name: build-docker-images - volumes: - - name: docker - path: /var/run/docker.sock + PRERELEASE_BUCKET: + from_secret: prerelease_bucket + SECURITY_DEST_BUCKET: + from_secret: security_dest_bucket + image: grafana/grafana-ci-deploy:1.3.3 + name: publish-artifacts - commands: - - ./bin/build build-docker --edition oss --shouldSave --ubuntu + - ./bin/build artifacts static-assets --tag ${DRONE_TAG} depends_on: - - copy-packages-for-docker - compile-build-cmd environment: GCP_KEY: from_secret: gcp_key - image: google/cloud-sdk - name: build-docker-images-ubuntu - volumes: - - name: docker + PRERELEASE_BUCKET: + from_secret: prerelease_bucket + STATIC_ASSET_EDITIONS: + from_secret: static_asset_editions + image: grafana/grafana-ci-deploy:1.3.3 + name: publish-static-assets +trigger: + event: + - promote + target: + - security +type: docker +volumes: +- host: path: /var/run/docker.sock + name: docker +--- +clone: + retries: 3 +depends_on: [] +environment: + EDITION: all +image_pull_secrets: +- dockerconfigjson +kind: pipeline +name: publish-artifacts-public +node: + type: no-parallel +platform: + arch: amd64 + os: linux +services: [] +steps: - commands: - - ./scripts/grafana-server/start-server - depends_on: - - build-plugins - - build-backend - - build-frontend - - build-frontend-packages - detach: true - environment: - ARCH: linux-amd64 - PORT: 3001 - image: grafana/build-container:1.6.6 - name: grafana-server -- commands: - - apt-get install -y netcat - - ./bin/build e2e-tests --port 3001 --suite dashboards-suite --tries 3 - depends_on: - - grafana-server - environment: - HOST: grafana-server - image: cypress/included:9.5.1-node16.14.0-slim-chrome99-ff97 - name: end-to-end-tests-dashboards-suite -- commands: - - apt-get install -y netcat - - ./bin/build e2e-tests --port 3001 --suite smoke-tests-suite --tries 3 - depends_on: - - grafana-server - environment: - HOST: grafana-server - image: cypress/included:9.5.1-node16.14.0-slim-chrome99-ff97 - name: end-to-end-tests-smoke-tests-suite -- commands: - - apt-get install -y netcat - - ./bin/build e2e-tests --port 3001 --suite panels-suite --tries 3 - depends_on: - - grafana-server - environment: - HOST: grafana-server - image: cypress/included:9.5.1-node16.14.0-slim-chrome99-ff97 - name: end-to-end-tests-panels-suite -- commands: - - apt-get install -y netcat - - ./bin/build e2e-tests --port 3001 --suite various-suite --tries 3 - depends_on: - - grafana-server - environment: - HOST: grafana-server - image: cypress/included:9.5.1-node16.14.0-slim-chrome99-ff97 - name: end-to-end-tests-various-suite -- commands: - - apt-get update - - apt-get install -yq zip - - ls -lah ./e2e - - find ./e2e -type f -name "*.mp4" - - printenv GCP_GRAFANA_UPLOAD_ARTIFACTS_KEY > /tmp/gcpkey_upload_artifacts.json - - gcloud auth activate-service-account --key-file=/tmp/gcpkey_upload_artifacts.json - - find ./e2e -type f -name "*spec.ts.mp4" | zip e2e/videos.zip -@ - - gsutil cp e2e/videos.zip gs://$${E2E_TEST_ARTIFACTS_BUCKET}/${DRONE_BUILD_NUMBER}/artifacts/videos/videos.zip - - export E2E_ARTIFACTS_VIDEO_ZIP=https://storage.googleapis.com/$${E2E_TEST_ARTIFACTS_BUCKET}/${DRONE_BUILD_NUMBER}/artifacts/videos/videos.zip - - 'echo "E2E Test artifacts uploaded to: $${E2E_ARTIFACTS_VIDEO_ZIP}"' - - 'curl -X POST https://api.github.com/repos/${DRONE_REPO}/statuses/${DRONE_COMMIT_SHA} - -H "Authorization: token $${GITHUB_TOKEN}" -d "{\"state\":\"success\",\"target_url\":\"$${E2E_ARTIFACTS_VIDEO_ZIP}\", - \"description\": \"Click on the details to download e2e recording videos\", \"context\": - \"e2e_artifacts\"}"' - depends_on: - - end-to-end-tests-dashboards-suite - - end-to-end-tests-panels-suite - - end-to-end-tests-smoke-tests-suite - - end-to-end-tests-various-suite + - go build -o ./bin/build -ldflags '-extldflags -static' ./pkg/build/cmd + depends_on: [] environment: - E2E_TEST_ARTIFACTS_BUCKET: releng-pipeline-artifacts-dev - GCP_GRAFANA_UPLOAD_ARTIFACTS_KEY: - from_secret: gcp_upload_artifacts_key - GITHUB_TOKEN: - from_secret: github_token - image: google/cloud-sdk:367.0.0 - name: e2e-tests-artifacts-upload - when: - status: - - success - - failure + CGO_ENABLED: 0 + image: golang:1.20.4 + name: compile-build-cmd - commands: - - yarn storybook:build - - ./bin/grabpl verify-storybook + - ./bin/build artifacts packages --tag $${DRONE_TAG} --src-bucket $${PRERELEASE_BUCKET} depends_on: - - build-frontend - - build-frontend-packages + - compile-build-cmd environment: - NODE_OPTIONS: --max_old_space_size=4096 - image: grafana/build-container:1.6.6 - name: build-storybook - when: - paths: - include: - - packages/grafana-ui/** + ENTERPRISE2_SECURITY_PREFIX: + from_secret: enterprise2_security_prefix + GCP_KEY: + from_secret: gcp_key + PRERELEASE_BUCKET: + from_secret: prerelease_bucket + SECURITY_DEST_BUCKET: + from_secret: security_dest_bucket + image: grafana/grafana-ci-deploy:1.3.3 + name: publish-artifacts - commands: - - ./bin/grabpl upload-cdn --edition oss + - ./bin/build artifacts static-assets --tag ${DRONE_TAG} depends_on: - - grafana-server + - compile-build-cmd environment: GCP_KEY: from_secret: gcp_key PRERELEASE_BUCKET: from_secret: prerelease_bucket + STATIC_ASSET_EDITIONS: + from_secret: static_asset_editions image: grafana/grafana-ci-deploy:1.3.3 - name: upload-cdn-assets - when: - repo: - - grafana/grafana + name: publish-static-assets - commands: - - ./bin/grabpl upload-packages --edition oss + - ./bin/build artifacts storybook --tag ${DRONE_TAG} depends_on: - - end-to-end-tests-dashboards-suite - - end-to-end-tests-panels-suite - - end-to-end-tests-smoke-tests-suite - - end-to-end-tests-various-suite + - compile-build-cmd environment: GCP_KEY: from_secret: gcp_key PRERELEASE_BUCKET: from_secret: prerelease_bucket image: grafana/grafana-ci-deploy:1.3.3 - name: upload-packages - when: - repo: - - grafana/grafana + name: publish-storybook trigger: - ref: - - refs/heads/v[0-9]* + event: + - promote + target: + - public type: docker volumes: - host: path: /var/run/docker.sock name: docker -- name: postgres - temp: - medium: memory -- name: mysql - temp: - medium: memory --- clone: retries: 3 depends_on: [] +environment: + EDITION: all image_pull_secrets: - dockerconfigjson kind: pipeline -name: release-branch-oss-test-frontend +name: publish-npm-packages-public node: type: no-parallel platform: @@ -4319,38 +4390,46 @@ platform: services: [] steps: - commands: - - echo $DRONE_RUNNER_NAME - image: alpine:3.15.6 - name: identify-runner -- commands: - - mkdir -p bin - - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.0.15/grabpl - - chmod +x bin/grabpl - image: byrnedo/alpine-curl:0.1.8 - name: grabpl + - go build -o ./bin/build -ldflags '-extldflags -static' ./pkg/build/cmd + depends_on: [] + environment: + CGO_ENABLED: 0 + image: golang:1.20.4 + name: compile-build-cmd - commands: - yarn install --immutable depends_on: [] - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: yarn-install - commands: - - yarn betterer ci + - ./bin/build artifacts npm retrieve --tag ${DRONE_TAG} depends_on: + - compile-build-cmd - yarn-install + environment: + GCP_KEY: + from_secret: gcp_key + PRERELEASE_BUCKET: + from_secret: prerelease_bucket failure: ignore - image: grafana/build-container:1.6.6 - name: betterer-frontend + image: grafana/grafana-ci-deploy:1.3.3 + name: retrieve-npm-packages - commands: - - yarn run ci:test-frontend + - ./bin/build artifacts npm release --tag ${DRONE_TAG} depends_on: - - yarn-install + - compile-build-cmd + - retrieve-npm-packages environment: - TEST_MAX_WORKERS: 50% - image: grafana/build-container:1.6.6 - name: test-frontend + NPM_TOKEN: + from_secret: npm_token + failure: ignore + image: grafana/build-container:1.7.4 + name: release-npm-packages trigger: - ref: - - refs/heads/v[0-9]* + event: + - promote + target: + - public type: docker volumes: - host: @@ -4359,13 +4438,16 @@ volumes: --- clone: retries: 3 -depends_on: [] +depends_on: +- publish-artifacts-public +- publish-docker-oss-public +- publish-docker-enterprise-public environment: EDITION: oss image_pull_secrets: - dockerconfigjson kind: pipeline -name: release-branch-oss-test-backend +name: publish-packages-oss node: type: no-parallel platform: @@ -4373,47 +4455,163 @@ platform: os: linux services: [] steps: -- commands: - - echo $DRONE_RUNNER_NAME - image: alpine:3.15.6 - name: identify-runner - commands: - go build -o ./bin/build -ldflags '-extldflags -static' ./pkg/build/cmd depends_on: [] environment: CGO_ENABLED: 0 - image: golang:1.19.4 + image: golang:1.20.4 name: compile-build-cmd +- depends_on: + - compile-build-cmd + image: us.gcr.io/kubernetes-dev/package-publish:latest + name: publish-linux-packages-deb + privileged: true + settings: + access_key_id: + from_secret: packages_access_key_id + deb_distribution: auto + gpg_passphrase: + from_secret: packages_gpg_passphrase + gpg_private_key: + from_secret: packages_gpg_private_key + gpg_public_key: + from_secret: packages_gpg_public_key + package_path: gs://grafana-prerelease/artifacts/downloads/*${DRONE_TAG}/oss/**.deb + secret_access_key: + from_secret: packages_secret_access_key + service_account_json: + from_secret: packages_service_account + target_bucket: grafana-packages +- depends_on: + - compile-build-cmd + image: us.gcr.io/kubernetes-dev/package-publish:latest + name: publish-linux-packages-rpm + privileged: true + settings: + access_key_id: + from_secret: packages_access_key_id + deb_distribution: auto + gpg_passphrase: + from_secret: packages_gpg_passphrase + gpg_private_key: + from_secret: packages_gpg_private_key + gpg_public_key: + from_secret: packages_gpg_public_key + package_path: gs://grafana-prerelease/artifacts/downloads/*${DRONE_TAG}/oss/**.rpm + secret_access_key: + from_secret: packages_secret_access_key + service_account_json: + from_secret: packages_service_account + target_bucket: grafana-packages - commands: - - '# It is required that code generated from Thema/CUE be committed and in sync - with its inputs.' - - '# The following command will fail if running code generators produces any diff - in output.' - - CODEGEN_VERIFY=1 make gen-cue - depends_on: [] - image: grafana/build-container:1.6.6 - name: verify-gen-cue -- commands: - - make gen-go + - ./bin/build publish grafana-com --edition oss ${DRONE_TAG} depends_on: - - verify-gen-cue - image: grafana/build-container:1.6.6 - name: wire-install + - publish-linux-packages-deb + - publish-linux-packages-rpm + environment: + GCP_KEY: + from_secret: gcp_key + GRAFANA_COM_API_KEY: + from_secret: grafana_api_key + image: grafana/grafana-ci-deploy:1.3.3 + name: publish-grafanacom-oss +trigger: + event: + - promote + target: + - public +type: docker +volumes: +- host: + path: /var/run/docker.sock + name: docker +--- +clone: + retries: 3 +depends_on: +- publish-artifacts-public +- publish-docker-oss-public +- publish-docker-enterprise-public +environment: + EDITION: enterprise +image_pull_secrets: +- dockerconfigjson +kind: pipeline +name: publish-packages-enterprise +node: + type: no-parallel +platform: + arch: amd64 + os: linux +services: [] +steps: - commands: - - go test -short -covermode=atomic -timeout=30m ./pkg/... - depends_on: - - wire-install - image: grafana/build-container:1.6.6 - name: test-backend + - go build -o ./bin/build -ldflags '-extldflags -static' ./pkg/build/cmd + depends_on: [] + environment: + CGO_ENABLED: 0 + image: golang:1.20.4 + name: compile-build-cmd +- depends_on: + - compile-build-cmd + image: us.gcr.io/kubernetes-dev/package-publish:latest + name: publish-linux-packages-deb + privileged: true + settings: + access_key_id: + from_secret: packages_access_key_id + deb_distribution: auto + gpg_passphrase: + from_secret: packages_gpg_passphrase + gpg_private_key: + from_secret: packages_gpg_private_key + gpg_public_key: + from_secret: packages_gpg_public_key + package_path: gs://grafana-prerelease/artifacts/downloads/*${DRONE_TAG}/enterprise/**.deb + secret_access_key: + from_secret: packages_secret_access_key + service_account_json: + from_secret: packages_service_account + target_bucket: grafana-packages +- depends_on: + - compile-build-cmd + image: us.gcr.io/kubernetes-dev/package-publish:latest + name: publish-linux-packages-rpm + privileged: true + settings: + access_key_id: + from_secret: packages_access_key_id + deb_distribution: auto + gpg_passphrase: + from_secret: packages_gpg_passphrase + gpg_private_key: + from_secret: packages_gpg_private_key + gpg_public_key: + from_secret: packages_gpg_public_key + package_path: gs://grafana-prerelease/artifacts/downloads/*${DRONE_TAG}/enterprise/**.rpm + secret_access_key: + from_secret: packages_secret_access_key + service_account_json: + from_secret: packages_service_account + target_bucket: grafana-packages - commands: - - go test -run Integration -covermode=atomic -timeout=30m ./pkg/... + - ./bin/build publish grafana-com --edition enterprise ${DRONE_TAG} depends_on: - - wire-install - image: grafana/build-container:1.6.6 - name: test-backend-integration + - publish-linux-packages-deb + - publish-linux-packages-rpm + environment: + GCP_KEY: + from_secret: gcp_key + GRAFANA_COM_API_KEY: + from_secret: grafana_api_key + image: grafana/grafana-ci-deploy:1.3.3 + name: publish-grafanacom-enterprise trigger: - ref: - - refs/heads/v[0-9]* + event: + - promote + target: + - public type: docker volumes: - host: @@ -4421,164 +4619,74 @@ volumes: name: docker --- clone: - retries: 3 + disable: true depends_on: [] environment: - EDITION: oss + EDITION: enterprise image_pull_secrets: - dockerconfigjson kind: pipeline -name: release-branch-oss-integration-tests +name: publish-artifacts-page node: type: no-parallel platform: arch: amd64 os: linux -services: -- environment: - PGDATA: /var/lib/postgresql/data/pgdata - POSTGRES_DB: grafanatest - POSTGRES_PASSWORD: grafanatest - POSTGRES_USER: grafanatest - image: postgres:12.3-alpine - name: postgres - volumes: - - name: postgres - path: /var/lib/postgresql/data/pgdata -- environment: - MYSQL_DATABASE: grafana_tests - MYSQL_PASSWORD: password - MYSQL_ROOT_PASSWORD: rootpass - MYSQL_USER: grafana - image: mysql:5.7.39 - name: mysql - volumes: - - name: mysql - path: /var/lib/mysql +services: [] steps: - commands: - mkdir -p bin - - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.0.15/grabpl + - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.0.30/grabpl - chmod +x bin/grabpl image: byrnedo/alpine-curl:0.1.8 name: grabpl - commands: - - echo $DRONE_RUNNER_NAME - image: alpine:3.15.6 - name: identify-runner -- commands: - - '# It is required that code generated from Thema/CUE be committed and in sync - with its inputs.' - - '# The following command will fail if running code generators produces any diff - in output.' - - CODEGEN_VERIFY=1 make gen-cue - depends_on: [] - image: grafana/build-container:1.6.6 - name: verify-gen-cue + - git clone "https://$${GITHUB_TOKEN}@github.com/grafana/grafana-enterprise.git" + - cd grafana-enterprise + - git checkout ${DRONE_TAG} + environment: + GITHUB_TOKEN: + from_secret: github_token + image: grafana/build-container:1.7.4 + name: clone-enterprise - commands: - - make gen-go - depends_on: - - verify-gen-cue - image: grafana/build-container:1.6.6 - name: wire-install -- commands: - - apt-get update - - apt-get install -yq postgresql-client - - dockerize -wait tcp://postgres:5432 -timeout 120s - - psql -p 5432 -h postgres -U grafanatest -d grafanatest -f devenv/docker/blocks/postgres_tests/setup.sql - - go clean -testcache - - go list './pkg/...' | xargs -I {} sh -c 'go test -run Integration -covermode=atomic - -timeout=30m {}' + - mv bin/grabpl /tmp/ + - rmdir bin + - mv grafana-enterprise /tmp/ + - /tmp/grabpl init-enterprise --github-token $${GITHUB_TOKEN} /tmp/grafana-enterprise + ${DRONE_TAG} + - mv /tmp/grafana-enterprise/deployment_tools_config.json deployment_tools_config.json + - mkdir bin + - mv /tmp/grabpl bin/ depends_on: - - wire-install + - clone-enterprise + - grabpl environment: - GRAFANA_TEST_DB: postgres - PGPASSWORD: grafanatest - POSTGRES_HOST: postgres - image: grafana/build-container:1.6.6 - name: postgres-integration-tests + GITHUB_TOKEN: + from_secret: github_token + image: grafana/build-container:1.7.4 + name: init-enterprise - commands: - - apt-get update - - apt-get install -yq default-mysql-client - - dockerize -wait tcp://mysql:3306 -timeout 120s - - cat devenv/docker/blocks/mysql_tests/setup.sql | mysql -h mysql -P 3306 -u root - -prootpass - - go clean -testcache - - go list './pkg/...' | xargs -I {} sh -c 'go test -run Integration -covermode=atomic - -timeout=30m {}' + - go build -o ./bin/build -ldflags '-extldflags -static' ./pkg/build/cmd depends_on: - - wire-install + - init-enterprise environment: - GRAFANA_TEST_DB: mysql - MYSQL_HOST: mysql - image: grafana/build-container:1.6.6 - name: mysql-integration-tests -trigger: - ref: - - refs/heads/v[0-9]* -type: docker -volumes: -- host: - path: /var/run/docker.sock - name: docker -- name: postgres - temp: - medium: memory -- name: mysql - temp: - medium: memory ---- -clone: - retries: 3 -depends_on: -- release-branch-oss-build-e2e-publish -- release-branch-oss-test-frontend -- release-branch-oss-test-backend -- release-branch-oss-integration-tests -environment: - EDITION: oss -image_pull_secrets: -- dockerconfigjson -kind: pipeline -name: release-branch-oss-windows -platform: - arch: amd64 - os: windows - version: "1809" -services: [] -steps: -- commands: - - echo $env:DRONE_RUNNER_NAME - image: mcr.microsoft.com/windows:1809 - name: identify-runner -- commands: - - $$ProgressPreference = "SilentlyContinue" - - Invoke-WebRequest https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.0.15/windows/grabpl.exe - -OutFile grabpl.exe - image: grafana/ci-wix:0.1.1 - name: windows-init + CGO_ENABLED: 0 + image: golang:1.20.4 + name: compile-build-cmd - commands: - - $$gcpKey = $$env:GCP_KEY - - '[System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($$gcpKey)) - > gcpkey.json' - - dos2unix gcpkey.json - - gcloud auth activate-service-account --key-file=gcpkey.json - - rm gcpkey.json - - cp C:\App\nssm-2.24.zip . + - ./bin/build artifacts-page depends_on: - - windows-init + - compile-build-cmd environment: GCP_KEY: from_secret: gcp_key - GITHUB_TOKEN: - from_secret: github_token - PRERELEASE_BUCKET: - from_secret: prerelease_bucket - image: grafana/ci-wix:0.1.1 - name: build-windows-installer + image: grafana/build-container:1.7.4 + name: artifacts-page trigger: - ref: - - refs/heads/v[0-9]* + event: + - promote + target: security type: docker volumes: - host: @@ -4586,14 +4694,14 @@ volumes: name: docker --- clone: - disable: true + retries: 3 depends_on: [] environment: - EDITION: enterprise + EDITION: oss image_pull_secrets: - dockerconfigjson kind: pipeline -name: release-branch-enterprise-build-e2e-publish +name: release-branch-oss-build-e2e-publish node: type: no-parallel platform: @@ -4601,122 +4709,85 @@ platform: os: linux services: [] steps: +- commands: + - echo $DRONE_RUNNER_NAME + image: alpine:3.17.1 + name: identify-runner - commands: - mkdir -p bin - - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.0.15/grabpl + - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.0.30/grabpl - chmod +x bin/grabpl image: byrnedo/alpine-curl:0.1.8 name: grabpl - commands: - - echo $DRONE_RUNNER_NAME - image: alpine:3.15.6 - name: identify-runner -- commands: - - git clone "https://$${GITHUB_TOKEN}@github.com/grafana/grafana-enterprise.git" - - cd grafana-enterprise - - git checkout ${DRONE_BRANCH} - environment: - GITHUB_TOKEN: - from_secret: github_token - image: grafana/build-container:1.6.6 - name: clone-enterprise -- commands: - - mv bin/grabpl /tmp/ - - rmdir bin - - mv grafana-enterprise /tmp/ - - /tmp/grabpl init-enterprise --github-token $${GITHUB_TOKEN} /tmp/grafana-enterprise - - mv /tmp/grafana-enterprise/deployment_tools_config.json deployment_tools_config.json - - mkdir bin - - mv /tmp/grabpl bin/ - depends_on: - - clone-enterprise - environment: - GITHUB_TOKEN: - from_secret: github_token - image: grafana/build-container:1.6.6 - name: init-enterprise -- commands: - - go build -o ./bin/build -ldflags '-extldflags -static' ./pkg/build/cmd - depends_on: - - init-enterprise - environment: - CGO_ENABLED: 0 - image: golang:1.19.4 - name: compile-build-cmd + - '# It is required that code generated from Thema/CUE be committed and in sync + with its inputs.' + - '# The following command will fail if running code generators produces any diff + in output.' + - CODEGEN_VERIFY=1 make gen-cue + depends_on: [] + image: grafana/build-container:1.7.4 + name: verify-gen-cue - commands: - make gen-go depends_on: - - init-enterprise - image: grafana/build-container:1.6.6 + - verify-gen-cue + image: grafana/build-container:1.7.4 name: wire-install - commands: - yarn install --immutable - depends_on: - - init-enterprise - image: grafana/build-container:1.6.6 + depends_on: [] + image: grafana/build-container:1.7.4 name: yarn-install - commands: - - '# It is required that code generated from Thema/CUE be committed and in sync - with its inputs.' - - '# The following command will fail if running code generators produces any diff - in output.' - - CODEGEN_VERIFY=1 make gen-cue - depends_on: - - init-enterprise - image: grafana/build-container:1.6.6 - name: verify-gen-cue + - go build -o ./bin/build -ldflags '-extldflags -static' ./pkg/build/cmd + depends_on: [] + environment: + CGO_ENABLED: 0 + image: golang:1.20.4 + name: compile-build-cmd - commands: - - ./bin/build build-backend --jobs 8 --edition enterprise --build-id ${DRONE_BUILD_NUMBER} + - ./bin/build build-backend --jobs 8 --edition oss --build-id ${DRONE_BUILD_NUMBER} depends_on: - wire-install - compile-build-cmd - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: build-backend - commands: - - ./bin/build build-frontend --jobs 8 --edition enterprise --build-id ${DRONE_BUILD_NUMBER} + - ./bin/build build-frontend --jobs 8 --edition oss --build-id ${DRONE_BUILD_NUMBER} depends_on: - compile-build-cmd - yarn-install environment: NODE_OPTIONS: --max_old_space_size=8192 - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: build-frontend - commands: - - ./bin/build build-frontend-packages --jobs 8 --edition enterprise --build-id ${DRONE_BUILD_NUMBER} + - ./bin/build build-frontend-packages --jobs 8 --edition oss --build-id ${DRONE_BUILD_NUMBER} depends_on: - compile-build-cmd - yarn-install environment: NODE_OPTIONS: --max_old_space_size=8192 - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: build-frontend-packages - commands: - - ./bin/build build-plugins --jobs 8 --edition enterprise + - ./bin/build build-plugins --jobs 8 --edition oss depends_on: - compile-build-cmd - yarn-install environment: GRAFANA_API_KEY: from_secret: grafana_api_key - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: build-plugins - commands: - - ./bin/build build-backend --jobs 8 --edition enterprise2 --build-id ${DRONE_BUILD_NUMBER} - --variants linux-amd64 - depends_on: - - wire-install - - compile-build-cmd - image: grafana/build-container:1.6.6 - name: build-backend-enterprise2 -- commands: - - ./bin/build package --jobs 8 --edition enterprise --build-id ${DRONE_BUILD_NUMBER} - --sign + - ./bin/build package --jobs 8 --edition oss --build-id ${DRONE_BUILD_NUMBER} --sign depends_on: - build-plugins - build-backend - build-frontend - build-frontend-packages - - build-backend-enterprise2 environment: GPG_KEY_PASSWORD: from_secret: packages_gpg_passphrase @@ -4726,17 +4797,17 @@ steps: from_secret: packages_gpg_public_key GRAFANA_API_KEY: from_secret: grafana_api_key - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: package - commands: - ls dist/*.tar.gz* - cp dist/*.tar.gz* packaging/docker/ depends_on: - package - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: copy-packages-for-docker - commands: - - ./bin/build build-docker --edition enterprise --shouldSave + - ./bin/build build-docker --edition oss --shouldSave depends_on: - copy-packages-for-docker - compile-build-cmd @@ -4749,7 +4820,7 @@ steps: - name: docker path: /var/run/docker.sock - commands: - - ./bin/build build-docker --edition enterprise --shouldSave --ubuntu + - ./bin/build build-docker --edition oss --shouldSave --ubuntu depends_on: - copy-packages-for-docker - compile-build-cmd @@ -4772,8 +4843,7 @@ steps: environment: ARCH: linux-amd64 PORT: 3001 - RUNDIR: scripts/grafana-server/tmp-grafana-enterprise - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: grafana-server - commands: - apt-get install -y netcat @@ -4814,8 +4884,6 @@ steps: - commands: - apt-get update - apt-get install -yq zip - - ls -lah ./e2e - - find ./e2e -type f -name "*.mp4" - printenv GCP_GRAFANA_UPLOAD_ARTIFACTS_KEY > /tmp/gcpkey_upload_artifacts.json - gcloud auth activate-service-account --key-file=/tmp/gcpkey_upload_artifacts.json - find ./e2e -type f -name "*spec.ts.mp4" | zip e2e/videos.zip -@ @@ -4837,16 +4905,31 @@ steps: from_secret: gcp_upload_artifacts_key GITHUB_TOKEN: from_secret: github_token - image: google/cloud-sdk:367.0.0 + failure: ignore + image: google/cloud-sdk:406.0.0 name: e2e-tests-artifacts-upload when: status: - success - failure - commands: - - ./bin/grabpl upload-cdn --edition enterprise + - yarn storybook:build + - ./bin/build verify-storybook depends_on: - - package + - build-frontend + - build-frontend-packages + environment: + NODE_OPTIONS: --max_old_space_size=4096 + image: grafana/build-container:1.7.4 + name: build-storybook + when: + paths: + include: + - packages/grafana-ui/** +- commands: + - ./bin/build upload-cdn --edition oss + depends_on: + - grafana-server environment: GCP_KEY: from_secret: gcp_key @@ -4858,9 +4941,12 @@ steps: repo: - grafana/grafana - commands: - - ./bin/grabpl upload-packages --edition enterprise + - ./bin/build upload-packages --edition oss depends_on: - - package + - end-to-end-tests-dashboards-suite + - end-to-end-tests-panels-suite + - end-to-end-tests-smoke-tests-suite + - end-to-end-tests-various-suite environment: GCP_KEY: from_secret: gcp_key @@ -4871,48 +4957,1028 @@ steps: when: repo: - grafana/grafana +trigger: + ref: + - refs/heads/v[0-9]* +type: docker +volumes: +- host: + path: /var/run/docker.sock + name: docker +- name: postgres + temp: + medium: memory +- name: mysql + temp: + medium: memory +--- +clone: + retries: 3 +depends_on: [] +environment: + EDITION: oss +image_pull_secrets: +- dockerconfigjson +kind: pipeline +name: release-branch-oss-test-frontend +node: + type: no-parallel +platform: + arch: amd64 + os: linux +services: [] +steps: +- commands: + - echo $DRONE_RUNNER_NAME + image: alpine:3.17.1 + name: identify-runner +- commands: + - mkdir -p bin + - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.0.30/grabpl + - chmod +x bin/grabpl + image: byrnedo/alpine-curl:0.1.8 + name: grabpl +- commands: + - yarn install --immutable + depends_on: [] + image: grafana/build-container:1.7.4 + name: yarn-install +- commands: + - yarn betterer ci + depends_on: + - yarn-install + image: grafana/build-container:1.7.4 + name: betterer-frontend +- commands: + - yarn run ci:test-frontend + depends_on: + - yarn-install + environment: + TEST_MAX_WORKERS: 50% + image: grafana/build-container:1.7.4 + name: test-frontend +trigger: + ref: + - refs/heads/v[0-9]* +type: docker +volumes: +- host: + path: /var/run/docker.sock + name: docker +--- +clone: + retries: 3 +depends_on: [] +environment: + EDITION: oss +image_pull_secrets: +- dockerconfigjson +kind: pipeline +name: release-branch-oss-test-backend +node: + type: no-parallel +platform: + arch: amd64 + os: linux +services: [] +steps: +- commands: + - echo $DRONE_RUNNER_NAME + image: alpine:3.17.1 + name: identify-runner +- commands: + - go build -o ./bin/build -ldflags '-extldflags -static' ./pkg/build/cmd + depends_on: [] + environment: + CGO_ENABLED: 0 + image: golang:1.20.4 + name: compile-build-cmd +- commands: + - '# It is required that code generated from Thema/CUE be committed and in sync + with its inputs.' + - '# The following command will fail if running code generators produces any diff + in output.' + - CODEGEN_VERIFY=1 make gen-cue + depends_on: [] + image: grafana/build-container:1.7.4 + name: verify-gen-cue +- commands: + - make gen-go + depends_on: + - verify-gen-cue + image: grafana/build-container:1.7.4 + name: wire-install +- commands: + - go test -tags requires_buildifer -short -covermode=atomic -timeout=5m ./pkg/... + depends_on: + - wire-install + image: grafana/build-container:1.7.4 + name: test-backend +- commands: + - go test -run Integration -covermode=atomic -timeout=5m ./pkg/... + depends_on: + - wire-install + image: grafana/build-container:1.7.4 + name: test-backend-integration +trigger: + ref: + - refs/heads/v[0-9]* +type: docker +volumes: +- host: + path: /var/run/docker.sock + name: docker +--- +clone: + retries: 3 +depends_on: [] +environment: + EDITION: oss +image_pull_secrets: +- dockerconfigjson +kind: pipeline +name: release-branch-oss-test-backend-windows +platform: + arch: amd64 + os: windows + version: "1809" +services: [] +steps: +- commands: [] + image: grafana/grafana-ci-windows-test:0.1.0 + name: windows-init +- commands: + - go install github.com/google/wire/cmd/wire@v0.5.0 + - wire gen -tags oss ./pkg/server + depends_on: + - windows-init + image: grafana/grafana-ci-windows-test:0.1.0 + name: wire-install +- commands: + - go test -tags requires_buildifer -short -covermode=atomic -timeout=5m ./pkg/... + depends_on: + - wire-install + failure: ignore + image: grafana/grafana-ci-windows-test:0.1.0 + name: test-backend +trigger: + ref: + - refs/heads/v[0-9]* +type: docker +volumes: +- host: + path: //./pipe/docker_engine/ + name: docker +--- +clone: + disable: true +depends_on: [] +environment: + EDITION: enterprise +image_pull_secrets: +- dockerconfigjson +kind: pipeline +name: release-branch-enterprise-test-backend-windows +platform: + arch: amd64 + os: windows + version: "1809" +services: [] +steps: +- commands: + - $$ProgressPreference = "SilentlyContinue" + - Invoke-WebRequest https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.0.30/windows/grabpl.exe + -OutFile grabpl.exe + image: grafana/ci-wix:0.1.1 + name: grabpl +- commands: + - git clone "https://$$env:GITHUB_TOKEN@github.com/grafana/grafana-enterprise.git" + - cd grafana-enterprise + - git checkout $$env:DRONE_BRANCH + environment: + GITHUB_TOKEN: + from_secret: github_token + image: grafana/ci-wix:0.1.1 + name: clone +- commands: + - cp -r grafana-enterprise C:\App\grafana-enterprise + - rm -r -force grafana-enterprise + - cp grabpl.exe C:\App\grabpl.exe + - rm -force grabpl.exe + - C:\App\grabpl.exe init-enterprise --github-token $$env:GITHUB_TOKEN C:\App\grafana-enterprise + $$env:DRONE_BRANCH + - cp C:\App\grabpl.exe grabpl.exe + depends_on: + - clone + environment: + GITHUB_TOKEN: + from_secret: github_token + image: grafana/ci-wix:0.1.1 + name: windows-init +- commands: + - go install github.com/google/wire/cmd/wire@v0.5.0 + - wire gen -tags enterprise ./pkg/server + depends_on: + - windows-init + image: grafana/grafana-ci-windows-test:0.1.0 + name: wire-install +- commands: + - go test -tags requires_buildifer -short -covermode=atomic -timeout=5m ./pkg/... + depends_on: + - wire-install + failure: ignore + image: grafana/grafana-ci-windows-test:0.1.0 + name: test-backend +trigger: + ref: + - refs/heads/v[0-9]* +type: docker +volumes: +- host: + path: //./pipe/docker_engine/ + name: docker +--- +clone: + retries: 3 +depends_on: [] +environment: + EDITION: oss +image_pull_secrets: +- dockerconfigjson +kind: pipeline +name: release-branch-oss-integration-tests +node: + type: no-parallel +platform: + arch: amd64 + os: linux +services: +- environment: + PGDATA: /var/lib/postgresql/data/pgdata + POSTGRES_DB: grafanatest + POSTGRES_PASSWORD: grafanatest + POSTGRES_USER: grafanatest + image: postgres:12.3-alpine + name: postgres + volumes: + - name: postgres + path: /var/lib/postgresql/data/pgdata +- environment: + MYSQL_DATABASE: grafana_tests + MYSQL_PASSWORD: password + MYSQL_ROOT_PASSWORD: rootpass + MYSQL_USER: grafana + image: mysql:5.7.39 + name: mysql + volumes: + - name: mysql + path: /var/lib/mysql +steps: +- commands: + - mkdir -p bin + - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.0.30/grabpl + - chmod +x bin/grabpl + image: byrnedo/alpine-curl:0.1.8 + name: grabpl +- commands: + - echo $DRONE_RUNNER_NAME + image: alpine:3.17.1 + name: identify-runner +- commands: + - '# It is required that code generated from Thema/CUE be committed and in sync + with its inputs.' + - '# The following command will fail if running code generators produces any diff + in output.' + - CODEGEN_VERIFY=1 make gen-cue + depends_on: [] + image: grafana/build-container:1.7.4 + name: verify-gen-cue +- commands: + - make gen-go + depends_on: + - verify-gen-cue + image: grafana/build-container:1.7.4 + name: wire-install +- commands: + - apt-get update + - apt-get install -yq postgresql-client + - dockerize -wait tcp://postgres:5432 -timeout 120s + - psql -p 5432 -h postgres -U grafanatest -d grafanatest -f devenv/docker/blocks/postgres_tests/setup.sql + - go clean -testcache + - go list './pkg/...' | xargs -I {} sh -c 'go test -run Integration -covermode=atomic + -timeout=5m {}' + depends_on: + - wire-install + environment: + GRAFANA_TEST_DB: postgres + PGPASSWORD: grafanatest + POSTGRES_HOST: postgres + image: grafana/build-container:1.7.4 + name: postgres-integration-tests +- commands: + - apt-get update + - apt-get install -yq default-mysql-client + - dockerize -wait tcp://mysql:3306 -timeout 120s + - cat devenv/docker/blocks/mysql_tests/setup.sql | mysql -h mysql -P 3306 -u root + -prootpass + - go clean -testcache + - go list './pkg/...' | xargs -I {} sh -c 'go test -run Integration -covermode=atomic + -timeout=5m {}' + depends_on: + - wire-install + environment: + GRAFANA_TEST_DB: mysql + MYSQL_HOST: mysql + image: grafana/build-container:1.7.4 + name: mysql-integration-tests +trigger: + ref: + - refs/heads/v[0-9]* +type: docker +volumes: +- host: + path: /var/run/docker.sock + name: docker +- name: postgres + temp: + medium: memory +- name: mysql + temp: + medium: memory +--- +clone: + retries: 3 +depends_on: +- release-branch-oss-build-e2e-publish +- release-branch-oss-test-frontend +- release-branch-oss-test-backend-windows +environment: + EDITION: oss +image_pull_secrets: +- dockerconfigjson +kind: pipeline +name: release-branch-oss-windows +platform: + arch: amd64 + os: windows + version: "1809" +services: [] +steps: +- commands: + - echo $env:DRONE_RUNNER_NAME + image: mcr.microsoft.com/windows:1809 + name: identify-runner +- commands: + - $$ProgressPreference = "SilentlyContinue" + - Invoke-WebRequest https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.0.30/windows/grabpl.exe + -OutFile grabpl.exe + image: grafana/ci-wix:0.1.1 + name: windows-init +- commands: + - $$gcpKey = $$env:GCP_KEY + - '[System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($$gcpKey)) + > gcpkey.json' + - dos2unix gcpkey.json + - gcloud auth activate-service-account --key-file=gcpkey.json + - rm gcpkey.json + - cp C:\App\nssm-2.24.zip . + depends_on: + - windows-init + environment: + GCP_KEY: + from_secret: gcp_key + GITHUB_TOKEN: + from_secret: github_token + PRERELEASE_BUCKET: + from_secret: prerelease_bucket + image: grafana/ci-wix:0.1.1 + name: build-windows-installer +trigger: + ref: + - refs/heads/v[0-9]* +type: docker +volumes: +- host: + path: //./pipe/docker_engine/ + name: docker +--- +clone: + disable: true +depends_on: [] +environment: + EDITION: enterprise +image_pull_secrets: +- dockerconfigjson +kind: pipeline +name: release-branch-enterprise-build-e2e-publish +node: + type: no-parallel +platform: + arch: amd64 + os: linux +services: [] +steps: +- commands: + - mkdir -p bin + - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.0.30/grabpl + - chmod +x bin/grabpl + image: byrnedo/alpine-curl:0.1.8 + name: grabpl +- commands: + - echo $DRONE_RUNNER_NAME + image: alpine:3.17.1 + name: identify-runner +- commands: + - git clone "https://$${GITHUB_TOKEN}@github.com/grafana/grafana-enterprise.git" + - cd grafana-enterprise + - git checkout ${DRONE_BRANCH} + environment: + GITHUB_TOKEN: + from_secret: github_token + image: grafana/build-container:1.7.4 + name: clone-enterprise +- commands: + - mv bin/grabpl /tmp/ + - rmdir bin + - mv grafana-enterprise /tmp/ + - /tmp/grabpl init-enterprise --github-token $${GITHUB_TOKEN} /tmp/grafana-enterprise + - mv /tmp/grafana-enterprise/deployment_tools_config.json deployment_tools_config.json + - mkdir bin + - mv /tmp/grabpl bin/ + depends_on: + - clone-enterprise + - grabpl + environment: + GITHUB_TOKEN: + from_secret: github_token + image: grafana/build-container:1.7.4 + name: init-enterprise +- commands: + - go build -o ./bin/build -ldflags '-extldflags -static' ./pkg/build/cmd + depends_on: + - init-enterprise + environment: + CGO_ENABLED: 0 + image: golang:1.20.4 + name: compile-build-cmd +- commands: + - make gen-go + depends_on: + - init-enterprise + image: grafana/build-container:1.7.4 + name: wire-install +- commands: + - yarn install --immutable + depends_on: + - init-enterprise + image: grafana/build-container:1.7.4 + name: yarn-install +- commands: + - '# It is required that code generated from Thema/CUE be committed and in sync + with its inputs.' + - '# The following command will fail if running code generators produces any diff + in output.' + - CODEGEN_VERIFY=1 make gen-cue + depends_on: + - init-enterprise + image: grafana/build-container:1.7.4 + name: verify-gen-cue +- commands: + - ./bin/build build-backend --jobs 8 --edition enterprise --build-id ${DRONE_BUILD_NUMBER} + depends_on: + - wire-install + - compile-build-cmd + image: grafana/build-container:1.7.4 + name: build-backend +- commands: + - ./bin/build build-frontend --jobs 8 --edition enterprise --build-id ${DRONE_BUILD_NUMBER} + depends_on: + - compile-build-cmd + - yarn-install + environment: + NODE_OPTIONS: --max_old_space_size=8192 + image: grafana/build-container:1.7.4 + name: build-frontend +- commands: + - ./bin/build build-frontend-packages --jobs 8 --edition enterprise --build-id ${DRONE_BUILD_NUMBER} + depends_on: + - compile-build-cmd + - yarn-install + environment: + NODE_OPTIONS: --max_old_space_size=8192 + image: grafana/build-container:1.7.4 + name: build-frontend-packages +- commands: + - ./bin/build build-plugins --jobs 8 --edition enterprise + depends_on: + - compile-build-cmd + - yarn-install + environment: + GRAFANA_API_KEY: + from_secret: grafana_api_key + image: grafana/build-container:1.7.4 + name: build-plugins +- commands: + - ./bin/build package --jobs 8 --edition enterprise --build-id ${DRONE_BUILD_NUMBER} + --sign + depends_on: + - build-plugins + - build-backend + - build-frontend + - build-frontend-packages + environment: + GPG_KEY_PASSWORD: + from_secret: packages_gpg_passphrase + GPG_PRIV_KEY: + from_secret: packages_gpg_private_key + GPG_PUB_KEY: + from_secret: packages_gpg_public_key + GRAFANA_API_KEY: + from_secret: grafana_api_key + image: grafana/build-container:1.7.4 + name: package +- commands: + - ls dist/*.tar.gz* + - cp dist/*.tar.gz* packaging/docker/ + depends_on: + - package + image: grafana/build-container:1.7.4 + name: copy-packages-for-docker +- commands: + - ./bin/build build-docker --edition enterprise --shouldSave + depends_on: + - copy-packages-for-docker + - compile-build-cmd + environment: + GCP_KEY: + from_secret: gcp_key + image: google/cloud-sdk + name: build-docker-images + volumes: + - name: docker + path: /var/run/docker.sock +- commands: + - ./bin/build build-docker --edition enterprise --shouldSave --ubuntu + depends_on: + - copy-packages-for-docker + - compile-build-cmd + environment: + GCP_KEY: + from_secret: gcp_key + image: google/cloud-sdk + name: build-docker-images-ubuntu + volumes: + - name: docker + path: /var/run/docker.sock +- commands: + - ./scripts/grafana-server/start-server + depends_on: + - build-plugins + - build-backend + - build-frontend + - build-frontend-packages + detach: true + environment: + ARCH: linux-amd64 + PORT: 3001 + RUNDIR: scripts/grafana-server/tmp-grafana-enterprise + image: grafana/build-container:1.7.4 + name: grafana-server +- commands: + - apt-get install -y netcat + - ./bin/build e2e-tests --port 3001 --suite dashboards-suite --tries 3 + depends_on: + - grafana-server + environment: + HOST: grafana-server + image: cypress/included:9.5.1-node16.14.0-slim-chrome99-ff97 + name: end-to-end-tests-dashboards-suite +- commands: + - apt-get install -y netcat + - ./bin/build e2e-tests --port 3001 --suite smoke-tests-suite --tries 3 + depends_on: + - grafana-server + environment: + HOST: grafana-server + image: cypress/included:9.5.1-node16.14.0-slim-chrome99-ff97 + name: end-to-end-tests-smoke-tests-suite +- commands: + - apt-get install -y netcat + - ./bin/build e2e-tests --port 3001 --suite panels-suite --tries 3 + depends_on: + - grafana-server + environment: + HOST: grafana-server + image: cypress/included:9.5.1-node16.14.0-slim-chrome99-ff97 + name: end-to-end-tests-panels-suite +- commands: + - apt-get install -y netcat + - ./bin/build e2e-tests --port 3001 --suite various-suite --tries 3 + depends_on: + - grafana-server + environment: + HOST: grafana-server + image: cypress/included:9.5.1-node16.14.0-slim-chrome99-ff97 + name: end-to-end-tests-various-suite +- commands: + - apt-get update + - apt-get install -yq zip + - printenv GCP_GRAFANA_UPLOAD_ARTIFACTS_KEY > /tmp/gcpkey_upload_artifacts.json + - gcloud auth activate-service-account --key-file=/tmp/gcpkey_upload_artifacts.json + - find ./e2e -type f -name "*spec.ts.mp4" | zip e2e/videos.zip -@ + - gsutil cp e2e/videos.zip gs://$${E2E_TEST_ARTIFACTS_BUCKET}/${DRONE_BUILD_NUMBER}/artifacts/videos/videos.zip + - export E2E_ARTIFACTS_VIDEO_ZIP=https://storage.googleapis.com/$${E2E_TEST_ARTIFACTS_BUCKET}/${DRONE_BUILD_NUMBER}/artifacts/videos/videos.zip + - 'echo "E2E Test artifacts uploaded to: $${E2E_ARTIFACTS_VIDEO_ZIP}"' + - 'curl -X POST https://api.github.com/repos/${DRONE_REPO}/statuses/${DRONE_COMMIT_SHA} + -H "Authorization: token $${GITHUB_TOKEN}" -d "{\"state\":\"success\",\"target_url\":\"$${E2E_ARTIFACTS_VIDEO_ZIP}\", + \"description\": \"Click on the details to download e2e recording videos\", \"context\": + \"e2e_artifacts\"}"' + depends_on: + - end-to-end-tests-dashboards-suite + - end-to-end-tests-panels-suite + - end-to-end-tests-smoke-tests-suite + - end-to-end-tests-various-suite + environment: + E2E_TEST_ARTIFACTS_BUCKET: releng-pipeline-artifacts-dev + GCP_GRAFANA_UPLOAD_ARTIFACTS_KEY: + from_secret: gcp_upload_artifacts_key + GITHUB_TOKEN: + from_secret: github_token + failure: ignore + image: google/cloud-sdk:406.0.0 + name: e2e-tests-artifacts-upload + when: + status: + - success + - failure +- commands: + - ./bin/build upload-cdn --edition enterprise + depends_on: + - package + environment: + GCP_KEY: + from_secret: gcp_key + PRERELEASE_BUCKET: + from_secret: prerelease_bucket + image: grafana/grafana-ci-deploy:1.3.3 + name: upload-cdn-assets + when: + repo: + - grafana/grafana +- commands: + - ./bin/build upload-packages --edition enterprise + depends_on: + - package + environment: + GCP_KEY: + from_secret: gcp_key + PRERELEASE_BUCKET: + from_secret: prerelease_bucket + image: grafana/grafana-ci-deploy:1.3.3 + name: upload-packages + when: + repo: + - grafana/grafana +trigger: + ref: + - refs/heads/v[0-9]* +type: docker +volumes: +- host: + path: /var/run/docker.sock + name: docker +- name: postgres + temp: + medium: memory +- name: mysql + temp: + medium: memory +--- +clone: + disable: true +depends_on: [] +environment: + EDITION: enterprise +image_pull_secrets: +- dockerconfigjson +kind: pipeline +name: release-branch-enterprise-test-frontend +node: + type: no-parallel +platform: + arch: amd64 + os: linux +services: [] +steps: +- commands: + - mkdir -p bin + - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.0.30/grabpl + - chmod +x bin/grabpl + image: byrnedo/alpine-curl:0.1.8 + name: grabpl +- commands: + - git clone "https://$${GITHUB_TOKEN}@github.com/grafana/grafana-enterprise.git" + - cd grafana-enterprise + - git checkout ${DRONE_BRANCH} + environment: + GITHUB_TOKEN: + from_secret: github_token + image: grafana/build-container:1.7.4 + name: clone-enterprise +- commands: + - mv bin/grabpl /tmp/ + - rmdir bin + - mv grafana-enterprise /tmp/ + - /tmp/grabpl init-enterprise --github-token $${GITHUB_TOKEN} /tmp/grafana-enterprise + - mv /tmp/grafana-enterprise/deployment_tools_config.json deployment_tools_config.json + - mkdir bin + - mv /tmp/grabpl bin/ + depends_on: + - clone-enterprise + - grabpl + environment: + GITHUB_TOKEN: + from_secret: github_token + image: grafana/build-container:1.7.4 + name: init-enterprise +- commands: + - echo $DRONE_RUNNER_NAME + image: alpine:3.17.1 + name: identify-runner +- commands: + - yarn install --immutable + depends_on: + - init-enterprise + image: grafana/build-container:1.7.4 + name: yarn-install +- commands: + - yarn betterer ci + depends_on: + - init-enterprise + - yarn-install + image: grafana/build-container:1.7.4 + name: betterer-frontend +- commands: + - yarn run ci:test-frontend + depends_on: + - init-enterprise + - yarn-install + environment: + TEST_MAX_WORKERS: 50% + image: grafana/build-container:1.7.4 + name: test-frontend +trigger: + ref: + - refs/heads/v[0-9]* +type: docker +volumes: +- host: + path: /var/run/docker.sock + name: docker +--- +clone: + disable: true +depends_on: [] +environment: + EDITION: enterprise +image_pull_secrets: +- dockerconfigjson +kind: pipeline +name: release-branch-enterprise-test-backend +node: + type: no-parallel +platform: + arch: amd64 + os: linux +services: [] +steps: +- commands: + - git clone "https://$${GITHUB_TOKEN}@github.com/grafana/grafana-enterprise.git" + - cd grafana-enterprise + - git checkout ${DRONE_BRANCH} + environment: + GITHUB_TOKEN: + from_secret: github_token + image: grafana/build-container:1.7.4 + name: clone-enterprise +- commands: + - mkdir -p bin + - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.0.30/grabpl + - chmod +x bin/grabpl + image: byrnedo/alpine-curl:0.1.8 + name: grabpl +- commands: + - mv bin/grabpl /tmp/ + - rmdir bin + - mv grafana-enterprise /tmp/ + - /tmp/grabpl init-enterprise --github-token $${GITHUB_TOKEN} /tmp/grafana-enterprise + - mv /tmp/grafana-enterprise/deployment_tools_config.json deployment_tools_config.json + - mkdir bin + - mv /tmp/grabpl bin/ + depends_on: + - clone-enterprise + - grabpl + environment: + GITHUB_TOKEN: + from_secret: github_token + image: grafana/build-container:1.7.4 + name: init-enterprise +- commands: + - echo $DRONE_RUNNER_NAME + image: alpine:3.17.1 + name: identify-runner +- commands: + - go build -o ./bin/build -ldflags '-extldflags -static' ./pkg/build/cmd + depends_on: + - init-enterprise + environment: + CGO_ENABLED: 0 + image: golang:1.20.4 + name: compile-build-cmd +- commands: + - '# It is required that code generated from Thema/CUE be committed and in sync + with its inputs.' + - '# The following command will fail if running code generators produces any diff + in output.' + - CODEGEN_VERIFY=1 make gen-cue + depends_on: + - init-enterprise + image: grafana/build-container:1.7.4 + name: verify-gen-cue +- commands: + - make gen-go + depends_on: + - verify-gen-cue + image: grafana/build-container:1.7.4 + name: wire-install +- commands: + - go test -tags requires_buildifer -short -covermode=atomic -timeout=5m ./pkg/... + depends_on: + - wire-install + image: grafana/build-container:1.7.4 + name: test-backend +- commands: + - go test -run Integration -covermode=atomic -timeout=5m ./pkg/... + depends_on: + - wire-install + image: grafana/build-container:1.7.4 + name: test-backend-integration +trigger: + ref: + - refs/heads/v[0-9]* +type: docker +volumes: +- host: + path: /var/run/docker.sock + name: docker +--- +clone: + disable: true +depends_on: [] +environment: + EDITION: enterprise +image_pull_secrets: +- dockerconfigjson +kind: pipeline +name: release-branch-enterprise-integration-tests +node: + type: no-parallel +platform: + arch: amd64 + os: linux +services: +- environment: + PGDATA: /var/lib/postgresql/data/pgdata + POSTGRES_DB: grafanatest + POSTGRES_PASSWORD: grafanatest + POSTGRES_USER: grafanatest + image: postgres:12.3-alpine + name: postgres + volumes: + - name: postgres + path: /var/lib/postgresql/data/pgdata +- environment: + MYSQL_DATABASE: grafana_tests + MYSQL_PASSWORD: password + MYSQL_ROOT_PASSWORD: rootpass + MYSQL_USER: grafana + image: mysql:5.7.39 + name: mysql + volumes: + - name: mysql + path: /var/lib/mysql +- environment: {} + image: redis:6.2.1-alpine + name: redis +- environment: {} + image: memcached:1.6.9-alpine + name: memcached +steps: +- commands: + - mkdir -p bin + - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.0.30/grabpl + - chmod +x bin/grabpl + image: byrnedo/alpine-curl:0.1.8 + name: grabpl +- commands: + - echo $DRONE_RUNNER_NAME + image: alpine:3.17.1 + name: identify-runner +- commands: + - git clone "https://$${GITHUB_TOKEN}@github.com/grafana/grafana-enterprise.git" + - cd grafana-enterprise + - git checkout ${DRONE_BRANCH} + environment: + GITHUB_TOKEN: + from_secret: github_token + image: grafana/build-container:1.7.4 + name: clone-enterprise +- commands: + - mv bin/grabpl /tmp/ + - rmdir bin + - mv grafana-enterprise /tmp/ + - /tmp/grabpl init-enterprise --github-token $${GITHUB_TOKEN} /tmp/grafana-enterprise + - mv /tmp/grafana-enterprise/deployment_tools_config.json deployment_tools_config.json + - mkdir bin + - mv /tmp/grabpl bin/ + depends_on: + - clone-enterprise + - grabpl + environment: + GITHUB_TOKEN: + from_secret: github_token + image: grafana/build-container:1.7.4 + name: init-enterprise +- commands: + - '# It is required that code generated from Thema/CUE be committed and in sync + with its inputs.' + - '# The following command will fail if running code generators produces any diff + in output.' + - CODEGEN_VERIFY=1 make gen-cue + depends_on: + - init-enterprise + image: grafana/build-container:1.7.4 + name: verify-gen-cue +- commands: + - make gen-go + depends_on: + - verify-gen-cue + image: grafana/build-container:1.7.4 + name: wire-install +- commands: + - apt-get update + - apt-get install -yq postgresql-client + - dockerize -wait tcp://postgres:5432 -timeout 120s + - psql -p 5432 -h postgres -U grafanatest -d grafanatest -f devenv/docker/blocks/postgres_tests/setup.sql + - go clean -testcache + - go list './pkg/...' | xargs -I {} sh -c 'go test -run Integration -covermode=atomic + -timeout=5m {}' + depends_on: + - wire-install + environment: + GRAFANA_TEST_DB: postgres + PGPASSWORD: grafanatest + POSTGRES_HOST: postgres + image: grafana/build-container:1.7.4 + name: postgres-integration-tests - commands: - - ./bin/build package --jobs 8 --edition enterprise2 --build-id ${DRONE_BUILD_NUMBER} - --variants linux-amd64 --sign + - apt-get update + - apt-get install -yq default-mysql-client + - dockerize -wait tcp://mysql:3306 -timeout 120s + - cat devenv/docker/blocks/mysql_tests/setup.sql | mysql -h mysql -P 3306 -u root + -prootpass + - go clean -testcache + - go list './pkg/...' | xargs -I {} sh -c 'go test -run Integration -covermode=atomic + -timeout=5m {}' depends_on: - - build-plugins - - build-backend - - build-frontend - - build-frontend-packages - - build-backend-enterprise2 + - wire-install environment: - GPG_KEY_PASSWORD: - from_secret: packages_gpg_passphrase - GPG_PRIV_KEY: - from_secret: packages_gpg_private_key - GPG_PUB_KEY: - from_secret: packages_gpg_public_key - GRAFANA_API_KEY: - from_secret: grafana_api_key - image: grafana/build-container:1.6.6 - name: package-enterprise2 + GRAFANA_TEST_DB: mysql + MYSQL_HOST: mysql + image: grafana/build-container:1.7.4 + name: mysql-integration-tests - commands: - - ./bin/grabpl upload-cdn --edition enterprise2 + - dockerize -wait tcp://redis:6379/0 -timeout 120s + - go clean -testcache + - go list './pkg/...' | xargs -I {} sh -c 'go test -run Integration -covermode=atomic + -timeout=5m {}' depends_on: - - package-enterprise2 + - wire-install environment: - GCP_KEY: - from_secret: gcp_key - PRERELEASE_BUCKET: - from_secret: prerelease_bucket - image: grafana/grafana-ci-deploy:1.3.3 - name: upload-cdn-assets-enterprise2 + REDIS_URL: redis://redis:6379/0 + image: grafana/build-container:1.7.4 + name: redis-integration-tests - commands: - - ./bin/grabpl upload-packages --edition enterprise2 + - dockerize -wait tcp://memcached:11211 -timeout 120s + - go clean -testcache + - go list './pkg/...' | xargs -I {} sh -c 'go test -run Integration -covermode=atomic + -timeout=5m {}' depends_on: - - package-enterprise2 + - wire-install environment: - GCP_KEY: - from_secret: gcp_key - PRERELEASE_BUCKET: - from_secret: prerelease_bucket - image: grafana/grafana-ci-deploy:1.3.3 - name: upload-packages-enterprise2 + MEMCACHED_HOSTS: memcached:11211 + image: grafana/build-container:1.7.4 + name: memcached-integration-tests trigger: ref: - refs/heads/v[0-9]* @@ -4930,93 +5996,90 @@ volumes: --- clone: disable: true -depends_on: [] +depends_on: +- release-branch-enterprise-build-e2e-publish +- release-branch-enterprise-test-frontend +- release-branch-enterprise-test-backend +environment: + EDITION: enterprise image_pull_secrets: - dockerconfigjson kind: pipeline -name: release-branch-enterprise-test-frontend -node: - type: no-parallel +name: release-branch-enterprise-windows platform: arch: amd64 - os: linux + os: windows + version: "1809" services: [] steps: - commands: - - git clone "https://$${GITHUB_TOKEN}@github.com/grafana/grafana-enterprise.git" + - echo $env:DRONE_RUNNER_NAME + image: mcr.microsoft.com/windows:1809 + name: identify-runner +- commands: + - $$ProgressPreference = "SilentlyContinue" + - Invoke-WebRequest https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.0.30/windows/grabpl.exe + -OutFile grabpl.exe + - git clone "https://$$env:GITHUB_TOKEN@github.com/grafana/grafana-enterprise.git" - cd grafana-enterprise - - git checkout ${DRONE_BRANCH} + - git checkout $$env:DRONE_BRANCH environment: GITHUB_TOKEN: from_secret: github_token - image: grafana/build-container:1.6.6 - name: clone-enterprise + image: grafana/ci-wix:0.1.1 + name: clone - commands: - - mv bin/grabpl /tmp/ - - rmdir bin - - mv grafana-enterprise /tmp/ - - /tmp/grabpl init-enterprise --github-token $${GITHUB_TOKEN} /tmp/grafana-enterprise - - mv /tmp/grafana-enterprise/deployment_tools_config.json deployment_tools_config.json - - mkdir bin - - mv /tmp/grabpl bin/ + - cp -r grafana-enterprise C:\App\grafana-enterprise + - rm -r -force grafana-enterprise + - cp grabpl.exe C:\App\grabpl.exe + - rm -force grabpl.exe + - C:\App\grabpl.exe init-enterprise --github-token $$env:GITHUB_TOKEN C:\App\grafana-enterprise + $$env:DRONE_BRANCH + - cp C:\App\grabpl.exe grabpl.exe depends_on: - - clone-enterprise + - clone environment: GITHUB_TOKEN: from_secret: github_token - image: grafana/build-container:1.6.6 - name: init-enterprise -- commands: - - echo $DRONE_RUNNER_NAME - image: alpine:3.15.6 - name: identify-runner -- commands: - - mkdir -p bin - - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.0.15/grabpl - - chmod +x bin/grabpl - image: byrnedo/alpine-curl:0.1.8 - name: grabpl -- commands: - - yarn install --immutable - depends_on: - - init-enterprise - image: grafana/build-container:1.6.6 - name: yarn-install -- commands: - - yarn betterer ci - depends_on: - - init-enterprise - - yarn-install - failure: ignore - image: grafana/build-container:1.6.6 - name: betterer-frontend + image: grafana/ci-wix:0.1.1 + name: windows-init - commands: - - yarn run ci:test-frontend + - $$gcpKey = $$env:GCP_KEY + - '[System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($$gcpKey)) + > gcpkey.json' + - dos2unix gcpkey.json + - gcloud auth activate-service-account --key-file=gcpkey.json + - rm gcpkey.json + - cp C:\App\nssm-2.24.zip . depends_on: - - init-enterprise - - yarn-install + - windows-init environment: - TEST_MAX_WORKERS: 50% - image: grafana/build-container:1.6.6 - name: test-frontend + GCP_KEY: + from_secret: gcp_key + GITHUB_TOKEN: + from_secret: github_token + PRERELEASE_BUCKET: + from_secret: prerelease_bucket + image: grafana/ci-wix:0.1.1 + name: build-windows-installer trigger: ref: - refs/heads/v[0-9]* type: docker volumes: - host: - path: /var/run/docker.sock + path: //./pipe/docker_engine/ name: docker --- clone: disable: true depends_on: [] environment: - EDITION: enterprise + EDITION: enterprise2 image_pull_secrets: - dockerconfigjson kind: pipeline -name: release-branch-enterprise-test-backend +name: release-branch-enterprise2-build-e2e-publish node: type: no-parallel platform: @@ -5024,6 +6087,16 @@ platform: os: linux services: [] steps: +- commands: + - mkdir -p bin + - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.0.30/grabpl + - chmod +x bin/grabpl + image: byrnedo/alpine-curl:0.1.8 + name: grabpl +- commands: + - echo $DRONE_RUNNER_NAME + image: alpine:3.17.1 + name: identify-runner - commands: - git clone "https://$${GITHUB_TOKEN}@github.com/grafana/grafana-enterprise.git" - cd grafana-enterprise @@ -5031,14 +6104,8 @@ steps: environment: GITHUB_TOKEN: from_secret: github_token - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: clone-enterprise -- commands: - - mkdir -p bin - - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.0.15/grabpl - - chmod +x bin/grabpl - image: byrnedo/alpine-curl:0.1.8 - name: grabpl - commands: - mv bin/grabpl /tmp/ - rmdir bin @@ -5049,23 +6116,32 @@ steps: - mv /tmp/grabpl bin/ depends_on: - clone-enterprise + - grabpl environment: GITHUB_TOKEN: from_secret: github_token - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: init-enterprise -- commands: - - echo $DRONE_RUNNER_NAME - image: alpine:3.15.6 - name: identify-runner - commands: - go build -o ./bin/build -ldflags '-extldflags -static' ./pkg/build/cmd depends_on: - init-enterprise environment: CGO_ENABLED: 0 - image: golang:1.19.4 + image: golang:1.20.4 name: compile-build-cmd +- commands: + - make gen-go + depends_on: + - init-enterprise + image: grafana/build-container:1.7.4 + name: wire-install +- commands: + - yarn install --immutable + depends_on: + - init-enterprise + image: grafana/build-container:1.7.4 + name: yarn-install - commands: - '# It is required that code generated from Thema/CUE be committed and in sync with its inputs.' @@ -5074,26 +6150,161 @@ steps: - CODEGEN_VERIFY=1 make gen-cue depends_on: - init-enterprise - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: verify-gen-cue - commands: - - make gen-go + - ./bin/build build-frontend --jobs 8 --edition enterprise --build-id ${DRONE_BUILD_NUMBER} + depends_on: + - compile-build-cmd + - yarn-install + environment: + NODE_OPTIONS: --max_old_space_size=8192 + image: grafana/build-container:1.7.4 + name: build-frontend +- commands: + - ./bin/build build-frontend-packages --jobs 8 --edition enterprise --build-id ${DRONE_BUILD_NUMBER} + depends_on: + - compile-build-cmd + - yarn-install + environment: + NODE_OPTIONS: --max_old_space_size=8192 + image: grafana/build-container:1.7.4 + name: build-frontend-packages +- commands: + - ./bin/build build-plugins --jobs 8 --edition enterprise + depends_on: + - compile-build-cmd + - yarn-install + environment: + GRAFANA_API_KEY: + from_secret: grafana_api_key + image: grafana/build-container:1.7.4 + name: build-plugins +- commands: + - ./bin/build build-backend --jobs 8 --edition enterprise2 --build-id ${DRONE_BUILD_NUMBER} + --variants linux-amd64 + depends_on: + - wire-install + - compile-build-cmd + image: grafana/build-container:1.7.4 + name: build-backend-enterprise2 +- commands: + - ./bin/build package --jobs 8 --edition enterprise2 --build-id ${DRONE_BUILD_NUMBER} + --sign + depends_on: + - build-plugins + - build-backend-enterprise2 + - build-frontend + - build-frontend-packages + environment: + GPG_KEY_PASSWORD: + from_secret: packages_gpg_passphrase + GPG_PRIV_KEY: + from_secret: packages_gpg_private_key + GPG_PUB_KEY: + from_secret: packages_gpg_public_key + GRAFANA_API_KEY: + from_secret: grafana_api_key + image: grafana/build-container:1.7.4 + name: package-enterprise2 +- commands: + - ./bin/build upload-cdn --edition enterprise2 + depends_on: + - package-enterprise2 + environment: + ENTERPRISE2_CDN_PATH: + from_secret: enterprise2-cdn-path + GCP_KEY: + from_secret: gcp_key + PRERELEASE_BUCKET: + from_secret: prerelease_bucket + image: grafana/grafana-ci-deploy:1.3.3 + name: upload-cdn-assets-enterprise2 +- commands: + - ls dist/*.tar.gz* + - cp dist/*.tar.gz* packaging/docker/ + depends_on: + - package-enterprise2 + image: grafana/build-container:1.7.4 + name: copy-packages-for-docker +- commands: + - ./bin/build build-docker --edition enterprise2 --shouldSave + depends_on: + - copy-packages-for-docker + - compile-build-cmd + environment: + DOCKER_ENTERPRISE2_REPO: + from_secret: docker_enterprise2_repo + GCP_KEY: + from_secret: gcp_key + image: google/cloud-sdk + name: build-docker-images + volumes: + - name: docker + path: /var/run/docker.sock +- commands: + - ./bin/build build-docker --edition enterprise2 --shouldSave --ubuntu + depends_on: + - copy-packages-for-docker + - compile-build-cmd + environment: + DOCKER_ENTERPRISE2_REPO: + from_secret: docker_enterprise2_repo + GCP_KEY: + from_secret: gcp_key + image: google/cloud-sdk + name: build-docker-images-ubuntu + volumes: + - name: docker + path: /var/run/docker.sock +- commands: + - ./bin/build artifacts docker fetch --edition enterprise2 depends_on: - - verify-gen-cue - image: grafana/build-container:1.6.6 - name: wire-install + - build-docker-images + - build-docker-images-ubuntu + environment: + DOCKER_ENTERPRISE2_REPO: + from_secret: docker_enterprise2_repo + DOCKER_PASSWORD: + from_secret: docker_password + DOCKER_USER: + from_secret: docker_username + GCP_KEY: + from_secret: gcp_key + image: google/cloud-sdk + name: fetch-images-enterprise2 + volumes: + - name: docker + path: /var/run/docker.sock - commands: - - go test -short -covermode=atomic -timeout=30m ./pkg/... + - ./bin/build artifacts docker publish-enterprise2 --dockerhub-repo $${DOCKER_ENTERPRISE2_REPO} depends_on: - - wire-install - image: grafana/build-container:1.6.6 - name: test-backend + - fetch-images-enterprise2 + environment: + DOCKER_ENTERPRISE2_REPO: + from_secret: docker_enterprise2_repo + DOCKER_PASSWORD: + from_secret: docker_password + DOCKER_USER: + from_secret: docker_username + GCP_KEY: + from_secret: gcp_key_hg + image: google/cloud-sdk + name: publish-images-enterprise2 + volumes: + - name: docker + path: /var/run/docker.sock - commands: - - go test -run Integration -covermode=atomic -timeout=30m ./pkg/... + - ./bin/build upload-packages --edition enterprise2 depends_on: - - wire-install - image: grafana/build-container:1.6.6 - name: test-backend-integration + - package-enterprise2 + environment: + GCP_KEY: + from_secret: gcp_key + PRERELEASE_BUCKET: + from_secret: prerelease_bucket + image: grafana/grafana-ci-deploy:1.3.3 + name: upload-packages-enterprise2 trigger: ref: - refs/heads/v[0-9]* @@ -5102,101 +6313,121 @@ volumes: - host: path: /var/run/docker.sock name: docker +- name: postgres + temp: + medium: memory +- name: mysql + temp: + medium: memory --- clone: - disable: true + retries: 3 depends_on: [] environment: - EDITION: enterprise2 + EDITION: oss image_pull_secrets: - dockerconfigjson kind: pipeline -name: release-branch-enterprise2-test-backend +name: integration-tests-oss node: type: no-parallel platform: arch: amd64 os: linux -services: [] +services: +- environment: + PGDATA: /var/lib/postgresql/data/pgdata + POSTGRES_DB: grafanatest + POSTGRES_PASSWORD: grafanatest + POSTGRES_USER: grafanatest + image: postgres:12.3-alpine + name: postgres + volumes: + - name: postgres + path: /var/lib/postgresql/data/pgdata +- environment: + MYSQL_DATABASE: grafana_tests + MYSQL_PASSWORD: password + MYSQL_ROOT_PASSWORD: rootpass + MYSQL_USER: grafana + image: mysql:5.7.39 + name: mysql + volumes: + - name: mysql + path: /var/lib/mysql steps: -- commands: - - git clone "https://$${GITHUB_TOKEN}@github.com/grafana/grafana-enterprise.git" - - cd grafana-enterprise - - git checkout ${DRONE_BRANCH} - environment: - GITHUB_TOKEN: - from_secret: github_token - image: grafana/build-container:1.6.6 - name: clone-enterprise - commands: - mkdir -p bin - - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.0.15/grabpl + - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.0.30/grabpl - chmod +x bin/grabpl image: byrnedo/alpine-curl:0.1.8 name: grabpl -- commands: - - mv bin/grabpl /tmp/ - - rmdir bin - - mv grafana-enterprise /tmp/ - - /tmp/grabpl init-enterprise --github-token $${GITHUB_TOKEN} /tmp/grafana-enterprise - - mv /tmp/grafana-enterprise/deployment_tools_config.json deployment_tools_config.json - - mkdir bin - - mv /tmp/grabpl bin/ - depends_on: - - clone-enterprise - environment: - GITHUB_TOKEN: - from_secret: github_token - image: grafana/build-container:1.6.6 - name: init-enterprise - commands: - echo $DRONE_RUNNER_NAME - image: alpine:3.15.6 + image: alpine:3.17.1 name: identify-runner -- commands: - - go build -o ./bin/build -ldflags '-extldflags -static' ./pkg/build/cmd - depends_on: - - init-enterprise - environment: - CGO_ENABLED: 0 - image: golang:1.19.4 - name: compile-build-cmd - commands: - '# It is required that code generated from Thema/CUE be committed and in sync with its inputs.' - '# The following command will fail if running code generators produces any diff in output.' - CODEGEN_VERIFY=1 make gen-cue - depends_on: - - init-enterprise - image: grafana/build-container:1.6.6 + depends_on: [] + image: grafana/build-container:1.7.4 name: verify-gen-cue - commands: - make gen-go depends_on: - verify-gen-cue - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: wire-install - commands: - - go test -tags=pro -covermode=atomic -timeout=30m ./pkg/... + - apt-get update + - apt-get install -yq postgresql-client + - dockerize -wait tcp://postgres:5432 -timeout 120s + - psql -p 5432 -h postgres -U grafanatest -d grafanatest -f devenv/docker/blocks/postgres_tests/setup.sql + - go clean -testcache + - go list './pkg/...' | xargs -I {} sh -c 'go test -run Integration -covermode=atomic + -timeout=5m {}' depends_on: - wire-install - image: grafana/build-container:1.6.6 - name: test-backend-enterprise2 + environment: + GRAFANA_TEST_DB: postgres + PGPASSWORD: grafanatest + POSTGRES_HOST: postgres + image: grafana/build-container:1.7.4 + name: postgres-integration-tests - commands: - - go test -run Integration -covermode=atomic -timeout=30m ./pkg/... + - apt-get update + - apt-get install -yq default-mysql-client + - dockerize -wait tcp://mysql:3306 -timeout 120s + - cat devenv/docker/blocks/mysql_tests/setup.sql | mysql -h mysql -P 3306 -u root + -prootpass + - go clean -testcache + - go list './pkg/...' | xargs -I {} sh -c 'go test -run Integration -covermode=atomic + -timeout=5m {}' depends_on: - wire-install - image: grafana/build-container:1.6.6 - name: test-backend-integration + environment: + GRAFANA_TEST_DB: mysql + MYSQL_HOST: mysql + image: grafana/build-container:1.7.4 + name: mysql-integration-tests trigger: - ref: - - refs/heads/v[0-9]* + event: + - promote + target: integration-tests type: docker volumes: - host: path: /var/run/docker.sock name: docker +- name: postgres + temp: + medium: memory +- name: mysql + temp: + medium: memory --- clone: disable: true @@ -5206,7 +6437,7 @@ environment: image_pull_secrets: - dockerconfigjson kind: pipeline -name: release-branch-enterprise-integration-tests +name: integration-tests-enterprise node: type: no-parallel platform: @@ -5242,37 +6473,39 @@ services: steps: - commands: - mkdir -p bin - - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.0.15/grabpl + - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.0.30/grabpl - chmod +x bin/grabpl image: byrnedo/alpine-curl:0.1.8 name: grabpl - commands: - echo $DRONE_RUNNER_NAME - image: alpine:3.15.6 + image: alpine:3.17.1 name: identify-runner - commands: - git clone "https://$${GITHUB_TOKEN}@github.com/grafana/grafana-enterprise.git" - cd grafana-enterprise - - git checkout ${DRONE_BRANCH} + - git checkout ${DRONE_TAG} environment: GITHUB_TOKEN: from_secret: github_token - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: clone-enterprise - commands: - mv bin/grabpl /tmp/ - rmdir bin - mv grafana-enterprise /tmp/ - /tmp/grabpl init-enterprise --github-token $${GITHUB_TOKEN} /tmp/grafana-enterprise + ${DRONE_TAG} - mv /tmp/grafana-enterprise/deployment_tools_config.json deployment_tools_config.json - mkdir bin - mv /tmp/grabpl bin/ depends_on: - clone-enterprise + - grabpl environment: GITHUB_TOKEN: from_secret: github_token - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: init-enterprise - commands: - '# It is required that code generated from Thema/CUE be committed and in sync @@ -5282,13 +6515,13 @@ steps: - CODEGEN_VERIFY=1 make gen-cue depends_on: - init-enterprise - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: verify-gen-cue - commands: - make gen-go depends_on: - verify-gen-cue - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: wire-install - commands: - apt-get update @@ -5297,14 +6530,14 @@ steps: - psql -p 5432 -h postgres -U grafanatest -d grafanatest -f devenv/docker/blocks/postgres_tests/setup.sql - go clean -testcache - go list './pkg/...' | xargs -I {} sh -c 'go test -run Integration -covermode=atomic - -timeout=30m {}' + -timeout=5m {}' depends_on: - wire-install environment: GRAFANA_TEST_DB: postgres PGPASSWORD: grafanatest POSTGRES_HOST: postgres - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: postgres-integration-tests - commands: - apt-get update @@ -5314,35 +6547,40 @@ steps: -prootpass - go clean -testcache - go list './pkg/...' | xargs -I {} sh -c 'go test -run Integration -covermode=atomic - -timeout=30m {}' + -timeout=5m {}' depends_on: - wire-install environment: GRAFANA_TEST_DB: mysql MYSQL_HOST: mysql - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: mysql-integration-tests - commands: - dockerize -wait tcp://redis:6379/0 -timeout 120s - - ./bin/grabpl integration-tests + - go clean -testcache + - go list './pkg/...' | xargs -I {} sh -c 'go test -run Integration -covermode=atomic + -timeout=5m {}' depends_on: - wire-install environment: REDIS_URL: redis://redis:6379/0 - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: redis-integration-tests - commands: - dockerize -wait tcp://memcached:11211 -timeout 120s - - ./bin/grabpl integration-tests + - go clean -testcache + - go list './pkg/...' | xargs -I {} sh -c 'go test -run Integration -covermode=atomic + -timeout=5m {}' depends_on: - wire-install environment: MEMCACHED_HOSTS: memcached:11211 - image: grafana/build-container:1.6.6 + image: grafana/build-container:1.7.4 name: memcached-integration-tests trigger: - ref: - - refs/heads/v[0-9]* + event: + - promote + target: integration-tests type: docker volumes: - host: @@ -5357,17 +6595,11 @@ volumes: --- clone: disable: true -depends_on: -- release-branch-enterprise-build-e2e-publish -- release-branch-enterprise-test-frontend -- release-branch-enterprise-test-backend -- release-branch-enterprise-integration-tests -environment: - EDITION: enterprise +depends_on: [] image_pull_secrets: - dockerconfigjson kind: pipeline -name: release-branch-enterprise-windows +name: publish-ci-windows-test-image platform: arch: amd64 os: windows @@ -5375,61 +6607,38 @@ platform: services: [] steps: - commands: - - echo $env:DRONE_RUNNER_NAME - image: mcr.microsoft.com/windows:1809 - name: identify-runner -- commands: - - $$ProgressPreference = "SilentlyContinue" - - Invoke-WebRequest https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.0.15/windows/grabpl.exe - -OutFile grabpl.exe - - git clone "https://$$env:GITHUB_TOKEN@github.com/grafana/grafana-enterprise.git" - - cd grafana-enterprise - - git checkout $$env:DRONE_BRANCH + - git clone "https://$$env:GITHUB_TOKEN@github.com/grafana/grafana-ci-sandbox.git" + . + - git checkout -f $$env:DRONE_COMMIT environment: GITHUB_TOKEN: from_secret: github_token image: grafana/ci-wix:0.1.1 name: clone - commands: - - cp -r grafana-enterprise C:\App\grafana-enterprise - - rm -r -force grafana-enterprise - - cp grabpl.exe C:\App\grabpl.exe - - rm -force grabpl.exe - - C:\App\grabpl.exe init-enterprise --github-token $$env:GITHUB_TOKEN C:\App\grafana-enterprise - - cp C:\App\grabpl.exe grabpl.exe - depends_on: - - clone - environment: - GITHUB_TOKEN: - from_secret: github_token - image: grafana/ci-wix:0.1.1 - name: windows-init -- commands: - - $$gcpKey = $$env:GCP_KEY - - '[System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($$gcpKey)) - > gcpkey.json' - - dos2unix gcpkey.json - - gcloud auth activate-service-account --key-file=gcpkey.json - - rm gcpkey.json - - cp C:\App\nssm-2.24.zip . - depends_on: - - windows-init + - cd scripts\build\ci-windows-test + - docker login -u $$env:DOCKER_USERNAME -p $$env:DOCKER_PASSWORD + - docker build -t grafana/grafana-ci-windows-test:$$env:TAG . + - docker push grafana/grafana-ci-windows-test:$$env:TAG environment: - GCP_KEY: - from_secret: gcp_key - GITHUB_TOKEN: - from_secret: github_token - PRERELEASE_BUCKET: - from_secret: prerelease_bucket - image: grafana/ci-wix:0.1.1 - name: build-windows-installer + DOCKER_PASSWORD: + from_secret: docker_password + DOCKER_USERNAME: + from_secret: docker_username + image: docker:windowsservercore-1809 + name: build-and-publish + volumes: + - name: docker + path: //./pipe/docker_engine/ trigger: - ref: - - refs/heads/v[0-9]* + event: + - promote + target: + - ci-windows-test-image type: docker volumes: - host: - path: /var/run/docker.sock + path: //./pipe/docker_engine/ name: docker --- clone: @@ -5554,6 +6763,37 @@ trigger: event: cron type: docker --- +clone: + retries: 3 +kind: pipeline +name: grafana-com-nightly +platform: + arch: amd64 + os: linux +steps: +- commands: + - go build -o ./bin/build -ldflags '-extldflags -static' ./pkg/build/cmd + depends_on: [] + environment: + CGO_ENABLED: 0 + image: golang:1.20.4 + name: compile-build-cmd +- commands: + - ./bin/build publish grafana-com --edition oss + depends_on: + - compile-build-cmd + environment: + GCP_KEY: + from_secret: gcp_key + GRAFANA_COM_API_KEY: + from_secret: grafana_api_key + image: grafana/grafana-ci-deploy:1.3.3 + name: post-to-grafana-com +trigger: + cron: grafana-com-nightly + event: cron +type: docker +--- get: name: .dockerconfigjson path: secret/data/common/gcr @@ -5656,7 +6896,37 @@ get: kind: secret name: aws_secret_access_key --- +get: + name: bucket + path: infra/data/ci/grafana-release-eng/security-bucket +kind: secret +name: security_dest_bucket +--- +get: + name: static_asset_editions + path: infra/data/ci/grafana-release-eng/artifact-publishing +kind: secret +name: static_asset_editions +--- +get: + name: security_prefix + path: infra/data/ci/grafana-release-eng/enterprise2 +kind: secret +name: enterprise2_security_prefix +--- +get: + name: cdn_path + path: infra/data/ci/grafana-release-eng/enterprise2 +kind: secret +name: enterprise2-cdn-path +--- +get: + name: security_prefix + path: infra/data/ci/grafana-release-eng/enterprise2 +kind: secret +name: enterprise2_security_prefix +--- kind: signature -hmac: 613244b7c6b51cdcbfb71f124850e27da526b72b2c07c7c660356b484b3e7cb4 +hmac: 74d07313b535ea68d5cbc704b3bd0d88cb2a100b627fd34cf5c43fc5fb90d06e ... \ No newline at end of file diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index b55814b198cd6..5b3546d204f9d 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -12,32 +12,211 @@ # This should make it easy to add new rules without breaking existing ones. # Documentation -/docs/ @grafana/docs-squad -/contribute/ @grafana/docs-squad -/docs/sources/developers/plugins/ @grafana/docs-squad @grafana/plugins-platform-frontend @grafana/plugins-platform-backend -/docs/sources/developers/plugins/backend @grafana/docs-squad @grafana/plugins-platform-backend -# Administration, data sources, querying, release updates: Garrett Guillotte +/docs/ @grafana/docs-grafana +/contribute/ @grafana/docs-grafana +/docs/sources/developers/plugins/ @grafana/docs-grafana @grafana/plugins-platform-frontend @grafana/plugins-platform-backend +/docs/sources/developers/plugins/backend/ @grafana/docs-grafana @grafana/plugins-platform-backend +/.changelog-archive @grafana/docs-grafana +CHANGELOG.md @grafana/docs-grafana +CODE_OF_CONDUCT.md @grafana/docs-grafana +CONTRIBUTING.md @grafana/docs-grafana +GOVERNANCE.md @RichiH +HALL_OF_FAME.md @grafana/docs-grafana +ISSUE_TRIAGE.md @grafana/grafana-community-support +LICENSE @torkelo +LICENSING.md @torkelo +MAINTAINERS.md @RichiH +NOTICE.md @torkelo +README.md @grafana/docs-grafana +ROADMAP.md @torkelo +SECURITY.md @grafana/security-team +SUPPORT.md @torkelo +UPGRADING_DEPENDENCIES.md @grafana/docs-grafana +WORKFLOW.md @torkelo + + # Set up, dashboards/visualization, best practices: Chris Moyer # Alerting: Brenda Muir -/docs/sources/administration/ @gguillotte-grafana -/docs/sources/alerting @brendamuir -/docs/sources/best-practices/ @chri2547 +/docs/sources/administration/ @Eve832 @GrafanaWriter +/docs/sources/alerting/ @brendamuir /docs/sources/dashboards/ @chri2547 -/docs/sources/datasources/ @gguillotte-grafana -/docs/sources/enterprise/ @gguillotte-grafana -/docs/sources/explore/ @gguillotte-grafana +/docs/sources/datasources/ @Eve832 @GrafanaWriter +/docs/sources/explore/ @Eve832 @GrafanaWriter /docs/sources/getting-started/ @chri2547 -/docs/sources/old-alerting @brendamuir -/docs/sources/panels/ @chri2547 -/docs/sources/release-notes/ @gguillotte-grafana -/docs/sources/visualization/ @chri2547 -/docs/sources/whatsnew/ @gguillotte-grafana +/docs/sources/old-alerting/ @brendamuir +/docs/sources/release-notes/ @Eve832 @GrafanaWriter +/docs/sources/setup-grafana/ @chri2547 +/docs/sources/whatsnew/ @Eve832 @GrafanaWriter # Backend code -*.go @grafana/backend-platform -go.mod @grafana/backend-platform -go.sum @grafana/backend-platform -/.bingo @grafana/backend-platform +/go.mod @grafana/backend-platform +/go.sum @grafana/backend-platform +/.bingo/ @grafana/backend-platform +/pkg/README.md @grafana/backend-platform +/pkg/ruleguard.rules.go @grafana/backend-platform +/.bra.toml @grafana/backend-platform +/.golangci.toml @grafana/backend-platform +/build.go @grafana/backend-platform + +/pkg/api/ @grafana/backend-platform +/pkg/bus/ @grafana/backend-platform +/pkg/cmd/ @grafana/backend-platform +/pkg/components/apikeygen/ @grafana/grafana-authnz-team +/pkg/components/apikeygenprefixed/ @grafana/grafana-authnz-team +/pkg/components/dashdiffs/ @grafana/backend-platform +/pkg/components/imguploader/ @grafana/backend-platform +/pkg/components/loki/ @grafana/backend-platform +/pkg/components/null/ @grafana/backend-platform +/pkg/components/simplejson/ @grafana/backend-platform +/pkg/events/ @grafana/backend-platform +/pkg/extensions/ @grafana/backend-platform +/pkg/ifaces/ @grafana/backend-platform +/pkg/infra/appcontext/ @grafana/backend-platform +/pkg/infra/db/ @grafana/backend-platform +/pkg/infra/grn/ @grafana/backend-platform +/pkg/infra/localcache/ @grafana/backend-platform +/pkg/infra/log/ @grafana/backend-platform +/pkg/infra/metrics/ @grafana/backend-platform +/pkg/infra/network/ @grafana/backend-platform +/pkg/infra/process/ @grafana/backend-platform +/pkg/infra/remotecache/ @grafana/backend-platform +/pkg/infra/serverlock/ @grafana/backend-platform +/pkg/infra/slugify/ @grafana/backend-platform +/pkg/infra/tracing/ @grafana/backend-platform +/pkg/infra/usagestats/ @grafana/backend-platform +/pkg/middleware/ @grafana/backend-platform +/pkg/mocks/ @grafana/backend-platform +/pkg/models/ @grafana/backend-platform +/pkg/server/ @grafana/backend-platform +/pkg/services/annotations/ @grafana/backend-platform +/pkg/services/apikey/ @grafana/backend-platform +/pkg/services/cleanup/ @grafana/backend-platform +/pkg/services/comments/ @grafana/backend-platform +/pkg/services/contexthandler/ @grafana/backend-platform +/pkg/services/correlations/ @grafana/backend-platform +/pkg/services/dashboardimport/ @grafana/backend-platform +/pkg/services/dashboards/ @grafana/backend-platform +/pkg/services/dashboardsnapshots/ @grafana/backend-platform +/pkg/services/dashboardversion/ @grafana/backend-platform +/pkg/services/encryption/ @grafana/backend-platform +/pkg/services/featuremgmt/ @grafana/backend-platform +/pkg/services/folder/ @grafana/backend-platform +/pkg/services/hooks/ @grafana/backend-platform +/pkg/services/kmsproviders/ @grafana/backend-platform +/pkg/services/licensing/ @grafana/backend-platform +/pkg/services/navtree/ @grafana/backend-platform +/pkg/services/notifications/ @grafana/backend-platform +/pkg/services/org/ @grafana/backend-platform +/pkg/services/playlist/ @grafana/backend-platform +/pkg/services/plugindashboards/ @grafana/backend-platform +/pkg/services/pluginsettings/ @grafana/backend-platform +/pkg/services/preference/ @grafana/backend-platform +/pkg/services/provisioning/ @grafana/backend-platform +/pkg/services/publicdashboards/ @grafana/dashboards-squad +/pkg/services/query/ @grafana/backend-platform +/pkg/services/queryhistory/ @grafana/backend-platform +/pkg/services/quota/ @grafana/backend-platform +/pkg/services/rendering/ @grafana/backend-platform +/pkg/services/screenshot/ @grafana/backend-platform +/pkg/services/search/ @grafana/backend-platform +/pkg/services/searchusers/ @grafana/backend-platform +/pkg/services/secrets/ @grafana/backend-platform +/pkg/services/shorturls/ @grafana/backend-platform +/pkg/services/sqlstore/ @grafana/backend-platform +/pkg/services/star/ @grafana/backend-platform +/pkg/services/stats/ @grafana/backend-platform +/pkg/services/tag/ @grafana/backend-platform +/pkg/services/team/ @grafana/grafana-authnz-team +/pkg/services/temp_user/ @grafana/backend-platform +/pkg/services/updatechecker/ @grafana/backend-platform +/pkg/services/user/ @grafana/backend-platform +/pkg/services/validations/ @grafana/backend-platform +/pkg/setting/ @grafana/backend-platform +/pkg/tests/ @grafana/backend-platform +/pkg/tsdb/grafanads/ @grafana/backend-platform +/pkg/tsdb/intervalv2/ @grafana/backend-platform +/pkg/tsdb/legacydata/ @grafana/backend-platform +/pkg/tsdb/opentsdb/ @grafana/backend-platform +/pkg/tsdb/sqleng/ @grafana/backend-platform +/pkg/util/ @grafana/backend-platform +/pkg/web/ @grafana/backend-platform + +/pkg/services/grpcserver/ @grafana/backend-platform +/pkg/infra/kvstore/ @grafana/backend-platform +/pkg/infra/fs/ @grafana/backend-platform +/pkg/infra/x/ @grafana/backend-platform + + +# devenv +# Backend code, developers environment +/devenv/docker/blocks/auth/ @grafana/grafana-authnz-team + +# Logs code, developers environment +/devenv/docker/blocks/loki* @grafana/observability-logs +/devenv/docker/blocks/elastic* @grafana/observability-logs + +# Performance tests +/devenv/docker/loadtest-ts/ @grafana/multitenancy-squad + +/devenv/bulk-dashboards/ @grafana/dashboards-squad +/devenv/bulk_alerting_dashboards/ @grafana/alerting-squad-backend +/devenv/create_docker_compose.sh @grafana/backend-platform +/devenv/dashboards.yaml @grafana/dashboards-squad +/devenv/datasources.yaml @grafana/backend-platform +/devenv/datasources_docker.yaml @grafana/backend-platform +/devenv/dev-dashboards-without-uid/ @grafana/dashboards-squad +/devenv/dev-dashboards/ @grafana/dashboards-squad +/devenv/docker/blocks/alert_webhook_listener/ @grafana/alerting-squad-backend +/devenv/docker/blocks/clickhouse/ @grafana/partner-plugins +/devenv/docker/blocks/collectd/ @grafana/observability-metrics +/devenv/docker/blocks/grafana/ @grafana/grafana-as-code +/devenv/docker/blocks/graphite/ @grafana/observability-metrics +/devenv/docker/blocks/graphite09/ @grafana/observability-metrics +/devenv/docker/blocks/graphite1/ @grafana/observability-metrics +/devenv/docker/blocks/influxdb/ @grafana/observability-metrics +/devenv/docker/blocks/influxdb1/ @grafana/observability-metrics +/devenv/docker/blocks/jaeger/ @grafana/observability-traces-and-profiling +/devenv/docker/blocks/maildev/ @grafana/alerting-squad-frontend +/devenv/docker/blocks/memcached/ @grafana/backend-platform +/devenv/docker/blocks/mssql/ @grafana/grafana-bi-squad +/devenv/docker/blocks/mssql_arm64/ @grafana/grafana-bi-squad +/devenv/docker/blocks/mssql_tests/ @grafana/grafana-bi-squad +/devenv/docker/blocks/mssql_tls/ @grafana/grafana-bi-squad +/devenv/docker/blocks/mysql/ @grafana/grafana-bi-squad +/devenv/docker/blocks/mysql_exporter/ @grafana/grafana-bi-squad +/devenv/docker/blocks/mysql_opendata/ @grafana/grafana-bi-squad +/devenv/docker/blocks/mysql_tests/ @grafana/grafana-bi-squad +/devenv/docker/blocks/opentsdb/ @grafana/observability-metrics +/devenv/docker/blocks/phlare/ @grafana/observability-traces-and-profiling +/devenv/docker/blocks/postgres/ @grafana/grafana-bi-squad +/devenv/docker/blocks/postgres_tests/ @grafana/grafana-bi-squad +/devenv/docker/blocks/prometheus/ @grafana/observability-metrics +/devenv/docker/blocks/prometheus_random_data/ @grafana/observability-metrics +/devenv/docker/blocks/redis/ @bergquist +/devenv/docker/blocks/sensugo/ @grafana/backend-platform +/devenv/docker/blocks/slow_proxy/ @bergquist +/devenv/docker/blocks/smtp/ @bergquist +/devenv/docker/blocks/tempo/ @grafana/observability-traces-and-profiling +/devenv/docker/blocks/traefik/ @mckn +/devenv/docker/blocks/zipkin/ @grafana/observability-traces-and-profiling +/devenv/docker/buildcontainer/ @bergquist +/devenv/docker/compose_header.yml @grafana/backend-platform +/devenv/docker/debtest/ @bergquist +/devenv/docker/ha-test-unified-alerting/ @grafana/alerting-squad-backend +/devenv/docker/ha_test/ @grafana/backend-platform +/devenv/docker/loadtest/ @grafana/backend-platform +/devenv/docker/rpmtest/ @grafana/backend-platform +/devenv/jsonnet/ @grafana/grafana-edge-squad +/devenv/local-npm/ @grafana/frontend-ops +/devenv/vscode/ @grafana/frontend-ops +/devenv/setup.sh @grafana/backend-platform + +# Emails +/emails/ @grafana/alerting-squad-frontend + +#Packaging +/packaging/ @DanCech + # Backend code, developers environment /devenv/docker/blocks/auth @grafana/grafana-authnz-team @@ -47,170 +226,394 @@ go.sum @grafana/backend-platform /devenv/docker/blocks/elastic* @grafana/observability-logs # Continuous Integration -.drone.yml @grafana/grafana-release-eng -.drone.star @grafana/grafana-release-eng -/scripts/drone/ @grafana/grafana-release-eng -/pkg/build/ @grafana/grafana-release-eng +.drone.yml @grafana/grafana-delivery +.drone.star @grafana/grafana-delivery +/scripts/drone/ @grafana/grafana-delivery +/pkg/build/ @grafana/grafana-delivery +/.dockerignore @grafana/grafana-delivery +/Dockerfile @grafana/grafana-delivery +/Makefile @grafana/grafana-delivery +/scripts/build/ @grafana/grafana-delivery -# Cloud Datasources backend code -/pkg/tsdb/cloudwatch @grafana/aws-plugins -/pkg/tsdb/azuremonitor @grafana/cloud-provider-plugins -/pkg/tsdb/cloudmonitoring @grafana/cloud-provider-plugins +# OSS Plugin Partnerships backend code +/pkg/tsdb/cloudwatch/ @grafana/aws-plugins +/pkg/tsdb/azuremonitor/ @grafana/partner-plugins +/pkg/tsdb/cloudmonitoring/ @grafana/partner-plugins # Observability backend code -/pkg/tsdb/prometheus @grafana/observability-metrics -/pkg/tsdb/influxdb @grafana/observability-metrics -/pkg/tsdb/elasticsearch @grafana/observability-logs -/pkg/tsdb/graphite @grafana/observability-metrics -/pkg/tsdb/jaeger @grafana/observability-traces-and-profiling -/pkg/tsdb/loki @grafana/observability-logs -/pkg/tsdb/zipkin @grafana/observability-traces-and-profiling -/pkg/tsdb/tempo @grafana/observability-traces-and-profiling +/pkg/tsdb/prometheus/ @grafana/observability-metrics +/pkg/tsdb/influxdb/ @grafana/observability-metrics +/pkg/tsdb/elasticsearch/ @grafana/observability-logs +/pkg/tsdb/graphite/ @grafana/observability-metrics +/pkg/tsdb/loki/ @grafana/observability-logs +/pkg/tsdb/tempo/ @grafana/observability-traces-and-profiling +/pkg/tsdb/phlare/ @grafana/observability-traces-and-profiling +/pkg/tsdb/parca/ @grafana/observability-traces-and-profiling # BI backend code -/pkg/tsdb/mysql @grafana/grafana-bi-squad -/pkg/tsdb/postgres @grafana/grafana-bi-squad -/pkg/tsdb/mssql @grafana/grafana-bi-squad +/pkg/tsdb/mysql/ @grafana/grafana-bi-squad +/pkg/tsdb/postgres/ @grafana/grafana-bi-squad +/pkg/tsdb/mssql/ @grafana/grafana-bi-squad # Database migrations -/pkg/services/sqlstore/migrations @grafana/backend-platform @grafana/hosted-grafana-team +/pkg/services/sqlstore/migrations/ @grafana/backend-platform @grafana/hosted-grafana-team *_mig.go @grafana/backend-platform @grafana/hosted-grafana-team -# Grafana edge -/pkg/services/live/ @grafana/grafana-edge-squad -/pkg/services/searchV2/ @grafana/grafana-edge-squad -/pkg/services/store/ @grafana/grafana-edge-squad -/pkg/services/export/ @grafana/grafana-edge-squad -/pkg/infra/filestore/ @grafana/grafana-edge-squad -/pkg/tsdb/testdatasource/sims/ @grafana/grafana-edge-squad +# Grafana multitenancy +/pkg/services/live/ @grafana/multitenancy-squad +/pkg/services/searchV2/ @grafana/multitenancy-squad +/pkg/services/store/ @grafana/multitenancy-squad +/pkg/services/querylibrary/ @grafana/multitenancy-squad +/pkg/services/export/ @grafana/multitenancy-squad +/pkg/infra/filestorage/ @grafana/multitenancy-squad +/pkg/util/converter/ @grafana/multitenancy-squad # Alerting -/pkg/services/ngalert @grafana/alerting-squad-backend -/pkg/services/sqlstore/migrations/ualert @grafana/alerting-squad-backend -/pkg/services/alerting @grafana/alerting-squad-backend -/pkg/tests/api/alerting @grafana/alerting-squad-backend -/public/app/features/alerting @grafana/alerting-squad-frontend +/pkg/services/ngalert/ @grafana/alerting-squad-backend +/pkg/services/sqlstore/migrations/ualert/ @grafana/alerting-squad-backend +/pkg/services/alerting/ @grafana/alerting-squad-backend +/pkg/tests/api/alerting/ @grafana/alerting-squad-backend +/public/app/features/alerting/ @grafana/alerting-squad-frontend # Library Services -/pkg/services/libraryelements @grafana/user-essentials -/pkg/services/librarypanels @grafana/user-essentials +/pkg/services/libraryelements/ @grafana/user-essentials +/pkg/services/librarypanels/ @grafana/user-essentials # Plugins -/pkg/api/pluginproxy @grafana/plugins-platform-backend -/pkg/plugins @grafana/plugins-platform-backend -/pkg/services/datasourceproxy @grafana/plugins-platform-backend -/pkg/services/datasources @grafana/plugins-platform-backend -/pkg/plugins/pfs @grafana/plugins-platform-backend @grafana/grafana-as-code +/pkg/api/pluginproxy/ @grafana/plugins-platform-backend +/pkg/infra/httpclient/ @grafana/plugins-platform-backend +/pkg/plugins/ @grafana/plugins-platform-backend +/pkg/services/datasourceproxy/ @grafana/plugins-platform-backend +/pkg/services/datasources/ @grafana/plugins-platform-backend +/pkg/services/pluginsintegration/ @grafana/plugins-platform-backend +/pkg/plugins/pfs/ @grafana/plugins-platform-backend @grafana/grafana-as-code +/pkg/tsdb/testdatasource/ @grafana/plugins-platform-backend # Dashboard previews / crawler (behind feature flag) -/pkg/services/thumbs @grafana/grafana-edge-squad +/pkg/services/thumbs/ @grafana/multitenancy-squad # Backend code docs -/contribute/style-guides/backend.md @grafana/backend-platform -/contribute/architecture/backend @grafana/backend-platform -/contribute/engineering/backend @grafana/backend-platform - -/e2e @grafana/user-essentials -/packages @grafana/user-essentials @grafana/plugins-platform-frontend @grafana/grafana-bi-squad -/packages/grafana-e2e-selectors @grafana/user-essentials -/packages/grafana-e2e @grafana/user-essentials -/packages/grafana-toolkit @grafana/plugins-platform-frontend -/packages/grafana-ui/.storybook @grafana/plugins-platform-frontend -/packages/grafana-ui/src/components/DateTimePickers @grafana/grafana-bi-squad -/packages/grafana-ui/src/components/GraphNG @grafana/grafana-bi-squad -/packages/grafana-ui/src/components/Logs @grafana/observability-logs -/packages/grafana-ui/src/components/Table @grafana/grafana-bi-squad -/packages/grafana-ui/src/components/TimeSeries @grafana/grafana-bi-squad -/packages/grafana-ui/src/components/uPlot @grafana/grafana-bi-squad -/packages/grafana-ui/src/utils/storybook @grafana/plugins-platform-frontend -/packages/jaeger-ui-components/ @grafana/observability-traces-and-profiling -/plugins-bundled @grafana/plugins-platform-frontend +/contribute/backend/ @grafana/backend-platform + + +/crowdin.yml @grafana/user-essentials +/public/locales/ @grafana/user-essentials +/public/app/core/internationalization/ @grafana/user-essentials +/e2e/ @grafana/user-essentials +/e2e/cloud-plugins-suite/ @grafana/partner-plugins +/packages/ @grafana/user-essentials @grafana/plugins-platform-frontend @grafana/grafana-bi-squad +/packages/grafana-e2e-selectors/ @grafana/user-essentials +/packages/grafana-e2e/ @grafana/user-essentials +/packages/grafana-toolkit/ @grafana/plugins-platform-frontend +/packages/grafana-ui/.storybook/ @grafana/plugins-platform-frontend +/packages/grafana-ui/src/components/DateTimePickers/ @grafana/user-essentials +/packages/grafana-ui/src/components/GraphNG/ @grafana/grafana-bi-squad +/packages/grafana-ui/src/components/Logs/ @grafana/observability-logs +/packages/grafana-ui/src/components/Table/ @grafana/grafana-bi-squad +/packages/grafana-ui/src/components/TimeSeries/ @grafana/grafana-bi-squad +/packages/grafana-ui/src/components/uPlot/ @grafana/grafana-bi-squad +/packages/grafana-ui/src/utils/storybook/ @grafana/plugins-platform-frontend +/packages/grafana-data/src/**/*logs* @grafana/observability-logs +/plugins-bundled/ @grafana/plugins-platform-frontend + + +# root files, mostly frontend +.browserslistrc @grafana/frontend-ops +package.json @grafana/frontend-ops +tsconfig.json @grafana/frontend-ops +/.editorconfig @grafana/frontend-ops +/.eslintignore @grafana/frontend-ops +/.gitattributes @grafana/frontend-ops +/.gitignore @grafana/frontend-ops +/.husky/pre-commit @grafana/frontend-ops +/.nvmrc @grafana/frontend-ops +/.prettierignore @grafana/frontend-ops +/.yarn @grafana/frontend-ops +/.yarnrc.yml @grafana/frontend-ops +/yarn.lock @grafana/frontend-ops +/.linguirc @grafana/user-essentials +/babel.config.json @grafana/frontend-ops +lerna.json @grafana/frontend-ops +/.prettierrc.js @grafana/frontend-ops +/.eslintrc @grafana/frontend-ops +/.vim @zoltanbedi +/jest.config.js @grafana/frontend-ops +/latest.json @grafana/frontend-ops +/metadata.md @grafana/plugins-platform +/stylelint.config.js @grafana/frontend-ops +/tools/ @grafana/frontend-ops + + # public folder -/public/app/core/components/TimePicker @grafana/grafana-bi-squad -/public/app/core/components/Layers @grafana/grafana-edge-squad +/public/app/core/ @grafana/user-essentials +/public/app/core/components/TimePicker/ @grafana/user-essentials +/public/app/core/components/Layers/ @grafana/grafana-edge-squad +/public/app/features/all.ts @grafana/user-essentials +/public/app/features/admin/ @grafana/grafana-authnz-team +/public/app/features/annotations/ @grafana/user-essentials +/public/app/features/api-keys/ @grafana/user-essentials /public/app/features/canvas/ @grafana/grafana-edge-squad +/public/app/features/commandPalette/ @grafana/user-essentials /public/app/features/comments/ @grafana/grafana-edge-squad +/public/app/features/connections/ @grafana/plugins-platform-frontend +/public/app/features/correlations/ @grafana/explore-squad +/public/app/features/dashboard/ @grafana/dashboards-squad +/public/app/features/datasources/ @grafana/user-essentials /public/app/features/dimensions/ @grafana/grafana-edge-squad +/public/app/features/explore/ @grafana/explore-squad +/public/app/features/expressions/ @grafana/observability-metrics +/public/app/features/folders/ @grafana/user-essentials +/public/app/features/inspector/ @grafana/user-essentials +/public/app/features/invites/ @grafana/user-essentials /public/app/features/geo/ @grafana/grafana-edge-squad -/public/app/features/storage/ @grafana/grafana-edge-squad -/public/app/features/live/ @grafana/grafana-edge-squad -/public/app/features/explore/ @grafana/observability-experience-squad -/public/app/features/plugins @grafana/plugins-platform-frontend -/public/app/features/transformers/spatial @grafana/grafana-edge-squad -/public/app/plugins/panel/alertlist @grafana/alerting-squad-frontend -/public/app/plugins/panel/barchart @grafana/grafana-bi-squad -/public/app/plugins/panel/heatmap @grafana/grafana-bi-squad -/public/app/plugins/panel/histogram @grafana/grafana-bi-squad -/public/app/plugins/panel/logs @grafana/observability-logs -/public/app/plugins/panel/nodeGraph @grafana/observability-traces-and-profiling -/public/app/plugins/panel/traces @grafana/observability-traces-and-profiling -/public/app/plugins/panel/piechart @grafana/grafana-bi-squad -/public/app/plugins/panel/state-timeline @grafana/grafana-bi-squad -/public/app/plugins/panel/status-history @grafana/grafana-bi-squad -/public/app/plugins/panel/table @grafana/grafana-bi-squad -/public/app/plugins/panel/timeseries @grafana/grafana-bi-squad -/public/app/plugins/panel/geomap @grafana/grafana-edge-squad -/public/app/plugins/panel/canvas @grafana/grafana-edge-squad -/public/app/plugins/panel/candlestick @grafana/grafana-edge-squad -/public/app/plugins/panel/icon @grafana/grafana-edge-squad -/scripts/build/release-packages.sh @grafana/plugins-platform-frontend -/scripts/circle-release-next-packages.sh @grafana/plugins-platform-frontend +/public/app/features/library-panels/ @grafana/user-essentials +/public/app/features/logs/ @grafana/observability-logs +/public/app/features/live/ @grafana/multitenancy-squad +/public/app/features/manage-dashboards/ @grafana/dashboards-squad +/public/app/features/notifications/ @grafana/user-essentials +/public/app/features/org/ @grafana/user-essentials +/public/app/features/panel/ @grafana/user-essentials +/public/app/features/playlist/ @grafana/dashboards-squad +/public/app/features/plugins/ @grafana/plugins-platform-frontend +/public/app/features/profile/ @grafana/user-essentials +/public/app/features/runtime/ @ryantxu +/public/app/features/query/ @grafana/dashboards-squad +/public/app/features/query-library/ @grafana/grafana-edge-squad +/public/app/features/sandbox/ @grafana/user-essentials +/public/app/features/scenes/ @grafana/dashboards-squad +/public/app/features/search/ @grafana/user-essentials +/public/app/features/serviceaccounts/ @grafana/grafana-authnz-team +/public/app/features/storage/ @grafana/multitenancy-squad +/public/app/features/teams/ @grafana/grafana-authnz-team +/public/app/features/templating/ @grafana/dashboards-squad +/public/app/features/transformers/ @grafana/grafana-edge-squad +/public/app/features/users/ @grafana/grafana-authnz-team +/public/app/features/variables/ @grafana/dashboards-squad +/public/app/plugins/panel/alertGroups/ @grafana/alerting-squad-frontend +/public/app/plugins/panel/alertlist/ @grafana/alerting-squad-frontend +/public/app/plugins/panel/annolist/ @grafana/user-essentials +/public/app/plugins/panel/barchart/ @grafana/grafana-bi-squad +/public/app/plugins/panel/bargauge/ @grafana/user-essentials +/public/app/plugins/panel/dashlist/ @grafana/user-essentials +/public/app/plugins/panel/debug/ @ryantxu +/public/app/plugins/panel/gauge/ @grafana/user-essentials +/public/app/plugins/panel/gettingstarted/ @grafana/user-essentials +/public/app/plugins/panel/graph/ @grafana/user-essentials +/public/app/plugins/panel/heatmap/ @grafana/grafana-bi-squad +/public/app/plugins/panel/histogram/ @grafana/grafana-bi-squad +/public/app/plugins/panel/logs/ @grafana/observability-logs +/public/app/plugins/panel/nodeGraph/ @grafana/observability-traces-and-profiling +/public/app/plugins/panel/traces/ @grafana/observability-traces-and-profiling +/public/app/plugins/panel/flamegraph/ @grafana/observability-traces-and-profiling +/public/app/plugins/panel/piechart/ @grafana/grafana-bi-squad +/public/app/plugins/panel/state-timeline/ @grafana/grafana-bi-squad +/public/app/plugins/panel/status-history/ @grafana/grafana-bi-squad +/public/app/plugins/panel/table/ @grafana/grafana-bi-squad +/public/app/plugins/panel/table-old/ @grafana/grafana-bi-squad +/public/app/plugins/panel/timeseries/ @grafana/grafana-bi-squad +/public/app/plugins/panel/geomap/ @grafana/grafana-edge-squad +/public/app/plugins/panel/canvas/ @grafana/grafana-edge-squad +/public/app/plugins/panel/candlestick/ @grafana/grafana-edge-squad +/public/app/plugins/panel/icon/ @grafana/grafana-edge-squad +/public/app/plugins/panel/live/ @grafana/multitenancy-squad +/public/app/plugins/panel/news/ @grafana/user-essentials +/public/app/plugins/panel/stat/ @grafana/user-essentials +/public/app/plugins/panel/text/ @grafana/user-essentials +/public/app/plugins/panel/welcome/ @grafana/user-essentials +/public/app/plugins/panel/xychart/ @grafana/grafana-bi-squad +/public/app/plugins/sdk.ts @grafana/plugins-platform-frontend +/public/app/polyfills/old-mediaquerylist.ts @grafana/user-essentials +/public/app/routes/ @grafana/user-essentials +/public/app/store/ @grafana/user-essentials +/public/app/types/ @grafana/user-essentials +/public/dashboards/ @grafana/dashboards-squad +/public/fonts/ @grafana/alerting-squad-frontend +/public/emails/ @grafana/user-essentials +/public/gazetteer/ @ryantxu +/public/img/ @grafana/user-essentials +/public/lib/ @grafana/user-essentials +/public/maps/ @ryantxu +/public/robots.txt @grafana/frontend-ops +/public/sass/ @grafana/user-essentials +/public/test/ @grafana/user-essentials +/public/testdata/ @grafana/user-essentials +/public/views/ @grafana/user-essentials + +/public/app/features/explore/Logs.tsx @grafana/observability-logs +/public/app/features/explore/LogsContainer.tsx @grafana/observability-logs + +/public/app/features/explore/TraceView/ @grafana/observability-traces-and-profiling + +/public/api-merged.json @grafana/backend-platform +/public/api-spec.json @grafana/backend-platform +/public/openapi3.json @grafana/backend-platform +/public/app/angular/ @torkelo +/public/app/app.ts @grafana/frontend-ops +/public/app/dev.ts @grafana/frontend-ops +/public/app/index.ts @grafana/frontend-ops +/public/app/AppWrapper.tsx @grafana/frontend-ops +/public/app/partials/ @grafana/user-essentials + + + + +/scripts/benchmark-access-control.sh @grafana/grafana-authnz-team +/scripts/check-breaking-changes.sh @grafana/plugins-platform-frontend +/scripts/ci-* @grafana/grafana-delivery +/scripts/circle-* @grafana/grafana-delivery /scripts/ci-frontend-metrics.sh @grafana/user-essentials @grafana/plugins-platform-frontend @grafana/grafana-bi-squad -/scripts/grunt @grafana/frontend-ops -/scripts/webpack @grafana/frontend-ops +/scripts/cli/ @grafana/user-essentials +/scripts/clean-git-or-error.sh @grafana/grafana-as-code +/scripts/grafana-server/ @grafana/user-essentials +/scripts/helpers/ @grafana/grafana-delivery +/scripts/import_many_dashboards.sh @torkelo +/scripts/mixin-check.sh @bergquist +/scripts/openapi3/ @grafana/grafana-partnerships-team +/scripts/prepare-packagejson.js @grafana/frontend-ops +/scripts/protobuf-check.sh @grafana/plugins-platform-backend +/scripts/stripnulls.sh @grafana/grafana-as-code +/scripts/tag_release.sh @grafana/grafana-delivery +/scripts/trigger_docker_build.sh @grafana/grafana-delivery +/scripts/trigger_grafana_packer.sh @grafana/grafana-delivery +/scripts/trigger_windows_build.sh @grafana/grafana-delivery +/scripts/validate-devenv-dashboards.sh @grafana/grafana-delivery +/scripts/verify-repo-update/ @grafana/grafana-delivery + +/scripts/webpack/ @grafana/frontend-ops /scripts/generate-a11y-report.sh @grafana/user-essentials -package.json @grafana/frontend-ops -tsconfig.json @grafana/frontend-ops -lerna.json @grafana/frontend-ops -.babelrc @grafana/frontend-ops -.prettierrc.js @grafana/frontend-ops -.eslintrc @grafana/frontend-ops .pa11yci.conf.js @grafana/user-essentials .pa11yci-pr.conf.js @grafana/user-essentials .betterer.results @joshhunt +.betterer.ts @joshhunt # @grafana/ui component documentation -*.mdx @jessover9000 @grafana/plugins-platform-frontend +*.mdx @grafana/plugins-platform-frontend + +# Design system +/public/img/icons/unicons/ @grafana/design-system # Core datasources -/public/app/plugins/datasource/cloudwatch @grafana/aws-plugins -/public/app/plugins/datasource/elasticsearch @grafana/observability-logs -/public/app/plugins/datasource/grafana-azure-monitor-datasource @grafana/cloud-provider-plugins -/public/app/plugins/datasource/graphite @grafana/observability-metrics -/public/app/plugins/datasource/influxdb @grafana/observability-metrics -/public/app/plugins/datasource/jaeger @grafana/observability-traces-and-profiling -/public/app/plugins/datasource/loki @grafana/observability-logs -/public/app/plugins/datasource/mssql @grafana/grafana-bi-squad -/public/app/plugins/datasource/mysql @grafana/grafana-bi-squad -/public/app/plugins/datasource/opentsdb @grafana/backend-platform -/public/app/plugins/datasource/postgres @grafana/grafana-bi-squad -/public/app/plugins/datasource/prometheus @grafana/observability-metrics -/public/app/plugins/datasource/cloud-monitoring @grafana/cloud-provider-plugins -/public/app/plugins/datasource/zipkin @grafana/observability-traces-and-profiling -/public/app/plugins/datasource/tempo @grafana/observability-traces-and-profiling -/public/app/plugins/datasource/alertmanager @grafana/alerting-squad +/public/app/plugins/datasource/dashboard/ @grafana/dashboards-squad +/public/app/plugins/datasource/cloudwatch/ @grafana/aws-plugins +/public/app/plugins/datasource/elasticsearch/ @grafana/observability-logs +/public/app/plugins/datasource/grafana/ @grafana/user-essentials +/public/app/plugins/datasource/testdata/ @grafana/plugins-platform-frontend +/public/app/plugins/datasource/grafana-azure-monitor-datasource/ @grafana/partner-plugins +/public/app/plugins/datasource/graphite/ @grafana/observability-metrics +/public/app/plugins/datasource/influxdb/ @grafana/observability-metrics +/public/app/plugins/datasource/jaeger/ @grafana/observability-traces-and-profiling +/public/app/plugins/datasource/loki/ @grafana/observability-logs +/public/app/plugins/datasource/mixed/ @grafana/dashboards-squad +/public/app/plugins/datasource/mssql/ @grafana/grafana-bi-squad +/public/app/plugins/datasource/mysql/ @grafana/grafana-bi-squad +/public/app/plugins/datasource/opentsdb/ @grafana/backend-platform +/public/app/plugins/datasource/postgres/ @grafana/grafana-bi-squad +/public/app/plugins/datasource/prometheus/ @grafana/observability-metrics +/public/app/plugins/datasource/cloud-monitoring/ @grafana/partner-plugins +/public/app/plugins/datasource/zipkin/ @grafana/observability-traces-and-profiling +/public/app/plugins/datasource/tempo/ @grafana/observability-traces-and-profiling +/public/app/plugins/datasource/phlare/ @grafana/observability-traces-and-profiling +/public/app/plugins/datasource/parca/ @grafana/observability-traces-and-profiling +/public/app/plugins/datasource/alertmanager/ @grafana/alerting-squad + +# SSE - Server Side Expressions +/pkg/expr/ @grafana/observability-metrics # Cloud middleware /grafana-mixin/ @grafana/hosted-grafana-team # Grafana authentication and authorization -/pkg/services/accesscontrol @grafana/grafana-authnz-team -/pkg/services/auth @grafana/grafana-authnz-team +/pkg/login/ @grafana/grafana-authnz-team +/pkg/services/accesscontrol/ @grafana/grafana-authnz-team +/pkg/services/auth/ @grafana/grafana-authnz-team /pkg/services/dashboards/accesscontrol.go @grafana/grafana-authnz-team -/pkg/services/datasources/permissions @grafana/grafana-authnz-team -/pkg/services/datasources/permissions/accesscontrol.go @grafana/grafana-authnz-team -/pkg/services/guardian @grafana/grafana-authnz-team -/pkg/services/ldap @grafana/grafana-authnz-team -/pkg/services/login @grafana/grafana-authnz-team -/pkg/services/multildap @grafana/grafana-authnz-team -/pkg/services/oauthtoken @grafana/grafana-authnz-team -/pkg/services/teamguardian @grafana/grafana-authnz-team -/pkg/services/serviceaccounts @grafana/grafana-authnz-team +/pkg/services/datasources/permissions/ @grafana/grafana-authnz-team +/pkg/services/guardian/ @grafana/grafana-authnz-team +/pkg/services/ldap/ @grafana/grafana-authnz-team +/pkg/services/login/ @grafana/grafana-authnz-team +/pkg/services/multildap/ @grafana/grafana-authnz-team +/pkg/services/oauthtoken/ @grafana/grafana-authnz-team +/pkg/services/teamguardian/ @grafana/grafana-authnz-team +/pkg/services/serviceaccounts/ @grafana/grafana-authnz-team +/pkg/services/loginattempt/ @grafana/grafana-authnz-team +/pkg/services/authn/ @grafana/grafana-authnz-team + +# Support bundles +/public/app/features/support-bundles/ @grafana/grafana-authnz-team +/pkg/services/supportbundles/ @grafana/grafana-authnz-team # Grafana Partnerships Team /pkg/infra/httpclient/httpclientprovider/sigv4_middleware.go @grafana/grafana-partnerships-team +/pkg/infra/httpclient/httpclientprovider/sigv4_middleware_test.go @grafana/grafana-partnerships-team + +# Kind definitions +/kinds/dashboard @grafana/dashboards-squad +/kinds/ @grafana/grafana-as-code -# Schema framework and code generation -/pkg/codegen @grafana/grafana-as-code -/pkg/framework/coremodel @grafana/grafana-as-code +# Kind system and code generation +embed.go @grafana/grafana-as-code +/pkg/kinds/ @grafana/grafana-as-code +/pkg/cuectx/ @grafana/grafana-as-code +/pkg/registry/ @grafana/grafana-as-code +/pkg/codegen/ @grafana/grafana-as-code +/pkg/kindsys/ @grafana/grafana-as-code +/pkg/kindsys/kindcat_custom.cue @grafana/cloud-app-platform-squad +/pkg/kinds/*/*_gen.go @grafana/grafana-as-code +/pkg/registry/corekind/ @grafana/grafana-as-code /public/app/plugins/*gen.go @grafana/grafana-as-code +/cue.mod/ @grafana/grafana-as-code + +# GitHub Workflows and Templates +/.github/CODEOWNERS @tolzhabayev +/.github/ISSUE_TEMPLATE/ @torkelo +/.github/PULL_REQUEST_TEMPLATE.md @torkelo +/.github/bot.md @torkelo +/.github/commands.json @torkelo +/.github/dependabot.yml @grafana/frontend-ops +/.github/metrics-collector.json @torkelo +/.github/pr-checks.json @marefr +/.github/pr-commands.json @marefr +/.github/renovate.json5 @grafana/frontend-ops +/.github/teams.yml @armandgrillet +/.github/workflows/backport.yml @grafana/grafana-delivery +/.github/workflows/bump-version.yml @grafana/grafana-delivery +/.github/workflows/close-milestone.yml @grafana/grafana-delivery +/.github/workflows/cloud-data-sources-code-coverage.yml @grafana/partner-plugins @grafana/aws-plugins +/.github/workflows/codeowners-validator.yml @tolzhabayev +/.github/workflows/codeql-analysis.yml @DanCech +/.github/workflows/commands.yml @torkelo +/.github/workflows/detect-breaking-changes-* @grafana/plugins-platform-frontend +/.github/workflows/doc-validator.yml @grafana/docs-grafana +/.github/workflows/epic-add-to-platform-ux-parent-project.yml @meanmina +/.github/workflows/github-release.yml @torkelo +/.github/workflows/issue-labeled.yml @armandgrillet +/.github/workflows/metrics-collector.yml @torkelo +/.github/workflows/milestone.yml @marefr +/.github/workflows/ox-code-coverage.yml @grafana/explore-squad +/.github/workflows/pr-checks.yml @marefr +/.github/workflows/pr-codeql-analysis-go.yml @DanCech +/.github/workflows/pr-codeql-analysis-javascript.yml @DanCech +/.github/workflows/pr-codeql-analysis-python.yml @DanCech +/.github/workflows/pr-commands-closed.yml @tolzhabayev +/.github/workflows/pr-commands.yml @marefr +/.github/workflows/publish-technical-documentation-next.yml @grafana/docs-grafana +/.github/workflows/publish-technical-documentation-release.yml @grafana/docs-grafana +/.github/workflows/remove-milestone.yml @grafana/user-essentials +/.github/workflows/sbom-report.yml @grafana/security-team +/.github/workflows/scripts/json-file-to-job-output.js @grafana/plugins-platform-frontend +/.github/workflows/scripts/pr-get-job-link.js @grafana/plugins-platform-frontend +/.github/workflows/stale.yml @grafana/user-essentials +/.github/workflows/update-changelog.yml @grafana/grafana-delivery +/.github/workflows/snyk.yml @grafana/security-team + +# Conf +/conf/defaults.ini @torkelo +/conf/sample.ini @torkelo +/conf/ldap.toml @grafana/grafana-authnz-team +/conf/ldap_multiple.toml @grafana/grafana-authnz-team +/conf/provisioning/access-control/ @grafana/grafana-authnz-team +/conf/provisioning/alerting/ @grafana/alerting-squad-backend +/conf/provisioning/dashboards/ @grafana/dashboards-squad +/conf/provisioning/datasources/ @grafana/plugins-platform-backend +/conf/provisioning/notifiers/ @bergquist +/conf/provisioning/plugins/ @grafana/plugins-platform-backend diff --git a/.github/pr-commands.json b/.github/pr-commands.json index addfca786bf10..544581a0a7c25 100644 --- a/.github/pr-commands.json +++ b/.github/pr-commands.json @@ -66,8 +66,7 @@ "scripts/build/**/*", "scripts/*.sh", "Makefile", - "Dockerfile", - "Dockerfile.ubuntu" + "Dockerfile" ], "action": "updateLabel", "addLabel": "type/build-packaging" diff --git a/.github/workflows/enterprise-pr-check.yml b/.github/workflows/enterprise-pr-check.yml deleted file mode 100644 index f5552fe94377b..0000000000000 --- a/.github/workflows/enterprise-pr-check.yml +++ /dev/null @@ -1,26 +0,0 @@ -name: Enterprise PR check -on: - pull_request: - branches: - - main - - 'v[0-9]+.[0-9]+.x' -jobs: - dispatch: - runs-on: ubuntu-latest - steps: - - name: Checkout Actions - uses: actions/checkout@v2 - with: - repository: "grafana/grafana-github-actions" - path: ./actions - ref: main - - name: Install Actions - run: npm install --production --prefix ./actions - - name: Repository Dispatch - uses: ./actions/repository-dispatch - with: - token: ${{ secrets.GH_BOT_ACCESS_TOKEN }} - repository: grafana/grafana-enterprise - event_type: oss-pull-request - client_payload: - '{"source_branch": "${{ github.head_ref }}", "target_branch": "${{ github.base_ref }}", "pr_number": "${{ github.event.number }}"}' diff --git a/.github/workflows/ox-code-coverage.yml b/.github/workflows/ox-code-coverage.yml index 847249fa6e770..b6cbf2996b7b2 100644 --- a/.github/workflows/ox-code-coverage.yml +++ b/.github/workflows/ox-code-coverage.yml @@ -8,8 +8,6 @@ on: branches-ignore: - dependabot/** - backport-* - # @PERCONA - disable workflow - - '*' jobs: workflow-call: diff --git a/.github/workflows/publish-technical-documentation-next.yml b/.github/workflows/publish-technical-documentation-next.yml index 1b23f8ba3f208..56b133ac8679b 100644 --- a/.github/workflows/publish-technical-documentation-next.yml +++ b/.github/workflows/publish-technical-documentation-next.yml @@ -6,7 +6,6 @@ on: - "main" paths: - "docs/sources/**" - - "packages/grafana-*/**" workflow_dispatch: jobs: sync: @@ -17,9 +16,11 @@ jobs: uses: "actions/checkout@v3" - name: "Clone website-sync Action" - # WEBSITE_SYNC_GRAFANA is a fine-grained GitHub Personal Access Token that expires. - # It must be updated in the grafanabot GitHub account. - run: "git clone --single-branch --no-tags --depth 1 -b master https://grafanabot:${{ secrets.WEBSITE_SYNC_GRAFANA }}@github.com/grafana/website-sync ./.github/actions/website-sync" + # WEBSITE_SYNC_TOKEN is a fine-grained GitHub Personal Access Token that expires. + # It must be regenerated in the grafanabot GitHub account and requires a Grafana organization + # GitHub administrator to update the organization secret. + # The IT helpdesk can update the organization secret. + run: "git clone --single-branch --no-tags --depth 1 -b master https://grafanabot:${{ secrets.WEBSITE_SYNC_TOKEN }}@github.com/grafana/website-sync ./.github/actions/website-sync" - name: "Publish to website repository (next)" uses: "./.github/actions/website-sync" @@ -28,8 +29,10 @@ jobs: repository: "grafana/website" branch: "master" host: "github.com" - # PUBLISH_TO_WEBSITE_GRAFANA is a fine-grained GitHub Personal Access Token that expires. - # It must be updated in the grafanabot GitHub account. - github_pat: "grafanabot:${{ secrets.PUBLISH_TO_WEBSITE_GRAFANA }}" + # PUBLISH_TO_WEBSITE_TOKEN is a fine-grained GitHub Personal Access Token that expires. + # It must be regenerated in the grafanabot GitHub account and requires a Grafana organization + # GitHub administrator to update the organization secret. + # The IT helpdesk can update the organization secret. + github_pat: "grafanabot:${{ secrets.PUBLISH_TO_WEBSITE_TOKEN }}" source_folder: "docs/sources" target_folder: "content/docs/grafana/next" diff --git a/.github/workflows/publish-technical-documentation-release.yml b/.github/workflows/publish-technical-documentation-release.yml index e57b25ec17de0..69fafd1d0e8d0 100644 --- a/.github/workflows/publish-technical-documentation-release.yml +++ b/.github/workflows/publish-technical-documentation-release.yml @@ -8,7 +8,6 @@ on: - v[0-9]+.[0-9]+.[0-9]+ paths: - "docs/sources/**" - - "packages/grafana-*/**" workflow_dispatch: jobs: sync: @@ -46,9 +45,11 @@ jobs: - name: "Clone website-sync Action" if: "steps.has-matching-release-tag.outputs.bool == 'true'" - # WEBSITE_SYNC_GRAFANA is a fine-grained GitHub Personal Access Token that expires. - # It must be updated in the grafanabot GitHub account. - run: "git clone --single-branch --no-tags --depth 1 -b master https://grafanabot:${{ secrets.WEBSITE_SYNC_GRAFANA }}@github.com/grafana/website-sync ./.github/actions/website-sync" + # WEBSITE_SYNC_TOKEN is a fine-grained GitHub Personal Access Token that expires. + # It must be regenerated in the grafanabot GitHub account and requires a Grafana organization + # GitHub administrator to update the organization secret. + # The IT helpdesk can update the organization secret. + run: "git clone --single-branch --no-tags --depth 1 -b master https://grafanabot:${{ secrets.WEBSITE_SYNC_TOKEN }}@github.com/grafana/website-sync ./.github/actions/website-sync" - name: "Publish to website repository (release)" if: "steps.has-matching-release-tag.outputs.bool == 'true'" @@ -58,8 +59,10 @@ jobs: repository: "grafana/website" branch: "master" host: "github.com" - # PUBLISH_TO_WEBSITE_GRAFANA is a fine-grained GitHub Personal Access Token that expires. - # It must be updated in the grafanabot GitHub account. - github_pat: "grafanabot:${{ secrets.PUBLISH_TO_WEBSITE_GRAFANA }}" + # PUBLISH_TO_WEBSITE_TOKEN is a fine-grained GitHub Personal Access Token that expires. + # It must be regenerated in the grafanabot GitHub account and requires a Grafana organization + # GitHub administrator to update the organization secret. + # The IT helpdesk can update the organization secret. + github_pat: "grafanabot:${{ secrets.PUBLISH_TO_WEBSITE_TOKEN }}" source_folder: "docs/sources" target_folder: "content/docs/grafana/${{ steps.target.outputs.target }}" diff --git a/.golangci.toml b/.golangci.toml index 8ae79c22f95fe..dd29a8fbc7560 100644 --- a/.golangci.toml +++ b/.golangci.toml @@ -56,7 +56,6 @@ enable = [ "typecheck", "asciicheck", "errorlint", - "sqlclosecheck", "revive", ] diff --git a/CHANGELOG.md b/CHANGELOG.md index a6596a89a3f88..227e9dcaaf982 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,13 @@ + + +# 9.2.15 (2023-03-22) + + + + + + + # 9.2.10 (2023-01-24) diff --git a/Dockerfile b/Dockerfile index 972ca3ad8aca3..5d979af72a2bd 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,94 +1,166 @@ -FROM node:16-alpine3.15 as js-builder +# syntax=docker/dockerfile:1 + +ARG BASE_IMAGE=alpine:3.17 +ARG JS_IMAGE=node:16-alpine3.17 +ARG GO_IMAGE=golang:1.20.4-alpine3.17 + +ARG GO_SRC=go-builder +ARG JS_SRC=js-builder + +FROM ${JS_IMAGE} as js-builder ENV NODE_OPTIONS=--max_old_space_size=8000 -WORKDIR /grafana +WORKDIR /tmp/grafana COPY package.json yarn.lock .yarnrc.yml ./ COPY .yarn .yarn COPY packages packages COPY plugins-bundled plugins-bundled +RUN apk add --update python3 make g++\ + && rm -rf /var/cache/apk/* + RUN yarn install COPY tsconfig.json .eslintrc .editorconfig .browserslistrc .prettierrc.js babel.config.json .linguirc ./ COPY public public -COPY tools tools COPY scripts scripts COPY emails emails ENV NODE_ENV production RUN yarn build -FROM golang:1.19.4-alpine3.15 as go-builder +FROM ${GO_IMAGE} as go-builder -RUN apk add --no-cache gcc g++ make +# Install build dependencies +RUN if grep -i -q alpine /etc/issue; then \ + apk add --no-cache gcc g++ make binutils-gold; \ + fi -WORKDIR /grafana +WORKDIR /tmp/grafana -COPY go.mod go.sum embed.go Makefile build.go package.json ./ +COPY go.* ./ +COPY .bingo .bingo + +RUN go mod download && \ + go install github.com/bwplotka/bingo@latest && \ + bingo get + +COPY embed.go Makefile build.go package.json ./ +COPY cue.mod cue.mod +COPY local local COPY packages/grafana-schema packages/grafana-schema COPY public/app/plugins public/app/plugins COPY public/api-spec.json public/api-spec.json COPY pkg pkg COPY scripts scripts -COPY cue.mod cue.mod -COPY .bingo .bingo +COPY conf conf +COPY .github .github -RUN go mod verify RUN make build-go +FROM ${BASE_IMAGE} as tgz-builder + +WORKDIR /tmp/grafana + +ARG GRAFANA_TGZ="grafana-latest.linux-x64-musl.tar.gz" + +COPY ${GRAFANA_TGZ} /tmp/grafana.tar.gz + +# add -v to make tar print every file it extracts +RUN tar x -z -f /tmp/grafana.tar.gz --strip-components=1 + +# helpers for COPY --from +FROM ${GO_SRC} as go-src +FROM ${JS_SRC} as js-src + # Final stage -FROM alpine:3.15.6 +FROM ${BASE_IMAGE} -LABEL maintainer="Grafana team " +LABEL maintainer="Grafana Labs " ARG GF_UID="472" ARG GF_GID="0" ENV PATH="/usr/share/grafana/bin:$PATH" \ - GF_PATHS_CONFIG="/etc/grafana/grafana.ini" \ - GF_PATHS_DATA="/var/lib/grafana" \ - GF_PATHS_HOME="/usr/share/grafana" \ - GF_PATHS_LOGS="/var/log/grafana" \ - GF_PATHS_PLUGINS="/var/lib/grafana/plugins" \ - GF_PATHS_PROVISIONING="/etc/grafana/provisioning" + GF_PATHS_CONFIG="/etc/grafana/grafana.ini" \ + GF_PATHS_DATA="/var/lib/grafana" \ + GF_PATHS_HOME="/usr/share/grafana" \ + GF_PATHS_LOGS="/var/log/grafana" \ + GF_PATHS_PLUGINS="/var/lib/grafana/plugins" \ + GF_PATHS_PROVISIONING="/etc/grafana/provisioning" WORKDIR $GF_PATHS_HOME -RUN apk add --no-cache ca-certificates bash tzdata musl-utils -RUN apk info -vv | sort - -COPY conf ./conf +# Install dependencies +RUN if grep -i -q alpine /etc/issue; then \ + apk add --no-cache ca-certificates bash tzdata musl-utils && \ + apk info -vv | sort; \ + elif grep -i -q ubuntu /etc/issue; then \ + DEBIAN_FRONTEND=noninteractive && \ + apt-get update && \ + apt-get install -y ca-certificates curl tzdata && \ + apt-get autoremove -y && \ + rm -rf /var/lib/apt/lists/*; \ + else \ + echo 'ERROR: Unsupported base image' && /bin/false; \ + fi + +# glibc support for alpine x86_64 only +RUN if grep -i -q alpine /etc/issue && [ `arch` = "x86_64" ]; then \ + wget -q -O /etc/apk/keys/sgerrand.rsa.pub https://alpine-pkgs.sgerrand.com/sgerrand.rsa.pub && \ + wget https://github.com/sgerrand/alpine-pkg-glibc/releases/download/2.35-r0/glibc-2.35-r0.apk \ + -O /tmp/glibc-2.35-r0.apk && \ + wget https://github.com/sgerrand/alpine-pkg-glibc/releases/download/2.35-r0/glibc-bin-2.35-r0.apk \ + -O /tmp/glibc-bin-2.35-r0.apk && \ + apk add --force-overwrite --no-cache /tmp/glibc-2.35-r0.apk /tmp/glibc-bin-2.35-r0.apk && \ + rm -f /lib64/ld-linux-x86-64.so.2 && \ + ln -s /usr/glibc-compat/lib64/ld-linux-x86-64.so.2 /lib64/ld-linux-x86-64.so.2 && \ + rm -f /tmp/glibc-2.35-r0.apk && \ + rm -f /tmp/glibc-bin-2.35-r0.apk && \ + rm -f /lib/ld-linux-x86-64.so.2 && \ + rm -f /etc/ld.so.cache; \ + fi + +COPY --from=go-src /tmp/grafana/conf ./conf RUN if [ ! $(getent group "$GF_GID") ]; then \ - addgroup -S -g $GF_GID grafana; \ - fi - -RUN export GF_GID_NAME=$(getent group $GF_GID | cut -d':' -f1) && \ - mkdir -p "$GF_PATHS_HOME/.aws" && \ - adduser -S -u $GF_UID -G "$GF_GID_NAME" grafana && \ - mkdir -p "$GF_PATHS_PROVISIONING/datasources" \ - "$GF_PATHS_PROVISIONING/dashboards" \ - "$GF_PATHS_PROVISIONING/notifiers" \ - "$GF_PATHS_PROVISIONING/plugins" \ - "$GF_PATHS_PROVISIONING/access-control" \ - "$GF_PATHS_PROVISIONING/alerting" \ - "$GF_PATHS_LOGS" \ - "$GF_PATHS_PLUGINS" \ - "$GF_PATHS_DATA" && \ - cp "$GF_PATHS_HOME/conf/sample.ini" "$GF_PATHS_CONFIG" && \ - cp "$GF_PATHS_HOME/conf/ldap.toml" /etc/grafana/ldap.toml && \ - chown -R "grafana:$GF_GID_NAME" "$GF_PATHS_DATA" "$GF_PATHS_HOME/.aws" "$GF_PATHS_LOGS" "$GF_PATHS_PLUGINS" "$GF_PATHS_PROVISIONING" && \ - chmod -R 777 "$GF_PATHS_DATA" "$GF_PATHS_HOME/.aws" "$GF_PATHS_LOGS" "$GF_PATHS_PLUGINS" "$GF_PATHS_PROVISIONING" - -COPY --from=go-builder /grafana/bin/*/grafana-server /grafana/bin/*/grafana-cli /grafana/bin/*/grafana ./bin/ -COPY --from=js-builder /grafana/public ./public -COPY --from=js-builder /grafana/tools ./tools + if grep -i -q alpine /etc/issue; then \ + addgroup -S -g $GF_GID grafana; \ + else \ + addgroup --system --gid $GF_GID grafana; \ + fi; \ + fi && \ + GF_GID_NAME=$(getent group $GF_GID | cut -d':' -f1) && \ + mkdir -p "$GF_PATHS_HOME/.aws" && \ + if grep -i -q alpine /etc/issue; then \ + adduser -S -u $GF_UID -G "$GF_GID_NAME" grafana; \ + else \ + adduser --system --uid $GF_UID --ingroup "$GF_GID_NAME" grafana; \ + fi && \ + mkdir -p "$GF_PATHS_PROVISIONING/datasources" \ + "$GF_PATHS_PROVISIONING/dashboards" \ + "$GF_PATHS_PROVISIONING/notifiers" \ + "$GF_PATHS_PROVISIONING/plugins" \ + "$GF_PATHS_PROVISIONING/access-control" \ + "$GF_PATHS_PROVISIONING/alerting" \ + "$GF_PATHS_LOGS" \ + "$GF_PATHS_PLUGINS" \ + "$GF_PATHS_DATA" && \ + cp conf/sample.ini "$GF_PATHS_CONFIG" && \ + cp conf/ldap.toml /etc/grafana/ldap.toml && \ + chown -R "grafana:$GF_GID_NAME" "$GF_PATHS_DATA" "$GF_PATHS_HOME/.aws" "$GF_PATHS_LOGS" "$GF_PATHS_PLUGINS" "$GF_PATHS_PROVISIONING" && \ + chmod -R 777 "$GF_PATHS_DATA" "$GF_PATHS_HOME/.aws" "$GF_PATHS_LOGS" "$GF_PATHS_PLUGINS" "$GF_PATHS_PROVISIONING" + +COPY --from=go-src /tmp/grafana/bin/grafana* /tmp/grafana/bin/*/grafana* ./bin/ +COPY --from=js-src /tmp/grafana/public ./public EXPOSE 3000 -COPY ./packaging/docker/run.sh /run.sh +ARG RUN_SH=./packaging/docker/run.sh + +COPY ${RUN_SH} /run.sh -USER grafana +USER "$GF_UID" ENTRYPOINT [ "/run.sh" ] diff --git a/Makefile b/Makefile index 7d6ccf06d4166..dce99c311db7d 100644 --- a/Makefile +++ b/Makefile @@ -156,12 +156,17 @@ shellcheck: $(SH_FILES) ## Run checks for shell scripts. build-docker-full: ## Build Docker image for development. @echo "build docker container" - docker build --tag grafana/grafana:dev . + DOCKER_BUILDKIT=1 \ + docker build \ + --tag grafana/grafana:dev . build-docker-full-ubuntu: ## Build Docker image based on Ubuntu for development. @echo "build docker container" - docker build --tag grafana/grafana:dev-ubuntu -f ./Dockerfile.ubuntu . - + DOCKER_BUILDKIT=1 \ + docker build \ + --build-arg BASE_IMAGE=ubuntu:20.04 \ + --build-arg GO_IMAGE=golang:1.20.4 \ + --tag grafana/grafana:dev-ubuntu . ##@ Services diff --git a/docs/Makefile b/docs/Makefile index 4f553a5e8788b..9b692032fc17d 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -1,24 +1,28 @@ .PHONY: pull docs docs-quick docs-no-pull docs-test docs-local-static +PODMAN = $(shell if command -v podman >/dev/null 2>&1; then echo podman; else echo docker; fi) IMAGE = grafana/docs-base:latest -CONTENT_PATH = /hugo/content/docs/grafana/next +CONTENT_PATH = /hugo/content/docs/grafana/latest LOCAL_STATIC_PATH = ../../website/static PORT = 3002:3002 pull: - docker pull $(IMAGE) + $(PODMAN) pull $(IMAGE) docs: pull - docker run -v $(shell pwd)/sources:$(CONTENT_PATH):Z -p $(PORT) --rm -it $(IMAGE) /bin/bash -c "make server" - + $(PODMAN) run --init -v $(shell pwd)/sources:$(CONTENT_PATH):Z -p $(PORT) --rm -it $(IMAGE) make server + +docs-preview: pull + $(PODMAN) run --init -v $(shell pwd)/sources:$(CONTENT_PATH):Z -p $(PORT) --rm -it $(IMAGE) make server BUILD_DRAFTS=true + docs-no-pull: - docker run -v $(shell pwd)/sources:$(CONTENT_PATH):Z -p $(PORT) --rm -it $(IMAGE) /bin/bash -c "make server" + $(PODMAN) run --init -v $(shell pwd)/sources:$(CONTENT_PATH):Z -p $(PORT) --rm -it $(IMAGE) make server docs-test: pull - docker run -v $(shell pwd)/sources:$(CONTENT_PATH):Z --rm -it $(IMAGE) /bin/bash -c 'make prod' + $(PODMAN) run --init -v $(shell pwd)/sources:$(CONTENT_PATH):Z --rm -it $(IMAGE) make prod # expects that you have grafana/website checked out in same path as the grafana repo. docs-local-static: pull if [ ! -d "$(LOCAL_STATIC_PATH)" ]; then echo "local path (website project) $(LOCAL_STATIC_PATH) not found"]; exit 1; fi - docker run -v $(shell pwd)/sources:$(CONTENT_PATH):Z \ + $(PODMAN) run --init -v $(shell pwd)/sources:$(CONTENT_PATH):Z \ -v $(shell pwd)/$(LOCAL_STATIC_PATH):/hugo/static:Z -p $(PORT) --rm -it $(IMAGE) diff --git a/docs/sources/_index.md b/docs/sources/_index.md index 9fa484e80a8bd..9f7c7d0e5e44d 100644 --- a/docs/sources/_index.md +++ b/docs/sources/_index.md @@ -40,7 +40,7 @@ title: Grafana documentation
Grafana Cloud
- +
Nightly builds
diff --git a/docs/sources/administration/provisioning/index.md b/docs/sources/administration/provisioning/index.md index 57164c7bed3a6..6cc09c70882d5 100644 --- a/docs/sources/administration/provisioning/index.md +++ b/docs/sources/administration/provisioning/index.md @@ -1188,4 +1188,4 @@ The following sections detail the supported settings and secure settings for eac Grafana Enterprise supports provisioning for the following resources: -- [Role-based access control provisioning]({{< relref "../roles-and-permissions/access-control/rbac-provisioning/" >}}) +- [Role-based access control provisioning]({{< relref "../roles-and-permissions/access-control/rbac-grafana-provisioning" >}}) diff --git a/docs/sources/administration/roles-and-permissions/_index.md b/docs/sources/administration/roles-and-permissions/_index.md index 2a938536b3259..5edcdf74ba6f8 100644 --- a/docs/sources/administration/roles-and-permissions/_index.md +++ b/docs/sources/administration/roles-and-permissions/_index.md @@ -123,7 +123,7 @@ For more information about assigning administrator permissions to editors, refer If you have access to the Grafana server, you can modify the default viewer role so that viewers can: - Edit and preview dashboards, but cannot save their changes or create new dashboards. -- Access and use [Explore]({{< ref "/explore" >}}). +- Access and use [Explore]({{< relref "../../explore" >}}). Extending the viewer role is useful for public Grafana installations where you want anonymous users to be able to edit panels and queries, but not be able to save or create new dashboards. diff --git a/docs/sources/administration/roles-and-permissions/access-control/assign-rbac-roles/index.md b/docs/sources/administration/roles-and-permissions/access-control/assign-rbac-roles/index.md index 4c3fe77abd14d..29682a58a6350 100644 --- a/docs/sources/administration/roles-and-permissions/access-control/assign-rbac-roles/index.md +++ b/docs/sources/administration/roles-and-permissions/access-control/assign-rbac-roles/index.md @@ -65,7 +65,7 @@ Instead of using the Grafana role picker, you can use file-based provisioning to **Before you begin:** -- Refer to [Role provisioning]({{< relref "./rbac-provisioning/#rbac-provisioning" >}}) +- Refer to [Role provisioning]({{< relref "../rbac-grafana-provisioning" >}}) - Ensure that the team to which you are adding the fixed role exists. For more information about creating teams, refer to [Manage teams]({{< relref "../../../team-management/" >}}) **To assign a role to a team:** diff --git a/docs/sources/administration/roles-and-permissions/access-control/custom-role-actions-scopes/index.md b/docs/sources/administration/roles-and-permissions/access-control/custom-role-actions-scopes/index.md index 966517b870053..f53e80bb2da5e 100644 --- a/docs/sources/administration/roles-and-permissions/access-control/custom-role-actions-scopes/index.md +++ b/docs/sources/administration/roles-and-permissions/access-control/custom-role-actions-scopes/index.md @@ -159,7 +159,7 @@ The following list contains role-based access control scopes. | `orgs:*`
`orgs:id:*` | Restrict an action to a set of organizations. For example, `orgs:*` matches any organization and `orgs:id:1` matches the organization whose ID is `1`. | | `permissions:type:delegate` | The scope is only applicable for roles associated with the Access Control itself and indicates that you can delegate your permissions only, or a subset of it, by creating a new role or making an assignment. | | `permissions:type:escalate` | The scope is required to trigger the reset of basic roles permissions. It indicates that users might acquire additional permissions they did not previously have. | -| `provisioners:*` | Restrict an action to a set of provisioners. For example, `provisioners:*` matches any provisioner, and `provisioners:accesscontrol` matches the role-based access control [provisioner]({{< relref "./rbac-provisioning/" >}}). | +| `provisioners:*` | Restrict an action to a set of provisioners. For example, `provisioners:*` matches any provisioner, and `provisioners:accesscontrol` matches the role-based access control [provisioner]({{< relref "../rbac-grafana-provisioning" >}}). | | `reports:*`
`reports:id:*` | Restrict an action to a set of reports. For example, `reports:*` matches any report and `reports:id:1` matches the report whose ID is `1`. | | `roles:*`
`roles:uid:*` | Restrict an action to a set of roles. For example, `roles:*` matches any role and `roles:uid:randomuid` matches only the role whose UID is `randomuid`. | | `services:accesscontrol` | Restrict an action to target only the role-based access control service. You can use this in conjunction with the `status:accesscontrol` actions. | @@ -167,3 +167,4 @@ The following list contains role-based access control scopes. | `settings:*` | Restrict an action to a subset of settings. For example, `settings:*` matches all settings, `settings:auth.saml:*` matches all SAML settings, and `settings:auth.saml:enabled` matches the enable property on the SAML settings. | | `teams:*`
`teams:id:*` | Restrict an action to a set of teams from an organization. For example, `teams:*` matches any team and `teams:id:1` matches the team whose ID is `1`. | | `users:*`
`users:id:*` | Restrict an action to a set of users from an organization. For example, `users:*` matches any user and `users:id:1` matches the user whose ID is `1`. | +| `n/a` | `n/a` means not applicable. If an action has `n/a` specified for the scope, then the action does not require a scope. For example, the `teams:create` action does not require a scope and allows users to create teams. | diff --git a/docs/sources/administration/roles-and-permissions/access-control/manage-rbac-roles/index.md b/docs/sources/administration/roles-and-permissions/access-control/manage-rbac-roles/index.md index 4950d9b03283d..fbc2ed4cd92ba 100644 --- a/docs/sources/administration/roles-and-permissions/access-control/manage-rbac-roles/index.md +++ b/docs/sources/administration/roles-and-permissions/access-control/manage-rbac-roles/index.md @@ -88,9 +88,9 @@ Create a custom role when basic roles and fixed roles do not meet your permissio **Before you begin:** -- [Plan your RBAC rollout strategy]({{< relref "./plan-rbac-rollout-strategy/" >}}). +- [Plan your RBAC rollout strategy]({{< relref "../plan-rbac-rollout-strategy" >}}). - Determine which permissions you want to add to the custom role. To see a list of actions and scope, refer to [RBAC permissions, actions, and scopes]({{< relref "./custom-role-actions-scopes/" >}}). -- [Enable role provisioning]({{< relref "./rbac-provisioning/" >}}). +- [Enable role provisioning]({{< relref "../rbac-grafana-provisioning" >}}). - Ensure that you have permissions to create a custom role. - By default, the Grafana Admin role has permission to create custom roles. - A Grafana Admin can delegate the custom role privilege to another user by creating a custom role with the relevant permissions and adding the `permissions:type:delegate` scope. diff --git a/docs/sources/administration/roles-and-permissions/access-control/rbac-grafana-provisioning/index.md b/docs/sources/administration/roles-and-permissions/access-control/rbac-grafana-provisioning/index.md index 63a5576c59987..67295a3337100 100644 --- a/docs/sources/administration/roles-and-permissions/access-control/rbac-grafana-provisioning/index.md +++ b/docs/sources/administration/roles-and-permissions/access-control/rbac-grafana-provisioning/index.md @@ -29,7 +29,7 @@ Grafana performs provisioning during startup. After you make a change to the con 3. Create a new YAML in the following folder: **provisioning/access-control**. For example, `provisioning/access-control/custom-roles.yml` -4. Add RBAC provisioning details to the configuration file. See [manage RBAC roles]({{< relref "./manage-rbac-roles/" >}}) and [assign RBAC roles]({{< relref "./assign-rbac-roles/" >}}) for instructions, and see this [example role provisioning file]({{< relref "./rbac-provisioning/#example" >}}) for a complete example of a provisioning file. +4. Add RBAC provisioning details to the configuration file. See [manage RBAC roles]({{< relref "../manage-rbac-roles" >}}) and [assign RBAC roles]({{< relref "../assign-rbac-roles" >}}) for instructions, and see this [example role provisioning file]({{< relref "#example" >}}) for a complete example of a provisioning file. 5. Reload the provisioning configuration file. diff --git a/docs/sources/alerting/fundamentals/annotation-label/_index.md b/docs/sources/alerting/fundamentals/annotation-label/_index.md index 777ab7d678ca5..6289f03f6e747 100644 --- a/docs/sources/alerting/fundamentals/annotation-label/_index.md +++ b/docs/sources/alerting/fundamentals/annotation-label/_index.md @@ -15,7 +15,7 @@ weight: 401 # Annotations and labels for alerting rules -Annotations and labels are key value pairs associated with alerts originating from the alerting rule, datasource response, and as a result of alerting rule evaluation. They can be used in alert notifications directly or in [templates]({{< relref "../../contact-points/message-templating/" >}}) and [template functions]({{< relref "../../contact-points/fundamentals/annotation-label/template-functions/" >}}) to create notification content dynamically. +Annotations and labels are key value pairs associated with alerts originating from the alerting rule, datasource response, and as a result of alerting rule evaluation. They can be used in alert notifications directly or in [templates]({{< relref "../../contact-points/message-templating" >}}) and [template functions]({{< relref "./template-functions" >}}) to create notification content dynamically. ## Annotations diff --git a/docs/sources/alerting/images-in-notifications.md b/docs/sources/alerting/images-in-notifications.md index 156d70e57cb3c..15143776b3b33 100644 --- a/docs/sources/alerting/images-in-notifications.md +++ b/docs/sources/alerting/images-in-notifications.md @@ -31,13 +31,13 @@ Please refer to the table at the end of this page for a list of contact points a To use images in notifications, Grafana must be set up to use [image rendering](https://grafana.com/docs/grafana/next/setup-grafana/image-rendering/). You can either install the image rendering plugin or run it as a remote rendering service. -When a screenshot is taken it is saved to the [data]({{< relref "../../setup-grafana/configure-grafana/#paths" >}}) path. This is where screenshots are stored before being sent in a notification or uploaded to a cloud storage service. Grafana must have write-access to this path. If Grafana cannot write to this path then screenshots cannot be saved to disk and an error will be logged for each failed screenshot attempt. +When a screenshot is taken it is saved to the [data]({{< relref "../setup-grafana/configure-grafana#paths" >}}) path. This is where screenshots are stored before being sent in a notification or uploaded to a cloud storage service. Grafana must have write-access to this path. If Grafana cannot write to this path then screenshots cannot be saved to disk and an error will be logged for each failed screenshot attempt. -If using a [cloud storage service](https://grafana.com/docs/grafana/latest/setup-grafana/configure-grafana/#external_image_storage) such as Amazon S3, Azure Blob Storage or Google Cloud Storage, uploaded images need to be accessible outside of a firewall, gateway service or VPN for screenshots to be shown in notifications. Grafana will not delete screenshots from cloud storage. We recommend configuring a retention policy on the bucket to delete screenshots older than 1 month. +If using a [cloud storage service]({{< relref "../setup-grafana/configure-grafana#external_image_storage" >}}) such as Amazon S3, Azure Blob Storage or Google Cloud Storage, uploaded images need to be accessible outside of a firewall, gateway service or VPN for screenshots to be shown in notifications. Grafana will not delete screenshots from cloud storage. We recommend configuring a retention policy on the bucket to delete screenshots older than 1 month. If using Grafana as its own cloud storage service then screenshots will be saved to `static_root_path/img/attachments`. `static_root_path` is a configuration option for Grafana and can be found in `defaults.ini`. However, like when using a cloud storage service, images need to be accessible outside of a firewall, gateway service or VPN for screenshots to be shown in notifications. -When using Grafana as its own cloud storage service screenshots are copied from [data]({{< relref "../../setup-grafana/configure-grafana/#paths" >}}) to `static_root_path/img/attachments`. Screenshots older than `temp_data_lifetime` are deleted from [data]({{< relref "../../setup-grafana/configure-grafana/#paths" >}}) but not from `static_root_path/images/attachments`. To delete screenshots from `static_root_path` after a certain amount of time we recommend setting up a CRON job. +When using Grafana as its own cloud storage service screenshots are copied from [data]({{< relref "../setup-grafana/configure-grafana#paths" >}}) to `static_root_path/img/attachments`. Screenshots older than `temp_data_lifetime` are deleted from [data]({{< relref "../setup-grafana/configure-grafana#paths" >}}) but not from `static_root_path/images/attachments`. To delete screenshots from `static_root_path` after a certain amount of time we recommend setting up a CRON job. ## Configuration diff --git a/docs/sources/dashboards/build-dashboards/add-organize-panels/index.md b/docs/sources/dashboards/build-dashboards/add-organize-panels/index.md index 82dce4b46b976..f16b6aaffd4ef 100644 --- a/docs/sources/dashboards/build-dashboards/add-organize-panels/index.md +++ b/docs/sources/dashboards/build-dashboards/add-organize-panels/index.md @@ -40,8 +40,8 @@ This section describes the areas of the Grafana panel editor. 1. Data section: The data section contains tabs where you enter queries, transform your data, and create alert rules (if applicable). -- **Query tab:** Select your data source and enter queries here. For more information, refer to [Add a query]({{< relref "../../../panels/query-a-data-source/add-a-query/" >}}). -- **Transform tab:** Apply data transformations. For more information, refer to [Transform data]({{< relref "../../../panels/transform-data/" >}}). +- **Query tab:** Select your data source and enter queries here. For more information, refer to [Add a query]({{< relref "../../../panels-visualizations/query-transform-data#add-a-query" >}}). +- **Transform tab:** Apply data transformations. For more information, refer to [Transform data]({{< relref "../../../panels-visualizations/query-transform-data/transform-data" >}}). - **Alert tab:** Write alert rules. For more information, refer to [Overview of Grafana 8 alerting]({{< relref "../../../alerting/" >}}). 1. Panel display options: The display options section contains tabs where you configure almost every aspect of your data visualization. @@ -96,17 +96,17 @@ For more information about data sources, refer to [Data sources]({{< relref "../ ![](/static/img/docs/panel-editor/select-visualization-8-0.png) -For more information about individual visualizations, refer to [Visualizations options]({{< relref "../../../visualizations/" >}}). +For more information about individual visualizations, refer to [Visualizations options]({{< relref "../../../panels-visualizations/visualizations" >}}). 1. Refer to the following documentation for ways you can adjust panel settings. While not required, most visualizations need some adjustment before they properly display the information that you need. - - [Configure value mappings]({{< relref "../../../panels/configure-value-mappings" >}}) - - [Visualization-specific options]({{< relref "../../../visualizations/" >}}) - - [Override field values]({{< relref "../../../panels/configure-overrides/" >}}) - - [Configure thresholds]({{< relref "../../../panels/configure-thresholds/" >}}) - - [Configure standard options]({{< relref "../../../panels/configure-standard-options/" >}}) + - [Configure value mappings]({{< relref "../../../panels-visualizations/configure-value-mappings" >}}) + - [Visualization-specific options]({{< relref "../../../panels-visualizations/visualizations" >}}) + - [Override field values]({{< relref "../../../panels-visualizations/configure-overrides" >}}) + - [Configure thresholds]({{< relref "../../../panels-visualizations/configure-thresholds" >}}) + - [Configure standard options]({{< relref "../../../panels-visualizations/configure-standard-options" >}}) 1. Add a note to describe the visualization (or describe your changes) and then click **Save** in the upper-right corner of the page. diff --git a/docs/sources/dashboards/variables/add-template-variables/index.md b/docs/sources/dashboards/variables/add-template-variables/index.md index e56147fae6047..de49e283f89a5 100644 --- a/docs/sources/dashboards/variables/add-template-variables/index.md +++ b/docs/sources/dashboards/variables/add-template-variables/index.md @@ -44,17 +44,17 @@ weight: 100 The following table lists the types of variables shipped with Grafana. -| Variable type | Description | -| :---------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Query | Query-generated list of values such as metric names, server names, sensor IDs, data centers, and so on. [Add a query variable]({{< relref "#add-a-query-variable" >}}). | -| Custom | Define the variable options manually using a comma-separated list. [Add a custom variable]({{< relref "#add-a-custom-variable" >}}). | -| Text box | Display a free text input field with an optional default value. [Add a text box variable]({{< relref "#add-a-text-box-variable" >}}). | -| Constant | Define a hidden constant. [Add a constant variable]({{< relref "#add-a-constant-variable" >}}). | -| Data source | Quickly change the data source for an entire dashboard. [Add a data source variable]({{< relref "#add-a-data-source-variable" >}}). | -| Interval | Interval variables represent time spans. [Add an interval variable]({{< relref "#add-an-interval-variable" >}}). | -| Ad hoc filters | Key/value filters that are automatically added to all metric queries for a data source (InfluxDB, Prometheus, and Elasticsearch only). [Add ad hoc filters]({{< relref "#add-ad-hoc-filters" >}}). | -| Global variables | Built-in variables that can be used in expressions in the query editor. Refer to [Global variables]({{< relref "#global-variables" >}}). | -| Chained variables | Variable queries can contain other variables. Refer to [Chained variables]({{< relref "#chained-variables" >}}). | +| Variable type | Description | +| :---------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Query | Query-generated list of values such as metric names, server names, sensor IDs, data centers, and so on. [Add a query variable]({{< relref "#add-a-query-variable" >}}). | +| Custom | Define the variable options manually using a comma-separated list. [Add a custom variable]({{< relref "#add-a-custom-variable" >}}). | +| Text box | Display a free text input field with an optional default value. [Add a text box variable]({{< relref "#add-a-text-box-variable" >}}). | +| Constant | Define a hidden constant. [Add a constant variable]({{< relref "#add-a-constant-variable" >}}). | +| Data source | Quickly change the data source for an entire dashboard. [Add a data source variable]({{< relref "#add-a-data-source-variable" >}}). | +| Interval | Interval variables represent time spans. [Add an interval variable]({{< relref "#add-an-interval-variable" >}}). | +| Ad hoc filters | Key/value filters that are automatically added to all metric queries for a data source (Prometheus, Loki, InfluxDB, and Elasticsearch only). [Add ad hoc filters]({{< relref "#add-ad-hoc-filters" >}}). | +| Global variables | Built-in variables that can be used in expressions in the query editor. Refer to [Global variables]({{< relref "#global-variables" >}}). | +| Chained variables | Variable queries can contain other variables. Refer to [Chained variables]({{< relref "#chained-variables" >}}). | ## Enter General options @@ -194,7 +194,7 @@ Ad hoc filters are one of the most complex and flexible variable options availab Interpolating a variable with multiple values selected is tricky as it is not straight forward how to format the multiple values into a string that is valid in the given context where the variable is used. Grafana tries to solve this by allowing each data source plugin to inform the templating interpolation engine what format to use for multiple values. -> **Note:** The **Custom all value** option on the variable must be blank for Grafana to format all values into a single string. If leave it blank, then the Grafana concatenates (adds together) all the values in the query. Something like `value1,value2,value3`. If a custom `all` value is used, then instead the value will be something like `*` or `all`. +> **Note:** The **Custom all value** option on the variable must be blank for Grafana to format all values into a single string. If it is left blank, then Grafana concatenates (adds together) all the values in the query. Something like `value1,value2,value3`. If a custom `all` value is used, then instead the value will be something like `*` or `all`. #### Multi-value variables with a Graphite data source @@ -281,6 +281,8 @@ This variable is the `$__interval` variable in milliseconds, not a time interval This variable is only available in the Singlestat panel and can be used in the prefix or suffix fields on the Options tab. The variable will be replaced with the series name or alias. +> **Note:** The Singlestat panel is no longer available from Grafana 8.0. + ### $\_\_org This variable is the ID of the current organization. @@ -398,7 +400,7 @@ apps.fakesite.web_server_01.cpu.* #### InfluxDB example -In this example, you have several data centers. Each data center has a different subset of hosts. It is based on the [InfluxDB Templated](https://play.grafana.org/d/000000002/influxdb-templated?orgId=1). +In this example, you have several data centers. Each data center has a different subset of hosts. It is based on the [InfluxDB Templated](https://play.grafana.org/d/000000002/influxdb-templated?orgId=1) dashboard. In this example, when the user changes the value of the `datacenter` variable, it changes the dropdown options returned by the `host` variable. The `host` variable uses the **Multi-value** option and **Include all option**, allowing users to select some or all options presented at any time. The `datacenter` does not use either option, so you can only select one data center at a time. @@ -407,7 +409,7 @@ In this example, when the user changes the value of the `datacenter` variable, i The query for this variable basically says, "Give me all the data centers that exist." ``` -SHOW TAG VALUES WITH KEY = "datacenter" +SHOW TAG VALUES WITH KEY = "datacenter" ``` The values returned are `America`, `Africa`, `Asia`, and `Europe`. diff --git a/docs/sources/datasources/elasticsearch.md b/docs/sources/datasources/elasticsearch.md index c64e41d7cbbd3..00c0d2564e74f 100644 --- a/docs/sources/datasources/elasticsearch.md +++ b/docs/sources/datasources/elasticsearch.md @@ -175,7 +175,7 @@ In the above example, we have a lucene query that filters documents based on the a variable in the _Terms_ group by field input box. This allows you to use a variable to quickly change how the data is grouped. Example dashboard: -[Elasticsearch Templated Dashboard](https://play.grafana.org/d/CknOEXDMk/elasticsearch-templated?orgId=1d) +[Elasticsearch Templated Dashboard](https://play.grafana.org/d/z8OZC66nk/elasticsearch-8-2-0-sample-flight-data?orgId=1) ## Annotations diff --git a/docs/sources/developers/http_api/alerting.md b/docs/sources/developers/http_api/alerting.md index 47639d9102891..8c54cc7248841 100644 --- a/docs/sources/developers/http_api/alerting.md +++ b/docs/sources/developers/http_api/alerting.md @@ -12,9 +12,9 @@ keywords: title: 'Alerting HTTP API ' --- -# Alerting API +# Legacy Alerting API -> **Note:** Starting with v9.0, the Alerting HTTP API is deprecated. It will be removed in a future release. +> **Note:** Starting with v9.0, the Legacy Alerting HTTP API is deprecated. It will be removed in a future release. This topic is relevant for the [legacy dashboard alerts](https://grafana.com/docs/grafana/v8.5/alerting/old-alerting/) only. diff --git a/docs/sources/developers/http_api/alerting_notification_channels.md b/docs/sources/developers/http_api/alerting_notification_channels.md index f47266484894b..af7231cff94e3 100644 --- a/docs/sources/developers/http_api/alerting_notification_channels.md +++ b/docs/sources/developers/http_api/alerting_notification_channels.md @@ -13,7 +13,9 @@ keywords: title: 'Alerting Notification Channels HTTP API ' --- -# Alerting Notification Channels API +# Legacy Alerting Notification Channels API + +> **Note:** Starting with v9.0, the Legacy Alerting Notification Channels API is deprecated. It will be removed in a future release. This page documents the Alerting Notification Channels API. diff --git a/docs/sources/developers/plugins/_index.md b/docs/sources/developers/plugins/_index.md index 5f64193cd42ab..905ce62a14ef9 100644 --- a/docs/sources/developers/plugins/_index.md +++ b/docs/sources/developers/plugins/_index.md @@ -24,8 +24,8 @@ npx @grafana/toolkit plugin:create my-grafana-plugin If you want a more guided introduction to plugin development, check out our tutorials: -- [Build a panel plugin]({{< ref "build-a-panel-plugin.md" >}}) -- [Build a data source plugin]({{< ref "build-a-data-source-plugin.md" >}}) +- [Build a panel plugin]({{< relref "/tutorials/build-a-panel-plugin" >}}) +- [Build a data source plugin]({{< relref "/tutorials/build-a-data-source-plugin" >}}) ## Go further @@ -35,13 +35,13 @@ Learn more about specific areas of plugin development. If you're looking to build your first plugin, check out these introductory tutorials: -- [Build a panel plugin]({{< ref "build-a-panel-plugin.md" >}}) -- [Build a data source plugin]({{< ref "build-a-data-source-plugin.md" >}}) -- [Build a data source backend plugin]({{< ref "build-a-data-source-backend-plugin.md" >}}) +- [Build a panel plugin]({{< relref "/tutorials/build-a-panel-plugin" >}}) +- [Build a data source plugin]({{< relref "/tutorials/build-a-data-source-plugin" >}}) +- [Build a data source backend plugin]({{< relref "/tutorials/build-a-data-source-backend-plugin" >}}) Ready to learn more? Check out our other tutorials: -- [Build a panel plugin with D3.js]({{< ref "build-a-panel-plugin-with-d3.md" >}}) +- [Build a panel plugin with D3.js]({{< relref "/tutorials/build-a-panel-plugin-with-d3" >}}) ### Guides diff --git a/docs/sources/developers/plugins/add-support-for-annotations.md b/docs/sources/developers/plugins/add-support-for-annotations.md index 154bd3a3d5c23..391b426a64755 100644 --- a/docs/sources/developers/plugins/add-support-for-annotations.md +++ b/docs/sources/developers/plugins/add-support-for-annotations.md @@ -6,7 +6,7 @@ title: Add support for annotations This guide explains how to add support for [annotations]({{< relref "../../dashboards/build-dashboards/annotate-visualizations" >}}) to an existing data source plugin. -This guide assumes that you're already familiar with how to [Build a data source plugin]({{< ref "build-a-data-source-plugin.md" >}}). +This guide assumes that you're already familiar with how to [Build a data source plugin]({{< relref "/tutorials/build-a-data-source-plugin" >}}). > **Note:** Annotation support for React plugins was released in Grafana 7.2. To support earlier versions, refer to [Add support for annotation for Grafana 7.1](https://grafana.com/docs/grafana/v7.1/developers/plugins/add-support-for-annotations/). diff --git a/docs/sources/developers/plugins/add-support-for-explore-queries.md b/docs/sources/developers/plugins/add-support-for-explore-queries.md index d3d59ba54cd17..57d40d844756a 100644 --- a/docs/sources/developers/plugins/add-support-for-explore-queries.md +++ b/docs/sources/developers/plugins/add-support-for-explore-queries.md @@ -6,7 +6,7 @@ title: Add support for Explore queries This guide explains how to improve support for [Explore]({{< relref "../../explore/" >}}) in an existing data source plugin. -This guide assumes that you're already familiar with how to [Build a data source plugin]({{< ref "build-a-data-source-plugin.md" >}}). +This guide assumes that you're already familiar with how to [Build a data source plugin]({{< relref "/tutorials/build-a-data-source-plugin" >}}). With Explore, users can make ad-hoc queries without the use of a dashboard. This is useful when users want to troubleshoot or to learn more about the data. diff --git a/docs/sources/developers/plugins/build-a-logs-data-source-plugin.md b/docs/sources/developers/plugins/build-a-logs-data-source-plugin.md index 5c779425ebf31..3c4beb6778d86 100644 --- a/docs/sources/developers/plugins/build-a-logs-data-source-plugin.md +++ b/docs/sources/developers/plugins/build-a-logs-data-source-plugin.md @@ -6,7 +6,7 @@ title: Build a logs data source plugin This guide explains how to build a logs data source plugin. -Data sources in Grafana supports both metrics and log data. The steps to build a logs data source plugin are largely the same as for a metrics data source. This guide assumes that you're already familiar with how to [Build a data source plugin]({{< ref "build-a-data-source-plugin.md" >}}) for metrics. +Data sources in Grafana supports both metrics and log data. The steps to build a logs data source plugin are largely the same as for a metrics data source. This guide assumes that you're already familiar with how to [Build a data source plugin]({{< relref "/tutorials/build-a-data-source-plugin" >}}) for metrics. ## Add logs support to your data source diff --git a/docs/sources/developers/plugins/build-a-streaming-data-source-plugin.md b/docs/sources/developers/plugins/build-a-streaming-data-source-plugin.md index c49f936a5d54b..f56129b341d1c 100644 --- a/docs/sources/developers/plugins/build-a-streaming-data-source-plugin.md +++ b/docs/sources/developers/plugins/build-a-streaming-data-source-plugin.md @@ -6,7 +6,7 @@ title: Build a streaming data source plugin This guide explains how to build a streaming data source plugin. -This guide assumes that you're already familiar with how to [Build a data source plugin]({{< ref "build-a-data-source-plugin.md" >}}). +This guide assumes that you're already familiar with how to [Build a data source plugin]({{< relref "/tutorials/build-a-data-source-plugin" >}}). When monitoring critical applications, you want your dashboard to refresh as soon as your data does. In Grafana, you can set your dashboards to automatically refresh at a certain interval, no matter what data source you use. Unfortunately, this means that your queries are requesting all the data to be sent again, regardless of whether the data has actually changed. diff --git a/docs/sources/enterprise/_index.md b/docs/sources/enterprise/_index.md index 3a2fcfb018b72..65bebc7b5d612 100644 --- a/docs/sources/enterprise/_index.md +++ b/docs/sources/enterprise/_index.md @@ -24,7 +24,7 @@ To learn more about Grafana Enterprise, refer to [our product page](https://graf ## Enterprise features in Grafana Cloud -Many Grafana Enterprise features are also available in [Grafana Cloud]({{< ref "/docs/grafana-cloud" >}}) Pro and Advanced accounts. For details, refer to [the Grafana Cloud features table](https://grafana.com/pricing/#featuresTable) and [Enterprise features available to Grafana Cloud Pro and Advanced accounts]({{< ref "/docs/grafana-cloud/reference/enterprise-features" >}}). +Many Grafana Enterprise features are also available in [Grafana Cloud]({{< relref "/docs/grafana-cloud" >}}) Pro and Advanced accounts. For details, refer to [the Grafana Cloud features table](https://grafana.com/pricing/#featuresTable). ## Authentication @@ -62,16 +62,16 @@ Grafana Enterprise adds the following features: - [Role-based access control]({{< relref "../administration/roles-and-permissions/access-control/" >}}) to control access with role-based permissions. - [Data source permissions]({{< relref "../administration/data-source-management/" >}}) to restrict query access to specific teams and users. -- [Data source query caching]({{< relref "query-caching" >}}) to temporarily store query results in Grafana to reduce data source load and rate limiting. +- [Data source query caching]({{< relref "../administration/data-source-management#query-caching" >}}) to temporarily store query results in Grafana to reduce data source load and rate limiting. - [Reporting]({{< relref "../dashboards/create-reports/" >}}) to generate a PDF report from any dashboard and set up a schedule to have it emailed to whoever you choose. - [Export dashboard as PDF]({{< relref "../dashboards/share-dashboards-panels/#export-dashboard-as-pdf" >}}) - [Custom branding]({{< relref "../setup-grafana/configure-grafana/configure-custom-branding/" >}}) to customize Grafana from the brand and logo to the footer links. - [Usage insights]({{< relref "../dashboards/assess-dashboard-usage/" >}}) to understand how your Grafana instance is used. -- [Recorded queries]({{< relref "recorded-queries" >}}) to see trends over time for your data sources. +- [Recorded queries]({{< relref "../administration/recorded-queries" >}}) to see trends over time for your data sources. - [Vault integration]({{< relref "../setup-grafana/configure-security/configure-database-encryption/integrate-with-hashicorp-vault/" >}}) to manage your configuration or provisioning secrets with Vault. - [Auditing]({{< relref "../setup-grafana/configure-security/audit-grafana/" >}}) tracks important changes to your Grafana instance to help you manage and mitigate suspicious activity and meet compliance requirements. - [Request security]({{< relref "../setup-grafana/configure-security/configure-request-security/" >}}) makes it possible to restrict outgoing requests from the Grafana server. -- [Settings updates at runtime]({{< relref "settings-updates" >}}) allows you to update Grafana settings at runtime without requiring a restart. +- [Settings updates at runtime]({{< relref "../setup-grafana/configure-grafana/settings-updates-at-runtime" >}}) allows you to update Grafana settings at runtime without requiring a restart. ## Enterprise data sources diff --git a/docs/sources/explore/logs-integration.md b/docs/sources/explore/logs-integration.md index 5e5b90d8656de..190221320f65c 100644 --- a/docs/sources/explore/logs-integration.md +++ b/docs/sources/explore/logs-integration.md @@ -21,7 +21,7 @@ During an infrastructure monitoring and incident response, you can dig deeper in 1. Drill down and examine metrics. 1. Drill down again and search logs related to the metric and time interval (and in the future, distributed traces). -### Logs visualization +## Logs visualization Results of log queries are shown as histograms in the graph and individual logs are explained in the following sections. @@ -31,7 +31,7 @@ If the data source supports a full range log volume histogram, the graph with lo If the data source does not support loading full range log volume histogram, the logs model computes a time series based on the log row counts bucketed by an automatically calculated time interval, and the first log row's timestamp then anchors the start of the histogram from the result. The end of the time series is anchored to the time picker's **To** range. -#### Log level +### Log level For logs where a level label is specified, we use the value of the label to determine the log level and update color accordingly. If the log doesn't have a level label specified, we try to find out if its content matches any of the supported expressions (see below for more information). The log level is always determined by the first match. In case Grafana is not able to determine a log level, it will be visualized with an unknown log level. @@ -59,33 +59,33 @@ For logs where a level label is specified, we use the value of the label to dete | trace | trace | light blue | | \* | unknown | grey | -### Logs navigation +## Logs navigation Logs navigation next to the log lines can be used to request more logs. You can do this by clicking on Older logs button on the bottom of navigation. This is especially useful when you hit the line limit and you want to see more logs. Each request that is run from the navigation is then displayed in the navigation as separate page. Every page is showing from and to timestamp of the incoming log lines. You can see previous results by clicking on the page. Explore is caching last five requests run from the logs navigation, so you are not re-running the same queries when clicking on the pages. ![Navigate logs in Explore](/static/img/docs/explore/navigate-logs-8-0.png) -### Visualization options +## Visualization options You can customize how logs are displayed and select which columns are shown. -#### Time +### Time Shows or hides the time column. This is the timestamp associated with the log line as reported from the data source. -#### Unique labels +### Unique labels Shows or hides the unique labels column that includes only non-common labels. All common labels are displayed above. -#### Wrap lines +### Wrap lines Set this to True if you want the display to use line wrapping. If set to False, it will result in horizontal scrolling. -#### Prettify JSON +### Prettify JSON Set this to `true` to pretty print all JSON logs. This setting does not affect logs in any format other than JSON. -#### Deduping +### Deduping Log data can be very repetitive and Explore can help by hiding duplicate log lines. There are a few different deduplication algorithms that you can use: @@ -93,15 +93,15 @@ Log data can be very repetitive and Explore can help by hiding duplicate log lin - **Numbers -** Matches on the line after stripping out numbers such as durations, IP addresses, and so on. - **Signature -** The most aggressive deduping, this strips all letters and numbers and matches on the remaining whitespace and punctuation. -#### Flip results order +### Flip results order You can change the order of received logs from the default descending order (newest first) to ascending order (oldest first). -### Labels and detected fields +## Labels and detected fields Each log row has an extendable area with its labels and detected fields, for more robust interaction. For all labels we have added the ability to filter for (positive filter) and filter out (negative filter) selected labels. Each field or label also has a stats icon to display ad-hoc statistics in relation to all displayed logs. -### Escaping newlines +## Escaping newlines Explore automatically detects some incorrectly escaped sequences in log lines, such as newlines (`\n`, `\r`) or tabs (`\t`). When it detects such sequences, Explore provides an "Escape newlines" option. @@ -112,12 +112,12 @@ To automatically fix incorrectly escaped sequences that Explore has detected: Explore replaces these sequences. When it does so, the option will change from "Escape newlines" to "Remove escaping". Evaluate the changes as the parsing may not be accurate based on the input received. You can revert the replacements by clicking "Remove escaping". -#### Derived fields links +### Derived fields links By using Derived fields, you can turn any part of a log message into an internal or external link. The created link is visible as a button next to the Detected field in the Log details view. {{< figure src="/static/img/docs/explore/detected-fields-link-7-4.png" max-width="800px" caption="Detected fields link in Explore" >}} -#### Toggle detected fields +### Toggle detected fields > **Note:** Available in Grafana 7.2 and later versions. @@ -125,13 +125,13 @@ If your logs are structured in `json` or `logfmt`, then you can show or hide det {{< figure src="/static/img/docs/explore/parsed-fields-7-2.gif" max-width="800px" caption="Toggling detected fields in Explore" >}} -### Loki-specific features +## Loki-specific features As mentioned, one of the log integrations is for the new open source log aggregation system from Grafana Labs - [Loki](https://github.com/grafana/loki). Loki is designed to be very cost effective, as it does not index the contents of the logs, but rather a set of labels for each log stream. The logs from Loki are queried in a similar way to querying with label selectors in Prometheus. It uses labels to group log streams which can be made to match up with your Prometheus labels. For more information about Grafana Loki, refer to [Grafana Loki](https://github.com/grafana/loki) or the Grafana Labs hosted variant: [Grafana Cloud Logs](https://grafana.com/loki). For more information, refer to [Loki's data source documentation]({{< relref "../datasources/loki/" >}}) on how to query for log data. -#### Switch from metrics to logs +### Switch from metrics to logs If you switch from a Prometheus query to a logs query (you can do a split first to have your metrics and logs side by side) then it will keep the labels from your query that exist in the logs and use those to query the log streams. For example, the following Prometheus query: @@ -143,7 +143,7 @@ after switching to the Logs data source, the query changes to: This will return a chunk of logs in the selected time range that can be grepped/text searched. -#### Live tailing +### Live tailing Use the Live tailing feature to see real-time logs on supported data sources. diff --git a/docs/sources/fundamentals/timeseries-dimensions/index.md b/docs/sources/fundamentals/timeseries-dimensions/index.md index 88c1281688bfc..c02144c53f668 100644 --- a/docs/sources/fundamentals/timeseries-dimensions/index.md +++ b/docs/sources/fundamentals/timeseries-dimensions/index.md @@ -86,7 +86,7 @@ In this case the labels that represent the dimensions will have two keys based o > **Note:** More than one dimension is currently only supported in the Logs queries within the Azure Monitor service as of version 7.1. -> **Note:** Multiple dimensions are not supported in a way that maps to multiple alerts in Grafana, but rather they are treated as multiple conditions to a single alert. For more information, see See the documentation on [creating alerts with multiple series]({{< relref "../alerting/alerting-rules/create-grafana-managed-rule/#single-and-multi-dimensional-rule" >}}). +> **Note:** Multiple dimensions are not supported in a way that maps to multiple alerts in Grafana, but rather they are treated as multiple conditions to a single alert. For more information, see See the documentation on [creating alerts with multiple series]({{< relref "../../alerting/alerting-rules/create-grafana-managed-rule#single-and-multi-dimensional-rule" >}}). ### Multiple values diff --git a/docs/sources/getting-started/get-started-grafana-influxdb.md b/docs/sources/getting-started/get-started-grafana-influxdb.md index f5627e02d665b..3fe423555949b 100644 --- a/docs/sources/getting-started/get-started-grafana-influxdb.md +++ b/docs/sources/getting-started/get-started-grafana-influxdb.md @@ -10,8 +10,6 @@ weight: 400 {{< docs/shared "influxdb/intro.md" >}} -{{< docs/shared "getting-started/first-step.md" >}} - #### Get InfluxDB You can [download InfluxDB](https://portal.influxdata.com/downloads/) and install it locally or you can sign up for [InfluxDB Cloud](https://www.influxdata.com/products/influxdb-cloud/). Windows installers are not available for some versions of InfluxDB. diff --git a/docs/sources/getting-started/get-started-grafana-ms-sql-server.md b/docs/sources/getting-started/get-started-grafana-ms-sql-server.md index a0f70abc44782..f28b133fac565 100644 --- a/docs/sources/getting-started/get-started-grafana-ms-sql-server.md +++ b/docs/sources/getting-started/get-started-grafana-ms-sql-server.md @@ -10,9 +10,7 @@ weight: 500 # Get started with Grafana and MS SQL Server -Microsoft SQL Server is a popular relational database management system that is widely used in development and production environments. This topic walks you through the steps to create a series of dashboards in Grafana to display metrics from a MS SQL Server database. You can also configure the MS SQL Server data source on a [Grafana Cloud](https://grafana.com/docs/grafana-cloud/) instance without having to host Grafana yourself. - -{{< docs/shared "getting-started/first-step.md" >}} +Microsoft SQL Server is a popular relational database management system that is widely used in development and production environments. This topic walks you through the steps to create a series of dashboards in Grafana to display metrics from a MS SQL Server database. > **Note:** You must install Grafana 5.1+ in order to use the integrated MS SQL data source. @@ -55,7 +53,7 @@ Optionally, play around this dashboard and customize it to: #### Start building dashboards -Now that you have gained some idea of using the pre-packaged MS SQL data source and some test data, the next step is to setup your own instance of MS SQL Server database and data your development or sandbox area. In the previous steps, if you followed along the path of deploying your own instance of MS SQL Server, you are already on your way. +Now that you have gained some idea of using the pre-packaged MS SQL data source and some test data, the next step is to setup your own instance of MS SQL Server database and data your development or sandbox area. To fetch data from your own instance of MS SQL Server, add the data source using instructions in Step 4 of this topic. In Grafana [Explore]({{< relref "../explore/" >}}) build queries to experiment with the metrics you want to monitor. diff --git a/docs/sources/getting-started/get-started-grafana-prometheus.md b/docs/sources/getting-started/get-started-grafana-prometheus.md index 88a3960c03e92..6917fb02cbdbd 100644 --- a/docs/sources/getting-started/get-started-grafana-prometheus.md +++ b/docs/sources/getting-started/get-started-grafana-prometheus.md @@ -12,8 +12,6 @@ weight: 300 Prometheus is an open source monitoring system for which Grafana provides out-of-the-box support. This topic walks you through the steps to create a series of dashboards in Grafana to display system metrics for a server monitored by Prometheus. -{{< docs/shared "getting-started/first-step.md" >}} - #### Download Prometheus and node_exporter Prometheus, like Grafana, can be installed on many different operating systems. Refer to the [Prometheus download page](https://prometheus.io/download/), which lists all stable versions of Prometheus components. Download the following components: diff --git a/docs/sources/panels-visualizations/configure-legend/index.md b/docs/sources/panels-visualizations/configure-legend/index.md new file mode 100644 index 0000000000000..73827297386c6 --- /dev/null +++ b/docs/sources/panels-visualizations/configure-legend/index.md @@ -0,0 +1,76 @@ +--- +aliases: + - ../panels/working-with-panels/configure-legend/ + - visualizations/configure-legend/ +title: Configure a legend +weight: 400 +--- + +# Configure a legend + +A panel includes a legend that you can use to interpret data displayed in a visualization. Each legend option adds context and clarity to the data illustrated in a visualization. + +## Isolate series data in a visualization + +Visualizations can often be visually complex, and include many data series. You can simplify the view by removing series data from the visualization, which isolates the data you want to see. Grafana automatically creates a new override in the **Override** tab. + +When you apply your changes, the visualization changes appear to all users of the panel. + +1. Open the panel. + +1. In the legend, click the label of the series you want to isolate. + + The system removes from view all other series data. + +1. To incrementally add series data to an isolated series, press the **Ctrl** or **Command** key and click the label of the series you want to add. + +1. To revert back to the default view that includes all data, click any series label twice. + +1. To save your changes so that they appear to all viewers of the panel, click **Apply**. + +This topic currently applies to the following visualizations: + +- [Bar chart]({{< relref "../bar-chart/" >}}) +- [Histogram]({{< relref "../histogram/" >}}) +- [Pie chart]({{< relref "../pie-chart/" >}}) +- [State timeline]({{< relref "../state-timeline/" >}}) +- [Status history]({{< relref "../status-history/" >}}) +- [Time series]({{< relref "../time-series/" >}}) + +## Add values to a legend + +As way to add more context to a visualization, you can add series data values to a legend. You can add as many values as you'd like; after you apply your changes, you can horizontally scroll the legend to see all values. + +1. Edit a panel. + +1. In the panel display options pane, locate the **Legend** section. + +1. In the **Legend values** field, select the values you want to appear in the legend. + +1. Click **Apply** to save your changes are navigate back to the dashboard. + +![Toggle series visibility](/static/img/docs/legend/legend-series-toggle-7-5.png) + +## Change a series color + +By default, Grafana specifies the color of your series data, which you can change. + +1. Edit a panel. + +1. In the legend, click the color bar associated with the series. + +1. Select a pre-set color or a custom color from the color palette. + +1. Click **Apply** to save your changes are navigate back to the dashboard. + +![Change legend series color](/static/img/docs/legend/legend-series-color-7-5.png) + +## Sort series + +You can change legend mode to **Table** and choose [calculations]({{< relref "../../calculation-types/" >}}) to be displayed in the legend. Click the calculation name header in the legend table to sort the values in the table in ascending or descending order. + +The sort order affects the positions of the bars in the Bar chart panel as well as the order of stacked series in the Time series and Bar chart panels. + +> **Note:** This feature is only supported in these panels: Bar chart, Histogram, Time series, XY Chart. + +![Sort legend series](/static/img/docs/legend/legend-series-sort-8-3.png). diff --git a/docs/sources/panels-visualizations/panel-editor-overview/index.md b/docs/sources/panels-visualizations/panel-editor-overview/index.md index 9e90b70e4199d..c2ad03ca62208 100644 --- a/docs/sources/panels-visualizations/panel-editor-overview/index.md +++ b/docs/sources/panels-visualizations/panel-editor-overview/index.md @@ -6,6 +6,7 @@ aliases: - ../panels/add-panels-dynamically/about-repeating-panels-rows/ - ../panels/add-panels-dynamically/configure-repeating-panels/ - ../panels/add-panels-dynamically/configure-repeating-rows/ + - ../panels/working-with-panels/ - ../panels/working-with-panels/add-panel/ - ../panels/working-with-panels/navigate-inspector-panel/ - ../panels/working-with-panels/navigate-panel-editor/ diff --git a/docs/sources/panels-visualizations/visualizations/logs/index.md b/docs/sources/panels-visualizations/visualizations/logs/index.md index 6a8a28a2ad36e..288eccc0084ee 100644 --- a/docs/sources/panels-visualizations/visualizations/logs/index.md +++ b/docs/sources/panels-visualizations/visualizations/logs/index.md @@ -26,7 +26,7 @@ To limit the number of lines rendered, you can use the **Max data points** setti ## Log level -For logs where a **level** label is specified, we use the value of the label to determine the log level and update color accordingly. If the log doesn't have a level label specified, we try to find out if its content matches any of the supported expressions (see below for more information). The log level is always determined by the first match. In case Grafana is not able to determine a log level, it will be visualized with **unknown** log level. See [supported log levels and mappings of log level abbreviation and expressions]({{< relref "../../../explore/#log-level" >}}). +For logs where a **level** label is specified, we use the value of the label to determine the log level and update color accordingly. If the log doesn't have a level label specified, we try to find out if its content matches any of the supported expressions (see below for more information). The log level is always determined by the first match. In case Grafana is not able to determine a log level, it will be visualized with **unknown** log level. See [supported log levels and mappings of log level abbreviation and expressions]({{< relref "../../../explore/logs-integration/#log-level" >}}). ## Log details diff --git a/docs/sources/setup-grafana/configure-grafana/_index.md b/docs/sources/setup-grafana/configure-grafana/_index.md index ec7f3be2a7335..cac434f9748fc 100644 --- a/docs/sources/setup-grafana/configure-grafana/_index.md +++ b/docs/sources/setup-grafana/configure-grafana/_index.md @@ -1306,7 +1306,7 @@ The interval string is a possibly signed sequence of decimal numbers, followed b ## [unified_alerting.screenshots] -For more information about screenshots, refer to [Images in notifications]({{< relref "../../alerting/images-in-notifications/" >}}). +For more information about screenshots, refer to [Images in notifications]({{< relref "../../alerting/manage-notifications/images-in-notifications">}}). ### capture diff --git a/docs/sources/setup-grafana/configure-grafana/enterprise-configuration.md b/docs/sources/setup-grafana/configure-grafana/enterprise-configuration.md index e0f61cf2a5928..8a21c1057069e 100644 --- a/docs/sources/setup-grafana/configure-grafana/enterprise-configuration.md +++ b/docs/sources/setup-grafana/configure-grafana/enterprise-configuration.md @@ -374,7 +374,7 @@ Setting 'enabled' to `true` allows users to configure query caching for data sou This value is `true` by default. -> **Note:** This setting enables the caching feature, but it does not turn on query caching for any data source. To turn on query caching for a data source, update the setting on the data source configuration page. For more information, refer to the [Query caching]({{< relref "../../../administration/data-source-management/#enable-and-configure-query-caching" >}}). +> **Note:** This setting enables the caching feature, but it does not turn on query caching for any data source. To turn on query caching for a data source, update the setting on the data source configuration page. For more information, refer to the [Query caching]({{< relref "../../administration/data-source-management#enable-and-configure-query-caching" >}}). ### ttl diff --git a/docs/sources/setup-grafana/configure-security/configure-authentication/enhanced_ldap.md b/docs/sources/setup-grafana/configure-security/configure-authentication/enhanced_ldap.md index 4b9af53be9009..93fc126deeba3 100644 --- a/docs/sources/setup-grafana/configure-security/configure-authentication/enhanced_ldap.md +++ b/docs/sources/setup-grafana/configure-security/configure-authentication/enhanced_ldap.md @@ -1,6 +1,7 @@ --- aliases: - ../../../enterprise/enhanced_ldap/ + - ../../../auth/enhanced_ldap/ description: Grafana Enhanced LDAP Integration Guide keywords: - grafana @@ -17,7 +18,8 @@ weight: 900 The enhanced LDAP integration adds additional functionality on top of the [LDAP integration]({{< relref "ldap/" >}}) available in the open source edition of Grafana. -> **Note:** Available in [Grafana Enterprise]({{< relref "../../../enterprise/" >}}) and [Grafana Cloud Advanced]({{< ref "/grafana-cloud" >}}). +> **Note:** Available in [Grafana Enterprise]({{< relref "../../../enterprise/" >}}) and [Grafana Cloud Advanced]({{< relref "/docs/grafana-cloud" >}}). +> If you are a Grafana Cloud customer, please [open a support ticket in the Cloud Portal](/profile/org#support) to request this feature. > To control user access with role-based permissions, refer to [role-based access control]({{< relref "../../../administration/roles-and-permissions/access-control/" >}}). @@ -66,3 +68,17 @@ active_sync_enabled = true # enabled by default ``` Single bind configuration (as in the [Single bind example]({{< relref "ldap/#single-bind-example" >}})) is not supported with active LDAP synchronization because Grafana needs user information to perform LDAP searches. + +For the synchronization to work, the `servers.search_filter` and `servers.attributes.username` in the ldap.toml config file must match. By default, the `servers.attributes.username` is `cn`, so if you use another attribute as the search filter, you must also update the username attribute. + +For example: + +``` +[[servers]] +search_filter = "(sAMAccountName=%s)" + +[servers.attributes] +username = "sAMAccountName" +``` + +If the attributes aren't the same, the users' sessions will be terminated after each synchronization. That's because the search will be done using the username's value, and that value doesn't exist for the attribute used in the search filter. diff --git a/docs/sources/setup-grafana/configure-security/configure-database-encryption/encrypt-secrets-using-azure-key-vault.md b/docs/sources/setup-grafana/configure-security/configure-database-encryption/encrypt-secrets-using-azure-key-vault.md index f5cc49adc42cb..f9c302f524835 100644 --- a/docs/sources/setup-grafana/configure-security/configure-database-encryption/encrypt-secrets-using-azure-key-vault.md +++ b/docs/sources/setup-grafana/configure-security/configure-database-encryption/encrypt-secrets-using-azure-key-vault.md @@ -25,7 +25,7 @@ You can use an encryption key from Azure Key Vault to encrypt secrets in the Gra 5. In the Key Permissions section, set encrypt and decrypt permissions, and click **Save**. -6. From within Grafana, turn on [envelope encryption]({{< relref "/" >}}). +6. From within Grafana, turn on [envelope encryption]({{< relref "./#envelope-encryption" >}}). 7. Add your Azure Key Vault details to the Grafana configuration file; depending on your operating system, is usually named `grafana.ini`:

a. Add a new section to the configuration file, with a name in the format of `[security.encryption.azurekv.]`, where `` is any name that uniquely identifies this key among other provider keys. diff --git a/docs/sources/setup-grafana/configure-security/configure-team-sync.md b/docs/sources/setup-grafana/configure-security/configure-team-sync.md index 82a1a6266f79e..fba368d0ea501 100644 --- a/docs/sources/setup-grafana/configure-security/configure-team-sync.md +++ b/docs/sources/setup-grafana/configure-security/configure-team-sync.md @@ -1,6 +1,5 @@ --- aliases: - - ../../auth/saml/ - ../../auth/team-sync/ - ../../enterprise/team-sync/ description: Learn how to use Team Sync to synchronize between your authentication diff --git a/docs/sources/setup-grafana/image-rendering/troubleshooting.md b/docs/sources/setup-grafana/image-rendering/troubleshooting.md index 20d075dfcafbd..0abf7cf64a3e1 100644 --- a/docs/sources/setup-grafana/image-rendering/troubleshooting.md +++ b/docs/sources/setup-grafana/image-rendering/troubleshooting.md @@ -114,7 +114,7 @@ If this happens, then you have to add the certificate to the trust store. If you ``` [root@server ~]# [ -d /usr/share/grafana/.pki/nssdb ] || mkdir -p /usr/share/grafana/.pki/nssdb -[root@merver ~]# certutil -d sql:/usr/share/grafana/.pki/nssdb -A -n internal-root-ca -t C -i /etc/pki/tls/certs/internal-root-ca.crt.pem +[root@server ~]# certutil -d sql:/usr/share/grafana/.pki/nssdb -A -n internal-root-ca -t C -i /etc/pki/tls/certs/internal-root-ca.crt.pem [root@server ~]# chown -R grafana: /usr/share/grafana/.pki/nssdb ``` diff --git a/docs/sources/setup-grafana/installation/docker.md b/docs/sources/setup-grafana/installation/docker.md index 5fb7a8b3dbb84..eadf40d6ba250 100644 --- a/docs/sources/setup-grafana/installation/docker.md +++ b/docs/sources/setup-grafana/installation/docker.md @@ -112,7 +112,20 @@ docker run -d \ You can build your own customized image that includes plugins. This saves time if you are creating multiple images and you want them all to have the same plugins installed on build. -In the [Grafana GitHub repository](https://github.com/grafana/grafana) there is a folder called `packaging/docker/custom/`, which includes two Dockerfiles, `Dockerfile` and `ubuntu.Dockerfile`, that can be used to build a custom Grafana image. It accepts `GRAFANA_VERSION`, `GF_INSTALL_PLUGINS`, and `GF_INSTALL_IMAGE_RENDERER_PLUGIN` as build arguments. +In the [Grafana GitHub repository](https://github.com/grafana/grafana) there is a folder called `packaging/docker/custom/`, which includes a Dockerfile that can be used to build a custom Grafana image. It accepts `GRAFANA_VERSION`, `GF_INSTALL_PLUGINS`, and `GF_INSTALL_IMAGE_RENDERER_PLUGIN` as build arguments. + +The `GRAFANA_VERSION` build argument must be a valid `grafana/grafana` docker image tag. By default, this builds an Alpine-based image. To build an Ubuntu-based image, append `-ubuntu` to the `GRAFANA_VERSION` build argument (available in Grafana v6.5 and later). + +The following example shows you how to build and run a custom Grafana Docker image based on the latest official Ubuntu-based Grafana Docker image: + +```bash +cd packaging/docker/custom +docker build \ + --build-arg "GRAFANA_VERSION=latest-ubuntu" \ + -t grafana-custom . + +docker run -d -p 3000:3000 --name=grafana grafana-custom +``` ### Build with pre-installed plugins @@ -125,7 +138,7 @@ cd packaging/docker/custom docker build \ --build-arg "GRAFANA_VERSION=latest" \ --build-arg "GF_INSTALL_PLUGINS=grafana-clock-panel,grafana-simple-json-datasource" \ - -t grafana-custom -f Dockerfile . + -t grafana-custom . docker run -d -p 3000:3000 --name=grafana grafana-custom ``` @@ -139,13 +152,11 @@ cd packaging/docker/custom docker build \ --build-arg "GRAFANA_VERSION=latest" \ --build-arg "GF_INSTALL_PLUGINS=http://plugin-domain.com/my-custom-plugin.zip;custom-plugin,grafana-clock-panel" \ - -t grafana-custom -f Dockerfile . + -t grafana-custom . docker run -d -p 3000:3000 --name=grafana grafana-custom ``` -Replace `Dockerfile` in above example with `ubuntu.Dockerfile` to build a custom Ubuntu based image (Grafana v6.5+). - ### Build with Grafana Image Renderer plugin pre-installed > Only available in Grafana v6.5 and later. This is experimental. @@ -159,13 +170,11 @@ cd packaging/docker/custom docker build \ --build-arg "GRAFANA_VERSION=latest" \ --build-arg "GF_INSTALL_IMAGE_RENDERER_PLUGIN=true" \ - -t grafana-custom -f Dockerfile . + -t grafana-custom . docker run -d -p 3000:3000 --name=grafana grafana-custom ``` -Replace `Dockerfile` in above example with `ubuntu.Dockerfile` to build a custom Ubuntu-based image (Grafana v6.5+). - ## Migrate from previous Docker containers versions This section contains important information if you want to migrate from previous Grafana container versions to a more current one. diff --git a/docs/sources/setup-grafana/set-up-https.md b/docs/sources/setup-grafana/set-up-https.md new file mode 100644 index 0000000000000..473b6a8a6ac46 --- /dev/null +++ b/docs/sources/setup-grafana/set-up-https.md @@ -0,0 +1,276 @@ +--- +keywords: + - grafana + - https + - ssl + - certificates +title: Set up Grafana HTTPS for secure web traffic +menuTitle: Set up HTTPS +weight: 900 +--- + +# Set up Grafana HTTPS for secure web traffic + +When accessing the Grafana UI through the web, it is important to set up HTTPS to ensure the communication between Grafana and the end user is encrypted, including login credentials and retrieved metric data. + +In order to ensure secure traffic over the internet, Grafana must have a key for encryption and a [Secure Socket Layer (SSL) Certificate](https://www.kaspersky.com/resource-center/definitions/what-is-a-ssl-certificate) to verify the identity of the site. + +The following image shows a browser lock icon which confirms the connection is safe. + +{{< figure src="/media/docs/grafana/https-config/screenshot-secure-https.png" max-width="500px" caption="Secure HTTPS connection" >}} + +This topic shows you how to: + +1. Obtain a certificate and key +2. Configure Grafana HTTPS +3. Restart the Grafana server + +## Before you begin + +To follow these instructions, you need: + +- You must have shell access to the system and `sudo` access to perform actions as root or administrator. +- For the CA-signed option, you need a domain name that you possess and that is associated with the machine you are using. + +## Obtain a certificate and key + +You can use one of two methods to obtain a certificate and a key. The faster and easier _self-signed_ option might show browser warnings to the user that they will have to accept each time they visit the site. Alternatively, the Certificate Authority (CA) signed option requires more steps to complete, but it enables full trust with the browser. To learn more about the difference between these options, refer to [Difference between self-signed CA and self-signed certificate](https://www.baeldung.com/cs/self-signed-ca-vs-certificate). + +### Generate a self-signed certificate + +This section shows you how to use `openssl` tooling to generate all necessary files from the command line. + +1. Run the following command to generate a 2048-bit RSA private key, which is used to decrypt traffic: + + ```bash + $ sudo openssl genrsa -out /etc/grafana/grafana.key 2048 + ``` + +1. Run the following command to generate a certificate, using the private key from the previous step. + + ```bash + $ sudo openssl req -new -key /etc/grafana/grafana.key -out /etc/grafana/grafana.csr + ``` + + When prompted, answer the questions, which might include your fully-qualified domain name, email address, country code, and others. The following example is similar to the prompts you will see. + + ``` + You are about to be asked to enter information that will be incorporated + into your certificate request. + What you are about to enter is what is called a Distinguished Name or a DN. + There are quite a few fields but you can leave some blank + For some fields there will be a default value, + If you enter '.', the field will be left blank. + ----- + Country Name (2 letter code) [AU]:US + State or Province Name (full name) [Some-State]:Virginia + Locality Name (eg, city) []:Richmond + Organization Name (eg, company) [Internet Widgits Pty Ltd]: + Organizational Unit Name (eg, section) []: + Common Name (e.g. server FQDN or YOUR name) []:subdomain.mysite.com + Email Address []:me@mysite.com + + Please enter the following 'extra' attributes + to be sent with your certificate request + A challenge password []: + An optional company name []: + ``` + +1. Run the following command to self-sign the certificate with the private key, for a period of validity of 365 days: + + ```bash + sudo openssl x509 -req -days 365 -in grafana.csr -signkey /etc/grafana/grafana.key -out /etc/grafana/grafana.crt + ``` + +1. Run the following commands to set the appropriate permissions for the files: + + ```bash + sudo chown grafana:grafana /etc/grafana/grafana.crt + sudo chown grafana:grafana /etc/grafana/grafana.key + sudo chmod 400 grafana.key /etc/grafana/grafana.crt + ``` + + **Note**: When using these files, browsers might provide warnings for the resulting website because a third-party source does not trust the certificate. Browsers will show trust warnings; however, the connection will remain encrypted. + + The following image shows an insecure HTTP connection. + + {{< figure src="/media/docs/grafana/https-config/screenshot-insecure-https.png" max-width="750px" caption="Insecure HTTPS connection" >}} + +### Obtain a signed certificate from LetsEncrypt + +[LetsEncrypt](https://letsencrypt.org/) is a nonprofit certificate authority that provides certificates without any charge. For signed certificates, there are multiple companies and certificate authorities (CAs) available. The principles for generating the certificates might vary slightly in accordance with the provider but will generally remain the same. + +The examples in this section use LetsEncrypt because it is free. + +> **Note**: The instructions provided in this section are for a Debian-based Linux system. For other distributions and operating systems, please refer to the [certbot instructions](https://certbot.eff.org/instructions). Also, these instructions require you to have a domain name that you are in control of. Dynamic domain names like those from Amazon EC2 or DynDNS providers will not function. + +#### Install `snapd` and `certbot` + +`certbot` is an open-source program used to manage LetsEncrypt certificates, and `snapd` is a tool that assists in running `certbot` and installing the certificates. + +1. To install `snapd`, run the following commands: + + ```bash + sudo apt-get install snapd + sudo snap install core; sudo snap refresh core + ``` + +1. Run the following commands to install: + + ```bash + sudo apt-get remove certbot + sudo snap install --classic certbot + sudo ln -s /snap/bin/certbot /usr/bin/certbot + ``` + + These commands: + + - Uninstall `certbot` from your system if it has been installed using a package manager + - Install `certbot` using `snapd` + +#### Generate certificates using `certbot` + +The `sudo certbot certonly --standalone` command prompts you to answer questions before it generates a certificate. This process temporarily opens a service on port `80` that LetsEncrypt uses to verify communication with your host. + +To generate certificates using `certbot`, complete the following steps: + +1. Ensure that port `80` traffic is permitted by applicable firewall rules. + +1. Run the following command to generate certificates: + + ```bash + $ sudo certbot certonly --standalone + + Saving debug log to /var/log/letsencrypt/letsencrypt.log + Enter email address (used for urgent renewal and security notices) + (Enter 'c' to cancel): me@mysite.com + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + Please read the Terms of Service at + https://letsencrypt.org/documents/LE-SA-v1.3-September-21-2022.pdf. You must + agree in order to register with the ACME server. Do you agree? + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + (Y)es/(N)o: y + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + Would you be willing, once your first certificate is successfully issued, to + share your email address with the Electronic Frontier Foundation, a founding + partner of the Let’s Encrypt project and the non-profit organization that + develops Certbot? We’d like to send you email about our work encrypting the web, + EFF news, campaigns, and ways to support digital freedom. + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + (Y)es/(N)o: n + Account registered. + Please enter the domain name(s) you would like on your certificate (comma and/or + space separated) (Enter 'c' to cancel): subdomain.mysite.com + Requesting a certificate for subdomain.mysite.com + + Successfully received certificate. + Certificate is saved at: /etc/letsencrypt/live/subdomain.mysite.com/fullchain.pem + Key is saved at: /etc/letsencrypt/live/subdomain.mysite.com/privkey.pem + This certificate expires on 2023-06-20. + These files will be updated when the certificate renews. + Certbot has set up a scheduled task to automatically renew this certificate in the background. + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + If you like Certbot, please consider supporting our work by: + * Donating to ISRG / Let’s Encrypt: https://letsencrypt.org/donate + * Donating to EFF: https://eff.org/donate-le + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + ``` + +#### Set up symlinks to Grafana + +Symbolic links, also known as symlinks, enable you to create pointers to existing LetsEncrypt files in the `/etc/grafana` directory. By using symlinks rather than copying files, you can use `certbot` to refresh or request updated certificates from LetsEncrypt without the need to reconfigure the Grafana settings. + +To set up symlinks to Grafana, run the following commands: + +```bash +$ sudo ln -s /etc/letsencrypt/live/subdomain.mysite.com/privkey.pem /etc/grafana/grafana.key +$ sudo ln -s /etc/letsencrypt/live/subdomain.mysite.com/fullchain.pem /etc/grafana/grafana.crt +``` + +#### Adjust permissions + +Grafana usually runs under the `grafana` Linux group, and you must ensure that the Grafana server process has permission to read the relevant files. Without read access, the HTTPS server fails to start properly. + +To adjust permissions, perform the following steps: + +1. Run the following commands to set the appropriate permissions and groups for the files: + + ```bash + $ sudo chgrp -R grafana /etc/letsencrypt/* + $ sudo chmod -R g+rx /etc/letsencrypt/* + $ sudo chgrp -R grafana /etc/grafana/grafana.crt /etc/grafana/grafana.key + $ sudo chmod 400 /etc/grafana/grafana.crt /etc/grafana/grafana.key + ``` + +1. Run the following command to verify that the `grafana` group can read the symlinks: + + ```bash + $ $ ls -l /etc/grafana/grafana.* + + lrwxrwxrwx 1 root grafana 67 Mar 22 14:15 /etc/grafana/grafana.crt -> /etc/letsencrypt/live/subdomain.mysite.com/fullchain.pem + -rw-r----- 1 root grafana 54554 Mar 22 14:13 /etc/grafana/grafana.ini + lrwxrwxrwx 1 root grafana 65 Mar 22 14:15 /etc/grafana/grafana.key -> /etc/letsencrypt/live/subdomain.mysite.com/privkey.pem + ``` + +## Configure Grafana HTTPS and restart Grafana + +In this section you edit the `grafana.ini` file so that it includes the certificate you created. If you need help identifying where to find this file, or what each key means, refer to [Configuration file location]({{< relref "./configure-grafana#configuration-file-location" >}}). + +To configure Grafana HTTPS and restart Grafana, complete the following steps. + +1. Open the `grafana.ini` file and edit the following configuration parameters: + + ``` + [server] + http_addr = + http_port = 3000 + domain = mysite.com + root_url = https://subdomain.mysite.com:3000 + cert_key = /etc/grafana/grafana.key + cert_file = /etc/grafana/grafana.crt + enforce_domain = False + protocol = https + ``` + + > **Note**: The standard port for SSL traffic is 443, which you can use instead of Grafana's default port 3000. This change might require additional operating system privileges or configuration to bind to lower-numbered privileged ports. + +1. [Restart the Grafana server]({{< relref "./start-restart-grafana/#linux" >}}) using `systemd`, `init.d`, or the binary as appropriate for your environment. + +## Troubleshooting + +Refer to the following troubleshooting tips as required. + +### Failure to obtain a certificate + +The following reasons explain why the `certbot` process might fail: + +- To make sure you can get a certificate from LetsEncrypt, you need to ensure that port 80 is open so that LetsEncrypt can communicate with your machine. If port 80 is blocked or firewall is enabled, the exchange will fail and you won't be able to receive a certificate. +- LetsEncrypt requires proof that you control the domain, so attempts to obtain certificates for domains you do not + control might be rejected. + +### Grafana starts, but HTTPS is unavailable + +When you configure HTTPS, the following errors might appear in Grafana's logs. + +#### Permission denied + +``` +level=error msg="Stopped background service" service=*api.HTTPServer reason="open /etc/grafana/grafana.crt: permission denied" +``` + +##### Resolution + +To ensure secure HTTPS setup, it is essential that the cryptographic keys and certificates are as restricted as possible. However, if the file permissions are too restricted, the Grafana process may not have access to the necessary files, thus impeding a successful HTTPS setup. Please re-examine the listed instructions to double check the file permissions and try again. + +#### Cannot assign requested address + +``` +listen tcp 34.148.30.243:3000: bind: cannot assign requested address +``` + +##### Resolution + +Check the config to ensure the `http_addr` is left blank, allowing Grafana to bind to all interfaces. If you have set `http_addr` to a specific subdomain, such as `subdomain.mysite.com`, this might prevent the Grafana process from binding to an external address, due to network address translation layers being present. diff --git a/docs/sources/troubleshooting/_index.md b/docs/sources/troubleshooting/_index.md index f569b57d473a3..339007b6d3494 100644 --- a/docs/sources/troubleshooting/_index.md +++ b/docs/sources/troubleshooting/_index.md @@ -45,7 +45,6 @@ sudo yum install freetype* sudo yum install urw-fonts ``` -## FAQs +## More help -Check out the [FAQ section](https://community.grafana.com/c/howto/faq) on the Grafana Community page for answers to frequently -asked questions. +Check out the [Grafana Community](https://community.grafana.com/) for more troubleshooting help (you must be logged in to post or comment). diff --git a/docs/sources/visualizations/configure-legend/index.md b/docs/sources/visualizations/configure-legend/index.md index 059bfb2acda5b..9ff1cf0f88244 100644 --- a/docs/sources/visualizations/configure-legend/index.md +++ b/docs/sources/visualizations/configure-legend/index.md @@ -1,10 +1,17 @@ --- aliases: +<<<<<<<< HEAD:docs/sources/visualizations/configure-legend/index.md - /docs/grafana/latest/panels/working-with-panels/configure-legend/ - /docs/grafana/latest/visualizations/configure-legend/ - /docs/grafana/latest/panels-visualizations/visualizations/configure-legend/ title: Configure a legend weight: 1300 +======== + - ../panels/working-with-panels/configure-legend/ + - visualizations/configure-legend/ +title: Configure a legend +weight: 400 +>>>>>>>> release-9.2.18:docs/sources/panels-visualizations/configure-legend/index.md --- # Configure a legend diff --git a/docs/sources/visualizations/geomap/_index.md b/docs/sources/visualizations/geomap/_index.md deleted file mode 100644 index f0c77faa5b71c..0000000000000 --- a/docs/sources/visualizations/geomap/_index.md +++ /dev/null @@ -1,162 +0,0 @@ ---- -aliases: - - /docs/grafana/latest/features/panels/geomap/ - - /docs/grafana/latest/panels/visualizations/geomap/ - - /docs/grafana/latest/visualizations/geomap/ -description: Geomap visualization documentation -keywords: - - grafana - - Geomap - - panel - - documentation -title: Geomap -weight: 600 ---- - -# Geomap - -The Geomap panel visualization allows you to view and customize the world map using geospatial data. You can configure various overlay styles and map view settings to easily focus on the important location-based characteristics of the data. - -{{< figure src="/static/img/docs/geomap-panel/geomap-example-8-1-0.png" max-width="1200px" caption="Geomap panel" >}} - -## Map View - -The map view controls the initial view of the map when the dashboard loads. - -### Initial View - -The initial view configures how the GeoMap panel renders when the panel is first loaded. - -- **View** sets the center for the map when the panel first loads. -- **Latitude** (available when the **View** mode is _Coordinates_) -- **Longitude** (available when the **View** mode is _Coordinates_) -- **Zoom** sets the initial zoom level for the GeoMap panel, or the initial maximum zoom level in case the _Fit data layers_ view is selected. - -## Map layers - -The Geomap visualization supports showing multiple layers. Each layer determines how you visualize geospatial data on top of the base map. - -### Types - -There are three map layer types to choose from in the Geomap visualization. - -- [Markers]({{< relref "markers/" >}}) renders a marker at each data point. -- [Heatmap]({{< relref "heatmap/" >}}) visualizes a heatmap of the data. -- [GeoJSON]({{< relref "geojson/" >}}) renders static data from a GeoJSON file. - -There are also four alpha layer types. - -- [Night / Day (alpha)]({{< relref "daynight/" >}}) renders a night / day region. -- **Icon at last point (alpha)** renders an icon at the last data point. -- **Dynamic GeoJSON (alpha)** styles a GeoJSON file based on query results. -- **Route (alpha)** render data points as a route. - -> **Note:** [Basemap layer types]({{< relref "#types-1" >}}) can also be added as layers. You can specify an opacity. - -### Layer Controls - -The layer controls allow you to create layers, change their name, reorder and delete layers. - -- **Add layer** creates an additional, configurable data layer for the Geomap visualization. When you add a layer, you are prompted to select a layer type. You can change the layer type at any point during panel configuration. See the **Layer Types** section above for details on each layer type. -- The layer controls allow you to rename, delete, and reorder the layers of the panel. - - **Edit layer name (pencil icon)** renames the layer. - - **Trash Bin** deletes the layer. - - **Reorder (six dots/grab handle)** allows you to change the layer order. Data on higher layers will appear above data on lower layers. The panel will update the layer order as you drag and drop to help simplify choosing a layer order. - -You can add multiple layers of data to a single Geomap panel in order to create rich, detailed visualizations. - -### Location - -The Geomap panel needs a source of geographical data. This data comes from a database query, and there are four mapping options for your data. - -- **Auto** automatically searches for location data. Use this option when your query is based on one of the following names for data fields. - - geohash: “geohash” - - latitude: “latitude”, “lat” - - longitude: “longitude”, “lng”, “lon” - - lookup: “lookup” -- **Coords** specifies that your query holds coordinate data. You will get prompted to select numeric data fields for latitude and longitude from your database query. -- **Geohash** specifies that your query holds geohash data. You will be prompted to select a string data field for the geohash from your database query. -- **Lookup** specifies that your query holds location name data that needs to be mapped to a value. You will be prompted to select the lookup field from your database query and a gazetteer. The gazetteer is the directory that is used to map your queried data to a geographical point. - -## Basemap layer - -A basemap layer provides the visual foundation for a mapping application. It typically contains data with global coverage. Several base layer options -are available each with specific configuration options to style the base map. - -### Types - -There are four basemap layer types to choose from in the Geomap visualization. - -- [Open Street Map]({{< relref "osm/" >}}) adds a map from a collaborative free geographic world database. -- [CARTO]({{< relref "carto/" >}}) adds a layer from CARTO Raster basemaps. -- [ArcGIS]({{< relref "arcgis/" >}}) adds a layer from an ESRI ArcGIS MapServer. -- [XYZ]({{< relref "xyz/" >}}) adds a map from a generic tile layer. - -### Default - -The default base layer uses the [CARTO]({{< relref "carto/" >}}) map. You can define custom default base layers in the `.ini` configuration file. - -![Basemap layer options](/static/img/docs/geomap-panel/geomap-baselayer-8-1-0.png) - -#### Configure the default base layer with provisioning - -You can configure the default base map using config files with Grafana’s provisioning system. For more information on all the settings, refer to the [provisioning docs page]({{< relref "../../administration/provisioning/" >}}). - -Use the JSON configuration option `default_baselayer_config` to define the default base map. There are currently four base map options to choose from: `carto`, `esri-xyz`, `osm-standard`, `xyz`. Here are some provisioning examples for each base map option. - -- **carto** loads the CartoDB tile server. You can choose from `auto`, `dark`, and `light` theme for the base map and can be set as shown below. The `showLabels` tag determines whether or not Grafana shows the Country details on top of the map. Here is an example: - -```ini -geomap_default_baselayer = `{ - "type": "carto", - "config": { - "theme": "auto", - "showLabels": true - } -}` -``` - -- **esri-xyz** loads the ESRI tile server. There are already multiple server instances implemented to show the various map styles: `world-imagery`, `world-physical`, `topo`, `usa-topo`, and `ocean`. The `custom` server option allows you to configure your own ArcGIS map server. Here are some examples: - -```ini -geomap_default_baselayer = `{ - "type": "esri-xyz", - "config": { - "server": "world-imagery" - } -}` -``` - -```ini -geomap_default_baselayer = `{ - "type": "esri-xyz", - "config": { - "server": "custom", - "url": "[tile server url]", - "attribution": "[tile server attribution]" - } -}` -``` - -- **osm-standard** loads the OpenStreetMap tile server. There are no additional configurations needed and the `config` fields can be left blank. Here is an example: - -```ini -default_baselayer_config = `{ - "type": "osm-standard", - "config": {} -}` -``` - -- **xyz** loads a custom tile server defined by the user. Set a valid tile server `url`, with {z}/{x}/{y} for this option in order to properly load a default base map. Here is an example: - -```ini -default_baselayer_config = `{ - "type": "xyz", - "config": { - "attribution": "Open street map", - "url": "https://tile.openstreetmap.org/{z}/{x}/{y}.png" - } -}` -``` - -`enable_custom_baselayers` allows you to enable or disable custom open source base maps that are already implemented. The default is `true`. diff --git a/docs/sources/whatsnew/whats-new-in-v9-2.md b/docs/sources/whatsnew/whats-new-in-v9-2.md index ada1d5a623dff..1e212b028c891 100644 --- a/docs/sources/whatsnew/whats-new-in-v9-2.md +++ b/docs/sources/whatsnew/whats-new-in-v9-2.md @@ -140,8 +140,8 @@ For details on using this functionality, see [GitHub pull request #55313](https: ## Transformations: INNER JOINs -Transformations allow you to shape raw data from data sources, like metrics series or GitHub issues, into a format that's appropriate for the chosen visualization. -We have extended the Join transformation to support INNER JOINs in addition to OUTER JOINs. These work similarly to SQL JOINs. +[Transformations]({{< relref "../panels-visualizations/query-transform-data/transform-data/" >}}) allow you to shape raw data from data sources, like metrics series or GitHub issues, into a format that's appropriate for the chosen visualization. +We have extended the [Join transformation]({{< relref "../panels-visualizations/query-transform-data/transform-data/#join-by-field" >}}) to support INNER JOINs in addition to OUTER JOINs. These work similarly to SQL JOINs. {{< figure src="/static/img/docs/transformations/transform-outer-join-9-2.png" max-width="750px" caption="Query builder groupings for Google Cloud monitoring" >}} diff --git a/e2e/cloud-plugins-suite/azure-monitor.spec.ts b/e2e/cloud-plugins-suite/azure-monitor.spec.ts new file mode 100644 index 0000000000000..a46ddf4fa7105 --- /dev/null +++ b/e2e/cloud-plugins-suite/azure-monitor.spec.ts @@ -0,0 +1,7 @@ +import { e2e } from '@grafana/e2e'; + +e2e.scenario({ + describeName: 'skip test', + itName: 'skip test', + skipScenario: true, +}); diff --git a/go.mod b/go.mod index 03c00985c458c..fafbb08ded586 100644 --- a/go.mod +++ b/go.mod @@ -30,7 +30,7 @@ require ( github.com/bradfitz/gomemcache v0.0.0-20190913173617-a41fca850d0b github.com/centrifugal/centrifuge v0.25.0 github.com/cortexproject/cortex v1.10.1-0.20211014125347-85c378182d0d - github.com/crewjam/saml v0.4.9 + github.com/crewjam/saml v0.4.13 github.com/davecgh/go-spew v1.1.1 github.com/denisenkom/go-mssqldb v0.12.0 github.com/dop251/goja v0.0.0-20210804101310-32956a348b49 @@ -49,7 +49,7 @@ require ( github.com/gogo/protobuf v1.3.2 github.com/golang/mock v1.6.0 github.com/golang/snappy v0.0.4 - github.com/google/go-cmp v0.5.8 + github.com/google/go-cmp v0.5.9 github.com/google/uuid v1.3.0 github.com/google/wire v0.5.0 github.com/gorilla/websocket v1.5.0 @@ -87,8 +87,8 @@ require ( github.com/prometheus/common v0.37.0 github.com/prometheus/prometheus v1.8.2-0.20211011171444-354d8d2ecfac github.com/robfig/cron/v3 v3.0.1 - github.com/russellhaering/goxmldsig v1.1.1 - github.com/stretchr/testify v1.8.0 + github.com/russellhaering/goxmldsig v1.2.0 + github.com/stretchr/testify v1.8.1 github.com/teris-io/shortid v0.0.0-20171029131806-771a37caa5cf github.com/ua-parser/uap-go v0.0.0-20211112212520-00c877edfe0f github.com/uber/jaeger-client-go v2.29.1+incompatible @@ -168,7 +168,7 @@ require ( github.com/go-openapi/validate v0.22.0 // indirect github.com/gogo/googleapis v1.4.1 // indirect github.com/gogo/status v1.1.0 // indirect - github.com/golang-jwt/jwt/v4 v4.4.2 // indirect + github.com/golang-jwt/jwt/v4 v4.4.3 // indirect github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe // indirect github.com/golang/glog v1.0.0 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect @@ -220,7 +220,7 @@ require ( github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749 // indirect github.com/shurcooL/vfsgen v0.0.0-20200824052919-0d455de96546 // indirect github.com/sirupsen/logrus v1.8.1 // indirect - github.com/stretchr/objx v0.4.0 // indirect + github.com/stretchr/objx v0.5.0 // indirect github.com/uber/jaeger-lib v2.4.1+incompatible // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/weaveworks/promrus v1.2.0 // indirect @@ -242,13 +242,16 @@ require ( github.com/Azure/azure-sdk-for-go/sdk/azidentity v0.13.2 github.com/Azure/azure-sdk-for-go/sdk/keyvault/azkeys v0.4.0 github.com/Azure/go-autorest/autorest/adal v0.9.17 + github.com/Masterminds/semver/v3 v3.1.1 github.com/armon/go-radix v1.0.0 github.com/blugelabs/bluge v0.1.9 github.com/blugelabs/bluge_segment_api v0.2.0 github.com/dlmiddlecote/sqlstats v1.0.2 + github.com/docker/docker v20.10.8+incompatible github.com/drone/drone-cli v1.5.0 github.com/getkin/kin-openapi v0.94.0 github.com/golang-migrate/migrate/v4 v4.7.0 + github.com/google/go-github v17.0.0+incompatible github.com/google/go-github/v45 v45.2.0 github.com/grafana/dskit v0.0.0-20211011144203-3a88ec0b675f github.com/jmoiron/sqlx v1.3.5 @@ -267,14 +270,16 @@ require ( github.com/bmatcuk/doublestar v1.1.1 // indirect github.com/buildkite/yaml v2.1.0+incompatible // indirect github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect + github.com/docker/distribution v2.7.1+incompatible // indirect + github.com/docker/go-connections v0.4.0 // indirect github.com/drone/drone-yaml v0.0.0-20190729072335-70fa398b3560 // indirect github.com/google/go-querystring v1.1.0 // indirect - github.com/google/gofuzz v1.2.0 // indirect github.com/gosimple/unidecode v1.0.1 // indirect github.com/hashicorp/go-immutable-radix v1.3.1 // indirect github.com/hashicorp/memberlist v0.4.0 // indirect github.com/mattn/go-colorable v0.1.12 // indirect github.com/mitchellh/mapstructure v1.4.3 // indirect + github.com/opencontainers/go-digest v1.0.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/segmentio/asm v1.1.4 // indirect go.starlark.net v0.0.0-20201118183435-e55f603d8c79 // indirect @@ -334,14 +339,10 @@ require ( go.opentelemetry.io/proto/otlp v0.15.0 // indirect golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect - k8s.io/api v0.22.5 // indirect - k8s.io/apimachinery v0.22.5 // indirect - k8s.io/klog/v2 v2.30.0 // indirect - k8s.io/utils v0.0.0-20210930125809-cb0fa318a74b // indirect ) // Use fork of crewjam/saml with fixes for some issues until changes get merged into upstream -replace github.com/crewjam/saml => github.com/grafana/saml v0.4.9-0.20230102094056-b61b9eb7c8b7 +replace github.com/crewjam/saml => github.com/grafana/saml v0.4.13-0.20230331080031-67cbfa09c7b6 replace github.com/apache/thrift => github.com/apache/thrift v0.14.1 diff --git a/go.sum b/go.sum index 5498eac5eeb2f..4060f922a7906 100644 --- a/go.sum +++ b/go.sum @@ -135,6 +135,7 @@ github.com/Azure/azure-storage-blob-go v0.13.0/go.mod h1:pA9kNqtjUeQF2zOSu4s//nU github.com/Azure/azure-storage-blob-go v0.14.0/go.mod h1:SMqIBi+SuiQH32bvyjngEewEeXoPfKMgWlBDaYf6fck= github.com/Azure/go-amqp v0.16.0/go.mod h1:9YJ3RhxRT1gquYnzpZO1vcYMMpAdJT+QEg6fwmw9Zlg= github.com/Azure/go-amqp v0.16.4/go.mod h1:9YJ3RhxRT1gquYnzpZO1vcYMMpAdJT+QEg6fwmw9Zlg= +github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 h1:w+iIsaOQNcT7OZ575w+acHgRric5iCyQh+xv+KJ4HB8= github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= github.com/Azure/go-autorest v10.8.1+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= github.com/Azure/go-autorest v11.2.8+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= @@ -225,6 +226,7 @@ github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go github.com/Masterminds/semver v1.4.2/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww= github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= +github.com/Masterminds/semver/v3 v3.1.1 h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030IGemrRc= github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= github.com/Masterminds/sprig v2.16.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o= github.com/Masterminds/squirrel v0.0.0-20161115235646-20f192218cf5/go.mod h1:xnKTFzjGUiZtiOagBsfnvomW+nJg2usB1ZpordQWqNM= @@ -690,6 +692,7 @@ github.com/davecgh/go-spew v0.0.0-20161028175848-04cdfd42973b/go.mod h1:J7Y8YcW2 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dchest/uniuri v1.2.0/go.mod h1:fSzm4SLHzNZvWLvWJew423PhAzkpNQYq+uNLq4kxhkY= github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.0-20210816181553-5444fa50b93d/go.mod h1:tmAIfUFEirG/Y8jhZ9M+h36obRZAk/1fcSpXwAVlfqE= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= @@ -923,7 +926,6 @@ github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KE github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= github.com/go-logr/logr v0.4.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= -github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0= github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= @@ -1160,8 +1162,8 @@ github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzq github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= github.com/golang-jwt/jwt/v4 v4.2.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= github.com/golang-jwt/jwt/v4 v4.4.1/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= -github.com/golang-jwt/jwt/v4 v4.4.2 h1:rcc4lwaZgFMCZ5jxF9ABolDcIHdBytAFgqFPbSJQAYs= -github.com/golang-jwt/jwt/v4 v4.4.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= +github.com/golang-jwt/jwt/v4 v4.4.3 h1:Hxl6lhQFj4AnOX6MLrsCb/+7tCj7DxP7VA+2rDIq5AU= +github.com/golang-jwt/jwt/v4 v4.4.3/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/golang-migrate/migrate/v4 v4.7.0 h1:gONcHxHApDTKXDyLH/H97gEHmpu1zcnnbAaq2zgrPrs= github.com/golang-migrate/migrate/v4 v4.7.0/go.mod h1:Qvut3N4xKWjoH3sokBccML6WyHSnggXm/DvMMnTsQIc= github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY= @@ -1243,8 +1245,10 @@ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= -github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +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/v45 v45.2.0 h1:5oRLszbrkvxDDqBCNj2hjDZMKmvexaZ1xw/FCD+K3FI= github.com/google/go-github/v45 v45.2.0/go.mod h1:FObaZJEDSTa/WGCzZ2Z3eoCDXWJKMenWWTrd8jrta28= @@ -1260,7 +1264,6 @@ github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/ github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g= github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= -github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian v2.1.1-0.20190517191504-25dcb96d9e51+incompatible h1:xmapqc1AyLoB+ddYT6r04bD9lIjlOqGaREovi0SzFaE= github.com/google/martian v2.1.1-0.20190517191504-25dcb96d9e51+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= @@ -1377,8 +1380,8 @@ github.com/grafana/grafana-plugin-sdk-go v0.139.0 h1:2RQKM2QpSaWTtaGN6sK+R7LO7zy github.com/grafana/grafana-plugin-sdk-go v0.139.0/go.mod h1:Y+Ps2sesZ62AyCnX+hzrYnyDQYe/ZZl+A8yKLOBm12c= github.com/grafana/prometheus-alertmanager v0.24.1-0.20221012142027-823cd9150293 h1:dJIdfHqu+XjKz+w9zXLqXKPdp6Jjx/UPSOwdeSfWdeQ= github.com/grafana/prometheus-alertmanager v0.24.1-0.20221012142027-823cd9150293/go.mod h1:HVHqK+BVPa/tmL8EMhLCCrPt2a1GdJpEyxr5hgur2UI= -github.com/grafana/saml v0.4.9-0.20230102094056-b61b9eb7c8b7 h1:cujJQ3XV6IK7Y96VpYurd2EpI5rfMRFcuyGqUlk+030= -github.com/grafana/saml v0.4.9-0.20230102094056-b61b9eb7c8b7/go.mod h1:9Zh6dWPtB3MSzTRt8fIFH60Z351QQ+s7hCU3J/tTlA4= +github.com/grafana/saml v0.4.13-0.20230331080031-67cbfa09c7b6 h1:oHn/OOUkECNX06DPHksS7R3UY5Qdye04b/sBj2/OJ5E= +github.com/grafana/saml v0.4.13-0.20230331080031-67cbfa09c7b6/go.mod h1:igEejV+fihTIlHXYP8zOec3V5A8y3lws5bQBFsTm4gA= github.com/grafana/thema v0.0.0-20220817114012-ebeee841c104 h1:dYpwFYIChrMfpq3wDa/ZBxAbUGSW5NYmYBeSezhaoao= github.com/grafana/thema v0.0.0-20220817114012-ebeee841c104/go.mod h1:fCV1rqv6XRQg2GfIQ7pU9zdxd5fLRcEBCnrDVwlK+ZY= github.com/grafana/xorm v0.8.3-0.20220614223926-2fcda7565af6 h1:I9dh1MXGX0wGyxdV/Sl7+ugnki4Dfsy8lv2s5Yf887o= @@ -1704,8 +1707,9 @@ github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFB github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.0.0/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= @@ -1907,6 +1911,7 @@ github.com/moby/sys/mountinfo v0.4.0/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2J github.com/moby/sys/mountinfo v0.4.1/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A= github.com/moby/sys/symlink v0.1.0/go.mod h1:GGDODQmbFOjFsXvfLVn3+ZRxkch54RkSiGqsZeMYowQ= github.com/moby/term v0.0.0-20200312100748-672ec06f55cd/go.mod h1:DdlQx2hp0Ss5/fLikoLlEeIYiATotOjgB//nb973jeo= +github.com/moby/term v0.0.0-20201216013528-df9cb8a40635 h1:rzf0wL0CHVc8CEsgyygG0Mn9CNCCPZqOPaz8RiiHYQk= github.com/moby/term v0.0.0-20201216013528-df9cb8a40635/go.mod h1:FBS0z0QWA44HXygs7VXDUOGoN/1TV3RuWkLO04am3wc= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= @@ -1920,6 +1925,7 @@ github.com/modocache/gover v0.0.0-20171022184752-b58185e213c5/go.mod h1:caMODM3P github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= github.com/montanaflynn/stats v0.6.6/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow= github.com/morikuni/aec v0.0.0-20170113033406-39771216ff4c/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= +github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= github.com/mozilla/tls-observatory v0.0.0-20190404164649-a3c1b6cfecfd/go.mod h1:SrKMQvPiws7F7iqYp8/TX+IhxCYhzr6N/1yb8cwHsGk= github.com/mozillazg/go-cos v0.13.0/go.mod h1:Zp6DvvXn0RUOXGJ2chmWt2bLEqRAnJnS3DnAZsJsoaE= @@ -2224,16 +2230,17 @@ github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFR github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= -github.com/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XFkP+Eg= github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o= +github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rs/cors v1.8.0/go.mod h1:EBwu+T5AvHOcXwvZIkQFjUN6s8Czyqw12GL/Y0tUyRM= github.com/rs/cors v1.8.2 h1:KCooALfAYGs415Cwu5ABvv9n9509fSiG5SQJn/AQo4U= github.com/rs/cors v1.8.2/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU= github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc= -github.com/russellhaering/goxmldsig v1.1.1 h1:vI0r2osGF1A9PLvsGdPUAGwEIrKa4Pj5sesSBsebIxM= -github.com/russellhaering/goxmldsig v1.1.1/go.mod h1:gM4MDENBQf7M+V824SGfyIUVFWydB7n0KkEubVJl+Tw= +github.com/russellhaering/goxmldsig v1.2.0 h1:Y6GTTc9Un5hCxSzVz4UIWQ/zuVwDvzJk80guqzwx6Vg= +github.com/russellhaering/goxmldsig v1.2.0/go.mod h1:gM4MDENBQf7M+V824SGfyIUVFWydB7n0KkEubVJl+Tw= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= @@ -2344,8 +2351,9 @@ github.com/stretchr/objx v0.0.0-20180129172003-8a3f7159479f/go.mod h1:HFkY916IF+ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= -github.com/stretchr/objx v0.4.0 h1:M2gUjqZET1qApGOWNSnZ49BAIMX4F/1plDv3+l31EJ4= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v0.0.0-20151208002404-e3a8ff8ce365/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v0.0.0-20161117074351-18a02ba4a312/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v0.0.0-20180303142811-b89eecf5ca5d/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= @@ -2357,8 +2365,9 @@ github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5 github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= @@ -2503,6 +2512,7 @@ github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43/go.mod h1:aX github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50/go.mod h1:NUSPSUX/bi6SeDMUh6brw0nXpxHnc96TguQh0+r/ssA= github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f/go.mod h1:GlGEuHIJweS1mbCqG+7vt2nvWLzLLnRHbXz5JKd/Qbg= github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= +github.com/zenazn/goji v1.0.1/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= github.com/ziutek/mymysql v1.5.4 h1:GB0qdRGsTwQSBVYuVShFBKaXSnSnYYC2d9knnE1LHFs= github.com/ziutek/mymysql v1.5.4/go.mod h1:LMSpPZ6DbqWFxNCHW77HeMg9I646SAhApZ/wKdgO/C0= gitlab.com/nyarla/go-crypt v0.0.0-20160106005555-d9a5dc2b789b/go.mod h1:T3BPAOm2cqquPa0MKWeNkmOM5RQsRhkrwMWonFMN7fE= @@ -2846,7 +2856,6 @@ golang.org/x/net v0.0.0-20210903162142-ad29c8ab022f/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211020060615-d418f374d309/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211209124913-491a49abca63/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220107192237-5cfca573fb4d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= @@ -3531,6 +3540,7 @@ gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= +gotest.tools/v3 v3.0.3 h1:4AuOwCGf4lLR9u3YOe2awrHygurzhO/HeQ6laiA6Sx0= gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8= honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= @@ -3561,7 +3571,6 @@ k8s.io/api v0.21.0/go.mod h1:+YbrhBBGgsxbF6o6Kj4KJPJnBmAKuXDeS3E18bgHNVU= k8s.io/api v0.21.1/go.mod h1:FstGROTmsSHBarKc8bylzXih8BLNYTiS3TZcsoEDg2s= k8s.io/api v0.22.1/go.mod h1:bh13rkTp3F1XEaLGykbyRD2QaTTzPm0e/BMd8ptFONY= k8s.io/api v0.22.5 h1:xk7C+rMjF/EGELiD560jdmwzrB788mfcHiNbMQLIVI8= -k8s.io/api v0.22.5/go.mod h1:mEhXyLaSD1qTOf40rRiKXkc+2iCem09rWLlFwhCEiAs= k8s.io/apimachinery v0.0.0-20181201231028-18a5ff3097b4/go.mod h1:ccL7Eh7zubPUSh9A3USN90/OzHNSVN6zxzde07TDCL0= k8s.io/apimachinery v0.0.0-20190809020650-423f5d784010/go.mod h1:Waf/xTS2FGRrgXCkO5FP3XxTOWh0qLf2QhL1qFZZ/R8= k8s.io/apimachinery v0.0.0-20191115015347-3c7067801da2/go.mod h1:dXFS2zaQR8fyzuvRdJDHw2Aerij/yVGJSre0bZQSVJA= @@ -3581,7 +3590,6 @@ k8s.io/apimachinery v0.21.0/go.mod h1:jbreFvJo3ov9rj7eWT7+sYiRx+qZuCYXwWT1bcDswP k8s.io/apimachinery v0.21.1/go.mod h1:jbreFvJo3ov9rj7eWT7+sYiRx+qZuCYXwWT1bcDswPY= k8s.io/apimachinery v0.22.1/go.mod h1:O3oNtNadZdeOMxHFVxOreoznohCpy0z6mocxbZr7oJ0= k8s.io/apimachinery v0.22.5 h1:cIPwldOYm1Slq9VLBRPtEYpyhjIm1C6aAMAoENuvN9s= -k8s.io/apimachinery v0.22.5/go.mod h1:xziclGKwuuJ2RM5/rSFQSYAj0zdbci3DH8kj+WvyN0U= k8s.io/apiserver v0.20.1/go.mod h1:ro5QHeQkgMS7ZGpvf4tSMx6bBOgPfE+f52KwvXfScaU= k8s.io/apiserver v0.20.4/go.mod h1:Mc80thBKOyy7tbvFtB4kJv1kbdD0eIH8k8vianJcbFM= k8s.io/apiserver v0.20.6/go.mod h1:QIJXNt6i6JB+0YQRNcS0hdRHJlMhflFmsBDeSgT1r8Q= @@ -3601,6 +3609,7 @@ k8s.io/klog v0.1.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= k8s.io/klog v0.3.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= k8s.io/klog v0.3.1/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= k8s.io/klog v0.4.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I= +k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8= k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I= k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= @@ -3611,7 +3620,6 @@ k8s.io/klog/v2 v2.8.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec= k8s.io/klog/v2 v2.9.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec= k8s.io/klog/v2 v2.10.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec= k8s.io/klog/v2 v2.30.0 h1:bUO6drIvCIsvZ/XFgfxoGFQU/a4Qkh0iAlvUR7vlHJw= -k8s.io/klog/v2 v2.30.0/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= k8s.io/kube-openapi v0.0.0-20190709113604-33be087ad058/go.mod h1:nfDlWeOsu3pUf4yWGL+ERqohP4YsZcBJXWMK+gkzOA4= k8s.io/kube-openapi v0.0.0-20190722073852-5e22f3d471e6/go.mod h1:RZvgC8MSN6DjiMV6oIfEE9pDL9CYXokkfaCKZeHm3nc= k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a/go.mod h1:1TqjTSzOxsLGIKfj0lK8EeCP7K1iUG65v09OM0/WG5E= @@ -3621,7 +3629,6 @@ k8s.io/kube-openapi v0.0.0-20200805222855-6aeccd4b50c6/go.mod h1:UuqjUnNftUyPE5H k8s.io/kube-openapi v0.0.0-20201113171705-d219536bb9fd/go.mod h1:WOJ3KddDSol4tAGcJo0Tvi+dK12EcqSLqcWsryKMpfM= k8s.io/kube-openapi v0.0.0-20210305001622-591a79e4bda7/go.mod h1:wXW5VT87nVfh/iLV8FpR2uDvrFyomxbtb1KivDbvPTE= k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e/go.mod h1:vHXdDvt9+2spS2Rx9ql3I8tycm3H9FDfdUoIuKCefvw= -k8s.io/kube-openapi v0.0.0-20211109043538-20434351676c/go.mod h1:vHXdDvt9+2spS2Rx9ql3I8tycm3H9FDfdUoIuKCefvw= k8s.io/kubernetes v1.13.0/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk= k8s.io/utils v0.0.0-20190809000727-6c36bc71fc4a/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew= k8s.io/utils v0.0.0-20191114200735-6ca3b61696b6/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew= @@ -3629,7 +3636,6 @@ k8s.io/utils v0.0.0-20200414100711-2df71ebbae66/go.mod h1:jPW/WVKK9YHAvNhRxK0md/ k8s.io/utils v0.0.0-20201110183641-67b214c5f920/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= k8s.io/utils v0.0.0-20210707171843-4b05e18ac7d9/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= k8s.io/utils v0.0.0-20210930125809-cb0fa318a74b h1:wxEMGetGMur3J1xuGLQY7GEQYg9bZxKn3tKo5k/eYcs= -k8s.io/utils v0.0.0-20210930125809-cb0fa318a74b/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= nhooyr.io/websocket v1.8.7/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= diff --git a/lerna.json b/lerna.json index 55053d447780b..ac8b674f6956d 100644 --- a/lerna.json +++ b/lerna.json @@ -2,5 +2,5 @@ "npmClient": "yarn", "useWorkspaces": true, "packages": ["packages/*"], - "version": "9.2.13" + "version": "9.2.18" } diff --git a/local/.gitkeep b/local/.gitkeep new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/package.json b/package.json index a1bc43a21b4ef..05d2bcea0e0b5 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "license": "AGPL-3.0-only", "private": true, "name": "grafana", - "version": "9.2.13", + "version": "9.2.18", "repository": "github:grafana/grafana", "scripts": { "api-tests": "jest --notify --watch --config=devenv/e2e-api-tests/jest.js", diff --git a/packages/grafana-data/package.json b/packages/grafana-data/package.json index 7094ba972e430..e9b3e64ed82a0 100644 --- a/packages/grafana-data/package.json +++ b/packages/grafana-data/package.json @@ -2,7 +2,7 @@ "author": "Grafana Labs", "license": "Apache-2.0", "name": "@grafana/data", - "version": "9.2.13", + "version": "9.2.18", "description": "Grafana Data Library", "keywords": [ "typescript" @@ -34,7 +34,7 @@ }, "dependencies": { "@braintree/sanitize-url": "6.0.0", - "@grafana/schema": "9.2.13", + "@grafana/schema": "9.2.18", "@types/d3-interpolate": "^1.4.0", "d3-interpolate": "1.4.0", "date-fns": "2.29.1", diff --git a/packages/grafana-e2e-selectors/package.json b/packages/grafana-e2e-selectors/package.json index 9cf2f69402ad0..8eb70eba09566 100644 --- a/packages/grafana-e2e-selectors/package.json +++ b/packages/grafana-e2e-selectors/package.json @@ -2,7 +2,7 @@ "author": "Grafana Labs", "license": "Apache-2.0", "name": "@grafana/e2e-selectors", - "version": "9.2.13", + "version": "9.2.18", "description": "Grafana End-to-End Test Selectors Library", "keywords": [ "cli", diff --git a/packages/grafana-e2e/package.json b/packages/grafana-e2e/package.json index 4359a8c542a5f..73ca699b2333b 100644 --- a/packages/grafana-e2e/package.json +++ b/packages/grafana-e2e/package.json @@ -2,7 +2,7 @@ "author": "Grafana Labs", "license": "Apache-2.0", "name": "@grafana/e2e", - "version": "9.2.13", + "version": "9.2.18", "description": "Grafana End-to-End Test Library", "keywords": [ "cli", @@ -61,7 +61,7 @@ "@babel/core": "7.19.0", "@babel/preset-env": "7.19.0", "@cypress/webpack-preprocessor": "5.12.0", - "@grafana/e2e-selectors": "9.2.13", + "@grafana/e2e-selectors": "9.2.18", "@grafana/tsconfig": "^1.2.0-rc1", "@mochajs/json-file-reporter": "^1.2.0", "babel-loader": "8.2.5", diff --git a/packages/grafana-runtime/package.json b/packages/grafana-runtime/package.json index 4c40df9a47a9a..0936d23a933f2 100644 --- a/packages/grafana-runtime/package.json +++ b/packages/grafana-runtime/package.json @@ -2,7 +2,7 @@ "author": "Grafana Labs", "license": "Apache-2.0", "name": "@grafana/runtime", - "version": "9.2.13", + "version": "9.2.18", "description": "Grafana Runtime Library", "keywords": [ "grafana", @@ -36,9 +36,9 @@ }, "dependencies": { "@grafana/agent-web": "^0.4.0", - "@grafana/data": "9.2.13", - "@grafana/e2e-selectors": "9.2.13", - "@grafana/ui": "9.2.13", + "@grafana/data": "9.2.18", + "@grafana/e2e-selectors": "9.2.18", + "@grafana/ui": "9.2.18", "@sentry/browser": "6.19.7", "history": "4.10.1", "lodash": "4.17.21", diff --git a/packages/grafana-runtime/src/utils/DataSourceWithBackend.test.ts b/packages/grafana-runtime/src/utils/DataSourceWithBackend.test.ts index d414b934886ec..db69fbebdc3d9 100644 --- a/packages/grafana-runtime/src/utils/DataSourceWithBackend.test.ts +++ b/packages/grafana-runtime/src/utils/DataSourceWithBackend.test.ts @@ -2,16 +2,21 @@ import { of } from 'rxjs'; import { BackendSrv, BackendSrvRequest, FetchResponse } from 'src/services'; import { - DataSourceJsonData, DataQuery, - DataSourceInstanceSettings, DataQueryRequest, DataQueryResponseData, - MutableDataFrame, + DataSourceInstanceSettings, + DataSourceJsonData, DataSourceRef, + MutableDataFrame, } from '@grafana/data'; -import { DataSourceWithBackend, standardStreamOptionsProvider, toStreamingDataResponse } from './DataSourceWithBackend'; +import { + DataSourceWithBackend, + isExpressionReference, + standardStreamOptionsProvider, + toStreamingDataResponse, +} from './DataSourceWithBackend'; class MyDataSource extends DataSourceWithBackend { constructor(instanceSettings: DataSourceInstanceSettings) { @@ -148,6 +153,16 @@ describe('DataSourceWithBackend', () => { obs = toStreamingDataResponse(rsp, request, standardStreamOptionsProvider); expect(obs).toBeDefined(); }); + + describe('isExpressionReference', () => { + test('check all possible expression references', () => { + expect(isExpressionReference('__expr__')).toBeTruthy(); // New UID + expect(isExpressionReference('-100')).toBeTruthy(); // Legacy UID + expect(isExpressionReference('Expression')).toBeTruthy(); // Name + expect(isExpressionReference({ type: '__expr__' })).toBeTruthy(); + expect(isExpressionReference({ type: '-100' })).toBeTruthy(); + }); + }); }); function runQueryAndReturnFetchMock( diff --git a/packages/grafana-runtime/src/utils/DataSourceWithBackend.ts b/packages/grafana-runtime/src/utils/DataSourceWithBackend.ts index bb9b75d1282d6..1b1376f3bdfc5 100644 --- a/packages/grafana-runtime/src/utils/DataSourceWithBackend.ts +++ b/packages/grafana-runtime/src/utils/DataSourceWithBackend.ts @@ -44,8 +44,8 @@ export function isExpressionReference(ref?: DataSourceRef | string | null): bool if (!ref) { return false; } - const v = (ref as any).type ?? ref; - return v === ExpressionDatasourceRef.type || v === '-100'; // -100 was a legacy accident that should be removed + const v = typeof ref === 'string' ? ref : ref.type; + return v === ExpressionDatasourceRef.type || v === ExpressionDatasourceRef.name || v === '-100'; // -100 was a legacy accident that should be removed } export class HealthCheckError extends Error { diff --git a/packages/grafana-schema/package.json b/packages/grafana-schema/package.json index 573b5a6c811b6..2b265ef9864d5 100644 --- a/packages/grafana-schema/package.json +++ b/packages/grafana-schema/package.json @@ -2,7 +2,7 @@ "author": "Grafana Labs", "license": "Apache-2.0", "name": "@grafana/schema", - "version": "9.2.13", + "version": "9.2.18", "description": "Grafana Schema Library", "keywords": [ "typescript" diff --git a/packages/grafana-toolkit/package.json b/packages/grafana-toolkit/package.json index 8ab3f44242b12..9d867393ce0b6 100644 --- a/packages/grafana-toolkit/package.json +++ b/packages/grafana-toolkit/package.json @@ -2,7 +2,7 @@ "author": "Grafana Labs", "license": "Apache-2.0", "name": "@grafana/toolkit", - "version": "9.2.13", + "version": "9.2.18", "description": "Grafana Toolkit", "keywords": [ "grafana", @@ -50,10 +50,10 @@ "@babel/preset-env": "7.18.9", "@babel/preset-react": "7.18.6", "@babel/preset-typescript": "7.18.6", - "@grafana/data": "9.2.13", + "@grafana/data": "9.2.18", "@grafana/eslint-config": "5.0.0", "@grafana/tsconfig": "^1.2.0-rc1", - "@grafana/ui": "9.2.13", + "@grafana/ui": "9.2.18", "@jest/core": "27.5.1", "@types/command-exists": "^1.2.0", "@types/eslint": "8.4.1", diff --git a/packages/grafana-ui/package.json b/packages/grafana-ui/package.json index 4285fe7147350..549ec6cee170e 100644 --- a/packages/grafana-ui/package.json +++ b/packages/grafana-ui/package.json @@ -2,7 +2,7 @@ "author": "Grafana Labs", "license": "Apache-2.0", "name": "@grafana/ui", - "version": "9.2.13", + "version": "9.2.18", "description": "Grafana Components Library", "keywords": [ "grafana", @@ -47,9 +47,9 @@ "dependencies": { "@emotion/css": "11.9.0", "@emotion/react": "11.9.3", - "@grafana/data": "9.2.13", - "@grafana/e2e-selectors": "9.2.13", - "@grafana/schema": "9.2.13", + "@grafana/data": "9.2.18", + "@grafana/e2e-selectors": "9.2.18", + "@grafana/schema": "9.2.18", "@monaco-editor/react": "4.4.5", "@popperjs/core": "2.11.5", "@react-aria/button": "3.6.1", diff --git a/packages/grafana-ui/src/components/Icon/iconBundle.ts b/packages/grafana-ui/src/components/Icon/iconBundle.ts index 56831148efcf5..46c97dcf81730 100644 --- a/packages/grafana-ui/src/components/Icon/iconBundle.ts +++ b/packages/grafana-ui/src/components/Icon/iconBundle.ts @@ -179,34 +179,35 @@ import u1168 from '../../../../../public/img/icons/mono/percona-dashboard.svg'; import u1169 from '../../../../../public/img/icons/mono/percona-database-checks.svg'; import u1170 from '../../../../../public/img/icons/mono/percona-database.svg'; import u1171 from '../../../../../public/img/icons/mono/percona-disk.svg'; -import u1173 from '../../../../../public/img/icons/mono/percona-kubernetes.svg'; -import u1174 from '../../../../../public/img/icons/mono/percona-memory.svg'; -import u1175 from '../../../../../public/img/icons/mono/percona-network.svg'; -import u1176 from '../../../../../public/img/icons/mono/percona-process.svg'; -import u1177 from '../../../../../public/img/icons/mono/percona-setting.svg'; -import u1178 from '../../../../../public/img/icons/mono/percona-summary.svg'; -import u1179 from '../../../../../public/img/icons/mono/percona-surface.svg'; -import u1180 from '../../../../../public/img/icons/mono/percona-temperature.svg'; -import u1181 from '../../../../../public/img/icons/mono/pmm-logo.svg'; -import u1182 from '../../../../../public/img/icons/mono/pmm-logo-light.svg'; -import u1183 from '../../../../../public/img/icons/mono/qan-logo.svg'; -import u1184 from '../../../../../public/img/icons/mono/percona-system.svg'; -import u1185 from '../../../../../public/img/icons/mono/percona-nav-overview.svg'; -import u1186 from '../../../../../public/img/icons/mono/percona-nav-summary.svg'; -import u1187 from '../../../../../public/img/icons/mono/percona-database-mysql.svg'; -import u1188 from '../../../../../public/img/icons/mono/percona-database-postgresql.svg'; -import u1189 from '../../../../../public/img/icons/mono/percona-database-mongodb.svg'; -import u1190 from '../../../../../public/img/icons/mono/percona-database-proxysql.svg'; -import u1191 from '../../../../../public/img/icons/mono/percona-database-haproxy.svg'; -import u1192 from '../../../../../public/img/icons/mono/percona-bell.svg'; -import u1193 from '../../../../../public/img/icons/mono/percona-bell-slash.svg'; -import u1194 from '../../../../../public/img/icons/unicons/ticket.svg'; -import u1195 from '../../../../../public/img/icons/unicons/cloud.svg'; -import u1196 from '../../../../../public/img/icons/unicons/angle-double-left.svg'; -import u1197 from '../../../../../public/img/icons/unicons/times-circle.svg'; -import u1198 from '../../../../../public/img/icons/mono/percona-asterisk.svg'; -import u1199 from '../../../../../public/img/icons/unicons/user-check.svg'; -import u1200 from '../../../../../public/img/icons/unicons/user-square.svg'; +import u1172 from '../../../../../public/img/icons/mono/percona-kubernetes.svg'; +import u1173 from '../../../../../public/img/icons/mono/percona-memory.svg'; +import u1174 from '../../../../../public/img/icons/mono/percona-network.svg'; +import u1175 from '../../../../../public/img/icons/mono/percona-process.svg'; +import u1176 from '../../../../../public/img/icons/mono/percona-setting.svg'; +import u1177 from '../../../../../public/img/icons/mono/percona-summary.svg'; +import u1178 from '../../../../../public/img/icons/mono/percona-surface.svg'; +import u1179 from '../../../../../public/img/icons/mono/percona-temperature.svg'; +import u1180 from '../../../../../public/img/icons/mono/pmm-logo.svg'; +import u1181 from '../../../../../public/img/icons/mono/pmm-logo-light.svg'; +import u1182 from '../../../../../public/img/icons/mono/qan-logo.svg'; +import u1183 from '../../../../../public/img/icons/mono/percona-system.svg'; +import u1184 from '../../../../../public/img/icons/mono/percona-nav-overview.svg'; +import u1185 from '../../../../../public/img/icons/mono/percona-nav-summary.svg'; +import u1186 from '../../../../../public/img/icons/mono/percona-database-mysql.svg'; +import u1187 from '../../../../../public/img/icons/mono/percona-database-postgresql.svg'; +import u1188 from '../../../../../public/img/icons/mono/percona-database-mongodb.svg'; +import u1189 from '../../../../../public/img/icons/mono/percona-database-proxysql.svg'; +import u1190 from '../../../../../public/img/icons/mono/percona-database-haproxy.svg'; +import u1191 from '../../../../../public/img/icons/mono/percona-bell.svg'; +import u1192 from '../../../../../public/img/icons/mono/percona-bell-slash.svg'; +import u1193 from '../../../../../public/img/icons/unicons/ticket.svg'; +import u1194 from '../../../../../public/img/icons/unicons/cloud.svg'; +import u1195 from '../../../../../public/img/icons/unicons/angle-double-left.svg'; +import u1196 from '../../../../../public/img/icons/unicons/times-circle.svg'; +import u1197 from '../../../../../public/img/icons/mono/percona-asterisk.svg'; +import u1198 from '../../../../../public/img/icons/unicons/user-check.svg'; +import u1199 from '../../../../../public/img/icons/unicons/user-square.svg'; +import u1200 from '../../../../../public/img/icons/unicons/record-audio.svg'; // do not edit this list directly // the list of icons live here: @grafana/ui/components/Icon/cached.json @@ -401,34 +402,35 @@ export function initIconCache() { cacheItem(u1169, 'mono/percona-database-checks.svg'); cacheItem(u1170, 'mono/percona-database.svg'); cacheItem(u1171, 'mono/percona-disk.svg'); - cacheItem(u1173, 'mono/percona-kubernetes.svg'); - cacheItem(u1174, 'mono/percona-memory.svg'); - cacheItem(u1175, 'mono/percona-network.svg'); - cacheItem(u1176, 'mono/percona-process.svg'); - cacheItem(u1177, 'mono/percona-setting.svg'); - cacheItem(u1178, 'mono/percona-summary.svg'); - cacheItem(u1179, 'mono/percona-surface.svg'); - cacheItem(u1180, 'mono/percona-temperature.svg'); - cacheItem(u1181, 'mono/pmm-logo.svg'); - cacheItem(u1182, 'mono/pmm-logo-light.svg'); - cacheItem(u1183, 'mono/qan-logo.svg'); - cacheItem(u1184, 'mono/percona-system.svg'); - cacheItem(u1185, 'mono/percona-nav-overview.svg'); - cacheItem(u1186, 'mono/percona-nav-summary.svg'); - cacheItem(u1187, 'mono/percona-database-mysql.svg'); - cacheItem(u1188, 'mono/percona-database-postgresql.svg'); - cacheItem(u1189, 'mono/percona-database-mongodb.svg'); - cacheItem(u1190, 'mono/percona-database-proxysql.svg'); - cacheItem(u1191, 'mono/percona-database-haproxy.svg'); - cacheItem(u1192, 'mono/percona-bell.svg'); - cacheItem(u1193, 'mono/percona-bell-slash.svg'); - cacheItem(u1194, 'unicons/ticket.svg'); - cacheItem(u1195, 'unicons/cloud.svg'); - cacheItem(u1196, 'unicons/angle-double-left.svg'); - cacheItem(u1197, 'unicons/times-circle.svg'); - cacheItem(u1198, 'mono/percona-asterisk.svg'); - cacheItem(u1199, 'unicons/user-check.svg'); - cacheItem(u1200, 'unicons/user-square.svg'); + cacheItem(u1172, 'mono/percona-kubernetes.svg'); + cacheItem(u1173, 'mono/percona-memory.svg'); + cacheItem(u1174, 'mono/percona-network.svg'); + cacheItem(u1175, 'mono/percona-process.svg'); + cacheItem(u1176, 'mono/percona-setting.svg'); + cacheItem(u1177, 'mono/percona-summary.svg'); + cacheItem(u1178, 'mono/percona-surface.svg'); + cacheItem(u1179, 'mono/percona-temperature.svg'); + cacheItem(u1180, 'mono/pmm-logo.svg'); + cacheItem(u1181, 'mono/pmm-logo-light.svg'); + cacheItem(u1182, 'mono/qan-logo.svg'); + cacheItem(u1183, 'mono/percona-system.svg'); + cacheItem(u1184, 'mono/percona-nav-overview.svg'); + cacheItem(u1185, 'mono/percona-nav-summary.svg'); + cacheItem(u1186, 'mono/percona-database-mysql.svg'); + cacheItem(u1187, 'mono/percona-database-postgresql.svg'); + cacheItem(u1188, 'mono/percona-database-mongodb.svg'); + cacheItem(u1189, 'mono/percona-database-proxysql.svg'); + cacheItem(u1190, 'mono/percona-database-haproxy.svg'); + cacheItem(u1191, 'mono/percona-bell.svg'); + cacheItem(u1192, 'mono/percona-bell-slash.svg'); + cacheItem(u1193, 'unicons/ticket.svg'); + cacheItem(u1194, 'unicons/cloud.svg'); + cacheItem(u1195, 'unicons/angle-double-left.svg'); + cacheItem(u1196, 'unicons/times-circle.svg'); + cacheItem(u1197, 'mono/percona-asterisk.svg'); + cacheItem(u1198, 'unicons/user-check.svg'); + cacheItem(u1199, 'unicons/user-square.svg'); + cacheItem(u1200, 'unicons/record-audio.svg'); // do not edit this list directly // the list of icons live here: @grafana/ui/components/Icon/cached.json } diff --git a/packages/jaeger-ui-components/package.json b/packages/jaeger-ui-components/package.json index 32cdb1f697b19..f15967054066d 100644 --- a/packages/jaeger-ui-components/package.json +++ b/packages/jaeger-ui-components/package.json @@ -1,6 +1,6 @@ { "name": "@jaegertracing/jaeger-ui-components", - "version": "9.2.13", + "version": "9.2.18", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -31,10 +31,10 @@ }, "dependencies": { "@emotion/css": "11.9.0", - "@grafana/data": "9.2.13", - "@grafana/e2e-selectors": "9.2.13", - "@grafana/runtime": "9.2.13", - "@grafana/ui": "9.2.13", + "@grafana/data": "9.2.18", + "@grafana/e2e-selectors": "9.2.18", + "@grafana/runtime": "9.2.18", + "@grafana/ui": "9.2.18", "chance": "^1.0.10", "classnames": "^2.2.5", "combokeys": "^3.0.0", diff --git a/packaging/docker/Dockerfile b/packaging/docker/Dockerfile deleted file mode 100644 index 7acefcc0b5af1..0000000000000 --- a/packaging/docker/Dockerfile +++ /dev/null @@ -1,75 +0,0 @@ -ARG BASE_IMAGE=alpine:3.15 -FROM ${BASE_IMAGE} - -ARG GRAFANA_TGZ="grafana-latest.linux-x64-musl.tar.gz" - -# Make sure we have Gnu tar -RUN apk add --no-cache tar - -COPY ${GRAFANA_TGZ} /tmp/grafana.tar.gz - -# Change to tar xfzv to make tar print every file it extracts -RUN mkdir /tmp/grafana && tar xzf /tmp/grafana.tar.gz --strip-components=1 -C /tmp/grafana - -FROM ${BASE_IMAGE} - -ARG GF_UID="472" -ARG GF_GID="0" - -ENV PATH=/usr/share/grafana/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin \ - GF_PATHS_CONFIG="/etc/grafana/grafana.ini" \ - GF_PATHS_DATA="/var/lib/grafana" \ - GF_PATHS_HOME="/usr/share/grafana" \ - GF_PATHS_LOGS="/var/log/grafana" \ - GF_PATHS_PLUGINS="/var/lib/grafana/plugins" \ - GF_PATHS_PROVISIONING="/etc/grafana/provisioning" - -WORKDIR $GF_PATHS_HOME - -RUN apk add --no-cache ca-certificates bash tzdata musl-utils -RUN apk info -vv | sort - -# Oracle Support for x86_64 only -RUN if [ `arch` = "x86_64" ]; then \ - wget https://github.com/sgerrand/alpine-pkg-glibc/releases/download/2.35-r0/glibc-2.35-r0.apk \ - -O /tmp/glibc-2.35-r0.apk && \ - wget https://github.com/sgerrand/alpine-pkg-glibc/releases/download/2.35-r0/glibc-bin-2.35-r0.apk \ - -O /tmp/glibc-bin-2.35-r0.apk && \ - apk add --no-cache --allow-untrusted /tmp/glibc-2.35-r0.apk /tmp/glibc-bin-2.35-r0.apk && \ - rm -f /lib64/ld-linux-x86-64.so.2 && \ - ln -s /usr/glibc-compat/lib64/ld-linux-x86-64.so.2 /lib64/ld-linux-x86-64.so.2 && \ - rm -f /tmp/glibc-2.35-r0.apk && \ - rm -f /tmp/glibc-bin-2.35-r0.apk && \ - rm -f /lib/ld-linux-x86-64.so.2 && \ - rm -f /etc/ld.so.cache; \ - fi - -COPY --from=0 /tmp/grafana "$GF_PATHS_HOME" - -RUN if [ ! $(getent group "$GF_GID") ]; then \ - addgroup -S -g $GF_GID grafana; \ - fi - -RUN export GF_GID_NAME=$(getent group $GF_GID | cut -d':' -f1) && \ - mkdir -p "$GF_PATHS_HOME/.aws" && \ - adduser -S -u $GF_UID -G "$GF_GID_NAME" grafana && \ - mkdir -p "$GF_PATHS_PROVISIONING/datasources" \ - "$GF_PATHS_PROVISIONING/dashboards" \ - "$GF_PATHS_PROVISIONING/notifiers" \ - "$GF_PATHS_PROVISIONING/plugins" \ - "$GF_PATHS_PROVISIONING/access-control" \ - "$GF_PATHS_PROVISIONING/alerting" \ - "$GF_PATHS_LOGS" \ - "$GF_PATHS_PLUGINS" \ - "$GF_PATHS_DATA" && \ - cp "$GF_PATHS_HOME/conf/sample.ini" "$GF_PATHS_CONFIG" && \ - cp "$GF_PATHS_HOME/conf/ldap.toml" /etc/grafana/ldap.toml && \ - chown -R "grafana:$GF_GID_NAME" "$GF_PATHS_DATA" "$GF_PATHS_HOME/.aws" "$GF_PATHS_LOGS" "$GF_PATHS_PLUGINS" "$GF_PATHS_PROVISIONING" && \ - chmod -R 777 "$GF_PATHS_DATA" "$GF_PATHS_HOME/.aws" "$GF_PATHS_LOGS" "$GF_PATHS_PLUGINS" "$GF_PATHS_PROVISIONING" - -EXPOSE 3000 - -COPY ./run.sh /run.sh - -USER "$GF_UID" -ENTRYPOINT [ "/run.sh" ] diff --git a/packaging/docker/build-enterprise.sh b/packaging/docker/build-enterprise.sh deleted file mode 100755 index a55696c4cef6b..0000000000000 --- a/packaging/docker/build-enterprise.sh +++ /dev/null @@ -1,59 +0,0 @@ -#!/bin/sh -set -e - -UBUNTU_BASE=0 - -while [ "$1" != "" ]; do - case "$1" in - "--ubuntu") - UBUNTU_BASE=1 - echo "Ubuntu base image enabled" - shift - ;; - * ) - # unknown param causes args to be passed through to $@ - break - ;; - esac -done - -_raw_grafana_tag=$1 -_docker_repo=${2:-grafana/grafana-enterprise} - -if echo "$_raw_grafana_tag" | grep -q "^v"; then - _grafana_tag=$(echo "${_raw_grafana_tag}" | cut -d "v" -f 2) -elif echo "$_raw_grafana_tag" | grep -q "^main-"; then - _grafana_tag="main" -else - _grafana_tag="${_raw_grafana_tag}" -fi - -if [ ${UBUNTU_BASE} = "0" ]; then - TAG_SUFFIX="" - DOCKERFILE="Dockerfile" -else - TAG_SUFFIX="-ubuntu" - DOCKERFILE="ubuntu.Dockerfile" -fi - -echo "Building and deploying ${_docker_repo}:${_grafana_tag}${TAG_SUFFIX}" - -docker build \ - --tag "${_docker_repo}:${_grafana_tag}${TAG_SUFFIX}" \ - --no-cache=true \ - -f ${DOCKERFILE} \ - . - -docker push "${_docker_repo}:${_grafana_tag}${TAG_SUFFIX}" - -if echo "$_raw_grafana_tag" | grep -q "^v" && echo "$_raw_grafana_tag" | grep -qv "beta"; then - docker tag "${_docker_repo}:${_grafana_tag}${TAG_SUFFIX}" "${_docker_repo}:latest${TAG_SUFFIX}" - docker push "${_docker_repo}:latest${TAG_SUFFIX}" -fi - - -if echo "${_raw_grafana_tag}" | grep -q "^main-" && [ ${UBUNTU_BASE} = "1" ]; then - docker tag "${_docker_repo}:${_grafana_tag}${TAG_SUFFIX}" "grafana/grafana-enterprise-dev:${_raw_grafana_tag}" - docker push "grafana/grafana-enterprise-dev:${_raw_grafana_tag}" -fi - diff --git a/packaging/docker/build.sh b/packaging/docker/build.sh index 533284ac8afd2..10e60888c2fd7 100755 --- a/packaging/docker/build.sh +++ b/packaging/docker/build.sh @@ -28,7 +28,7 @@ done _grafana_tag=${1:-} _docker_repo=${2:-grafana/grafana} -# If the tag starts with v, treat this as a official release +# If the tag starts with v, treat this as an official release if echo "$_grafana_tag" | grep -q "^v"; then _grafana_version=$(echo "${_grafana_tag}" | cut -d "v" -f 2) else @@ -59,23 +59,25 @@ docker_build () { esac if [ $UBUNTU_BASE = "0" ]; then libc="-musl" - dockerfile="Dockerfile" - base_image="${base_arch}alpine:3.15" + base_image="${base_arch}alpine:3.17" else libc="" - dockerfile="ubuntu.Dockerfile" base_image="${base_arch}ubuntu:20.04" fi - grafana_tgz="grafana-latest.linux-${arch}${libc}.tar.gz" + grafana_tgz=${GRAFANA_TGZ:-"grafana-latest.linux-${arch}${libc}.tar.gz"} tag="${_docker_repo}${repo_arch}:${_grafana_version}${TAG_SUFFIX}" + DOCKER_BUILDKIT=1 \ docker build \ --build-arg BASE_IMAGE=${base_image} \ --build-arg GRAFANA_TGZ=${grafana_tgz} \ + --build-arg GO_SRC=tgz-builder \ + --build-arg JS_SRC=tgz-builder \ + --build-arg RUN_SH=./run.sh \ --tag "${tag}" \ --no-cache=true \ - -f "${dockerfile}" \ + --file ../../Dockerfile \ . } diff --git a/packaging/docker/custom/Dockerfile b/packaging/docker/custom/Dockerfile index 0bfed47c44c8e..3a4c6aa1bbdc2 100644 --- a/packaging/docker/custom/Dockerfile +++ b/packaging/docker/custom/Dockerfile @@ -1,51 +1,56 @@ -ARG GRAFANA_VERSION="latest" - -FROM grafana/grafana:${GRAFANA_VERSION} - -USER root - -ARG GF_INSTALL_IMAGE_RENDERER_PLUGIN="false" - -ARG GF_GID="0" -ENV GF_PATHS_PLUGINS="/var/lib/grafana-plugins" - -RUN mkdir -p "$GF_PATHS_PLUGINS" && \ - chown -R grafana:${GF_GID} "$GF_PATHS_PLUGINS" - -RUN if [ $GF_INSTALL_IMAGE_RENDERER_PLUGIN = "true" ]; then \ - echo "http://dl-cdn.alpinelinux.org/alpine/edge/community" >> /etc/apk/repositories && \ - echo "http://dl-cdn.alpinelinux.org/alpine/edge/main" >> /etc/apk/repositories && \ - echo "http://dl-cdn.alpinelinux.org/alpine/edge/testing" >> /etc/apk/repositories && \ - apk --no-cache upgrade && \ - apk add --no-cache udev ttf-opensans chromium && \ - rm -rf /tmp/* && \ - rm -rf /usr/share/grafana/tools/phantomjs; \ -fi - -USER grafana - -ENV GF_PLUGIN_RENDERING_CHROME_BIN="/usr/bin/chromium-browser" - -RUN if [ $GF_INSTALL_IMAGE_RENDERER_PLUGIN = "true" ]; then \ - grafana-cli \ - --pluginsDir "$GF_PATHS_PLUGINS" \ - --pluginUrl https://github.com/grafana/grafana-image-renderer/releases/latest/download/plugin-linux-x64-glibc-no-chromium.zip \ - plugins install grafana-image-renderer; \ -fi - -ARG GF_INSTALL_PLUGINS="" - -RUN if [ ! -z "${GF_INSTALL_PLUGINS}" ]; then \ - OLDIFS=$IFS; \ - IFS=','; \ - for plugin in ${GF_INSTALL_PLUGINS}; do \ - IFS=$OLDIFS; \ - if expr match "$plugin" '.*\;.*'; then \ - pluginUrl=$(echo "$plugin" | cut -d';' -f 1); \ - pluginInstallFolder=$(echo "$plugin" | cut -d';' -f 2); \ - grafana-cli --pluginUrl ${pluginUrl} --pluginsDir "${GF_PATHS_PLUGINS}" plugins install "${pluginInstallFolder}"; \ - else \ - grafana-cli --pluginsDir "${GF_PATHS_PLUGINS}" plugins install ${plugin}; \ - fi \ - done \ -fi +ARG GRAFANA_VERSION="latest" + +FROM grafana/grafana:${GRAFANA_VERSION} + +ARG GF_INSTALL_IMAGE_RENDERER_PLUGIN="false" + +ARG GF_GID="0" + +ENV GF_PATHS_PLUGINS="/var/lib/grafana-plugins" +ENV GF_PLUGIN_RENDERING_CHROME_BIN="/usr/bin/chrome" + +USER root + +RUN mkdir -p "$GF_PATHS_PLUGINS" && \ + chown -R grafana:${GF_GID} "$GF_PATHS_PLUGINS" && \ + if [ $GF_INSTALL_IMAGE_RENDERER_PLUGIN = "true" ]; then \ + if grep -i -q alpine /etc/issue; then \ + apk add --no-cache udev ttf-opensans chromium && \ + ln -s /usr/bin/chromium-browser "$GF_PLUGIN_RENDERING_CHROME_BIN"; \ + else \ + cd /tmp && \ + curl -sLO https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb && \ + DEBIAN_FRONTEND=noninteractive && \ + apt-get update -q && \ + apt-get install -q -y ./google-chrome-stable_current_amd64.deb && \ + rm -rf /var/lib/apt/lists/* && \ + rm ./google-chrome-stable_current_amd64.deb && \ + ln -s /usr/bin/google-chrome "$GF_PLUGIN_RENDERING_CHROME_BIN"; \ + fi \ + fi + +USER grafana + +RUN if [ $GF_INSTALL_IMAGE_RENDERER_PLUGIN = "true" ]; then \ + grafana-cli \ + --pluginsDir "$GF_PATHS_PLUGINS" \ + --pluginUrl https://github.com/grafana/grafana-image-renderer/releases/latest/download/plugin-linux-x64-glibc-no-chromium.zip \ + plugins install grafana-image-renderer; \ + fi + +ARG GF_INSTALL_PLUGINS="" + +RUN if [ ! -z "${GF_INSTALL_PLUGINS}" ]; then \ + OLDIFS=$IFS; \ + IFS=','; \ + for plugin in ${GF_INSTALL_PLUGINS}; do \ + IFS=$OLDIFS; \ + if expr match "$plugin" '.*\;.*'; then \ + pluginUrl=$(echo "$plugin" | cut -d';' -f 1); \ + pluginInstallFolder=$(echo "$plugin" | cut -d';' -f 2); \ + grafana-cli --pluginUrl ${pluginUrl} --pluginsDir "${GF_PATHS_PLUGINS}" plugins install "${pluginInstallFolder}"; \ + else \ + grafana-cli --pluginsDir "${GF_PATHS_PLUGINS}" plugins install ${plugin}; \ + fi \ + done \ + fi diff --git a/packaging/docker/custom/ubuntu.Dockerfile b/packaging/docker/custom/ubuntu.Dockerfile deleted file mode 100644 index 470ec50e6ab25..0000000000000 --- a/packaging/docker/custom/ubuntu.Dockerfile +++ /dev/null @@ -1,55 +0,0 @@ -ARG GRAFANA_VERSION="latest" - -FROM grafana/grafana:${GRAFANA_VERSION}-ubuntu - -USER root - -# Set DEBIAN_FRONTEND=noninteractive in environment at build-time -ARG DEBIAN_FRONTEND=noninteractive - -ARG GF_INSTALL_IMAGE_RENDERER_PLUGIN="false" - -ARG GF_GID="0" -ENV GF_PATHS_PLUGINS="/var/lib/grafana-plugins" - -RUN mkdir -p "$GF_PATHS_PLUGINS" && \ - chown -R grafana:${GF_GID} "$GF_PATHS_PLUGINS" - -RUN if [ $GF_INSTALL_IMAGE_RENDERER_PLUGIN = "true" ]; then \ - apt-get update && \ - apt-get upgrade -y && \ - apt-get install -y gdebi-core && \ - cd /tmp && \ - curl -LO https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb && \ - gdebi --n google-chrome-stable_current_amd64.deb && \ - apt-get autoremove -y && \ - rm -rf /var/lib/apt/lists/*; \ -fi - -USER grafana - -ENV GF_PLUGIN_RENDERING_CHROME_BIN="/usr/bin/google-chrome" - -RUN if [ $GF_INSTALL_IMAGE_RENDERER_PLUGIN = "true" ]; then \ - grafana-cli \ - --pluginsDir "$GF_PATHS_PLUGINS" \ - --pluginUrl https://github.com/grafana/grafana-image-renderer/releases/latest/download/plugin-linux-x64-glibc-no-chromium.zip \ - plugins install grafana-image-renderer; \ -fi - -ARG GF_INSTALL_PLUGINS="" - -RUN if [ ! -z "${GF_INSTALL_PLUGINS}" ]; then \ - OLDIFS=$IFS; \ - IFS=','; \ - for plugin in ${GF_INSTALL_PLUGINS}; do \ - IFS=$OLDIFS; \ - if expr match "$plugin" '.*\;.*'; then \ - pluginUrl=$(echo "$plugin" | cut -d';' -f 1); \ - pluginInstallFolder=$(echo "$plugin" | cut -d';' -f 2); \ - grafana-cli --pluginUrl ${pluginUrl} --pluginsDir "${GF_PATHS_PLUGINS}" plugins install "${pluginInstallFolder}"; \ - else \ - grafana-cli --pluginsDir "${GF_PATHS_PLUGINS}" plugins install ${plugin}; \ - fi \ - done \ -fi diff --git a/packaging/docker/push_to_docker_hub.sh b/packaging/docker/push_to_docker_hub.sh index 09f483965dee1..cd5a8fd548c7f 100755 --- a/packaging/docker/push_to_docker_hub.sh +++ b/packaging/docker/push_to_docker_hub.sh @@ -24,18 +24,18 @@ _docker_repo=${2:-grafana/grafana} # If the tag starts with v, treat this as an official release if echo "$_grafana_tag" | grep -q "^v"; then - _grafana_version=$(echo "${_grafana_tag}" | cut -d "v" -f 2) + _grafana_version=$(echo "${_grafana_tag}" | cut -d "v" -f 2) else - _grafana_version=$_grafana_tag + _grafana_version=$_grafana_tag fi -export DOCKER_CLI_EXPERIMENTAL=enabled - echo "pushing ${_docker_repo}:${_grafana_version}${TAG_SUFFIX}" +export DOCKER_CLI_EXPERIMENTAL=enabled + docker_push_all () { - repo=$1 - tag=$2 + repo=$1 + tag=$2 # Push each image individually docker push "${repo}:${tag}${TAG_SUFFIX}" @@ -52,18 +52,18 @@ docker_push_all () { } if echo "$_grafana_tag" | grep -q "^v" && echo "$_grafana_tag" | grep -vq "beta"; then - echo "pushing ${_docker_repo}:latest${TAG_SUFFIX}" - docker_push_all "${_docker_repo}" "latest" - docker_push_all "${_docker_repo}" "${_grafana_version}" - # Push to the grafana-dev repository with the expected tag - # for running the end to end tests successfully + echo "pushing ${_docker_repo}:latest${TAG_SUFFIX}" + docker_push_all "${_docker_repo}" "latest" + docker_push_all "${_docker_repo}" "${_grafana_version}" + # Push to the grafana-dev repository with the expected tag + # for running the end to end tests successfully docker push "grafana/grafana-dev:${_grafana_tag}${TAG_SUFFIX}" elif echo "$_grafana_tag" | grep -q "^v" && echo "$_grafana_tag" | grep -q "beta"; then - docker_push_all "${_docker_repo}" "${_grafana_version}" - # Push to the grafana-dev repository with the expected tag - # for running the end to end tests successfully + docker_push_all "${_docker_repo}" "${_grafana_version}" + # Push to the grafana-dev repository with the expected tag + # for running the end to end tests successfully docker push "grafana/grafana-dev:${_grafana_tag}${TAG_SUFFIX}" elif echo "$_grafana_tag" | grep -q "main"; then - docker_push_all "${_docker_repo}" "main" + docker_push_all "${_docker_repo}" "main" docker push "grafana/grafana-dev:${_grafana_version}${TAG_SUFFIX}" fi diff --git a/packaging/docker/ubuntu.Dockerfile b/packaging/docker/ubuntu.Dockerfile deleted file mode 100644 index c4bc984edf67d..0000000000000 --- a/packaging/docker/ubuntu.Dockerfile +++ /dev/null @@ -1,60 +0,0 @@ -ARG BASE_IMAGE=ubuntu:20.04 -FROM ${BASE_IMAGE} AS grafana-builder - -ARG GRAFANA_TGZ="grafana-latest.linux-x64.tar.gz" - -COPY ${GRAFANA_TGZ} /tmp/grafana.tar.gz - -RUN mkdir /tmp/grafana && tar xzf /tmp/grafana.tar.gz --strip-components=1 -C /tmp/grafana - -FROM ${BASE_IMAGE} - -EXPOSE 3000 - -# Set DEBIAN_FRONTEND=noninteractive in environment at build-time -ARG DEBIAN_FRONTEND=noninteractive -ARG GF_UID="472" -ARG GF_GID="0" - -ENV PATH=/usr/share/grafana/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin \ - GF_PATHS_CONFIG="/etc/grafana/grafana.ini" \ - GF_PATHS_DATA="/var/lib/grafana" \ - GF_PATHS_HOME="/usr/share/grafana" \ - GF_PATHS_LOGS="/var/log/grafana" \ - GF_PATHS_PLUGINS="/var/lib/grafana/plugins" \ - GF_PATHS_PROVISIONING="/etc/grafana/provisioning" - -WORKDIR $GF_PATHS_HOME - -# Install dependencies -# We need curl in the image -RUN apt-get update && apt-get install -y ca-certificates curl tzdata && \ - apt-get autoremove -y && rm -rf /var/lib/apt/lists/*; - -COPY --from=grafana-builder /tmp/grafana "$GF_PATHS_HOME" - -RUN if [ ! $(getent group "$GF_GID") ]; then \ - addgroup --system --gid $GF_GID grafana; \ - fi - -RUN export GF_GID_NAME=$(getent group $GF_GID | cut -d':' -f1) && \ - mkdir -p "$GF_PATHS_HOME/.aws" && \ - adduser --system --uid $GF_UID --ingroup "$GF_GID_NAME" grafana && \ - mkdir -p "$GF_PATHS_PROVISIONING/datasources" \ - "$GF_PATHS_PROVISIONING/dashboards" \ - "$GF_PATHS_PROVISIONING/notifiers" \ - "$GF_PATHS_PROVISIONING/plugins" \ - "$GF_PATHS_PROVISIONING/access-control" \ - "$GF_PATHS_PROVISIONING/alerting" \ - "$GF_PATHS_LOGS" \ - "$GF_PATHS_PLUGINS" \ - "$GF_PATHS_DATA" && \ - cp "$GF_PATHS_HOME/conf/sample.ini" "$GF_PATHS_CONFIG" && \ - cp "$GF_PATHS_HOME/conf/ldap.toml" /etc/grafana/ldap.toml && \ - chown -R "grafana:$GF_GID_NAME" "$GF_PATHS_DATA" "$GF_PATHS_HOME/.aws" "$GF_PATHS_LOGS" "$GF_PATHS_PLUGINS" "$GF_PATHS_PROVISIONING" && \ - chmod -R 777 "$GF_PATHS_DATA" "$GF_PATHS_HOME/.aws" "$GF_PATHS_LOGS" "$GF_PATHS_PLUGINS" "$GF_PATHS_PROVISIONING" - -COPY ./run.sh /run.sh - -USER "$GF_UID" -ENTRYPOINT [ "/run.sh" ] diff --git a/pkg/build/cmd.go b/pkg/build/cmd.go index 2476caf2d429b..93de968f7b489 100644 --- a/pkg/build/cmd.go +++ b/pkg/build/cmd.go @@ -146,6 +146,11 @@ func setup(goos string) { func doBuild(binaryName, pkg string, opts BuildOpts) error { log.Println("building", binaryName, pkg) + + if err := setBuildEnv(opts); err != nil { + return err + } + libcPart := "" if opts.libc != "" { libcPart = fmt.Sprintf("-%s", opts.libc) @@ -194,9 +199,6 @@ func doBuild(binaryName, pkg string, opts BuildOpts) error { return nil } - if err := setBuildEnv(opts); err != nil { - return err - } runPrint("go", "version") libcPart = "" if opts.libc != "" { diff --git a/pkg/build/cmd/argcount_wrapper.go b/pkg/build/cmd/argcount_wrapper.go index d3a3cfd67f6f2..690695cd35086 100644 --- a/pkg/build/cmd/argcount_wrapper.go +++ b/pkg/build/cmd/argcount_wrapper.go @@ -2,7 +2,22 @@ package main import "github.com/urfave/cli/v2" -func ArgCountWrapper(max int, action cli.ActionFunc) cli.ActionFunc { +// ArgCountWrapper will cause the action to fail if there were not exactly `num` args provided. +func ArgCountWrapper(num int, action cli.ActionFunc) cli.ActionFunc { + return func(ctx *cli.Context) error { + if ctx.NArg() != num { + if err := cli.ShowSubcommandHelp(ctx); err != nil { + return cli.Exit(err.Error(), 1) + } + return cli.Exit("", 1) + } + + return action(ctx) + } +} + +// ArgCountWrapper will cause the action to fail if there were more than `num` args provided. +func MaxArgCountWrapper(max int, action cli.ActionFunc) cli.ActionFunc { return func(ctx *cli.Context) error { if ctx.NArg() > max { if err := cli.ShowSubcommandHelp(ctx); err != nil { diff --git a/pkg/build/cmd/buildbackend.go b/pkg/build/cmd/buildbackend.go index 29ffb307d63b1..39f0d707fe413 100644 --- a/pkg/build/cmd/buildbackend.go +++ b/pkg/build/cmd/buildbackend.go @@ -13,7 +13,7 @@ import ( ) func BuildBackend(ctx *cli.Context) error { - metadata, err := GenerateMetadata(ctx) + metadata, err := config.GenerateMetadata(ctx) if err != nil { return err } diff --git a/pkg/build/cmd/builddocker.go b/pkg/build/cmd/builddocker.go index f17037664a710..ac1858a65ba47 100644 --- a/pkg/build/cmd/builddocker.go +++ b/pkg/build/cmd/builddocker.go @@ -14,7 +14,7 @@ func BuildDocker(c *cli.Context) error { return err } - metadata, err := GenerateMetadata(c) + metadata, err := config.GenerateMetadata(c) if err != nil { return err } diff --git a/pkg/build/cmd/buildfrontend.go b/pkg/build/cmd/buildfrontend.go index 2874a119403f7..d7825f419cd29 100644 --- a/pkg/build/cmd/buildfrontend.go +++ b/pkg/build/cmd/buildfrontend.go @@ -3,6 +3,7 @@ package main import ( "log" + "github.com/grafana/grafana/pkg/build/config" "github.com/grafana/grafana/pkg/build/errutil" "github.com/grafana/grafana/pkg/build/frontend" "github.com/grafana/grafana/pkg/build/syncutil" @@ -10,7 +11,7 @@ import ( ) func BuildFrontend(c *cli.Context) error { - metadata, err := GenerateMetadata(c) + metadata, err := config.GenerateMetadata(c) if err != nil { return err } diff --git a/pkg/build/cmd/buildinternalplugins.go b/pkg/build/cmd/buildinternalplugins.go index 2871106c933b1..fad80b818d58d 100644 --- a/pkg/build/cmd/buildinternalplugins.go +++ b/pkg/build/cmd/buildinternalplugins.go @@ -17,7 +17,7 @@ func BuildInternalPlugins(c *cli.Context) error { } const grafanaDir = "." - metadata, err := GenerateMetadata(c) + metadata, err := config.GenerateMetadata(c) if err != nil { return err } diff --git a/pkg/build/cmd/enterprisecheck.go b/pkg/build/cmd/enterprisecheck.go new file mode 100644 index 0000000000000..f2c36b0fc2eb9 --- /dev/null +++ b/pkg/build/cmd/enterprisecheck.go @@ -0,0 +1,132 @@ +package main + +import ( + "fmt" + "log" + "os" + "strconv" + + "github.com/grafana/grafana/pkg/build/env" + "github.com/grafana/grafana/pkg/build/git" + "github.com/urfave/cli/v2" +) + +// checkOpts are options used to create a new GitHub check for the enterprise downstream test. +type checkOpts struct { + SHA string + URL string + Branch string + PR int +} + +func getCheckOpts(args []string) (*checkOpts, error) { + branch, ok := env.Lookup("DRONE_SOURCE_BRANCH", args) + if !ok { + return nil, cli.Exit("Unable to retrieve build source branch", 1) + } + + var ( + rgx = git.PRCheckRegexp() + matches = rgx.FindStringSubmatch(branch) + ) + + sha, ok := env.Lookup("SOURCE_COMMIT", args) + if !ok { + if matches == nil || len(matches) <= 1 { + return nil, cli.Exit("Unable to retrieve source commit", 1) + } + sha = matches[2] + } + + url, ok := env.Lookup("DRONE_BUILD_LINK", args) + if !ok { + return nil, cli.Exit(`missing environment variable "DRONE_BUILD_LINK"`, 1) + } + + prStr, ok := env.Lookup("OSS_PULL_REQUEST", args) + if !ok { + if matches == nil || len(matches) <= 1 { + return nil, cli.Exit("Unable to retrieve PR number", 1) + } + + prStr = matches[1] + } + + pr, err := strconv.Atoi(prStr) + if err != nil { + return nil, err + } + + return &checkOpts{ + Branch: branch, + PR: pr, + SHA: sha, + URL: url, + }, nil +} + +// EnterpriseCheckBegin creates the GitHub check and signals the beginning of the downstream build / test process +func EnterpriseCheckBegin(c *cli.Context) error { + var ( + ctx = c.Context + client = git.NewGitHubClient(ctx, c.String("github-token")) + ) + + opts, err := getCheckOpts(os.Environ()) + if err != nil { + return err + } + + if _, err = git.CreateEnterpriseStatus(ctx, client.Repositories, opts.SHA, opts.URL, "pending"); err != nil { + return err + } + + return nil +} + +func EnterpriseCheckSuccess(c *cli.Context) error { + return completeEnterpriseCheck(c, true) +} + +func EnterpriseCheckFail(c *cli.Context) error { + return completeEnterpriseCheck(c, false) +} + +func completeEnterpriseCheck(c *cli.Context, success bool) error { + var ( + ctx = c.Context + client = git.NewGitHubClient(ctx, c.String("github-token")) + ) + + // Update the pull request labels + opts, err := getCheckOpts(os.Environ()) + if err != nil { + return err + } + + status := "failure" + if success { + status = "success" + } + + // Update the GitHub check... + if _, err := git.CreateEnterpriseStatus(ctx, client.Repositories, opts.SHA, opts.URL, status); err != nil { + return err + } + + // Delete branch if needed + log.Printf("Checking branch '%s' against '%s'", git.PRCheckRegexp().String(), opts.Branch) + if git.PRCheckRegexp().MatchString(opts.Branch) { + log.Println("Deleting branch", opts.Branch) + if err := git.DeleteEnterpriseBranch(ctx, client.Git, opts.Branch); err != nil { + return fmt.Errorf("error deleting enterprise branch: %w", err) + } + } + + label := "enterprise-failed" + if success { + label = "enterprise-ok" + } + + return git.AddLabelToPR(ctx, client.Issues, opts.PR, label) +} diff --git a/pkg/build/cmd/enterprisecheck_test.go b/pkg/build/cmd/enterprisecheck_test.go new file mode 100644 index 0000000000000..0eeb5bd57412c --- /dev/null +++ b/pkg/build/cmd/enterprisecheck_test.go @@ -0,0 +1,69 @@ +package main + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestGetCheckOpts(t *testing.T) { + t.Run("it should return the checkOpts if the correct environment variables are set", func(t *testing.T) { + args := []string{ + "SOURCE_COMMIT=1234", + "DRONE_SOURCE_BRANCH=test", + "DRONE_BUILD_LINK=http://example.com", + "OSS_PULL_REQUEST=1", + } + + opts, err := getCheckOpts(args) + require.NoError(t, err) + require.Equal(t, opts.SHA, "1234") + require.Equal(t, opts.URL, "http://example.com") + }) + t.Run("it should return an error if SOURCE_COMMIT is not set", func(t *testing.T) { + args := []string{ + "DRONE_BUILD_LINK=http://example.com", + "DRONE_SOURCE_BRANCH=test", + "DRONE_BUILD_LINK=http://example.com", + "OSS_PULL_REQUEST=1", + } + + opts, err := getCheckOpts(args) + require.Nil(t, opts) + require.Error(t, err) + }) + t.Run("it should return an error if DRONE_BUILD_LINK is not set", func(t *testing.T) { + args := []string{ + "SOURCE_COMMIT=1234", + "DRONE_SOURCE_BRANCH=test", + "OSS_PULL_REQUEST=1", + } + + opts, err := getCheckOpts(args) + require.Nil(t, opts) + require.Error(t, err) + }) + t.Run("it should return an error if OSS_PULL_REQUEST is not set", func(t *testing.T) { + args := []string{ + "SOURCE_COMMIT=1234", + "DRONE_SOURCE_BRANCH=test", + "DRONE_BUILD_LINK=http://example.com", + } + + opts, err := getCheckOpts(args) + require.Nil(t, opts) + require.Error(t, err) + }) + t.Run("it should return an error if OSS_PULL_REQUEST is not an integer", func(t *testing.T) { + args := []string{ + "SOURCE_COMMIT=1234", + "DRONE_SOURCE_BRANCH=test", + "DRONE_BUILD_LINK=http://example.com", + "OSS_PULL_REQUEST=http://example.com", + } + + opts, err := getCheckOpts(args) + require.Nil(t, opts) + require.Error(t, err) + }) +} diff --git a/pkg/build/cmd/exportversion.go b/pkg/build/cmd/exportversion.go index afbe05114af72..a3a54309c737c 100644 --- a/pkg/build/cmd/exportversion.go +++ b/pkg/build/cmd/exportversion.go @@ -4,11 +4,12 @@ import ( "os" "path/filepath" + "github.com/grafana/grafana/pkg/build/config" "github.com/urfave/cli/v2" ) func ExportVersion(c *cli.Context) error { - metadata, err := GenerateMetadata(c) + metadata, err := config.GenerateMetadata(c) if err != nil { return err } diff --git a/pkg/build/cmd/fetchimages.go b/pkg/build/cmd/fetchimages.go index 3845daed5a7f6..bd1ec6a5102c1 100644 --- a/pkg/build/cmd/fetchimages.go +++ b/pkg/build/cmd/fetchimages.go @@ -20,12 +20,12 @@ const ( func FetchImages(c *cli.Context) error { if c.NArg() > 0 { if err := cli.ShowSubcommandHelp(c); err != nil { - return cli.NewExitError(err.Error(), 1) + return cli.Exit(err.Error(), 1) } - return cli.NewExitError("", 1) + return cli.Exit("", 1) } - metadata, err := GenerateMetadata(c) + metadata, err := config.GenerateMetadata(c) if err != nil { return err } diff --git a/pkg/build/cmd/flags.go b/pkg/build/cmd/flags.go index 7aa6d98d02635..c9020fe2403cb 100644 --- a/pkg/build/cmd/flags.go +++ b/pkg/build/cmd/flags.go @@ -41,9 +41,32 @@ var ( Name: "dry-run", Usage: "Only simulate actions", } - gcpKeyFlag = cli.StringFlag{ - Name: "gcp-key", - Usage: "Google Cloud Platform key file", - Required: true, + gitHubTokenFlag = cli.StringFlag{ + Name: "github-token", + Value: "", + EnvVars: []string{"GITHUB_TOKEN"}, + Usage: "GitHub token", + } + tagFlag = cli.StringFlag{ + Name: "tag", + Usage: "Grafana version tag", + } + securityFlag = cli.BoolFlag{ + Name: "security", + Usage: "Security release", + } + srcFlag = cli.StringFlag{ + Name: "src-bucket", + Value: "grafana-prerelease", + Usage: "Google Cloud Storage bucket", + } + securityDestBucketFlag = cli.StringFlag{ + Name: "security-dest-bucket", + Usage: "Google Cloud Storage bucket for security packages (or $SECURITY_DEST_BUCKET)", + } + destFlag = cli.StringFlag{ + Name: "dest-bucket", + Value: "grafana-downloads", + Usage: "Google Cloud Storage bucket for published packages", } ) diff --git a/pkg/build/cmd/grafanacom.go b/pkg/build/cmd/grafanacom.go index 9d81d8b62f9df..43f5bc9eb0f24 100644 --- a/pkg/build/cmd/grafanacom.go +++ b/pkg/build/cmd/grafanacom.go @@ -15,11 +15,12 @@ import ( "strings" "time" + "github.com/urfave/cli/v2" + "github.com/grafana/grafana/pkg/build/config" "github.com/grafana/grafana/pkg/build/gcloud" "github.com/grafana/grafana/pkg/build/gcloud/storage" "github.com/grafana/grafana/pkg/build/packaging" - "github.com/urfave/cli/v2" ) const grafanaAPI = "https://grafana.com/api" @@ -33,7 +34,7 @@ func GrafanaCom(c *cli.Context) error { return fmt.Errorf("couldn't activate service account, err: %w", err) } - metadata, err := GenerateMetadata(c) + metadata, err := config.GenerateMetadata(c) if err != nil { return err } @@ -66,11 +67,11 @@ func GrafanaCom(c *cli.Context) error { grafanaAPIKey := strings.TrimSpace(os.Getenv("GRAFANA_COM_API_KEY")) if grafanaAPIKey == "" { - return cli.NewExitError("the environment variable GRAFANA_COM_API_KEY must be set", 1) + return cli.Exit("the environment variable GRAFANA_COM_API_KEY must be set", 1) } whatsNewURL, releaseNotesURL, err := getReleaseURLs() if err != nil { - return cli.NewExitError(err.Error(), 1) + return cli.Exit(err.Error(), 1) } // TODO: Verify config values @@ -89,7 +90,7 @@ func GrafanaCom(c *cli.Context) error { } if err := publishPackages(cfg); err != nil { - return cli.NewExitError(err.Error(), 1) + return cli.Exit(err.Error(), 1) } log.Println("Successfully published packages to grafana.com!") @@ -146,7 +147,7 @@ func publishPackages(cfg packaging.PublishConfig) error { } switch cfg.ReleaseMode.Mode { - case config.MainMode, config.CustomMode, config.CronjobMode: + case config.MainMode, config.DownstreamMode, config.CronjobMode: pth = path.Join(pth, packaging.MainFolder) default: pth = path.Join(pth, packaging.ReleaseFolder) @@ -177,7 +178,7 @@ func publishPackages(cfg packaging.PublishConfig) error { Version: cfg.Version, ReleaseDate: time.Now().UTC(), Builds: builds, - Stable: cfg.ReleaseMode.Mode == config.TagMode, + Stable: cfg.ReleaseMode.Mode == config.TagMode && !cfg.ReleaseMode.IsBeta && !cfg.ReleaseMode.IsTest, Beta: cfg.ReleaseMode.IsBeta, Nightly: cfg.ReleaseMode.Mode == config.CronjobMode, } diff --git a/pkg/build/cmd/main.go b/pkg/build/cmd/main.go index a045a9330767d..225a02f38bc0b 100644 --- a/pkg/build/cmd/main.go +++ b/pkg/build/cmd/main.go @@ -5,12 +5,18 @@ import ( "os" "strings" - "github.com/grafana/grafana/pkg/build/config" - "github.com/grafana/grafana/pkg/build/docker" - "github.com/grafana/grafana/pkg/build/packaging" "github.com/urfave/cli/v2" + + "github.com/grafana/grafana/pkg/build/docker" ) +var additionalCommands []*cli.Command = make([]*cli.Command, 0, 5) + +//nolint:unused +func registerAppCommand(c *cli.Command) { + additionalCommands = append(additionalCommands, c) +} + func main() { app := cli.NewApp() app.Commands = cli.Commands{ @@ -18,7 +24,7 @@ func main() { Name: "build-backend", Usage: "Build one or more variants of back-end binaries", ArgsUsage: "[version]", - Action: ArgCountWrapper(1, BuildBackend), + Action: MaxArgCountWrapper(1, BuildBackend), Flags: []cli.Flag{ &jobsFlag, &variantsFlag, @@ -58,13 +64,18 @@ func main() { Value: "grafana-server", Usage: "Specify the server host", }, + &cli.StringFlag{ + Name: "video", + Value: "true", + Usage: "Specify if videos should be recorded", + }, }, }, { Name: "build-frontend", Usage: "Build front-end artifacts", ArgsUsage: "[version]", - Action: ArgCountWrapper(1, BuildFrontend), + Action: MaxArgCountWrapper(1, BuildFrontend), Flags: []cli.Flag{ &jobsFlag, &editionFlag, @@ -74,7 +85,7 @@ func main() { { Name: "build-docker", Usage: "Build Grafana Docker images", - Action: ArgCountWrapper(1, BuildDocker), + Action: MaxArgCountWrapper(1, BuildDocker), Flags: []cli.Flag{ &jobsFlag, &editionFlag, @@ -93,6 +104,14 @@ func main() { }, }, }, + { + Name: "upload-cdn", + Usage: "Upload public/* to a cdn bucket", + Action: UploadCDN, + Flags: []cli.Flag{ + &editionFlag, + }, + }, { Name: "shellcheck", Usage: "Run shellcheck on shell scripts", @@ -101,7 +120,7 @@ func main() { { Name: "build-plugins", Usage: "Build internal plug-ins", - Action: ArgCountWrapper(1, BuildInternalPlugins), + Action: MaxArgCountWrapper(1, BuildInternalPlugins), Flags: []cli.Flag{ &jobsFlag, &editionFlag, @@ -114,13 +133,19 @@ func main() { Name: "publish-metrics", Usage: "Publish a set of metrics from stdin", ArgsUsage: "", - Action: ArgCountWrapper(1, PublishMetrics), + Action: MaxArgCountWrapper(1, PublishMetrics), }, { Name: "verify-drone", Usage: "Verify Drone configuration", Action: VerifyDrone, }, + { + Name: "verify-starlark", + Usage: "Verify Starlark configuration", + ArgsUsage: "", + Action: VerifyStarlark, + }, { Name: "export-version", Usage: "Exports version in dist/grafana.version", @@ -130,7 +155,7 @@ func main() { Name: "package", Usage: "Package one or more Grafana variants", ArgsUsage: "[version]", - Action: ArgCountWrapper(1, Package), + Action: MaxArgCountWrapper(1, Package), Flags: []cli.Flag{ &jobsFlag, &variantsFlag, @@ -141,7 +166,7 @@ func main() { }, { Name: "store-storybook", - Usage: "Integrity check for storybook build", + Usage: "Stores storybook to GCS buckets", Action: StoreStorybook, Flags: []cli.Flag{ &cli.StringFlag{ @@ -150,10 +175,92 @@ func main() { }, }, }, + { + Name: "verify-storybook", + Usage: "Integrity check for storybook build", + Action: VerifyStorybook, + }, + { + Name: "upload-packages", + Usage: "Upload Grafana packages", + Action: UploadPackages, + Flags: []cli.Flag{ + &jobsFlag, + &editionFlag, + &cli.BoolFlag{ + Name: "enterprise2", + Usage: "Declare if the edition is enterprise2", + }, + }, + }, { Name: "artifacts", Usage: "Handle Grafana artifacts", Subcommands: cli.Commands{ + { + Name: "storybook", + Usage: "Publish Grafana storybook", + Action: PublishStorybookAction, + Flags: []cli.Flag{ + &editionFlag, + &tagFlag, + &srcFlag, + &cli.StringFlag{ + Name: "storybook-bucket", + Value: "grafana-storybook", + Usage: "Google Cloud Storage bucket for storybooks", + }, + }, + }, + { + Name: "static-assets", + Usage: "Publish Grafana static assets", + Action: PublishStaticAssetsAction, + Flags: []cli.Flag{ + &editionFlag, + &securityFlag, + &securityDestBucketFlag, + &tagFlag, + &srcFlag, + &destFlag, + &cli.StringFlag{ + Name: "static-assets-bucket", + Value: "grafana-static-assets", + Usage: "Google Cloud Storage bucket for static assets", + }, + &cli.StringSliceFlag{ + Name: "static-asset-editions", + Usage: "All the editions of the static assets (or $STATIC_ASSET_EDITIONS)", + }, + }, + }, + { + Name: "packages", + Usage: "Publish Grafana packages", + Action: PublishArtifactsAction, + Flags: []cli.Flag{ + &editionFlag, + &securityFlag, + &securityDestBucketFlag, + &tagFlag, + &srcFlag, + &destFlag, + &cli.StringSliceFlag{ + Name: "artifacts-editions", + Value: cli.NewStringSlice("oss", "enterprise", "enterprise2"), + Usage: "Editions for which the artifacts should be delivered (oss,enterprise,enterprise2), (or $ARTIFACTS_EDITIONS)", + }, + &cli.StringFlag{ + Name: "enterprise2-dest-bucket", + Value: "grafana-downloads-enterprise2", + Usage: "Google Cloud Storage bucket for published packages", + }, + &cli.StringFlag{ + Name: "enterprise2-security-prefix", + Usage: "Bucket path prefix for enterprise2 security releases (or $ENTERPRISE2_SECURITY_PREFIX)", + }, + }, + }, { Name: "docker", Usage: "Handle Grafana Docker images", @@ -162,11 +269,54 @@ func main() { Name: "fetch", Usage: "Fetch Grafana Docker images", ArgsUsage: "[version]", - Action: ArgCountWrapper(1, FetchImages), + Action: MaxArgCountWrapper(1, FetchImages), Flags: []cli.Flag{ &editionFlag, }, }, + { + Name: "publish-enterprise2", + Usage: "Handle Grafana Enterprise2 Docker images", + ArgsUsage: "[version]", + Action: Enterprise2, + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "dockerhub-repo", + Usage: "DockerHub repo to push images", + }, + }, + }, + }, + }, + { + Name: "npm", + Usage: "Handle Grafana npm packages", + Subcommands: cli.Commands{ + { + Name: "release", + Usage: "Release npm packages", + ArgsUsage: "[version]", + Action: NpmReleaseAction, + Flags: []cli.Flag{ + &tagFlag, + }, + }, + { + Name: "store", + Usage: "Store npm packages tarball", + Action: NpmStoreAction, + Flags: []cli.Flag{ + &tagFlag, + }, + }, + { + Name: "retrieve", + Usage: "Retrieve npm packages tarball", + Action: NpmRetrieveAction, + Flags: []cli.Flag{ + &tagFlag, + }, + }, }, }, }, @@ -176,66 +326,108 @@ func main() { Usage: "Publish packages to Grafana com and repositories", Subcommands: cli.Commands{ { - Name: "packages", - Usage: "publish Grafana packages", - ArgsUsage: "[version]", - Action: PublishPackages, + Name: "grafana-com", + Usage: "Publish packages to grafana.com", + Action: GrafanaCom, Flags: []cli.Flag{ - &jobsFlag, &editionFlag, &buildIDFlag, &dryRunFlag, - &gcpKeyFlag, - &cli.StringFlag{ - Name: "packages-bucket", - Value: config.PublicBucket, - Usage: "Google Cloud Storage Debian database bucket", - }, &cli.StringFlag{ - Name: "deb-db-bucket", - Value: packaging.DefaultDebDBBucket, - Usage: "Google Cloud Storage Debian database bucket", + Name: "src-bucket", + Value: "grafana-downloads", + Usage: "Google Cloud Storage bucket", }, + }, + }, + { + Name: "github", + Usage: "Publish packages to GitHub releases", + Action: PublishGithub, + Flags: []cli.Flag{ + &dryRunFlag, &cli.StringFlag{ - Name: "deb-repo-bucket", - Value: packaging.DefaultDebRepoBucket, - Usage: "Google Cloud Storage Debian repo bucket", + Name: "path", + Usage: "Path to the asset to be published", }, &cli.StringFlag{ - Name: "rpm-repo-bucket", - Value: packaging.DefaultRPMRepoBucket, - Usage: "Google Cloud Storage RPM repo bucket", + Name: "repo", + Required: true, + Usage: "GitHub repository", }, &cli.StringFlag{ - Name: "ttl", - Value: packaging.DefaultTTLSeconds, - Usage: "Cache time to live for uploaded packages", + Name: "tag", + Usage: "Release tag (default from metadata)", }, &cli.BoolFlag{ - Name: "simulate-release", - Usage: "Only simulate creating release at grafana.com", + Name: "create", + Usage: "Create release if it doesn't exist", }, }, }, { - Name: "grafana-com", - Usage: "Publish packages to grafana.com", - Action: GrafanaCom, + Name: "aws", + Usage: "Publish image to AWS Marketplace releases", + Action: PublishAwsMarketplace, Flags: []cli.Flag{ - &editionFlag, - &buildIDFlag, &dryRunFlag, &cli.StringFlag{ - Name: "src-bucket", - Value: "grafana-downloads", - Usage: "Google Cloud Storage bucket", + Name: "version", + Usage: "Release version (default from metadata)", + }, + &cli.StringFlag{ + Name: "image", + Required: true, + Usage: "Name of the image to be released", + }, + &cli.StringFlag{ + Name: "repo", + Required: true, + Usage: "AWS Marketplace ECR repository", + }, + &cli.StringFlag{ + Name: "product", + Required: true, + Usage: "AWS Marketplace product identifier", }, }, }, }, }, + { + Name: "enterprise-check", + Usage: "Commands for testing against Grafana Enterprise", + Subcommands: cli.Commands{ + { + Name: "begin", + Usage: "Creates the GitHub check in a pull request and begins the tests", + Action: EnterpriseCheckBegin, + Flags: []cli.Flag{ + &gitHubTokenFlag, + }, + }, + { + Name: "success", + Usage: "Updates the GitHub check in a pull request to show a successful build and updates the pull request labels", + Action: EnterpriseCheckSuccess, + Flags: []cli.Flag{ + &gitHubTokenFlag, + }, + }, + { + Name: "fail", + Usage: "Updates the GitHub check in a pull request to show a failed build and updates the pull request labels", + Action: EnterpriseCheckFail, + Flags: []cli.Flag{ + &gitHubTokenFlag, + }, + }, + }, + }, } + app.Commands = append(app.Commands, additionalCommands...) + if err := app.Run(os.Args); err != nil { log.Fatalln(err) } diff --git a/pkg/build/cmd/npm.go b/pkg/build/cmd/npm.go new file mode 100644 index 0000000000000..07c2fe1365f11 --- /dev/null +++ b/pkg/build/cmd/npm.go @@ -0,0 +1,88 @@ +package main + +import ( + "fmt" + "os" + "os/exec" + "strings" + + "github.com/grafana/grafana/pkg/build/npm" + "github.com/urfave/cli/v2" +) + +func NpmRetrieveAction(c *cli.Context) error { + if c.NArg() > 0 { + if err := cli.ShowSubcommandHelp(c); err != nil { + return cli.Exit(err.Error(), 1) + } + return cli.Exit("", 1) + } + + tag := c.String("tag") + if tag == "" { + return fmt.Errorf("no tag version specified, exitting") + } + + prereleaseBucket := strings.TrimSpace(os.Getenv("PRERELEASE_BUCKET")) + if prereleaseBucket == "" { + return cli.Exit("the environment variable PRERELEASE_BUCKET must be set", 1) + } + + err := npm.FetchNpmPackages(c.Context, tag, prereleaseBucket) + if err != nil { + return err + } + return nil +} + +func NpmStoreAction(c *cli.Context) error { + if c.NArg() > 0 { + if err := cli.ShowSubcommandHelp(c); err != nil { + return cli.Exit(err.Error(), 1) + } + return cli.Exit("", 1) + } + + tag := c.String("tag") + if tag == "" { + return fmt.Errorf("no tag version specified, exiting") + } + + prereleaseBucket := strings.TrimSpace(os.Getenv("PRERELEASE_BUCKET")) + if prereleaseBucket == "" { + return cli.Exit("the environment variable PRERELEASE_BUCKET must be set", 1) + } + + err := npm.StoreNpmPackages(c.Context, tag, prereleaseBucket) + if err != nil { + return err + } + return nil +} + +func NpmReleaseAction(c *cli.Context) error { + if c.NArg() > 0 { + if err := cli.ShowSubcommandHelp(c); err != nil { + return cli.Exit(err.Error(), 1) + } + return cli.Exit("", 1) + } + + tag := c.String("tag") + if tag == "" { + return fmt.Errorf("no tag version specified, exitting") + } + + cmd := exec.Command("git", "checkout", ".") + if err := cmd.Run(); err != nil { + fmt.Println("command failed to run, err: ", err) + return err + } + + err := npm.PublishNpmPackages(c.Context, tag) + if err != nil { + return err + } + + return nil +} diff --git a/pkg/build/cmd/package.go b/pkg/build/cmd/package.go index 37b8d2e81fda8..7f1b2da25bc8a 100644 --- a/pkg/build/cmd/package.go +++ b/pkg/build/cmd/package.go @@ -13,7 +13,7 @@ import ( ) func Package(c *cli.Context) error { - metadata, err := GenerateMetadata(c) + metadata, err := config.GenerateMetadata(c) if err != nil { return err } @@ -22,12 +22,12 @@ func Package(c *cli.Context) error { releaseMode, err := metadata.GetReleaseMode() if err != nil { - return cli.NewExitError(err.Error(), 1) + return cli.Exit(err.Error(), 1) } releaseModeConfig, err := config.GetBuildConfig(metadata.ReleaseMode.Mode) if err != nil { - return cli.NewExitError(err.Error(), 1) + return cli.Exit(err.Error(), 1) } cfg := config.Config{ @@ -37,14 +37,17 @@ func Package(c *cli.Context) error { ctx := context.Background() - variantStrs := strings.Split(c.String("variants"), ",") variants := []config.Variant{} - for _, varStr := range variantStrs { - if varStr == "" { - continue + variantStrs := strings.Split(c.String("variants"), ",") + if c.String("variants") != "" { + for _, varStr := range variantStrs { + if varStr == "" { + continue + } + variants = append(variants, config.Variant(varStr)) } - - variants = append(variants, config.Variant(varStr)) + } else { + variants = releaseModeConfig.Variants } if len(variants) == 0 { diff --git a/pkg/build/cmd/publishartifacts.go b/pkg/build/cmd/publishartifacts.go new file mode 100644 index 0000000000000..bf3f162e36245 --- /dev/null +++ b/pkg/build/cmd/publishartifacts.go @@ -0,0 +1,112 @@ +package main + +import ( + "fmt" + "log" + "path/filepath" + "strings" + + "github.com/grafana/grafana/pkg/build/env" + "github.com/grafana/grafana/pkg/build/gcloud" + "github.com/grafana/grafana/pkg/build/gcloud/storage" + "github.com/urfave/cli/v2" +) + +// PublishArtifactsAction Action implements the sub-command "publish-artifacts". +func PublishArtifactsAction(c *cli.Context) error { + if c.NArg() > 0 { + if err := cli.ShowSubcommandHelp(c); err != nil { + return cli.Exit(err.Error(), 1) + } + return cli.Exit("", 1) + } + + security := c.Bool("security") + var securityDestBucket, enterprise2SecurityPrefix string + + artifactsEditions, err := env.RequireListWithEnvFallback(c, "artifacts-editions", "ARTIFACTS_EDITIONS") + if err != nil { + return err + } + + if security { + securityDestBucket, err = env.RequireStringWithEnvFallback(c, "security-dest-bucket", "SECURITY_DEST_BUCKET") + if err != nil { + return err + } + enterprise2SecurityPrefix, err = env.RequireStringWithEnvFallback(c, "enterprise2-security-prefix", "ENTERPRISE2_SECURITY_PREFIX") + if err != nil { + return err + } + } + + if err := gcloud.ActivateServiceAccount(); err != nil { + return fmt.Errorf("error connecting to gcp, %q", err) + } + + cfg := publishConfig{ + srcBucket: c.String("src-bucket"), + destBucket: c.String("dest-bucket"), + enterprise2DestBucket: c.String("enterprise2-dest-bucket"), + enterprise2SecurityPrefix: enterprise2SecurityPrefix, + security: security, + tag: strings.TrimPrefix(c.String("tag"), "v"), + } + + if cfg.security { + cfg.destBucket = securityDestBucket + } + + gcs, err := storage.New() + if err != nil { + return err + } + + for _, edition := range artifactsEditions { + switch edition { + case "oss", "enterprise": + err = copyArtifacts(c, gcs, cfg, edition) + if err != nil { + return err + } + case "enterprise2": + err = copyEnterprise2Artifacts(c, gcs, cfg) + if err != nil { + return err + } + default: + log.Printf("unrecognised artifacts edition: %s\n", edition) + } + } + + return nil +} + +func copyArtifacts(c *cli.Context, gcs *storage.Client, cfg publishConfig, edition string) error { + bucket := gcs.Bucket(cfg.destBucket) + destURL := edition + if !cfg.security { + destURL = filepath.Join(destURL, "release") + } + log.Printf("Copying downloads for %s, from %s bucket to %s bucket", edition, cfg.srcBucket, destURL) + if err := gcs.CopyRemoteDir(c.Context, gcs.Bucket(cfg.srcBucket), fmt.Sprintf("artifacts/downloads/v%s/%s/release", cfg.tag, edition), bucket, destURL); err != nil { + return err + } + + log.Printf("Successfully copied downloads.") + return nil +} + +func copyEnterprise2Artifacts(c *cli.Context, gcs *storage.Client, cfg publishConfig) error { + bucket := gcs.Bucket(cfg.enterprise2DestBucket) + var prefix string + if cfg.security { + prefix = cfg.enterprise2SecurityPrefix + } + destURL := fmt.Sprintf("enterprise2/%srelease", prefix) + log.Printf("Copying downloads for enterprise2, from %s bucket to %s bucket", cfg.srcBucket, destURL) + if err := gcs.CopyRemoteDir(c.Context, gcs.Bucket(cfg.srcBucket), fmt.Sprintf("artifacts/downloads-enterprise2/v%s/enterprise2/release", cfg.tag), bucket, destURL); err != nil { + return err + } + return nil +} diff --git a/pkg/build/cmd/publishaws.go b/pkg/build/cmd/publishaws.go new file mode 100644 index 0000000000000..e499c6b27fa58 --- /dev/null +++ b/pkg/build/cmd/publishaws.go @@ -0,0 +1,308 @@ +package main + +import ( + "context" + "encoding/base64" + "encoding/json" + "errors" + "fmt" + "io" + "os" + "strings" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/request" + "github.com/aws/aws-sdk-go/aws/session" + "github.com/aws/aws-sdk-go/service/ecr" + "github.com/aws/aws-sdk-go/service/marketplacecatalog" + "github.com/docker/docker/api/types" + "github.com/docker/docker/client" + "github.com/grafana/grafana/pkg/build/config" + "github.com/urfave/cli/v2" +) + +const ( + marketplaceChangeSetName = "Add new version" + marketplaceCatalogId = "AWSMarketplace" + marketplaceRegistryId = "709825985650" + marketplaceRegistryRegion = "us-east-1" + marketplaceRegistryUrl = "709825985650.dkr.ecr.us-east-1.amazonaws.com" + marketplaceRequestsUrl = "https://aws.amazon.com/marketplace/management/requests/" + releaseNotesTemplateUrl = "https://grafana.com/docs/grafana/latest/release-notes/release-notes-${TAG}/" + helmChartsUrl = "https://grafana.github.io/helm-charts/" + docsUrl = "https://grafana.com/docs/grafana/latest/enterprise/license/" + imagePlatform = "linux/amd64" + + publishAwsMarketplaceTestKey publishAwsMarketplaceTestKeyType = "test-client" +) + +var ( + errEmptyVersion = errors.New(`failed to retrieve release version from metadata, use "--version" to set it manually`) +) + +type publishAwsMarketplaceTestKeyType string + +type publishAwsMarketplaceFlags struct { + dryRun bool + version string + repo string + image string + product string +} + +type AwsMarketplacePublishingService struct { + auth string + docker AwsMarketplaceDocker + ecr AwsMarketplaceRegistry + mkt AwsMarketplaceCatalog +} + +type AwsMarketplaceDocker interface { + ImagePull(ctx context.Context, refStr string, options types.ImagePullOptions) (io.ReadCloser, error) + ImageTag(ctx context.Context, source string, target string) error + ImagePush(ctx context.Context, image string, options types.ImagePushOptions) (io.ReadCloser, error) +} + +type AwsMarketplaceRegistry interface { + GetAuthorizationTokenWithContext(ctx context.Context, input *ecr.GetAuthorizationTokenInput, opts ...request.Option) (*ecr.GetAuthorizationTokenOutput, error) +} + +type AwsMarketplaceCatalog interface { + DescribeEntityWithContext(ctx context.Context, input *marketplacecatalog.DescribeEntityInput, opts ...request.Option) (*marketplacecatalog.DescribeEntityOutput, error) + StartChangeSetWithContext(ctx context.Context, input *marketplacecatalog.StartChangeSetInput, opts ...request.Option) (*marketplacecatalog.StartChangeSetOutput, error) +} + +func PublishAwsMarketplace(ctx *cli.Context) error { + f, err := getPublishAwsMarketplaceFlags(ctx) + if err != nil { + return err + } + + if f.version == "" { + return errEmptyVersion + } + + svc, err := getAwsMarketplacePublishingService() + if err != nil { + return err + } + + if ctx.Context.Value(publishAwsMarketplaceTestKey) != nil { + svc = ctx.Context.Value(publishAwsMarketplaceTestKey).(*AwsMarketplacePublishingService) + } + + fmt.Println("Logging in to AWS Marketplace registry") + err = svc.Login(ctx.Context) + if err != nil { + return err + } + + fmt.Printf("Retrieving image '%s:%s' from Docker Hub\n", f.image, f.version) + err = svc.PullImage(ctx.Context, f.image, f.version) + if err != nil { + return err + } + + fmt.Printf("Renaming image '%s:%s' to '%s/%s:%s'\n", f.image, f.version, marketplaceRegistryUrl, f.repo, f.version) + err = svc.TagImage(ctx.Context, f.image, f.repo, f.version) + if err != nil { + return err + } + + if !f.dryRun { + fmt.Printf("Pushing image '%s/%s:%s' to the AWS Marketplace ECR\n", marketplaceRegistryUrl, f.repo, f.version) + err = svc.PushToMarketplace(ctx.Context, f.repo, f.version) + if err != nil { + return err + } + } else { + fmt.Printf("Dry-Run: Pushing image '%s/%s:%s' to the AWS Marketplace ECR\n", marketplaceRegistryUrl, f.repo, f.version) + } + + fmt.Printf("Retrieving product identifier for product '%s'\n", f.product) + pid, err := svc.GetProductIdentifier(ctx.Context, f.product) + if err != nil { + return err + } + + if !f.dryRun { + fmt.Printf("Releasing to product, you can view the progress of the release on %s\n", marketplaceRequestsUrl) + return svc.ReleaseToProduct(ctx.Context, pid, f.repo, f.version) + } else { + fmt.Printf("Dry-Run: Releasing to product, you can view the progress of the release on %s\n", marketplaceRequestsUrl) + } + + return nil +} + +func getAwsMarketplacePublishingService() (*AwsMarketplacePublishingService, error) { + cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation()) + if err != nil { + return nil, err + } + + mySession := session.Must(session.NewSession()) + ecr := ecr.New(mySession, aws.NewConfig().WithRegion(marketplaceRegistryRegion)) + mkt := marketplacecatalog.New(mySession, aws.NewConfig().WithRegion(marketplaceRegistryRegion)) + return &AwsMarketplacePublishingService{ + docker: cli, + ecr: ecr, + mkt: mkt, + }, nil +} + +func (s *AwsMarketplacePublishingService) Login(ctx context.Context) error { + out, err := s.ecr.GetAuthorizationTokenWithContext(ctx, &ecr.GetAuthorizationTokenInput{}) + if err != nil { + return err + } + s.auth = *out.AuthorizationData[0].AuthorizationToken + authData, err := base64.StdEncoding.DecodeString(s.auth) + if err != nil { + return err + } + authString := strings.Split(string(authData), ":") + authData, err = json.Marshal(types.AuthConfig{ + Username: authString[0], + Password: authString[1], + }) + s.auth = base64.StdEncoding.EncodeToString(authData) + return err +} + +func (s *AwsMarketplacePublishingService) PullImage(ctx context.Context, image string, version string) error { + reader, err := s.docker.ImagePull(ctx, fmt.Sprintf("%s:%s", image, version), types.ImagePullOptions{ + Platform: imagePlatform, + }) + if err != nil { + return err + } + + _, err = io.Copy(os.Stdout, reader) + if err != nil { + return err + } + + err = reader.Close() + if err != nil { + return err + } + return nil +} + +func (s *AwsMarketplacePublishingService) TagImage(ctx context.Context, image string, repo string, version string) error { + err := s.docker.ImageTag(ctx, fmt.Sprintf("%s:%s", image, version), fmt.Sprintf("%s/%s:%s", marketplaceRegistryUrl, repo, version)) + if err != nil { + return err + } + return nil +} + +func (s *AwsMarketplacePublishingService) PushToMarketplace(ctx context.Context, repo string, version string) error { + reader, err := s.docker.ImagePush(ctx, fmt.Sprintf("%s/%s:%s", marketplaceRegistryUrl, repo, version), types.ImagePushOptions{ + RegistryAuth: s.auth, + }) + if err != nil { + return err + } + + _, err = io.Copy(os.Stdout, reader) + if err != nil { + return err + } + + err = reader.Close() + if err != nil { + return err + } + return nil +} + +func (s *AwsMarketplacePublishingService) GetProductIdentifier(ctx context.Context, product string) (string, error) { + out, err := s.mkt.DescribeEntityWithContext(ctx, &marketplacecatalog.DescribeEntityInput{ + EntityId: aws.String(product), + Catalog: aws.String(marketplaceCatalogId), + }) + if err != nil { + return "", err + } + return *out.EntityIdentifier, nil +} + +func (s *AwsMarketplacePublishingService) ReleaseToProduct(ctx context.Context, pid string, repo string, version string) error { + _, err := s.mkt.StartChangeSetWithContext(ctx, &marketplacecatalog.StartChangeSetInput{ + Catalog: aws.String(marketplaceCatalogId), + ChangeSetName: aws.String(marketplaceChangeSetName), + ChangeSet: []*marketplacecatalog.Change{ + buildAwsMarketplaceChangeSet(pid, repo, version), + }, + }) + return err +} + +func getPublishAwsMarketplaceFlags(ctx *cli.Context) (*publishAwsMarketplaceFlags, error) { + metadata, err := config.GenerateMetadata(ctx) + if err != nil { + return nil, err + } + version := ctx.String("version") + if version == "" && metadata.GrafanaVersion != "" { + version = metadata.GrafanaVersion + } + image := ctx.String("image") + repo := ctx.String("repo") + product := ctx.String("product") + dryRun := ctx.Bool("dry-run") + return &publishAwsMarketplaceFlags{ + dryRun: dryRun, + version: version, + image: image, + repo: repo, + product: product, + }, nil +} + +func buildAwsMarketplaceReleaseNotesUrl(version string) string { + sanitizedVersion := strings.ReplaceAll(version, ".", "-") + return strings.ReplaceAll(releaseNotesTemplateUrl, "${TAG}", sanitizedVersion) +} + +func buildAwsMarketplaceChangeSet(entityId string, repo string, version string) *marketplacecatalog.Change { + return &marketplacecatalog.Change{ + ChangeType: aws.String("AddDeliveryOptions"), + Entity: &marketplacecatalog.Entity{ + Type: aws.String("ContainerProduct@1.0"), + Identifier: aws.String(entityId), + }, + Details: aws.String(buildAwsMarketplaceVersionDetails(repo, version)), + } +} + +func buildAwsMarketplaceVersionDetails(repo string, version string) string { + releaseNotesUrl := buildAwsMarketplaceReleaseNotesUrl(version) + return fmt.Sprintf(`{ + "Version": { + "ReleaseNotes": "Release notes are available on the website %s", + "VersionTitle": "v%s" + }, + "DeliveryOptions": [ + { + "Details": { + "EcrDeliveryOptionDetails": { + "DeploymentResources": [ + { + "Name": "Helm Charts", + "Url": "%s" + } + ], + "CompatibleServices": ["EKS", "ECS", "ECS-Anywhere", "EKS-Anywhere"], + "ContainerImages": ["%s/%s:%s"], + "Description": "Grafana Enterprise can be installed using the official Grafana Helm chart repository. The repository is available on Github: %s", + "UsageInstructions": "You can apply your Grafana Enterprise license to a new or existing Grafana Enterprise deployment by updating a configuration setting or environment variable. Your Grafana instance must be deployed on AWS, or have network access to AWS. For more information, see %s" + } + }, + "DeliveryOptionTitle": "Helm Chart" + } + ] + }`, releaseNotesUrl, version, helmChartsUrl, marketplaceRegistryUrl, repo, version, helmChartsUrl, docsUrl) +} diff --git a/pkg/build/cmd/publishaws_test.go b/pkg/build/cmd/publishaws_test.go new file mode 100644 index 0000000000000..fc8f261533683 --- /dev/null +++ b/pkg/build/cmd/publishaws_test.go @@ -0,0 +1,207 @@ +package main + +import ( + "bytes" + "context" + "encoding/base64" + "errors" + "io" + "os" + "testing" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/credentials" + "github.com/aws/aws-sdk-go/aws/request" + "github.com/aws/aws-sdk-go/service/ecr" + "github.com/aws/aws-sdk-go/service/marketplacecatalog" + "github.com/docker/docker/api/types" + "github.com/stretchr/testify/assert" + "github.com/urfave/cli/v2" +) + +type awsPublishTestCase struct { + name string + args []string + expectedError error + errorContains string + expectedOutput string + mockedService *AwsMarketplacePublishingService +} + +func TestPublishAwsMarketplace(t *testing.T) { + t.Setenv("DRONE_BUILD_EVENT", "promote") + t.Setenv("DRONE_TAG", "v1.0.0") + t.Setenv("DRONE_COMMIT", "abcdefgh") + testApp := setupPublishAwsMarketplaceTests(t) + errShouldNotCallMock := errors.New("shouldn't call") + + testCases := []awsPublishTestCase{ + { + name: "try to publish without required flags", + errorContains: `Required flags "image, repo, product" not set`, + }, + { + name: "try to publish without credentials", + args: []string{"--image", "test/test", "--repo", "test/test", "--product", "test", "--version", "1.0.0"}, + mockedService: &AwsMarketplacePublishingService{ + ecr: &mockAwsMarketplaceRegistry{ + GetAuthorizationTokenWithContextError: credentials.ErrNoValidProvidersFoundInChain, + }, + }, + expectedError: credentials.ErrNoValidProvidersFoundInChain, + }, + { + name: "try to publish with valid credentials and nonexisting version", + args: []string{"--image", "test/test", "--repo", "test/test", "--product", "test", "--version", "1.0.0"}, + mockedService: &AwsMarketplacePublishingService{ + ecr: &mockAwsMarketplaceRegistry{}, + docker: &mockAwsMarketplaceDocker{}, + mkt: &mockAwsMarketplaceCatalog{}, + }, + expectedOutput: "Releasing to product", + }, + { + name: "try to publish with valid credentials and existing version", + args: []string{"--image", "test/test", "--repo", "test/test", "--product", "test", "--version", "1.0.0"}, + mockedService: &AwsMarketplacePublishingService{ + ecr: &mockAwsMarketplaceRegistry{}, + docker: &mockAwsMarketplaceDocker{}, + mkt: &mockAwsMarketplaceCatalog{}, + }, + expectedOutput: "Releasing to product", + }, + { + name: "dry run with invalid credentials", + args: []string{"--dry-run", "--image", "test/test", "--repo", "test/test", "--product", "test", "--version", "1.0.0"}, + mockedService: &AwsMarketplacePublishingService{ + ecr: &mockAwsMarketplaceRegistry{ + GetAuthorizationTokenWithContextError: credentials.ErrNoValidProvidersFoundInChain, + }, + }, + expectedError: credentials.ErrNoValidProvidersFoundInChain, + }, + { + name: "dry run with valid credentials", + args: []string{"--dry-run", "--image", "test/test", "--repo", "test/test", "--product", "test", "--version", "1.0.0"}, + mockedService: &AwsMarketplacePublishingService{ + ecr: &mockAwsMarketplaceRegistry{}, + docker: &mockAwsMarketplaceDocker{ + ImagePushError: errShouldNotCallMock, + }, + mkt: &mockAwsMarketplaceCatalog{ + StartChangeSetWithContextError: errShouldNotCallMock, + }, + }, + expectedOutput: "Dry-Run: Releasing to product", + }, + } + + if os.Getenv("DRONE_COMMIT") == "" { + // this test only works locally due to Drone environment + testCases = append(testCases, + awsPublishTestCase{ + name: "try to publish without version", + args: []string{"--image", "test/test", "--repo", "test/test", "--product", "test"}, + expectedError: errEmptyVersion, + }, + ) + } + + for _, test := range testCases { + t.Run(test.name, func(t *testing.T) { + ctx := context.WithValue(context.Background(), publishAwsMarketplaceTestKey, test.mockedService) + args := []string{"run"} + args = append(args, test.args...) + out, err := captureStdout(t, func() error { + return testApp.RunContext(ctx, args) + }) + if test.expectedOutput != "" { + assert.Contains(t, out, test.expectedOutput) + } + if test.expectedError != nil || test.errorContains != "" { + assert.Error(t, err) + if test.expectedError != nil { + assert.ErrorIs(t, err, test.expectedError) + } + if test.errorContains != "" { + assert.ErrorContains(t, err, test.errorContains) + } + } else { + assert.NoError(t, err) + } + }) + } +} + +func setupPublishAwsMarketplaceTests(t *testing.T) *cli.App { + t.Helper() + testApp := cli.NewApp() + testApp.Action = PublishAwsMarketplace + testApp.Flags = []cli.Flag{ + &dryRunFlag, + &cli.StringFlag{ + Name: "version", + Usage: "Release version (default from metadata)", + }, + &cli.StringFlag{ + Name: "image", + Required: true, + Usage: "Name of the image to be released", + }, + &cli.StringFlag{ + Name: "repo", + Required: true, + Usage: "AWS Marketplace ECR repository", + }, + &cli.StringFlag{ + Name: "product", + Required: true, + Usage: "AWS Marketplace product identifier", + }, + } + return testApp +} + +type mockAwsMarketplaceDocker struct { + ImagePullError error + ImageTagError error + ImagePushError error +} + +func (m *mockAwsMarketplaceDocker) ImagePull(ctx context.Context, refStr string, options types.ImagePullOptions) (io.ReadCloser, error) { + return io.NopCloser(bytes.NewReader([]byte(""))), m.ImagePullError +} +func (m *mockAwsMarketplaceDocker) ImageTag(ctx context.Context, source string, target string) error { + return m.ImageTagError +} +func (m *mockAwsMarketplaceDocker) ImagePush(ctx context.Context, image string, options types.ImagePushOptions) (io.ReadCloser, error) { + return io.NopCloser(bytes.NewReader([]byte(""))), m.ImagePushError +} + +type mockAwsMarketplaceRegistry struct { + GetAuthorizationTokenWithContextError error +} + +func (m *mockAwsMarketplaceRegistry) GetAuthorizationTokenWithContext(ctx context.Context, input *ecr.GetAuthorizationTokenInput, opts ...request.Option) (*ecr.GetAuthorizationTokenOutput, error) { + return &ecr.GetAuthorizationTokenOutput{ + AuthorizationData: []*ecr.AuthorizationData{ + { + AuthorizationToken: aws.String(base64.StdEncoding.EncodeToString([]byte("username:password"))), + }, + }, + }, m.GetAuthorizationTokenWithContextError +} + +type mockAwsMarketplaceCatalog struct { + DescribeEntityWithContextError error + StartChangeSetWithContextError error +} + +func (m *mockAwsMarketplaceCatalog) DescribeEntityWithContext(ctx context.Context, input *marketplacecatalog.DescribeEntityInput, opts ...request.Option) (*marketplacecatalog.DescribeEntityOutput, error) { + return &marketplacecatalog.DescribeEntityOutput{ + EntityIdentifier: aws.String("productid"), + }, m.DescribeEntityWithContextError +} +func (m *mockAwsMarketplaceCatalog) StartChangeSetWithContext(ctx context.Context, input *marketplacecatalog.StartChangeSetInput, opts ...request.Option) (*marketplacecatalog.StartChangeSetOutput, error) { + return &marketplacecatalog.StartChangeSetOutput{}, m.StartChangeSetWithContextError +} diff --git a/pkg/build/cmd/publishconfig.go b/pkg/build/cmd/publishconfig.go new file mode 100644 index 0000000000000..4715fce25e7a6 --- /dev/null +++ b/pkg/build/cmd/publishconfig.go @@ -0,0 +1,13 @@ +package main + +type publishConfig struct { + tag string + srcBucket string + destBucket string + enterprise2DestBucket string + enterprise2SecurityPrefix string + staticAssetsBucket string + staticAssetEditions []string + storybookBucket string + security bool +} diff --git a/pkg/build/cmd/publishgithub.go b/pkg/build/cmd/publishgithub.go new file mode 100644 index 0000000000000..e01a199b4d97c --- /dev/null +++ b/pkg/build/cmd/publishgithub.go @@ -0,0 +1,190 @@ +package main + +import ( + "context" + "errors" + "fmt" + "os" + "path" + "strings" + + "github.com/google/go-github/github" + "github.com/grafana/grafana/pkg/build/config" + "github.com/urfave/cli/v2" + "golang.org/x/oauth2" +) + +type githubRepositoryService interface { + GetReleaseByTag(ctx context.Context, owner string, repo string, tag string) (*github.RepositoryRelease, *github.Response, error) + CreateRelease(ctx context.Context, owner string, repo string, release *github.RepositoryRelease) (*github.RepositoryRelease, *github.Response, error) + UploadReleaseAsset(ctx context.Context, owner string, repo string, id int64, opt *github.UploadOptions, file *os.File) (*github.ReleaseAsset, *github.Response, error) + DeleteReleaseAsset(ctx context.Context, owner string, repo string, id int64) (*github.Response, error) + ListReleaseAssets(ctx context.Context, owner string, repo string, id int64, opt *github.ListOptions) ([]*github.ReleaseAsset, *github.Response, error) +} + +type githubRepo struct { + owner string + name string +} + +type publishGithubFlags struct { + create bool + dryRun bool + tag string + repo *githubRepo + artifactPath string +} + +var ( + newGithubClient = githubRepositoryClient + errTokenIsEmpty = errors.New("the environment variable GH_TOKEN must be set") + errTagIsEmpty = errors.New(`failed to retrieve release tag from metadata, use "--tag" to set it manually`) + errReleaseNotFound = errors.New(`release not found, use "--create" to create the release`) +) + +func PublishGithub(c *cli.Context) error { + ctx := c.Context + token := os.Getenv("GH_TOKEN") + f, err := getPublishGithubFlags(c) + if err != nil { + return err + } + + if f.tag == "" { + return errTagIsEmpty + } + + if token == "" { + return errTokenIsEmpty + } + + if f.dryRun { + return runPublishGithubDryRun(f, token, c) + } + + client := newGithubClient(ctx, token) + release, res, err := client.GetReleaseByTag(ctx, f.repo.owner, f.repo.name, f.tag) + if err != nil && res.StatusCode != 404 { + return err + } + + if release == nil { + if f.create { + release, _, err = client.CreateRelease(ctx, f.repo.owner, f.repo.name, &github.RepositoryRelease{TagName: &f.tag}) + if err != nil { + return err + } + } else { + return errReleaseNotFound + } + } + + artifactName := path.Base(f.artifactPath) + file, err := os.Open(f.artifactPath) + if err != nil { + return err + } + + assetsPage := 1 + foundAsset := false + for { + assets, resp, err := client.ListReleaseAssets(ctx, f.repo.owner, f.repo.name, *release.ID, &github.ListOptions{ + Page: assetsPage, + }) + if err != nil { + return err + } + for _, asset := range assets { + if asset.GetName() == artifactName { + fmt.Printf("Found existing artifact with the name '%s'. Deleting that now.\n", artifactName) + if _, err := client.DeleteReleaseAsset(ctx, f.repo.owner, f.repo.name, asset.GetID()); err != nil { + return fmt.Errorf("failed to delete already existing asset: %w", err) + } + foundAsset = true + break + } + } + if resp.NextPage <= assetsPage || foundAsset { + break + } + assetsPage = resp.NextPage + } + + asset, _, err := client.UploadReleaseAsset(ctx, f.repo.owner, f.repo.name, *release.ID, &github.UploadOptions{Name: artifactName}, file) + if err != nil { + return err + } + fmt.Printf("Asset '%s' uploaded to release '%s' on repository '%s/%s'\nDownload: %s\n", *asset.Name, f.tag, f.repo.owner, f.repo.name, *asset.BrowserDownloadURL) + return nil +} + +func githubRepositoryClient(ctx context.Context, token string) githubRepositoryService { + ts := oauth2.StaticTokenSource( + &oauth2.Token{AccessToken: token}, + ) + tc := oauth2.NewClient(ctx, ts) + + client := github.NewClient(tc) + return client.Repositories +} + +func getPublishGithubFlags(c *cli.Context) (*publishGithubFlags, error) { + metadata, err := config.GenerateMetadata(c) + if err != nil { + return nil, err + } + tag := c.Value("tag").(string) + if tag == "" && metadata.GrafanaVersion != "" { + tag = fmt.Sprintf("v%s", metadata.GrafanaVersion) + } + fullRepo := c.Value("repo").(string) + dryRun := c.Value("dry-run").(bool) + owner := strings.Split(fullRepo, "/")[0] + name := strings.Split(fullRepo, "/")[1] + create := c.Value("create").(bool) + artifactPath := c.Value("path").(string) + if artifactPath == "" { + artifactPath = fmt.Sprintf("grafana-enterprise2-%s-amd64.img", metadata.GrafanaVersion) + fmt.Printf("path argument is not provided, resolving to default %s...\n", artifactPath) + } + return &publishGithubFlags{ + artifactPath: artifactPath, + create: create, + dryRun: dryRun, + tag: tag, + repo: &githubRepo{ + owner: owner, + name: name, + }, + }, nil +} + +func runPublishGithubDryRun(f *publishGithubFlags, token string, c *cli.Context) error { + client := newGithubClient(c.Context, token) + fmt.Println("Dry-Run: Retrieving release on repository by tag") + release, res, err := client.GetReleaseByTag(c.Context, f.repo.owner, f.repo.name, f.tag) + if err != nil && res.StatusCode != 404 { + fmt.Println("Dry-Run: Github communication error:\n", err) + return nil + } + + if release == nil { + if f.create { + fmt.Println("Dry-Run: Release doesn't exist and --create is enabled, so it would try to create the release") + } else { + fmt.Println("Dry-Run: Release doesn't exist and --create is disabled, so it would fail with error") + return nil + } + } + + artifactName := path.Base(f.artifactPath) + fmt.Printf("Dry-Run: Opening file for release: %s\n", f.artifactPath) + _, err = os.Open(f.artifactPath) + if err != nil { + fmt.Println("Dry-Run: Error opening file\n", err) + return nil + } + + fmt.Printf("Dry-Run: Would upload asset '%s' to release '%s' on repo '%s/%s' and return download URL if successful\n", artifactName, f.tag, f.repo.owner, f.repo.name) + return nil +} diff --git a/pkg/build/cmd/publishgithub_test.go b/pkg/build/cmd/publishgithub_test.go new file mode 100644 index 0000000000000..698b8048a05ea --- /dev/null +++ b/pkg/build/cmd/publishgithub_test.go @@ -0,0 +1,238 @@ +package main + +import ( + "context" + "errors" + "io" + "net/http" + "os" + "path/filepath" + "testing" + + "github.com/google/go-github/github" + "github.com/stretchr/testify/assert" + "github.com/urfave/cli/v2" +) + +type githubPublishTestCases struct { + name string + args []string + token string + expectedError error + errorContains string + expectedOutput string + mockedService *mockGithubRepositoryServiceImpl +} + +var mockGithubRepositoryService = &mockGithubRepositoryServiceImpl{} + +func mockGithubRepositoryClient(context.Context, string) githubRepositoryService { + return mockGithubRepositoryService +} + +func TestPublishGithub(t *testing.T) { + t.Setenv("DRONE_BUILD_EVENT", "promote") + t.Setenv("DRONE_TAG", "v1.0.0") + t.Setenv("DRONE_COMMIT", "abcdefgh") + testApp, testPath := setupPublishGithubTests(t) + mockErrUnauthorized := errors.New("401") + + testCases := []githubPublishTestCases{ + { + name: "try to publish without required flags", + errorContains: `Required flags "path, repo" not set`, + }, + { + name: "try to publish without token", + args: []string{"--path", testPath, "--repo", "test/test", "--tag", "v1.0.0"}, + expectedError: errTokenIsEmpty, + }, + { + name: "try to publish with invalid token", + token: "invalid", + args: []string{"--path", testPath, "--repo", "test/test", "--tag", "v1.0.0"}, + mockedService: &mockGithubRepositoryServiceImpl{tagErr: mockErrUnauthorized}, + expectedError: mockErrUnauthorized, + }, + { + name: "try to publish with valid token and nonexisting tag with create disabled", + token: "valid", + args: []string{"--path", testPath, "--repo", "test/test", "--tag", "v1.0.0"}, + mockedService: &mockGithubRepositoryServiceImpl{tagErr: errReleaseNotFound}, + expectedError: errReleaseNotFound, + }, + { + name: "try to publish with valid token and nonexisting tag with create enabled", + token: "valid", + args: []string{"--path", testPath, "--repo", "test/test", "--tag", "v1.0.0", "--create"}, + mockedService: &mockGithubRepositoryServiceImpl{tagErr: errReleaseNotFound}, + }, + { + name: "try to publish with valid token and existing tag", + token: "valid", + args: []string{"--path", testPath, "--repo", "test/test", "--tag", "v1.0.0"}, + }, + { + name: "dry run with invalid token", + token: "invalid", + args: []string{"--dry-run", "--path", testPath, "--repo", "test/test", "--tag", "v1.0.0"}, + mockedService: &mockGithubRepositoryServiceImpl{tagErr: mockErrUnauthorized}, + expectedOutput: "Github communication error", + }, + { + name: "dry run with valid token and nonexisting tag with create disabled", + token: "valid", + args: []string{"--dry-run", "--path", testPath, "--repo", "test/test", "--tag", "v1.0.0"}, + mockedService: &mockGithubRepositoryServiceImpl{tagErr: errReleaseNotFound}, + expectedOutput: "Release doesn't exist", + }, + { + name: "dry run with valid token and nonexisting tag with create enabled", + token: "valid", + args: []string{"--dry-run", "--path", testPath, "--repo", "test/test", "--tag", "v1.0.0", "--create"}, + mockedService: &mockGithubRepositoryServiceImpl{tagErr: errReleaseNotFound}, + expectedOutput: "Would upload asset", + }, + { + name: "dry run with valid token and existing tag", + token: "valid", + args: []string{"--dry-run", "--path", testPath, "--repo", "test/test", "--tag", "v1.0.0"}, + expectedOutput: "Would upload asset", + }, + } + + if os.Getenv("DRONE_COMMIT") == "" { + // this test only works locally due to Drone environment + testCases = append(testCases, + githubPublishTestCases{ + name: "try to publish without tag", + args: []string{"--path", testPath, "--repo", "test/test"}, + expectedError: errTagIsEmpty, + }, + ) + } + + for _, test := range testCases { + t.Run(test.name, func(t *testing.T) { + if test.token != "" { + t.Setenv("GH_TOKEN", test.token) + } + if test.mockedService != nil { + mockGithubRepositoryService = test.mockedService + } else { + mockGithubRepositoryService = &mockGithubRepositoryServiceImpl{} + } + args := []string{"run"} + args = append(args, test.args...) + out, err := captureStdout(t, func() error { + return testApp.Run(args) + }) + if test.expectedOutput != "" { + assert.Contains(t, out, test.expectedOutput) + } + if test.expectedError != nil || test.errorContains != "" { + assert.Error(t, err) + if test.expectedError != nil { + assert.ErrorIs(t, err, test.expectedError) + } + if test.errorContains != "" { + assert.ErrorContains(t, err, test.errorContains) + } + } else { + assert.NoError(t, err) + } + }) + } +} + +func setupPublishGithubTests(t *testing.T) (*cli.App, string) { + t.Helper() + ex, err := os.Executable() + if err != nil { + panic(err) + } + testPath := filepath.Dir(ex) + + newGithubClient = mockGithubRepositoryClient + + testApp := cli.NewApp() + testApp.Action = PublishGithub + testApp.Flags = []cli.Flag{ + &dryRunFlag, + &cli.StringFlag{ + Name: "path", + Required: true, + Usage: "Path to the asset to be published", + }, + &cli.StringFlag{ + Name: "repo", + Required: true, + Usage: "Github repository", + }, + &cli.StringFlag{ + Name: "tag", + Usage: "Release tag (default from metadata)ß", + }, + &cli.BoolFlag{ + Name: "create", + Usage: "Create release if it doesn't exist", + }, + } + return testApp, testPath +} + +func captureStdout(t *testing.T, fn func() error) (string, error) { + t.Helper() + rescueStdout := os.Stdout + r, w, _ := os.Pipe() + os.Stdout = w + err := fn() + werr := w.Close() + if werr != nil { + return "", err + } + out, _ := io.ReadAll(r) + os.Stdout = rescueStdout + return string(out), err +} + +type mockGithubRepositoryServiceImpl struct { + tagErr error + createErr error + uploadErr error +} + +func (m *mockGithubRepositoryServiceImpl) GetReleaseByTag(ctx context.Context, owner string, repo string, tag string) (*github.RepositoryRelease, *github.Response, error) { + var release *github.RepositoryRelease + res := &github.Response{Response: &http.Response{}} + if m.tagErr == nil { + releaseID := int64(1) + release = &github.RepositoryRelease{ID: &releaseID} + } else if errors.Is(m.tagErr, errReleaseNotFound) { + res.StatusCode = 404 + } + return release, res, m.tagErr +} + +func (m *mockGithubRepositoryServiceImpl) CreateRelease(ctx context.Context, owner string, repo string, release *github.RepositoryRelease) (*github.RepositoryRelease, *github.Response, error) { + releaseID := int64(1) + return &github.RepositoryRelease{ID: &releaseID}, &github.Response{}, m.createErr +} + +func (m *mockGithubRepositoryServiceImpl) UploadReleaseAsset(ctx context.Context, owner string, repo string, id int64, opt *github.UploadOptions, file *os.File) (*github.ReleaseAsset, *github.Response, error) { + assetName := "test" + assetUrl := "testurl.com.br" + return &github.ReleaseAsset{Name: &assetName, BrowserDownloadURL: &assetUrl}, &github.Response{}, m.uploadErr +} + +func (m *mockGithubRepositoryServiceImpl) DeleteReleaseAsset(ctx context.Context, owner string, repo string, id int64) (*github.Response, error) { + return nil, nil +} + +func (m *mockGithubRepositoryServiceImpl) ListReleaseAssets(ctx context.Context, owner string, repo string, id int64, opts *github.ListOptions) ([]*github.ReleaseAsset, *github.Response, error) { + resp := github.Response{} + resp.LastPage = 1 + resp.FirstPage = 1 + resp.NextPage = 0 + return []*github.ReleaseAsset{}, &resp, nil +} diff --git a/pkg/build/cmd/publishimages_enterprise2.go b/pkg/build/cmd/publishimages_enterprise2.go new file mode 100644 index 0000000000000..b76b2688d6fab --- /dev/null +++ b/pkg/build/cmd/publishimages_enterprise2.go @@ -0,0 +1,100 @@ +package main + +import ( + "fmt" + "log" + "os" + "os/exec" + + "github.com/grafana/grafana/pkg/build/config" + "github.com/grafana/grafana/pkg/build/docker" + "github.com/grafana/grafana/pkg/build/gcloud" + "github.com/urfave/cli/v2" +) + +func Enterprise2(c *cli.Context) error { + if c.NArg() > 0 { + if err := cli.ShowSubcommandHelp(c); err != nil { + return cli.Exit(err.Error(), 1) + } + return cli.Exit("", 1) + } + + if err := gcloud.ActivateServiceAccount(); err != nil { + return fmt.Errorf("couldn't activate service account, err: %w", err) + } + + metadata, err := config.GenerateMetadata(c) + if err != nil { + return err + } + + buildConfig, err := config.GetBuildConfig(metadata.ReleaseMode.Mode) + if err != nil { + return err + } + + cfg := docker.Config{ + Archs: buildConfig.Docker.Architectures, + Distribution: buildConfig.Docker.Distribution, + DockerHubRepo: c.String("dockerhub-repo"), + Tag: metadata.GrafanaVersion, + } + + err = dockerLoginEnterprise2() + if err != nil { + return err + } + + var distributionStr []string + for _, distribution := range cfg.Distribution { + switch distribution { + case alpine: + distributionStr = append(distributionStr, "") + case ubuntu: + distributionStr = append(distributionStr, "-ubuntu") + default: + return fmt.Errorf("unrecognized distribution %q", distribution) + } + } + + for _, distribution := range distributionStr { + var imageFileNames []string + for _, arch := range cfg.Archs { + imageFilename := fmt.Sprintf("%s:%s%s-%s", cfg.DockerHubRepo, cfg.Tag, distribution, arch) + err := docker.PushImage(imageFilename) + if err != nil { + return err + } + imageFileNames = append(imageFileNames, imageFilename) + } + manifest := fmt.Sprintf("%s:%s%s", cfg.DockerHubRepo, cfg.Tag, distribution) + args := []string{"manifest", "create", manifest} + args = append(args, imageFileNames...) + + //nolint:gosec + cmd := exec.Command("docker", args...) + cmd.Env = append(os.Environ(), "DOCKER_CLI_EXPERIMENTAL=enabled") + if output, err := cmd.CombinedOutput(); err != nil { + return fmt.Errorf("failed to create Docker manifest: %w\n%s", err, output) + } + + err = docker.PushManifest(manifest) + if err != nil { + return err + } + } + + return nil +} + +func dockerLoginEnterprise2() error { + log.Println("Docker login...") + cmd := exec.Command("gcloud", "auth", "configure-docker") + if out, err := cmd.CombinedOutput(); err != nil { + return fmt.Errorf("error logging in to DockerHub: %s %q", out, err) + } + + log.Println("Successful login!") + return nil +} diff --git a/pkg/build/cmd/publishmetrics.go b/pkg/build/cmd/publishmetrics.go index d88911fc32821..9d0576891fde1 100644 --- a/pkg/build/cmd/publishmetrics.go +++ b/pkg/build/cmd/publishmetrics.go @@ -8,8 +8,9 @@ import ( "os" "regexp" - "github.com/grafana/grafana/pkg/build/metrics" "github.com/urfave/cli/v2" + + "github.com/grafana/grafana/pkg/build/metrics" ) func PublishMetrics(c *cli.Context) error { @@ -17,24 +18,24 @@ func PublishMetrics(c *cli.Context) error { input, err := io.ReadAll(os.Stdin) if err != nil { - return cli.NewExitError(fmt.Sprintf("Reading from stdin failed: %s", err), 1) + return cli.Exit(fmt.Sprintf("Reading from stdin failed: %s", err), 1) } reMetrics := regexp.MustCompile(`(?ms)^Metrics: (\{.+\})`) ms := reMetrics.FindSubmatch(input) if len(ms) == 0 { - return cli.NewExitError(fmt.Sprintf("Input on wrong format: %q", string(input)), 1) + return cli.Exit(fmt.Sprintf("Input on wrong format: %q", string(input)), 1) } m := map[string]string{} if err := json.Unmarshal(ms[1], &m); err != nil { - return cli.NewExitError(fmt.Sprintf("decoding metrics failed: %s", err), 1) + return cli.Exit(fmt.Sprintf("decoding metrics failed: %s", err), 1) } log.Printf("Received metrics %+v", m) if err := metrics.Publish(m, apiKey); err != nil { - return cli.NewExitError(fmt.Sprintf("publishing metrics failed: %s", err), 1) + return cli.Exit(fmt.Sprintf("publishing metrics failed: %s", err), 1) } return nil diff --git a/pkg/build/cmd/publishstaticassets.go b/pkg/build/cmd/publishstaticassets.go new file mode 100644 index 0000000000000..5b6eff9f12a28 --- /dev/null +++ b/pkg/build/cmd/publishstaticassets.go @@ -0,0 +1,51 @@ +package main + +import ( + "fmt" + "strings" + + "github.com/grafana/grafana/pkg/build/env" + "github.com/grafana/grafana/pkg/build/gcloud" + "github.com/grafana/grafana/pkg/build/gcloud/storage" + "github.com/urfave/cli/v2" +) + +// PublishStaticAssetsAction Action implements the sub-command "artifacts static-assets". +func PublishStaticAssetsAction(c *cli.Context) error { + if c.NArg() > 0 { + if err := cli.ShowSubcommandHelp(c); err != nil { + return cli.Exit(err.Error(), 1) + } + return cli.Exit("", 1) + } + + staticAssetEditions, err := env.RequireListWithEnvFallback(c, "static-asset-editions", "STATIC_ASSET_EDITIONS") + if err != nil { + return err + } + + if err := gcloud.ActivateServiceAccount(); err != nil { + return fmt.Errorf("error connecting to gcp, %q", err) + } + + cfg := publishConfig{ + srcBucket: c.String("src-bucket"), + staticAssetsBucket: c.String("static-assets-bucket"), + staticAssetEditions: staticAssetEditions, + tag: strings.TrimPrefix(c.String("tag"), "v"), + } + + gcs, err := storage.New() + if err != nil { + return err + } + bucket := gcs.Bucket(cfg.staticAssetsBucket) + + for _, edition := range staticAssetEditions { + if err := gcs.CopyRemoteDir(c.Context, gcs.Bucket(cfg.srcBucket), fmt.Sprintf("artifacts/static-assets/%s/%s", edition, cfg.tag), bucket, fmt.Sprintf("%s/%s", edition, cfg.tag)); err != nil { + return err + } + } + + return nil +} diff --git a/pkg/build/cmd/publishstorybook.go b/pkg/build/cmd/publishstorybook.go new file mode 100644 index 0000000000000..b147d9a7b4029 --- /dev/null +++ b/pkg/build/cmd/publishstorybook.go @@ -0,0 +1,64 @@ +package main + +import ( + "fmt" + "log" + "strings" + + "github.com/grafana/grafana/pkg/build/gcloud" + "github.com/grafana/grafana/pkg/build/gcloud/storage" + "github.com/grafana/grafana/pkg/build/versions" + "github.com/urfave/cli/v2" +) + +// PublishStorybookAction Action implements the sub-command "publish-artifacts". +func PublishStorybookAction(c *cli.Context) error { + if c.NArg() > 0 { + if err := cli.ShowSubcommandHelp(c); err != nil { + return cli.Exit(err.Error(), 1) + } + return cli.Exit("", 1) + } + + if err := gcloud.ActivateServiceAccount(); err != nil { + return fmt.Errorf("error connecting to gcp, %q", err) + } + + cfg := publishConfig{ + srcBucket: c.String("src-bucket"), + storybookBucket: c.String("storybook-bucket"), + tag: strings.TrimPrefix(c.String("tag"), "v"), + } + + gcs, err := storage.New() + if err != nil { + return err + } + bucket := gcs.Bucket(cfg.storybookBucket) + if err := gcs.CopyRemoteDir(c.Context, gcs.Bucket(cfg.srcBucket), fmt.Sprintf("artifacts/storybook/v%s", cfg.tag), bucket, cfg.tag); err != nil { + return err + } + + if latest, err := isLatest(cfg); err != nil && latest { + log.Printf("Copying storybooks to latest...") + if err := gcs.CopyRemoteDir(c.Context, gcs.Bucket(cfg.srcBucket), fmt.Sprintf("artifacts/storybook/v%s", cfg.tag), bucket, "latest"); err != nil { + return err + } + } else { + return err + } + + return nil +} + +func isLatest(cfg publishConfig) (bool, error) { + stableVersion, err := versions.GetLatestVersion(versions.LatestStableVersionURL) + if err != nil { + return false, err + } + isLatest, err := versions.IsGreaterThanOrEqual(cfg.tag, stableVersion) + if err != nil { + return false, err + } + return isLatest, nil +} diff --git a/pkg/build/cmd/storestorybook.go b/pkg/build/cmd/storestorybook.go index 0daeb7080f64c..65adfa1fbb77b 100644 --- a/pkg/build/cmd/storestorybook.go +++ b/pkg/build/cmd/storestorybook.go @@ -13,7 +13,7 @@ import ( func StoreStorybook(c *cli.Context) error { deployment := c.String("deployment") - metadata, err := GenerateMetadata(c) + metadata, err := config.GenerateMetadata(c) if err != nil { return err } diff --git a/pkg/build/cmd/uploadcdn.go b/pkg/build/cmd/uploadcdn.go new file mode 100644 index 0000000000000..8b8ddb0cd81e3 --- /dev/null +++ b/pkg/build/cmd/uploadcdn.go @@ -0,0 +1,75 @@ +package main + +import ( + "fmt" + "log" + "os" + "path/filepath" + + "github.com/grafana/grafana/pkg/build/config" + "github.com/grafana/grafana/pkg/build/gcloud/storage" + "github.com/urfave/cli/v2" +) + +// UploadCDN implements the sub-command "upload-cdn". +func UploadCDN(c *cli.Context) error { + if c.NArg() > 0 { + if err := cli.ShowSubcommandHelp(c); err != nil { + return cli.Exit(err.Error(), 1) + } + return cli.Exit("", 1) + } + + metadata, err := config.GenerateMetadata(c) + if err != nil { + return err + } + + version := metadata.GrafanaVersion + if err != nil { + return cli.Exit(err.Error(), 1) + } + + buildConfig, err := config.GetBuildConfig(metadata.ReleaseMode.Mode) + if err != nil { + return err + } + + edition := os.Getenv("EDITION") + log.Printf("Uploading Grafana CDN Assets, version %s, %s edition...", version, edition) + + editionPath := "" + + switch config.Edition(edition) { + case config.EditionOSS: + editionPath = "grafana-oss" + case config.EditionEnterprise: + editionPath = "grafana" + case config.EditionEnterprise2: + editionPath = os.Getenv("ENTERPRISE2_CDN_PATH") + default: + panic(fmt.Sprintf("unrecognized edition %q", edition)) + } + + gcs, err := storage.New() + if err != nil { + return err + } + + bucket := gcs.Bucket(buildConfig.Buckets.CDNAssets) + srcPath := buildConfig.Buckets.CDNAssetsDir + srcPath = filepath.Join(srcPath, editionPath, version) + + if err := gcs.DeleteDir(c.Context, bucket, srcPath); err != nil { + return err + } + log.Printf("Successfully cleaned source: %s/%s\n", buildConfig.Buckets.CDNAssets, srcPath) + + if err := gcs.CopyLocalDir(c.Context, "./public", bucket, srcPath, false); err != nil { + return err + } + + log.Printf("Successfully uploaded cdn static assets to: %s/%s!\n", buildConfig.Buckets.CDNAssets, srcPath) + + return nil +} diff --git a/pkg/build/cmd/uploadpackages.go b/pkg/build/cmd/uploadpackages.go new file mode 100644 index 0000000000000..2c8f94d347f50 --- /dev/null +++ b/pkg/build/cmd/uploadpackages.go @@ -0,0 +1,213 @@ +package main + +import ( + "encoding/base64" + "fmt" + "log" + "os" + "os/exec" + "path/filepath" + "strings" + + "github.com/grafana/grafana/pkg/build/config" + "github.com/grafana/grafana/pkg/build/droneutil" + "github.com/grafana/grafana/pkg/build/gcloud" + "github.com/grafana/grafana/pkg/build/packaging" + "github.com/urfave/cli/v2" +) + +const releaseFolder = "release" +const mainFolder = "main" +const releaseBranchFolder = "prerelease" + +type uploadConfig struct { + config.Config + + edition config.Edition + versionMode config.VersionMode + gcpKey string + distDir string + versionFolder string +} + +// UploadPackages implements the sub-command "upload-packages". +func UploadPackages(c *cli.Context) error { + if c.NArg() > 0 { + if err := cli.ShowSubcommandHelp(c); err != nil { + return cli.Exit(err.Error(), 1) + } + return cli.Exit("", 1) + } + + gcpKeyB64 := strings.TrimSpace(os.Getenv("GCP_KEY")) + if gcpKeyB64 == "" { + return cli.Exit("the environment variable GCP_KEY must be set", 1) + } + gcpKeyB, err := base64.StdEncoding.DecodeString(gcpKeyB64) + if err != nil { + return cli.Exit("failed to base64 decode $GCP_KEY", 1) + } + gcpKey := string(gcpKeyB) + + distDir, err := filepath.Abs("dist") + if err != nil { + return cli.Exit(err.Error(), 1) + } + + metadata, err := config.GenerateMetadata(c) + if err != nil { + return err + } + + version := metadata.GrafanaVersion + + releaseMode, err := metadata.GetReleaseMode() + if err != nil { + return cli.Exit(err.Error(), 1) + } + + releaseModeConfig, err := config.GetBuildConfig(releaseMode.Mode) + if err != nil { + return cli.Exit(err.Error(), 1) + } + + var edition config.Edition + if e, ok := os.LookupEnv("EDITION"); ok { + edition = config.Edition(e) + } + + if c.Bool("enterprise2") { + edition = config.EditionEnterprise2 + } + + if edition == "" { + return fmt.Errorf("both EDITION envvar and '--enterprise2' flag are missing. At least one of those is required") + } + + // TODO: Verify config values + cfg := uploadConfig{ + Config: config.Config{ + Version: version, + Bucket: releaseModeConfig.Buckets.Artifacts, + }, + edition: edition, + versionMode: releaseMode.Mode, + gcpKey: gcpKey, + distDir: distDir, + } + + event, err := droneutil.GetDroneEventFromEnv() + if err != nil { + return err + } + + if cfg.edition == config.EditionEnterprise2 { + cfg.Bucket, err = bucketForEnterprise2(releaseModeConfig, event) + if err != nil { + return err + } + } + + cfg.versionFolder, err = getVersionFolder(cfg, event) + if err != nil { + return err + } + + if err := uploadPackages(cfg); err != nil { + return cli.Exit(err.Error(), 1) + } + + log.Println("Successfully uploaded packages!") + return nil +} + +// Corner case for custom enterprise2 mode +func bucketForEnterprise2(releaseModeConfig *config.BuildConfig, event string) (string, error) { + if event == config.Custom { + buildConfig, err := config.GetBuildConfig(config.ReleaseBranchMode) + if err != nil { + return "", err + } + return buildConfig.Buckets.ArtifactsEnterprise2, nil + } + + if releaseModeConfig.Buckets.ArtifactsEnterprise2 != "" { + return releaseModeConfig.Buckets.ArtifactsEnterprise2, nil + } + + return "", fmt.Errorf("enterprise2 bucket var doesn't exist") +} + +func getVersionFolder(cfg uploadConfig, event string) (string, error) { + switch cfg.versionMode { + case config.TagMode, config.CloudMode: + return releaseFolder, nil + case config.MainMode, config.DownstreamMode: + return mainFolder, nil + case config.ReleaseBranchMode: + return releaseBranchFolder, nil + default: + // Corner case for custom enterprise2 mode + if event == config.Custom && cfg.versionMode == config.Enterprise2Mode { + return releaseFolder, nil + } + return "", fmt.Errorf("unrecognized version mode: %s", cfg.versionMode) + } +} + +func uploadPackages(cfg uploadConfig) error { + log.Printf("Uploading Grafana packages, version %s, %s edition, %s mode...\n", cfg.Version, cfg.edition, + cfg.versionMode) + + if err := gcloud.ActivateServiceAccount(); err != nil { + return fmt.Errorf("couldn't activate service account, err: %w", err) + } + + edition := strings.ToLower(string(cfg.edition)) + + var sfx string + switch cfg.edition { + case config.EditionOSS: + case config.EditionEnterprise: + sfx = "-enterprise" + case config.EditionEnterprise2: + sfx = "-enterprise2" + default: + panic(fmt.Sprintf("unrecognized edition %q", cfg.edition)) + } + matches, err := filepath.Glob(filepath.Join(cfg.distDir, fmt.Sprintf("grafana%s*", sfx))) + if err != nil { + return fmt.Errorf("failed to list packages: %w", err) + } + fpaths := []string{} + rePkg := packaging.PackageRegexp(cfg.edition) + for _, fpath := range matches { + fname := filepath.Base(fpath) + if strings.Contains(fname, "latest") || !rePkg.MatchString(fname) { + log.Printf("Ignoring file %q\n", fpath) + continue + } + + fpaths = append(fpaths, fpath) + } + + var tag, gcsPath string + droneTag := strings.TrimSpace(os.Getenv("DRONE_TAG")) + if droneTag != "" { + tag = droneTag + gcsPath = fmt.Sprintf("gs://%s/%s/%s/%s", cfg.Bucket, tag, edition, cfg.versionFolder) + } else { + gcsPath = fmt.Sprintf("gs://%s/%s/%s/", cfg.Bucket, edition, cfg.versionFolder) + } + log.Printf("Uploading %d file(s) to GCS (%s)...\n", len(fpaths), gcsPath) + + args := []string{"-m", "cp"} + args = append(args, fpaths...) + args = append(args, gcsPath) + cmd := exec.Command("gsutil", args...) + if output, err := cmd.CombinedOutput(); err != nil { + return fmt.Errorf("failed to upload files to GCS: %s", output) + } + + return nil +} diff --git a/pkg/build/cmd/uploadpackages_test.go b/pkg/build/cmd/uploadpackages_test.go new file mode 100644 index 0000000000000..d8147187cbfa4 --- /dev/null +++ b/pkg/build/cmd/uploadpackages_test.go @@ -0,0 +1,67 @@ +package main + +import ( + "errors" + "fmt" + "testing" + + "github.com/grafana/grafana/pkg/build/config" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func Test_getVersionFolder(t *testing.T) { + type args struct { + cfg uploadConfig + event string + versionFolder string + } + tests := []struct { + name string + args args + err error + }{ + {"tag mode", args{uploadConfig{versionMode: config.TagMode}, "", releaseFolder}, nil}, + {"main mode", args{uploadConfig{versionMode: config.MainMode}, "", mainFolder}, nil}, + {"downstream mode", args{uploadConfig{versionMode: config.DownstreamMode}, "", mainFolder}, nil}, + {"release branch mode", args{uploadConfig{versionMode: config.ReleaseBranchMode}, "", releaseBranchFolder}, nil}, + {"enterprise pro mode", args{uploadConfig{versionMode: config.Enterprise2Mode}, config.Custom, releaseFolder}, nil}, + {"cloud mode", args{uploadConfig{versionMode: config.CloudMode}, "", releaseFolder}, nil}, + {"unrecognised version mode", args{uploadConfig{versionMode: "foo"}, config.Custom, ""}, errors.New("")}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + versionMode, err := getVersionFolder(tt.args.cfg, tt.args.event) + if tt.err != nil { + require.Error(t, err) + } + require.Equal(t, versionMode, tt.args.versionFolder) + }) + } +} + +func Test_checkForEnterprise2Edition(t *testing.T) { + type args struct { + releaseModeConfig *config.BuildConfig + event string + } + tests := []struct { + name string + args args + want string + err error + }{ + {"event is not custom", args{releaseModeConfig: &config.BuildConfig{Buckets: config.Buckets{ArtifactsEnterprise2: "dummy"}}}, "dummy", nil}, + {"event is not custom and string is empty", args{releaseModeConfig: &config.BuildConfig{Buckets: config.Buckets{ArtifactsEnterprise2: ""}}}, "", fmt.Errorf("enterprise2 bucket var doesn't exist")}, + {"event is custom", args{releaseModeConfig: nil, event: "custom"}, "grafana-downloads-enterprise2", nil}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := bucketForEnterprise2(tt.args.releaseModeConfig, tt.args.event) + if tt.err != nil { + require.Error(t, err) + } + assert.Equalf(t, tt.want, got, "bucketForEnterprise2(%v, %v)", tt.args.releaseModeConfig, tt.args.event) + }) + } +} diff --git a/pkg/build/cmd/verifydrone.go b/pkg/build/cmd/verifydrone.go index ed34e0f77df53..19da6fb5a35e1 100644 --- a/pkg/build/cmd/verifydrone.go +++ b/pkg/build/cmd/verifydrone.go @@ -13,10 +13,11 @@ import ( "github.com/google/go-cmp/cmp" - "github.com/grafana/grafana/pkg/build/fsutil" cliv1 "github.com/urfave/cli" "github.com/urfave/cli/v2" "gopkg.in/yaml.v3" + + "github.com/grafana/grafana/pkg/build/fsutil" ) func VerifyDrone(c *cli.Context) error { @@ -24,7 +25,7 @@ func VerifyDrone(c *cli.Context) error { const backup = ".drone.yml.bak" if err := fsutil.CopyFile(yml, backup); err != nil { - return cli.NewExitError(fmt.Sprintf("failed to copy %s to %s: %s", yml, backup, err), 1) + return cli.Exit(fmt.Sprintf("failed to copy %s to %s: %s", yml, backup, err), 1) } defer func() { if err := os.Remove(yml); err != nil { @@ -73,7 +74,7 @@ func readConfig(fpath string) ([]map[string]interface{}, error) { //nolint:gosec f, err := os.Open(fpath) if err != nil { - return nil, cli.NewExitError(fmt.Sprintf("failed to read %s: %s", fpath, err), 1) + return nil, cli.Exit(fmt.Sprintf("failed to read %s: %s", fpath, err), 1) } defer func() { if err := f.Close(); err != nil { @@ -90,7 +91,7 @@ func readConfig(fpath string) ([]map[string]interface{}, error) { if errors.Is(err, io.EOF) { break } - return nil, cli.NewExitError(fmt.Sprintf("Failed to decode %s: %s", fpath, err), 1) + return nil, cli.Exit(fmt.Sprintf("Failed to decode %s: %s", fpath, err), 1) } if m["kind"] == "signature" { @@ -118,7 +119,7 @@ func verifyYAML(yml, backup string) error { } if !cmp.Equal(c1, c2) { - return cli.NewExitError(fmt.Sprintf("%s is out of sync with .drone.star - regenerate it with drone starlark convert", + return cli.Exit(fmt.Sprintf("%s is out of sync with .drone.star - regenerate it with drone starlark convert", yml), 1) } diff --git a/pkg/build/cmd/verifystarlark.go b/pkg/build/cmd/verifystarlark.go new file mode 100644 index 0000000000000..ff33a77a3afc5 --- /dev/null +++ b/pkg/build/cmd/verifystarlark.go @@ -0,0 +1,142 @@ +package main + +import ( + "context" + "errors" + "fmt" + "io/fs" + "os/exec" + "path/filepath" + "strings" + + "github.com/urfave/cli/v2" +) + +func mapSlice[I any, O any](a []I, f func(I) O) []O { + o := make([]O, len(a)) + for i, e := range a { + o[i] = f(e) + } + return o +} + +// VerifyStarlark is the CLI Action for verifying Starlark files in a workspace. +// It expects a single context argument which is the path to the workspace. +// The actual verification procedure can return multiple errors which are +// joined together to be one holistic error for the action. +func VerifyStarlark(c *cli.Context) error { + if c.NArg() != 1 { + var message string + if c.NArg() == 0 { + message = "ERROR: missing required argument " + } + if c.NArg() > 1 { + message = "ERROR: too many arguments" + } + + if err := cli.ShowSubcommandHelp(c); err != nil { + return err + } + + return cli.Exit(message, 1) + } + + workspace := c.Args().Get(0) + verificationErrs, executionErr := verifyStarlark(c.Context, workspace, buildifierLintCommand) + if executionErr != nil { + return executionErr + } + + if len(verificationErrs) == 0 { + return nil + } + + noun := "file" + if len(verificationErrs) > 1 { + noun += "s" + } + + return fmt.Errorf("verification failed for %d %s:\n%s", + len(verificationErrs), + noun, + strings.Join( + mapSlice(verificationErrs, func(e error) string { return e.Error() }), + "\n", + )) +} + +type commandFunc = func(path string) (command string, args []string) + +func buildifierLintCommand(path string) (string, []string) { + return "buildifier", []string{"-lint", "warn", "-mode", "check", path} +} + +// verifyStarlark walks all directories starting at provided workspace path and +// verifies any Starlark files it finds. +// Starlark files are assumed to end with the .star extension. +// The verification relies on linting frovided by the 'buildifier' binary which +// must be in the PATH. +// A slice of verification errors are returned, one for each file that failed verification. +// If any execution of the `buildifier` command fails, this is returned separately. +// commandFn is executed on every Starlark file to determine the command and arguments to be executed. +// The caller is trusted and it is the callers responsibility to ensure that the resulting command is safe to execute. +func verifyStarlark(ctx context.Context, workspace string, commandFn commandFunc) ([]error, error) { + var verificationErrs []error + + // All errors from filepath.WalkDir are filtered by the fs.WalkDirFunc. + // Lstat or ReadDir errors are reported as verificationErrors. + // If any execution of the `buildifier` command fails or if the context is cancelled, + // it is reported as an error and any verification of subsequent files is skipped. + err := filepath.WalkDir(workspace, func(path string, d fs.DirEntry, err error) error { + // Skip verification of the file or files within the directory if there is an error + // returned by Lstat or ReadDir. + if err != nil { + verificationErrs = append(verificationErrs, err) + return nil + } + + if d.IsDir() { + return nil + } + + if filepath.Ext(path) == ".star" { + command, args := commandFn(path) + // The caller is trusted. + //nolint:gosec + cmd := exec.CommandContext(ctx, command, args...) + cmd.Dir = workspace + + _, err = cmd.Output() + if err == nil { // No error, early return. + return nil + } + + // The error returned from cmd.Output() is never wrapped. + //nolint:errorlint + if err, ok := err.(*exec.ExitError); ok { + switch err.ExitCode() { + // Case comments are informed by the output of `buildifier --help` + case 1: // syntax errors in input + verificationErrs = append(verificationErrs, errors.New(string(err.Stderr))) + return nil + case 2: // usage errors: invoked incorrectly + return fmt.Errorf("command %q: %s", cmd, err.Stderr) + case 3: // unexpected runtime errors: file I/O problems or internal bugs + return fmt.Errorf("command %q: %s", cmd, err.Stderr) + case 4: // check mode failed (reformat is needed) + verificationErrs = append(verificationErrs, errors.New(string(err.Stderr))) + return nil + default: + return fmt.Errorf("command %q: %s", cmd, err.Stderr) + } + } + + // Error was not an exit error from the command. + return fmt.Errorf("command %q: %v", cmd, err) + } + + return nil + }) + + return verificationErrs, err +} diff --git a/pkg/build/cmd/verifystarlark_test.go b/pkg/build/cmd/verifystarlark_test.go new file mode 100644 index 0000000000000..1121ca5bd646f --- /dev/null +++ b/pkg/build/cmd/verifystarlark_test.go @@ -0,0 +1,137 @@ +//go:build requires_buildifier + +package main + +import ( + "context" + "os" + "path/filepath" + "strings" + "testing" + + "github.com/stretchr/testify/require" +) + +func TestVerifyStarlark(t *testing.T) { + t.Run("execution errors", func(t *testing.T) { + t.Run("invalid usage", func(t *testing.T) { + ctx := context.Background() + workspace := t.TempDir() + err := os.WriteFile(filepath.Join(workspace, "ignored.star"), []byte{}, os.ModePerm) + if err != nil { + t.Fatalf(err.Error()) + } + + _, executionErr := verifyStarlark(ctx, workspace, func(string) (string, []string) { return "buildifier", []string{"--invalid"} }) + if executionErr == nil { + t.Fatalf("Expected execution error but got none") + } + }) + + t.Run("context cancellation", func(t *testing.T) { + ctx, cancel := context.WithCancel(context.Background()) + workspace := t.TempDir() + err := os.WriteFile(filepath.Join(workspace, "ignored.star"), []byte{}, os.ModePerm) + if err != nil { + t.Fatalf(err.Error()) + } + err = os.WriteFile(filepath.Join(workspace, "other-ignored.star"), []byte{}, os.ModePerm) + if err != nil { + t.Fatalf(err.Error()) + } + cancel() + + _, executionErr := verifyStarlark(ctx, workspace, buildifierLintCommand) + if executionErr == nil { + t.Fatalf("Expected execution error but got none") + } + }) + }) + + t.Run("verification errors", func(t *testing.T) { + t.Run("a single file with lint", func(t *testing.T) { + ctx := context.Background() + workspace := t.TempDir() + + invalidContent := []byte(`load("scripts/drone/other.star", "function") + +function()`) + err := os.WriteFile(filepath.Join(workspace, "has-lint.star"), invalidContent, os.ModePerm) + if err != nil { + t.Fatalf(err.Error()) + } + + verificationErrs, executionErr := verifyStarlark(ctx, workspace, buildifierLintCommand) + if executionErr != nil { + t.Fatalf("Unexpected execution error: %v", executionErr) + } + if len(verificationErrs) == 0 { + t.Fatalf(`"has-lint.star" requires linting but the verifyStarlark function provided no linting error`) + } + if len(verificationErrs) > 1 { + t.Fatalf(`verifyStarlark returned multiple errors for the "has-lint.star" file but only one was expected: %v`, verificationErrs) + } + if !strings.Contains(verificationErrs[0].Error(), "has-lint.star:1: module-docstring: The file has no module docstring.") { + t.Fatalf(`"has-lint.star" is missing a module docstring but the verifyStarlark function linting error did not mention this, instead we got: %v`, verificationErrs[0]) + } + }) + + t.Run("no files with lint", func(t *testing.T) { + ctx := context.Background() + workspace := t.TempDir() + + content := []byte(`""" +This module does nothing. +""" + +load("scripts/drone/other.star", "function") + +function() +`) + require.NoError(t, os.WriteFile(filepath.Join(workspace, "no-lint.star"), content, os.ModePerm)) + + verificationErrs, executionErr := verifyStarlark(ctx, workspace, buildifierLintCommand) + if executionErr != nil { + t.Fatalf("Unexpected execution error: %v", executionErr) + } + if len(verificationErrs) != 0 { + t.Log(`"no-lint.star" has no lint but the verifyStarlark function provided at least one error`) + for _, err := range verificationErrs { + t.Log(err) + } + t.FailNow() + } + }) + + t.Run("multiple files with lint", func(t *testing.T) { + ctx := context.Background() + workspace := t.TempDir() + + invalidContent := []byte(`load("scripts/drone/other.star", "function") + +function()`) + require.NoError(t, os.WriteFile(filepath.Join(workspace, "has-lint.star"), invalidContent, os.ModePerm)) + require.NoError(t, os.WriteFile(filepath.Join(workspace, "has-lint2.star"), invalidContent, os.ModePerm)) + + verificationErrs, executionErr := verifyStarlark(ctx, workspace, buildifierLintCommand) + if executionErr != nil { + t.Fatalf("Unexpected execution error: %v", executionErr) + } + if len(verificationErrs) == 0 { + t.Fatalf(`Two files require linting but the verifyStarlark function provided no linting error`) + } + if len(verificationErrs) == 1 { + t.Fatalf(`Two files require linting but the verifyStarlark function provided only one linting error: %v`, verificationErrs[0]) + } + if len(verificationErrs) > 2 { + t.Fatalf(`verifyStarlark returned more errors than expected: %v`, verificationErrs) + } + if !strings.Contains(verificationErrs[0].Error(), "has-lint.star:1: module-docstring: The file has no module docstring.") { + t.Errorf(`"has-lint.star" is missing a module docstring but the verifyStarlark function linting error did not mention this, instead we got: %v`, verificationErrs[0]) + } + if !strings.Contains(verificationErrs[1].Error(), "has-lint2.star:1: module-docstring: The file has no module docstring.") { + t.Fatalf(`"has-lint2.star" is missing a module docstring but the verifyStarlark function linting error did not mention this, instead we got: %v`, verificationErrs[0]) + } + }) + }) +} diff --git a/pkg/build/cmd/verifystorybook.go b/pkg/build/cmd/verifystorybook.go new file mode 100644 index 0000000000000..c074bb768573f --- /dev/null +++ b/pkg/build/cmd/verifystorybook.go @@ -0,0 +1,33 @@ +// Package verifystorybook contains the sub-command "verify-storybook". +package main + +import ( + "fmt" + "log" + "path/filepath" + + "github.com/urfave/cli/v2" + + "github.com/grafana/grafana/pkg/infra/fs" +) + +// VerifyStorybook Action implements the sub-command "verify-storybook". +func VerifyStorybook(c *cli.Context) error { + const grafanaDir = "." + + paths := []string{ + "packages/grafana-ui/dist/storybook/index.html", + "packages/grafana-ui/dist/storybook/iframe.html"} + for _, p := range paths { + exists, err := fs.Exists(filepath.Join(grafanaDir, p)) + if err != nil { + return cli.Exit(fmt.Sprintf("failed to verify Storybook build: %s", err), 1) + } + if !exists { + return fmt.Errorf("failed to verify Storybook build, missing %q", p) + } + } + + log.Printf("Successfully verified Storybook integrity") + return nil +} diff --git a/pkg/build/config/config.go b/pkg/build/config/config.go index 7c8b4b133bf8d..7aa4176e13a5f 100644 --- a/pkg/build/config/config.go +++ b/pkg/build/config/config.go @@ -1,20 +1,18 @@ package config type Config struct { - Version string - Bucket string - DebRepoBucket string - DebDBBucket string - RPMRepoBucket string - GPGPassPath string - GPGPrivateKey string - GPGPublicKey string - GCPKeyFile string - NumWorkers int - GitHubUser string - GitHubToken string - PullEnterprise bool - NetworkConcurrency bool - PackageVersion string - SignPackages bool + Version string + Bucket string + DebRepoBucket string + DebDBBucket string + RPMRepoBucket string + GPGPassPath string + GPGPrivateKey string + GPGPublicKey string + NumWorkers int + GitHubUser string + GitHubToken string + PullEnterprise bool + PackageVersion string + SignPackages bool } diff --git a/pkg/build/config/genmetadata.go b/pkg/build/config/genmetadata.go new file mode 100644 index 0000000000000..885a13de514f6 --- /dev/null +++ b/pkg/build/config/genmetadata.go @@ -0,0 +1,102 @@ +package config + +import ( + "fmt" + "os" + "strings" + + "github.com/grafana/grafana/pkg/build/droneutil" + "github.com/urfave/cli/v2" +) + +func GenerateMetadata(c *cli.Context) (Metadata, error) { + var metadata Metadata + version := "" + + event, err := droneutil.GetDroneEventFromEnv() + if err != nil { + return Metadata{}, err + } + + tag, ok := os.LookupEnv("DRONE_TAG") + if !ok { + fmt.Println("DRONE_TAG envvar not present, %w", err) + } + + var releaseMode ReleaseMode + switch event { + case string(PullRequestMode): + releaseMode = ReleaseMode{Mode: PullRequestMode} + case Push: + mode, err := CheckDroneTargetBranch() + if err != nil { + return Metadata{}, err + } + releaseMode = ReleaseMode{Mode: mode} + case Custom: + if edition, _ := os.LookupEnv("EDITION"); edition == string(EditionEnterprise2) { + releaseMode = ReleaseMode{Mode: Enterprise2Mode} + if tag != "" { + version = strings.TrimPrefix(tag, "v") + } + break + } + mode, err := CheckDroneTargetBranch() + if err != nil { + return Metadata{}, err + } + // if there is a custom event targeting the main branch, that's an enterprise downstream build + if mode == MainBranch { + releaseMode = ReleaseMode{Mode: DownstreamMode} + } else { + releaseMode = ReleaseMode{Mode: mode} + } + case Tag, Promote: + if tag == "" { + return Metadata{}, fmt.Errorf("DRONE_TAG envvar not present for a tag/promotion event, %w", err) + } + version = strings.TrimPrefix(tag, "v") + mode, err := CheckSemverSuffix() + if err != nil { + return Metadata{}, err + } + releaseMode = mode + case Cronjob: + releaseMode = ReleaseMode{Mode: CronjobMode} + } + + if version == "" { + version, err = generateVersionFromBuildID() + if err != nil { + return Metadata{}, err + } + } + + currentCommit, err := GetDroneCommit() + if err != nil { + return Metadata{}, err + } + metadata = Metadata{ + GrafanaVersion: version, + ReleaseMode: releaseMode, + GrabplVersion: c.App.Version, + CurrentCommit: currentCommit, + } + + fmt.Printf("building Grafana version: %s, release mode: %+v\n", metadata.GrafanaVersion, metadata.ReleaseMode) + + return metadata, nil +} + +func generateVersionFromBuildID() (string, error) { + buildID, ok := os.LookupEnv("DRONE_BUILD_NUMBER") + if !ok { + return "", fmt.Errorf("unable to get DRONE_BUILD_NUMBER environmental variable") + } + var err error + version, err := GetGrafanaVersion(buildID, ".") + if err != nil { + return "", err + } + return version, nil +} diff --git a/pkg/build/config/genmetadata_test.go b/pkg/build/config/genmetadata_test.go new file mode 100644 index 0000000000000..605b68496c703 --- /dev/null +++ b/pkg/build/config/genmetadata_test.go @@ -0,0 +1,81 @@ +package config + +import ( + "flag" + "os" + "testing" + + "github.com/stretchr/testify/require" + "github.com/urfave/cli/v2" +) + +const ( + DroneBuildEvent = "DRONE_BUILD_EVENT" + DroneTargetBranch = "DRONE_TARGET_BRANCH" + DroneTag = "DRONE_TAG" + DroneSemverPrerelease = "DRONE_SEMVER_PRERELEASE" + DroneBuildNumber = "DRONE_BUILD_NUMBER" +) + +const ( + hashedGrafanaVersion = "9.2.0-12345pre" + versionedBranch = "v9.2.x" +) + +func TestGetMetadata(t *testing.T) { + tcs := []struct { + envMap map[string]string + expVersion string + mode ReleaseMode + }{ + {map[string]string{DroneBuildEvent: PullRequest, DroneTargetBranch: "", DroneTag: "", DroneSemverPrerelease: "", DroneBuildNumber: "12345"}, hashedGrafanaVersion, ReleaseMode{Mode: PullRequestMode}}, + {map[string]string{DroneBuildEvent: Push, DroneTargetBranch: versionedBranch, DroneTag: "", DroneSemverPrerelease: "", DroneBuildNumber: "12345"}, hashedGrafanaVersion, ReleaseMode{Mode: ReleaseBranchMode}}, + {map[string]string{DroneBuildEvent: Push, DroneTargetBranch: MainBranch, DroneTag: "", DroneSemverPrerelease: "", DroneBuildNumber: "12345"}, hashedGrafanaVersion, ReleaseMode{Mode: MainMode}}, + {map[string]string{DroneBuildEvent: Custom, DroneTargetBranch: versionedBranch, DroneTag: "", DroneSemverPrerelease: "", DroneBuildNumber: "12345"}, hashedGrafanaVersion, ReleaseMode{Mode: ReleaseBranchMode}}, + {map[string]string{DroneBuildEvent: Custom, DroneTargetBranch: MainBranch, DroneTag: "", DroneSemverPrerelease: "", DroneBuildNumber: "12345"}, hashedGrafanaVersion, ReleaseMode{Mode: DownstreamMode}}, + {map[string]string{DroneBuildEvent: Custom, DroneTargetBranch: MainBranch, DroneTag: "", DroneSemverPrerelease: "", DroneBuildNumber: "12345", "EDITION": string(EditionEnterprise2)}, hashedGrafanaVersion, ReleaseMode{Mode: Enterprise2Mode}}, + {map[string]string{DroneBuildEvent: Tag, DroneTargetBranch: "", DroneTag: "v9.2.0", DroneSemverPrerelease: "", DroneBuildNumber: "12345"}, "9.2.0", ReleaseMode{Mode: TagMode, IsBeta: false, IsTest: false}}, + {map[string]string{DroneBuildEvent: Tag, DroneTargetBranch: "", DroneTag: "v9.2.0-beta", DroneSemverPrerelease: "beta", DroneBuildNumber: "12345"}, "9.2.0-beta", ReleaseMode{Mode: TagMode, IsBeta: true, IsTest: false}}, + {map[string]string{DroneBuildEvent: Tag, DroneTargetBranch: "", DroneTag: "v9.2.0-test", DroneSemverPrerelease: "test", DroneBuildNumber: "12345"}, "9.2.0-test", ReleaseMode{Mode: TagMode, IsBeta: false, IsTest: true}}, + {map[string]string{DroneBuildEvent: Promote, DroneTargetBranch: "", DroneTag: "v9.2.0", DroneSemverPrerelease: "", DroneBuildNumber: "12345"}, "9.2.0", ReleaseMode{Mode: TagMode, IsBeta: false, IsTest: false}}, + {map[string]string{DroneBuildEvent: Promote, DroneTargetBranch: "", DroneTag: "v9.2.0-beta", DroneSemverPrerelease: "beta", DroneBuildNumber: "12345"}, "9.2.0-beta", ReleaseMode{Mode: TagMode, IsBeta: true, IsTest: false}}, + {map[string]string{DroneBuildEvent: Promote, DroneTargetBranch: "", DroneTag: "v9.2.0-test", DroneSemverPrerelease: "test", DroneBuildNumber: "12345"}, "9.2.0-test", ReleaseMode{Mode: TagMode, IsBeta: false, IsTest: true}}, + } + + ctx := cli.NewContext(cli.NewApp(), &flag.FlagSet{}, nil) + for _, tc := range tcs { + t.Run("Should return valid metadata, ", func(t *testing.T) { + setUpEnv(t, tc.envMap) + testMetadata(t, ctx, tc.expVersion, tc.mode) + }) + } +} + +func testMetadata(t *testing.T, ctx *cli.Context, version string, releaseMode ReleaseMode) { + t.Helper() + + metadata, err := GenerateMetadata(ctx) + require.NoError(t, err) + t.Run("with a valid version", func(t *testing.T) { + expVersion := metadata.GrafanaVersion + require.Equal(t, expVersion, version) + }) + + t.Run("with a valid release mode from the built-in list", func(t *testing.T) { + expMode := metadata.ReleaseMode + require.NoError(t, err) + require.Equal(t, expMode, releaseMode) + }) +} + +func setUpEnv(t *testing.T, envMap map[string]string) { + t.Helper() + + os.Clearenv() + err := os.Setenv("DRONE_COMMIT", "abcd12345") + require.NoError(t, err) + for k, v := range envMap { + err := os.Setenv(k, v) + require.NoError(t, err) + } +} diff --git a/pkg/build/config/package.json b/pkg/build/config/package.json new file mode 100644 index 0000000000000..1a5184b05c739 --- /dev/null +++ b/pkg/build/config/package.json @@ -0,0 +1,3 @@ +{ + "version": "9.2.0-pre" +} diff --git a/pkg/build/config/version.go b/pkg/build/config/version.go index fa8c8b3555ba9..de37c608ca145 100644 --- a/pkg/build/config/version.go +++ b/pkg/build/config/version.go @@ -7,6 +7,8 @@ import ( "path/filepath" "regexp" "strings" + + "github.com/grafana/grafana/pkg/build/git" ) type Metadata struct { @@ -100,8 +102,8 @@ func GetGrafanaVersion(buildID, grafanaDir string) (string, error) { } func CheckDroneTargetBranch() (VersionMode, error) { + rePRCheckBranch := git.PRCheckRegexp() reRlsBranch := regexp.MustCompile(`^v\d+\.\d+\.x$`) - rePRCheckBranch := regexp.MustCompile(`^pr-check-\d+`) target := os.Getenv("DRONE_TARGET_BRANCH") if target == "" { return "", fmt.Errorf("failed to get DRONE_TARGET_BRANCH environmental variable") @@ -121,6 +123,7 @@ func CheckDroneTargetBranch() (VersionMode, error) { func CheckSemverSuffix() (ReleaseMode, error) { reBetaRls := regexp.MustCompile(`beta.*`) reTestRls := regexp.MustCompile(`test.*`) + reCloudRls := regexp.MustCompile(`cloud.*`) tagSuffix, ok := os.LookupEnv("DRONE_SEMVER_PRERELEASE") if !ok || tagSuffix == "" { fmt.Println("DRONE_SEMVER_PRERELEASE doesn't exist for a tag, this is a release event...") @@ -131,6 +134,8 @@ func CheckSemverSuffix() (ReleaseMode, error) { return ReleaseMode{Mode: TagMode, IsBeta: true}, nil case reTestRls.MatchString(tagSuffix): return ReleaseMode{Mode: TagMode, IsTest: true}, nil + case reCloudRls.MatchString(tagSuffix): + return ReleaseMode{Mode: CloudMode}, nil default: fmt.Printf("DRONE_SEMVER_PRERELEASE is custom string, release event with %s suffix\n", tagSuffix) return ReleaseMode{Mode: TagMode}, nil diff --git a/pkg/build/config/version_mode.go b/pkg/build/config/version_mode.go index f7aa6578fe47f..d7734bb7d0170 100644 --- a/pkg/build/config/version_mode.go +++ b/pkg/build/config/version_mode.go @@ -8,8 +8,10 @@ const ( TagMode VersionMode = "release" ReleaseBranchMode VersionMode = "branch" PullRequestMode VersionMode = "pull_request" - CustomMode VersionMode = "custom" + DownstreamMode VersionMode = "downstream" + Enterprise2Mode VersionMode = "enterprise2" CronjobMode VersionMode = "cron" + CloudMode VersionMode = "cloud" ) const ( diff --git a/pkg/build/config/versions.go b/pkg/build/config/versions.go index baf8e6b8f464e..7078b4b46022a 100644 --- a/pkg/build/config/versions.go +++ b/pkg/build/config/versions.go @@ -59,7 +59,7 @@ var Versions = VersionMap{ Storybook: "grafana-storybook", }, }, - CustomMode: { + DownstreamMode: { Variants: []Variant{ VariantArmV6, VariantArmV7, @@ -120,6 +120,7 @@ var Versions = VersionMap{ Alpine, Ubuntu, }, + PrereleaseBucket: "grafana-prerelease/artifacts/docker", }, Buckets: Buckets{ Artifacts: "grafana-downloads", @@ -165,4 +166,71 @@ var Versions = VersionMap{ StorybookSrcDir: "artifacts/storybook", }, }, + Enterprise2Mode: { + Variants: []Variant{ + VariantArmV6, + VariantArmV7, + VariantArmV7Musl, + VariantArm64, + VariantArm64Musl, + VariantDarwinAmd64, + VariantWindowsAmd64, + VariantLinuxAmd64, + VariantLinuxAmd64Musl, + }, + PluginSignature: PluginSignature{ + Sign: true, + AdminSign: true, + }, + Docker: Docker{ + ShouldSave: true, + Architectures: []Architecture{ + ArchAMD64, + ArchARM64, + ArchARMv7, + }, + Distribution: []Distribution{ + Alpine, + Ubuntu, + }, + PrereleaseBucket: "grafana-prerelease/artifacts/docker", + }, + Buckets: Buckets{ + Artifacts: "grafana-prerelease/artifacts/downloads", + ArtifactsEnterprise2: "grafana-prerelease/artifacts/downloads-enterprise2", + CDNAssets: "grafana-prerelease", + CDNAssetsDir: "artifacts/static-assets", + Storybook: "grafana-prerelease", + StorybookSrcDir: "artifacts/storybook", + }, + }, + CloudMode: { + Variants: []Variant{ + VariantLinuxAmd64Musl, + // We still need this variant to build the .deb file + VariantLinuxAmd64, + }, + PluginSignature: PluginSignature{ + Sign: true, + AdminSign: true, + }, + Docker: Docker{ + ShouldSave: true, + Architectures: []Architecture{ + ArchAMD64, + }, + Distribution: []Distribution{ + Alpine, + }, + PrereleaseBucket: "grafana-prerelease/artifacts/docker", + }, + Buckets: Buckets{ + Artifacts: "grafana-prerelease/artifacts/downloads", + ArtifactsEnterprise2: "grafana-prerelease/artifacts/downloads-enterprise2", + CDNAssets: "grafana-prerelease", + CDNAssetsDir: "artifacts/static-assets", + Storybook: "grafana-prerelease", + StorybookSrcDir: "artifacts/storybook", + }, + }, } diff --git a/pkg/build/docker/build.go b/pkg/build/docker/build.go index f77d54cd43e0e..55e4970308833 100644 --- a/pkg/build/docker/build.go +++ b/pkg/build/docker/build.go @@ -70,12 +70,10 @@ func BuildImage(version string, arch config.Architecture, grafanaDir string, use } libc := "-musl" - dockerfile := "Dockerfile" - baseImage := fmt.Sprintf("%salpine:3.15", baseArch) + baseImage := fmt.Sprintf("%salpine:3.17", baseArch) tagSuffix := "" if useUbuntu { libc = "" - dockerfile = "ubuntu.Dockerfile" baseImage = fmt.Sprintf("%subuntu:20.04", baseArch) tagSuffix = "-ubuntu" } @@ -85,6 +83,11 @@ func BuildImage(version string, arch config.Architecture, grafanaDir string, use var additionalDockerRepo string var tags []string var imageFileBase string + var dockerEnterprise2Repo string + if repo, ok := os.LookupEnv("DOCKER_ENTERPRISE2_REPO"); ok { + dockerEnterprise2Repo = repo + } + switch edition { case config.EditionOSS: dockerRepo = "grafana/grafana-image-tags" @@ -94,6 +97,10 @@ func BuildImage(version string, arch config.Architecture, grafanaDir string, use dockerRepo = "grafana/grafana-enterprise-image-tags" imageFileBase = "grafana-enterprise" editionStr = "-enterprise" + case config.EditionEnterprise2: + dockerRepo = dockerEnterprise2Repo + imageFileBase = "grafana-enterprise2" + editionStr = "-enterprise2" default: return []string{}, fmt.Errorf("unrecognized edition %s", edition) } @@ -109,33 +116,49 @@ func BuildImage(version string, arch config.Architecture, grafanaDir string, use tags = append(tags, tag) args := []string{ - "build", "--build-arg", fmt.Sprintf("BASE_IMAGE=%s", baseImage), - "--build-arg", fmt.Sprintf("GRAFANA_TGZ=%s", archive), "--tag", tag, "--no-cache", - "-f", dockerfile, ".", + "build", + "-q", + "--build-arg", fmt.Sprintf("BASE_IMAGE=%s", baseImage), + "--build-arg", fmt.Sprintf("GRAFANA_TGZ=%s", archive), + "--build-arg", "GO_SRC=tgz-builder", + "--build-arg", "JS_SRC=tgz-builder", + "--build-arg", "RUN_SH=./run.sh", + "--tag", tag, + "--no-cache", + "--file", "../../Dockerfile", + ".", } - log.Printf("Running Docker: docker %s", strings.Join(args, " ")) //nolint:gosec cmd := exec.Command("docker", args...) cmd.Dir = buildDir - cmd.Env = append(os.Environ(), "DOCKER_CLI_EXPERIMENTAL=enabled") - if output, err := cmd.CombinedOutput(); err != nil { - return []string{}, fmt.Errorf("building Docker image failed: %w\n%s", err, output) + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + cmd.Env = append(os.Environ(), "DOCKER_CLI_EXPERIMENTAL=enabled", "DOCKER_BUILDKIT=1") + log.Printf("Running Docker: DOCKER_CLI_EXPERIMENTAL=enabled DOCKER_BUILDKIT=1 %s", cmd) + if err := cmd.Run(); err != nil { + return []string{}, fmt.Errorf("building Docker image failed: %w", err) } if shouldSave { imageFile := fmt.Sprintf("%s-%s%s-%s.img", imageFileBase, version, tagSuffix, arch) //nolint:gosec cmd = exec.Command("docker", "save", tag, "-o", imageFile) cmd.Dir = buildDir - if output, err := cmd.CombinedOutput(); err != nil { - return []string{}, fmt.Errorf("saving Docker image failed: %w\n%s", err, output) + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + log.Printf("Running Docker: %s", cmd) + if err := cmd.Run(); err != nil { + return []string{}, fmt.Errorf("saving Docker image failed: %w", err) } gcsURL := fmt.Sprintf("gs://grafana-prerelease/artifacts/docker/%s/%s", version, imageFile) //nolint:gosec - cmd = exec.Command("gsutil", "cp", imageFile, gcsURL) + cmd = exec.Command("gsutil", "-q", "cp", imageFile, gcsURL) cmd.Dir = buildDir - if output, err := cmd.CombinedOutput(); err != nil { - return []string{}, fmt.Errorf("storing Docker image failed: %w\n%s", err, output) + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + log.Printf("Running gsutil: %s", cmd) + if err := cmd.Run(); err != nil { + return []string{}, fmt.Errorf("storing Docker image failed: %w", err) } log.Printf("Docker image %s stored to grafana-prerelease GCS bucket", imageFile) } @@ -145,8 +168,11 @@ func BuildImage(version string, arch config.Architecture, grafanaDir string, use //nolint:gosec cmd = exec.Command("docker", "tag", tag, additionalTag) cmd.Dir = buildDir - if output, err := cmd.CombinedOutput(); err != nil { - return []string{}, fmt.Errorf("tagging Docker image failed: %w\n%s", err, output) + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + log.Printf("Running Docker: %s", cmd) + if err := cmd.Run(); err != nil { + return []string{}, fmt.Errorf("tagging Docker image failed: %w", err) } tags = append(tags, additionalTag) } diff --git a/pkg/build/docker/init.go b/pkg/build/docker/init.go index 658bba02f103c..c7262613b2bbc 100644 --- a/pkg/build/docker/init.go +++ b/pkg/build/docker/init.go @@ -10,6 +10,9 @@ import ( // AllArchs is a list of all supported Docker image architectures. var AllArchs = []string{"amd64", "armv7", "arm64"} +// emulatorImage is the docker image used as the cross-platform emulator +var emulatorImage = "tonistiigi/binfmt:qemu-v7.0.0" + // Init initializes the OS for Docker image building. func Init() error { // Necessary for cross-platform builds @@ -18,11 +21,14 @@ func Init() error { } // Enable execution of Docker images for other architectures + //nolint:gosec cmd := exec.Command("docker", "run", "--privileged", "--rm", - "docker/binfmt:a7996909642ee92942dcd6cff44b9b95f08dad64") + emulatorImage, "--install", "all") output, err := cmd.CombinedOutput() if err != nil { return fmt.Errorf("failed to enable execution of cross-platform Docker images: %w\n%s", err, output) } + log.Println("emulators have been installed successfully!") + return nil } diff --git a/pkg/build/docker/push.go b/pkg/build/docker/push.go new file mode 100644 index 0000000000000..da87ef2cb169a --- /dev/null +++ b/pkg/build/docker/push.go @@ -0,0 +1,62 @@ +package docker + +import ( + "fmt" + "log" + "os" + "os/exec" + "time" +) + +const ( + tries = 3 + sleepTime = 30 +) + +func PushImage(newImage string) error { + var err error + for i := 0; i < tries; i++ { + log.Printf("push attempt #%d...", i+1) + var out []byte + cmd := exec.Command("docker", "push", newImage) + cmd.Dir = "." + out, err = cmd.CombinedOutput() + if err != nil { + log.Printf("output: %s", out) + log.Printf("sleep for %d, before retrying...", sleepTime) + time.Sleep(sleepTime * time.Second) + } else { + log.Printf("Successfully pushed %s!", newImage) + break + } + } + if err != nil { + return fmt.Errorf("error pushing images to DockerHub: %q", err) + } + return nil +} + +func PushManifest(manifest string) error { + log.Printf("Pushing Docker manifest %s...", manifest) + + var err error + for i := 0; i < tries; i++ { + log.Printf("push attempt #%d...", i+1) + var out []byte + cmd := exec.Command("docker", "manifest", "push", manifest) + cmd.Env = append(os.Environ(), "DOCKER_CLI_EXPERIMENTAL=enabled") + out, err = cmd.CombinedOutput() + if err != nil { + log.Printf("output: %s", out) + log.Printf("sleep for %d, before retrying...", sleepTime) + time.Sleep(sleepTime * time.Second) + } else { + log.Printf("Successful manifest push! %s", string(out)) + break + } + } + if err != nil { + return fmt.Errorf("failed to push manifest, err: %w", err) + } + return nil +} diff --git a/pkg/build/env/fallback.go b/pkg/build/env/fallback.go new file mode 100644 index 0000000000000..7f4f31cb09e63 --- /dev/null +++ b/pkg/build/env/fallback.go @@ -0,0 +1,40 @@ +package env + +import ( + "fmt" + "os" + "strings" + + "github.com/urfave/cli/v2" +) + +// RequireListWithEnvFallback first checks the CLI for a flag with the required +// name. If this is empty, it falls back to taking the environment variable. +// Sadly, we cannot use cli.Flag.EnvVars for this due to it potentially leaking +// environment variables as default values in usage-errors. +func RequireListWithEnvFallback(cctx *cli.Context, name string, envName string) ([]string, error) { + result := cctx.StringSlice(name) + if len(result) == 0 { + for _, v := range strings.Split(os.Getenv(envName), ",") { + value := strings.TrimSpace(v) + if value != "" { + result = append(result, value) + } + } + } + if len(result) == 0 { + return nil, cli.Exit(fmt.Sprintf("Required flag (%s) or environment variable (%s) not set", name, envName), 1) + } + return result, nil +} + +func RequireStringWithEnvFallback(cctx *cli.Context, name string, envName string) (string, error) { + result := cctx.String(name) + if result == "" { + result = os.Getenv(envName) + } + if result == "" { + return "", cli.Exit(fmt.Sprintf("Required flag (%s) or environment variable (%s) not set", name, envName), 1) + } + return result, nil +} diff --git a/pkg/build/env/fallback_test.go b/pkg/build/env/fallback_test.go new file mode 100644 index 0000000000000..d14e13ee774b5 --- /dev/null +++ b/pkg/build/env/fallback_test.go @@ -0,0 +1,143 @@ +package env + +import ( + "flag" + "fmt" + "os" + "testing" + + "github.com/stretchr/testify/require" + "github.com/urfave/cli/v2" +) + +const ( + flag1 = "flag1" + flag2 = "flag2" +) + +func TestRequireListWithEnvFallback(t *testing.T) { + var app = cli.NewApp() + tests := []struct { + testName string + ctx *cli.Context + name string + envName string + expected []string + expectedErr error + }{ + { + testName: "string slice present in context", + ctx: cli.NewContext(app, applyFlagSet(t, flag1, "a"), nil), + name: flag1, + envName: "", + expected: []string{"a"}, + expectedErr: nil, + }, + { + testName: "string slice present in env", + ctx: cli.NewContext(app, flag.NewFlagSet("test", 0), nil), + name: flag1, + envName: setEnv(t, flag1, "a"), + expected: []string{"a"}, + expectedErr: nil, + }, + { + testName: "string slice absent in both context and env", + ctx: cli.NewContext(app, flag.NewFlagSet("test", 0), nil), + name: flag1, + envName: "", + expected: []string(nil), + expectedErr: cli.Exit("Required flag (flag1) or environment variable () not set", 1), + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + flagList, err := RequireListWithEnvFallback(tt.ctx, tt.name, tt.envName) + if tt.expectedErr != nil { + require.Error(t, err) + } + require.Equal(t, tt.expected, flagList) + }) + } +} + +func TestRequireStringWithEnvFallback(t *testing.T) { + var app = cli.NewApp() + tests := []struct { + testName string + ctx *cli.Context + name string + envName string + expected string + expectedErr error + }{ + { + testName: "string present in the context", + ctx: cli.NewContext(app, setFlags(t, flag1, flag2, flag.NewFlagSet("test", flag.ContinueOnError)), nil), + name: flag1, + envName: "", + expected: "a", + expectedErr: nil, + }, + { + testName: "string present in env", + ctx: cli.NewContext(app, setFlags(t, "", "", flag.NewFlagSet("test", flag.ContinueOnError)), nil), + name: flag1, + envName: setEnv(t, flag1, "a"), + expected: "a", + expectedErr: nil, + }, + { + testName: "string absent from both context and env", + ctx: cli.NewContext(app, setFlags(t, "", flag2, flag.NewFlagSet("test", flag.ContinueOnError)), nil), + name: flag1, + envName: "", + expected: "", + expectedErr: cli.Exit("Required flag (flag1) or environment variable () not set", 1), + }, + } + for _, tt := range tests { + t.Run(tt.testName, func(t *testing.T) { + flagString, err := RequireStringWithEnvFallback(tt.ctx, tt.name, tt.envName) + if tt.expectedErr != nil { + require.Error(t, err) + } + require.Equal(t, tt.expected, flagString) + }) + } +} + +func applyFlagSet(t *testing.T, aFlag, aValue string) *flag.FlagSet { + t.Helper() + var val cli.StringSlice + fl := cli.StringSliceFlag{Name: aFlag, EnvVars: []string{"FLAG"}, Value: &val} + set := flag.NewFlagSet("test", 0) + parseInput := []string{fmt.Sprintf("-%s", aFlag), aValue} + err := fl.Apply(set) + require.NoError(t, err) + err = set.Parse(parseInput) + require.NoError(t, err) + return set +} + +func setFlags(t *testing.T, flag1, flag2 string, flagSet *flag.FlagSet) *flag.FlagSet { + t.Helper() + if flag1 != "" { + flagSet.StringVar(&flag1, "flag1", "a", "") + } + if flag2 != "" { + flagSet.StringVar(&flag2, "flag2", "b", "") + } + return flagSet +} + +func setEnv(t *testing.T, key, value string) string { + t.Helper() + os.Clearenv() + + err := os.Setenv(key, value) + if err != nil { + require.NoError(t, err) + } + return key +} diff --git a/pkg/build/env/lookup.go b/pkg/build/env/lookup.go new file mode 100644 index 0000000000000..993b7259e146b --- /dev/null +++ b/pkg/build/env/lookup.go @@ -0,0 +1,18 @@ +package env + +import ( + "strings" +) + +// Lookup is the equivalent of os.LookupEnv, only you are able to provide the list of environment variables. +// To use this as os.LookupEnv would be used, simply call +// `env.Lookup("ENVIRONMENT_VARIABLE", os.Environ())` +func Lookup(name string, vars []string) (string, bool) { + for _, v := range vars { + if strings.HasPrefix(v, name) { + return strings.TrimPrefix(v, name+"="), true + } + } + + return "", false +} diff --git a/pkg/build/env/lookup_test.go b/pkg/build/env/lookup_test.go new file mode 100644 index 0000000000000..cebfb4fac295a --- /dev/null +++ b/pkg/build/env/lookup_test.go @@ -0,0 +1,43 @@ +package env_test + +import ( + "testing" + + "github.com/grafana/grafana/pkg/build/env" + + "github.com/stretchr/testify/require" +) + +func TestLookup(t *testing.T) { + values := []string{"ENV_1=a", "ENV_2=b", "ENV_3=c", "ENV_4_TEST="} + + { + v, ok := env.Lookup("ENV_1", values) + require.Equal(t, v, "a") + require.True(t, ok) + } + + { + v, ok := env.Lookup("ENV_2", values) + require.Equal(t, v, "b") + require.True(t, ok) + } + + { + v, ok := env.Lookup("ENV_3", values) + require.Equal(t, v, "c") + require.True(t, ok) + } + + { + v, ok := env.Lookup("ENV_4_TEST", values) + require.Equal(t, v, "") + require.True(t, ok) + } + + { + v, ok := env.Lookup("NOT_THERE", values) + require.Equal(t, v, "") + require.False(t, ok) + } +} diff --git a/pkg/build/gcloud/storage/gsutil.go b/pkg/build/gcloud/storage/gsutil.go index 461fd58c98abb..8bc92066e9466 100644 --- a/pkg/build/gcloud/storage/gsutil.go +++ b/pkg/build/gcloud/storage/gsutil.go @@ -206,7 +206,6 @@ func (client *Client) RemoteCopy(ctx context.Context, file File, fromBucket, toB return fmt.Errorf("failed to copy object %s, to %s, err: %w", file.FullPath, dstObject, err) } - log.Printf("%s was successfully copied to %v bucket!.\n\n", file.FullPath, toBucket) return nil } @@ -352,7 +351,7 @@ func (client *Client) DownloadDirectory(ctx context.Context, bucket *storage.Buc } for _, file := range files { - err = client.downloadFile(ctx, bucket, file.FullPath, filepath.Join(destPath, file.PathTrimmed)) + err = client.downloadFile(ctx, bucket, file.FullPath, file.PathTrimmed) if err != nil { return err } diff --git a/pkg/build/git/git.go b/pkg/build/git/git.go new file mode 100644 index 0000000000000..7539a815de60f --- /dev/null +++ b/pkg/build/git/git.go @@ -0,0 +1,142 @@ +package git + +import ( + "context" + "errors" + "fmt" + "net/http" + "regexp" + + "github.com/google/go-github/v45/github" + "github.com/grafana/grafana/pkg/build/stringutil" + "golang.org/x/oauth2" +) + +const ( + MainBranch = "main" + HomeDir = "." + RepoOwner = "grafana" + OSSRepo = "grafana" + EnterpriseRepo = "grafana-enterprise" + EnterpriseCheckName = "Grafana Enterprise" + EnterpriseCheckDescription = "Downstream tests to ensure that your changes are compatible with Grafana Enterprise" +) + +var EnterpriseCheckLabels = []string{"enterprise-ok", "enterprise-failed", "enterprise-override"} + +var ( + ErrorNoDroneBuildLink = errors.New("no drone build link") +) + +type GitService interface { + DeleteRef(ctx context.Context, owner string, repo string, ref string) (*github.Response, error) +} + +type LabelsService interface { + ListLabelsByIssue(ctx context.Context, owner string, repo string, number int, opts *github.ListOptions) ([]*github.Label, *github.Response, error) + RemoveLabelForIssue(ctx context.Context, owner string, repo string, number int, label string) (*github.Response, error) + AddLabelsToIssue(ctx context.Context, owner string, repo string, number int, labels []string) ([]*github.Label, *github.Response, error) +} + +type CommentService interface { + CreateComment(ctx context.Context, owner string, repo string, number int, comment *github.IssueComment) (*github.IssueComment, *github.Response, error) +} + +type StatusesService interface { + CreateStatus(ctx context.Context, owner, repo, ref string, status *github.RepoStatus) (*github.RepoStatus, *github.Response, error) +} + +// NewGitHubClient creates a new Client using the provided GitHub token if not empty. +func NewGitHubClient(ctx context.Context, token string) *github.Client { + var tc *http.Client + if token != "" { + ts := oauth2.StaticTokenSource(&oauth2.Token{ + AccessToken: token, + }) + tc = oauth2.NewClient(ctx, ts) + } + + return github.NewClient(tc) +} + +func PRCheckRegexp() *regexp.Regexp { + reBranch, err := regexp.Compile(`^prc-([0-9]+)-([A-Za-z0-9]+)\/(.+)$`) + if err != nil { + panic(fmt.Sprintf("Failed to compile regexp: %s", err)) + } + + return reBranch +} + +func AddLabelToPR(ctx context.Context, client LabelsService, prID int, newLabel string) error { + // Check existing labels + labels, _, err := client.ListLabelsByIssue(ctx, RepoOwner, OSSRepo, prID, nil) + if err != nil { + return err + } + + duplicate := false + for _, label := range labels { + if *label.Name == newLabel { + duplicate = true + continue + } + + // Delete existing "enterprise-xx" labels + if stringutil.Contains(EnterpriseCheckLabels, *label.Name) { + _, err := client.RemoveLabelForIssue(ctx, RepoOwner, OSSRepo, prID, *label.Name) + if err != nil { + return err + } + } + } + + if duplicate { + return nil + } + + _, _, err = client.AddLabelsToIssue(ctx, RepoOwner, OSSRepo, prID, []string{newLabel}) + if err != nil { + return err + } + + return nil +} + +func DeleteEnterpriseBranch(ctx context.Context, client GitService, branchName string) error { + ref := "heads/" + branchName + if _, err := client.DeleteRef(ctx, RepoOwner, EnterpriseRepo, ref); err != nil { + return err + } + + return nil +} + +// CreateEnterpriseStatus sets the status on a commit for the enterprise build check. +func CreateEnterpriseStatus(ctx context.Context, client StatusesService, sha, link, status string) (*github.RepoStatus, error) { + check, _, err := client.CreateStatus(ctx, RepoOwner, OSSRepo, sha, &github.RepoStatus{ + Context: github.String(EnterpriseCheckName), + Description: github.String(EnterpriseCheckDescription), + TargetURL: github.String(link), + State: github.String(status), + }) + + if err != nil { + return nil, err + } + + return check, nil +} + +func CreateEnterpriseBuildFailedComment(ctx context.Context, client CommentService, link string, prID int) error { + body := fmt.Sprintf("Drone build failed: %s", link) + + _, _, err := client.CreateComment(ctx, RepoOwner, OSSRepo, prID, &github.IssueComment{ + Body: &body, + }) + if err != nil { + return err + } + + return nil +} diff --git a/pkg/build/git/git_checks_test.go b/pkg/build/git/git_checks_test.go new file mode 100644 index 0000000000000..ed3d34a8d282e --- /dev/null +++ b/pkg/build/git/git_checks_test.go @@ -0,0 +1,55 @@ +package git_test + +import ( + "context" + "errors" + "testing" + + "github.com/google/go-github/v45/github" + "github.com/grafana/grafana/pkg/build/git" + "github.com/stretchr/testify/require" +) + +type TestChecksService struct { + CreateCheckRunError error +} + +func (s *TestChecksService) CreateStatus(ctx context.Context, owner, repo, ref string, status *github.RepoStatus) (*github.RepoStatus, *github.Response, error) { + if s.CreateCheckRunError != nil { + return nil, nil, s.CreateCheckRunError + } + + return &github.RepoStatus{ + ID: github.Int64(1), + URL: status.URL, + }, nil, nil +} + +func TestCreateEnterpriseRepoStatus(t *testing.T) { + t.Run("It should create a repo status", func(t *testing.T) { + var ( + ctx = context.Background() + client = &TestChecksService{} + link = "http://example.com" + sha = "1234" + ) + + _, err := git.CreateEnterpriseStatus(ctx, client, link, sha, "success") + + require.NoError(t, err) + }) + t.Run("It should return an error if GitHub fails to create the status", func(t *testing.T) { + var ( + ctx = context.Background() + createCheckError = errors.New("create check run error") + client = &TestChecksService{ + CreateCheckRunError: createCheckError, + } + link = "http://example.com" + sha = "1234" + ) + + _, err := git.CreateEnterpriseStatus(ctx, client, link, sha, "success") + require.ErrorIs(t, err, createCheckError) + }) +} diff --git a/pkg/build/git/git_issues_test.go b/pkg/build/git/git_issues_test.go new file mode 100644 index 0000000000000..4eaa3bb616928 --- /dev/null +++ b/pkg/build/git/git_issues_test.go @@ -0,0 +1,134 @@ +package git_test + +import ( + "context" + "errors" + "testing" + + "github.com/google/go-github/v45/github" + "github.com/grafana/grafana/pkg/build/git" + "github.com/stretchr/testify/require" +) + +type TestLabelsService struct { + Labels []*github.Label + ListLabelsError error + RemoveLabelError error + AddLabelsError error +} + +func (s *TestLabelsService) ListLabelsByIssue(ctx context.Context, owner string, repo string, number int, opts *github.ListOptions) ([]*github.Label, *github.Response, error) { + if s.ListLabelsError != nil { + return nil, nil, s.ListLabelsError + } + + labels := s.Labels + if labels == nil { + labels = []*github.Label{} + } + + return labels, nil, nil +} + +func (s *TestLabelsService) RemoveLabelForIssue(ctx context.Context, owner string, repo string, number int, label string) (*github.Response, error) { + if s.RemoveLabelError != nil { + return nil, s.RemoveLabelError + } + + return &github.Response{}, nil +} + +func (s *TestLabelsService) AddLabelsToIssue(ctx context.Context, owner string, repo string, number int, labels []string) ([]*github.Label, *github.Response, error) { + if s.AddLabelsError != nil { + return nil, nil, s.AddLabelsError + } + + l := make([]*github.Label, len(labels)) + for i, v := range labels { + l[i] = &github.Label{ + Name: github.String(v), + } + } + + return l, nil, nil +} + +func TestAddLabelToPR(t *testing.T) { + t.Run("It should add a label to a pull request", func(t *testing.T) { + var ( + ctx = context.Background() + client = &TestLabelsService{} + pr = 20 + label = "test-label" + ) + + require.NoError(t, git.AddLabelToPR(ctx, client, pr, label)) + }) + t.Run("It should not return an error if the label already exists", func(t *testing.T) { + var ( + ctx = context.Background() + client = &TestLabelsService{ + Labels: []*github.Label{ + { + Name: github.String("test-label"), + }, + }, + } + pr = 20 + label = "test-label" + ) + + require.NoError(t, git.AddLabelToPR(ctx, client, pr, label)) + }) + + t.Run("It should return an error if GitHub returns an error when listing labels", func(t *testing.T) { + var ( + ctx = context.Background() + listLabelsError = errors.New("list labels error") + client = &TestLabelsService{ + ListLabelsError: listLabelsError, + Labels: []*github.Label{}, + } + pr = 20 + label = "test-label" + ) + + require.ErrorIs(t, git.AddLabelToPR(ctx, client, pr, label), listLabelsError) + }) + + t.Run("It should not return an error if there are existing enterprise-check labels.", func(t *testing.T) { + var ( + ctx = context.Background() + client = &TestLabelsService{ + Labels: []*github.Label{ + { + Name: github.String("enterprise-failed"), + }, + }, + } + pr = 20 + label = "test-label" + ) + + require.NoError(t, git.AddLabelToPR(ctx, client, pr, label)) + }) + + t.Run("It should return an error if GitHub returns an error when removing existing enterprise-check labels", func(t *testing.T) { + var ( + ctx = context.Background() + removeLabelError = errors.New("remove label error") + client = &TestLabelsService{ + RemoveLabelError: removeLabelError, + Labels: []*github.Label{ + { + Name: github.String("enterprise-failed"), + }, + }, + } + pr = 20 + label = "test-label" + ) + + require.ErrorIs(t, git.AddLabelToPR(ctx, client, pr, label), removeLabelError) + }) +} diff --git a/pkg/build/git/git_test.go b/pkg/build/git/git_test.go new file mode 100644 index 0000000000000..c0cbd4c8cd889 --- /dev/null +++ b/pkg/build/git/git_test.go @@ -0,0 +1,56 @@ +package git_test + +import ( + "testing" + + "github.com/grafana/grafana/pkg/build/git" + "github.com/stretchr/testify/assert" +) + +func TestPRCheckRegexp(t *testing.T) { + type match struct { + String string + Commit string + Branch string + PR string + } + + var ( + shouldMatch = []match{ + { + String: "prc-1-a1b2c3d4/branch-name", + Branch: "branch-name", + Commit: "a1b2c3d4", + PR: "1", + }, + { + String: "prc-111-a1b2c3d4/branch/name", + Branch: "branch/name", + Commit: "a1b2c3d4", + PR: "111", + }, + { + String: "prc-102930122-a1b2c3d4/branch-name", + Branch: "branch-name", + Commit: "a1b2c3d4", + PR: "102930122", + }, + } + + shouldNotMatch = []string{"prc-a/branch", "km/test", "test", "prc", "prc/test", "price"} + ) + + regex := git.PRCheckRegexp() + + for _, v := range shouldMatch { + assert.Truef(t, regex.MatchString(v.String), "regex '%s' should match %s", regex.String(), v) + m := regex.FindStringSubmatch(v.String) + assert.Equal(t, m[1], v.PR) + assert.Equal(t, m[2], v.Commit) + assert.Equal(t, m[3], v.Branch) + } + + for _, v := range shouldNotMatch { + assert.False(t, regex.MatchString(v), "regex '%s' should not match %s", regex.String(), v) + } +} diff --git a/pkg/build/grafana/build.go b/pkg/build/grafana/build.go index 4d661e8d85180..0596d094875b9 100644 --- a/pkg/build/grafana/build.go +++ b/pkg/build/grafana/build.go @@ -99,7 +99,7 @@ func BuildGrafanaBinary(ctx context.Context, name, version string, args BuildArg descriptor := GrafanaDescriptor(opts) - log.Printf("Building %q for %s\nwith env: %v", binary, descriptor, opts.Env()) + log.Printf("Building %q for %s", binary, descriptor) opts.LdFlags = append(args.LdFlags, GrafanaLDFlags(version, revision)...) diff --git a/pkg/build/lerna/lerna.go b/pkg/build/lerna/lerna.go index de0cbbfe46137..de04f5f0e8825 100644 --- a/pkg/build/lerna/lerna.go +++ b/pkg/build/lerna/lerna.go @@ -1,6 +1,7 @@ package lerna import ( + "context" "encoding/json" "fmt" "os" @@ -9,6 +10,7 @@ import ( "strings" "github.com/grafana/grafana/pkg/build/config" + "github.com/grafana/grafana/pkg/build/fsutil" ) // BuildFrontendPackages will bump the version for the package to the latest canary build @@ -56,3 +58,29 @@ func GetLernaVersion(grafanaDir string) (string, error) { } return strings.TrimSpace(version), nil } + +func PackFrontendPackages(ctx context.Context, tag, grafanaDir, artifactsDir string) error { + exists, err := fsutil.Exists(artifactsDir) + if err != nil { + return err + } + if exists { + err = os.RemoveAll(artifactsDir) + if err != nil { + return err + } + } + // nolint:gosec + if err = os.MkdirAll(artifactsDir, 0755); err != nil { + return err + } + + // nolint:gosec + cmd := exec.CommandContext(ctx, "yarn", "lerna", "exec", "--no-private", "--", "yarn", "pack", "--out", fmt.Sprintf("../../npm-artifacts/%%s-%v.tgz", tag)) + cmd.Dir = grafanaDir + if output, err := cmd.CombinedOutput(); err != nil { + return fmt.Errorf("command '%s' failed to run, output: %s, err: %q", cmd.String(), output, err) + } + + return nil +} diff --git a/pkg/build/npm/npm.go b/pkg/build/npm/npm.go new file mode 100644 index 0000000000000..c2b93aef46b37 --- /dev/null +++ b/pkg/build/npm/npm.go @@ -0,0 +1,240 @@ +package npm + +import ( + "context" + "fmt" + "log" + "os" + "os/exec" + "path/filepath" + "strings" + + "github.com/grafana/grafana/pkg/build/gcloud/storage" + "github.com/grafana/grafana/pkg/build/lerna" + "github.com/grafana/grafana/pkg/build/versions" +) + +const GrafanaDir = "." +const NpmArtifactDir = "./npm-artifacts" + +// TODO: could this be replaced by `yarn lerna list -p` ? +var packages = []string{ + "@grafana/ui", + "@grafana/data", + "@grafana/toolkit", + "@grafana/runtime", + "@grafana/e2e", + "@grafana/e2e-selectors", + "@grafana/schema", +} + +// PublishNpmPackages will publish local NPM packages to NPM registry. +func PublishNpmPackages(ctx context.Context, tag string) error { + version, err := versions.GetVersion(tag) + if err != nil { + return err + } + + log.Printf("Grafana version: %s", version.Version) + + if err := setNpmCredentials(); err != nil { + return err + } + + npmArtifacts, err := storage.ListLocalFiles(NpmArtifactDir) + if err != nil { + return err + } + for _, packedFile := range npmArtifacts { + // nolint:gosec + cmd := exec.CommandContext(ctx, "npm", "publish", packedFile.FullPath, "--tag", version.Channel) + cmd.Dir = GrafanaDir + if out, err := cmd.CombinedOutput(); err != nil { + return fmt.Errorf("command '%s' failed to run, output: %s, err: %q", cmd.String(), out, err) + } + } + + return updateTag(ctx, version, tag) +} + +// StoreNpmPackages will store local NPM packages in GCS bucket `bucketName`. +func StoreNpmPackages(ctx context.Context, tag, bucketName string) error { + err := lerna.PackFrontendPackages(ctx, tag, GrafanaDir, NpmArtifactDir) + if err != nil { + return err + } + + gcs, err := storage.New() + if err != nil { + return err + } + + bucket := gcs.Bucket(bucketName) + bucketPath := fmt.Sprintf("artifacts/npm/%s/", tag) + if err = gcs.CopyLocalDir(ctx, NpmArtifactDir, bucket, bucketPath, true); err != nil { + return err + } + + log.Print("Successfully stored npm packages!") + return nil +} + +// FetchNpmPackages will store NPM packages stored in GCS bucket `bucketName` on local disk in `frontend.NpmArtifactDir`. +func FetchNpmPackages(ctx context.Context, tag, bucketName string) error { + gcs, err := storage.New() + if err != nil { + return err + } + + bucketPath := fmt.Sprintf("artifacts/npm/%s/", tag) + bucket := gcs.Bucket(bucketName) + err = gcs.DownloadDirectory(ctx, bucket, NpmArtifactDir, storage.FilesFilter{ + Prefix: bucketPath, + FileExts: []string{".tgz"}, + }) + if err != nil { + return err + } + return nil +} + +// updateTag will move next or latest npm dist-tags, if needed. +// +// Note: This function makes the assumption that npm dist-tags has already +// been updated and hence why move of dist-tags not always happens: +// +// If stable the dist-tag latest was used. +// If beta the dist-tag next was used. +// +// Scenarios: +// +// 1. Releasing a newer stable than the current stable +// Latest and next is 9.1.5. +// 9.1.6 is released, latest and next should point to 9.1.6. +// The next dist-tag is moved to point to 9.1.6. +// +// 2. Releasing during an active beta period: +// Latest and next is 9.1.6. +// 9.2.0-beta1 is released, the latest should stay on 9.1.6, next should point to 9.2.0-beta1 +// No move of dist-tags +// 9.1.7 is relased, the latest should point to 9.1.7, next should stay to 9.2.0-beta1 +// No move of dist-tags +// Next week 9.2.0-beta2 is released, the latest should point to 9.1.7, next should point to 9.2.0-beta2 +// No move of dist-tags +// In two weeks 9.2.0 stable is relased, the latest and next should point to 9.2.0. +// The next dist-tag is moved to point to 9.2.0. +// +// 3. Releasing an older stable than the current stable +// Latest and next is 9.2.0. +// Next 9.1.8 is released, latest should point to 9.2.0, next should point to 9.2.0 +// The latest dist-tag is moved to point to 9.2.0. +func updateTag(ctx context.Context, version *versions.Version, releaseVersion string) error { + if version.Channel != versions.Latest { + return nil + } + + latestStableVersion, err := getLatestStableVersion() + if err != nil { + return err + } + + betaVersion, err := getLatestBetaVersion() + if err != nil { + return err + } + + isLatest, err := versions.IsGreaterThanOrEqual(releaseVersion, latestStableVersion) + if err != nil { + return err + } + + isNewerThanLatestBeta, err := versions.IsGreaterThanOrEqual(releaseVersion, betaVersion) + if err != nil { + return err + } + + for _, pkg := range packages { + if !isLatest { + err = runMoveLatestNPMTagCommand(ctx, pkg, latestStableVersion) + if err != nil { + return err + } + } + + if isLatest && isNewerThanLatestBeta { + err = runMoveNextNPMTagCommand(ctx, pkg, version.Version) + if err != nil { + return err + } + } + } + + return nil +} + +func getLatestStableVersion() (string, error) { + return versions.GetLatestVersion(versions.LatestStableVersionURL) +} + +func getLatestBetaVersion() (string, error) { + return versions.GetLatestVersion(versions.LatestBetaVersionURL) +} + +func runMoveNextNPMTagCommand(ctx context.Context, pkg string, packageVersion string) error { + // nolint:gosec + cmd := exec.CommandContext(ctx, "npm", "dist-tag", "add", fmt.Sprintf("%s@%s", pkg, packageVersion), "next") + if out, err := cmd.CombinedOutput(); err != nil { + return fmt.Errorf("command '%s' failed to run, output: %s, err: %q", cmd.String(), out, err) + } + + return nil +} + +func runMoveLatestNPMTagCommand(ctx context.Context, pkg string, latestStableVersion string) error { + // nolint:gosec + cmd := exec.CommandContext(ctx, "npm", "dist-tag", "add", fmt.Sprintf("%s@%s", pkg, latestStableVersion), "latest") + if out, err := cmd.CombinedOutput(); err != nil { + return fmt.Errorf("command '%s' failed to run, output: %s, err: %q", cmd.String(), out, err) + } + + return nil +} + +// setNpmCredentials Creates a .npmrc file in the users home folder and writes the +// necessary credentials to it for publishing packages to the NPM registry. +func setNpmCredentials() error { + npmToken := strings.TrimSpace(os.Getenv("NPM_TOKEN")) + if npmToken == "" { + return fmt.Errorf("npm token is not set") + } + + homeDir, err := os.UserHomeDir() + if err != nil { + return fmt.Errorf("failed to obtain home directory, err: %q", err) + } + + npmPath := filepath.Join(homeDir, ".npmrc") + registry := []byte(fmt.Sprintf("//registry.npmjs.org/:_authToken=%s", npmToken)) + if _, err = os.Stat(npmPath); os.IsNotExist(err) { + // nolint:gosec + f, err := os.Create(npmPath) + if err != nil { + return fmt.Errorf("couldn't create npmrc file, err: %q", err) + } + _, err = f.Write(registry) + if err != nil { + return fmt.Errorf("failed to write to file, err: %q", err) + } + defer func() { + if err := f.Close(); err != nil { + log.Printf("Failed to close file: %s", err.Error()) + } + }() + } else { + err = os.WriteFile(npmPath, registry, 0644) + if err != nil { + return fmt.Errorf("error writing to file, err: %q", err) + } + } + return nil +} diff --git a/pkg/build/packaging/deb.go b/pkg/build/packaging/deb.go index a5c01bd2ea651..1781b345fff59 100644 --- a/pkg/build/packaging/deb.go +++ b/pkg/build/packaging/deb.go @@ -8,10 +8,11 @@ import ( "path/filepath" "strings" + "github.com/urfave/cli/v2" + "github.com/grafana/grafana/pkg/build/config" "github.com/grafana/grafana/pkg/build/fsutil" "github.com/grafana/grafana/pkg/infra/fs" - "github.com/urfave/cli/v2" ) func writeAptlyConf(dbDir, repoDir string) error { @@ -166,20 +167,16 @@ func UpdateDebRepo(cfg PublishConfig, workDir string) error { cmd := exec.Command("aptly", "publish", "update", "-batch", passArg, "-force-overwrite", tp, "filesystem:repo:grafana") if output, err := cmd.CombinedOutput(); err != nil { - return cli.NewExitError(fmt.Sprintf("failed to update Debian %q repository: %s", tp, output), 1) + return cli.Exit(fmt.Sprintf("failed to update Debian %q repository: %s", tp, output), 1) } } - - // Update database in GCS - u = fmt.Sprintf("gs://%s/%s", cfg.DebDBBucket, strings.ToLower(string(cfg.Edition))) if cfg.DryRun { - log.Printf("Simulating upload of Debian repo database to GCS (%s)\n", u) } else { log.Printf("Uploading Debian repo database to GCS (%s)...\n", u) //nolint:gosec cmd = exec.Command("gsutil", "-m", "rsync", "-r", "-d", dbDir, u) if output, err := cmd.CombinedOutput(); err != nil { - return cli.NewExitError(fmt.Sprintf("failed to upload Debian repo database to GCS: %s", output), 1) + return cli.Exit(fmt.Sprintf("failed to upload Debian repo database to GCS: %s", output), 1) } } @@ -193,14 +190,14 @@ func UpdateDebRepo(cfg PublishConfig, workDir string) error { //nolint:gosec cmd = exec.Command("gsutil", "-m", "rsync", "-r", "-d", grafDir, u) if output, err := cmd.CombinedOutput(); err != nil { - return cli.NewExitError(fmt.Sprintf("failed to upload Debian repo resources to GCS: %s", output), 1) + return cli.Exit(fmt.Sprintf("failed to upload Debian repo resources to GCS: %s", output), 1) } allRepoResources := fmt.Sprintf("%s/**/*", u) log.Printf("Setting cache ttl for Debian repo resources on GCS (%s)...\n", allRepoResources) //nolint:gosec cmd = exec.Command("gsutil", "-m", "setmeta", "-h", CacheSettings+cfg.TTL, allRepoResources) if output, err := cmd.CombinedOutput(); err != nil { - return cli.NewExitError(fmt.Sprintf("failed to set cache ttl for Debian repo resources on GCS: %s", output), 1) + return cli.Exit(fmt.Sprintf("failed to set cache ttl for Debian repo resources on GCS: %s", output), 1) } } @@ -238,7 +235,7 @@ func addPkgsToRepo(cfg PublishConfig, workDir, tmpDir, repoName string) error { //nolint:gosec cmd := exec.Command("aptly", "repo", "add", "-force-replace", repoName, tmpDir) if output, err := cmd.CombinedOutput(); err != nil { - return cli.NewExitError(fmt.Sprintf("failed to add packages to local Debian repository: %s", output), 1) + return cli.Exit(fmt.Sprintf("failed to add packages to local Debian repository: %s", output), 1) } return nil diff --git a/pkg/build/packaging/grafana.go b/pkg/build/packaging/grafana.go index 71de93ea32436..2b3f02df5b84d 100644 --- a/pkg/build/packaging/grafana.go +++ b/pkg/build/packaging/grafana.go @@ -184,30 +184,32 @@ func signRPMPackages(edition config.Edition, cfg config.Config, grafanaDir strin return err } - rpmArgs := append([]string{"--addsign"}, rpms...) - log.Printf("Invoking rpm with args: %+v", rpmArgs) - //nolint:gosec - cmd := exec.Command("rpm", rpmArgs...) - if output, err := cmd.CombinedOutput(); err != nil { - return fmt.Errorf("failed to sign RPM packages: %s", output) - } - if err := os.Remove(cfg.GPGPassPath); err != nil { - return fmt.Errorf("failed to remove %q: %w", cfg.GPGPassPath, err) - } - - log.Printf("Verifying %s RPM packages...", edition) - // The output changed between rpm versions - reOutput := regexp.MustCompile("(?:digests signatures OK)|(?:pgp.+OK)") - for _, p := range rpms { + if len(rpms) > 0 { + rpmArgs := append([]string{"--addsign"}, rpms...) + log.Printf("Invoking rpm with args: %+v", rpmArgs) //nolint:gosec - cmd := exec.Command("rpm", "-K", p) - output, err := cmd.CombinedOutput() - if err != nil { - return fmt.Errorf("failed to verify RPM signature: %w", err) + cmd := exec.Command("rpm", rpmArgs...) + if output, err := cmd.CombinedOutput(); err != nil { + return fmt.Errorf("failed to sign RPM packages: %s", output) + } + if err := os.Remove(cfg.GPGPassPath); err != nil { + return fmt.Errorf("failed to remove %q: %w", cfg.GPGPassPath, err) } - if !reOutput.Match(output) { - return fmt.Errorf("RPM package %q not verified: %s", p, output) + log.Printf("Verifying %s RPM packages...", edition) + // The output changed between rpm versions + reOutput := regexp.MustCompile("(?:digests signatures OK)|(?:pgp.+OK)") + for _, p := range rpms { + //nolint:gosec + cmd := exec.Command("rpm", "-K", p) + output, err := cmd.CombinedOutput() + if err != nil { + return fmt.Errorf("failed to verify RPM signature: %w", err) + } + + if !reOutput.Match(output) { + return fmt.Errorf("RPM package %q not verified: %s", p, output) + } } } diff --git a/pkg/build/packaging/grafana_test.go b/pkg/build/packaging/grafana_test.go new file mode 100644 index 0000000000000..8f143893085db --- /dev/null +++ b/pkg/build/packaging/grafana_test.go @@ -0,0 +1,22 @@ +package packaging_test + +import ( + "testing" + + "github.com/grafana/grafana/pkg/build/config" + "github.com/grafana/grafana/pkg/build/packaging" + "github.com/stretchr/testify/assert" +) + +func TestPackageRegexp(t *testing.T) { + t.Run("It should match enterprise2 packages", func(t *testing.T) { + rgx := packaging.PackageRegexp(config.EditionEnterprise2) + matches := []string{ + "grafana-enterprise2-1.2.3-4567pre.linux-amd64.tar.gz", + "grafana-enterprise2-1.2.3-4567pre.linux-amd64.tar.gz.sha256", + } + for _, v := range matches { + assert.Truef(t, rgx.MatchString(v), "'%s' should match regex '%s'", v, rgx.String()) + } + }) +} diff --git a/pkg/build/packaging/rpm.go b/pkg/build/packaging/rpm.go index 24da71a185af5..a4e8e55722152 100644 --- a/pkg/build/packaging/rpm.go +++ b/pkg/build/packaging/rpm.go @@ -10,12 +10,15 @@ import ( "path/filepath" "strings" + // Consider switching this over to a community fork unless there is + // an option to move us away from OpenPGP. + "golang.org/x/crypto/openpgp" //nolint:staticcheck + "golang.org/x/crypto/openpgp/armor" //nolint:staticcheck + "golang.org/x/crypto/openpgp/packet" //nolint:staticcheck + "github.com/grafana/grafana/pkg/build/config" "github.com/grafana/grafana/pkg/build/fsutil" "github.com/grafana/grafana/pkg/infra/fs" - "golang.org/x/crypto/openpgp" - "golang.org/x/crypto/openpgp/armor" - "golang.org/x/crypto/openpgp/packet" ) // UpdateRPMRepo updates the RPM repository with the new release. diff --git a/pkg/build/stringutil/contains.go b/pkg/build/stringutil/contains.go new file mode 100644 index 0000000000000..b53efe707594d --- /dev/null +++ b/pkg/build/stringutil/contains.go @@ -0,0 +1,10 @@ +package stringutil + +func Contains(arr []string, s string) bool { + for _, e := range arr { + if e == s { + return true + } + } + return false +} diff --git a/pkg/build/versions/version.go b/pkg/build/versions/version.go new file mode 100644 index 0000000000000..c1ee0b33d67bc --- /dev/null +++ b/pkg/build/versions/version.go @@ -0,0 +1,160 @@ +package versions + +import ( + "encoding/json" + "fmt" + "io" + "log" + "net/http" + "regexp" + "strconv" + + "github.com/Masterminds/semver/v3" +) + +var ( + reGrafanaTag = regexp.MustCompile(`^v(\d+\.\d+\.\d+$)`) + reGrafanaTagBeta = regexp.MustCompile(`^v(\d+\.\d+\.\d+-beta)`) + reGrafanaTagCustom = regexp.MustCompile(`^v(\d+\.\d+\.\d+-\w+)`) +) + +const ( + Latest = "latest" + Next = "next" + Test = "test" +) + +type Version struct { + Version string + Channel string +} + +type VersionFromAPI struct { + Version string `json:"version"` +} + +type LatestGcomAPI = string + +const ( + LatestStableVersionURL LatestGcomAPI = "https://grafana.com/api/grafana/versions/stable" + LatestBetaVersionURL LatestGcomAPI = "https://grafana.com/api/grafana/versions/beta" +) + +func GetLatestVersion(url LatestGcomAPI) (string, error) { + // nolint:gosec + resp, err := http.Get(url) + if err != nil { + return "", err + } + defer func() { + if err := resp.Body.Close(); err != nil { + log.Printf("Failed to close body: %s", err.Error()) + } + }() + + if resp.StatusCode != http.StatusOK { + return "", fmt.Errorf("server returned non 200 status code: %d", resp.StatusCode) + } + + body, err := io.ReadAll(resp.Body) + if err != nil { + return "", err + } + + var apiResponse VersionFromAPI + err = json.Unmarshal(body, &apiResponse) + if err != nil { + return "", err + } + + return apiResponse.Version, nil +} + +// IsGreaterThanOrEqual semantically checks whether newVersion is greater than or equal to stableVersion. +func IsGreaterThanOrEqual(newVersion, stableVersion string) (bool, error) { + v1SemVer, err := semver.NewVersion(newVersion) + if err != nil { + return isGreaterThanOrEqualFourDigit(newVersion, stableVersion) + } + + v2SemVer, err := semver.NewVersion(stableVersion) + if err != nil { + return isGreaterThanOrEqualFourDigit(newVersion, stableVersion) + } + + comp := v1SemVer.Compare(v2SemVer) + switch comp { + case -1: + return false, nil + case 1, 0: + return true, nil + default: + return true, fmt.Errorf("unknown comparison value between scemantic versions, err: %q", err) + } +} + +var fourDigitRe = regexp.MustCompile(`(\d+\.\d+\.\d+)\.(\d+)`) + +func parseFourDigit(version string) (*semver.Version, int, error) { + matches := fourDigitRe.FindStringSubmatch(version) + if len(matches) < 2 { + semVer, err := semver.NewVersion(version) + if err != nil { + return nil, 0, err + } + return semVer, 0, nil + } + semVer, err := semver.NewVersion(matches[1]) + if err != nil { + return nil, 0, err + } + i, err := strconv.Atoi(matches[2]) + if err != nil { + return nil, 0, err + } + + return semVer, i, nil +} + +func isGreaterThanOrEqualFourDigit(newVersion, stableVersion string) (bool, error) { + newVersionSemVer, newVersionSemVerNo, err := parseFourDigit(newVersion) + if err != nil { + return false, err + } + + stableVersionSemVer, stableVersionSemVerNo, err := parseFourDigit(stableVersion) + if err != nil { + return false, err + } + + if stableVersionSemVer.Original() != newVersionSemVer.Original() { + return IsGreaterThanOrEqual(newVersionSemVer.Original(), stableVersionSemVer.Original()) + } + + return newVersionSemVerNo >= stableVersionSemVerNo, nil +} + +func GetVersion(tag string) (*Version, error) { + var version Version + switch { + case reGrafanaTag.MatchString(tag): + version = Version{ + Version: reGrafanaTag.FindStringSubmatch(tag)[1], + Channel: Latest, + } + case reGrafanaTagBeta.MatchString(tag): + version = Version{ + Version: reGrafanaTagBeta.FindStringSubmatch(tag)[1], + Channel: Next, + } + case reGrafanaTagCustom.MatchString(tag): + version = Version{ + Version: reGrafanaTagCustom.FindStringSubmatch(tag)[1], + Channel: Test, + } + default: + return nil, fmt.Errorf("%s not a supported Grafana version, exitting", tag) + } + + return &version, nil +} diff --git a/pkg/build/versions/version_test.go b/pkg/build/versions/version_test.go new file mode 100644 index 0000000000000..8d80ace1429c2 --- /dev/null +++ b/pkg/build/versions/version_test.go @@ -0,0 +1,69 @@ +package versions + +import ( + "encoding/json" + "fmt" + "net/http" + "net/http/httptest" + "testing" + + "github.com/stretchr/testify/require" +) + +func TestIsGreaterThanOrEqual(t *testing.T) { + testCases := []struct { + newVersion string + stableVersion string + expected bool + }{ + {newVersion: "9.0.0", stableVersion: "8.0.0", expected: true}, + {newVersion: "6.0.0", stableVersion: "6.0.0", expected: true}, + {newVersion: "7.0.0", stableVersion: "8.0.0", expected: false}, + {newVersion: "8.5.0-beta1", stableVersion: "8.0.0", expected: true}, + {newVersion: "8.5.0", stableVersion: "8.5.0-beta1", expected: true}, + {newVersion: "9.0.0.1", stableVersion: "9.0.0", expected: true}, + {newVersion: "9.0.0.2", stableVersion: "9.0.0.1", expected: true}, + {newVersion: "9.1.0", stableVersion: "9.0.0.1", expected: true}, + {newVersion: "9.1-0-beta1", stableVersion: "9.0.0.1", expected: true}, + {newVersion: "9.0.0.1", stableVersion: "9.0.1.1", expected: false}, + {newVersion: "9.0.1.1", stableVersion: "9.0.0.1", expected: true}, + {newVersion: "9.0.0.1", stableVersion: "9.0.0.1", expected: true}, + {newVersion: "7.0.0.1", stableVersion: "8.0.0", expected: false}, + {newVersion: "9.1-0-beta1", stableVersion: "9.1-0-beta2", expected: false}, + {newVersion: "9.1-0-beta3", stableVersion: "9.1-0-beta2", expected: true}, + } + + for _, tc := range testCases { + name := fmt.Sprintf("newVersion %s greater than or equal stableVersion %s = %v", tc.newVersion, tc.stableVersion, tc.expected) + t.Run(name, func(t *testing.T) { + result, err := IsGreaterThanOrEqual(tc.newVersion, tc.stableVersion) + require.NoError(t, err) + require.Equal(t, tc.expected, result) + }) + } +} + +func TestGetLatestVersion(t *testing.T) { + t.Run("it returns a version", func(t *testing.T) { + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { + response := VersionFromAPI{ + Version: "8.4.0", + } + jsonRes, err := json.Marshal(&response) + require.NoError(t, err) + _, err = w.Write(jsonRes) + require.NoError(t, err) + })) + version, err := GetLatestVersion(server.URL) + require.NoError(t, err) + require.Equal(t, "8.4.0", version) + }) + + t.Run("it handles non 200 responses", func(t *testing.T) { + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { + w.WriteHeader(http.StatusInternalServerError) + })) + _, err := GetLatestVersion(server.URL) + require.Error(t, err) + }) +} diff --git a/pkg/services/contexthandler/auth_jwt.go b/pkg/services/contexthandler/auth_jwt.go index b671d816d687c..29b6d4da682e4 100644 --- a/pkg/services/contexthandler/auth_jwt.go +++ b/pkg/services/contexthandler/auth_jwt.go @@ -10,13 +10,15 @@ import ( "github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/services/org" "github.com/grafana/grafana/pkg/services/user" + "github.com/grafana/grafana/pkg/setting" "github.com/jmespath/go-jmespath" ) const ( - InvalidJWT = "Invalid JWT" - InvalidRole = "Invalid Role" - UserNotFound = "User not found" + InvalidJWT = "Invalid JWT" + InvalidRole = "Invalid Role" + UserNotFound = "User not found" + authQueryParamName = "auth_token" ) func (h *ContextHandler) initContextWithJWT(ctx *models.ReqContext, orgId int64) bool { @@ -26,13 +28,16 @@ func (h *ContextHandler) initContextWithJWT(ctx *models.ReqContext, orgId int64) jwtToken := ctx.Req.Header.Get(h.Cfg.JWTAuthHeaderName) if jwtToken == "" && h.Cfg.JWTAuthURLLogin { - jwtToken = ctx.Req.URL.Query().Get("auth_token") + params := ctx.Req.URL.Query() + jwtToken = params.Get(authQueryParamName) } if jwtToken == "" { return false } + stripSensitiveParam(h.Cfg, ctx.Req) + // Strip the 'Bearer' prefix if it exists. jwtToken = strings.TrimPrefix(jwtToken, "Bearer ") @@ -205,3 +210,15 @@ func looksLikeJWT(token string) bool { parts := strings.Split(token, ".") return len(parts) == 3 } + +// remove sensitive query params +// avoid JWT URL login passing auth_token in URL +func stripSensitiveParam(cfg *setting.Cfg, httpRequest *http.Request) { + if cfg.JWTAuthURLLogin { + params := httpRequest.URL.Query() + if params.Has(authQueryParamName) { + params.Del(authQueryParamName) + httpRequest.URL.RawQuery = params.Encode() + } + } +} diff --git a/pkg/services/featuremgmt/registry.go b/pkg/services/featuremgmt/registry.go index 70884cd5fa04e..cf20ef80494c7 100644 --- a/pkg/services/featuremgmt/registry.go +++ b/pkg/services/featuremgmt/registry.go @@ -318,5 +318,35 @@ var ( Name: "increaseInMemDatabaseQueryCache", Description: "Enable more in memory caching for database queries", }, + { + Name: "userRemoteCache", + Description: "Enable using remote cache for users", + State: FeatureStateAlpha, + }, + { + Name: "datasourceLogger", + Description: "Logs all datasource requests", + }, + { + Name: "sessionRemoteCache", + Description: "Enable using remote cache for user sessions", + State: FeatureStateAlpha, + }, + { + Name: "redshiftAsyncQueryDataSupport", + Description: "Enable async query data support for Redshift", + State: FeatureStateAlpha, + FrontendOnly: true, + }, + { + Name: "athenaAsyncQueryDataSupport", + Description: "Enable async query data support for Athena", + State: FeatureStateAlpha, + FrontendOnly: true, + }, + { + Name: "increaseInMemDatabaseQueryCache", + Description: "Enable more in memory caching for database queries", + }, } ) diff --git a/pkg/services/ngalert/api/tooling/api.json b/pkg/services/ngalert/api/tooling/api.json index 7dcc10782dd5c..3ba09a98fc6ec 100644 --- a/pkg/services/ngalert/api/tooling/api.json +++ b/pkg/services/ngalert/api/tooling/api.json @@ -184,6 +184,9 @@ "AlertStateType": { "type": "string" }, + "AlertStateType": { + "type": "string" + }, "AlertingRule": { "description": "adapted from cortex", "properties": { @@ -3611,6 +3614,37 @@ ], "type": "object" }, + "integration": { + "description": "Integration integration", + "properties": { + "lastNotifyAttempt": { + "description": "A timestamp indicating the last attempt to deliver a notification regardless of the outcome.\nFormat: date-time", + "format": "date-time", + "type": "string" + }, + "lastNotifyAttemptDuration": { + "description": "Duration of the last attempt to deliver a notification in humanized format (`1s` or `15ms`, etc).", + "type": "string" + }, + "lastNotifyAttemptError": { + "description": "Error string for the last attempt to deliver a notification. Empty if the last attempt was successful.", + "type": "string" + }, + "name": { + "description": "name", + "type": "string" + }, + "sendResolved": { + "description": "send resolved", + "type": "boolean" + } + }, + "required": [ + "name", + "sendResolved" + ], + "type": "object" + }, "labelSet": { "additionalProperties": { "type": "string" diff --git a/pkg/services/ngalert/api/tooling/post.json b/pkg/services/ngalert/api/tooling/post.json index 60bb01d66dc4c..57e26c180347f 100644 --- a/pkg/services/ngalert/api/tooling/post.json +++ b/pkg/services/ngalert/api/tooling/post.json @@ -184,6 +184,9 @@ "AlertStateType": { "type": "string" }, + "AlertStateType": { + "type": "string" + }, "AlertingRule": { "description": "adapted from cortex", "properties": { diff --git a/pkg/services/ngalert/api/tooling/spec.json b/pkg/services/ngalert/api/tooling/spec.json index 585344664a1bb..b7d8638444794 100644 --- a/pkg/services/ngalert/api/tooling/spec.json +++ b/pkg/services/ngalert/api/tooling/spec.json @@ -3286,6 +3286,9 @@ "AlertStateType": { "type": "string" }, + "AlertStateType": { + "type": "string" + }, "AlertingRule": { "description": "adapted from cortex", "type": "object", diff --git a/pkg/services/ngalert/provisioning/notification_policies.go b/pkg/services/ngalert/provisioning/notification_policies.go index b7489485162b0..f9e71ef868371 100644 --- a/pkg/services/ngalert/provisioning/notification_policies.go +++ b/pkg/services/ngalert/provisioning/notification_policies.go @@ -74,6 +74,10 @@ func (nps *NotificationPolicyService) UpdatePolicyTree(ctx context.Context, orgI } receivers, err := nps.receiversToMap(revision.cfg.AlertmanagerConfig.Receivers) + if err != nil { + return err + } + err = tree.ValidateReceivers(receivers) if err != nil { return fmt.Errorf("%w: %s", ErrValidation, err.Error()) diff --git a/pkg/services/sqlstore/migrations/accesscontrol/dashboard_permissions.go b/pkg/services/sqlstore/migrations/accesscontrol/dashboard_permissions.go index aa20a878aeb0b..57ee6b542b839 100644 --- a/pkg/services/sqlstore/migrations/accesscontrol/dashboard_permissions.go +++ b/pkg/services/sqlstore/migrations/accesscontrol/dashboard_permissions.go @@ -150,9 +150,7 @@ func (m dashboardPermissionsMigrator) migratePermissions(dashboards []dashboard, return fmt.Errorf("failed to bulk-create roles: %w", err) } - for i := range createdRoles { - allRoles = append(allRoles, createdRoles[i]) - } + allRoles = append(allRoles, createdRoles...) if err := m.bulkAssignRoles(createdRoles); err != nil { return fmt.Errorf("failed to bulk-assign roles: %w", err) diff --git a/pkg/services/sqlstore/migrations/ualert/migration_test.go b/pkg/services/sqlstore/migrations/ualert/migration_test.go index 2076fd99476f8..13b8add29ab49 100644 --- a/pkg/services/sqlstore/migrations/ualert/migration_test.go +++ b/pkg/services/sqlstore/migrations/ualert/migration_test.go @@ -542,6 +542,43 @@ func TestDashAlertMigration(t *testing.T) { } } }) + + t.Run("when folder is missing put alert in General folder", func(t *testing.T) { + o := createOrg(t, 1) + folder1 := createDashboard(t, 1, o.Id, "folder-1") + folder1.IsFolder = true + dash1 := createDashboard(t, 3, o.Id, "dash1") + dash1.FolderId = folder1.Id + dash2 := createDashboard(t, 4, o.Id, "dash2") + dash2.FolderId = 22 // missing folder + + a1 := createAlert(t, o.Id, dash1.Id, int64(1), "alert-1", []string{}) + a2 := createAlert(t, o.Id, dash2.Id, int64(1), "alert-2", []string{}) + + _, err := x.Insert(o, folder1, dash1, dash2, a1, a2) + require.NoError(t, err) + + runDashAlertMigrationTestRun(t, x) + + rules := getAlertRules(t, x, o.Id) + require.Len(t, rules, 2) + + var generalFolder models.Dashboard + _, err = x.Table(&models.Dashboard{}).Where("title = ? AND org_id = ?", ualert.GENERAL_FOLDER, o.Id).Get(&generalFolder) + require.NoError(t, err) + + require.NotNil(t, generalFolder) + + for _, rule := range rules { + var expectedFolder models.Dashboard + if rule.Title == a1.Name { + expectedFolder = *folder1 + } else { + expectedFolder = generalFolder + } + require.Equal(t, expectedFolder.Uid, rule.NamespaceUID) + } + }) } const ( diff --git a/pkg/services/sqlstore/migrations/ualert/ualert.go b/pkg/services/sqlstore/migrations/ualert/ualert.go index aad94f761e3dc..c633883a3a6d5 100644 --- a/pkg/services/sqlstore/migrations/ualert/ualert.go +++ b/pkg/services/sqlstore/migrations/ualert/ualert.go @@ -262,10 +262,35 @@ func (m *migration) Exec(sess *xorm.Session, mg *migrator.Migrator) error { // cache for the general folders generalFolderCache := make(map[int64]*dashboard) + folderHelper := folderHelper{ + sess: sess, + mg: mg, + } + + gf := func(dash dashboard, da dashAlert) (*dashboard, error) { + f, ok := generalFolderCache[dash.OrgId] + if !ok { + // get or create general folder + f, err = folderHelper.getOrCreateGeneralFolder(dash.OrgId) + if err != nil { + return nil, MigrationError{ + Err: fmt.Errorf("failed to get or create general folder under organisation %d: %w", dash.OrgId, err), + AlertId: da.Id, + } + } + generalFolderCache[dash.OrgId] = f + } + // No need to assign default permissions to general folder + // because they are included to the query result if it's a folder with no permissions + // https://github.com/grafana/grafana/blob/076e2ce06a6ecf15804423fcc8dca1b620a321e5/pkg/services/sqlstore/dashboard_acl.go#L109 + return f, nil + } + // Per org map of newly created rules to which notification channels it should send to. rulesPerOrg := make(map[int64]map[*alertRule][]uidOrID) for _, da := range dashAlerts { + l := mg.Logger.New("ruleID", da.Id, "ruleName", da.Name, "dashboardUID", da.DashboardUID, "orgID", da.OrgId) newCond, err := transConditions(*da.ParsedSettings, da.OrgId, dsIDMap) if err != nil { return err @@ -289,18 +314,13 @@ func (m *migration) Exec(sess *xorm.Session, mg *migrator.Migrator) error { } } - folderHelper := folderHelper{ - sess: sess, - mg: mg, - } - var folder *dashboard switch { case dash.HasACL: folderName := getAlertFolderNameFromDashboard(&dash) f, ok := folderCache[folderName] if !ok { - mg.Logger.Info("create a new folder for alerts that belongs to dashboard because it has custom permissions", "org", dash.OrgId, "dashboard_uid", dash.Uid, "folder", folderName) + l.Info("create a new folder for alerts that belongs to dashboard because it has custom permissions", "folder", folderName) // create folder and assign the permissions of the dashboard (included default and inherited) f, err = folderHelper.createFolder(dash.OrgId, folderName) if err != nil { @@ -330,29 +350,20 @@ func (m *migration) Exec(sess *xorm.Session, mg *migrator.Migrator) error { // get folder if exists f, err := folderHelper.getFolder(dash, da) if err != nil { - return MigrationError{ - Err: err, - AlertId: da.Id, + // If folder does not exist then the dashboard is an orphan and we migrate the alert to the general folder. + l.Warn("Failed to find folder for dashboard. Migrate rule to the default folder", "rule_name", da.Name, "dashboard_uid", da.DashboardUID, "missing_folder_id", dash.FolderId) + folder, err = gf(dash, da) + if err != nil { + return err } + } else { + folder = &f } - folder = &f default: - f, ok := generalFolderCache[dash.OrgId] - if !ok { - // get or create general folder - f, err = folderHelper.getOrCreateGeneralFolder(dash.OrgId) - if err != nil { - return MigrationError{ - Err: fmt.Errorf("failed to get or create general folder under organisation %d: %w", dash.OrgId, err), - AlertId: da.Id, - } - } - generalFolderCache[dash.OrgId] = f + folder, err = gf(dash, da) + if err != nil { + return err } - // No need to assign default permissions to general folder - // because they are included to the query result if it's a folder with no permissions - // https://github.com/grafana/grafana/blob/076e2ce06a6ecf15804423fcc8dca1b620a321e5/pkg/services/sqlstore/dashboard_acl.go#L109 - folder = f } if folder.Uid == "" { diff --git a/pkg/tests/api/alerting/api_alertmanager_test.go b/pkg/tests/api/alerting/api_alertmanager_test.go index d13d83d34c40e..d6a484805b84f 100644 --- a/pkg/tests/api/alerting/api_alertmanager_test.go +++ b/pkg/tests/api/alerting/api_alertmanager_test.go @@ -17,7 +17,9 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/grafana/grafana/pkg/expr" "github.com/grafana/grafana/pkg/models" + apimodels "github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions" ngmodels "github.com/grafana/grafana/pkg/services/ngalert/models" ngstore "github.com/grafana/grafana/pkg/services/ngalert/store" @@ -34,6 +36,8 @@ type Response struct { } func TestAMConfigAccess(t *testing.T) { + t.Skip("skip broken test") + dir, path := testinfra.CreateGrafDir(t, testinfra.GrafanaOpts{ DisableLegacyAlerting: true, EnableUnifiedAlerting: true, @@ -207,11 +211,11 @@ func TestAMConfigAccess(t *testing.T) { }) t.Run("when creating silence", func(t *testing.T) { - body := ` + now := time.Now() + body := fmt.Sprintf(` { "comment": "string", "createdBy": "string", - "endsAt": "2023-03-31T14:17:04.419Z", "matchers": [ { "isRegex": true, @@ -219,9 +223,10 @@ func TestAMConfigAccess(t *testing.T) { "value": "string" } ], - "startsAt": "2021-03-31T13:17:04.419Z" + "startsAt": "%s", + "endsAt": "%s" } - ` + `, now.Format(time.RFC3339), now.Add(10*time.Second).Format(time.RFC3339)) testCases := []testCase{ { diff --git a/pkg/tsdb/azuremonitor/loganalytics/azure-log-analytics-datasource.go b/pkg/tsdb/azuremonitor/loganalytics/azure-log-analytics-datasource.go index 7e0a984e60bdd..58907fbee2715 100644 --- a/pkg/tsdb/azuremonitor/loganalytics/azure-log-analytics-datasource.go +++ b/pkg/tsdb/azuremonitor/loganalytics/azure-log-analytics-datasource.go @@ -172,7 +172,7 @@ func (e *AzureLogAnalyticsDatasource) executeQuery(ctx context.Context, query *A tracer.Inject(ctx, req.Header, span) azlog.Debug("AzureLogAnalytics", "Request ApiURL", req.URL.String()) - res, err := client.Do(req) + res, err := client.Do(req) //nolint:bodyclose // fixed in main if err != nil { return dataResponseErrorWithExecuted(err) } diff --git a/pkg/tsdb/azuremonitor/resourcegraph/azure-resource-graph-datasource.go b/pkg/tsdb/azuremonitor/resourcegraph/azure-resource-graph-datasource.go index 72b42f174cfe1..b1dc5538629f1 100644 --- a/pkg/tsdb/azuremonitor/resourcegraph/azure-resource-graph-datasource.go +++ b/pkg/tsdb/azuremonitor/resourcegraph/azure-resource-graph-datasource.go @@ -178,7 +178,7 @@ func (e *AzureResourceGraphDatasource) executeQuery(ctx context.Context, query * tracer.Inject(ctx, req.Header, span) azlog.Debug("AzureResourceGraph", "Request ApiURL", req.URL.String()) - res, err := client.Do(req) + res, err := client.Do(req) //nolint:bodyclose // fixed in main if err != nil { return dataResponseErrorWithExecuted(err) } diff --git a/pkg/tsdb/cloudmonitoring/time_series_filter.go b/pkg/tsdb/cloudmonitoring/time_series_filter.go index 021a293c49dcb..ae7b750906b0b 100644 --- a/pkg/tsdb/cloudmonitoring/time_series_filter.go +++ b/pkg/tsdb/cloudmonitoring/time_series_filter.go @@ -69,6 +69,12 @@ func (timeSeriesFilter *cloudMonitoringTimeSeriesFilter) run(ctx context.Context r = r.WithContext(ctx) res, err := dsInfo.services[cloudMonitor].client.Do(r) + defer func() { + if err := res.Body.Close(); err != nil { + slog.Warn("Failed to close response body", "err", err) + return + } + }() if err != nil { dr.Error = err return dr, cloudMonitoringResponse{}, "", nil diff --git a/pkg/tsdb/cloudmonitoring/time_series_query.go b/pkg/tsdb/cloudmonitoring/time_series_query.go index 1f5af1d4501ed..bacf8df5a71b0 100644 --- a/pkg/tsdb/cloudmonitoring/time_series_query.go +++ b/pkg/tsdb/cloudmonitoring/time_series_query.go @@ -78,6 +78,12 @@ func (timeSeriesQuery *cloudMonitoringTimeSeriesQuery) run(ctx context.Context, r = r.WithContext(ctx) res, err := dsInfo.services[cloudMonitor].client.Do(r) + defer func() { + if err := res.Body.Close(); err != nil { + slog.Warn("Failed to close response body", "err", err) + return + } + }() if err != nil { dr.Error = err return dr, cloudMonitoringResponse{}, "", nil diff --git a/pkg/tsdb/graphite/graphite.go b/pkg/tsdb/graphite/graphite.go index 37c1f53b7f726..4d02c9ca469cb 100644 --- a/pkg/tsdb/graphite/graphite.go +++ b/pkg/tsdb/graphite/graphite.go @@ -162,7 +162,10 @@ func (s *Service) QueryData(ctx context.Context, req *backend.QueryDataRequest) defer span.End() s.tracer.Inject(ctx, graphiteReq.Header, span) - res, err := dsInfo.HTTPClient.Do(graphiteReq) + res, err := dsInfo.HTTPClient.Do(graphiteReq) //nolint:bodyclose // fixed in main + if res != nil { + span.SetAttributes("graphite.response.code", res.StatusCode, attribute.Key("graphite.response.code").Int(res.StatusCode)) + } if err != nil { return &result, err } diff --git a/pkg/tsdb/opentsdb/opentsdb.go b/pkg/tsdb/opentsdb/opentsdb.go index 954e5c08319c9..1b19164c92308 100644 --- a/pkg/tsdb/opentsdb/opentsdb.go +++ b/pkg/tsdb/opentsdb/opentsdb.go @@ -91,7 +91,7 @@ func (s *Service) QueryData(ctx context.Context, req *backend.QueryDataRequest) return &backend.QueryDataResponse{}, err } - res, err := dsInfo.HTTPClient.Do(request) + res, err := dsInfo.HTTPClient.Do(request) //nolint:bodyclose // fixed in main if err != nil { return &backend.QueryDataResponse{}, err } diff --git a/pkg/tsdb/prometheus/querydata/request.go b/pkg/tsdb/prometheus/querydata/request.go index 2e52aaab2bde0..4e29ba51dc31d 100644 --- a/pkg/tsdb/prometheus/querydata/request.go +++ b/pkg/tsdb/prometheus/querydata/request.go @@ -151,6 +151,7 @@ func (s *QueryData) fetch(ctx context.Context, client *client.Client, q *models. } func (s *QueryData) rangeQuery(ctx context.Context, c *client.Client, q *models.Query, headers map[string]string) (*backend.DataResponse, error) { + //nolint:bodyclose // fixed in main res, err := c.QueryRange(ctx, q, sdkHeaderToHttpHeader(headers)) if err != nil { return nil, err @@ -159,6 +160,7 @@ func (s *QueryData) rangeQuery(ctx context.Context, c *client.Client, q *models. } func (s *QueryData) instantQuery(ctx context.Context, c *client.Client, q *models.Query, headers map[string]string) (*backend.DataResponse, error) { + //nolint:bodyclose // fixed in main res, err := c.QueryInstant(ctx, q, sdkHeaderToHttpHeader(headers)) if err != nil { return nil, err @@ -167,6 +169,7 @@ func (s *QueryData) instantQuery(ctx context.Context, c *client.Client, q *model } func (s *QueryData) exemplarQuery(ctx context.Context, c *client.Client, q *models.Query, headers map[string]string) (*backend.DataResponse, error) { + //nolint:bodyclose // fixed in main res, err := c.QueryExemplars(ctx, q, sdkHeaderToHttpHeader(headers)) if err != nil { return nil, err diff --git a/pkg/tsdb/prometheus/querydata/request_test.go b/pkg/tsdb/prometheus/querydata/request_test.go index 5ff93ad8ee12f..d01c9c644b239 100644 --- a/pkg/tsdb/prometheus/querydata/request_test.go +++ b/pkg/tsdb/prometheus/querydata/request_test.go @@ -351,7 +351,7 @@ func execute(tctx *testContext, query backend.DataQuery, qr interface{}) (data.F Headers: map[string]string{}, } - promRes, err := toAPIResponse(qr) + promRes, err := toAPIResponse(qr) //nolint:bodyclose // fixed in main if err != nil { return nil, err } diff --git a/pkg/util/errutil/log.go b/pkg/util/errutil/log.go index 58f008131eba2..eff9700815baf 100644 --- a/pkg/util/errutil/log.go +++ b/pkg/util/errutil/log.go @@ -31,7 +31,7 @@ func (l LogLevel) LogFunc(logger LogInterface) func(msg string, ctx ...interface return logger.Info case LevelWarn: return logger.Warn - default: // LevelUnknown and LevelError + default: // LevelUnknown and LevelError. return logger.Error } } diff --git a/plugins-bundled/internal/input-datasource/package.json b/plugins-bundled/internal/input-datasource/package.json index 4ff0d7df9644e..eafc010c24a3a 100644 --- a/plugins-bundled/internal/input-datasource/package.json +++ b/plugins-bundled/internal/input-datasource/package.json @@ -1,6 +1,6 @@ { "name": "@grafana-plugins/input-datasource", - "version": "9.2.13", + "version": "9.2.18", "description": "Input Datasource", "private": true, "repository": { @@ -15,15 +15,15 @@ }, "author": "Grafana Labs", "devDependencies": { - "@grafana/toolkit": "9.2.13", + "@grafana/toolkit": "9.2.18", "@types/jest": "26.0.15", "@types/lodash": "4.14.149", "@types/react": "17.0.30", "lodash": "4.17.21" }, "dependencies": { - "@grafana/data": "9.2.13", - "@grafana/ui": "9.2.13", + "@grafana/data": "9.2.18", + "@grafana/ui": "9.2.18", "jquery": "3.5.1", "react": "17.0.1", "react-dom": "17.0.1", diff --git a/public/app/features/alerting/unified/components/rule-editor/QueryRows.tsx b/public/app/features/alerting/unified/components/rule-editor/QueryRows.tsx index 42dddb36fec90..53ff0f10dc20c 100644 --- a/public/app/features/alerting/unified/components/rule-editor/QueryRows.tsx +++ b/public/app/features/alerting/unified/components/rule-editor/QueryRows.tsx @@ -202,7 +202,11 @@ export class QueryRows extends PureComponent { }; getDataSourceSettings = (query: AlertQuery): DataSourceInstanceSettings | undefined => { - return getDataSourceSrv().getInstanceSettings(query.datasourceUid); + let uid = query.datasourceUid; + if (isExpressionQuery(query.model)) { + uid = query.model.datasource?.type ?? query.datasourceUid; + } + return getDataSourceSrv().getInstanceSettings(uid); }; getThresholdsForQueries = (queries: AlertQuery[]): Record => { diff --git a/public/app/features/alerting/unified/components/rule-viewer/RuleViewerVisualization.tsx b/public/app/features/alerting/unified/components/rule-viewer/RuleViewerVisualization.tsx index 4739f2e526b88..a8cebb0116a26 100644 --- a/public/app/features/alerting/unified/components/rule-viewer/RuleViewerVisualization.tsx +++ b/public/app/features/alerting/unified/components/rule-viewer/RuleViewerVisualization.tsx @@ -28,7 +28,11 @@ export function RuleViewerVisualization(props: RuleViewerVisualizationProps): JS const { data, query, onChangeQuery } = props; const defaultPanel = isExpressionQuery(query.model) ? TABLE : TIMESERIES; const [panel, setPanel] = useState(defaultPanel); - const dsSettings = getDataSourceSrv().getInstanceSettings(query.datasourceUid); + let uid = query.datasourceUid; + if (isExpressionQuery(query.model)) { + uid = query.model.datasource?.type ?? query.datasourceUid; + } + const dsSettings = getDataSourceSrv().getInstanceSettings(uid); const relativeTimeRange = query.relativeTimeRange; const [options, setOptions] = useState({ frameIndex: 0, diff --git a/public/app/features/alerting/unified/hooks/useAlertQueriesStatus.ts b/public/app/features/alerting/unified/hooks/useAlertQueriesStatus.ts index 4a7b3386a927a..af3b744ceaa65 100644 --- a/public/app/features/alerting/unified/hooks/useAlertQueriesStatus.ts +++ b/public/app/features/alerting/unified/hooks/useAlertQueriesStatus.ts @@ -1,11 +1,18 @@ import { useMemo } from 'react'; import { getDataSourceSrv } from '@grafana/runtime'; +import { isExpressionReference } from '@grafana/runtime/src/utils/DataSourceWithBackend'; import { AlertQuery } from 'app/types/unified-alerting-dto'; export function useAlertQueriesStatus(queries: AlertQuery[]) { const allDataSourcesAvailable = useMemo( - () => queries.every((query) => Boolean(getDataSourceSrv().getInstanceSettings(query.datasourceUid))), + () => + queries + .filter((query) => !isExpressionReference(query.datasourceUid)) + .every((query) => { + const instanceSettings = getDataSourceSrv().getInstanceSettings(query.datasourceUid); + return Boolean(instanceSettings); + }), [queries] ); diff --git a/public/app/features/alerting/unified/utils/misc.ts b/public/app/features/alerting/unified/utils/misc.ts index af75f60522fb7..153c9f5952a0e 100644 --- a/public/app/features/alerting/unified/utils/misc.ts +++ b/public/app/features/alerting/unified/utils/misc.ts @@ -103,6 +103,7 @@ export function makeDataSourceLink(dataSource: Dat } export function makeFolderLink(folderUID: string, slug: string): string { + // @PERCONA add slug to url return `${config.appSubUrl}/dashboards/f/${folderUID}/${slug}`; } diff --git a/public/app/features/dashboard/components/ShareModal/SharePublicDashboard/SharePublicDashboard.test.tsx b/public/app/features/dashboard/components/ShareModal/SharePublicDashboard/SharePublicDashboard.test.tsx index 690fc241f97fe..e6ea9772cea73 100644 --- a/public/app/features/dashboard/components/ShareModal/SharePublicDashboard/SharePublicDashboard.test.tsx +++ b/public/app/features/dashboard/components/ShareModal/SharePublicDashboard/SharePublicDashboard.test.tsx @@ -87,6 +87,7 @@ beforeEach(() => { mockPanel = new PanelModel({ id: 'mockPanelId', + timezone: 'utc', }); jest.spyOn(contextSrv, 'hasAccess').mockReturnValue(true); @@ -143,7 +144,7 @@ describe('SharePublic', () => { await renderSharePublicDashboard({ panel: mockPanel, dashboard: mockDashboard, onDismiss: () => {} }); await screen.findByText('Welcome to Grafana public dashboards alpha!'); - expect(screen.getByText('2022-08-30 00:00:00 to 2022-09-04 01:59:59')).toBeInTheDocument(); + expect(screen.getByText('2022-08-30 00:00:00 to 2022-09-04 00:59:59')).toBeInTheDocument(); }); it('when modal is opened, then loader spinner appears and inputs are disabled', async () => { await renderSharePublicDashboard({ panel: mockPanel, dashboard: mockDashboard, onDismiss: () => {} }); diff --git a/public/app/features/plugins/datasource_srv.ts b/public/app/features/plugins/datasource_srv.ts index 6483056f97ba7..fd02192626faf 100644 --- a/public/app/features/plugins/datasource_srv.ts +++ b/public/app/features/plugins/datasource_srv.ts @@ -7,15 +7,15 @@ import { ScopedVars, } from '@grafana/data'; import { - GetDataSourceListFilters, DataSourceSrv as DataSourceService, + getBackendSrv, + GetDataSourceListFilters, getDataSourceSrv as getDataSourceService, - TemplateSrv, - getTemplateSrv, getLegacyAngularInjector, - getBackendSrv, + getTemplateSrv, + TemplateSrv, } from '@grafana/runtime'; -import { ExpressionDatasourceRef } from '@grafana/runtime/src/utils/DataSourceWithBackend'; +import { ExpressionDatasourceRef, isExpressionReference } from '@grafana/runtime/src/utils/DataSourceWithBackend'; import appEvents from 'app/core/app_events'; import config from 'app/core/config'; import { @@ -80,6 +80,13 @@ export class DatasourceSrv implements DataSourceService { return this.settingsMapByUid[this.defaultName] ?? this.settingsMapByName[this.defaultName]; } + // Expressions has a new UID as __expr__ See: https://github.com/grafana/grafana/pull/62510/ + // But we still have dashboards/panels with old expression UID (-100) + // To support both UIDs until we migrate them all to new one, this check is necessary + if (isExpressionReference(nameOrUid)) { + return expressionDatasource.instanceSettings; + } + // Complex logic to support template variable data source names // For this we just pick the current or first data source in the variable if (nameOrUid[0] === '$') { diff --git a/public/app/features/plugins/tests/datasource_srv.test.ts b/public/app/features/plugins/tests/datasource_srv.test.ts index 14517b7d3e82f..d19635ba59567 100644 --- a/public/app/features/plugins/tests/datasource_srv.test.ts +++ b/public/app/features/plugins/tests/datasource_srv.test.ts @@ -5,6 +5,7 @@ import { DataSourcePluginMeta, ScopedVar, } from '@grafana/data'; +import { ExpressionDatasourceRef } from '@grafana/runtime/src/utils/DataSourceWithBackend'; import { DatasourceSrv } from 'app/features/plugins/datasource_srv'; // Datasource variable $datasource with current value 'BBB' @@ -199,6 +200,25 @@ describe('datasource_srv', () => { } `); }); + + it('should return expression settings with either expression UIDs', () => { + const exprWithOldUID = dataSourceSrv.getInstanceSettings('-100'); + expect(exprWithOldUID?.name).toBe('Expression'); + expect(exprWithOldUID?.uid).toBe(ExpressionDatasourceRef.uid); + expect(exprWithOldUID?.type).toBe(ExpressionDatasourceRef.type); + + const exprWithNewUID = dataSourceSrv.getInstanceSettings('__expr__'); + expect(exprWithNewUID?.name).toBe('Expression'); + expect(exprWithNewUID?.uid).toBe(ExpressionDatasourceRef.uid); + expect(exprWithNewUID?.type).toBe(ExpressionDatasourceRef.type); + }); + + it('should return expression settings with expression name', () => { + const exprWithName = dataSourceSrv.getInstanceSettings('Expression'); + expect(exprWithName?.name).toBe(ExpressionDatasourceRef.name); + expect(exprWithName?.uid).toBe(ExpressionDatasourceRef.uid); + expect(exprWithName?.type).toBe(ExpressionDatasourceRef.type); + }); }); describe('when getting external metric sources', () => { diff --git a/public/app/features/query/components/QueryEditorRow.tsx b/public/app/features/query/components/QueryEditorRow.tsx index 5c7252e901e0d..ec4d052c298fb 100644 --- a/public/app/features/query/components/QueryEditorRow.tsx +++ b/public/app/features/query/components/QueryEditorRow.tsx @@ -33,6 +33,8 @@ import { getTimeSrv } from 'app/features/dashboard/services/TimeSrv'; import { DashboardModel } from 'app/features/dashboard/state/DashboardModel'; import { PanelModel } from 'app/features/dashboard/state/PanelModel'; +import { isExpressionQuery } from '../../expressions/guards'; + import { RowActionComponents } from './QueryActionComponent'; import { QueryEditorRowHeader } from './QueryEditorRowHeader'; import { QueryErrorAlert } from './QueryErrorAlert'; @@ -135,6 +137,9 @@ export class QueryEditorRow extends PureComponent { - // @ts-ignore - const { default: rst2html } = await import(/* webpackChunkName: "rst2html" */ 'rst2html'); return { default(props: { description?: string }) { - return
; + return
{props.description}
; }, }; }); diff --git a/public/app/plugins/datasource/influxdb/migrations.ts b/public/app/plugins/datasource/influxdb/migrations.ts index ad53c824d3beb..e0ebecf016997 100644 --- a/public/app/plugins/datasource/influxdb/migrations.ts +++ b/public/app/plugins/datasource/influxdb/migrations.ts @@ -1,3 +1,5 @@ +import { InfluxQuery, InfluxQueryTag } from './types'; + type LegacyAnnotation = { query?: string; queryType?: string; @@ -7,11 +9,19 @@ type LegacyAnnotation = { timeEndColumn?: string; titleColumn?: string; name?: string; + target?: { + limit?: string | number | undefined; + matchAny?: boolean; + tags?: InfluxQueryTag[]; + type?: string; + }; }; // this becomes the target in the migrated annotations const migrateLegacyAnnotation = (json: LegacyAnnotation) => { - return { + // eslint-ignore-next-line + const target: InfluxQuery = { + refId: '', query: json.query ?? '', queryType: 'tags', fromAnnotations: true, @@ -21,11 +31,31 @@ const migrateLegacyAnnotation = (json: LegacyAnnotation) => { titleColumn: json.titleColumn ?? '', name: json.name ?? '', }; + + // handle json target fields + if (json.target && json.target.limit) { + target.limit = json.target.limit; + } + + if (json.target && json.target.matchAny) { + target.matchAny = json.target.matchAny; + } + + if (json.target && json.target.tags) { + target.tags = json.target.tags; + } + + if (json.target && json.target.type) { + target.type = json.target.type; + } + + return target; }; // eslint-ignore-next-line export const prepareAnnotation = (json: any) => { - json.target = json.target ?? migrateLegacyAnnotation(json); + // make sure that any additional target fields are migrated + json.target = json.target && !json.target?.query ? migrateLegacyAnnotation(json) : json.target; return json; }; diff --git a/public/app/plugins/datasource/influxdb/response_parser.ts b/public/app/plugins/datasource/influxdb/response_parser.ts index a156e98be56bb..4dc1c2b63263b 100644 --- a/public/app/plugins/datasource/influxdb/response_parser.ts +++ b/public/app/plugins/datasource/influxdb/response_parser.ts @@ -158,7 +158,7 @@ export default class ResponseParser { function colContainsTag(colText: string, tagsColumn: string): boolean { const tags = (tagsColumn || '').replace(' ', '').split(','); for (const tag of tags) { - if (colText.includes(tag)) { + if (tag !== '' && colText.includes(tag)) { return true; } } diff --git a/public/app/plugins/datasource/influxdb/types.ts b/public/app/plugins/datasource/influxdb/types.ts index a3eb732c568c6..6bb354f71d7e9 100644 --- a/public/app/plugins/datasource/influxdb/types.ts +++ b/public/app/plugins/datasource/influxdb/types.ts @@ -69,5 +69,8 @@ export interface InfluxQuery extends DataQuery { timeEndColumn?: string; titleColumn?: string; name?: string; + matchAny?: boolean; + type?: string; + textEditor?: boolean; } diff --git a/public/app/plugins/datasource/mysql/MySqlDatasource.ts b/public/app/plugins/datasource/mysql/MySqlDatasource.ts new file mode 100644 index 0000000000000..9075f9d5e5b77 --- /dev/null +++ b/public/app/plugins/datasource/mysql/MySqlDatasource.ts @@ -0,0 +1,104 @@ +import { DataSourceInstanceSettings, ScopedVars, TimeRange } from '@grafana/data'; +import { CompletionItemKind, LanguageDefinition, TableIdentifier } from '@grafana/experimental'; +import { TemplateSrv } from '@grafana/runtime'; +import { SqlDatasource } from 'app/features/plugins/sql/datasource/SqlDatasource'; +import { DB, ResponseParser, SQLQuery } from 'app/features/plugins/sql/types'; +import { formatSQL } from 'app/features/plugins/sql/utils/formatSQL'; + +import MySQLQueryModel from './MySqlQueryModel'; +import MySqlResponseParser from './MySqlResponseParser'; +import { mapFieldsToTypes } from './fields'; +import { buildColumnQuery, buildTableQuery, showDatabases } from './mySqlMetaQuery'; +import { getSqlCompletionProvider } from './sqlCompletionProvider'; +import { MySQLOptions } from './types'; + +export class MySqlDatasource extends SqlDatasource { + responseParser: MySqlResponseParser; + sqlLanguageDefinition: LanguageDefinition | undefined; + + constructor(private instanceSettings: DataSourceInstanceSettings) { + super(instanceSettings); + this.responseParser = new MySqlResponseParser(); + } + + getQueryModel(target?: Partial, templateSrv?: TemplateSrv, scopedVars?: ScopedVars): MySQLQueryModel { + return new MySQLQueryModel(target!, templateSrv, scopedVars); + } + + getResponseParser(): ResponseParser { + return this.responseParser; + } + + getSqlLanguageDefinition(db: DB): LanguageDefinition { + if (this.sqlLanguageDefinition !== undefined) { + return this.sqlLanguageDefinition; + } + + const args = { + getMeta: { current: (identifier?: TableIdentifier) => this.fetchMeta(identifier) }, + }; + this.sqlLanguageDefinition = { + id: 'sql', + completionProvider: getSqlCompletionProvider(args), + formatter: formatSQL, + }; + return this.sqlLanguageDefinition; + } + + async fetchDatasets(): Promise { + const datasets = await this.runSql(showDatabases(), { refId: 'datasets' }); + return datasets.map((t) => t[0]); + } + + async fetchTables(dataset?: string): Promise { + const tables = await this.runSql(buildTableQuery(dataset), { refId: 'tables' }); + return tables.map((t) => t[0]); + } + + async fetchFields(query: Partial) { + if (!query.dataset || !query.table) { + return []; + } + const queryString = buildColumnQuery(this.getQueryModel(query), query.table!); + const frame = await this.runSql(queryString, { refId: 'fields' }); + const fields = frame.map((f) => ({ name: f[0], text: f[0], value: f[0], type: f[1], label: f[0] })); + return mapFieldsToTypes(fields); + } + + async fetchMeta(identifier?: TableIdentifier) { + const defaultDB = this.instanceSettings.jsonData.database; + if (!identifier?.schema && defaultDB) { + const tables = await this.fetchTables(defaultDB); + return tables.map((t) => ({ name: t, completion: `${defaultDB}.${t}`, kind: CompletionItemKind.Class })); + } else if (!identifier?.schema && !defaultDB) { + const datasets = await this.fetchDatasets(); + return datasets.map((d) => ({ name: d, completion: `${d}.`, kind: CompletionItemKind.Module })); + } else { + if (!identifier?.table && !defaultDB) { + const tables = await this.fetchTables(identifier?.schema); + return tables.map((t) => ({ name: t, completion: t, kind: CompletionItemKind.Class })); + } else if (identifier?.table && identifier.schema) { + const fields = await this.fetchFields({ dataset: identifier.schema, table: identifier.table }); + return fields.map((t) => ({ name: t.value, completion: t.value, kind: CompletionItemKind.Field })); + } else { + return []; + } + } + } + + getDB(): DB { + if (this.db !== undefined) { + return this.db; + } + return { + datasets: () => this.fetchDatasets(), + tables: (dataset?: string) => this.fetchTables(dataset), + fields: (query: SQLQuery) => this.fetchFields(query), + validateQuery: (query: SQLQuery, range?: TimeRange) => + Promise.resolve({ query, error: '', isError: false, isValid: true }), + dsID: () => this.id, + functions: () => ['VARIANCE', 'STDDEV'], + getEditorLanguageDefinition: () => this.getSqlLanguageDefinition(this.db), + }; + } +} diff --git a/public/app/plugins/datasource/mysql/MySqlResponseParser.ts b/public/app/plugins/datasource/mysql/MySqlResponseParser.ts new file mode 100644 index 0000000000000..d4ef6c9f0d75c --- /dev/null +++ b/public/app/plugins/datasource/mysql/MySqlResponseParser.ts @@ -0,0 +1,27 @@ +import { uniqBy } from 'lodash'; + +import { DataFrame, MetricFindValue } from '@grafana/data'; + +export default class ResponseParser { + transformMetricFindResponse(frame: DataFrame): MetricFindValue[] { + const values: MetricFindValue[] = []; + const textField = frame.fields.find((f) => f.name === '__text'); + const valueField = frame.fields.find((f) => f.name === '__value'); + + if (textField && valueField) { + for (let i = 0; i < textField.values.length; i++) { + values.push({ text: '' + textField.values.get(i), value: '' + valueField.values.get(i) }); + } + } else { + values.push( + ...frame.fields + .flatMap((f) => f.values.toArray()) + .map((v) => ({ + text: v, + })) + ); + } + + return uniqBy(values, 'text'); + } +} diff --git a/public/app/plugins/datasource/mysql/configuration/ConfigurationEditor.tsx b/public/app/plugins/datasource/mysql/configuration/ConfigurationEditor.tsx new file mode 100644 index 0000000000000..b32669907603a --- /dev/null +++ b/public/app/plugins/datasource/mysql/configuration/ConfigurationEditor.tsx @@ -0,0 +1,182 @@ +import React, { SyntheticEvent } from 'react'; + +import { + DataSourcePluginOptionsEditorProps, + onUpdateDatasourceJsonDataOption, + onUpdateDatasourceSecureJsonDataOption, + updateDatasourcePluginJsonDataOption, + updateDatasourcePluginResetOption, +} from '@grafana/data'; +import { Alert, FieldSet, InlineField, InlineFieldRow, InlineSwitch, Input, Link, SecretInput } from '@grafana/ui'; +import { ConnectionLimits } from 'app/features/plugins/sql/components/configuration/ConnectionLimits'; +import { TLSSecretsConfig } from 'app/features/plugins/sql/components/configuration/TLSSecretsConfig'; + +import { MySQLOptions } from '../types'; + +export const ConfigurationEditor = (props: DataSourcePluginOptionsEditorProps) => { + const { options, onOptionsChange } = props; + const jsonData = options.jsonData; + + const onResetPassword = () => { + updateDatasourcePluginResetOption(props, 'password'); + }; + + const onDSOptionChanged = (property: keyof MySQLOptions) => { + return (event: SyntheticEvent) => { + onOptionsChange({ ...options, ...{ [property]: event.currentTarget.value } }); + }; + }; + + const onSwitchChanged = (property: keyof MySQLOptions) => { + return (event: SyntheticEvent) => { + updateDatasourcePluginJsonDataOption(props, property, event.currentTarget.checked); + }; + }; + + const mediumWidth = 20; + const shortWidth = 15; + const longWidth = 40; + + return ( + <> +
+ + + + + + + + + + + + + + + + Specify the time zone used in the database session, e.g. Europe/Berlin or + +02:00. This is necessary, if the timezone of the database (or the host of the database) is + set to something other than UTC. The value is set in the session with + SET time_zone='...'. If you leave this field empty, the timezone is not updated. + You can find more information in the MySQL documentation. + + } + label="Session timezone" + labelWidth={mediumWidth} + > + + + + + + + + + + + + + +
+ + {jsonData.tlsAuth || jsonData.tlsAuthWithCACert ? ( +
+ +
+ ) : null} + + { + updateDatasourcePluginJsonDataOption(props, property, value); + }} + > + +
+ + A lower limit for the auto group by time interval. Recommended to be set to write frequency, for example + 1m if your data is written every minute. + + } + labelWidth={mediumWidth} + label="Min time interval" + > + + +
+ + + The database user should only be granted SELECT permissions on the specified database & tables you want to + query. Grafana does not validate that queries are safe so queries can contain any SQL statement. For example, + statements like USE otherdb; and DROP TABLE user; would be executed. To protect + against this we Highly recommend you create a specific MySQL user with restricted permissions. + Checkout the{' '} + + MySQL Data Source Docs + + for more information. + + + ); +}; diff --git a/public/app/plugins/datasource/mysql/fields.ts b/public/app/plugins/datasource/mysql/fields.ts new file mode 100644 index 0000000000000..96eb122c35e86 --- /dev/null +++ b/public/app/plugins/datasource/mysql/fields.ts @@ -0,0 +1,91 @@ +import { RAQBFieldTypes, SQLSelectableValue } from 'app/features/plugins/sql/types'; + +export function mapFieldsToTypes(columns: SQLSelectableValue[]) { + const fields: SQLSelectableValue[] = []; + for (const col of columns) { + let type: RAQBFieldTypes = 'text'; + switch (col.type?.toUpperCase()) { + case 'BOOLEAN': + case 'BOOL': { + type = 'boolean'; + break; + } + case 'BYTES': + case 'VARCHAR': { + type = 'text'; + break; + } + case 'FLOAT': + case 'FLOAT64': + case 'INT': + case 'INTEGER': + case 'INT64': + case 'NUMERIC': + case 'BIGNUMERIC': { + type = 'number'; + break; + } + case 'DATE': { + type = 'date'; + break; + } + case 'DATETIME': { + type = 'datetime'; + break; + } + case 'TIME': { + type = 'time'; + break; + } + case 'TIMESTAMP': { + type = 'datetime'; + break; + } + case 'GEOGRAPHY': { + type = 'text'; + break; + } + default: + break; + } + + fields.push({ ...col, raqbFieldType: type, icon: mapColumnTypeToIcon(col.type!.toUpperCase()) }); + } + return fields; +} + +export function mapColumnTypeToIcon(type: string) { + switch (type) { + case 'TIME': + case 'DATETIME': + case 'TIMESTAMP': + return 'clock-nine'; + case 'BOOLEAN': + return 'toggle-off'; + case 'INTEGER': + case 'FLOAT': + case 'FLOAT64': + case 'INT': + case 'SMALLINT': + case 'BIGINT': + case 'TINYINT': + case 'BYTEINT': + case 'INT64': + case 'NUMERIC': + case 'DECIMAL': + return 'calculator-alt'; + case 'CHAR': + case 'VARCHAR': + case 'STRING': + case 'BYTES': + case 'TEXT': + case 'TINYTEXT': + case 'MEDIUMTEXT': + case 'LONGTEXT': + return 'text'; + case 'GEOGRAPHY': + return 'map'; + default: + return undefined; + } +} diff --git a/public/app/plugins/datasource/mysql/mySqlMetaQuery.ts b/public/app/plugins/datasource/mysql/mySqlMetaQuery.ts new file mode 100644 index 0000000000000..25d09bcb8e0c0 --- /dev/null +++ b/public/app/plugins/datasource/mysql/mySqlMetaQuery.ts @@ -0,0 +1,60 @@ +import MySQLQueryModel from './MySqlQueryModel'; + +export function buildTableQuery(dataset?: string) { + const database = dataset !== undefined ? `'${dataset}'` : 'database()'; + return `SELECT table_name FROM information_schema.tables WHERE table_schema = ${database} ORDER BY table_name`; +} + +export function showDatabases() { + return `SELECT DISTINCT TABLE_SCHEMA from information_schema.TABLES where TABLE_TYPE != 'SYSTEM VIEW' ORDER BY TABLE_SCHEMA`; +} + +export function buildColumnQuery(queryModel: MySQLQueryModel, table: string, type?: string, timeColumn?: string) { + let query = 'SELECT column_name, data_type FROM information_schema.columns WHERE '; + query += buildTableConstraint(queryModel, table); + + switch (type) { + case 'time': { + query += " AND data_type IN ('timestamp','datetime','bigint','int','double','float')"; + break; + } + case 'metric': { + query += " AND data_type IN ('text','tinytext','mediumtext','longtext','varchar','char')"; + break; + } + case 'value': { + query += " AND data_type IN ('bigint','int','smallint','mediumint','tinyint','double','decimal','float')"; + query += ' AND column_name <> ' + quoteIdentAsLiteral(queryModel, timeColumn!); + break; + } + case 'group': { + query += " AND data_type IN ('text','tinytext','mediumtext','longtext','varchar','char')"; + break; + } + } + + query += ' ORDER BY column_name'; + + return query; +} + +export function buildTableConstraint(queryModel: MySQLQueryModel, table: string) { + let query = ''; + + // check for schema qualified table + if (table.includes('.')) { + const parts = table.split('.'); + query = 'table_schema = ' + quoteIdentAsLiteral(queryModel, parts[0]); + query += ' AND table_name = ' + quoteIdentAsLiteral(queryModel, parts[1]); + return query; + } else { + const database = queryModel.getDatabase() !== undefined ? `'${queryModel.getDatabase()}'` : 'database()'; + query = `table_schema = ${database} AND table_name = ` + quoteIdentAsLiteral(queryModel, table); + + return query; + } +} + +export function quoteIdentAsLiteral(queryModel: MySQLQueryModel, value: string) { + return queryModel.quoteLiteral(queryModel.unquoteIdentifier(value)); +} diff --git a/public/app/plugins/datasource/postgres/configuration/ConfigurationEditor.tsx b/public/app/plugins/datasource/postgres/configuration/ConfigurationEditor.tsx new file mode 100644 index 0000000000000..9a8184abb02ec --- /dev/null +++ b/public/app/plugins/datasource/postgres/configuration/ConfigurationEditor.tsx @@ -0,0 +1,287 @@ +import React, { SyntheticEvent, useState } from 'react'; + +import { + DataSourcePluginOptionsEditorProps, + onUpdateDatasourceJsonDataOption, + onUpdateDatasourceSecureJsonDataOption, + SelectableValue, + updateDatasourcePluginJsonDataOption, + updateDatasourcePluginResetOption, +} from '@grafana/data'; +import { Alert, InlineSwitch, FieldSet, InlineField, InlineFieldRow, Input, Select, SecretInput } from '@grafana/ui'; +import { ConnectionLimits } from 'app/features/plugins/sql/components/configuration/ConnectionLimits'; +import { TLSSecretsConfig } from 'app/features/plugins/sql/components/configuration/TLSSecretsConfig'; + +import { PostgresOptions, PostgresTLSMethods, PostgresTLSModes, SecureJsonData } from '../types'; + +import { useAutoDetectFeatures } from './useAutoDetectFeatures'; + +export const postgresVersions: Array> = [ + { label: '9.0', value: 900 }, + { label: '9.1', value: 901 }, + { label: '9.2', value: 902 }, + { label: '9.3', value: 903 }, + { label: '9.4', value: 904 }, + { label: '9.5', value: 905 }, + { label: '9.6', value: 906 }, + { label: '10', value: 1000 }, + { label: '11', value: 1100 }, + { label: '12', value: 1200 }, + { label: '13', value: 1300 }, + { label: '14', value: 1400 }, + { label: '15', value: 1500 }, +]; + +export const PostgresConfigEditor = (props: DataSourcePluginOptionsEditorProps) => { + const [versionOptions, setVersionOptions] = useState(postgresVersions); + + useAutoDetectFeatures({ props, setVersionOptions }); + + const { options, onOptionsChange } = props; + const jsonData = options.jsonData; + + const onResetPassword = () => { + updateDatasourcePluginResetOption(props, 'password'); + }; + + const tlsModes: Array> = [ + { value: PostgresTLSModes.disable, label: 'disable' }, + { value: PostgresTLSModes.require, label: 'require' }, + { value: PostgresTLSModes.verifyCA, label: 'verify-ca' }, + { value: PostgresTLSModes.verifyFull, label: 'verify-full' }, + ]; + + const tlsMethods: Array> = [ + { value: PostgresTLSMethods.filePath, label: 'File system path' }, + { value: PostgresTLSMethods.fileContent, label: 'Certificate content' }, + ]; + + const onJSONDataOptionSelected = (property: keyof PostgresOptions) => { + return (value: SelectableValue) => { + updateDatasourcePluginJsonDataOption(props, property, value.value); + }; + }; + + const onTimeScaleDBChanged = (event: SyntheticEvent) => { + updateDatasourcePluginJsonDataOption(props, 'timescaledb', event.currentTarget.checked); + }; + + const onDSOptionChanged = (property: keyof PostgresOptions) => { + return (event: SyntheticEvent) => { + onOptionsChange({ ...options, ...{ [property]: event.currentTarget.value } }); + }; + }; + + const labelWidthSSLDetails = 25; + const labelWidthConnection = 20; + const labelWidthShort = 20; + + return ( + <> +
+ + + + + + + + + + + + + + + + + + {options.jsonData.sslmode !== PostgresTLSModes.disable ? ( + + This option determines how TLS/SSL certifications are configured. Selecting File system path will + allow you to configure certificates by specifying paths to existing certificates on the local file + system where Grafana is running. Be sure that the file is readable by the user executing the Grafana + process. +
+
+ Selecting Certificate content will allow you to configure certificates by specifying its content. + The content will be stored encrypted in Grafana's database. When connecting to the database the + certificates will be written as files to Grafana's configured data path on the local file system. + + } + > + +
+ ) : null} +
+ + {jsonData.sslmode !== PostgresTLSModes.disable ? ( +
+ {jsonData.tlsConfigurationMethod === PostgresTLSMethods.fileContent ? ( + + ) : ( + <> + + If the selected TLS/SSL mode requires a server root certificate, provide the path to the file here. + + } + labelWidth={labelWidthSSLDetails} + label="TLS/SSL Root Certificate" + > + + + + To authenticate with an TLS/SSL client certificate, provide the path to the file here. Be sure that + the file is readable by the user executing the grafana process. + + } + labelWidth={labelWidthSSLDetails} + label="TLS/SSL Client Certificate" + > + + + + To authenticate with a client TLS/SSL certificate, provide the path to the corresponding key file + here. Be sure that the file is only readable by the user executing the grafana process. + + } + labelWidth={labelWidthSSLDetails} + label="TLS/SSL Client Key" + > + + + + )} +
+ ) : null} + + { + updateDatasourcePluginJsonDataOption(props, property, value); + }} + > + +
+ + + + + TimescaleDB is a time-series database built as a PostgreSQL extension. If enabled, Grafana will use + time_bucket in the $__timeGroup macro and display TimescaleDB specific aggregate + functions in the query builder. + + } + labelWidth={labelWidthShort} + label="TimescaleDB" + htmlFor="timescaledb" + > + + + + A lower limit for the auto group by time interval. Recommended to be set to write frequency, for example + 1m if your data is written every minute. + + } + labelWidth={labelWidthShort} + label="Min time interval" + > + + +
+ + + The database user should only be granted SELECT permissions on the specified database & tables you want to + query. Grafana does not validate that queries are safe so queries can contain any SQL statement. For example, + statements like DELETE FROM user; and DROP TABLE user; would be executed. To protect + against this we Highly recommend you create a specific PostgreSQL user with restricted + permissions. + + + ); +}; diff --git a/public/app/plugins/datasource/postgres/configuration/useAutoDetectFeatures.ts b/public/app/plugins/datasource/postgres/configuration/useAutoDetectFeatures.ts new file mode 100644 index 0000000000000..be52d37ffa666 --- /dev/null +++ b/public/app/plugins/datasource/postgres/configuration/useAutoDetectFeatures.ts @@ -0,0 +1,87 @@ +import { Dispatch, SetStateAction, useState } from 'react'; +import { useDeepCompareEffect } from 'react-use'; + +import { + DataSourcePluginOptionsEditorProps, + DataSourceSettings, + SelectableValue, + updateDatasourcePluginJsonDataOption, + updateDatasourcePluginOption, +} from '@grafana/data'; +import { getBackendSrv } from '@grafana/runtime'; +import { getDatasourceSrv } from 'app/features/plugins/datasource_srv'; + +import { PostgresDatasource } from '../datasource'; +import { PostgresOptions, PostgresTLSModes, SecureJsonData } from '../types'; + +import { postgresVersions } from './ConfigurationEditor'; + +type Options = { + props: DataSourcePluginOptionsEditorProps; + setVersionOptions: Dispatch>>>; +}; + +export function useAutoDetectFeatures({ props, setVersionOptions }: Options) { + const [saved, setSaved] = useState(false); + const { options, onOptionsChange } = props; + + useDeepCompareEffect(() => { + const getVersion = async () => { + if (!saved) { + // We need to save the datasource before we can get the version so we can query the database with the options we have. + const result = await getBackendSrv().put<{ datasource: DataSourceSettings }>( + `/api/datasources/${options.id}`, + options + ); + + setSaved(true); + // This is needed or else we get an error when we try to save the datasource. + updateDatasourcePluginOption({ options, onOptionsChange }, 'version', result.datasource.version); + } else { + const datasource = await getDatasourceSrv().loadDatasource(options.name); + + if (datasource instanceof PostgresDatasource) { + const version = await datasource.getVersion(); + const versionNumber = parseInt(version, 10); + + // timescaledb is only available for 9.6+ + if (versionNumber >= 906 && !options.jsonData.timescaledb) { + const timescaledbVersion = await datasource.getTimescaleDBVersion(); + if (timescaledbVersion?.length) { + updateDatasourcePluginJsonDataOption({ options, onOptionsChange }, 'timescaledb', true); + } + } + const major = Math.trunc(versionNumber / 100); + const minor = versionNumber % 100; + let name = String(major); + if (versionNumber < 1000) { + name = String(major) + '.' + String(minor); + } + if (!postgresVersions.find((p) => p.value === versionNumber)) { + setVersionOptions((prev) => [...prev, { label: name, value: versionNumber }]); + } + if (options.jsonData.postgresVersion === undefined || options.jsonData.postgresVersion !== versionNumber) { + updateDatasourcePluginJsonDataOption({ options, onOptionsChange }, 'postgresVersion', versionNumber); + } + } + } + }; + // This logic is only going to run when we create a new datasource + if (isValidConfig(options)) { + getVersion(); + } + }, [options, saved, setVersionOptions]); +} + +function isValidConfig(options: DataSourceSettings) { + return ( + options.url && + options.database && + options.user && + (options.secureJsonData?.password || options.secureJsonFields?.password) && + (options.jsonData.sslmode === PostgresTLSModes.disable || + (options.jsonData.sslCertFile && options.jsonData.sslKeyFile && options.jsonData.sslRootCertFile)) && + !options.jsonData.postgresVersion && + !options.readOnly + ); +} diff --git a/public/app/plugins/datasource/postgres/types.ts b/public/app/plugins/datasource/postgres/types.ts index 8a9c679840db1..a07ff7a831a55 100644 --- a/public/app/plugins/datasource/postgres/types.ts +++ b/public/app/plugins/datasource/postgres/types.ts @@ -1,21 +1,46 @@ import { DataQuery, DataSourceJsonData } from '@grafana/data'; +import { SQLConnectionLimits } from 'app/features/plugins/sql/types'; -export interface PostgresQueryForInterpolation { - alias?: any; - format?: any; - rawSql?: any; - refId: any; - hide?: any; +export enum PostgresTLSModes { + disable = 'disable', + require = 'require', + verifyCA = 'verify-ca', + verifyFull = 'verify-full', } -export interface PostgresOptions extends DataSourceJsonData { +export enum PostgresTLSMethods { + filePath = 'file-path', + fileContent = 'file-content', +} +export interface PostgresOptions extends DataSourceJsonData, SQLConnectionLimits { + url: string; timeInterval: string; + database: string; + user: string; + tlsConfigurationMethod: PostgresTLSMethods; + sslmode: PostgresTLSModes; + sslRootCertFile: string; + sslCertFile: string; + sslKeyFile: string; + postgresVersion: number; + timescaledb: boolean; } -export type ResultFormat = 'time_series' | 'table'; +export interface SecureJsonData { + password: string; +} +export type ResultFormat = 'time_series' | 'table'; export interface PostgresQuery extends DataQuery { alias?: string; format?: ResultFormat; rawSql?: any; } + +export interface PostgresQueryForInterpolation { + alias?: any; + format?: any; + rawSql?: any; + refId: any; + hide?: any; +} diff --git a/public/app/plugins/datasource/prometheus/querybuilder/components/MetricSelect.test.tsx b/public/app/plugins/datasource/prometheus/querybuilder/components/MetricSelect.test.tsx index e76a6fecc541c..8ba7c27bac478 100644 --- a/public/app/plugins/datasource/prometheus/querybuilder/components/MetricSelect.test.tsx +++ b/public/app/plugins/datasource/prometheus/querybuilder/components/MetricSelect.test.tsx @@ -7,7 +7,7 @@ import { DataSourceInstanceSettings, MetricFindValue } from '@grafana/data/src'; import { PrometheusDatasource } from '../../datasource'; import { PromOptions } from '../../types'; -import { MetricSelect } from './MetricSelect'; +import { formatPrometheusLabelFilters, formatPrometheusLabelFiltersToString, MetricSelect } from './MetricSelect'; const instanceSettings = { url: 'proxied', @@ -129,6 +129,43 @@ describe('MetricSelect', () => { await userEvent.type(input, 'new'); await waitFor(() => expect(document.querySelector('mark')).not.toBeInTheDocument()); }); + + it('label filters properly join', () => { + const query = formatPrometheusLabelFilters([ + { + value: 'value', + label: 'label', + op: '=', + }, + { + value: 'value2', + label: 'label2', + op: '=', + }, + ]); + query.forEach((label) => { + expect(label.includes(',', 0)); + }); + }); + it('label filter creation', () => { + const labels = [ + { + value: 'value', + label: 'label', + op: '=', + }, + { + value: 'value2', + label: 'label2', + op: '=', + }, + ]; + + const queryString = formatPrometheusLabelFiltersToString('query', labels); + queryString.split(',').forEach((queryChunk) => { + expect(queryChunk.length).toBeGreaterThan(1); // must be longer then ',' + }); + }); }); async function openMetricSelect() { diff --git a/public/app/plugins/datasource/prometheus/querybuilder/components/MetricSelect.tsx b/public/app/plugins/datasource/prometheus/querybuilder/components/MetricSelect.tsx index 43fe9936bb865..5bda5e639200a 100644 --- a/public/app/plugins/datasource/prometheus/querybuilder/components/MetricSelect.tsx +++ b/public/app/plugins/datasource/prometheus/querybuilder/components/MetricSelect.tsx @@ -65,24 +65,6 @@ export function MetricSelect({ datasource, query, onChange, onGetMetrics, labels [styles.highlight] ); - const formatLabelFilters = (labelsFilters: QueryBuilderLabelFilter[]): string[] => { - return labelsFilters.map((label) => { - return `,${label.label}="${label.value}"`; - }); - }; - - /** - * Transform queryString and any currently set label filters into label_values() string - */ - const queryAndFilterToLabelValuesString = ( - queryString: string, - labelsFilters: QueryBuilderLabelFilter[] | undefined - ): string => { - return `label_values({__name__=~".*${queryString}"${ - labelsFilters ? formatLabelFilters(labelsFilters).join() : '' - }},__name__)`; - }; - /** * Reformat the query string and label filters to return all valid results for current query editor state */ @@ -92,7 +74,7 @@ export function MetricSelect({ datasource, query, onChange, onGetMetrics, labels ): string => { const queryString = regexifyLabelValuesQueryString(query); - return queryAndFilterToLabelValuesString(queryString, labelsFilters); + return formatPrometheusLabelFiltersToString(queryString, labelsFilters); }; /** @@ -161,3 +143,18 @@ const getStyles = (theme: GrafanaTheme2) => ({ background-color: ${theme.colors.warning.main}; `, }); + +export const formatPrometheusLabelFiltersToString = ( + queryString: string, + labelsFilters: QueryBuilderLabelFilter[] | undefined +): string => { + const filterArray = labelsFilters ? formatPrometheusLabelFilters(labelsFilters) : []; + + return `label_values({__name__=~".*${queryString}"${filterArray ? filterArray.join('') : ''}},__name__)`; +}; + +export const formatPrometheusLabelFilters = (labelsFilters: QueryBuilderLabelFilter[]): string[] => { + return labelsFilters.map((label) => { + return `,${label.label}="${label.value}"`; + }); +}; diff --git a/scripts/build/ci-build/Dockerfile b/scripts/build/ci-build/Dockerfile index a0c1e6f792c1f..6db37bb85bb83 100644 --- a/scripts/build/ci-build/Dockerfile +++ b/scripts/build/ci-build/Dockerfile @@ -102,7 +102,7 @@ RUN rm dockerize-linux-amd64-v${DOCKERIZE_VERSION}.tar.gz # Use old Debian (LTS into 2024) in order to ensure binary compatibility with older glibc's. FROM debian:buster-20220822 -ENV GOVERSION=1.19.4 \ +ENV GOVERSION=1.20.4 \ PATH=/usr/local/go/bin:$PATH \ GOPATH=/go \ NODEVERSION=16.14.0-1nodesource1 \ diff --git a/scripts/build/ci-windows-test/Dockerfile b/scripts/build/ci-windows-test/Dockerfile new file mode 100644 index 0000000000000..86dadef8e4cd3 --- /dev/null +++ b/scripts/build/ci-windows-test/Dockerfile @@ -0,0 +1,6 @@ +FROM golang:1.20.3-windowsservercore-1809 + +SHELL ["powershell", "-command"] + +RUN Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1')) +RUN choco install mingw -y --version 12.2.0.03042023 diff --git a/scripts/drone/TAGS b/scripts/drone/TAGS new file mode 100644 index 0000000000000..1c9f9da89a50e --- /dev/null +++ b/scripts/drone/TAGS @@ -0,0 +1,628 @@ + +events/release.star,6652 +ver_mode =ver_mode64,1602 +release_trigger =release_trigger65,1623 +def store_npm_packages_step():store_npm_packages_step74,1752 +def retrieve_npm_packages_step():retrieve_npm_packages_step90,2193 +def release_npm_packages_step():release_npm_packages_step107,2663 +def oss_pipelines(ver_mode = ver_mode, trigger = release_trigger):oss_pipelines123,3076 + environment =environment135,3492 + edition =edition136,3529 + services =services137,3549 + volumes =volumes138,3609 + package_steps =package_steps139,3659 + publish_steps =publish_steps140,3682 + should_publish =should_publish141,3705 + should_upload =should_upload142,3748 + init_steps =init_steps143,3818 + build_steps =build_steps152,4033 + integration_test_steps =integration_test_steps159,4342 + build_storybook =build_storybook182,5254 + publish_step =publish_step190,5674 + store_npm_step =store_npm_step191,5758 + windows_package_steps =windows_package_steps196,5957 + windows_pipeline =windows_pipeline198,6044 + name =name199,6077 + edition =edition200,6127 + trigger =trigger201,6154 + steps =steps202,6181 + platform =platform203,6256 + depends_on =depends_on204,6286 + environment =environment207,6393 + pipelines =pipelines209,6434 + name =name211,6470 + edition =edition212,6550 + trigger =trigger213,6581 + services =services214,6612 + steps =steps215,6639 + environment =environment216,6717 + volumes =volumes217,6756 + name =name225,6970 + edition =edition226,7038 + trigger =trigger227,7073 + services =services228,7108 + steps =steps229,7145 + environment =environment230,7329 + volumes =volumes231,7372 + deps =deps234,7433 +def enterprise_pipelines(ver_mode = ver_mode, trigger = release_trigger):enterprise_pipelines247,7856 + environment =environment259,8284 + edition =edition260,8328 + services =services261,8355 + volumes =volumes262,8415 + package_steps =package_steps263,8465 + publish_steps =publish_steps264,8488 + should_publish =should_publish265,8511 + should_upload =should_upload266,8554 + include_enterprise =include_enterprise267,8624 + edition2 =edition2268,8673 + init_steps =init_steps269,8702 + build_steps =build_steps277,8909 + integration_test_steps =integration_test_steps284,9218 + build_storybook =build_storybook312,10299 + publish_step =publish_step324,10892 + store_npm_step =store_npm_step325,10976 + windows_package_steps =windows_package_steps330,11175 + step =step333,11284 + deps_on_clone_enterprise_step =deps_on_clone_enterprise_step337,11418 + windows_pipeline =windows_pipeline347,11746 + name =name348,11779 + edition =edition349,11836 + trigger =trigger350,11863 + steps =steps351,11890 + platform =platform352,11965 + depends_on =depends_on353,11995 + environment =environment356,12109 + pipelines =pipelines358,12150 + name =name360,12186 + edition =edition361,12273 + trigger =trigger362,12304 + services =services363,12335 + steps =steps364,12362 + environment =environment365,12440 + volumes =volumes366,12479 + name =name374,12711 + edition =edition375,12786 + trigger =trigger376,12821 + services =services377,12856 + steps =steps378,12893 + environment =environment379,13213 + volumes =volumes380,13256 + deps =deps383,13317 +def enterprise2_pipelines(prefix = "", ver_mode = ver_mode, trigger = release_trigger):enterprise2_pipelines397,13769 + environment =environment412,14364 + edition =edition415,14424 + volumes =volumes416,14451 + package_steps =package_steps417,14501 + publish_steps =publish_steps418,14524 + should_publish =should_publish419,14547 + should_upload =should_upload420,14590 + include_enterprise =include_enterprise421,14660 + edition2 =edition2422,14709 + init_steps =init_steps423,14738 + build_steps =build_steps431,14945 + fetch_images =fetch_images442,15355 + upload_cdn =upload_cdn444,15497 + step =step458,16187 + deps_on_clone_enterprise_step =deps_on_clone_enterprise_step462,16321 + pipelines =pipelines472,16608 + name =name474,16644 + edition =edition475,16742 + trigger =trigger476,16773 + services =services477,16804 + steps =steps478,16831 + volumes =volumes479,16909 + environment =environment480,16940 +def publish_artifacts_step(mode):publish_artifacts_step486,17019 + security =security487,17053 + security =security489,17098 +def publish_artifacts_pipelines(mode):publish_artifacts_pipelines501,17538 + trigger =trigger502,17577 + steps =steps506,17655 + name =name512,17768 + trigger =trigger513,17820 + steps =steps514,17847 + edition =edition515,17870 + environment =environment516,17895 +def publish_packages_pipeline():publish_packages_pipeline519,17945 + trigger =trigger526,18162 + oss_steps =oss_steps530,18244 + enterprise_steps =enterprise_steps538,18560 + deps =deps545,18903 + name =name552,19062 + trigger =trigger553,19101 + steps =steps554,19128 + edition =edition555,19155 + depends_on =depends_on556,19180 + environment =environment557,19207 + name =name559,19266 + trigger =trigger560,19312 + steps =steps561,19339 + edition =edition562,19373 + depends_on =depends_on563,19398 + environment =environment564,19425 +def publish_npm_pipelines(mode):publish_npm_pipelines567,19482 + trigger =trigger568,19515 + steps =steps572,19593 + name =name580,19772 + trigger =trigger581,19827 + steps =steps582,19854 + edition =edition583,19877 + environment =environment584,19902 +def artifacts_page_pipeline():artifacts_page_pipeline587,19952 + trigger =trigger588,19983 + name =name593,20087 + trigger =trigger594,20128 + steps =steps595,20155 + edition =edition596,20220 + environment =environment597,20245 +def get_e2e_suffix():get_e2e_suffix600,20295 + +events/cron.star,1016 +aquasec_trivy_image =aquasec_trivy_image8,209 +def cronjobs(edition):cronjobs10,255 + grafana_com_nightly_pipeline =grafana_com_nightly_pipeline11,278 + cronName =cronName12,332 + name =name13,374 + steps =steps14,412 +def cron_job_pipeline(cronName, name, steps):cron_job_pipeline24,773 +def scan_docker_image_pipeline(edition, tag):scan_docker_image_pipeline43,1175 + edition =edition55,1530 + edition =edition57,1579 + docker_image =docker_image59,1608 + cronName =cronName62,1695 + name =name63,1725 + steps =steps64,1775 +def scan_docker_image_unkown_low_medium_vulnerabilities_step(docker_image):scan_docker_image_unkown_low_medium_vulnerabilities_step71,2047 +def scan_docker_image_high_critical_vulnerabilities_step(docker_image):scan_docker_image_high_critical_vulnerabilities_step80,2353 +def slack_job_failed_step(channel, image):slack_job_failed_step89,2646 +def post_to_grafana_com_step():post_to_grafana_com_step103,3069 + +events/main.star,633 +ver_mode =ver_mode49,966 +trigger =trigger50,984 +def main_pipelines(edition):main_pipelines62,1168 + drone_change_trigger =drone_change_trigger63,1197 + pipelines =pipelines79,1513 + name =name89,1951 + slack_channel =slack_channel90,1994 + trigger =trigger91,2045 + template =template92,2089 + secret =secret93,2135 + name =name97,2276 + slack_channel =slack_channel98,2310 + trigger =trigger99,2366 + depends_on =depends_on100,2425 + template =template101,2563 + secret =secret102,2604 + +events/pr.star,252 +ver_mode =ver_mode48,997 +trigger =trigger49,1013 +def pr_pipelines(edition):pr_pipelines62,1198 +def get_pr_trigger(include_paths = None, exclude_paths = None):get_pr_trigger76,2396 + paths_ex =paths_ex91,3080 + paths_in =paths_in92,3115 + +services/services.star,225 +def integration_test_services_volumes():integration_test_services_volumes5,79 +def integration_test_services(edition):integration_test_services14,292 + services =services15,332 +def ldap_service():ldap_service59,1616 + +utils/utils.star,561 +failure_template =failure_template11,191 +drone_change_template =drone_change_template12,509 + services =services19,932 + platform =platform20,955 + depends_on =depends_on21,983 + environment =environment22,1008 + volumes =volumes23,1036 + platform_conf =platform_conf50,2166 + platform_conf =platform_conf62,2534 + pipeline =pipeline70,2713 +def notify_pipeline(name, slack_channel, trigger, depends_on = [], template = None, secret = None):notify_pipeline105,3545 + trigger =trigger106,3645 + +pipelines/trigger_downstream.star,440 +trigger =trigger14,249 +def enterprise_downstream_pipeline(edition, ver_mode):enterprise_downstream_pipeline26,433 + environment =environment27,488 + steps =steps28,527 + deps =deps29,587 + name =name31,672 + edition =edition32,714 + trigger =trigger33,741 + services =services34,768 + steps =steps35,791 + depends_on =depends_on36,814 + environment =environment37,841 + +pipelines/verify_starlark.star,323 +def verify_starlark(trigger, ver_mode):verify_starlark17,305 + environment =environment18,345 + steps =steps19,382 + name =name26,546 + edition =edition27,600 + trigger =trigger28,625 + services =services29,652 + steps =steps30,675 + environment =environment31,698 + +pipelines/build.star,508 +def build_e2e(trigger, ver_mode, edition):build_e2e39,936 + environment =environment50,1096 + variants =variants51,1135 + init_steps =init_steps52,1219 + build_steps =build_steps61,1491 + publish_suffix =publish_suffix107,4049 + publish_suffix =publish_suffix109,4100 + name =name112,4158 + edition =edition113,4224 + environment =environment114,4249 + services =services115,4284 + steps =steps116,4307 + trigger =trigger117,4349 + +pipelines/shellcheck.star,386 +trigger =trigger15,235 +def shellcheck_step():shellcheck_step31,483 +def shellcheck_pipeline():shellcheck_pipeline43,725 + environment =environment44,752 + steps =steps45,789 + name =name50,886 + edition =edition51,918 + trigger =trigger52,943 + services =services53,970 + steps =steps54,993 + environment =environment55,1016 + +pipelines/verify_drone.star,317 +def verify_drone(trigger, ver_mode):verify_drone17,293 + environment =environment18,330 + steps =steps19,367 + name =name26,528 + edition =edition27,579 + trigger =trigger28,604 + services =services29,631 + steps =steps30,654 + environment =environment31,677 + +pipelines/test_backend.star,474 +def test_backend(trigger, ver_mode, edition = "oss"):test_backend23,463 + environment =environment35,882 + init_steps =init_steps36,921 + test_steps =test_steps46,1291 + pipeline_name =pipeline_name51,1387 + pipeline_name =pipeline_name53,1492 + name =name55,1584 + edition =edition56,1614 + trigger =trigger57,1641 + services =services58,1668 + steps =steps59,1691 + environment =environment60,1732 + +pipelines/lint_frontend.star,415 +def lint_frontend_pipeline(trigger, ver_mode):lint_frontend_pipeline16,260 + environment =environment26,546 + yarn_step =yarn_step27,583 + init_steps =init_steps29,660 + test_steps =test_steps33,736 + name =name37,812 + edition =edition38,864 + trigger =trigger39,889 + services =services40,916 + steps =steps41,939 + environment =environment42,980 + +pipelines/docs.star,494 +docs_paths =docs_paths19,383 +def docs_pipelines(edition, ver_mode, trigger):docs_pipelines28,511 + environment =environment29,559 + steps =steps30,598 + name =name40,815 + edition =edition41,858 + trigger =trigger42,885 + services =services43,912 + steps =steps44,935 + environment =environment45,958 +def lint_docs():lint_docs48,1000 +def trigger_docs_main():trigger_docs_main63,1328 +def trigger_docs_pr():trigger_docs_pr72,1478 + +pipelines/test_frontend.star,476 +def test_frontend(trigger, ver_mode, edition = "oss"):test_frontend20,374 + environment =environment32,794 + init_steps =init_steps33,833 + test_steps =test_steps41,1102 + pipeline_name =pipeline_name45,1205 + pipeline_name =pipeline_name47,1311 + name =name49,1404 + edition =edition50,1434 + trigger =trigger51,1461 + services =services52,1488 + steps =steps53,1511 + environment =environment54,1552 + +pipelines/integration_tests.star,483 +def integration_tests(trigger, ver_mode, edition):integration_tests26,542 + environment =environment37,900 + services =services38,939 + volumes =volumes39,989 + init_steps =init_steps40,1039 + test_steps =test_steps48,1282 + name =name54,1412 + edition =edition55,1468 + trigger =trigger56,1493 + services =services57,1520 + steps =steps58,1549 + environment =environment59,1590 + volumes =volumes60,1625 + +pipelines/windows.star,954 +def windows(trigger, edition, ver_mode):windows17,339 + environment =environment29,798 + init_cmds =init_cmds30,837 + steps =steps38,1205 + bucket =bucket49,1497 + ver_part =ver_part51,1590 + dir =dir52,1628 + dir =dir54,1670 + bucket =bucket55,1695 + build_no =build_no56,1736 + ver_part =ver_part57,1780 + installer_commands =installer_commands58,1842 + committish =committish100,3763 + committish =committish102,3846 + committish =committish104,3906 + download_grabpl_step_cmds =download_grabpl_step_cmds107,4057 + clone_cmds =clone_cmds113,4363 + name =name146,5711 + edition =edition147,5742 + trigger =trigger148,5769 + steps =steps149,5830 + depends_on =depends_on150,5889 + platform =platform151,6007 + environment =environment152,6037 + +pipelines/lint_backend.star,418 +def lint_backend_pipeline(trigger, ver_mode):lint_backend_pipeline18,306 + environment =environment28,590 + wire_step =wire_step29,627 + init_steps =init_steps31,704 + test_steps =test_steps36,809 + name =name43,959 + edition =edition44,1010 + trigger =trigger45,1035 + services =services46,1062 + steps =steps47,1085 + environment =environment48,1126 + +pipelines/publish_images.star,998 +def publish_image_steps(edition, mode, docker_repo):publish_image_steps17,303 + additional_docker_repo =additional_docker_repo31,922 + additional_docker_repo =additional_docker_repo33,979 + steps =steps34,1034 +def publish_image_pipelines_public():publish_image_pipelines_public45,1369 + mode =mode51,1521 + trigger =trigger52,1541 + name =name57,1641 + trigger =trigger58,1694 + steps =steps59,1721 + edition =edition60,1813 + environment =environment61,1835 + name =name63,1894 + trigger =trigger64,1954 + steps =steps65,1981 + edition =edition66,2091 + environment =environment67,2113 +def publish_image_pipelines_security():publish_image_pipelines_security70,2170 + mode =mode71,2210 + trigger =trigger72,2232 + name =name77,2332 + trigger =trigger78,2392 + steps =steps79,2419 + edition =edition80,2529 + environment =environment81,2551 + +steps/lib.star,8579 +grabpl_version =grabpl_version7,181 +build_image =build_image8,208 +publish_image =publish_image9,254 +deploy_docker_image =deploy_docker_image10,304 +alpine_image =alpine_image11,380 +curl_image =curl_image12,411 +windows_image =windows_image13,452 +wix_image =wix_image14,501 +go_image =go_image15,536 +disable_tests =disable_tests17,564 +trigger_oss =trigger_oss18,586 +def slack_step(channel, template, secret):slack_step24,653 +def yarn_install_step(edition = "oss"):yarn_install_step35,918 + deps =deps36,958 + deps =deps38,1004 +def wire_install_step():wire_install_step48,1222 +def identify_runner_step(platform = "linux"):identify_runner_step60,1454 +def clone_enterprise_step(ver_mode):clone_enterprise_step78,1916 + committish =committish87,2193 + committish =committish89,2268 + committish =committish91,2317 +def init_enterprise_step(ver_mode):init_enterprise_step105,2747 + source_commit =source_commit115,3098 + source_commit =source_commit117,3151 + environment =environment118,3191 + token =token121,3280 + environment =environment123,3369 + token =token126,3458 + environment =environment128,3518 + token =token129,3543 +def download_grabpl_step(platform = "linux"):download_grabpl_step148,4147 +def lint_drone_step():lint_drone_step173,4973 +def lint_starlark_step():lint_starlark_step185,5216 +def enterprise_downstream_step(edition, ver_mode):enterprise_downstream_step206,6000 + repo =repo219,6482 + step =step225,6623 +def lint_backend_step():lint_backend_step247,7248 +def benchmark_ldap_step():benchmark_ldap_step265,7713 +def build_storybook_step(edition, ver_mode):build_storybook_step278,8087 +def store_storybook_step(edition, ver_mode, trigger = None):store_storybook_step300,8743 + commands =commands314,9202 + commands =commands323,9521 + step =step325,9593 + when_cond =when_cond338,10125 + step =step346,10330 +def e2e_tests_artifacts(edition):e2e_tests_artifacts349,10391 +def upload_cdn_step(edition, ver_mode, trigger = None):upload_cdn_step386,12378 + deps =deps397,12763 + step =step407,12970 + step =step420,13423 +def build_backend_step(edition, ver_mode, variants = None):build_backend_step423,13482 + variants_str =variants_str437,14070 + variants_str =variants_str439,14109 + cmds =cmds443,14256 + build_no =build_no449,14418 + cmds =cmds450,14461 +def build_frontend_step(edition, ver_mode):build_frontend_step468,14906 + build_no =build_no478,15246 + cmds =cmds482,15356 + cmds =cmds487,15505 +def build_frontend_package_step(edition, ver_mode):build_frontend_package_step505,15960 + build_no =build_no515,16312 + cmds =cmds519,16422 + cmds =cmds524,16580 +def build_plugins_step(edition, ver_mode):build_plugins_step542,17053 + env =env544,17121 + env =env548,17220 +def test_backend_step():test_backend_step563,17607 +def test_backend_integration_step():test_backend_integration_step575,17880 +def betterer_frontend_step(edition = "oss"):betterer_frontend_step587,18187 + deps =deps596,18427 +def test_frontend_step(edition = "oss"):test_frontend_step609,18728 + deps =deps618,18962 +def lint_frontend_step():lint_frontend_step634,19343 +def test_a11y_frontend_step(ver_mode, edition, port = 3001):test_a11y_frontend_step652,19793 + commands =commands664,20279 + failure =failure667,20345 + failure =failure672,20483 +def frontend_metrics_step(edition, trigger = None):frontend_metrics_step693,21146 + step =step706,21507 + step =step721,22007 +def codespell_step():codespell_step724,22066 +def package_step(edition, ver_mode, variants = None):package_step736,22468 + deps =deps750,23006 + variants_str =variants_str757,23167 + variants_str =variants_str759,23206 + sign_args =sign_args762,23332 + env =env763,23362 + test_args =test_args769,23628 + sign_args =sign_args771,23661 + env =env772,23684 + test_args =test_args773,23703 + cmds =cmds777,23829 + build_no =build_no784,24036 + cmds =cmds785,24079 +def grafana_server_step(edition, port = 3001):grafana_server_step798,24459 + package_file_pfx =package_file_pfx808,24729 + package_file_pfx =package_file_pfx810,24788 + package_file_pfx =package_file_pfx812,24889 + environment =environment814,24938 +def e2e_tests_step(suite, edition, port = 3001, tries = None):e2e_tests_step837,25554 + cmd =cmd838,25617 +def cloud_plugins_e2e_tests_step(suite, edition, cloud, trigger = None):cloud_plugins_e2e_tests_step856,26186 + environment =environment869,26649 + when =when870,26670 + when =when872,26700 + environment =environment874,26748 + when =when882,27129 + branch =branch888,27345 + step =step889,27401 + step =step901,27822 +def build_docs_website_step():build_docs_website_step904,27874 +def copy_packages_for_docker_step(edition = None):copy_packages_for_docker_step916,28272 +def build_docker_images_step(edition, archs = None, ubuntu = False, publish = False):build_docker_images_step929,28622 + cmd =cmd943,29193 + ubuntu_sfx =ubuntu_sfx947,29307 + ubuntu_sfx =ubuntu_sfx949,29342 + environment =environment955,29468 +def fetch_images_step(edition):fetch_images_step979,30079 +def publish_images_step(edition, ver_mode, mode, docker_repo, trigger = None):publish_images_step997,30745 + name =name1013,31562 + docker_repo =docker_repo1014,31585 + mode =mode1016,31663 + mode =mode1018,31709 + environment =environment1020,31728 + cmd =cmd1026,31912 + deps =deps1029,32041 + deps =deps1032,32147 + name =name1035,32250 + docker_repo =docker_repo1036,32273 + cmd =cmd1038,32459 + step =step1040,32565 + step =step1052,32929 +def postgres_integration_tests_step():postgres_integration_tests_step1056,32989 + cmds =cmds1057,33028 +def mysql_integration_tests_step():mysql_integration_tests_step1079,33850 + cmds =cmds1080,33886 +def redis_integration_tests_step():redis_integration_tests_step1100,34629 +def memcached_integration_tests_step():memcached_integration_tests_step1114,35026 +def release_canary_npm_packages_step(edition, trigger = None):release_canary_npm_packages_step1128,35435 + step =step1141,35805 + step =step1153,36143 +def enterprise2_suffix(edition):enterprise2_suffix1156,36202 +def upload_packages_step(edition, ver_mode, trigger = None):upload_packages_step1161,36320 + deps =deps1176,36816 + step =step1184,37036 + step =step1195,37471 +def publish_grafanacom_step(edition, ver_mode):publish_grafanacom_step1198,37530 + cmd =cmd1211,38044 + build_no =build_no1215,38188 + cmd =cmd1216,38231 +def publish_linux_packages_step(edition, package_manager = "deb"):publish_linux_packages_step1239,38866 +def get_windows_steps(edition, ver_mode):get_windows_steps1261,39989 + init_cmds =init_cmds1270,40281 + steps =steps1278,40649 + bucket =bucket1289,40941 + ver_part =ver_part1291,41034 + dir =dir1292,41072 + dir =dir1294,41114 + bucket =bucket1295,41139 + build_no =build_no1296,41180 + ver_part =ver_part1297,41224 + installer_commands =installer_commands1298,41286 + committish =committish1340,43207 + committish =committish1342,43290 + committish =committish1344,43350 + download_grabpl_step_cmds =download_grabpl_step_cmds1347,43501 + clone_cmds =clone_cmds1353,43807 +def verify_gen_cue_step(edition):verify_gen_cue_step1387,45152 + deps =deps1388,45186 +def verify_gen_jsonnet_step(edition):verify_gen_jsonnet_step1402,45694 + deps =deps1403,45732 +def trigger_test_release():trigger_test_release1417,46236 +def artifacts_page_step():artifacts_page_step1451,47731 +def end_to_end_tests_deps():end_to_end_tests_deps1466,48058 +def compile_build_cmd(edition = "oss"):compile_build_cmd1476,48321 + dependencies =dependencies1477,48361 + dependencies =dependencies1479,48432 +def get_trigger_storybook(ver_mode):get_trigger_storybook1492,48780 + trigger_storybook =trigger_storybook1500,49031 + trigger_storybook =trigger_storybook1502,49088 + trigger_storybook =trigger_storybook1506,49168 + +vault.star,444 +pull_secret =pull_secret4,87 +github_token =github_token5,120 +drone_token =drone_token6,150 +prerelease_bucket =prerelease_bucket7,178 +gcp_upload_artifacts_key =gcp_upload_artifacts_key8,218 +azure_sp_app_id =azure_sp_app_id9,272 +azure_sp_app_pw =azure_sp_app_pw10,308 +azure_tenant =azure_tenant11,344 +def from_secret(secret):from_secret13,375 +def vault_secret(name, path, key):vault_secret18,451 +def secrets():secrets28,633 + +version.star,116 +ver_mode =ver_mode12,197 +trigger =trigger13,225 +def version_branch_pipelines():version_branch_pipelines15,268 diff --git a/scripts/drone/events/cron.star b/scripts/drone/events/cron.star index e36814f5dc35d..9b718f79572b4 100644 --- a/scripts/drone/events/cron.star +++ b/scripts/drone/events/cron.star @@ -1,79 +1,115 @@ -load('scripts/drone/vault.star', 'from_secret') +""" +This module provides functions for cronjob pipelines and steps used within. +""" -aquasec_trivy_image = 'aquasec/trivy:0.21.0' +load("scripts/drone/vault.star", "from_secret") +load( + "scripts/drone/steps/lib.star", + "compile_build_cmd", + "publish_image", +) -def cronjobs(edition): +aquasec_trivy_image = "aquasec/trivy:0.21.0" + +def cronjobs(): return [ - scan_docker_image_pipeline(edition, 'latest'), - scan_docker_image_pipeline(edition, 'main'), - scan_docker_image_pipeline(edition, 'latest-ubuntu'), - scan_docker_image_pipeline(edition, 'main-ubuntu'), + scan_docker_image_pipeline("latest"), + scan_docker_image_pipeline("main"), + scan_docker_image_pipeline("latest-ubuntu"), + scan_docker_image_pipeline("main-ubuntu"), + grafana_com_nightly_pipeline(), ] def cron_job_pipeline(cronName, name, steps): return { - 'kind': 'pipeline', - 'type': 'docker', - 'platform': { - 'os': 'linux', - 'arch': 'amd64', + "kind": "pipeline", + "type": "docker", + "platform": { + "os": "linux", + "arch": "amd64", }, - 'name': name, - 'trigger': { - 'event': 'cron', - 'cron': cronName, + "name": name, + "trigger": { + "event": "cron", + "cron": cronName, }, - 'clone': { - 'retries': 3, + "clone": { + "retries": 3, }, - 'steps': steps, + "steps": steps, } -def scan_docker_image_pipeline(edition, tag): - if edition != 'oss': - edition='grafana-enterprise' - else: - edition='grafana' +def scan_docker_image_pipeline(tag): + """Generates a cronjob pipeline for nightly scans of grafana Docker images. + + Args: + tag: determines which image tag is scanned. - dockerImage='grafana/{}:{}'.format(edition, tag) + Returns: + Drone cronjob pipeline. + """ + docker_image = "grafana/grafana:{}".format(tag) return cron_job_pipeline( - cronName='nightly', - name='scan-' + dockerImage + '-image', - steps=[ - scan_docker_image_unkown_low_medium_vulnerabilities_step(dockerImage), - scan_docker_image_high_critical_vulnerabilities_step(dockerImage), - slack_job_failed_step('grafana-backend-ops', dockerImage), - ]) + cronName = "nightly", + name = "scan-" + docker_image + "-image", + steps = [ + scan_docker_image_unkown_low_medium_vulnerabilities_step(docker_image), + scan_docker_image_high_critical_vulnerabilities_step(docker_image), + slack_job_failed_step("grafana-backend-ops", docker_image), + ], + ) -def scan_docker_image_unkown_low_medium_vulnerabilities_step(dockerImage): +def scan_docker_image_unkown_low_medium_vulnerabilities_step(docker_image): return { - 'name': 'scan-unkown-low-medium-vulnerabilities', - 'image': aquasec_trivy_image, - 'commands': [ - 'trivy --exit-code 0 --severity UNKNOWN,LOW,MEDIUM ' + dockerImage, + "name": "scan-unkown-low-medium-vulnerabilities", + "image": aquasec_trivy_image, + "commands": [ + "trivy --exit-code 0 --severity UNKNOWN,LOW,MEDIUM " + docker_image, ], } -def scan_docker_image_high_critical_vulnerabilities_step(dockerImage): +def scan_docker_image_high_critical_vulnerabilities_step(docker_image): return { - 'name': 'scan-high-critical-vulnerabilities', - 'image': aquasec_trivy_image, - 'commands': [ - 'trivy --exit-code 1 --severity HIGH,CRITICAL ' + dockerImage, + "name": "scan-high-critical-vulnerabilities", + "image": aquasec_trivy_image, + "commands": [ + "trivy --exit-code 1 --severity HIGH,CRITICAL " + docker_image, ], } def slack_job_failed_step(channel, image): return { - 'name': 'slack-notify-failure', - 'image': 'plugins/slack', - 'settings': { - 'webhook': from_secret('slack_webhook_backend'), - 'channel': channel, - 'template': 'Nightly docker image scan job for ' + image + ' failed: {{build.link}}', + "name": "slack-notify-failure", + "image": "plugins/slack", + "settings": { + "webhook": from_secret("slack_webhook_backend"), + "channel": channel, + "template": "Nightly docker image scan job for " + + image + + " failed: {{build.link}}", + }, + "when": {"status": "failure"}, + } + +def post_to_grafana_com_step(): + return { + "name": "post-to-grafana-com", + "image": publish_image, + "environment": { + "GRAFANA_COM_API_KEY": from_secret("grafana_api_key"), + "GCP_KEY": from_secret("gcp_key"), }, - 'when': { - 'status': 'failure' - } + "depends_on": ["compile-build-cmd"], + "commands": ["./bin/build publish grafana-com --edition oss"], } + +def grafana_com_nightly_pipeline(): + return cron_job_pipeline( + cronName = "grafana-com-nightly", + name = "grafana-com-nightly", + steps = [ + compile_build_cmd(), + post_to_grafana_com_step(), + ], + ) diff --git a/scripts/drone/events/main.star b/scripts/drone/events/main.star index a718362e9580e..1d43da3f8c6f0 100644 --- a/scripts/drone/events/main.star +++ b/scripts/drone/events/main.star @@ -1,114 +1,119 @@ -load( - 'scripts/drone/utils/utils.star', - 'pipeline', - 'notify_pipeline', - 'failure_template', - 'drone_change_template', -) +""" +This module returns all the pipelines used in the event of pushes to the main branch. +""" load( - 'scripts/drone/pipelines/docs.star', - 'docs_pipelines', - 'trigger_docs_main', + "scripts/drone/utils/utils.star", + "drone_change_template", + "failure_template", + "notify_pipeline", ) - load( - 'scripts/drone/pipelines/test_frontend.star', - 'test_frontend', + "scripts/drone/pipelines/docs.star", + "docs_pipelines", + "trigger_docs_main", ) - load( - 'scripts/drone/pipelines/test_backend.star', - 'test_backend', + "scripts/drone/pipelines/test_frontend.star", + "test_frontend", ) - load( - 'scripts/drone/pipelines/integration_tests.star', - 'integration_tests', + "scripts/drone/pipelines/test_backend.star", + "test_backend", ) - load( - 'scripts/drone/pipelines/build.star', - 'build_e2e', + "scripts/drone/pipelines/integration_tests.star", + "integration_tests", ) - load( - 'scripts/drone/pipelines/windows.star', - 'windows', + "scripts/drone/pipelines/build.star", + "build_e2e", ) - load( - 'scripts/drone/pipelines/publish.star', - 'publish', + "scripts/drone/pipelines/windows.star", + "windows", + "windows_test_backend", ) - load( - 'scripts/drone/pipelines/trigger_downstream.star', - 'enterprise_downstream_pipeline', + "scripts/drone/pipelines/trigger_downstream.star", + "enterprise_downstream_pipeline", ) - load( - 'scripts/drone/pipelines/lint_backend.star', - 'lint_backend_pipeline', + "scripts/drone/pipelines/lint_backend.star", + "lint_backend_pipeline", ) - load( - 'scripts/drone/pipelines/lint_frontend.star', - 'lint_frontend_pipeline', + "scripts/drone/pipelines/lint_frontend.star", + "lint_frontend_pipeline", ) -load('scripts/drone/vault.star', 'from_secret') - - -ver_mode = 'main' +ver_mode = "main" trigger = { - 'event': ['push',], - 'branch': 'main', - 'paths': { - 'exclude': [ - '*.md', - 'docs/**', - 'latest.json', + "event": [ + "push", + ], + "branch": "main", + "paths": { + "exclude": [ + "*.md", + "docs/**", + "latest.json", ], }, } -def main_pipelines(edition): +def main_pipelines(): drone_change_trigger = { - 'event': ['push',], - 'branch': 'main', - 'repo': [ - 'grafana/grafana', + "event": [ + "push", + ], + "branch": "main", + "repo": [ + "grafana/grafana", ], - 'paths': { - 'include': [ - '.drone.yml', + "paths": { + "include": [ + ".drone.yml", ], - 'exclude': [ - 'exclude', + "exclude": [ + "exclude", ], }, } pipelines = [ - docs_pipelines(edition, ver_mode, trigger_docs_main()), + docs_pipelines(ver_mode, trigger_docs_main()), test_frontend(trigger, ver_mode), lint_frontend_pipeline(trigger, ver_mode), test_backend(trigger, ver_mode), lint_backend_pipeline(trigger, ver_mode), - build_e2e(trigger, ver_mode, edition), - integration_tests(trigger, ver_mode, edition), - windows(trigger, edition, ver_mode), - notify_pipeline( - name='notify-drone-changes', slack_channel='slack-webhooks-test', trigger=drone_change_trigger, - template=drone_change_template, secret='drone-changes-webhook', - ), - publish(trigger, ver_mode, edition), - enterprise_downstream_pipeline(edition, ver_mode), - notify_pipeline( - name='main-notify', slack_channel='grafana-ci-notifications', trigger=dict(trigger, status=['failure']), - depends_on=['main-test-frontend', 'main-test-backend', 'main-build-e2e-publish', 'main-integration-tests', 'main-windows', 'main-publish'], - template=failure_template, secret='slack_webhook' - )] + build_e2e(trigger, ver_mode), + integration_tests(trigger, prefix = ver_mode, ver_mode = ver_mode), + windows(trigger, edition = "oss", ver_mode = ver_mode), + windows_test_backend(trigger, "oss", ver_mode), + windows_test_backend(trigger, "enterprise", ver_mode), + notify_pipeline( + name = "notify-drone-changes", + slack_channel = "slack-webhooks-test", + trigger = drone_change_trigger, + template = drone_change_template, + secret = "drone-changes-webhook", + ), + enterprise_downstream_pipeline(), + notify_pipeline( + name = "main-notify", + slack_channel = "grafana-ci-notifications", + trigger = dict(trigger, status = ["failure"]), + depends_on = [ + "main-test-frontend", + "main-test-backend", + "main-build-e2e-publish", + "main-integration-tests", + "main-windows", + ], + template = failure_template, + secret = "slack_webhook", + ), + ] return pipelines diff --git a/scripts/drone/events/pr.star b/scripts/drone/events/pr.star index c193cba8a337d..9e1ba26a046ad 100644 --- a/scripts/drone/events/pr.star +++ b/scripts/drone/events/pr.star @@ -1,85 +1,166 @@ +""" +This module returns all pipelines used in the event of a pull request. +It also includes a function generating a PR trigger from a list of included and excluded paths. +""" + load( - 'scripts/drone/utils/utils.star', - 'pipeline', + "scripts/drone/pipelines/test_frontend.star", + "test_frontend", ) - load( - 'scripts/drone/pipelines/test_frontend.star', - 'test_frontend', + "scripts/drone/pipelines/test_backend.star", + "test_backend", ) - load( - 'scripts/drone/pipelines/test_backend.star', - 'test_backend', + "scripts/drone/pipelines/integration_tests.star", + "integration_tests", ) - load( - 'scripts/drone/pipelines/integration_tests.star', - 'integration_tests', + "scripts/drone/pipelines/windows.star", + "windows_test_backend", ) - load( - 'scripts/drone/pipelines/build.star', - 'build_e2e', + "scripts/drone/pipelines/build.star", + "build_e2e", ) - load( - 'scripts/drone/pipelines/verify_drone.star', - 'verify_drone', + "scripts/drone/pipelines/verify_drone.star", + "verify_drone", ) - load( - 'scripts/drone/pipelines/docs.star', - 'docs_pipelines', - 'trigger_docs_pr', + "scripts/drone/pipelines/verify_starlark.star", + "verify_starlark", ) - load( - 'scripts/drone/pipelines/shellcheck.star', - 'shellcheck_pipeline', + "scripts/drone/pipelines/docs.star", + "docs_pipelines", + "trigger_docs_pr", ) - load( - 'scripts/drone/pipelines/lint_backend.star', - 'lint_backend_pipeline', + "scripts/drone/pipelines/shellcheck.star", + "shellcheck_pipeline", +) +load( + "scripts/drone/pipelines/lint_backend.star", + "lint_backend_pipeline", ) - load( - 'scripts/drone/pipelines/lint_frontend.star', - 'lint_frontend_pipeline', + "scripts/drone/pipelines/lint_frontend.star", + "lint_frontend_pipeline", ) -ver_mode = 'pr' +ver_mode = "pr" trigger = { - 'event': [ - 'pull_request', + "event": [ + "pull_request", ], - 'paths': { - 'exclude': [ - '*.md', - 'docs/**', - 'latest.json', + "paths": { + "exclude": [ + "*.md", + "docs/**", + "latest.json", ], }, } - -def pr_pipelines(edition): +def pr_pipelines(): return [ - verify_drone(get_pr_trigger(include_paths=['scripts/drone/**', '.drone.yml', '.drone.star']), ver_mode), - test_frontend(get_pr_trigger(exclude_paths=['pkg/**', 'packaging/**', 'go.sum', 'go.mod']), ver_mode), - lint_frontend_pipeline(get_pr_trigger(exclude_paths=['pkg/**', 'packaging/**', 'go.sum', 'go.mod']), ver_mode), - test_backend(get_pr_trigger(include_paths=['pkg/**', 'packaging/**', '.drone.yml', 'conf/**', 'go.sum', 'go.mod', 'public/app/plugins/**/plugin.json', 'devenv/**']), ver_mode), - lint_backend_pipeline(get_pr_trigger(include_paths=['pkg/**', 'packaging/**', 'conf/**', 'go.sum', 'go.mod', 'public/app/plugins/**/plugin.json', 'devenv/**']), ver_mode), - build_e2e(trigger, ver_mode, edition), - integration_tests(get_pr_trigger(include_paths=['pkg/**', 'packaging/**', '.drone.yml', 'conf/**', 'go.sum', 'go.mod', 'public/app/plugins/**/plugin.json']), ver_mode, edition), - docs_pipelines(edition, ver_mode, trigger_docs_pr()), + verify_drone( + get_pr_trigger( + include_paths = ["scripts/drone/**", ".drone.yml", ".drone.star"], + ), + ver_mode, + ), + verify_starlark( + get_pr_trigger( + include_paths = ["scripts/drone/**", ".drone.star"], + ), + ver_mode, + ), + test_frontend( + get_pr_trigger( + exclude_paths = ["pkg/**", "packaging/**", "go.sum", "go.mod"], + ), + ver_mode, + ), + lint_frontend_pipeline( + get_pr_trigger( + exclude_paths = ["pkg/**", "packaging/**", "go.sum", "go.mod"], + ), + ver_mode, + ), + test_backend( + get_pr_trigger( + include_paths = [ + "pkg/**", + "packaging/**", + ".drone.yml", + "conf/**", + "go.sum", + "go.mod", + "public/app/plugins/**/plugin.json", + "devenv/**", + ], + ), + ver_mode, + ), + windows_test_backend( + get_pr_trigger( + exclude_paths = ["pkg/**", "packaging/**", "go.sum", "go.mod"], + ), + "oss", + ver_mode, + ), + lint_backend_pipeline( + get_pr_trigger( + include_paths = [ + "pkg/**", + "packaging/**", + "conf/**", + "go.sum", + "go.mod", + "public/app/plugins/**/plugin.json", + "devenv/**", + ".bingo/**", + ], + ), + ver_mode, + ), + build_e2e(trigger, ver_mode), + integration_tests( + get_pr_trigger( + include_paths = [ + "pkg/**", + "packaging/**", + ".drone.yml", + "conf/**", + "go.sum", + "go.mod", + "public/app/plugins/**/plugin.json", + ], + ), + prefix = ver_mode, + ), + docs_pipelines(ver_mode, trigger_docs_pr()), shellcheck_pipeline(), ] +def get_pr_trigger(include_paths = None, exclude_paths = None): + """Generates a trigger filter from the lists of included and excluded path patterns. + + This function is primarily intended to generate a trigger for code changes + as the patterns 'docs/**' and '*.md' are always excluded. -def get_pr_trigger(include_paths=None, exclude_paths=None): - paths_ex = ['docs/**', '*.md'] + Args: + include_paths: a list of path patterns using the same syntax as gitignore. + Changes affecting files matching these path patterns trigger the pipeline. + exclude_paths: a list of path patterns using the same syntax as gitignore. + Changes affecting files matching these path patterns do not trigger the pipeline. + + Returns: + Drone trigger. + """ + paths_ex = ["docs/**", "*.md"] paths_in = [] if include_paths: for path in include_paths: @@ -88,12 +169,11 @@ def get_pr_trigger(include_paths=None, exclude_paths=None): for path in exclude_paths: paths_ex.extend([path]) return { - 'event': [ - 'pull_request', + "event": [ + "pull_request", ], - 'paths': { - 'exclude': paths_ex, - 'include': paths_in, + "paths": { + "exclude": paths_ex, + "include": paths_in, }, } - diff --git a/scripts/drone/events/release.star b/scripts/drone/events/release.star index fe34c11872371..61a242475c21a 100644 --- a/scripts/drone/events/release.star +++ b/scripts/drone/events/release.star @@ -1,468 +1,794 @@ +""" +This module returns all the pipelines used in the event of a release along with supporting functions. +""" + load( - 'scripts/drone/steps/lib.star', - 'disable_tests', - 'clone_enterprise_step', - 'download_grabpl_step', - 'yarn_install_step', - 'wire_install_step', - 'init_enterprise_step', - 'lint_drone_step', - 'build_image', - 'identify_runner_step', - 'publish_image', - 'lint_backend_step', - 'lint_frontend_step', - 'test_backend_step', - 'test_backend_integration_step', - 'test_frontend_step', - 'build_backend_step', - 'build_frontend_step', - 'build_frontend_package_step', - 'build_plugins_step', - 'package_step', - 'grafana_server_step', - 'e2e_tests_step', - 'e2e_tests_artifacts', - 'build_storybook_step', - 'copy_packages_for_docker_step', - 'build_docker_images_step', - 'postgres_integration_tests_step', - 'mysql_integration_tests_step', - 'redis_integration_tests_step', - 'memcached_integration_tests_step', - 'get_windows_steps', - 'benchmark_ldap_step', - 'store_storybook_step', - 'upload_packages_step', - 'publish_packages_step', - 'publish_grafanacom_step', - 'upload_cdn_step', - 'verify_gen_cue_step', - 'publish_images_step', - 'publish_linux_packages_step', - 'trigger_oss', - 'artifacts_page_step', - 'fetch_images_step', - 'compile_build_cmd', + "scripts/drone/steps/lib.star", + "artifacts_page_step", + "build_backend_step", + "build_docker_images_step", + "build_frontend_package_step", + "build_frontend_step", + "build_image", + "build_plugins_step", + "build_storybook_step", + "clone_enterprise_step", + "compile_build_cmd", + "copy_packages_for_docker_step", + "download_grabpl_step", + "e2e_tests_artifacts", + "e2e_tests_step", + "fetch_images_step", + "get_windows_steps", + "grafana_server_step", + "identify_runner_step", + "init_enterprise_step", + "memcached_integration_tests_step", + "mysql_integration_tests_step", + "package_step", + "postgres_integration_tests_step", + "publish_grafanacom_step", + "publish_image", + "publish_images_step", + "publish_linux_packages_step", + "redis_integration_tests_step", + "store_storybook_step", + "trigger_oss", + "upload_cdn_step", + "upload_packages_step", + "verify_gen_cue_step", + "wire_install_step", + "yarn_install_step", ) - load( - 'scripts/drone/services/services.star', - 'integration_test_services', - 'integration_test_services_volumes', - 'ldap_service', + "scripts/drone/services/services.star", + "integration_test_services", + "integration_test_services_volumes", ) - load( - 'scripts/drone/utils/utils.star', - 'pipeline', - 'notify_pipeline', - 'failure_template', - 'drone_change_template', + "scripts/drone/utils/utils.star", + "pipeline", + "with_deps", ) - load( - 'scripts/drone/pipelines/test_frontend.star', - 'test_frontend', + "scripts/drone/pipelines/test_frontend.star", + "test_frontend", + "test_frontend_enterprise", ) - load( - 'scripts/drone/pipelines/test_backend.star', - 'test_backend', + "scripts/drone/pipelines/test_backend.star", + "test_backend", + "test_backend_enterprise", ) +load( + "scripts/drone/pipelines/windows.star", + "windows_test_backend", +) +load("scripts/drone/vault.star", "from_secret", "prerelease_bucket") -load('scripts/drone/vault.star', 'from_secret', 'github_token', 'pull_secret', 'drone_token', 'prerelease_bucket') +ver_mode = "release" +release_trigger = { + "event": { + "exclude": [ + "promote", + ], + }, + "ref": { + "include": [ + "refs/tags/v*", + ], + "exclude": [ + "refs/tags/*-cloud*", + ], + }, +} def store_npm_packages_step(): return { - 'name': 'store-npm-packages', - 'image': build_image, - 'depends_on': [ - 'build-frontend-packages', + "name": "store-npm-packages", + "image": build_image, + "depends_on": [ + "compile-build-cmd", + "build-frontend-packages", ], - 'environment': { - 'GCP_KEY': from_secret('gcp_key'), - 'PRERELEASE_BUCKET': from_secret(prerelease_bucket) + "environment": { + "GCP_KEY": from_secret("gcp_key"), + "PRERELEASE_BUCKET": from_secret(prerelease_bucket), }, - 'commands': [ - './bin/grabpl artifacts npm store --tag ${DRONE_TAG}' - ], + "commands": ["./bin/build artifacts npm store --tag ${DRONE_TAG}"], } def retrieve_npm_packages_step(): return { - 'name': 'retrieve-npm-packages', - 'image': publish_image, - 'depends_on': [ - 'yarn-install', + "name": "retrieve-npm-packages", + "image": publish_image, + "depends_on": [ + "compile-build-cmd", + "yarn-install", ], - 'failure': 'ignore', - 'environment': { - 'GCP_KEY': from_secret('gcp_key'), - 'PRERELEASE_BUCKET': from_secret(prerelease_bucket) + "failure": "ignore", + "environment": { + "GCP_KEY": from_secret("gcp_key"), + "PRERELEASE_BUCKET": from_secret(prerelease_bucket), }, - 'commands': [ - './bin/grabpl artifacts npm retrieve --tag v${TAG}' - ], + "commands": ["./bin/build artifacts npm retrieve --tag ${DRONE_TAG}"], } def release_npm_packages_step(): return { - 'name': 'release-npm-packages', - 'image': build_image, - 'depends_on': [ - 'retrieve-npm-packages', + "name": "release-npm-packages", + "image": build_image, + "depends_on": [ + "compile-build-cmd", + "retrieve-npm-packages", ], - 'failure': 'ignore', - 'environment': { - 'NPM_TOKEN': from_secret('npm_token'), + "failure": "ignore", + "environment": { + "NPM_TOKEN": from_secret("npm_token"), }, - 'commands': [ - './bin/grabpl artifacts npm release --tag v${TAG}' - ], + "commands": ["./bin/build artifacts npm release --tag ${DRONE_TAG}"], } -def get_oss_pipelines(trigger, ver_mode): - environment = {'EDITION': 'oss'} - edition = 'oss' - services = integration_test_services(edition=edition) +def oss_pipelines(ver_mode = ver_mode, trigger = release_trigger): + """Generates all pipelines used for Grafana OSS. + + Args: + ver_mode: controls which steps are included in the pipeline. + Defaults to 'release'. + trigger: controls which events can trigger the pipeline execution. + Defaults to tag events for tags with a 'v' prefix. + + Returns: + List of Drone pipelines. + """ + + environment = {"EDITION": "oss"} + + services = integration_test_services(edition = "oss") volumes = integration_test_services_volumes() - package_steps = [] - publish_steps = [] - should_publish = ver_mode == 'release' - should_upload = should_publish or ver_mode in ('release-branch',) + init_steps = [ identify_runner_step(), download_grabpl_step(), - verify_gen_cue_step(edition), + verify_gen_cue_step(), wire_install_step(), yarn_install_step(), compile_build_cmd(), ] build_steps = [ - build_backend_step(edition=edition, ver_mode=ver_mode), - build_frontend_step(edition=edition, ver_mode=ver_mode), - build_frontend_package_step(edition=edition, ver_mode=ver_mode), - build_plugins_step(edition=edition, ver_mode=ver_mode), + build_backend_step(edition = "oss", ver_mode = ver_mode), + build_frontend_step(edition = "oss", ver_mode = ver_mode), + build_frontend_package_step(edition = "oss", ver_mode = ver_mode), + build_plugins_step(edition = "oss", ver_mode = ver_mode), + package_step(edition = "oss", ver_mode = ver_mode), + copy_packages_for_docker_step(), + build_docker_images_step(edition = "oss", publish = True), + build_docker_images_step( + edition = "oss", + publish = True, + ubuntu = True, + ), + grafana_server_step(edition = "oss"), + e2e_tests_step("dashboards-suite", tries = 3), + e2e_tests_step("smoke-tests-suite", tries = 3), + e2e_tests_step("panels-suite", tries = 3), + e2e_tests_step("various-suite", tries = 3), + e2e_tests_artifacts(), + build_storybook_step(ver_mode = ver_mode), ] + publish_steps = [] + + if ver_mode in ( + "release", + "release-branch", + ): + publish_steps.extend( + [ + upload_cdn_step(edition = "oss", ver_mode = ver_mode, trigger = trigger_oss), + upload_packages_step( + edition = "oss", + ver_mode = ver_mode, + trigger = trigger_oss, + ), + ], + ) + + if ver_mode in ("release",): + publish_steps.extend( + [ + store_storybook_step(ver_mode = ver_mode), + store_npm_packages_step(), + ], + ) + integration_test_steps = [ - postgres_integration_tests_step(edition=edition, ver_mode=ver_mode), - mysql_integration_tests_step(edition=edition, ver_mode=ver_mode), + postgres_integration_tests_step(), + mysql_integration_tests_step(), ] - # Insert remaining steps - build_steps.extend([ - package_step(edition=edition, ver_mode=ver_mode), - copy_packages_for_docker_step(), - build_docker_images_step(edition=edition, ver_mode=ver_mode, publish=True), - build_docker_images_step(edition=edition, ver_mode=ver_mode, ubuntu=True, publish=True), - grafana_server_step(edition=edition), - ]) - - if not disable_tests: - build_steps.extend([ - e2e_tests_step('dashboards-suite', edition=edition, tries=3), - e2e_tests_step('smoke-tests-suite', edition=edition, tries=3), - e2e_tests_step('panels-suite', edition=edition, tries=3), - e2e_tests_step('various-suite', edition=edition, tries=3), - e2e_tests_artifacts(edition=edition), - ]) - - build_storybook = build_storybook_step(edition=edition, ver_mode=ver_mode) - if build_storybook: - build_steps.append(build_storybook) - - if should_upload: - publish_steps.append(upload_cdn_step(edition=edition, ver_mode=ver_mode, trigger=trigger_oss)) - publish_steps.append(upload_packages_step(edition=edition, ver_mode=ver_mode, trigger=trigger_oss)) - if should_publish: - publish_step = store_storybook_step(edition=edition, ver_mode=ver_mode) - store_npm_step = store_npm_packages_step() - if publish_step: - publish_steps.append(publish_step) - if store_npm_step: - publish_steps.append(store_npm_step) - windows_package_steps = get_windows_steps(edition=edition, ver_mode=ver_mode) + # We don't need to run integration tests at release time since they have + # been run multiple times before: + if ver_mode in ("release"): + integration_test_steps = [] + volumes = [] windows_pipeline = pipeline( - name='{}-oss-windows'.format(ver_mode), edition=edition, trigger=trigger, - steps=[identify_runner_step('windows')] + windows_package_steps, - platform='windows', depends_on=[ - 'oss-build{}-publish-{}'.format(get_e2e_suffix(), ver_mode), - ], environment=environment, + name = "{}-oss-windows".format(ver_mode), + edition = "oss", + trigger = trigger, + steps = get_windows_steps(edition = "oss", ver_mode = ver_mode), + platform = "windows", + depends_on = [ + "{}-oss-build-e2e-publish".format(ver_mode), + "{}-oss-test-frontend".format(ver_mode), + "{}-oss-test-backend-windows".format(ver_mode), + ], + environment = environment, ) + pipelines = [ pipeline( - name='{}-oss-build{}-publish'.format(ver_mode, get_e2e_suffix()), edition=edition, trigger=trigger, services=[], - steps=init_steps + build_steps + package_steps + publish_steps, - environment=environment, volumes=volumes, + name = "{}-oss-build-e2e-publish".format(ver_mode), + edition = "oss", + trigger = trigger, + services = [], + steps = init_steps + build_steps + publish_steps, + environment = environment, + volumes = volumes, ), + test_frontend(trigger, ver_mode), + test_backend(trigger, ver_mode), + windows_test_backend(trigger, "oss", ver_mode), + windows_test_backend(trigger, "enterprise", ver_mode), ] - if not disable_tests: - pipelines.extend([ - test_frontend(trigger, ver_mode), - test_backend(trigger, ver_mode), - pipeline( - name='{}-oss-integration-tests'.format(ver_mode), edition=edition, trigger=trigger, services=services, - steps=[download_grabpl_step(), identify_runner_step(), verify_gen_cue_step(edition), wire_install_step(), ] + integration_test_steps, - environment=environment, volumes=volumes, - ) - ]) - deps = { - 'depends_on': [ - '{}-oss-build{}-publish'.format(ver_mode, get_e2e_suffix()), - '{}-oss-test-frontend'.format(ver_mode), - '{}-oss-test-backend'.format(ver_mode), - '{}-oss-integration-tests'.format(ver_mode) - ] - } - windows_pipeline.update(deps) - - pipelines.extend([windows_pipeline]) + + if ver_mode not in ("release"): + pipelines.append(pipeline( + name = "{}-oss-integration-tests".format(ver_mode), + edition = "oss", + trigger = trigger, + services = services, + steps = [ + download_grabpl_step(), + identify_runner_step(), + verify_gen_cue_step(), + wire_install_step(), + ] + + integration_test_steps, + environment = environment, + volumes = volumes, + )) + + pipelines.append(windows_pipeline) + return pipelines -def get_enterprise_pipelines(trigger, ver_mode): - environment = {'EDITION': 'enterprise'} - edition = 'enterprise' - services = integration_test_services(edition=edition) +def enterprise_pipelines(ver_mode = ver_mode, trigger = release_trigger): + """Generates all pipelines used for Grafana Enterprise. + + Args: + ver_mode: controls which steps are included in the pipeline. + Defaults to 'release'. + trigger: controls which events can trigger the pipeline execution. + Defaults to tag events for tags with a 'v' prefix. + + Returns: + List of Drone pipelines. + """ + if ver_mode == "release": + source = "${DRONE_TAG}" + elif ver_mode == "release-branch": + source = "${DRONE_BRANCH}" + else: + source = "${DRONE_COMMIT}" + + environment = {"EDITION": "enterprise"} + + services = integration_test_services(edition = "enterprise") volumes = integration_test_services_volumes() - package_steps = [] - publish_steps = [] - should_publish = ver_mode == 'release' - should_upload = should_publish or ver_mode in ('release-branch',) - include_enterprise = edition == 'enterprise' - edition2 = 'enterprise2' + init_steps = [ download_grabpl_step(), identify_runner_step(), - clone_enterprise_step(ver_mode), + clone_enterprise_step(source = source), init_enterprise_step(ver_mode), - compile_build_cmd(edition), - ] + compile_build_cmd("enterprise"), + ] + with_deps( + [ + wire_install_step(), + yarn_install_step(), + verify_gen_cue_step(), + ], + [ + "init-enterprise", + ], + ) build_steps = [ - build_backend_step(edition=edition, ver_mode=ver_mode), - build_frontend_step(edition=edition, ver_mode=ver_mode), - build_frontend_package_step(edition=edition, ver_mode=ver_mode), - build_plugins_step(edition=edition, ver_mode=ver_mode), + build_backend_step(edition = "enterprise", ver_mode = ver_mode), + build_frontend_step(edition = "enterprise", ver_mode = ver_mode), + build_frontend_package_step(edition = "enterprise", ver_mode = ver_mode), + build_plugins_step(edition = "enterprise", ver_mode = ver_mode), + package_step( + edition = "enterprise", + ver_mode = ver_mode, + ), + copy_packages_for_docker_step(), + build_docker_images_step(edition = "enterprise", publish = True), + build_docker_images_step( + edition = "enterprise", + publish = True, + ubuntu = True, + ), + grafana_server_step(edition = "enterprise"), + e2e_tests_step("dashboards-suite", tries = 3), + e2e_tests_step("smoke-tests-suite", tries = 3), + e2e_tests_step("panels-suite", tries = 3), + e2e_tests_step("various-suite", tries = 3), + e2e_tests_artifacts(), ] + publish_steps = [] + + if ver_mode in ( + "release", + "release-branch", + ): + upload_packages_enterprise = upload_packages_step( + edition = "enterprise", + ver_mode = ver_mode, + trigger = trigger_oss, + ) + upload_packages_enterprise["depends_on"] = ["package"] + + publish_steps.extend( + [ + upload_cdn_step( + edition = "enterprise", + ver_mode = ver_mode, + trigger = trigger_oss, + ), + upload_packages_enterprise, + ], + ) + integration_test_steps = [ - postgres_integration_tests_step(edition=edition, ver_mode=ver_mode), - mysql_integration_tests_step(edition=edition, ver_mode=ver_mode), + postgres_integration_tests_step(), + mysql_integration_tests_step(), + redis_integration_tests_step(), + memcached_integration_tests_step(), ] - if include_enterprise: - build_steps.extend([ - build_backend_step(edition=edition2, ver_mode=ver_mode, variants=['linux-amd64']), - ]) + # We don't need to run integration tests at release time since they have + # been run multiple times before: + if ver_mode in ("release"): + integration_test_steps = [] + volumes = [] - # Insert remaining steps - build_steps.extend([ - package_step(edition=edition, ver_mode=ver_mode, include_enterprise2=include_enterprise), - copy_packages_for_docker_step(), - build_docker_images_step(edition=edition, ver_mode=ver_mode, publish=True), - build_docker_images_step(edition=edition, ver_mode=ver_mode, ubuntu=True, publish=True), - grafana_server_step(edition=edition), - ]) - - if not disable_tests: - build_steps.extend([ - e2e_tests_step('dashboards-suite', edition=edition, tries=3), - e2e_tests_step('smoke-tests-suite', edition=edition, tries=3), - e2e_tests_step('panels-suite', edition=edition, tries=3), - e2e_tests_step('various-suite', edition=edition, tries=3), - e2e_tests_artifacts(edition=edition), - ]) - - build_storybook = build_storybook_step(edition=edition, ver_mode=ver_mode) - if build_storybook: - build_steps.append(build_storybook) - - if should_upload: - publish_steps.extend([ - upload_cdn_step(edition=edition, ver_mode=ver_mode, trigger=trigger_oss), - upload_packages_step(edition=edition, ver_mode=ver_mode, trigger=trigger_oss), - package_step(edition=edition2, ver_mode=ver_mode, include_enterprise2=include_enterprise, variants=['linux-amd64']), - upload_cdn_step(edition=edition2, ver_mode=ver_mode), - ]) - if should_publish: - publish_step = store_storybook_step(edition=edition, ver_mode=ver_mode) - store_npm_step = store_npm_packages_step() - if publish_step: - publish_steps.append(publish_step) - if store_npm_step: - publish_steps.append(store_npm_step) - windows_package_steps = get_windows_steps(edition=edition, ver_mode=ver_mode) - - if should_upload: - step = upload_packages_step(edition=edition2, ver_mode=ver_mode) - if step: - publish_steps.append(step) - - deps_on_clone_enterprise_step = { - 'depends_on': [ - 'init-enterprise', - ] + windows_pipeline = pipeline( + name = "{}-enterprise-windows".format(ver_mode), + edition = "enterprise", + trigger = trigger, + steps = get_windows_steps(edition = "enterprise", ver_mode = ver_mode), + platform = "windows", + depends_on = [ + "{}-enterprise-build-e2e-publish".format(ver_mode), + "{}-enterprise-test-frontend".format(ver_mode), + "{}-enterprise-test-backend".format(ver_mode), + ], + environment = environment, + ) + + pipelines = [ + pipeline( + name = "{}-enterprise-build-e2e-publish".format(ver_mode), + edition = "enterprise", + trigger = trigger, + services = [], + steps = init_steps + build_steps + publish_steps, + environment = environment, + volumes = volumes, + ), + test_frontend_enterprise(trigger, ver_mode, source = source), + test_backend_enterprise(trigger, ver_mode, source = source), + ] + + if ver_mode not in ("release"): + pipelines.append(pipeline( + name = "{}-enterprise-integration-tests".format(ver_mode), + edition = "enterprise", + trigger = trigger, + services = services, + steps = [ + download_grabpl_step(), + identify_runner_step(), + clone_enterprise_step(source = source), + init_enterprise_step(ver_mode), + ] + + with_deps( + [ + verify_gen_cue_step(), + ], + [ + "init-enterprise", + ], + ) + + [ + wire_install_step(), + ] + + integration_test_steps, + environment = environment, + volumes = volumes, + )) + + pipelines.append(windows_pipeline) + + return pipelines + +def enterprise2_pipelines(prefix = "", ver_mode = ver_mode, trigger = release_trigger): + """Generate the next generation of pipelines for Grafana Enterprise. + + Args: + prefix: a prefix for the pipeline name used to differentiate multiple instances of + the same pipeline. + Defaults to ''. + ver_mode: controls which steps are included in the pipeline. + Defaults to 'release'. + trigger: controls which events can trigger the pipeline execution. + Defaults to tag events for tags with a 'v' prefix. + + Returns: + List of Drone pipelines. + """ + if ver_mode == "release": + source = "${DRONE_TAG}" + if prefix == "custom-": + source = "${DRONE_TARGET_BRANCH}" + elif ver_mode == "release-branch": + source = "${DRONE_BRANCH}" + else: + source = "${DRONE_COMMIT}" + + environment = { + "EDITION": "enterprise2", } - for step in [wire_install_step(), yarn_install_step(edition), verify_gen_cue_step(edition)]: - step.update(deps_on_clone_enterprise_step) - init_steps.extend([step]) + volumes = integration_test_services_volumes() - windows_pipeline = pipeline( - name='{}-enterprise-windows'.format(ver_mode), edition=edition, trigger=trigger, - steps=[identify_runner_step('windows')] + windows_package_steps, - platform='windows', depends_on=[ - 'enterprise-build{}-publish-{}'.format(get_e2e_suffix(), ver_mode), - ], environment=environment, + init_steps = [ + download_grabpl_step(), + identify_runner_step(), + clone_enterprise_step(source = source), + init_enterprise_step(ver_mode), + compile_build_cmd("enterprise"), + ] + with_deps( + [ + wire_install_step(), + yarn_install_step(), + verify_gen_cue_step(), + ], + [ + "init-enterprise", + ], ) + + build_steps = [ + build_frontend_step(edition = "enterprise", ver_mode = ver_mode), + build_frontend_package_step(edition = "enterprise", ver_mode = ver_mode), + build_plugins_step(edition = "enterprise", ver_mode = ver_mode), + build_backend_step( + edition = "enterprise2", + ver_mode = ver_mode, + variants = ["linux-amd64"], + ), + ] + + fetch_images = fetch_images_step("enterprise2") + fetch_images.update( + {"depends_on": ["build-docker-images", "build-docker-images-ubuntu"]}, + ) + + upload_cdn = upload_cdn_step(edition = "enterprise2", ver_mode = ver_mode) + upload_cdn["environment"].update( + {"ENTERPRISE2_CDN_PATH": from_secret("enterprise2-cdn-path")}, + ) + + build_steps.extend( + [ + package_step( + edition = "enterprise2", + ver_mode = ver_mode, + ), + upload_cdn, + copy_packages_for_docker_step(edition = "enterprise2"), + build_docker_images_step( + edition = "enterprise2", + publish = True, + ), + build_docker_images_step( + edition = "enterprise2", + publish = True, + ubuntu = True, + ), + fetch_images, + publish_images_step( + "enterprise2", + "release", + mode = "enterprise2", + docker_repo = "${{DOCKER_ENTERPRISE2_REPO}}", + ), + ], + ) + + publish_steps = [] + + if ver_mode in ( + "release", + "release-branch", + ): + step = upload_packages_step(edition = "enterprise2", ver_mode = ver_mode) + step["depends_on"] = ["package-enterprise2"] + + publish_steps.append(step) + pipelines = [ pipeline( - name='{}-enterprise-build{}-publish'.format(ver_mode, get_e2e_suffix()), edition=edition, trigger=trigger, services=[], - steps=init_steps + build_steps + package_steps + publish_steps, environment=environment, - volumes=volumes, + name = "{}{}-enterprise2-build-e2e-publish".format(prefix, ver_mode), + edition = "enterprise", + trigger = trigger, + services = [], + steps = init_steps + build_steps + publish_steps, + volumes = volumes, + environment = environment, ), ] - if not disable_tests: - pipelines.extend([ - test_frontend(trigger, ver_mode, edition), - test_backend(trigger, ver_mode, edition), - test_backend(trigger, ver_mode, edition2), - pipeline( - name='{}-enterprise-integration-tests'.format(ver_mode), edition=edition, trigger=trigger, services=services, - steps=[download_grabpl_step(), identify_runner_step(), clone_enterprise_step(ver_mode), init_enterprise_step(ver_mode), verify_gen_cue_step(edition), wire_install_step()] + integration_test_steps + [redis_integration_tests_step(), memcached_integration_tests_step()], - environment=environment, volumes=volumes, - ), - ]) - deps = { - 'depends_on': [ - '{}-enterprise-build{}-publish'.format(ver_mode, get_e2e_suffix()), - '{}-enterprise-test-frontend'.format(ver_mode), - '{}-enterprise-test-backend'.format(ver_mode), - '{}-enterprise-integration-tests'.format(ver_mode) - ] - } - windows_pipeline.update(deps) - - pipelines.extend([windows_pipeline]) return pipelines def publish_artifacts_step(mode): - security = '' - if mode == 'security': - security = '--security ' + security = "" + if mode == "security": + security = "--security " + return { + "name": "publish-artifacts", + "image": publish_image, + "environment": { + "GCP_KEY": from_secret("gcp_key"), + "PRERELEASE_BUCKET": from_secret("prerelease_bucket"), + "ENTERPRISE2_SECURITY_PREFIX": from_secret("enterprise2_security_prefix"), + "SECURITY_DEST_BUCKET": from_secret("security_dest_bucket"), + }, + "commands": [ + "./bin/build artifacts packages {}--tag $${{DRONE_TAG}} --src-bucket $${{PRERELEASE_BUCKET}}".format( + security, + ), + ], + "depends_on": ["compile-build-cmd"], + } + +def publish_static_assets_step(): + return { + "name": "publish-static-assets", + "image": publish_image, + "environment": { + "GCP_KEY": from_secret("gcp_key"), + "PRERELEASE_BUCKET": from_secret("prerelease_bucket"), + "STATIC_ASSET_EDITIONS": from_secret("static_asset_editions"), + }, + "commands": [ + "./bin/build artifacts static-assets --tag ${DRONE_TAG}", + ], + "depends_on": ["compile-build-cmd"], + } + +def publish_storybook_step(): return { - 'name': 'publish-artifacts', - 'image': publish_image, - 'environment': { - 'GCP_KEY': from_secret('gcp_key'), - 'PRERELEASE_BUCKET': from_secret('prerelease_bucket'), + "name": "publish-storybook", + "image": publish_image, + "environment": { + "GCP_KEY": from_secret("gcp_key"), + "PRERELEASE_BUCKET": from_secret("prerelease_bucket"), }, - 'commands': ['./bin/grabpl artifacts publish {}--tag ${{TAG}} --src-bucket $${{PRERELEASE_BUCKET}}'.format(security)], - 'depends_on': ['grabpl'], + "commands": [ + "./bin/build artifacts storybook --tag ${DRONE_TAG}", + ], + "depends_on": ["compile-build-cmd"], } def publish_artifacts_pipelines(mode): + """Published artifacts after they've been stored and tested in prerelease buckets. + + Args: + mode: public or security. + Defaults to ''. + + Returns: + List of Drone pipelines. + """ trigger = { - 'event': ['promote'], - 'target': [mode], + "event": ["promote"], + "target": [mode], } steps = [ - download_grabpl_step(), + compile_build_cmd(), publish_artifacts_step(mode), + publish_static_assets_step(), ] + if mode != "security": + steps.extend([publish_storybook_step()]) - return [pipeline( - name='publish-artifacts-{}'.format(mode), trigger=trigger, steps=steps, edition="all" - )] + return [ + pipeline( + name = "publish-artifacts-{}".format(mode), + trigger = trigger, + steps = steps, + edition = "all", + environment = {"EDITION": "all"}, + ), + ] def publish_packages_pipeline(): + """Generates pipelines used for publishing packages for both OSS and enterprise. + + Returns: + List of Drone pipelines. One for each of OSS and enterprise packages. + """ + trigger = { - 'event': ['promote'], - 'target': ['public'], + "event": ["promote"], + "target": ["public"], } oss_steps = [ - download_grabpl_step(), compile_build_cmd(), - publish_packages_step(edition='oss', ver_mode='release'), - publish_grafanacom_step(edition='oss', ver_mode='release'), - publish_linux_packages_step(edition='oss', package_manager='deb'), - publish_linux_packages_step(edition='oss', package_manager='rpm'), + publish_linux_packages_step(edition = "oss", package_manager = "deb"), + publish_linux_packages_step(edition = "oss", package_manager = "rpm"), + publish_grafanacom_step(edition = "oss", ver_mode = "release"), ] enterprise_steps = [ - download_grabpl_step(), compile_build_cmd(), - publish_packages_step(edition='enterprise', ver_mode='release'), - publish_grafanacom_step(edition='enterprise', ver_mode='release'), - publish_linux_packages_step(edition='enterprise', package_manager='deb'), - publish_linux_packages_step(edition='enterprise', package_manager='rpm'), + publish_linux_packages_step(edition = "enterprise", package_manager = "deb"), + publish_linux_packages_step(edition = "enterprise", package_manager = "rpm"), + publish_grafanacom_step(edition = "enterprise", ver_mode = "release"), ] deps = [ - 'publish-artifacts-public', - 'publish-docker-oss-public', - 'publish-docker-enterprise-public' + "publish-artifacts-public", + "publish-docker-oss-public", + "publish-docker-enterprise-public", ] - return [pipeline( - name='publish-packages-oss', trigger=trigger, steps=oss_steps, edition="all", depends_on=deps - ), pipeline( - name='publish-packages-enterprise', trigger=trigger, steps=enterprise_steps, edition="all", depends_on=deps - )] + return [ + pipeline( + name = "publish-packages-oss", + trigger = trigger, + steps = oss_steps, + edition = "all", + depends_on = deps, + environment = {"EDITION": "oss"}, + ), + pipeline( + name = "publish-packages-enterprise", + trigger = trigger, + steps = enterprise_steps, + edition = "all", + depends_on = deps, + environment = {"EDITION": "enterprise"}, + ), + ] -def publish_npm_pipelines(mode): +def publish_npm_pipelines(): trigger = { - 'event': ['promote'], - 'target': [mode], + "event": ["promote"], + "target": ["public"], } steps = [ - download_grabpl_step(), + compile_build_cmd(), yarn_install_step(), retrieve_npm_packages_step(), - release_npm_packages_step() + release_npm_packages_step(), ] - return [pipeline( - name='publish-npm-packages-{}'.format(mode), trigger=trigger, steps = steps, edition="all" - )] + return [ + pipeline( + name = "publish-npm-packages-public", + trigger = trigger, + steps = steps, + edition = "all", + environment = {"EDITION": "all"}, + ), + ] def artifacts_page_pipeline(): trigger = { - 'event': ['promote'], - 'target': 'security', + "event": ["promote"], + "target": "security", } - return [pipeline(name='publish-artifacts-page', trigger=trigger, steps = [download_grabpl_step(), artifacts_page_step()], edition="all")] - -def release_pipelines(ver_mode='release', trigger=None): - # 'enterprise' edition services contain both OSS and enterprise services - if not trigger: - trigger = { - 'event': { - 'exclude': [ - 'promote' - ] - }, - 'ref': ['refs/tags/v*',], - 'repo': { - 'exclude': ['grafana/grafana'], - }, - } - - # The release pipelines include also enterprise ones, so both editions are built for a release. - # We could also solve this by triggering a downstream build for the enterprise repo, but by including enterprise - # in OSS release builds, we simplify the UX for the release engineer. - oss_pipelines = get_oss_pipelines(ver_mode=ver_mode, trigger=trigger) - enterprise_pipelines = get_enterprise_pipelines(ver_mode=ver_mode, trigger=trigger) - - pipelines = oss_pipelines + enterprise_pipelines + return [ + pipeline( + name = "publish-artifacts-page", + trigger = trigger, + steps = [ + download_grabpl_step(), + clone_enterprise_step(source = "${DRONE_TAG}"), + init_enterprise_step("release"), + compile_build_cmd("enterprise"), + artifacts_page_step(), + ], + edition = "enterprise", + environment = {"EDITION": "enterprise"}, + ), + ] - return pipelines +def integration_test_pipelines(): + """ + Trigger integration tests on release builds -def get_e2e_suffix(): - if not disable_tests: - return '-e2e' - return '' + These pipelines should be triggered when we have a release that does a lot of + cherry-picking and we still want to have all the integration tests run on that + particular build. + + Returns: + List of Drone pipelines (one for enterprise and one for oss integration tests) + """ + trigger = { + "event": ["promote"], + "target": "integration-tests", + } + pipelines = [] + volumes = integration_test_services_volumes() + oss_integration_test_steps = [ + postgres_integration_tests_step(), + mysql_integration_tests_step(), + ] + enterprise_integration_test_steps = oss_integration_test_steps + [ + redis_integration_tests_step(), + memcached_integration_tests_step(), + ] + source = "${DRONE_TAG}" + + pipelines.append(pipeline( + name = "integration-tests-oss", + edition = "oss", + trigger = trigger, + services = integration_test_services(edition = "oss"), + steps = [ + download_grabpl_step(), + identify_runner_step(), + verify_gen_cue_step(), + wire_install_step(), + ] + + oss_integration_test_steps, + environment = {"EDITION": "oss"}, + volumes = volumes, + )) + + pipelines.append(pipeline( + name = "integration-tests-enterprise", + edition = "enterprise", + trigger = trigger, + services = integration_test_services(edition = "enterprise"), + steps = [ + download_grabpl_step(), + identify_runner_step(), + clone_enterprise_step(source = source), + init_enterprise_step(ver_mode), + ] + + with_deps( + [ + verify_gen_cue_step(), + ], + [ + "init-enterprise", + ], + ) + + [ + wire_install_step(), + ] + + enterprise_integration_test_steps, + environment = {"EDITION": "enterprise"}, + volumes = volumes, + )) + + return pipelines diff --git a/scripts/drone/pipelines/aws_marketplace.star b/scripts/drone/pipelines/aws_marketplace.star new file mode 100644 index 0000000000000..a9ca6c57ab491 --- /dev/null +++ b/scripts/drone/pipelines/aws_marketplace.star @@ -0,0 +1,42 @@ +""" +This module contains steps and pipelines publishing to AWS Marketplace. +""" + +load( + "scripts/drone/steps/lib.star", + "compile_build_cmd", + "publish_image", +) +load("scripts/drone/vault.star", "from_secret") +load( + "scripts/drone/utils/utils.star", + "pipeline", +) + +def publish_aws_marketplace_step(): + return { + "name": "publish-aws-marketplace", + "image": publish_image, + "commands": ["./bin/build publish aws --image grafana/grafana-enterprise --repo grafana-labs/grafanaenterprise --product 422b46fb-bea6-4f27-8bcc-832117bd627e"], + "depends_on": ["compile-build-cmd"], + "environment": { + "AWS_REGION": from_secret("aws_region"), + "AWS_ACCESS_KEY_ID": from_secret("aws_access_key_id"), + "AWS_SECRET_ACCESS_KEY": from_secret("aws_secret_access_key"), + }, + "volumes": [{"name": "docker", "path": "/var/run/docker.sock"}], + } + +def publish_aws_marketplace_pipeline(mode): + trigger = { + "event": ["promote"], + "target": [mode], + } + return [pipeline( + name = "publish-aws-marketplace-{}".format(mode), + trigger = trigger, + steps = [compile_build_cmd(), publish_aws_marketplace_step()], + edition = "", + depends_on = ["publish-docker-enterprise-public"], + environment = {"EDITION": "enterprise2"}, + )] diff --git a/scripts/drone/pipelines/build.star b/scripts/drone/pipelines/build.star index 3d7b46a50156a..8b37a176a2e9e 100644 --- a/scripts/drone/pipelines/build.star +++ b/scripts/drone/pipelines/build.star @@ -1,107 +1,160 @@ +"""This module contains the comprehensive build pipeline.""" + load( - 'scripts/drone/steps/lib.star', - 'download_grabpl_step', - 'build_image', - 'identify_runner_step', - 'wire_install_step', - 'yarn_install_step', - 'build_backend_step', - 'build_frontend_step', - 'build_frontend_package_step', - 'build_plugins_step', - 'package_step', - 'grafana_server_step', - 'e2e_tests_step', - 'e2e_tests_artifacts', - 'build_storybook_step', - 'copy_packages_for_docker_step', - 'build_docker_images_step', - 'publish_images_step', - 'postgres_integration_tests_step', - 'mysql_integration_tests_step', - 'redis_integration_tests_step', - 'memcached_integration_tests_step', - 'get_windows_steps', - 'benchmark_ldap_step', - 'enterprise_downstream_step', - 'frontend_metrics_step', - 'store_storybook_step', - 'release_canary_npm_packages_step', - 'upload_packages_step', - 'upload_cdn_step', - 'verify_gen_cue_step', - 'test_a11y_frontend_step', - 'trigger_oss', - 'betterer_frontend_step', - 'trigger_test_release', - 'compile_build_cmd', + "scripts/drone/steps/lib.star", + "build_backend_step", + "build_docker_images_step", + "build_frontend_package_step", + "build_frontend_step", + "build_plugins_step", + "build_storybook_step", + "cloud_plugins_e2e_tests_step", + "compile_build_cmd", + "copy_packages_for_docker_step", + "download_grabpl_step", + "e2e_tests_artifacts", + "e2e_tests_step", + "enterprise_downstream_step", + "frontend_metrics_step", + "grafana_server_step", + "identify_runner_step", + "package_step", + "publish_images_step", + "release_canary_npm_packages_step", + "store_storybook_step", + "test_a11y_frontend_step", + "trigger_oss", + "trigger_test_release", + "upload_cdn_step", + "upload_packages_step", + "verify_gen_cue_step", + "wire_install_step", + "yarn_install_step", ) - load( - 'scripts/drone/utils/utils.star', - 'pipeline', + "scripts/drone/utils/utils.star", + "pipeline", ) -def build_e2e(trigger, ver_mode, edition): - variants = ['linux-amd64', 'linux-amd64-musl', 'darwin-amd64', 'windows-amd64',] +# @unused +def build_e2e(trigger, ver_mode): + """Perform e2e building, testing, and publishing. + + Args: + trigger: controls which events can trigger the pipeline execution. + ver_mode: used in the naming of the pipeline. + + Returns: + Drone pipeline. + """ + + edition = "oss" + environment = {"EDITION": edition} init_steps = [ identify_runner_step(), download_grabpl_step(), compile_build_cmd(), - verify_gen_cue_step(edition="oss"), + verify_gen_cue_step(), wire_install_step(), yarn_install_step(), ] + build_steps = [] - if ver_mode == 'main': - build_steps.extend([trigger_test_release()]) - if ver_mode == 'pr': - build_steps.extend([enterprise_downstream_step(edition=edition, ver_mode=ver_mode)]) - build_steps.extend([ - build_backend_step(edition=edition, ver_mode=ver_mode), - build_frontend_step(edition=edition, ver_mode=ver_mode), - build_frontend_package_step(edition=edition, ver_mode=ver_mode), - build_plugins_step(edition=edition, ver_mode=ver_mode), - ]) - if ver_mode == 'main': - build_steps.extend([package_step(edition=edition, ver_mode=ver_mode)]) - elif ver_mode == 'pr': - build_steps.extend([package_step(edition=edition, ver_mode=ver_mode, variants=variants)]) - build_steps.extend([ - grafana_server_step(edition=edition), - e2e_tests_step('dashboards-suite', edition=edition), - e2e_tests_step('smoke-tests-suite', edition=edition), - e2e_tests_step('panels-suite', edition=edition), - e2e_tests_step('various-suite', edition=edition), - e2e_tests_artifacts(edition=edition), - build_storybook_step(edition=edition, ver_mode=ver_mode), - copy_packages_for_docker_step(), - test_a11y_frontend_step(ver_mode=ver_mode, edition=edition), - ]) - if ver_mode == 'main': - build_steps.extend([ - store_storybook_step(edition=edition, ver_mode=ver_mode, trigger=trigger_oss), - frontend_metrics_step(edition=edition, trigger=trigger_oss) - ]) + if ver_mode == "pr": + build_steps.extend( + [ + trigger_test_release(), + enterprise_downstream_step(ver_mode = ver_mode), + ], + ) + + build_steps.extend( + [ + build_backend_step(edition = edition, ver_mode = ver_mode), + build_frontend_step(edition = edition, ver_mode = ver_mode), + build_frontend_package_step(edition = edition, ver_mode = ver_mode), + build_plugins_step(edition = edition, ver_mode = ver_mode), + package_step(edition = edition, ver_mode = ver_mode), + grafana_server_step(edition = edition), + e2e_tests_step("dashboards-suite"), + e2e_tests_step("smoke-tests-suite"), + e2e_tests_step("panels-suite"), + e2e_tests_step("various-suite"), + cloud_plugins_e2e_tests_step( + "cloud-plugins-suite", + cloud = "azure", + trigger = trigger_oss, + ), + e2e_tests_artifacts(), + build_storybook_step(ver_mode = ver_mode), + copy_packages_for_docker_step(), + test_a11y_frontend_step(ver_mode = ver_mode), + ], + ) - if ver_mode == 'main': - build_steps.extend([ - build_docker_images_step(edition=edition, ver_mode=ver_mode, publish=False), - build_docker_images_step(edition=edition, ver_mode=ver_mode, ubuntu=True, publish=False), - publish_images_step(edition=edition, ver_mode=ver_mode, mode='', docker_repo='grafana/grafana', trigger=trigger_oss), - publish_images_step(edition=edition, ver_mode=ver_mode, mode='', docker_repo='grafana/grafana-oss', trigger=trigger_oss), - release_canary_npm_packages_step(edition, trigger=trigger_oss), - upload_packages_step(edition=edition, ver_mode=ver_mode, trigger=trigger_oss), - upload_cdn_step(edition=edition, ver_mode=ver_mode, trigger=trigger_oss) - ]) - elif ver_mode == 'pr': - build_steps.extend([build_docker_images_step(edition=edition, ver_mode=ver_mode, archs=['amd64', ])]) + if ver_mode == "main": + build_steps.extend( + [ + store_storybook_step(trigger = trigger_oss, ver_mode = ver_mode), + frontend_metrics_step(trigger = trigger_oss), + build_docker_images_step( + edition = edition, + publish = False, + ), + build_docker_images_step( + edition = edition, + publish = False, + ubuntu = True, + ), + publish_images_step( + docker_repo = "grafana", + edition = edition, + mode = "", + trigger = trigger_oss, + ver_mode = ver_mode, + ), + publish_images_step( + docker_repo = "grafana-oss", + edition = edition, + mode = "", + trigger = trigger_oss, + ver_mode = ver_mode, + ), + release_canary_npm_packages_step(trigger = trigger_oss), + upload_packages_step( + edition = edition, + trigger = trigger_oss, + ver_mode = ver_mode, + ), + upload_cdn_step( + edition = edition, + trigger = trigger_oss, + ver_mode = ver_mode, + ), + ], + ) + elif ver_mode == "pr": + build_steps.extend( + [ + build_docker_images_step( + archs = [ + "amd64", + ], + edition = edition, + ), + ], + ) - publish_suffix = '' - if ver_mode == 'main': - publish_suffix = '-publish' + publish_suffix = "" + if ver_mode == "main": + publish_suffix = "-publish" return pipeline( - name='{}-build-e2e{}'.format(ver_mode, publish_suffix), edition="oss", trigger=trigger, services=[], steps=init_steps + build_steps, + name = "{}-build-e2e{}".format(ver_mode, publish_suffix), + edition = "oss", + environment = environment, + services = [], + steps = init_steps + build_steps, + trigger = trigger, ) diff --git a/scripts/drone/pipelines/ci_images.star b/scripts/drone/pipelines/ci_images.star new file mode 100644 index 0000000000000..fa6f458cd2b36 --- /dev/null +++ b/scripts/drone/pipelines/ci_images.star @@ -0,0 +1,67 @@ +""" +This module contains steps and pipelines relating to creating CI Docker images. +""" + +load( + "scripts/drone/steps/lib.star", + "wix_image", +) +load( + "scripts/drone/utils/utils.star", + "pipeline", +) +load( + "scripts/drone/vault.star", + "from_secret", +) + +def publish_ci_windows_test_image_pipeline(): + trigger = { + "event": ["promote"], + "target": ["ci-windows-test-image"], + } + pl = pipeline( + name = "publish-ci-windows-test-image", + trigger = trigger, + edition = "", + platform = "windows", + steps = [ + { + "name": "clone", + "image": wix_image, + "environment": { + "GITHUB_TOKEN": from_secret("github_token"), + }, + "commands": [ + 'git clone "https://$$env:GITHUB_TOKEN@github.com/grafana/grafana-ci-sandbox.git" .', + "git checkout -f $$env:DRONE_COMMIT", + ], + }, + { + "name": "build-and-publish", + "image": "docker:windowsservercore-1809", + "environment": { + "DOCKER_USERNAME": from_secret("docker_username"), + "DOCKER_PASSWORD": from_secret("docker_password"), + }, + "commands": [ + "cd scripts\\build\\ci-windows-test", + "docker login -u $$env:DOCKER_USERNAME -p $$env:DOCKER_PASSWORD", + "docker build -t grafana/grafana-ci-windows-test:$$env:TAG .", + "docker push grafana/grafana-ci-windows-test:$$env:TAG", + ], + "volumes": [ + { + "name": "docker", + "path": "//./pipe/docker_engine/", + }, + ], + }, + ], + ) + + pl["clone"] = { + "disable": True, + } + + return [pl] diff --git a/scripts/drone/pipelines/docs.star b/scripts/drone/pipelines/docs.star index eefecd599e7c3..5113fc09de2c5 100644 --- a/scripts/drone/pipelines/docs.star +++ b/scripts/drone/pipelines/docs.star @@ -1,39 +1,32 @@ -load( - 'scripts/drone/steps/lib.star', - 'build_image', - 'yarn_install_step', - 'identify_runner_step', - 'download_grabpl_step', - 'lint_frontend_step', - 'codespell_step', - 'test_frontend_step', - 'build_storybook_step', - 'build_docs_website_step', -) +""" +This module returns all the pipelines used in the event of documentation changes along with supporting functions. +""" load( - 'scripts/drone/services/services.star', - 'integration_test_services', - 'ldap_service', + "scripts/drone/steps/lib.star", + "build_docs_website_step", + "build_image", + "codespell_step", + "identify_runner_step", + "yarn_install_step", ) - load( - 'scripts/drone/utils/utils.star', - 'pipeline', + "scripts/drone/utils/utils.star", + "pipeline", ) docs_paths = { - 'include': [ - '*.md', - 'docs/**', - 'packages/**/*.md', - 'latest.json', + "include": [ + "*.md", + "docs/**", + "packages/**/*.md", + "latest.json", ], } -def docs_pipelines(edition, ver_mode, trigger): +def docs_pipelines(ver_mode, trigger): + environment = {"EDITION": "oss"} steps = [ - download_grabpl_step(), identify_runner_step(), yarn_install_step(), codespell_step(), @@ -42,38 +35,42 @@ def docs_pipelines(edition, ver_mode, trigger): ] return pipeline( - name='{}-docs'.format(ver_mode), edition=edition, trigger=trigger, services=[], steps=steps, + name = "{}-docs".format(ver_mode), + edition = "oss", + trigger = trigger, + services = [], + steps = steps, + environment = environment, ) def lint_docs(): return { - 'name': 'lint-docs', - 'image': build_image, - 'depends_on': [ - 'yarn-install', + "name": "lint-docs", + "image": build_image, + "depends_on": [ + "yarn-install", ], - 'environment': { - 'NODE_OPTIONS': '--max_old_space_size=8192', + "environment": { + "NODE_OPTIONS": "--max_old_space_size=8192", }, - 'commands': [ - 'yarn run prettier:checkDocs', + "commands": [ + "yarn run prettier:checkDocs", ], } - def trigger_docs_main(): return { - 'branch': 'main', - 'event': [ - 'push', + "branch": "main", + "event": [ + "push", ], - 'paths': docs_paths, + "paths": docs_paths, } def trigger_docs_pr(): return { - 'event': [ - 'pull_request', + "event": [ + "pull_request", ], - 'paths': docs_paths, + "paths": docs_paths, } diff --git a/scripts/drone/pipelines/github.star b/scripts/drone/pipelines/github.star new file mode 100644 index 0000000000000..d3ccb6b30c91c --- /dev/null +++ b/scripts/drone/pipelines/github.star @@ -0,0 +1,40 @@ +""" +This module contains steps and pipelines relating to GitHub. +""" + +load( + "scripts/drone/steps/lib.star", + "compile_build_cmd", + "fetch_images_step", + "publish_image", +) +load("scripts/drone/vault.star", "from_secret") +load( + "scripts/drone/utils/utils.star", + "pipeline", +) + +def publish_github_step(): + return { + "name": "publish-github", + "image": publish_image, + "commands": ["./bin/build publish github --repo $${GH_REGISTRY} --create"], + "depends_on": ["fetch-images-enterprise2"], + "environment": { + "GH_TOKEN": from_secret("github_token"), + "GH_REGISTRY": from_secret("gh_registry"), + }, + } + +def publish_github_pipeline(mode): + trigger = { + "event": ["promote"], + "target": [mode], + } + return [pipeline( + name = "publish-github-{}".format(mode), + trigger = trigger, + steps = [compile_build_cmd(), fetch_images_step("enterprise2"), publish_github_step()], + edition = "", + environment = {"EDITION": "enterprise2"}, + )] diff --git a/scripts/drone/pipelines/integration_tests.star b/scripts/drone/pipelines/integration_tests.star index ee4d77ef9f1dc..01e2c45da9afa 100644 --- a/scripts/drone/pipelines/integration_tests.star +++ b/scripts/drone/pipelines/integration_tests.star @@ -1,42 +1,75 @@ +""" +This module returns the pipeline used for integration tests. +""" + load( - 'scripts/drone/steps/lib.star', - 'identify_runner_step', - 'download_grabpl_step', - 'verify_gen_cue_step', - 'wire_install_step', - 'postgres_integration_tests_step', - 'mysql_integration_tests_step', - 'compile_build_cmd', + "scripts/drone/steps/lib.star", + "compile_build_cmd", + "download_grabpl_step", + "enterprise_setup_step", + "identify_runner_step", + "mysql_integration_tests_step", + "postgres_integration_tests_step", + "verify_gen_cue_step", + "wire_install_step", ) - load( - 'scripts/drone/services/services.star', - 'integration_test_services', - 'integration_test_services_volumes', - 'ldap_service', + "scripts/drone/services/services.star", + "integration_test_services", + "integration_test_services_volumes", ) - load( - 'scripts/drone/utils/utils.star', - 'pipeline', + "scripts/drone/utils/utils.star", + "pipeline", ) -def integration_tests(trigger, ver_mode, edition): - services = integration_test_services(edition) +def integration_tests(trigger, prefix, ver_mode = "pr"): + """Generate a pipeline for integration tests. + + Args: + trigger: controls which events can trigger the pipeline execution. + prefix: used in the naming of the pipeline. + ver_mode: defines the event / origin of this build. In this function, if it is set to pr, then it will attempt to clone grafana-enterprise. Otherwise it has no effect. + + Returns: + Drone pipeline. + """ + environment = {"EDITION": "oss"} + + services = integration_test_services(edition = "oss") volumes = integration_test_services_volumes() - init_steps = [ + + init_steps = [] + + verify_step = verify_gen_cue_step() + + if ver_mode == "pr": + # In pull requests, attempt to clone grafana enterprise. + init_steps.append(enterprise_setup_step()) + + # Ensure that verif_gen_cue happens after we clone enterprise + # At the time of writing this, very_gen_cue is depended on by the wire step which is what everything else depends on. + verify_step["depends_on"].append("clone-enterprise") + + init_steps += [ download_grabpl_step(), compile_build_cmd(), identify_runner_step(), - verify_gen_cue_step(edition="oss"), + verify_step, wire_install_step(), ] + test_steps = [ - postgres_integration_tests_step(edition=edition, ver_mode=ver_mode), - mysql_integration_tests_step(edition=edition, ver_mode=ver_mode), + postgres_integration_tests_step(), + mysql_integration_tests_step(), ] return pipeline( - name='{}-integration-tests'.format(ver_mode), edition="oss", trigger=trigger, services=services, steps=init_steps + test_steps, - volumes=volumes + name = "{}-integration-tests".format(prefix), + edition = "oss", + trigger = trigger, + environment = environment, + services = services, + volumes = volumes, + steps = init_steps + test_steps, ) diff --git a/scripts/drone/pipelines/lint_backend.star b/scripts/drone/pipelines/lint_backend.star index f127f655db4a9..f2605c44598fb 100644 --- a/scripts/drone/pipelines/lint_backend.star +++ b/scripts/drone/pipelines/lint_backend.star @@ -1,31 +1,60 @@ +""" +This module returns the pipeline used for linting backend code. +""" + load( - 'scripts/drone/steps/lib.star', - 'identify_runner_step', - 'wire_install_step', - 'lint_backend_step', - 'lint_drone_step', - 'compile_build_cmd', + "scripts/drone/steps/lib.star", + "compile_build_cmd", + "enterprise_setup_step", + "identify_runner_step", + "lint_backend_step", + "lint_drone_step", + "wire_install_step", ) - load( - 'scripts/drone/utils/utils.star', - 'pipeline', + "scripts/drone/utils/utils.star", + "pipeline", ) def lint_backend_pipeline(trigger, ver_mode): + """Generates the pipelines used linting backend code. + + Args: + trigger: controls which events can trigger the pipeline execution. + ver_mode: used in the naming of the pipeline. + + Returns: + Drone pipeline. + """ + environment = {"EDITION": "oss"} + wire_step = wire_install_step() - wire_step.update({ 'depends_on': [] }) + wire_step.update({"depends_on": []}) + init_steps = [ identify_runner_step(), compile_build_cmd(), - wire_step, ] + + if ver_mode == "pr": + # In pull requests, attempt to clone grafana enterprise. + init_steps.append(enterprise_setup_step()) + wire_step["depends_on"].append("clone-enterprise") + + init_steps.append(wire_step) + test_steps = [ - lint_backend_step(edition="oss"), + lint_backend_step(), ] - if ver_mode == 'main': - test_steps.extend([lint_drone_step()]) + + if ver_mode == "main": + test_steps.append(lint_drone_step()) return pipeline( - name='{}-lint-backend'.format(ver_mode), edition="oss", trigger=trigger, services=[], steps=init_steps + test_steps, + name = "{}-lint-backend".format(ver_mode), + edition = "oss", + trigger = trigger, + services = [], + steps = init_steps + test_steps, + environment = environment, ) diff --git a/scripts/drone/pipelines/lint_frontend.star b/scripts/drone/pipelines/lint_frontend.star index f40621c1d9a59..9ef74c2ee74c9 100644 --- a/scripts/drone/pipelines/lint_frontend.star +++ b/scripts/drone/pipelines/lint_frontend.star @@ -1,25 +1,54 @@ +""" +This module returns the pipeline used for linting frontend code. +""" + load( - 'scripts/drone/steps/lib.star', - 'identify_runner_step', - 'yarn_install_step', - 'lint_frontend_step', + "scripts/drone/steps/lib.star", + "enterprise_setup_step", + "identify_runner_step", + "lint_frontend_step", + "yarn_install_step", ) - load( - 'scripts/drone/utils/utils.star', - 'pipeline', + "scripts/drone/utils/utils.star", + "pipeline", ) def lint_frontend_pipeline(trigger, ver_mode): - yarn_step = yarn_install_step() - yarn_step.update({ 'depends_on': [] }) - init_steps = [ + """Generates the pipelines used linting frontend code. + + Args: + trigger: controls which events can trigger the pipeline execution. + ver_mode: used in the naming of the pipeline. + + Returns: + Drone pipeline. + """ + environment = {"EDITION": "oss"} + + init_steps = [] + lint_step = lint_frontend_step() + + if ver_mode == "pr": + # In pull requests, attempt to clone grafana enterprise. + init_steps = [enterprise_setup_step()] + # Ensure the lint step happens after the clone-enterprise step + + lint_step["depends_on"].append("clone-enterprise") + + init_steps += [ identify_runner_step(), - yarn_step, + yarn_install_step(), ] test_steps = [ - lint_frontend_step(), + lint_step, ] + return pipeline( - name='{}-lint-frontend'.format(ver_mode), edition="oss", trigger=trigger, services=[], steps=init_steps + test_steps, + name = "{}-lint-frontend".format(ver_mode), + edition = "oss", + trigger = trigger, + services = [], + steps = init_steps + test_steps, + environment = environment, ) diff --git a/scripts/drone/pipelines/publish.star b/scripts/drone/pipelines/publish.star deleted file mode 100644 index 9d80d4a55ae02..0000000000000 --- a/scripts/drone/pipelines/publish.star +++ /dev/null @@ -1,25 +0,0 @@ -load( - 'scripts/drone/steps/lib.star', - 'identify_runner_step', - 'download_grabpl_step', - 'publish_packages_step', - 'compile_build_cmd', -) - -load( - 'scripts/drone/utils/utils.star', - 'pipeline', -) - -def publish(trigger, ver_mode, edition): - steps = [ - download_grabpl_step(), - compile_build_cmd(), - identify_runner_step(), - publish_packages_step(edition=edition, ver_mode=ver_mode), - ] - return pipeline( - name='main-publish', edition=edition, trigger=dict(trigger, repo=['grafana/grafana']), - steps=steps, - depends_on=['main-test-frontend', 'main-test-backend', 'main-build-e2e-publish', 'main-integration-tests', 'main-windows', ], - ) diff --git a/scripts/drone/pipelines/publish_images.star b/scripts/drone/pipelines/publish_images.star index 5365880d16953..18c94dcbca3e0 100644 --- a/scripts/drone/pipelines/publish_images.star +++ b/scripts/drone/pipelines/publish_images.star @@ -1,50 +1,97 @@ +""" +This module returns the pipeline used for publishing Docker images and its steps. +""" + load( - 'scripts/drone/steps/lib.star', - 'download_grabpl_step', - 'publish_images_step', - 'compile_build_cmd', - 'fetch_images_step', + "scripts/drone/steps/lib.star", + "compile_build_cmd", + "download_grabpl_step", + "fetch_images_step", + "identify_runner_step", + "publish_images_step", ) - load( - 'scripts/drone/utils/utils.star', - 'pipeline', + "scripts/drone/utils/utils.star", + "pipeline", ) - def publish_image_steps(edition, mode, docker_repo): - additional_docker_repo = "" - if edition == 'oss': - additional_docker_repo='grafana/grafana-oss' + """Generates the steps used for publising Docker images using grabpl. + + Args: + edition: controls which version of an image is fetched in the case of a release. + It also controls which publishing implementation is used. + If edition == 'oss', it additionally publishes the grafana/grafana-oss repository. + mode: uses to control the publishing of security images when mode == 'security'. + docker_repo: the Docker image name. + It is combined with the 'grafana/' library prefix. + + Returns: + List of Drone steps. + """ steps = [ + identify_runner_step(), download_grabpl_step(), compile_build_cmd(), fetch_images_step(edition), - publish_images_step(edition, 'release', mode, docker_repo), + publish_images_step(edition, "release", mode, docker_repo), ] - if additional_docker_repo != "": - steps.extend([publish_images_step(edition, 'release', mode, additional_docker_repo)]) + + if edition == "oss": + steps.append( + publish_images_step(edition, "release", mode, "grafana-oss"), + ) return steps def publish_image_pipelines_public(): - mode='public' + """Generates the pipeline used for publising public Docker images. + + Returns: + Drone pipeline + """ + mode = "public" trigger = { - 'event': ['promote'], - 'target': [mode], + "event": ["promote"], + "target": [mode], } - return [pipeline( - name='publish-docker-oss-{}'.format(mode), trigger=trigger, steps=publish_image_steps(edition='oss', mode=mode, docker_repo='grafana/grafana'), edition="" - ), pipeline( - name='publish-docker-enterprise-{}'.format(mode), trigger=trigger, steps=publish_image_steps(edition='enterprise', mode=mode, docker_repo='grafana/grafana-enterprise'), edition="" - ),] + return [ + pipeline( + name = "publish-docker-oss-{}".format(mode), + trigger = trigger, + steps = publish_image_steps(edition = "oss", mode = mode, docker_repo = "grafana"), + edition = "", + environment = {"EDITION": "oss"}, + ), + pipeline( + name = "publish-docker-enterprise-{}".format(mode), + trigger = trigger, + steps = publish_image_steps( + edition = "enterprise", + mode = mode, + docker_repo = "grafana-enterprise", + ), + edition = "", + environment = {"EDITION": "enterprise"}, + ), + ] def publish_image_pipelines_security(): - mode='security' + mode = "security" trigger = { - 'event': ['promote'], - 'target': [mode], + "event": ["promote"], + "target": [mode], } - return [pipeline( - name='publish-docker-enterprise-{}'.format(mode), trigger=trigger, steps=publish_image_steps(edition='enterprise', mode=mode, docker_repo='grafana/grafana-enterprise'), edition="" - ),] + return [ + pipeline( + name = "publish-docker-enterprise-{}".format(mode), + trigger = trigger, + steps = publish_image_steps( + edition = "enterprise", + mode = mode, + docker_repo = "grafana-enterprise", + ), + edition = "", + environment = {"EDITION": "enterprise"}, + ), + ] diff --git a/scripts/drone/pipelines/shellcheck.star b/scripts/drone/pipelines/shellcheck.star index 808d7329ba964..2a2aa55149e4b 100644 --- a/scripts/drone/pipelines/shellcheck.star +++ b/scripts/drone/pipelines/shellcheck.star @@ -1,48 +1,50 @@ -load( - 'scripts/drone/steps/lib.star', - 'build_image', - 'compile_build_cmd' -) +""" +This module returns a Drone step and pipeline for linting with shellcheck. +""" +load("scripts/drone/steps/lib.star", "build_image", "compile_build_cmd") load( - 'scripts/drone/utils/utils.star', - 'pipeline', + "scripts/drone/utils/utils.star", + "pipeline", ) trigger = { - 'event': [ - 'pull_request', + "event": [ + "pull_request", ], - 'paths': { - 'exclude': [ - '*.md', - 'docs/**', - 'latest.json', - ], - 'include': [ - 'scripts/**/*.sh' + "paths": { + "exclude": [ + "*.md", + "docs/**", + "latest.json", ], + "include": ["scripts/**/*.sh"], }, } def shellcheck_step(): return { - 'name': 'shellcheck', - 'image': build_image, - 'depends_on': [ - 'compile-build-cmd', + "name": "shellcheck", + "image": build_image, + "depends_on": [ + "compile-build-cmd", ], - 'commands': [ - './bin/build shellcheck', + "commands": [ + "./bin/build shellcheck", ], } def shellcheck_pipeline(): + environment = {"EDITION": "oss"} steps = [ compile_build_cmd(), shellcheck_step(), ] return pipeline( - name='pr-shellcheck', edition="oss", trigger=trigger, services=[], steps=steps, + name = "pr-shellcheck", + edition = "oss", + trigger = trigger, + services = [], + steps = steps, + environment = environment, ) - diff --git a/scripts/drone/pipelines/test_backend.star b/scripts/drone/pipelines/test_backend.star index 94df1f1e59de4..b75277139cfc4 100644 --- a/scripts/drone/pipelines/test_backend.star +++ b/scripts/drone/pipelines/test_backend.star @@ -1,40 +1,119 @@ +""" +This module returns the pipeline used for testing backend code. +""" + load( - 'scripts/drone/steps/lib.star', - 'identify_runner_step', - 'download_grabpl_step', - 'wire_install_step', - 'test_backend_step', - 'test_backend_integration_step', - 'verify_gen_cue_step', - 'compile_build_cmd', - 'clone_enterprise_step', - 'init_enterprise_step', + "scripts/drone/steps/lib.star", + "clone_enterprise_step", + "compile_build_cmd", + "download_grabpl_step", + "enterprise_setup_step", + "identify_runner_step", + "init_enterprise_step", + "test_backend_integration_step", + "test_backend_step", + "verify_gen_cue_step", + "wire_install_step", ) - load( - 'scripts/drone/utils/utils.star', - 'pipeline', + "scripts/drone/utils/utils.star", + "pipeline", + "with_deps", ) -def test_backend(trigger, ver_mode, edition="oss"): - environment = {'EDITION': edition} - init_steps = [] - if edition != 'oss': - init_steps.extend([clone_enterprise_step(ver_mode), download_grabpl_step(), init_enterprise_step(ver_mode),]) - init_steps.extend([ +def test_backend(trigger, ver_mode): + """Generates the pipeline used for testing OSS backend code. + + Args: + trigger: a Drone trigger for the pipeline. + ver_mode: affects the pipeline name. + + Returns: + Drone pipeline. + """ + environment = {"EDITION": "oss"} + + steps = [] + + verify_step = verify_gen_cue_step() + + if ver_mode == "pr": + # In pull requests, attempt to clone grafana enterprise. + steps.append(enterprise_setup_step()) + + # Ensure that verif_gen_cue happens after we clone enterprise + # At the time of writing this, very_gen_cue is depended on by the wire step which is what everything else depends on. + verify_step["depends_on"].append("clone-enterprise") + + steps += [ identify_runner_step(), - compile_build_cmd(edition), - verify_gen_cue_step(edition), + compile_build_cmd(edition = "oss"), + verify_step, wire_install_step(), - ]) - test_steps = [ - test_backend_step(edition), - test_backend_integration_step(edition), + test_backend_step(), + test_backend_integration_step(), ] + pipeline_name = "{}-test-backend".format(ver_mode) + if ver_mode in ("release-branch", "release"): + pipeline_name = "{}-{}-test-backend".format(ver_mode, "oss") + pipeline_name = '{}-test-backend'.format(ver_mode) if ver_mode in ("release-branch", "release"): pipeline_name = '{}-{}-test-backend'.format(ver_mode, edition) return pipeline( - name=pipeline_name, edition=edition, trigger=trigger, services=[], steps=init_steps + test_steps, environment=environment + name = pipeline_name, + edition = "oss", + trigger = trigger, + steps = steps, + environment = environment, + ) + +def test_backend_enterprise(trigger, ver_mode, source, edition = "enterprise"): + """Generates the pipeline used for testing backend enterprise code. + + Args: + trigger: a Drone trigger for the pipeline. + ver_mode: affects the pipeline name. + source: controls what revision of enterprise code to test with. The source of the PR, usually. + edition: affects the clone step in the pipeline and also affects the pipeline name. + + Returns: + Drone pipeline. + """ + environment = {"EDITION": edition} + + steps = ( + [ + clone_enterprise_step(source), + download_grabpl_step(), + init_enterprise_step(ver_mode), + identify_runner_step(), + compile_build_cmd(edition), + ] + + with_deps( + [ + verify_gen_cue_step(), + ], + [ + "init-enterprise", + ], + ) + + [ + wire_install_step(), + test_backend_step(), + test_backend_integration_step(), + ] + ) + + pipeline_name = "{}-test-backend".format(ver_mode) + if ver_mode in ("release-branch", "release"): + pipeline_name = "{}-{}-test-backend".format(ver_mode, edition) + + return pipeline( + name = pipeline_name, + edition = edition, + trigger = trigger, + steps = steps, + environment = environment, ) diff --git a/scripts/drone/pipelines/test_frontend.star b/scripts/drone/pipelines/test_frontend.star index 7490c66c2e25e..d41d1b7a08a81 100644 --- a/scripts/drone/pipelines/test_frontend.star +++ b/scripts/drone/pipelines/test_frontend.star @@ -1,36 +1,103 @@ +""" +This module returns the pipeline used for testing backend code. +""" + load( - 'scripts/drone/steps/lib.star', - 'identify_runner_step', - 'clone_enterprise_step', - 'init_enterprise_step', - 'download_grabpl_step', - 'yarn_install_step', - 'betterer_frontend_step', - 'test_frontend_step', + "scripts/drone/steps/lib.star", + "betterer_frontend_step", + "clone_enterprise_step", + "download_grabpl_step", + "enterprise_setup_step", + "identify_runner_step", + "init_enterprise_step", + "test_frontend_step", + "yarn_install_step", ) - load( - 'scripts/drone/utils/utils.star', - 'pipeline', + "scripts/drone/utils/utils.star", + "pipeline", + "with_deps", ) -def test_frontend(trigger, ver_mode, edition="oss"): - environment = {'EDITION': edition} - init_steps = [] - if edition != 'oss': - init_steps.extend([clone_enterprise_step(ver_mode), init_enterprise_step(ver_mode),]) - init_steps.extend([ +def test_frontend(trigger, ver_mode): + """Generates the pipeline used for testing frontend code. + + Args: + trigger: a Drone trigger for the pipeline + ver_mode: indirectly controls which revision of enterprise code to use. + + Returns: + Drone pipeline. + """ + environment = {"EDITION": "oss"} + + steps = [ identify_runner_step(), download_grabpl_step(), - yarn_install_step(edition), - ]) - test_steps = [ - betterer_frontend_step(edition), - test_frontend_step(edition), + yarn_install_step(), + betterer_frontend_step(edition = "oss"), ] - pipeline_name = '{}-test-frontend'.format(ver_mode) + + pipeline_name = "{}-test-frontend".format(ver_mode) + + test_step = test_frontend_step(edition = "oss") + + if ver_mode == "pr": + # In pull requests, attempt to clone grafana enterprise. + steps.append(enterprise_setup_step()) + + # Also, make the test step depend on 'clone-enterprise + test_step["depends_on"].append("clone-enterprise") + + steps.append(test_step) + + pipeline_name = "{}-test-frontend".format(ver_mode) if ver_mode in ("release-branch", "release"): - pipeline_name = '{}-{}-test-frontend'.format(ver_mode, edition) + pipeline_name = "{}-oss-test-frontend".format(ver_mode) + + return pipeline( + name = pipeline_name, + edition = "oss", + trigger = trigger, + steps = steps, + environment = environment, + ) + +def test_frontend_enterprise(trigger, ver_mode, source, edition = "enterprise"): + """Generates the pipeline used for testing frontend enterprise code. + + Args: + trigger: a Drone trigger for the pipeline. + ver_mode: affects the pipeline name. + source: controls what revision of Grafana code to test with. + edition: affects the clone step in the pipeline and also affects the pipeline name. + + Returns: + Drone pipeline. + """ + environment = {"EDITION": edition} + steps = ( + [ + download_grabpl_step(), + clone_enterprise_step(source), + init_enterprise_step(ver_mode), + identify_runner_step(), + ] + + with_deps([yarn_install_step()], ["init-enterprise"]) + + [ + betterer_frontend_step(edition), + test_frontend_step(edition), + ] + ) + + pipeline_name = "{}-test-frontend".format(ver_mode) + if ver_mode in ("release-branch", "release"): + pipeline_name = "{}-{}-test-frontend".format(ver_mode, edition) + return pipeline( - name=pipeline_name, edition=edition, trigger=trigger, services=[], steps=init_steps + test_steps, + name = pipeline_name, + edition = edition, + trigger = trigger, + steps = steps, + environment = environment, ) diff --git a/scripts/drone/pipelines/trigger_downstream.star b/scripts/drone/pipelines/trigger_downstream.star index 2c40f06d82ad0..d3403de50f185 100644 --- a/scripts/drone/pipelines/trigger_downstream.star +++ b/scripts/drone/pipelines/trigger_downstream.star @@ -1,28 +1,45 @@ +""" +This module returns the pipeline used for triggering a downstream pipeline for Grafana Enterprise. +""" + load( - 'scripts/drone/steps/lib.star', - 'enterprise_downstream_step', + "scripts/drone/steps/lib.star", + "enterprise_downstream_step", ) - load( - 'scripts/drone/utils/utils.star', - 'pipeline', + "scripts/drone/utils/utils.star", + "pipeline", ) trigger = { - 'event': ['push',], - 'branch': 'main', - 'paths': { - 'exclude': [ - '*.md', - 'docs/**', - 'latest.json', + "event": [ + "push", + ], + "branch": "main", + "paths": { + "exclude": [ + "*.md", + "docs/**", + "latest.json", ], }, } -def enterprise_downstream_pipeline(edition, ver_mode): - steps = [enterprise_downstream_step(edition, ver_mode)] - deps = ['main-publish'] +def enterprise_downstream_pipeline(): + environment = {"EDITION": "oss"} + steps = [ + enterprise_downstream_step(ver_mode = "main"), + ] + deps = [ + "main-build-e2e-publish", + "main-integration-tests", + ] return pipeline( - name='main-trigger-downstream', edition=edition, trigger=trigger, services=[], steps=steps, depends_on=deps - ) + name = "main-trigger-downstream", + edition = "oss", + trigger = trigger, + services = [], + steps = steps, + depends_on = deps, + environment = environment, + ) diff --git a/scripts/drone/pipelines/verify_drone.star b/scripts/drone/pipelines/verify_drone.star index e350c8e0a7e01..8975abec2c881 100644 --- a/scripts/drone/pipelines/verify_drone.star +++ b/scripts/drone/pipelines/verify_drone.star @@ -1,23 +1,30 @@ +""" +This module returns the pipeline used for verifying Drone configuration. +""" + load( - 'scripts/drone/steps/lib.star', - 'identify_runner_step', - 'download_grabpl_step', - 'lint_drone_step', - 'compile_build_cmd', + "scripts/drone/steps/lib.star", + "compile_build_cmd", + "identify_runner_step", + "lint_drone_step", ) - load( - 'scripts/drone/utils/utils.star', - 'pipeline', + "scripts/drone/utils/utils.star", + "pipeline", ) def verify_drone(trigger, ver_mode): + environment = {"EDITION": "oss"} steps = [ identify_runner_step(), - download_grabpl_step(), compile_build_cmd(), lint_drone_step(), ] return pipeline( - name='{}-verify-drone'.format(ver_mode), edition="oss", trigger=trigger, services=[], steps=steps, + name = "{}-verify-drone".format(ver_mode), + edition = "oss", + trigger = trigger, + services = [], + steps = steps, + environment = environment, ) diff --git a/scripts/drone/pipelines/verify_starlark.star b/scripts/drone/pipelines/verify_starlark.star new file mode 100644 index 0000000000000..b95962b2eb548 --- /dev/null +++ b/scripts/drone/pipelines/verify_starlark.star @@ -0,0 +1,30 @@ +""" +This module returns a Drone pipeline that verifies all Starlark files are linted. +""" + +load( + "scripts/drone/steps/lib.star", + "compile_build_cmd", + "identify_runner_step", + "lint_starlark_step", +) +load( + "scripts/drone/utils/utils.star", + "pipeline", +) + +def verify_starlark(trigger, ver_mode): + environment = {"EDITION": "oss"} + steps = [ + identify_runner_step(), + compile_build_cmd(), + lint_starlark_step(), + ] + return pipeline( + name = "{}-verify-starlark".format(ver_mode), + edition = "oss", + trigger = trigger, + services = [], + steps = steps, + environment = environment, + ) diff --git a/scripts/drone/pipelines/windows.star b/scripts/drone/pipelines/windows.star index c0e0f61f7f652..3669cfb9986e6 100644 --- a/scripts/drone/pipelines/windows.star +++ b/scripts/drone/pipelines/windows.star @@ -1,134 +1,81 @@ +""" +This module returns the pipeline used for building Grafana on Windows. +""" + load( - 'scripts/drone/steps/lib.star', - 'grabpl_version', - 'wix_image', - 'identify_runner_step', + "scripts/drone/utils/utils.star", + "pipeline", ) - load( - 'scripts/drone/utils/utils.star', - 'pipeline', + "scripts/drone/steps/lib.star", + "get_windows_steps", + "windows_go_image", + "windows_init_enterprise_steps", + "windows_test_backend_step", + "windows_wire_install_step", ) -load('scripts/drone/vault.star', 'from_secret', 'prerelease_bucket', 'github_token') +def windows_test_backend(trigger, edition, ver_mode): + """ Generates a pipeline that runs backend tests on Windows -def windows(trigger, edition, ver_mode): - init_cmds = [] - sfx = '' - if edition in ('enterprise', 'enterprise2'): - sfx = '-{}'.format(edition) + Args: + trigger: a Drone trigger for the pipeline + edition: controls whether enterprise code is included or not + ver_mode: controls whether a pre-release or actual release pipeline is generated. + Returns: + A single pipeline running backend tests for Windows + """ + environment = {"EDITION": edition} + steps = [] + + if edition == "enterprise": + steps.extend(windows_init_enterprise_steps(ver_mode)) else: - init_cmds.extend([ - '$$ProgressPreference = "SilentlyContinue"', - 'Invoke-WebRequest https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/{}/windows/grabpl.exe -OutFile grabpl.exe'.format( - grabpl_version), - ]) - steps = [ - { - 'name': 'windows-init', - 'image': wix_image, - 'commands': init_cmds, - }, - ] - if (ver_mode == 'main' and (edition not in ('enterprise', 'enterprise2'))) or ver_mode in ( - 'release', 'release-branch', - ): - bucket = '%PRERELEASE_BUCKET%/artifacts/downloads' - if ver_mode == 'release': - ver_part = '${DRONE_TAG}' - dir = 'release' - else: - dir = 'main' - bucket = 'grafana-downloads' - build_no = 'DRONE_BUILD_NUMBER' - ver_part = '--build-id $$env:{}'.format(build_no) - installer_commands = [ - '$$gcpKey = $$env:GCP_KEY', - '[System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($$gcpKey)) > gcpkey.json', - # gcloud fails to read the file unless converted with dos2unix - 'dos2unix gcpkey.json', - 'gcloud auth activate-service-account --key-file=gcpkey.json', - 'rm gcpkey.json', - 'cp C:\\App\\nssm-2.24.zip .', - ] - if (ver_mode == 'main' and (edition not in ('enterprise', 'enterprise2'))) or ver_mode in ( - 'release', - ): - installer_commands.extend([ - '.\\grabpl.exe windows-installer --edition {} {}'.format(edition, ver_part), - '$$fname = ((Get-Childitem grafana*.msi -name) -split "`n")[0]', - ]) - if ver_mode == 'main': - installer_commands.extend([ - 'gsutil cp $$fname gs://{}/{}/{}/'.format(bucket, edition, dir), - 'gsutil cp "$$fname.sha256" gs://{}/{}/{}/'.format(bucket, edition, dir), - ]) - else: - installer_commands.extend([ - 'gsutil cp $$fname gs://{}/{}/{}/{}/'.format(bucket, ver_part, edition, dir), - 'gsutil cp "$$fname.sha256" gs://{}/{}/{}/{}/'.format(bucket, ver_part, edition, dir), - ]) - steps.append({ - 'name': 'build-windows-installer', - 'image': wix_image, - 'depends_on': [ - 'windows-init', - ], - 'environment': { - 'GCP_KEY': from_secret('gcp_key'), - 'PRERELEASE_BUCKET': from_secret(prerelease_bucket), - 'GITHUB_TOKEN': from_secret('github_token') - }, - 'commands': installer_commands, - }) + steps.extend([{ + "name": "windows-init", + "image": windows_go_image, + "commands": [], + }]) + + steps.extend([ + windows_wire_install_step(edition), + windows_test_backend_step(), + ]) + return pipeline( + name = "{}-{}-test-backend-windows".format(ver_mode, edition), + edition = edition, + trigger = trigger, + steps = steps, + depends_on = [], + platform = "windows", + environment = environment, + ) + +def windows(trigger, edition, ver_mode): + """Generates the pipeline used for building Grafana on Windows. + + Args: + trigger: a Drone trigger for the pipeline. + edition: controls whether enterprise code is included in the pipeline steps. + ver_mode: controls whether a pre-release or actual release pipeline is generated. + Also indirectly controls which version of enterprise code is used. - if edition in ('enterprise', 'enterprise2'): - if ver_mode == 'release': - committish = '${DRONE_TAG}' - elif ver_mode == 'release-branch': - committish = '$$env:DRONE_BRANCH' - else: - committish = '$$env:DRONE_COMMIT' - # For enterprise, we have to clone both OSS and enterprise and merge the latter into the former - download_grabpl_step_cmds = [ - '$$ProgressPreference = "SilentlyContinue"', - 'Invoke-WebRequest https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/{}/windows/grabpl.exe -OutFile grabpl.exe'.format( - grabpl_version), - ] - clone_cmds = [ - 'git clone "https://$$env:GITHUB_TOKEN@github.com/grafana/grafana-enterprise.git"', - ] - clone_cmds.extend([ - 'cd grafana-enterprise', - 'git checkout {}'.format(committish), - ]) - steps.insert(0, { - 'name': 'clone', - 'image': wix_image, - 'environment': { - 'GITHUB_TOKEN': from_secret(github_token), - }, - 'commands': download_grabpl_step_cmds + clone_cmds, - }) - steps[1]['depends_on'] = [ - 'clone', - ] - steps[1]['commands'].extend([ - # Need to move grafana-enterprise out of the way, so directory is empty and can be cloned into - 'cp -r grafana-enterprise C:\\App\\grafana-enterprise', - 'rm -r -force grafana-enterprise', - 'cp grabpl.exe C:\\App\\grabpl.exe', - 'rm -force grabpl.exe', - 'C:\\App\\grabpl.exe init-enterprise --github-token $$env:GITHUB_TOKEN C:\\App\\grafana-enterprise', - 'cp C:\\App\\grabpl.exe grabpl.exe', - ]) - if 'environment' in steps[1]: - steps[1]['environment'] + {'GITHUB_TOKEN': from_secret(github_token)} - else: - steps[1]['environment'] = {'GITHUB_TOKEN': from_secret(github_token)} + Returns: + Drone pipeline. + """ + environment = {"EDITION": edition} return pipeline( - name='main-windows', edition=edition, trigger=dict(trigger, repo=['grafana/grafana']), - steps=[identify_runner_step('windows')] + steps, - depends_on=['main-test-frontend', 'main-test-backend', 'main-build-e2e-publish', 'main-integration-tests'], platform='windows', + name = "main-windows", + edition = edition, + trigger = dict(trigger, repo = ["grafana/grafana"]), + steps = get_windows_steps(edition, ver_mode), + depends_on = [ + "main-test-frontend", + "main-test-backend", + "main-build-e2e-publish", + "main-integration-tests", + ], + platform = "windows", + environment = environment, ) diff --git a/scripts/drone/services/services.star b/scripts/drone/services/services.star index e81d05500776f..9d7d04a2dedff 100644 --- a/scripts/drone/services/services.star +++ b/scripts/drone/services/services.star @@ -1,61 +1,66 @@ +""" +This module has functions for Drone services to be used in pipelines. +""" + def integration_test_services_volumes(): return [ - { 'name': 'postgres', 'temp': { 'medium': 'memory' } }, - { 'name': 'mysql', 'temp': { 'medium': 'memory' } - }] + {"name": "postgres", "temp": {"medium": "memory"}}, + {"name": "mysql", "temp": {"medium": "memory"}}, + ] def integration_test_services(edition): services = [ { - 'name': 'postgres', - 'image': 'postgres:12.3-alpine', - 'environment': { - 'POSTGRES_USER': 'grafanatest', - 'POSTGRES_PASSWORD': 'grafanatest', - 'POSTGRES_DB': 'grafanatest', - 'PGDATA': '/var/lib/postgresql/data/pgdata', + "name": "postgres", + "image": "postgres:12.3-alpine", + "environment": { + "POSTGRES_USER": "grafanatest", + "POSTGRES_PASSWORD": "grafanatest", + "POSTGRES_DB": "grafanatest", + "PGDATA": "/var/lib/postgresql/data/pgdata", }, - 'volumes': [{ - 'name': 'postgres', - 'path': '/var/lib/postgresql/data/pgdata' - }], + "volumes": [ + {"name": "postgres", "path": "/var/lib/postgresql/data/pgdata"}, + ], }, { - 'name': 'mysql', - 'image': 'mysql:5.7.39', - 'environment': { - 'MYSQL_ROOT_PASSWORD': 'rootpass', - 'MYSQL_DATABASE': 'grafana_tests', - 'MYSQL_USER': 'grafana', - 'MYSQL_PASSWORD': 'password', + "name": "mysql", + "image": "mysql:5.7.39", + "environment": { + "MYSQL_ROOT_PASSWORD": "rootpass", + "MYSQL_DATABASE": "grafana_tests", + "MYSQL_USER": "grafana", + "MYSQL_PASSWORD": "password", }, - 'volumes': [{ - 'name': 'mysql', - 'path': '/var/lib/mysql' - }] + "volumes": [{"name": "mysql", "path": "/var/lib/mysql"}], }, ] - if edition in ('enterprise', 'enterprise2'): - services.extend([{ - 'name': 'redis', - 'image': 'redis:6.2.1-alpine', - 'environment': {}, - }, { - 'name': 'memcached', - 'image': 'memcached:1.6.9-alpine', - 'environment': {}, - }]) + if edition in ("enterprise", "enterprise2"): + services.extend( + [ + { + "name": "redis", + "image": "redis:6.2.1-alpine", + "environment": {}, + }, + { + "name": "memcached", + "image": "memcached:1.6.9-alpine", + "environment": {}, + }, + ], + ) return services def ldap_service(): return { - 'name': 'ldap', - 'image': 'osixia/openldap:1.4.0', - 'environment': { - 'LDAP_ADMIN_PASSWORD': 'grafana', - 'LDAP_DOMAIN': 'grafana.org', - 'SLAPD_ADDITIONAL_MODULES': 'memberof', + "name": "ldap", + "image": "osixia/openldap:1.4.0", + "environment": { + "LDAP_ADMIN_PASSWORD": "grafana", + "LDAP_DOMAIN": "grafana.org", + "SLAPD_ADDITIONAL_MODULES": "memberof", }, } diff --git a/scripts/drone/steps/lib.star b/scripts/drone/steps/lib.star index 3d8cdd4e01ee0..ee484a6b6990d 100644 --- a/scripts/drone/steps/lib.star +++ b/scripts/drone/steps/lib.star @@ -1,1287 +1,1637 @@ -load('scripts/drone/vault.star', 'from_secret', 'github_token', 'pull_secret', 'drone_token', 'prerelease_bucket') - -grabpl_version = 'v3.0.15' -build_image = 'grafana/build-container:1.6.6' -publish_image = 'grafana/grafana-ci-deploy:1.3.3' -deploy_docker_image = 'us.gcr.io/kubernetes-dev/drone/plugins/deploy-image' -alpine_image = 'alpine:3.15.6' -curl_image = 'byrnedo/alpine-curl:0.1.8' -windows_image = 'mcr.microsoft.com/windows:1809' -wix_image = 'grafana/ci-wix:0.1.1' -go_image = 'golang:1.19.4' - -disable_tests = False +""" +This module is a library of Drone steps and other pipeline components. +""" + +load( + "scripts/drone/vault.star", + "from_secret", + "prerelease_bucket", +) + +grabpl_version = "v3.0.30" +build_image = "grafana/build-container:1.7.4" +publish_image = "grafana/grafana-ci-deploy:1.3.3" +deploy_docker_image = "us.gcr.io/kubernetes-dev/drone/plugins/deploy-image" +alpine_image = "alpine:3.17.1" +curl_image = "byrnedo/alpine-curl:0.1.8" +windows_image = "mcr.microsoft.com/windows:1809" +wix_image = "grafana/ci-wix:0.1.1" +go_image = "golang:1.20.4" +windows_go_image = "grafana/grafana-ci-windows-test:0.1.0" + trigger_oss = { - 'repo': [ - 'grafana/grafana', - ] + "repo": [ + "grafana/grafana", + ], } - def slack_step(channel, template, secret): return { - 'name': 'slack', - 'image': 'plugins/slack', - 'settings': { - 'webhook': from_secret(secret), - 'channel': channel, - 'template': template, + "name": "slack", + "image": "plugins/slack", + "settings": { + "webhook": from_secret(secret), + "channel": channel, + "template": template, }, } -def yarn_install_step(edition="oss"): - deps = [] - if edition == 'enterprise': - deps = ['init-enterprise'] +def yarn_install_step(): return { - 'name': 'yarn-install', - 'image': build_image, - 'commands': [ - 'yarn install --immutable', + "name": "yarn-install", + "image": build_image, + "commands": [ + "yarn install --immutable", ], - 'depends_on': deps, + "depends_on": [], } - def wire_install_step(): return { - 'name': 'wire-install', - 'image': build_image, - 'commands': [ - 'make gen-go', + "name": "wire-install", + "image": build_image, + "commands": [ + "make gen-go", ], - 'depends_on': [ - 'verify-gen-cue', + "depends_on": [ + "verify-gen-cue", ], } +def windows_wire_install_step(edition): + return { + "name": "wire-install", + "image": windows_go_image, + "commands": [ + "go install github.com/google/wire/cmd/wire@v0.5.0", + "wire gen -tags {} ./pkg/server".format(edition), + ], + "depends_on": [ + "windows-init", + ], + } -def identify_runner_step(platform='linux'): - if platform == 'windows': +def identify_runner_step(platform = "linux"): + if platform == "linux": return { - 'name': 'identify-runner', - 'image': windows_image, - 'commands': [ - 'echo $env:DRONE_RUNNER_NAME', + "name": "identify-runner", + "image": alpine_image, + "commands": [ + "echo $DRONE_RUNNER_NAME", ], } else: return { - 'name': 'identify-runner', - 'image': alpine_image, - 'commands': [ - 'echo $DRONE_RUNNER_NAME', + "name": "identify-runner", + "image": windows_image, + "commands": [ + "echo $env:DRONE_RUNNER_NAME", ], } +def enterprise_setup_step(source = "${DRONE_SOURCE_BRANCH}", canFail = True): + step = clone_enterprise_step_pr(source = source, target = "${DRONE_TARGET_BRANCH}", canFail = canFail, location = "../grafana-enterprise") + step["commands"] += [ + "cd ../", + "ln -s src grafana", + "cd ./grafana-enterprise", + "./build.sh", + ] -def clone_enterprise_step(ver_mode): - if ver_mode == 'release': - committish = '${DRONE_TAG}' - elif ver_mode == 'release-branch': - committish = '${DRONE_BRANCH}' - else: - committish = '${DRONE_COMMIT}' - return { - 'name': 'clone-enterprise', - 'image': build_image, - 'environment': { - 'GITHUB_TOKEN': from_secret(github_token), + return step + +def clone_enterprise_step(source = "${DRONE_COMMIT}"): + """Clone the enterprise source into the ./grafana-enterprise directory. + + Args: + source: controls which revision of grafana-enterprise is checked out, if it exists. The name 'source' derives from the 'source branch' of a pull request. + Returns: + Drone step. + """ + step = { + "name": "clone-enterprise", + "image": build_image, + "environment": { + "GITHUB_TOKEN": from_secret("github_token"), }, - 'commands': [ + "commands": [ 'git clone "https://$${GITHUB_TOKEN}@github.com/grafana/grafana-enterprise.git"', - 'cd grafana-enterprise', - 'git checkout {}'.format(committish), + "cd grafana-enterprise", + "git checkout {}".format(source), + ], + } + + return step + +def clone_enterprise_step_pr(source = "${DRONE_COMMIT}", target = "main", canFail = False, location = "grafana-enterprise"): + """Clone the enterprise source into the ./grafana-enterprise directory. + + Args: + source: controls which revision of grafana-enterprise is checked out, if it exists. The name 'source' derives from the 'source branch' of a pull request. + target: controls which revision of grafana-enterprise is checked out, if it 'source' does not exist. The name 'target' derives from the 'target branch' of a pull request. If this does not exist, then 'main' will be checked out. + canFail: controls whether or not this step is allowed to fail. If it fails and this is true, then the pipeline will continue. canFail is used in pull request pipelines where enterprise may be cloned but may not clone in forks. + location: the path where grafana-enterprise is cloned. + Returns: + Drone step. + """ + step = { + "name": "clone-enterprise", + "image": build_image, + "environment": { + "GITHUB_TOKEN": from_secret("github_token"), + }, + "commands": [ + 'is_fork=$(curl "https://$GITHUB_TOKEN@api.github.com/repos/grafana/grafana/pulls/$DRONE_PULL_REQUEST" | jq .head.repo.fork)', + 'if [ "$is_fork" != false ]; then return 1; fi', # Only clone if we're confident that 'fork' is 'false'. Fail if it's also empty. + 'git clone "https://$${GITHUB_TOKEN}@github.com/grafana/grafana-enterprise.git" ' + location, + "cd {}".format(location), + 'if git checkout {0}; then echo "checked out {0}"; elif git checkout {1}; then echo "git checkout {1}"; else git checkout main; fi'.format(source, target), ], } + if canFail: + step["failure"] = "ignore" + + return step + def init_enterprise_step(ver_mode): - source_commit = '' - if ver_mode == 'release': - source_commit = ' ${DRONE_TAG}' + """Adds the enterprise deployment configuration into the source directory. + + Args: + ver_mode: controls what revision of the OSS source to use. + If ver_mode is 'release', the step uses the tagged revision. + Otherwise, the DRONE_SOURCE_BRANCH is used. + + Returns: + Drone step. + """ + source_commit = "" + if ver_mode == "release": + source_commit = " ${DRONE_TAG}" environment = { - 'GITHUB_TOKEN': from_secret(github_token), + "GITHUB_TOKEN": from_secret("github_token"), } token = "--github-token $${GITHUB_TOKEN}" - elif ver_mode == 'release-branch': + elif ver_mode == "release-branch": environment = { - 'GITHUB_TOKEN': from_secret(github_token), + "GITHUB_TOKEN": from_secret("github_token"), } token = "--github-token $${GITHUB_TOKEN}" else: environment = {} token = "" return { - 'name': 'init-enterprise', - 'image': build_image, - 'depends_on': [ - 'clone-enterprise', + "name": "init-enterprise", + "image": build_image, + "depends_on": [ + "clone-enterprise", + "grabpl", ], - 'environment': environment, - 'commands': [ - 'mv bin/grabpl /tmp/', - 'rmdir bin', - 'mv grafana-enterprise /tmp/', - '/tmp/grabpl init-enterprise {} /tmp/grafana-enterprise{}'.format(token, source_commit), - 'mv /tmp/grafana-enterprise/deployment_tools_config.json deployment_tools_config.json', - 'mkdir bin', - 'mv /tmp/grabpl bin/' + "environment": environment, + "commands": [ + "mv bin/grabpl /tmp/", + "rmdir bin", + "mv grafana-enterprise /tmp/", + "/tmp/grabpl init-enterprise {} /tmp/grafana-enterprise{}".format( + token, + source_commit, + ).rstrip(), + "mv /tmp/grafana-enterprise/deployment_tools_config.json deployment_tools_config.json", + "mkdir bin", + "mv /tmp/grabpl bin/", ], } +def windows_init_enterprise_steps(ver_mode): + """Performs init-enterprise steps in a Windows environment + + Args: + ver_mode: in what mode should this be run + + Returns: + A list of steps setting up an enterprise folder + """ + if ver_mode == "release": + source = "${DRONE_TAG}" + elif ver_mode == "release-branch": + source = "$$env:DRONE_BRANCH" + else: + source = "main" -def download_grabpl_step(platform="linux"): - if platform == 'windows': + clone_cmds = [ + 'git clone "https://$$env:GITHUB_TOKEN@github.com/grafana/grafana-enterprise.git"', + "cd grafana-enterprise", + "git checkout {}".format(source), + ] + + init_cmds = [ + # Need to move grafana-enterprise out of the way, so directory is empty and can be cloned into + "cp -r grafana-enterprise C:\\App\\grafana-enterprise", + "rm -r -force grafana-enterprise", + "cp grabpl.exe C:\\App\\grabpl.exe", + "rm -force grabpl.exe", + "C:\\App\\grabpl.exe init-enterprise --github-token $$env:GITHUB_TOKEN C:\\App\\grafana-enterprise {}".format(source), + "cp C:\\App\\grabpl.exe grabpl.exe", + ] + + steps = [] + steps.extend( + [ + download_grabpl_step(platform = "windows"), + { + "name": "clone", + "image": wix_image, + "environment": { + "GITHUB_TOKEN": from_secret("github_token"), + }, + "commands": clone_cmds, + }, + { + "name": "windows-init", + "image": wix_image, + "commands": init_cmds, + "depends_on": ["clone"], + "environment": {"GITHUB_TOKEN": from_secret("github_token")}, + }, + ], + ) + return steps + +def download_grabpl_step(platform = "linux"): + if platform == "windows": return { - 'name': 'grabpl', - 'image': wix_image, - 'commands': [ + "name": "grabpl", + "image": wix_image, + "commands": [ '$$ProgressPreference = "SilentlyContinue"', - 'Invoke-WebRequest https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/{}/windows/grabpl.exe -OutFile grabpl.exe'.format( - grabpl_version), - ] + "Invoke-WebRequest https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/{}/windows/grabpl.exe -OutFile grabpl.exe".format( + grabpl_version, + ), + ], } return { - 'name': 'grabpl', - 'image': curl_image, - 'commands': [ - 'mkdir -p bin', - 'curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/{}/grabpl'.format( - grabpl_version + "name": "grabpl", + "image": curl_image, + "commands": [ + "mkdir -p bin", + "curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/{}/grabpl".format( + grabpl_version, ), - 'chmod +x bin/grabpl', - ] + "chmod +x bin/grabpl", + ], } - def lint_drone_step(): return { - 'name': 'lint-drone', - 'image': curl_image, - 'commands': [ - './bin/build verify-drone', + "name": "lint-drone", + "image": curl_image, + "commands": [ + "./bin/build verify-drone", + ], + "depends_on": [ + "compile-build-cmd", + ], + } + +def lint_starlark_step(): + return { + "name": "lint-starlark", + "image": build_image, + "commands": [ + "./bin/build verify-starlark .", ], - 'depends_on': [ - 'compile-build-cmd', + "depends_on": [ + "compile-build-cmd", ], } -def enterprise_downstream_step(edition, ver_mode): - if edition in ('enterprise', 'enterprise2'): - return None +def enterprise_downstream_step(ver_mode): + """Triggers a downstream pipeline in the grafana-enterprise repository. - repo = 'grafana/grafana-enterprise@' - if ver_mode == 'pr': - repo += '${DRONE_SOURCE_BRANCH}' + Args: + ver_mode: indirectly controls the revision used for downstream pipelines. + It also used to allow the step to fail for pull requests without blocking merging. + + Returns: + Drone step. + """ + repo = "grafana/grafana-enterprise@" + if ver_mode == "pr": + repo += "${DRONE_SOURCE_BRANCH}" else: - repo += 'main' + repo += "main" step = { - 'name': 'trigger-enterprise-downstream', - 'image': 'grafana/drone-downstream', - 'settings': { - 'server': 'https://drone.grafana.net', - 'token': from_secret(drone_token), - 'repositories': [ + "name": "trigger-enterprise-downstream", + "image": "grafana/drone-downstream", + "settings": { + "server": "https://drone.grafana.net", + "token": from_secret("drone_token"), + "repositories": [ repo, ], - 'params': [ - 'SOURCE_BUILD_NUMBER=${DRONE_COMMIT}', - 'SOURCE_COMMIT=${DRONE_COMMIT}', + "params": [ + "SOURCE_BUILD_NUMBER=${DRONE_COMMIT}", + "SOURCE_COMMIT=${DRONE_COMMIT}", ], }, } - if ver_mode == 'pr': - step.update({ 'failure': 'ignore' }) - step['settings']['params'].append('OSS_PULL_REQUEST=${DRONE_PULL_REQUEST}') + if ver_mode == "pr": + step.update({"failure": "ignore"}) + step["settings"]["params"].append("OSS_PULL_REQUEST=${DRONE_PULL_REQUEST}") return step - -def lint_backend_step(edition): +def lint_backend_step(): return { - 'name': 'lint-backend' + enterprise2_suffix(edition), - 'image': go_image, - 'environment': { + "name": "lint-backend", + # TODO: build_image or go_image? + "image": go_image, + "environment": { # We need CGO because of go-sqlite3 - 'CGO_ENABLED': '1', + "CGO_ENABLED": "1", }, - 'depends_on': [ - 'wire-install', + "depends_on": [ + "wire-install", ], - 'commands': [ - 'apt-get update && apt-get install make', + "commands": [ + "apt-get update && apt-get install make", # Don't use Make since it will re-download the linters - 'make lint-go', + "make lint-go", ], } - def benchmark_ldap_step(): return { - 'name': 'benchmark-ldap', - 'image': build_image, - 'environment': { - 'LDAP_HOSTNAME': 'ldap', + "name": "benchmark-ldap", + "image": build_image, + "environment": { + "LDAP_HOSTNAME": "ldap", }, - 'commands': [ - 'dockerize -wait tcp://ldap:389 -timeout 120s', + "commands": [ + "dockerize -wait tcp://ldap:389 -timeout 120s", 'go test -benchmem -run=^$ ./pkg/extensions/ldapsync -bench "^(Benchmark50Users)$"', ], } - -def build_storybook_step(edition, ver_mode): - if edition in ('enterprise', 'enterprise2'): - return None - +def build_storybook_step(ver_mode): return { - 'name': 'build-storybook', - 'image': build_image, - 'depends_on': [ + "name": "build-storybook", + "image": build_image, + "depends_on": [ # Best to ensure that this step doesn't mess with what's getting built and packaged - 'build-frontend', - 'build-frontend-packages', + "build-frontend", + "build-frontend-packages", ], - 'environment': { - 'NODE_OPTIONS': '--max_old_space_size=4096', + "environment": { + "NODE_OPTIONS": "--max_old_space_size=4096", }, - 'commands': [ - 'yarn storybook:build', - './bin/grabpl verify-storybook', + "commands": [ + "yarn storybook:build", + "./bin/build verify-storybook", ], - 'when': get_trigger_storybook(ver_mode), + "when": get_trigger_storybook(ver_mode), } +def store_storybook_step(ver_mode, trigger = None): + """Publishes the Grafana UI components storybook. -def store_storybook_step(edition, ver_mode, trigger=None): - if edition in ('enterprise', 'enterprise2'): - return None + Args: + ver_mode: controls whether a release or canary version is published. + trigger: a Drone trigger for the step. + Defaults to None. + Returns: + Drone step. + """ commands = [] - if ver_mode == 'release': - commands.extend([ - './bin/build store-storybook --deployment latest', - './bin/build store-storybook --deployment ${DRONE_TAG}', - ]) + if ver_mode == "release": + commands.extend( + [ + "./bin/build store-storybook --deployment latest", + "./bin/build store-storybook --deployment ${DRONE_TAG}", + ], + ) else: # main pipelines should deploy storybook to grafana-storybook/canary public bucket - commands = ['./bin/build store-storybook --deployment canary', ] + commands = [ + "./bin/build store-storybook --deployment canary", + ] step = { - 'name': 'store-storybook', - 'image': publish_image, - 'depends_on': ['build-storybook', ] + end_to_end_tests_deps(edition), - 'environment': { - 'GCP_KEY': from_secret('gcp_key'), - 'PRERELEASE_BUCKET': from_secret(prerelease_bucket) + "name": "store-storybook", + "image": publish_image, + "depends_on": [ + "build-storybook", + ] + + end_to_end_tests_deps(), + "environment": { + "GCP_KEY": from_secret("gcp_key"), + "PRERELEASE_BUCKET": from_secret(prerelease_bucket), }, - 'commands': commands, - 'when': get_trigger_storybook(ver_mode), + "commands": commands, + "when": get_trigger_storybook(ver_mode), } if trigger and ver_mode in ("release-branch", "main"): # no dict merge operation available, https://github.com/harness/drone-cli/pull/220 when_cond = { - 'repo': ['grafana/grafana',], - 'paths': { - 'include': [ - 'packages/grafana-ui/**', + "repo": [ + "grafana/grafana", + ], + "paths": { + "include": [ + "packages/grafana-ui/**", ], - } + }, } - step = dict(step, when=when_cond) + step = dict(step, when = when_cond) return step - -def e2e_tests_artifacts(edition): +def e2e_tests_artifacts(): return { - 'name': 'e2e-tests-artifacts-upload' + enterprise2_suffix(edition), - 'image': 'google/cloud-sdk:367.0.0', - 'depends_on': [ - 'end-to-end-tests-dashboards-suite', - 'end-to-end-tests-panels-suite', - 'end-to-end-tests-smoke-tests-suite', - 'end-to-end-tests-various-suite', + "name": "e2e-tests-artifacts-upload", + "image": "google/cloud-sdk:406.0.0", + "depends_on": [ + "end-to-end-tests-dashboards-suite", + "end-to-end-tests-panels-suite", + "end-to-end-tests-smoke-tests-suite", + "end-to-end-tests-various-suite", ], - 'when': { - 'status': [ - 'success', - 'failure', - ] + "failure": "ignore", + "when": { + "status": [ + "success", + "failure", + ], }, - 'environment': { - 'GCP_GRAFANA_UPLOAD_ARTIFACTS_KEY': from_secret('gcp_upload_artifacts_key'), - 'E2E_TEST_ARTIFACTS_BUCKET': 'releng-pipeline-artifacts-dev', - 'GITHUB_TOKEN': from_secret('github_token'), + "environment": { + "GCP_GRAFANA_UPLOAD_ARTIFACTS_KEY": from_secret("gcp_upload_artifacts_key"), + "E2E_TEST_ARTIFACTS_BUCKET": "releng-pipeline-artifacts-dev", + "GITHUB_TOKEN": from_secret("github_token"), }, - 'commands': [ - 'apt-get update', - 'apt-get install -yq zip', - 'ls -lah ./e2e', - 'find ./e2e -type f -name "*.mp4"', - 'printenv GCP_GRAFANA_UPLOAD_ARTIFACTS_KEY > /tmp/gcpkey_upload_artifacts.json', - 'gcloud auth activate-service-account --key-file=/tmp/gcpkey_upload_artifacts.json', + "commands": [ + "apt-get update", + "apt-get install -yq zip", + "printenv GCP_GRAFANA_UPLOAD_ARTIFACTS_KEY > /tmp/gcpkey_upload_artifacts.json", + "gcloud auth activate-service-account --key-file=/tmp/gcpkey_upload_artifacts.json", # we want to only include files in e2e folder that end with .spec.ts.mp4 'find ./e2e -type f -name "*spec.ts.mp4" | zip e2e/videos.zip -@', - 'gsutil cp e2e/videos.zip gs://$${E2E_TEST_ARTIFACTS_BUCKET}/${DRONE_BUILD_NUMBER}/artifacts/videos/videos.zip', - 'export E2E_ARTIFACTS_VIDEO_ZIP=https://storage.googleapis.com/$${E2E_TEST_ARTIFACTS_BUCKET}/${DRONE_BUILD_NUMBER}/artifacts/videos/videos.zip', + "gsutil cp e2e/videos.zip gs://$${E2E_TEST_ARTIFACTS_BUCKET}/${DRONE_BUILD_NUMBER}/artifacts/videos/videos.zip", + "export E2E_ARTIFACTS_VIDEO_ZIP=https://storage.googleapis.com/$${E2E_TEST_ARTIFACTS_BUCKET}/${DRONE_BUILD_NUMBER}/artifacts/videos/videos.zip", 'echo "E2E Test artifacts uploaded to: $${E2E_ARTIFACTS_VIDEO_ZIP}"', 'curl -X POST https://api.github.com/repos/${DRONE_REPO}/statuses/${DRONE_COMMIT_SHA} -H "Authorization: token $${GITHUB_TOKEN}" -d ' + '"{\\"state\\":\\"success\\",\\"target_url\\":\\"$${E2E_ARTIFACTS_VIDEO_ZIP}\\", \\"description\\": \\"Click on the details to download e2e recording videos\\", \\"context\\": \\"e2e_artifacts\\"}"', ], } +def upload_cdn_step(edition, ver_mode, trigger = None): + """Uploads CDN assets using the Grafana build tool. -def upload_cdn_step(edition, ver_mode, trigger=None): + Args: + edition: controls the output directory for the CDN assets. + ver_mode: only uses the step trigger when ver_mode == 'release-branch' or 'main' + trigger: a Drone trigger for the step. + Defaults to None. + + Returns: + Drone step. + """ deps = [] - if edition in 'enterprise2': - deps.extend([ - 'package' + enterprise2_suffix(edition), - ]) + if edition in "enterprise2": + deps.extend( + [ + "package" + enterprise2_suffix(edition), + ], + ) else: - deps.extend([ - 'grafana-server', - ]) + deps.extend( + [ + "grafana-server", + ], + ) step = { - 'name': 'upload-cdn-assets' + enterprise2_suffix(edition), - 'image': publish_image, - 'depends_on': deps, - 'environment': { - 'GCP_KEY': from_secret('gcp_key'), - 'PRERELEASE_BUCKET': from_secret(prerelease_bucket) + "name": "upload-cdn-assets" + enterprise2_suffix(edition), + "image": publish_image, + "depends_on": deps, + "environment": { + "GCP_KEY": from_secret("gcp_key"), + "PRERELEASE_BUCKET": from_secret(prerelease_bucket), }, - 'commands': [ - './bin/grabpl upload-cdn --edition {}'.format(edition), + "commands": [ + "./bin/build upload-cdn --edition {}".format(edition), ], } if trigger and ver_mode in ("release-branch", "main"): - step = dict(step, when=trigger) + step = dict(step, when = trigger) return step - -def build_backend_step(edition, ver_mode, variants=None): - variants_str = '' +def build_backend_step(edition, ver_mode, variants = None): + """Build the backend code using the Grafana build tool. + + Args: + edition: controls which edition of the backend is built. + ver_mode: if ver_mode != 'release', pass the DRONE_BUILD_NUMBER environment + variable as the value for the --build-id option. + TODO: is this option actually used by the build-backend subcommand? + variants: a list of variants be passed to the build-backend subcommand + using the --variants option. + Defaults to None. + + Returns: + Drone step. + """ + variants_str = "" if variants: - variants_str = ' --variants {}'.format(','.join(variants)) + variants_str = " --variants {}".format(",".join(variants)) # TODO: Convert number of jobs to percentage - if ver_mode == 'release': + if ver_mode == "release": cmds = [ - './bin/build build-backend --jobs 8 --edition {} ${{DRONE_TAG}}'.format( + "./bin/build build-backend --jobs 8 --edition {} ${{DRONE_TAG}}".format( edition, ), ] else: - build_no = '${DRONE_BUILD_NUMBER}' + build_no = "${DRONE_BUILD_NUMBER}" cmds = [ - './bin/build build-backend --jobs 8 --edition {} --build-id {}{}'.format( - edition, build_no, variants_str, + "./bin/build build-backend --jobs 8 --edition {} --build-id {}{}".format( + edition, + build_no, + variants_str, ), ] return { - 'name': 'build-backend' + enterprise2_suffix(edition), - 'image': build_image, - 'depends_on': [ - 'wire-install', - 'compile-build-cmd', + "name": "build-backend" + enterprise2_suffix(edition), + "image": build_image, + "depends_on": [ + "wire-install", + "compile-build-cmd", ], - 'commands': cmds, + "commands": cmds, } - def build_frontend_step(edition, ver_mode): - build_no = '${DRONE_BUILD_NUMBER}' + """Build the frontend code using the Grafana build tool. + + Args: + edition: controls which edition of the frontend is built. + ver_mode: if ver_mode != 'release', use the DRONE_BUILD_NUMBER environment + variable as a build identifier. + + Returns: + Drone step. + """ + build_no = "${DRONE_BUILD_NUMBER}" # TODO: Use percentage for num jobs - if ver_mode == 'release': + if ver_mode == "release": cmds = [ - './bin/build build-frontend --jobs 8 ' + \ - '--edition {} ${{DRONE_TAG}}'.format(edition), + "./bin/build build-frontend --jobs 8 " + + "--edition {} ${{DRONE_TAG}}".format(edition), ] else: cmds = [ - './bin/build build-frontend --jobs 8 --edition {} '.format(edition) + \ - '--build-id {}'.format(build_no), + "./bin/build build-frontend --jobs 8 --edition {} ".format(edition) + + "--build-id {}".format(build_no), ] return { - 'name': 'build-frontend', - 'image': build_image, - 'environment': { - 'NODE_OPTIONS': '--max_old_space_size=8192', + "name": "build-frontend", + "image": build_image, + "environment": { + "NODE_OPTIONS": "--max_old_space_size=8192", }, - 'depends_on': [ - 'compile-build-cmd', - 'yarn-install', + "depends_on": [ + "compile-build-cmd", + "yarn-install", ], - 'commands': cmds, + "commands": cmds, } - def build_frontend_package_step(edition, ver_mode): - build_no = '${DRONE_BUILD_NUMBER}' + """Build the frontend packages using the Grafana build tool. + + Args: + edition: controls which edition of the frontend is built. + ver_mode: if ver_mode != 'release', use the DRONE_BUILD_NUMBER environment + variable as a build identifier. + + Returns: + Drone step. + """ + build_no = "${DRONE_BUILD_NUMBER}" # TODO: Use percentage for num jobs - if ver_mode == 'release': + if ver_mode == "release": cmds = [ - './bin/build build-frontend-packages --jobs 8 ' + \ - '--edition {} ${{DRONE_TAG}}'.format(edition), + "./bin/build build-frontend-packages --jobs 8 " + + "--edition {} ${{DRONE_TAG}}".format(edition), ] else: cmds = [ - './bin/build build-frontend-packages --jobs 8 --edition {} '.format(edition) + \ - '--build-id {}'.format(build_no), + "./bin/build build-frontend-packages --jobs 8 --edition {} ".format(edition) + + "--build-id {}".format(build_no), ] return { - 'name': 'build-frontend-packages', - 'image': build_image, - 'environment': { - 'NODE_OPTIONS': '--max_old_space_size=8192', + "name": "build-frontend-packages", + "image": build_image, + "environment": { + "NODE_OPTIONS": "--max_old_space_size=8192", }, - 'depends_on': [ - 'compile-build-cmd', - 'yarn-install', + "depends_on": [ + "compile-build-cmd", + "yarn-install", ], - 'commands': cmds, + "commands": cmds, } - def build_plugins_step(edition, ver_mode): - if ver_mode!='pr': + if ver_mode != "pr": env = { - 'GRAFANA_API_KEY': from_secret('grafana_api_key'), + "GRAFANA_API_KEY": from_secret("grafana_api_key"), } else: env = None return { - 'name': 'build-plugins', - 'image': build_image, - 'environment': env, - 'depends_on': [ - 'compile-build-cmd', - 'yarn-install', + "name": "build-plugins", + "image": build_image, + "environment": env, + "depends_on": [ + "compile-build-cmd", + "yarn-install", ], - 'commands': [ + "commands": [ # TODO: Use percentage for num jobs - './bin/build build-plugins --jobs 8 --edition {}'.format(edition), + "./bin/build build-plugins --jobs 8 --edition {}".format(edition), ], } +def test_backend_step(image = build_image): + return { + "name": "test-backend", + "image": image, + "depends_on": [ + "wire-install", + ], + "commands": [ + "go test -tags requires_buildifer -short -covermode=atomic -timeout=5m ./pkg/...", + ], + } -def test_backend_step(edition): - if edition == 'enterprise2': - return { - 'name': 'test-backend' + enterprise2_suffix(edition), - 'image': build_image, - 'depends_on': [ - 'wire-install', - ], - 'commands': [ - 'go test -tags=pro -covermode=atomic -timeout=30m ./pkg/...', - ], - } - else: - return { - 'name': 'test-backend' + enterprise2_suffix(edition), - 'image': build_image, - 'depends_on': [ - 'wire-install', - ], - 'commands': [ - 'go test -short -covermode=atomic -timeout=30m ./pkg/...', - ], - } - - +def windows_test_backend_step(): + step = test_backend_step(image = windows_go_image) + step["failure"] = "ignore" + return step -def test_backend_integration_step(edition): +def test_backend_integration_step(): return { - 'name': 'test-backend-integration', - 'image': build_image, - 'depends_on': [ - 'wire-install', + "name": "test-backend-integration", + "image": build_image, + "depends_on": [ + "wire-install", ], - 'commands': [ - 'go test -run Integration -covermode=atomic -timeout=30m ./pkg/...', + "commands": [ + "go test -run Integration -covermode=atomic -timeout=5m ./pkg/...", ], } -def betterer_frontend_step(edition="oss"): +def betterer_frontend_step(edition = "oss"): + """Run betterer on frontend code. + + Args: + edition: controls whether enterprise code is also included in the source. + Defaults to 'oss'. + + Returns: + Drone step. + """ deps = [] if edition == "enterprise": - deps.extend(['init-enterprise']) - deps.extend(['yarn-install']) + deps.extend(["init-enterprise"]) + deps.extend(["yarn-install"]) return { - 'name': 'betterer-frontend', - 'image': build_image, - 'depends_on': deps, - 'commands': [ - 'yarn betterer ci', + "name": "betterer-frontend", + "image": build_image, + "depends_on": deps, + "commands": [ + "yarn betterer ci", ], - 'failure': 'ignore', } +def test_frontend_step(edition = "oss"): + """Runs tests on frontend code. + Args: + edition: controls whether enterprise code is also included in the source. + Defaults to 'oss'. -def test_frontend_step(edition="oss"): + Returns: + Drone step. + """ deps = [] if edition == "enterprise": - deps.extend(['init-enterprise']) - deps.extend(['yarn-install']) + deps.extend(["init-enterprise"]) + deps.extend(["yarn-install"]) return { - 'name': 'test-frontend', - 'image': build_image, - 'environment': { - 'TEST_MAX_WORKERS': '50%', + "name": "test-frontend", + "image": build_image, + "environment": { + "TEST_MAX_WORKERS": "50%", }, - 'depends_on': deps, - 'commands': [ - 'yarn run ci:test-frontend', + "depends_on": deps, + "commands": [ + "yarn run ci:test-frontend", ], } - def lint_frontend_step(): return { - 'name': 'lint-frontend', - 'image': build_image, - 'environment': { - 'TEST_MAX_WORKERS': '50%', + "name": "lint-frontend", + "image": build_image, + "environment": { + "TEST_MAX_WORKERS": "50%", }, - 'depends_on': [ - 'yarn-install', + "depends_on": [ + "yarn-install", ], - 'commands': [ - 'yarn run prettier:check', - 'yarn run lint', - 'yarn run i18n:compile', # TODO: right place for this? - 'yarn run typecheck', + "commands": [ + "yarn run prettier:check", + "yarn run lint", + "yarn run i18n:compile", # TODO: right place for this? + "yarn run typecheck", ], } +def test_a11y_frontend_step(ver_mode, port = 3001): + """Runs automated accessiblity tests against the frontend. -def test_a11y_frontend_step(ver_mode, edition, port=3001): + Args: + ver_mode: controls whether the step is blocking or just reporting. + If ver_mode == 'pr', the step causes the pipeline to fail. + port: which port to grafana-server is expected to be listening on. + Defaults to 3001. + + Returns: + Drone step. + """ commands = [ - 'yarn wait-on http://$HOST:$PORT', + "yarn wait-on http://$HOST:$PORT", ] - failure = 'ignore' - if ver_mode == 'pr': - commands.extend([ - 'pa11y-ci --config .pa11yci-pr.conf.js', - ]) - failure = 'always' + failure = "ignore" + if ver_mode == "pr": + commands.extend( + [ + "pa11y-ci --config .pa11yci-pr.conf.js", + ], + ) + failure = "always" else: - commands.extend([ - 'pa11y-ci --config .pa11yci.conf.js --json > pa11y-ci-results.json', - ]) + commands.extend( + [ + "pa11y-ci --config .pa11yci.conf.js --json > pa11y-ci-results.json", + ], + ) return { - 'name': 'test-a11y-frontend' + enterprise2_suffix(edition), - 'image': 'grafana/docker-puppeteer:1.1.0', - 'depends_on': [ - 'grafana-server' + enterprise2_suffix(edition), + "name": "test-a11y-frontend", + # TODO which image should be used? + "image": "grafana/docker-puppeteer:1.1.0", + "depends_on": [ + "grafana-server", ], - 'environment': { - 'GRAFANA_MISC_STATS_API_KEY': from_secret('grafana_misc_stats_api_key'), - 'HOST': 'grafana-server' + enterprise2_suffix(edition), - 'PORT': port, + "environment": { + "GRAFANA_MISC_STATS_API_KEY": from_secret("grafana_misc_stats_api_key"), + "HOST": "grafana-server", + "PORT": port, }, - 'failure': failure, - 'commands': commands, + "failure": failure, + "commands": commands, } +def frontend_metrics_step(trigger = None): + """Reports frontend metrics to Grafana Cloud. -def frontend_metrics_step(edition, trigger=None): - if edition in ('enterprise', 'enterprise2'): - return None + Args: + trigger: a Drone trigger for the step. + Defaults to None. + Returns: + Drone step. + """ step = { - 'name': 'publish-frontend-metrics', - 'image': build_image, - 'depends_on': [ - 'test-a11y-frontend' + enterprise2_suffix(edition), + "name": "publish-frontend-metrics", + "image": build_image, + "depends_on": [ + "test-a11y-frontend", ], - 'environment': { - 'GRAFANA_MISC_STATS_API_KEY': from_secret('grafana_misc_stats_api_key'), + "environment": { + "GRAFANA_MISC_STATS_API_KEY": from_secret("grafana_misc_stats_api_key"), }, - 'failure': 'ignore', - 'commands': [ - './scripts/ci-frontend-metrics.sh | ./bin/build publish-metrics $${GRAFANA_MISC_STATS_API_KEY}', + "failure": "ignore", + "commands": [ + "./scripts/ci-frontend-metrics.sh | ./bin/build publish-metrics $${GRAFANA_MISC_STATS_API_KEY}", ], } if trigger: - step = dict(step, when=trigger) + step = dict(step, when = trigger) return step - def codespell_step(): return { - 'name': 'codespell', - 'image': build_image, - 'commands': [ + "name": "codespell", + "image": build_image, + "commands": [ # Important: all words have to be in lowercase, and separated by "\n". 'echo -e "unknwon\nreferer\nerrorstring\neror\niam\nwan" > words_to_ignore.txt', - 'codespell -I words_to_ignore.txt docs/', - 'rm words_to_ignore.txt', + "codespell -I words_to_ignore.txt docs/", + "rm words_to_ignore.txt", ], } +def package_step(edition, ver_mode): + """Packages Grafana with the Grafana build tool. + + Args: + edition: controls which edition of Grafana is packaged. + ver_mode: controls whether the packages are signed for a release. + If ver_mode != 'release', use the DRONE_BUILD_NUMBER environment + variable as a build identifier. -def package_step(edition, ver_mode, include_enterprise2=False, variants=None): + Returns: + Drone step. + """ deps = [ - 'build-plugins', - 'build-backend', - 'build-frontend', - 'build-frontend-packages', + "build-plugins", + "build-backend" + enterprise2_suffix(edition), + "build-frontend", + "build-frontend-packages", ] - if include_enterprise2: - sfx = '-enterprise2' - deps.extend([ - 'build-backend' + sfx, - ]) - variants_str = '' - if variants: - variants_str = ' --variants {}'.format(','.join(variants)) - - if ver_mode in ('main', 'release', 'release-branch'): - sign_args = ' --sign' + if ver_mode in ("main", "release", "release-branch"): + sign_args = " --sign" env = { - 'GRAFANA_API_KEY': from_secret('grafana_api_key'), - 'GPG_PRIV_KEY': from_secret('packages_gpg_private_key'), - 'GPG_PUB_KEY': from_secret('packages_gpg_public_key'), - 'GPG_KEY_PASSWORD': from_secret('packages_gpg_passphrase'), + "GRAFANA_API_KEY": from_secret("grafana_api_key"), + "GPG_PRIV_KEY": from_secret("packages_gpg_private_key"), + "GPG_PUB_KEY": from_secret("packages_gpg_public_key"), + "GPG_KEY_PASSWORD": from_secret("packages_gpg_passphrase"), } - test_args = '' + test_args = "" else: - sign_args = '' + sign_args = "" env = None - test_args = '. scripts/build/gpg-test-vars.sh && ' + + # TODO: env vars no longer needed by build if not signing + test_args = ". scripts/build/gpg-test-vars.sh && " # TODO: Use percentage for jobs - if ver_mode == 'release': + if ver_mode == "release": cmds = [ - '{}./bin/build package --jobs 8 --edition {} '.format(test_args, edition) + \ - '{} ${{DRONE_TAG}}'.format( - sign_args - ), + "{}./bin/build package --jobs 8 --edition {} ".format(test_args, edition) + + "{} ${{DRONE_TAG}}".format(sign_args), ] else: - build_no = '${DRONE_BUILD_NUMBER}' + build_no = "${DRONE_BUILD_NUMBER}" cmds = [ - '{}./bin/build package --jobs 8 --edition {} '.format(test_args, edition) + \ - '--build-id {}{}{}'.format(build_no, variants_str, sign_args), + "{}./bin/build package --jobs 8 --edition {} ".format(test_args, edition) + + "--build-id {}{}".format(build_no, sign_args), ] return { - 'name': 'package' + enterprise2_suffix(edition), - 'image': build_image, - 'depends_on': deps, - 'environment': env, - 'commands': cmds, + "name": "package" + enterprise2_suffix(edition), + "image": build_image, + "depends_on": deps, + "environment": env, + "commands": cmds, } +def grafana_server_step(edition, port = 3001): + """Runs the grafana-server binary as a service. -def grafana_server_step(edition, port=3001): - package_file_pfx = '' - if edition == 'enterprise2': - package_file_pfx = 'grafana' + enterprise2_suffix(edition) - elif edition == 'enterprise': - package_file_pfx = 'grafana-' + edition + Args: + edition: controls which edition of grafana-server to run. + port: port to listen on. + Defaults to 3001. - environment = { - 'PORT': port, - 'ARCH': 'linux-amd64' - } - if package_file_pfx: - environment['RUNDIR'] = 'scripts/grafana-server/tmp-{}'.format(package_file_pfx) + Returns: + Drone step. + """ + environment = {"PORT": port, "ARCH": "linux-amd64"} + if edition == "enterprise": + environment["RUNDIR"] = "scripts/grafana-server/tmp-grafana-enterprise" return { - 'name': 'grafana-server' + enterprise2_suffix(edition), - 'image': build_image, - 'detach': True, - 'depends_on': [ - 'build-plugins', - 'build-backend', - 'build-frontend', - 'build-frontend-packages', + "name": "grafana-server", + "image": build_image, + "detach": True, + "depends_on": [ + "build-plugins", + "build-backend", + "build-frontend", + "build-frontend-packages", ], - 'environment': environment, - 'commands': [ - './scripts/grafana-server/start-server', + "environment": environment, + "commands": [ + "./scripts/grafana-server/start-server", ], } - -def e2e_tests_step(suite, edition, port=3001, tries=None): - cmd = './bin/build e2e-tests --port {} --suite {}'.format(port, suite) +def e2e_tests_step(suite, port = 3001, tries = None): + cmd = "./bin/build e2e-tests --port {} --suite {}".format(port, suite) if tries: - cmd += ' --tries {}'.format(tries) + cmd += " --tries {}".format(tries) return { - 'name': 'end-to-end-tests-{}'.format(suite) + enterprise2_suffix(edition), - 'image': 'cypress/included:9.5.1-node16.14.0-slim-chrome99-ff97', - 'depends_on': [ - 'grafana-server', + "name": "end-to-end-tests-{}".format(suite), + "image": "cypress/included:9.5.1-node16.14.0-slim-chrome99-ff97", + "depends_on": [ + "grafana-server", ], - 'environment': { - 'HOST': 'grafana-server' + enterprise2_suffix(edition), + "environment": { + "HOST": "grafana-server", }, - 'commands': [ - 'apt-get install -y netcat', + "commands": [ + "apt-get install -y netcat", cmd, ], } +def cloud_plugins_e2e_tests_step(suite, cloud, trigger = None): + """Run cloud plugins end-to-end tests. + + Args: + suite: affects the pipeline name. + TODO: check if this actually affects step behavior. + cloud: used to determine cloud provider specific tests. + trigger: a Drone trigger for the step. + Defaults to None. + + Returns: + Drone step. + """ + environment = {} + when = {} + if trigger: + when = trigger + if cloud == "azure": + environment = { + "CYPRESS_CI": "true", + "HOST": "grafana-server", + "GITHUB_TOKEN": from_secret("github_token_pr"), + "AZURE_SP_APP_ID": from_secret("azure_sp_app_id"), + "AZURE_SP_PASSWORD": from_secret("azure_sp_app_pw"), + "AZURE_TENANT": from_secret("azure_tenant"), + } + when = dict( + when, + paths = { + "include": [ + "pkg/tsdb/azuremonitor/**", + "public/app/plugins/datasource/grafana-azure-monitor-datasource/**", + "e2e/cloud-plugins-suite/azure-monitor.spec.ts", + ], + }, + ) + branch = "${DRONE_SOURCE_BRANCH}".replace("/", "-") + step = { + "name": "end-to-end-tests-{}-{}".format(suite, cloud), + "image": "us-docker.pkg.dev/grafanalabs-dev/cloud-data-sources/e2e:latest", + "depends_on": [ + "grafana-server", + ], + "environment": environment, + "commands": ["cd /", "./cpp-e2e/scripts/ci-run.sh {} {}".format(cloud, branch)], + } + step = dict(step, when = when) + return step def build_docs_website_step(): return { - 'name': 'build-docs-website', + "name": "build-docs-website", # Use latest revision here, since we want to catch if it breaks - 'image': 'grafana/docs-base:latest', - 'commands': [ - 'mkdir -p /hugo/content/docs/grafana', - 'cp -r docs/sources/* /hugo/content/docs/grafana/latest/', - 'cd /hugo && make prod', + "image": "grafana/docs-base:latest", + "commands": [ + "mkdir -p /hugo/content/docs/grafana", + "cp -r docs/sources/* /hugo/content/docs/grafana/latest/", + "cd /hugo && make prod", ], } - -def copy_packages_for_docker_step(): +def copy_packages_for_docker_step(edition = None): return { - 'name': 'copy-packages-for-docker', - 'image': build_image, - 'depends_on': [ - 'package', + "name": "copy-packages-for-docker", + "image": build_image, + "depends_on": [ + "package" + enterprise2_suffix(edition), ], - 'commands': [ - 'ls dist/*.tar.gz*', - 'cp dist/*.tar.gz* packaging/docker/', + "commands": [ + "ls dist/*.tar.gz*", + "cp dist/*.tar.gz* packaging/docker/", ], } - -def build_docker_images_step(edition, ver_mode, archs=None, ubuntu=False, publish=False): - cmd = './bin/build build-docker --edition {}'.format(edition) +def build_docker_images_step(edition, archs = None, ubuntu = False, publish = False): + """Build Docker images using the Grafana build tool. + + Args: + edition: controls which repository the image is published to. + archs: a list of architectures to build the image for. + Defaults to None. + ubuntu: controls whether the final image is built from an Ubuntu base image. + Defaults to False. + publish: controls whether the built image is saved to a pre-release repository. + Defaults to False. + + Returns: + Drone step. + """ + cmd = "./bin/build build-docker --edition {}".format(edition) if publish: - cmd += ' --shouldSave' + cmd += " --shouldSave" - ubuntu_sfx = '' + ubuntu_sfx = "" if ubuntu: - ubuntu_sfx = '-ubuntu' - cmd += ' --ubuntu' + ubuntu_sfx = "-ubuntu" + cmd += " --ubuntu" if archs: - cmd += ' -archs {}'.format(','.join(archs)) + cmd += " -archs {}".format(",".join(archs)) + + environment = { + "GCP_KEY": from_secret("gcp_key"), + } + + if edition == "enterprise2": + environment.update( + {"DOCKER_ENTERPRISE2_REPO": from_secret("docker_enterprise2_repo")}, + ) return { - 'name': 'build-docker-images' + ubuntu_sfx, - 'image': 'google/cloud-sdk', - 'depends_on': [ - 'copy-packages-for-docker', - 'compile-build-cmd', - ], - 'commands': [ - cmd + "name": "build-docker-images" + ubuntu_sfx, + "image": "google/cloud-sdk", + "depends_on": [ + "copy-packages-for-docker", + "compile-build-cmd", ], - 'volumes': [{ - 'name': 'docker', - 'path': '/var/run/docker.sock' - }], - 'environment': { - 'GCP_KEY': from_secret('gcp_key'), - }, + "commands": [cmd], + "volumes": [{"name": "docker", "path": "/var/run/docker.sock"}], + "environment": environment, } def fetch_images_step(edition): return { - 'name': 'fetch-images-{}'.format(edition), - 'image': 'google/cloud-sdk', - 'environment': { - 'GCP_KEY': from_secret('gcp_key'), - 'DOCKER_USER': from_secret('docker_username'), - 'DOCKER_PASSWORD': from_secret('docker_password'), + "name": "fetch-images-{}".format(edition), + "image": "google/cloud-sdk", + "environment": { + "GCP_KEY": from_secret("gcp_key"), + "DOCKER_USER": from_secret("docker_username"), + "DOCKER_PASSWORD": from_secret("docker_password"), + "DOCKER_ENTERPRISE2_REPO": from_secret("docker_enterprise2_repo"), }, - 'commands': ['./bin/build artifacts docker fetch --edition {}'.format(edition)], - 'depends_on': ['compile-build-cmd'], - 'volumes': [{ - 'name': 'docker', - 'path': '/var/run/docker.sock' - }], + "commands": ["./bin/build artifacts docker fetch --edition {}".format(edition)], + "depends_on": ["compile-build-cmd"], + "volumes": [{"name": "docker", "path": "/var/run/docker.sock"}], } - -def publish_images_step(edition, ver_mode, mode, docker_repo, trigger=None): - if mode == 'security': - mode = '--{} '.format(mode) +def publish_images_step(edition, ver_mode, mode, docker_repo, trigger = None): + """Generates a step for publishing public Docker images with grabpl. + + Args: + edition: controls which version of an image is fetched in the case of a release. + It also controls which publishing implementation is used. + ver_mode: controls whether the image needs to be built or retrieved from a previous build. + If ver_mode == 'release', the previously built image is fetched instead of being built again. + mode: uses to control the publishing of security images when mode == 'security'. + docker_repo: the Docker image name. + It is combined with the 'grafana/' library prefix. + trigger: a Drone trigger for the pipeline. + Defaults to None. + + Returns: + Drone step. + """ + name = docker_repo + docker_repo = "grafana/{}".format(docker_repo) + if mode == "security": + mode = "--{} ".format(mode) else: - mode = '' + mode = "" - cmd = './bin/grabpl artifacts docker publish {}--dockerhub-repo {}'.format( - mode, docker_repo) + environment = { + "GCP_KEY": from_secret("gcp_key"), + "DOCKER_USER": from_secret("docker_username"), + "DOCKER_PASSWORD": from_secret("docker_password"), + } - if ver_mode == 'release': - deps = ['fetch-images-{}'.format(edition)] - cmd += ' --version-tag ${TAG}' - else: - deps = ['build-docker-images', 'build-docker-images-ubuntu'] + cmd = "./bin/grabpl artifacts docker publish {}--dockerhub-repo {}".format( + mode, + docker_repo, + ) + + deps = ["build-docker-images", "build-docker-images-ubuntu"] + if ver_mode == "release": + deps = ["fetch-images-{}".format(edition)] + cmd += " --version-tag ${DRONE_TAG}" + + if edition == "enterprise2": + name = edition + docker_repo = "$${DOCKER_ENTERPRISE2_REPO}" + environment.update( + { + "GCP_KEY": from_secret("gcp_key_hg"), + "DOCKER_ENTERPRISE2_REPO": from_secret("docker_enterprise2_repo"), + }, + ) + cmd = "./bin/build artifacts docker publish-enterprise2 --dockerhub-repo {}".format( + docker_repo, + ) step = { - 'name': 'publish-images-{}'.format(docker_repo), - 'image': 'google/cloud-sdk', - 'environment': { - 'GCP_KEY': from_secret('gcp_key'), - 'DOCKER_USER': from_secret('docker_username'), - 'DOCKER_PASSWORD': from_secret('docker_password'), - }, - 'commands': [cmd], - 'depends_on': deps, - 'volumes': [{ - 'name': 'docker', - 'path': '/var/run/docker.sock' - }], + "name": "publish-images-{}".format(name), + "image": "google/cloud-sdk", + "environment": environment, + "commands": [cmd], + "depends_on": deps, + "volumes": [{"name": "docker", "path": "/var/run/docker.sock"}], } if trigger and ver_mode in ("release-branch", "main"): - step = dict(step, when=trigger) + step = dict(step, when = trigger) return step - -def postgres_integration_tests_step(edition, ver_mode): +def postgres_integration_tests_step(): cmds = [ - 'apt-get update', - 'apt-get install -yq postgresql-client', - 'dockerize -wait tcp://postgres:5432 -timeout 120s', - 'psql -p 5432 -h postgres -U grafanatest -d grafanatest -f ' + - 'devenv/docker/blocks/postgres_tests/setup.sql', - # Make sure that we don't use cached results for another database - 'go clean -testcache', - "go list './pkg/...' | xargs -I {} sh -c 'go test -run Integration -covermode=atomic -timeout=30m {}'", - ] + "apt-get update", + "apt-get install -yq postgresql-client", + "dockerize -wait tcp://postgres:5432 -timeout 120s", + "psql -p 5432 -h postgres -U grafanatest -d grafanatest -f " + + "devenv/docker/blocks/postgres_tests/setup.sql", + # Make sure that we don't use cached results for another database + "go clean -testcache", + "go list './pkg/...' | xargs -I {} sh -c 'go test -run Integration -covermode=atomic -timeout=5m {}'", + ] return { - 'name': 'postgres-integration-tests', - 'image': build_image, - 'depends_on': ['wire-install'], - 'environment': { - 'PGPASSWORD': 'grafanatest', - 'GRAFANA_TEST_DB': 'postgres', - 'POSTGRES_HOST': 'postgres', + "name": "postgres-integration-tests", + "image": build_image, + "depends_on": ["wire-install"], + "environment": { + "PGPASSWORD": "grafanatest", + "GRAFANA_TEST_DB": "postgres", + "POSTGRES_HOST": "postgres", }, - 'commands': cmds, + "commands": cmds, } - -def mysql_integration_tests_step(edition, ver_mode): +def mysql_integration_tests_step(): cmds = [ - 'apt-get update', - 'apt-get install -yq default-mysql-client', - 'dockerize -wait tcp://mysql:3306 -timeout 120s', - 'cat devenv/docker/blocks/mysql_tests/setup.sql | mysql -h mysql -P 3306 -u root -prootpass', - # Make sure that we don't use cached results for another database - 'go clean -testcache', - "go list './pkg/...' | xargs -I {} sh -c 'go test -run Integration -covermode=atomic -timeout=30m {}'", - ] + "apt-get update", + "apt-get install -yq default-mysql-client", + "dockerize -wait tcp://mysql:3306 -timeout 120s", + "cat devenv/docker/blocks/mysql_tests/setup.sql | mysql -h mysql -P 3306 -u root -prootpass", + # Make sure that we don't use cached results for another database + "go clean -testcache", + "go list './pkg/...' | xargs -I {} sh -c 'go test -run Integration -covermode=atomic -timeout=5m {}'", + ] return { - 'name': 'mysql-integration-tests', - 'image': build_image, - 'depends_on': ['wire-install'], - 'environment': { - 'GRAFANA_TEST_DB': 'mysql', - 'MYSQL_HOST': 'mysql', + "name": "mysql-integration-tests", + "image": build_image, + "depends_on": ["wire-install"], + "environment": { + "GRAFANA_TEST_DB": "mysql", + "MYSQL_HOST": "mysql", }, - 'commands': cmds, + "commands": cmds, } - def redis_integration_tests_step(): return { - 'name': 'redis-integration-tests', - 'image': build_image, - 'depends_on': ['wire-install'], - 'environment': { - 'REDIS_URL': 'redis://redis:6379/0', + "name": "redis-integration-tests", + "image": build_image, + "depends_on": ["wire-install"], + "environment": { + "REDIS_URL": "redis://redis:6379/0", }, - 'commands': [ - 'dockerize -wait tcp://redis:6379/0 -timeout 120s', - './bin/grabpl integration-tests', + "commands": [ + "dockerize -wait tcp://redis:6379/0 -timeout 120s", + "go clean -testcache", + "go list './pkg/...' | xargs -I {} sh -c 'go test -run Integration -covermode=atomic -timeout=5m {}'", ], } - def memcached_integration_tests_step(): return { - 'name': 'memcached-integration-tests', - 'image': build_image, - 'depends_on': ['wire-install'], - 'environment': { - 'MEMCACHED_HOSTS': 'memcached:11211', + "name": "memcached-integration-tests", + "image": build_image, + "depends_on": ["wire-install"], + "environment": { + "MEMCACHED_HOSTS": "memcached:11211", }, - 'commands': [ - 'dockerize -wait tcp://memcached:11211 -timeout 120s', - './bin/grabpl integration-tests', + "commands": [ + "dockerize -wait tcp://memcached:11211 -timeout 120s", + "go clean -testcache", + "go list './pkg/...' | xargs -I {} sh -c 'go test -run Integration -covermode=atomic -timeout=5m {}'", ], } +def release_canary_npm_packages_step(trigger = None): + """Releases canary NPM packages. -def release_canary_npm_packages_step(edition, trigger=None): - if edition in ('enterprise', 'enterprise2'): - return None + Args: + trigger: a Drone trigger for the step. + Defaults to None. + Returns: + Drone step. + """ step = { - 'name': 'release-canary-npm-packages', - 'image': build_image, - 'depends_on': end_to_end_tests_deps(edition), - 'environment': { - 'NPM_TOKEN': from_secret('npm_token'), + "name": "release-canary-npm-packages", + "image": build_image, + "depends_on": end_to_end_tests_deps(), + "environment": { + "NPM_TOKEN": from_secret("npm_token"), }, - 'commands': [ - './scripts/circle-release-canary-packages.sh', + "commands": [ + "./scripts/circle-release-canary-packages.sh", ], } if trigger: - step = dict(step, when=trigger) + step = dict(step, when = trigger) return step - def enterprise2_suffix(edition): - if edition == 'enterprise2': - return '-{}'.format(edition) - return '' - - -def upload_packages_step(edition, ver_mode, trigger=None): - if ver_mode == 'main' and edition in ('enterprise', 'enterprise2'): - return None - - deps = [] - if edition in 'enterprise2' or not end_to_end_tests_deps(edition): - deps.extend([ - 'package' + enterprise2_suffix(edition), - ]) - else: - deps.extend(end_to_end_tests_deps(edition)) - + if edition == "enterprise2": + return "-{}".format(edition) + return "" + +def upload_packages_step(edition, ver_mode, trigger = None): + """Upload packages to object storage. + + Args: + edition: controls which edition of Grafana packages to upload. + ver_mode: when ver_mode == 'main', inhibit upload of enterprise + edition packages when executed. + trigger: a Drone trigger for the step. + Defaults to None. + + Returns: + Drone step. + """ step = { - 'name': 'upload-packages' + enterprise2_suffix(edition), - 'image': publish_image, - 'depends_on': deps, - 'environment': { - 'GCP_KEY': from_secret('gcp_key'), - 'PRERELEASE_BUCKET': from_secret('prerelease_bucket'), + "name": "upload-packages" + enterprise2_suffix(edition), + "image": publish_image, + "depends_on": end_to_end_tests_deps(), + "environment": { + "GCP_KEY": from_secret("gcp_key"), + "PRERELEASE_BUCKET": from_secret("prerelease_bucket"), }, - 'commands': ['./bin/grabpl upload-packages --edition {}'.format(edition),], + "commands": [ + "./bin/build upload-packages --edition {}".format(edition), + ], } if trigger and ver_mode in ("release-branch", "main"): - step = dict(step, when=trigger) + step = dict(step, when = trigger) return step - -def publish_packages_step(edition, ver_mode): - if ver_mode == 'release': - cmd = './bin/build publish packages --edition {} --gcp-key /tmp/gcpkey.json ${{DRONE_TAG}}'.format( - edition, - ) - elif ver_mode == 'main': - build_no = '${DRONE_BUILD_NUMBER}' - cmd = './bin/build publish packages --edition {} --gcp-key /tmp/gcpkey.json --build-id {}'.format( - edition, build_no, - ) - else: - fail('Unexpected version mode {}'.format(ver_mode)) - - return { - 'name': 'publish-packages-{}'.format(edition), - 'image': publish_image, - 'depends_on': [ - 'compile-build-cmd', - ], - 'environment': { - 'GRAFANA_COM_API_KEY': from_secret('grafana_api_key'), - 'GCP_KEY': from_secret('gcp_key'), - 'GPG_PRIV_KEY': from_secret('packages_gpg_private_key'), - 'GPG_PUB_KEY': from_secret('packages_gpg_public_key'), - 'GPG_KEY_PASSWORD': from_secret('packages_gpg_passphrase'), - }, - 'commands': [ - cmd, - ], - } - def publish_grafanacom_step(edition, ver_mode): - if ver_mode == 'release': - cmd = './bin/build publish grafana-com --edition {} ${{DRONE_TAG}}'.format( + """Publishes Grafana packages to grafana.com. + + Args: + edition: controls which edition of Grafana to publish to. + ver_mode: if ver_mode == 'main', pass the DRONE_BUILD_NUMBER environment + variable as the value for the --build-id option. + TODO: is this actually used by the grafanacom subcommand? I think it might + just use the environment varaiable directly. + + Returns: + Drone step. + """ + if ver_mode == "release": + cmd = "./bin/build publish grafana-com --edition {} ${{DRONE_TAG}}".format( edition, ) - elif ver_mode == 'main': - build_no = '${DRONE_BUILD_NUMBER}' - cmd = './bin/build publish grafana-com --edition {} --build-id {}'.format( - edition, build_no, + elif ver_mode == "main": + build_no = "${DRONE_BUILD_NUMBER}" + cmd = "./bin/build publish grafana-com --edition {} --build-id {}".format( + edition, + build_no, ) else: - fail('Unexpected version mode {}'.format(ver_mode)) + fail("Unexpected version mode {}".format(ver_mode)) return { - 'name': 'publish-grafanacom-{}'.format(edition), - 'image': publish_image, - 'depends_on': [ - 'publish-packages-{}'.format(edition), + "name": "publish-grafanacom-{}".format(edition), + "image": publish_image, + "depends_on": [ + "publish-linux-packages-deb", + "publish-linux-packages-rpm", ], - 'environment': { - 'GRAFANA_COM_API_KEY': from_secret('grafana_api_key'), - 'GCP_KEY': from_secret('gcp_key'), + "environment": { + "GRAFANA_COM_API_KEY": from_secret("grafana_api_key"), + "GCP_KEY": from_secret("gcp_key"), }, - 'commands': [ + "commands": [ cmd, ], } -def publish_linux_packages_step(edition, package_manager='deb'): +def publish_linux_packages_step(edition, package_manager = "deb"): return { - 'name': 'publish-linux-packages-{}'.format(package_manager), + "name": "publish-linux-packages-{}".format(package_manager), # See https://github.com/grafana/deployment_tools/blob/master/docker/package-publish/README.md for docs on that image - 'image': 'us.gcr.io/kubernetes-dev/package-publish:latest', - 'depends_on': [ - 'grabpl' - ], - 'privileged': True, - 'failure': 'ignore', # While we're testing it - 'settings': { - 'access_key_id': from_secret('packages_access_key_id'), - 'secret_access_key': from_secret('packages_secret_access_key'), - 'service_account_json': from_secret('packages_service_account'), - 'target_bucket': 'grafana-packages', - 'deb_distribution': 'auto', - 'gpg_passphrase': from_secret('packages_gpg_passphrase'), - 'gpg_public_key': from_secret('packages_gpg_public_key'), - 'gpg_private_key': from_secret('packages_gpg_private_key'), - 'package_path': 'gs://grafana-prerelease/artifacts/downloads/*${{DRONE_TAG}}/{}/**.{}'.format(edition, package_manager) - } + "image": "us.gcr.io/kubernetes-dev/package-publish:latest", + "depends_on": ["compile-build-cmd"], + "privileged": True, + "settings": { + "access_key_id": from_secret("packages_access_key_id"), + "secret_access_key": from_secret("packages_secret_access_key"), + "service_account_json": from_secret("packages_service_account"), + "target_bucket": "grafana-packages", + "deb_distribution": "auto", + "gpg_passphrase": from_secret("packages_gpg_passphrase"), + "gpg_public_key": from_secret("packages_gpg_public_key"), + "gpg_private_key": from_secret("packages_gpg_private_key"), + "package_path": "gs://grafana-prerelease/artifacts/downloads/*${{DRONE_TAG}}/{}/**.{}".format( + edition, + package_manager, + ), + }, } - def get_windows_steps(edition, ver_mode): - init_cmds = [] - sfx = '' - if edition in ('enterprise', 'enterprise2'): - sfx = '-{}'.format(edition) - else: - init_cmds.extend([ - '$$ProgressPreference = "SilentlyContinue"', - 'Invoke-WebRequest https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/{}/windows/grabpl.exe -OutFile grabpl.exe'.format( - grabpl_version), - ]) + """Generate the list of Windows steps. + + Args: + edition: used to differentiate steps for different Grafana editions. + ver_mode: used to differentiate steps for different version modes. + + Returns: + List of Drone steps. + """ steps = [ - { - 'name': 'windows-init', - 'image': wix_image, - 'commands': init_cmds, - }, + identify_runner_step("windows"), ] - if (ver_mode == 'main' and (edition not in ('enterprise', 'enterprise2'))) or ver_mode in ( - 'release', 'release-branch', - ): - bucket = '%PRERELEASE_BUCKET%/artifacts/downloads' - if ver_mode == 'release': - ver_part = '${DRONE_TAG}' - dir = 'release' - else: - dir = 'main' - bucket = 'grafana-downloads' - build_no = 'DRONE_BUILD_NUMBER' - ver_part = '--build-id $$env:{}'.format(build_no) - installer_commands = [ - '$$gcpKey = $$env:GCP_KEY', - '[System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($$gcpKey)) > gcpkey.json', - # gcloud fails to read the file unless converted with dos2unix - 'dos2unix gcpkey.json', - 'gcloud auth activate-service-account --key-file=gcpkey.json', - 'rm gcpkey.json', - 'cp C:\\App\\nssm-2.24.zip .', - ] - if (ver_mode == 'main' and (edition not in ('enterprise', 'enterprise2'))) or ver_mode in ( - 'release', - ): - installer_commands.extend([ - '.\\grabpl.exe windows-installer --edition {} {}'.format(edition, ver_part), - '$$fname = ((Get-Childitem grafana*.msi -name) -split "`n")[0]', - ]) - if ver_mode == 'main': - installer_commands.extend([ - 'gsutil cp $$fname gs://{}/{}/{}/'.format(bucket, edition, dir), - 'gsutil cp "$$fname.sha256" gs://{}/{}/{}/'.format(bucket, edition, dir), - ]) - else: - installer_commands.extend([ - 'gsutil cp $$fname gs://{}/{}/{}/{}/'.format(bucket, ver_part, edition, dir), - 'gsutil cp "$$fname.sha256" gs://{}/{}/{}/{}/'.format(bucket, ver_part, edition, dir), - ]) - steps.append({ - 'name': 'build-windows-installer', - 'image': wix_image, - 'depends_on': [ - 'windows-init', - ], - 'environment': { - 'GCP_KEY': from_secret('gcp_key'), - 'PRERELEASE_BUCKET': from_secret(prerelease_bucket), - 'GITHUB_TOKEN': from_secret('github_token') - }, - 'commands': installer_commands, - }) - - if edition in ('enterprise', 'enterprise2'): - if ver_mode == 'release': - committish = '${DRONE_TAG}' - elif ver_mode == 'release-branch': - committish = '$$env:DRONE_BRANCH' + + if edition in ("enterprise", "enterprise2"): + if ver_mode == "release": + source = "${DRONE_TAG}" + elif ver_mode == "release-branch": + source = "$$env:DRONE_BRANCH" else: - committish = '$$env:DRONE_COMMIT' + source = "$$env:DRONE_COMMIT" + # For enterprise, we have to clone both OSS and enterprise and merge the latter into the former - download_grabpl_step_cmds = [ + download_grabpl_cmds = [ '$$ProgressPreference = "SilentlyContinue"', - 'Invoke-WebRequest https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/{}/windows/grabpl.exe -OutFile grabpl.exe'.format( - grabpl_version), + "Invoke-WebRequest https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/{}/windows/grabpl.exe -OutFile grabpl.exe".format( + grabpl_version, + ), ] + clone_cmds = [ 'git clone "https://$$env:GITHUB_TOKEN@github.com/grafana/grafana-enterprise.git"', + "cd grafana-enterprise", + "git checkout {}".format(source), ] - clone_cmds.extend([ - 'cd grafana-enterprise', - 'git checkout {}'.format(committish), - ]) - steps.insert(0, { - 'name': 'clone', - 'image': wix_image, - 'environment': { - 'GITHUB_TOKEN': from_secret(github_token), - }, - 'commands': download_grabpl_step_cmds + clone_cmds, - }) - steps[1]['depends_on'] = [ - 'clone', - ] - steps[1]['commands'].extend([ + + init_cmds = [ # Need to move grafana-enterprise out of the way, so directory is empty and can be cloned into - 'cp -r grafana-enterprise C:\\App\\grafana-enterprise', - 'rm -r -force grafana-enterprise', - 'cp grabpl.exe C:\\App\\grabpl.exe', - 'rm -force grabpl.exe', - 'C:\\App\\grabpl.exe init-enterprise --github-token $$env:GITHUB_TOKEN C:\\App\\grafana-enterprise', - 'cp C:\\App\\grabpl.exe grabpl.exe', - ]) - if 'environment' in steps[1]: - steps[1]['environment'] + {'GITHUB_TOKEN': from_secret(github_token)} + "cp -r grafana-enterprise C:\\App\\grafana-enterprise", + "rm -r -force grafana-enterprise", + "cp grabpl.exe C:\\App\\grabpl.exe", + "rm -force grabpl.exe", + "C:\\App\\grabpl.exe init-enterprise --github-token $$env:GITHUB_TOKEN C:\\App\\grafana-enterprise {}".format(source), + "cp C:\\App\\grabpl.exe grabpl.exe", + ] + + steps.extend( + [ + { + "name": "clone", + "image": wix_image, + "environment": { + "GITHUB_TOKEN": from_secret("github_token"), + }, + "commands": download_grabpl_cmds + clone_cmds, + }, + { + "name": "windows-init", + "image": wix_image, + "commands": init_cmds, + "depends_on": ["clone"], + "environment": {"GITHUB_TOKEN": from_secret("github_token")}, + }, + ], + ) + else: + init_cmds = [ + '$$ProgressPreference = "SilentlyContinue"', + "Invoke-WebRequest https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/{}/windows/grabpl.exe -OutFile grabpl.exe".format( + grabpl_version, + ), + ] + + steps.extend( + [ + { + "name": "windows-init", + "image": wix_image, + "commands": init_cmds, + }, + ], + ) + + # TODO: Run windows backend tests + + if ( + ver_mode == "main" and (edition not in ("enterprise", "enterprise2")) + ) or ver_mode in ( + "release", + "release-branch", + ): + bucket = "%PRERELEASE_BUCKET%/artifacts/downloads" + if ver_mode == "release": + ver_part = "${DRONE_TAG}" + dir = "release" else: - steps[1]['environment'] = {'GITHUB_TOKEN': from_secret(github_token)} + dir = "main" + bucket = "grafana-downloads" + build_no = "DRONE_BUILD_NUMBER" + ver_part = "--build-id $$env:{}".format(build_no) + installer_commands = [ + "$$gcpKey = $$env:GCP_KEY", + "[System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($$gcpKey)) > gcpkey.json", + # gcloud fails to read the file unless converted with dos2unix + "dos2unix gcpkey.json", + "gcloud auth activate-service-account --key-file=gcpkey.json", + "rm gcpkey.json", + "cp C:\\App\\nssm-2.24.zip .", + ] + if ( + ver_mode == "main" and (edition not in ("enterprise", "enterprise2")) + ) or ver_mode in ("release",): + installer_commands.extend( + [ + ".\\grabpl.exe windows-installer --edition {} {}".format( + edition, + ver_part, + ), + '$$fname = ((Get-Childitem grafana*.msi -name) -split "`n")[0]', + ], + ) + if ver_mode == "main": + installer_commands.extend( + [ + "gsutil cp $$fname gs://{}/{}/{}/".format(bucket, edition, dir), + 'gsutil cp "$$fname.sha256" gs://{}/{}/{}/'.format( + bucket, + edition, + dir, + ), + ], + ) + else: + installer_commands.extend( + [ + "gsutil cp $$fname gs://{}/{}/{}/{}/".format( + bucket, + ver_part, + edition, + dir, + ), + 'gsutil cp "$$fname.sha256" gs://{}/{}/{}/{}/'.format( + bucket, + ver_part, + edition, + dir, + ), + ], + ) + steps.append( + { + "name": "build-windows-installer", + "image": wix_image, + "depends_on": [ + "windows-init", + ], + "environment": { + "GCP_KEY": from_secret("gcp_key"), + "PRERELEASE_BUCKET": from_secret(prerelease_bucket), + "GITHUB_TOKEN": from_secret("github_token"), + }, + "commands": installer_commands, + }, + ) return steps -def verify_gen_cue_step(edition): - deps = [] - if edition in ('enterprise', 'enterprise2'): - deps.extend(['init-enterprise']) +def verify_gen_cue_step(): return { - 'name': 'verify-gen-cue', - 'image': build_image, - 'depends_on': deps, - 'commands': [ - '# It is required that code generated from Thema/CUE be committed and in sync with its inputs.', - '# The following command will fail if running code generators produces any diff in output.', - 'CODEGEN_VERIFY=1 make gen-cue', + "name": "verify-gen-cue", + "image": build_image, + "depends_on": [], + "commands": [ + "# It is required that code generated from Thema/CUE be committed and in sync with its inputs.", + "# The following command will fail if running code generators produces any diff in output.", + "CODEGEN_VERIFY=1 make gen-cue", ], } def trigger_test_release(): return { - 'name': 'trigger-test-release', - 'image': build_image, - 'environment': { - 'GITHUB_TOKEN': from_secret('github_token'), - 'DOWNSTREAM_REPO': from_secret('downstream'), - 'TEST_TAG': 'v0.0.0-test', + "name": "trigger-test-release", + "image": build_image, + "environment": { + "GITHUB_TOKEN": from_secret("github_token_pr"), + "TEST_TAG": "v0.0.0-test", }, - 'commands': [ + "commands": [ 'git clone "https://$${GITHUB_TOKEN}@github.com/grafana/grafana-enterprise.git" --depth=1', - 'cd grafana-enterprise', - 'git fetch origin "refs/tags/*:refs/tags/*"', - 'git tag -d $${TEST_TAG} && git push --delete origin $${TEST_TAG} && git tag $${TEST_TAG} && git push origin $${TEST_TAG}', - 'cd -', - 'git fetch origin "refs/tags/*:refs/tags/*"', - 'git remote add downstream https://$${GITHUB_TOKEN}@github.com/grafana/$${DOWNSTREAM_REPO}.git', - 'git tag -d $${TEST_TAG} && git push --delete downstream --quiet $${TEST_TAG} && git tag $${TEST_TAG} && git push downstream $${TEST_TAG} --quiet', + "cd grafana-enterprise", + 'git fetch origin "refs/tags/*:refs/tags/*" --quiet', + "if git show-ref --tags $${TEST_TAG} --quiet; then git tag -d $${TEST_TAG} && git push --delete origin $${TEST_TAG}; fi", + "git tag $${TEST_TAG} && git push origin $${TEST_TAG}", + "cd -", + 'git fetch https://$${GITHUB_TOKEN}@github.com/grafana/grafana.git "refs/tags/*:refs/tags/*" --quiet && git fetch --quiet', + "if git show-ref --tags $${TEST_TAG} --quiet; then git tag -d $${TEST_TAG} && git push --delete https://$${GITHUB_TOKEN}@github.com/grafana/grafana.git $${TEST_TAG}; fi", + "git tag $${TEST_TAG} && git push https://$${GITHUB_TOKEN}@github.com/grafana/grafana.git $${TEST_TAG}", ], - 'failure': 'ignore', - 'when': { - 'paths': { - 'include': [ - '.drone.yml', - 'pkg/build/**', - ] + "failure": "ignore", + "when": { + "paths": { + "include": [ + ".drone.yml", + "pkg/build/**", + ], }, - 'repo': [ - 'grafana/grafana', - ] - } + "repo": [ + "grafana/grafana", + ], + }, } def artifacts_page_step(): return { - 'name': 'artifacts-page', - 'image': build_image, - 'depends_on': [ - 'grabpl', + "name": "artifacts-page", + "image": build_image, + "depends_on": [ + "compile-build-cmd", ], - 'environment': { - 'GCP_KEY': from_secret('gcp_key'), + "environment": { + "GCP_KEY": from_secret("gcp_key"), }, - 'commands': [ - './bin/grabpl artifacts-page', + "commands": [ + "./bin/build artifacts-page", ], } -def end_to_end_tests_deps(edition): - if disable_tests: - return [] +def end_to_end_tests_deps(): return [ - 'end-to-end-tests-dashboards-suite' + enterprise2_suffix(edition), - 'end-to-end-tests-panels-suite' + enterprise2_suffix(edition), - 'end-to-end-tests-smoke-tests-suite' + enterprise2_suffix(edition), - 'end-to-end-tests-various-suite' + enterprise2_suffix(edition), + "end-to-end-tests-dashboards-suite", + "end-to-end-tests-panels-suite", + "end-to-end-tests-smoke-tests-suite", + "end-to-end-tests-various-suite", ] -def compile_build_cmd(edition='oss'): +def compile_build_cmd(edition = "oss"): dependencies = [] - if edition in ('enterprise', 'enterprise2'): - dependencies = ['init-enterprise',] + if edition in ("enterprise", "enterprise2"): + dependencies = [ + "init-enterprise", + ] return { - 'name': 'compile-build-cmd', - 'image': go_image, - 'commands': [ + "name": "compile-build-cmd", + "image": go_image, + "commands": [ "go build -o ./bin/build -ldflags '-extldflags -static' ./pkg/build/cmd", ], - 'depends_on': dependencies, - 'environment': { - 'CGO_ENABLED': 0, - }, -} + "depends_on": dependencies, + "environment": { + "CGO_ENABLED": 0, + }, + } def get_trigger_storybook(ver_mode): - trigger_storybook = '' - if ver_mode == 'release': - trigger_storybook = { - 'event': ['tag'] - } + """Generate a Drone trigger for UI changes that affect the Grafana UI storybook. + + Args: + ver_mode: affects whether the trigger is event tags or changed files. + + Returns: + Drone trigger. + """ + trigger_storybook = "" + if ver_mode == "release": + trigger_storybook = {"event": ["tag"]} else: trigger_storybook = { - 'paths': { - 'include': [ - 'packages/grafana-ui/**', + "paths": { + "include": [ + "packages/grafana-ui/**", ], - } + }, } return trigger_storybook diff --git a/scripts/drone/utils/utils.star b/scripts/drone/utils/utils.star index eef792b9207e9..82af7ca960465 100644 --- a/scripts/drone/utils/utils.star +++ b/scripts/drone/utils/utils.star @@ -1,91 +1,140 @@ +""" +This module contains utility functions for generating Drone pipelines. +""" + load( - 'scripts/drone/steps/lib.star', - 'download_grabpl_step', - 'slack_step', + "scripts/drone/steps/lib.star", + "slack_step", ) +load("scripts/drone/vault.star", "pull_secret") -load('scripts/drone/vault.star', 'from_secret', 'github_token', 'pull_secret', 'drone_token') - -failure_template = 'Build {{build.number}} failed for commit: : {{build.link}}\nBranch: \nAuthor: {{build.author}}' -drone_change_template = '`.drone.yml` and `starlark` files have been changed on the OSS repo, by: {{build.author}}. \nBranch: \nCommit hash: ' +failure_template = "Build {{build.number}} failed for commit: : {{build.link}}\nBranch: \nAuthor: {{build.author}}" +drone_change_template = "`.drone.yml` and `starlark` files have been changed on the OSS repo, by: {{build.author}}. \nBranch: \nCommit hash: " def pipeline( - name, edition, trigger, steps, services=[], platform='linux', depends_on=[], environment=None, volumes=[], - ): - if platform != 'windows': + name, + edition, + trigger, + steps, + services = [], + platform = "linux", + depends_on = [], + environment = None, + volumes = []): + """Generate a Drone Docker pipeline with commonly used values. + + In addition to the parameters provided, it configures: + - the use of an image pull secret + - a retry count for cloning + - a volume 'docker' that can be used to access the Docker socket + + Args: + name: controls the pipeline name. + edition: used to differentiate the pipeline for enterprise builds. + trigger: a Drone trigger for the pipeline. + steps: the Drone steps for the pipeline. + services: auxilliary services used during the pipeline. + Defaults to []. + platform: abstracts platform specific configuration primarily for different Drone behavior on Windows. + Defaults to 'linux'. + depends_on: list of pipelines that must have succeeded before this pipeline can start. + Defaults to []. + environment: environment variables passed through to pipeline steps. + Defaults to None. + volumes: additional volumes available to be mounted by pipeline steps. + Defaults to []. + + Returns: + Drone pipeline + """ + if platform != "windows": platform_conf = { - 'platform': { - 'os': 'linux', - 'arch': 'amd64' - }, + "platform": {"os": "linux", "arch": "amd64"}, # A shared cache is used on the host # To avoid issues with parallel builds, we run this repo on single build agents - 'node': { - 'type': 'no-parallel' - } + "node": {"type": "no-parallel"}, } else: platform_conf = { - 'platform': { - 'os': 'windows', - 'arch': 'amd64', - 'version': '1809', - } + "platform": { + "os": "windows", + "arch": "amd64", + "version": "1809", + }, } + docker_mount_path = "/var/run/docker.sock" + if platform == "windows": + docker_mount_path = "//./pipe/docker_engine/" + pipeline = { - 'kind': 'pipeline', - 'type': 'docker', - 'name': name, - 'trigger': trigger, - 'services': services, - 'steps': steps, - 'clone': { - 'retries': 3, + "kind": "pipeline", + "type": "docker", + "name": name, + "trigger": trigger, + "services": services, + "steps": steps, + "clone": { + "retries": 3, }, - 'volumes': [{ - 'name': 'docker', - 'host': { - 'path': '/var/run/docker.sock', + "volumes": [ + { + "name": "docker", + "host": { + "path": docker_mount_path, + }, }, - }], - 'depends_on': depends_on, - 'image_pull_secrets': [pull_secret], + ], + "depends_on": depends_on, + "image_pull_secrets": [pull_secret], } if environment: - pipeline.update({ - 'environment': environment, - }) + pipeline.update( + { + "environment": environment, + }, + ) - pipeline['volumes'].extend(volumes) + pipeline["volumes"].extend(volumes) pipeline.update(platform_conf) - if edition in ('enterprise', 'enterprise2'): + if edition in ("enterprise", "enterprise2"): # We have a custom clone step for enterprise - pipeline['clone'] = { - 'disable': True, + pipeline["clone"] = { + "disable": True, } return pipeline -def notify_pipeline(name, slack_channel, trigger, depends_on=[], template=None, secret=None): +def notify_pipeline( + name, + slack_channel, + trigger, + depends_on = [], + template = None, + secret = None): trigger = dict(trigger) return { - 'kind': 'pipeline', - 'type': 'docker', - 'platform': { - 'os': 'linux', - 'arch': 'amd64', + "kind": "pipeline", + "type": "docker", + "platform": { + "os": "linux", + "arch": "amd64", }, - 'name': name, - 'trigger': trigger, - 'steps': [ + "name": name, + "trigger": trigger, + "steps": [ slack_step(slack_channel, template, secret), ], - 'clone': { - 'retries': 3, + "clone": { + "retries": 3, }, - 'depends_on': depends_on, + "depends_on": depends_on, } - +# TODO: this overrides any existing dependencies because we're following the existing logic +# it should append to any existing dependencies +def with_deps(steps, deps = []): + for step in steps: + step["depends_on"] = deps + return steps diff --git a/scripts/drone/vault.star b/scripts/drone/vault.star index b7ebbd54e8b04..e6aa40db100de 100644 --- a/scripts/drone/vault.star +++ b/scripts/drone/vault.star @@ -1,97 +1,123 @@ -pull_secret = 'dockerconfigjson' -drone_token = 'drone_token' -prerelease_bucket = 'prerelease_bucket' -gcp_upload_artifacts_key = 'gcp_upload_artifacts_key' -azure_sp_app_id = 'azure_sp_app_id' -azure_sp_app_pw = 'azure_sp_app_pw' -azure_tenant = 'azure_tenant' -github_token = 'github_token' +""" +This module returns functions for generating Drone secrets fetched from Vault. +""" +pull_secret = "dockerconfigjson" +drone_token = "drone_token" +prerelease_bucket = "prerelease_bucket" +gcp_upload_artifacts_key = "gcp_upload_artifacts_key" +azure_sp_app_id = "azure_sp_app_id" +azure_sp_app_pw = "azure_sp_app_pw" +azure_tenant = "azure_tenant" def from_secret(secret): - return {'from_secret': secret} - + return {"from_secret": secret} def vault_secret(name, path, key): return { - 'kind': 'secret', - 'name': name, - 'get': { - 'path': path, - 'name': key, + "kind": "secret", + "name": name, + "get": { + "path": path, + "name": key, }, } def secrets(): return [ - vault_secret(pull_secret, 'secret/data/common/gcr', '.dockerconfigjson'), - vault_secret('github_token', 'infra/data/ci/github/grafanabot', 'pat'), - vault_secret(drone_token, 'infra/data/ci/drone', 'machine-user-token'), - vault_secret(prerelease_bucket, 'infra/data/ci/grafana/prerelease', 'bucket'), + vault_secret(pull_secret, "secret/data/common/gcr", ".dockerconfigjson"), + vault_secret("github_token", "infra/data/ci/github/grafanabot", "pat"), + vault_secret(drone_token, "infra/data/ci/drone", "machine-user-token"), + vault_secret(prerelease_bucket, "infra/data/ci/grafana/prerelease", "bucket"), vault_secret( gcp_upload_artifacts_key, - 'infra/data/ci/grafana/releng/artifacts-uploader-service-account', - 'credentials.json', + "infra/data/ci/grafana/releng/artifacts-uploader-service-account", + "credentials.json", ), vault_secret( azure_sp_app_id, - 'infra/data/ci/datasources/cpp-azure-resourcemanager-credentials', - 'application_id', + "infra/data/ci/datasources/cpp-azure-resourcemanager-credentials", + "application_id", ), vault_secret( azure_sp_app_pw, - 'infra/data/ci/datasources/cpp-azure-resourcemanager-credentials', - 'application_secret', + "infra/data/ci/datasources/cpp-azure-resourcemanager-credentials", + "application_secret", ), vault_secret( azure_tenant, - 'infra/data/ci/datasources/cpp-azure-resourcemanager-credentials', - 'tenant_id', + "infra/data/ci/datasources/cpp-azure-resourcemanager-credentials", + "tenant_id", ), # Package publishing vault_secret( - 'packages_gpg_public_key', - 'infra/data/ci/packages-publish/gpg', - 'public-key-b64', + "packages_gpg_public_key", + "infra/data/ci/packages-publish/gpg", + "public-key-b64", + ), + vault_secret( + "packages_gpg_private_key", + "infra/data/ci/packages-publish/gpg", + "private-key-b64", + ), + vault_secret( + "packages_gpg_passphrase", + "infra/data/ci/packages-publish/gpg", + "passphrase", + ), + vault_secret( + "packages_service_account", + "infra/data/ci/packages-publish/service-account", + "credentials.json", + ), + vault_secret( + "packages_access_key_id", + "infra/data/ci/packages-publish/bucket-credentials", + "AccessID", + ), + vault_secret( + "packages_secret_access_key", + "infra/data/ci/packages-publish/bucket-credentials", + "Secret", ), vault_secret( - 'packages_gpg_private_key', - 'infra/data/ci/packages-publish/gpg', - 'private-key-b64', + "aws_region", + "secret/data/common/aws-marketplace", + "aws_region", ), vault_secret( - 'packages_gpg_passphrase', - 'infra/data/ci/packages-publish/gpg', - 'passphrase', + "aws_access_key_id", + "secret/data/common/aws-marketplace", + "aws_access_key_id", ), vault_secret( - 'packages_service_account', - 'infra/data/ci/packages-publish/service-account', - 'credentials.json', + "aws_secret_access_key", + "secret/data/common/aws-marketplace", + "aws_secret_access_key", ), vault_secret( - 'packages_access_key_id', - 'infra/data/ci/packages-publish/bucket-credentials', - 'AccessID', + "security_dest_bucket", + "infra/data/ci/grafana-release-eng/security-bucket", + "bucket", ), vault_secret( - 'packages_secret_access_key', - 'infra/data/ci/packages-publish/bucket-credentials', - 'Secret', + "static_asset_editions", + "infra/data/ci/grafana-release-eng/artifact-publishing", + "static_asset_editions", ), vault_secret( - 'aws_region', - 'secret/data/common/aws-marketplace', - 'aws_region', + "enterprise2_security_prefix", + "infra/data/ci/grafana-release-eng/enterprise2", + "security_prefix", ), vault_secret( - 'aws_access_key_id', - 'secret/data/common/aws-marketplace', - 'aws_access_key_id', + "enterprise2-cdn-path", + "infra/data/ci/grafana-release-eng/enterprise2", + "cdn_path", ), vault_secret( - 'aws_secret_access_key', - 'secret/data/common/aws-marketplace', - 'aws_secret_access_key', + "enterprise2_security_prefix", + "infra/data/ci/grafana-release-eng/enterprise2", + "security_prefix", ), ] diff --git a/scripts/drone/version.star b/scripts/drone/version.star index 80f0c6ac48f8d..f56a82740009a 100644 --- a/scripts/drone/version.star +++ b/scripts/drone/version.star @@ -1,11 +1,20 @@ +""" +This module returns the pipeline used for version branches. +""" + load( - 'scripts/drone/events/release.star', - 'release_pipelines', + "scripts/drone/events/release.star", + "enterprise2_pipelines", + "enterprise_pipelines", + "oss_pipelines", ) -ver_mode = 'release-branch' +ver_mode = "release-branch" +trigger = {"ref": ["refs/heads/v[0-9]*"]} def version_branch_pipelines(): - return release_pipelines(ver_mode=ver_mode, trigger={ - 'ref': ['refs/heads/v[0-9]*'], - }) + return ( + oss_pipelines(ver_mode = ver_mode, trigger = trigger) + + enterprise_pipelines(ver_mode = ver_mode, trigger = trigger) + + enterprise2_pipelines(ver_mode = ver_mode, trigger = trigger) + ) diff --git a/yarn.lock b/yarn.lock index 3139fa5710b30..5bb657224f1a1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4061,11 +4061,11 @@ __metadata: linkType: hard "@babel/runtime@npm:^7.10.0, @babel/runtime@npm:^7.19.4": - version: 7.21.0 - resolution: "@babel/runtime@npm:7.21.0" + version: 7.21.5 + resolution: "@babel/runtime@npm:7.21.5" dependencies: regenerator-runtime: ^0.13.11 - checksum: 7b33e25bfa9e0e1b9e8828bb61b2d32bdd46b41b07ba7cb43319ad08efc6fda8eb89445193e67d6541814627df0ca59122c0ea795e412b99c5183a0540d338ab + checksum: 358f2779d3187f5c67ad302e8f8d435412925d0b991d133c7d4a7b1ddd5a3fda1b6f34537cb64628dfd96a27ae46df105bed3895b8d754b88cacdded8d1129dd languageName: node linkType: hard @@ -5334,9 +5334,9 @@ __metadata: version: 0.0.0-use.local resolution: "@grafana-plugins/input-datasource@workspace:plugins-bundled/internal/input-datasource" dependencies: - "@grafana/data": 9.2.13 - "@grafana/toolkit": 9.2.13 - "@grafana/ui": 9.2.13 + "@grafana/data": 9.2.18 + "@grafana/toolkit": 9.2.18 + "@grafana/ui": 9.2.18 "@types/jest": 26.0.15 "@types/lodash": 4.14.149 "@types/react": 17.0.30 @@ -5380,12 +5380,12 @@ __metadata: languageName: node linkType: hard -"@grafana/data@9.2.13, @grafana/data@workspace:*, @grafana/data@workspace:packages/grafana-data": +"@grafana/data@9.2.18, @grafana/data@workspace:*, @grafana/data@workspace:packages/grafana-data": version: 0.0.0-use.local resolution: "@grafana/data@workspace:packages/grafana-data" dependencies: "@braintree/sanitize-url": 6.0.0 - "@grafana/schema": 9.2.13 + "@grafana/schema": 9.2.18 "@grafana/tsconfig": ^1.2.0-rc1 "@rollup/plugin-commonjs": 22.0.1 "@rollup/plugin-json": 4.1.0 @@ -5444,7 +5444,7 @@ __metadata: languageName: unknown linkType: soft -"@grafana/e2e-selectors@9.2.13, @grafana/e2e-selectors@workspace:*, @grafana/e2e-selectors@workspace:packages/grafana-e2e-selectors": +"@grafana/e2e-selectors@9.2.18, @grafana/e2e-selectors@workspace:*, @grafana/e2e-selectors@workspace:packages/grafana-e2e-selectors": version: 0.0.0-use.local resolution: "@grafana/e2e-selectors@workspace:packages/grafana-e2e-selectors" dependencies: @@ -5470,7 +5470,7 @@ __metadata: "@babel/core": 7.19.0 "@babel/preset-env": 7.19.0 "@cypress/webpack-preprocessor": 5.12.0 - "@grafana/e2e-selectors": 9.2.13 + "@grafana/e2e-selectors": 9.2.18 "@grafana/tsconfig": ^1.2.0-rc1 "@mochajs/json-file-reporter": ^1.2.0 "@rollup/plugin-node-resolve": 13.3.0 @@ -5557,15 +5557,15 @@ __metadata: languageName: node linkType: hard -"@grafana/runtime@9.2.13, @grafana/runtime@workspace:*, @grafana/runtime@workspace:packages/grafana-runtime": +"@grafana/runtime@9.2.18, @grafana/runtime@workspace:*, @grafana/runtime@workspace:packages/grafana-runtime": version: 0.0.0-use.local resolution: "@grafana/runtime@workspace:packages/grafana-runtime" dependencies: "@grafana/agent-web": ^0.4.0 - "@grafana/data": 9.2.13 - "@grafana/e2e-selectors": 9.2.13 + "@grafana/data": 9.2.18 + "@grafana/e2e-selectors": 9.2.18 "@grafana/tsconfig": ^1.2.0-rc1 - "@grafana/ui": 9.2.13 + "@grafana/ui": 9.2.18 "@rollup/plugin-commonjs": 22.0.1 "@rollup/plugin-node-resolve": 13.3.0 "@sentry/browser": 6.19.7 @@ -5601,7 +5601,7 @@ __metadata: languageName: unknown linkType: soft -"@grafana/schema@9.2.13, @grafana/schema@workspace:*, @grafana/schema@workspace:packages/grafana-schema": +"@grafana/schema@9.2.18, @grafana/schema@workspace:*, @grafana/schema@workspace:packages/grafana-schema": version: 0.0.0-use.local resolution: "@grafana/schema@workspace:packages/grafana-schema" dependencies: @@ -5621,7 +5621,7 @@ __metadata: languageName: unknown linkType: soft -"@grafana/toolkit@9.2.13, @grafana/toolkit@workspace:*, @grafana/toolkit@workspace:packages/grafana-toolkit": +"@grafana/toolkit@9.2.18, @grafana/toolkit@workspace:*, @grafana/toolkit@workspace:packages/grafana-toolkit": version: 0.0.0-use.local resolution: "@grafana/toolkit@workspace:packages/grafana-toolkit" dependencies: @@ -5637,10 +5637,10 @@ __metadata: "@babel/preset-env": 7.18.9 "@babel/preset-react": 7.18.6 "@babel/preset-typescript": 7.18.6 - "@grafana/data": 9.2.13 + "@grafana/data": 9.2.18 "@grafana/eslint-config": 5.0.0 "@grafana/tsconfig": ^1.2.0-rc1 - "@grafana/ui": 9.2.13 + "@grafana/ui": 9.2.18 "@jest/core": 27.5.1 "@types/command-exists": ^1.2.0 "@types/eslint": 8.4.1 @@ -5721,16 +5721,16 @@ __metadata: languageName: node linkType: hard -"@grafana/ui@9.2.13, @grafana/ui@workspace:*, @grafana/ui@workspace:packages/grafana-ui": +"@grafana/ui@9.2.18, @grafana/ui@workspace:*, @grafana/ui@workspace:packages/grafana-ui": version: 0.0.0-use.local resolution: "@grafana/ui@workspace:packages/grafana-ui" dependencies: "@babel/core": 7.19.0 "@emotion/css": 11.9.0 "@emotion/react": 11.9.3 - "@grafana/data": 9.2.13 - "@grafana/e2e-selectors": 9.2.13 - "@grafana/schema": 9.2.13 + "@grafana/data": 9.2.18 + "@grafana/e2e-selectors": 9.2.18 + "@grafana/schema": 9.2.18 "@grafana/tsconfig": ^1.2.0-rc1 "@mdx-js/react": 1.6.22 "@monaco-editor/react": 4.4.5 @@ -6013,11 +6013,11 @@ __metadata: resolution: "@jaegertracing/jaeger-ui-components@workspace:packages/jaeger-ui-components" dependencies: "@emotion/css": 11.9.0 - "@grafana/data": 9.2.13 - "@grafana/e2e-selectors": 9.2.13 - "@grafana/runtime": 9.2.13 + "@grafana/data": 9.2.18 + "@grafana/e2e-selectors": 9.2.18 + "@grafana/runtime": 9.2.18 "@grafana/tsconfig": ^1.2.0-rc1 - "@grafana/ui": 9.2.13 + "@grafana/ui": 9.2.18 "@testing-library/jest-dom": 5.16.4 "@testing-library/react": 12.1.4 "@testing-library/user-event": 14.4.3 @@ -7626,7 +7626,7 @@ __metadata: ramda: ^0.27.1 peerDependencies: "@babel/core": ^7.0.0 - babel-plugin-macros: 2 || 3 + babel-plugin-macros: 2 || 3 typescript: 2 || 3 || 4 bin: lingui: lingui.js @@ -7681,7 +7681,7 @@ __metadata: "@lingui/conf": ^3.12.1 ramda: ^0.27.1 peerDependencies: - babel-plugin-macros: 2 || 3 + babel-plugin-macros: 2 || 3 checksum: 83384f2d796dbc7ecadb74a1c6159ccad82976c194f97b82c2ba72cc8113f95bf0193aa6a4e9596db25b713129a9037a873bf1282bc30e197c2a72855707162f languageName: node linkType: hard @@ -7696,7 +7696,7 @@ __metadata: peerDependencies: "@lingui/core": ^3.13.0 "@lingui/react": ^3.13.0 - babel-plugin-macros: 2 || 3 + babel-plugin-macros: 2 || 3 checksum: 246f56a5458f2c730f05551ca47f14f45dc3fea01988f93eafafd5e2d19661f7b6894afad72df22f332e1d560efd4b492248d37c99f67f845d276aa0504f541e languageName: node linkType: hard @@ -8788,21 +8788,6 @@ __metadata: languageName: node linkType: hard -"@react-aria/focus@npm:3.6.1": - version: 3.6.1 - resolution: "@react-aria/focus@npm:3.6.1" - dependencies: - "@babel/runtime": ^7.6.2 - "@react-aria/interactions": ^3.9.1 - "@react-aria/utils": ^3.13.1 - "@react-types/shared": ^3.13.1 - clsx: ^1.1.1 - peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 - checksum: ca273afec9c21dc65d5d51ca93e979b89ee924a75d5a9e355dea1574f5db729d72e90437197c855ad45ea8bbacf227e8b4dc1bc2e74016427c5cdabe82e3017b - languageName: node - linkType: hard - "@react-aria/focus@npm:3.8.0, @react-aria/focus@npm:^3.8.0": version: 3.8.0 resolution: "@react-aria/focus@npm:3.8.0" @@ -8849,19 +8834,6 @@ __metadata: languageName: node linkType: hard -"@react-aria/interactions@npm:^3.9.1": - version: 3.14.0 - resolution: "@react-aria/interactions@npm:3.14.0" - dependencies: - "@react-aria/utils": ^3.15.0 - "@react-types/shared": ^3.17.0 - "@swc/helpers": ^0.4.14 - peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 - checksum: d4e2dd2617bdaa60025a9f50e2c314b2a74c56dba40cc536b909b78bb1c1268a25c5593f28661c86b1d2d37a443878dcacf86a3d6d597abfe8afee258b103ed8 - languageName: node - linkType: hard - "@react-aria/menu@npm:3.6.1": version: 3.6.1 resolution: "@react-aria/menu@npm:3.6.1" @@ -8946,17 +8918,6 @@ __metadata: languageName: node linkType: hard -"@react-aria/ssr@npm:^3.5.0": - version: 3.5.0 - resolution: "@react-aria/ssr@npm:3.5.0" - dependencies: - "@swc/helpers": ^0.4.14 - peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 - checksum: 3287fe756ff458a3ce46ba0fabe2ede349bff0b232cce30aab0f50afa1c0ac7604809d229b8b19a62a5116cf12bc8099d2c9c72335126499c55c794dd3419dbd - languageName: node - linkType: hard - "@react-aria/utils@npm:3.13.1": version: 3.13.1 resolution: "@react-aria/utils@npm:3.13.1" @@ -8972,21 +8933,6 @@ __metadata: languageName: node linkType: hard -"@react-aria/utils@npm:^3.13.1, @react-aria/utils@npm:^3.15.0": - version: 3.15.0 - resolution: "@react-aria/utils@npm:3.15.0" - dependencies: - "@react-aria/ssr": ^3.5.0 - "@react-stately/utils": ^3.6.0 - "@react-types/shared": ^3.17.0 - "@swc/helpers": ^0.4.14 - clsx: ^1.1.1 - peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 - checksum: 9d852b3a8ca492b5e8c733f6258437430d050950d4cbdb99ab221d1a076ebca2625d45384bfb7b651072adc93368462445061c83ceac079418c8deafca2b47c3 - languageName: node - linkType: hard - "@react-aria/utils@npm:^3.13.3": version: 3.13.3 resolution: "@react-aria/utils@npm:3.13.3" @@ -9163,17 +9109,6 @@ __metadata: languageName: node linkType: hard -"@react-stately/utils@npm:^3.6.0": - version: 3.6.0 - resolution: "@react-stately/utils@npm:3.6.0" - dependencies: - "@swc/helpers": ^0.4.14 - peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 - checksum: d2ff4cfed5555b112ad71b9bc1837abd777d8fa225043c476b7c9417f8b21a0bcddad0d7127e0acdbf4d85dc9a260c9ae97722b4e9507e6243b412c2724c5f54 - languageName: node - linkType: hard - "@react-types/button@npm:3.6.1, @react-types/button@npm:^3.6.1": version: 3.6.1 resolution: "@react-types/button@npm:3.6.1" @@ -9260,64 +9195,50 @@ __metadata: languageName: node linkType: hard -"@react-types/shared@npm:^3.17.0": - version: 3.17.0 - resolution: "@react-types/shared@npm:3.17.0" - peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 - checksum: 004fc58ab0d3d64a84ce5a98e7e201b88bbb64f8b4a8309d50be30fe6172d0f172f00c666074aa96f13bbbfbced8b986901ad6b35b6d2d32d8dc25e251fcdb31 - languageName: node - linkType: hard - "@reactour/mask@npm:*": - version: 1.0.0 - resolution: "@reactour/mask@npm:1.0.0" + version: 1.1.0 + resolution: "@reactour/mask@npm:1.1.0" dependencies: "@reactour/utils": "*" - "@types/react": 17.0.39 peerDependencies: react: 16.x || 17.x || 18.x - checksum: 7e978576733db89007a08fd297d7339e647d16ace6c6fc8fd81e528eae5580885592d6447354bca0b9433e16ec82fa51e8b7e3f6971300432a12a4b3e4119576 + checksum: 0a4ea5d3c4f530f8e44d0530e68f8086316e08dacf8622d150f1458443a1764799160bf5f53322dfc6552dd5880aad67205b78cd5ce1b21ebe292bfe207627fe languageName: node linkType: hard "@reactour/popover@npm:*": - version: 1.0.0 - resolution: "@reactour/popover@npm:1.0.0" + version: 1.1.1 + resolution: "@reactour/popover@npm:1.1.1" dependencies: "@reactour/utils": "*" - "@types/react": 17.0.39 peerDependencies: react: 16.x || 17.x || 18.x - checksum: 593ef7d026dc0a8a7c4b9c5911b6059373feb56d3a2a6e55ba341a5a44d3fb2137cb203fb17a6821677dff17582d9bf8fd7cc4b32c42cf3e7c6dcf4aa29f678b + checksum: 7a0cacfbe05050036d8d26338eae3d20b8dbae14e670b8ae59c7baf941f7a77fceb3de755a322562915bc0b8c9f04e8677d79f587faf8a5ed389d5854c39a45b languageName: node linkType: hard "@reactour/tour@npm:^3.0.0": version: 3.0.0 - resolution: "@reactour/tour@npm:3.0.0" + resolution: "@reactour/tour@npm:3.4.0" dependencies: - "@react-aria/focus": 3.6.1 "@reactour/mask": "*" "@reactour/popover": "*" "@reactour/utils": "*" - "@types/react": 17.0.39 peerDependencies: react: 16.x || 17.x || 18.x - checksum: 2454c27362d99f525f00d96380647bf3d39141f70677e437bc2fea218773ad99e1a8a4cb63c9dbd5ae774b040b2eb455b3c1d5cf580c0f44101dbff46b0429fd + checksum: 1b0777b6ae04cc48baa174a9d6790c89a81ac6e82ce4b74271d639f9c24ef38256285860e15eedb75d5e0a09c3817b3b49f61607727befec3d0ea89954acd1d3 languageName: node linkType: hard "@reactour/utils@npm:*": - version: 0.4.0 - resolution: "@reactour/utils@npm:0.4.0" + version: 0.5.0 + resolution: "@reactour/utils@npm:0.5.0" dependencies: - "@rooks/use-mutation-observer": 4.11.2 - "@types/react": 17.0.39 - resize-observer-polyfill: 1.5.1 + "@rooks/use-mutation-observer": ^4.11.2 + resize-observer-polyfill: ^1.5.1 peerDependencies: react: 16.x || 17.x || 18.x - checksum: 0cd25fd19842a3f815ce6d7f1ef0135511f779ad2d456cbd46b9cf53a6950fa150cc218782bab752a2f0f04227e577eafb4998d72355796dffcbabbc97530afc + checksum: 425b408fb024fd7a8ed93da340c567bbecafca2ae254373fa7ff5bb61c425445f90fa3493b862cf352136b35d727e530d1e6835310503a02ec61e40974a32b4d languageName: node linkType: hard @@ -9408,7 +9329,7 @@ __metadata: languageName: node linkType: hard -"@rooks/use-mutation-observer@npm:4.11.2": +"@rooks/use-mutation-observer@npm:^4.11.2": version: 4.11.2 resolution: "@rooks/use-mutation-observer@npm:4.11.2" peerDependencies: @@ -11098,15 +11019,6 @@ __metadata: languageName: node linkType: hard -"@swc/helpers@npm:^0.4.14": - version: 0.4.14 - resolution: "@swc/helpers@npm:0.4.14" - dependencies: - tslib: ^2.4.0 - checksum: 273fd3f3fc461a92f3790cc551ea054745c6d6959afbe1232e6d7aa1c722bbc114d308aab96bef5c78fc0303c85c7b472ef00e2253251cc89737f3b1af56e5a5 - languageName: node - linkType: hard - "@swc/wasm@npm:1.2.122": version: 1.2.122 resolution: "@swc/wasm@npm:1.2.122" @@ -12754,17 +12666,6 @@ __metadata: languageName: node linkType: hard -"@types/react@npm:17.0.39": - version: 17.0.39 - resolution: "@types/react@npm:17.0.39" - dependencies: - "@types/prop-types": "*" - "@types/scheduler": "*" - csstype: ^3.0.2 - checksum: bf04d3c2894559012710d595553e12b422d3b91cd8f4f7e122d8cb044ba9c2ba17f6e8a4e09581359cc5509ddc59cd8c8fabd6774f3505a40a45393f074d6e6e - languageName: node - linkType: hard - "@types/react@npm:17.0.42": version: 17.0.42 resolution: "@types/react@npm:17.0.42" @@ -14145,7 +14046,7 @@ __metadata: languageName: node linkType: hard -"ajv-keywords@npm:^5.0.0": +"ajv-keywords@npm:^5.0.0, ajv-keywords@npm:^5.1.0": version: 5.1.0 resolution: "ajv-keywords@npm:5.1.0" dependencies: @@ -14192,6 +14093,18 @@ __metadata: languageName: node linkType: hard +"ajv@npm:^8.9.0": + version: 8.12.0 + resolution: "ajv@npm:8.12.0" + dependencies: + fast-deep-equal: ^3.1.1 + json-schema-traverse: ^1.0.0 + require-from-string: ^2.0.2 + uri-js: ^4.2.2 + checksum: 4dc13714e316e67537c8b31bc063f99a1d9d9a497eb4bbd55191ac0dcd5e4985bbb71570352ad6f1e76684fb6d790928f96ba3b2d4fd6e10024be9612fe3f001 + languageName: node + linkType: hard + "angular-bindonce@npm:0.3.1": version: 0.3.1 resolution: "angular-bindonce@npm:0.3.1" @@ -33264,7 +33177,7 @@ __metadata: languageName: node linkType: hard -"resize-observer-polyfill@npm:1.5.1, resize-observer-polyfill@npm:^1.5.1": +"resize-observer-polyfill@npm:^1.5.1": version: 1.5.1 resolution: "resize-observer-polyfill@npm:1.5.1" checksum: 57e7f79489867b00ba43c9c051524a5c8f162a61d5547e99333549afc23e15c44fd43f2f318ea0261ea98c0eb3158cca261e6f48d66e1ed1cd1f340a43977094 @@ -33862,15 +33775,15 @@ __metadata: languageName: node linkType: hard -"schema-utils@npm:>1.0.0, schema-utils@npm:^4.0.0": - version: 4.0.0 - resolution: "schema-utils@npm:4.0.0" +"schema-utils@npm:>1.0.0": + version: 4.0.1 + resolution: "schema-utils@npm:4.0.1" dependencies: "@types/json-schema": ^7.0.9 - ajv: ^8.8.0 + ajv: ^8.9.0 ajv-formats: ^2.1.1 - ajv-keywords: ^5.0.0 - checksum: c843e92fdd1a5c145dbb6ffdae33e501867f9703afac67bdf35a685e49f85b1dcc10ea250033175a64bd9d31f0555bc6785b8359da0c90bcea30cf6dfbb55a8f + ajv-keywords: ^5.1.0 + checksum: 745e7293c6b6c84940de16753c207311da821aa9911b9e2d158cfd9ffc5bf1f880147abbbe775b96cb8cd3c7f48890950fe0164f54eed9a8aabb948ebf8a3fdd languageName: node linkType: hard @@ -33896,6 +33809,18 @@ __metadata: languageName: node linkType: hard +"schema-utils@npm:^4.0.0": + version: 4.0.0 + resolution: "schema-utils@npm:4.0.0" + dependencies: + "@types/json-schema": ^7.0.9 + ajv: ^8.8.0 + ajv-formats: ^2.1.1 + ajv-keywords: ^5.0.0 + checksum: c843e92fdd1a5c145dbb6ffdae33e501867f9703afac67bdf35a685e49f85b1dcc10ea250033175a64bd9d31f0555bc6785b8359da0c90bcea30cf6dfbb55a8f + languageName: node + linkType: hard + "screenfull@npm:^5.1.0": version: 5.1.0 resolution: "screenfull@npm:5.1.0"